Tor 0.4.9.0-alpha-dev
confmgt.c
Go to the documentation of this file.
1/* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2021, The Tor Project, Inc. */
5/* See LICENSE for licensing information */
6
7/**
8 * \file confmgt.c
9 *
10 * \brief Back-end for parsing and generating key-value files, used to
11 * implement the torrc file format and the state file.
12 *
13 * This module is used by config.c to parse and encode torrc
14 * configuration files, and by statefile.c to parse and encode the
15 * $DATADIR/state file.
16 *
17 * To use this module, its callers provide an instance of
18 * config_format_t to describe the mappings from a set of configuration
19 * options to a number of fields in a C structure. With this mapping,
20 * the functions here can convert back and forth between the C structure
21 * specified, and a linked list of key-value pairs.
22 */
23
24#define CONFMGT_PRIVATE
25#include "orconfig.h"
26#include "lib/confmgt/confmgt.h"
27
33#include "lib/log/escape.h"
34#include "lib/log/log.h"
35#include "lib/log/util_bug.h"
37#include "lib/string/printf.h"
39
40#include "ext/siphash.h"
41
42/**
43 * A managed_var_t is an internal wrapper around a config_var_t in
44 * a config_format_t structure. It is used by config_mgr_t to
45 * keep track of which option goes with which structure. */
46typedef struct managed_var_t {
47 /**
48 * A pointer to the config_var_t for this option.
49 */
51 /**
52 * The index of the object in which this option is stored. It is
53 * IDX_TOPLEVEL to indicate that the object is the top-level object.
54 **/
57
58static void config_reset(const config_mgr_t *fmt, void *options,
59 const managed_var_t *var, int use_defaults);
61 const config_format_t *fmt,
62 int object_idx);
63
64/** Release all storage held in a managed_var_t. */
65static void
67{
68 if (!mv)
69 return;
70 tor_free(mv);
71}
72#define managed_var_free(mv) \
73 FREE_AND_NULL(managed_var_t, managed_var_free_, (mv))
74
76 /** A list of configuration objects managed by a given configuration
77 * manager. They are stored in the same order as the config_format_t
78 * objects in the manager's list of subformats. */
80};
81
82/**
83 * Allocate a new empty config_suite_t.
84 **/
85static config_suite_t *
87{
88 config_suite_t *suite = tor_malloc_zero(sizeof(config_suite_t));
89 suite->configs = smartlist_new();
90 return suite;
91}
92
93/** Release all storage held by a config_suite_t. (Does not free
94 * any configuration objects it holds; the caller must do that first.) */
95static void
97{
98 if (!suite)
99 return;
100 smartlist_free(suite->configs);
101 tor_free(suite);
102}
103
104#define config_suite_free(suite) \
105 FREE_AND_NULL(config_suite_t, config_suite_free_, (suite))
106
108 /** The 'top-level' configuration format. This one is used for legacy
109 * options that have not yet been assigned to different sub-modules.
110 *
111 * (NOTE: for now, this is the only config_format_t that a config_mgr_t
112 * contains. A subsequent commit will add more. XXXX)
113 */
115 /**
116 * List of second-level configuration format objects that this manager
117 * also knows about.
118 */
120 /** A smartlist of managed_var_t objects for all configuration formats. */
122 /** A smartlist of config_abbrev_t objects for all configuration
123 * formats. These objects are used to track synonyms and abbreviations for
124 * different configuration options. */
126 /** A smartlist of config_deprecation_t for all configuration formats. */
128 /** True if this manager has been frozen and cannot have any more formats
129 * added to it. A manager must be frozen before it can be used to construct
130 * or manipulate objects. */
131 bool frozen;
132 /** A replacement for the magic number of the toplevel object. We override
133 * that number to make it unique for this particular config_mgr_t, so that
134 * an object constructed with one mgr can't be used with another, even if
135 * those managers' contents are equal.
136 */
138};
139
140#define IDX_TOPLEVEL (-1)
141
142/** Create a new config_mgr_t to manage a set of configuration objects to be
143 * wrapped under <b>toplevel_fmt</b>. */
145config_mgr_new(const config_format_t *toplevel_fmt)
146{
147 config_mgr_t *mgr = tor_malloc_zero(sizeof(config_mgr_t));
148 mgr->subconfigs = smartlist_new();
149 mgr->all_vars = smartlist_new();
150 mgr->all_abbrevs = smartlist_new();
152
153 config_mgr_register_fmt(mgr, toplevel_fmt, IDX_TOPLEVEL);
154 mgr->toplevel = toplevel_fmt;
155
156 return mgr;
157}
158
159/** Add a config_format_t to a manager, with a specified (unique) index. */
160static void
162 const config_format_t *fmt,
163 int object_idx)
164{
165 int i;
166
167 tor_assertf(!mgr->frozen,
168 "Tried to add a format to a configuration manager after "
169 "it had been frozen.");
170
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");
174 }
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.");
178 }
179
180 tor_assertf(fmt != mgr->toplevel &&
181 ! smartlist_contains(mgr->subconfigs, fmt),
182 "Tried to register an already-registered format.");
183
184 /* register variables */
185 for (i = 0; fmt->vars[i].member.name; ++i) {
186 managed_var_t *mv = tor_malloc_zero(sizeof(managed_var_t));
187 mv->cvar = &fmt->vars[i];
188 mv->object_idx = object_idx;
189 smartlist_add(mgr->all_vars, mv);
190 }
191
192 /* register abbrevs */
193 if (fmt->abbrevs) {
194 for (i = 0; fmt->abbrevs[i].abbreviated; ++i) {
195 smartlist_add(mgr->all_abbrevs, (void*)&fmt->abbrevs[i]);
196 }
197 }
198
199 /* register deprecations. */
200 if (fmt->deprecations) {
201 const config_deprecation_t *d;
202 for (d = fmt->deprecations; d->name; ++d) {
203 smartlist_add(mgr->all_deprecations, (void*)d);
204 }
205 }
206}
207
208/**
209 * Add a new format to this configuration object. Asserts on failure.
210 *
211 * Returns an internal "index" value used to identify this format within
212 * all of those formats contained in <b>mgr</b>. This index value
213 * should not generally be used outside of this module.
214 **/
215int
217 const config_format_t *fmt)
218{
219 tor_assert(mgr);
220 int idx = smartlist_len(mgr->subconfigs);
221 config_mgr_register_fmt(mgr, fmt, idx);
222 smartlist_add(mgr->subconfigs, (void *)fmt);
223 return idx;
224}
225
226/** Return a pointer to the config_suite_t * pointer inside a
227 * configuration object; returns NULL if there is no such member. */
228static inline config_suite_t **
229config_mgr_get_suite_ptr(const config_mgr_t *mgr, void *toplevel)
230{
231 if (! mgr->toplevel->has_config_suite)
232 return NULL;
233 return STRUCT_VAR_P(toplevel, mgr->toplevel->config_suite_offset);
234}
235
236/**
237 * Return a pointer to the configuration object within <b>toplevel</b> whose
238 * index is <b>idx</b>.
239 *
240 * NOTE: XXXX Eventually, there will be multiple objects supported within the
241 * toplevel object. For example, the or_options_t will contain pointers
242 * to configuration objects for other modules. This function gets
243 * the sub-object for a particular module.
244 */
245void *
246config_mgr_get_obj_mutable(const config_mgr_t *mgr, void *toplevel, int idx)
247{
248 tor_assert(mgr);
249 tor_assert(toplevel);
250 if (idx == IDX_TOPLEVEL)
251 return toplevel;
252
253 tor_assertf(idx >= 0 && idx < smartlist_len(mgr->subconfigs),
254 "Index %d is out of range.", idx);
255 config_suite_t **suite = config_mgr_get_suite_ptr(mgr, toplevel);
256 tor_assert(suite);
257 tor_assert(smartlist_len(mgr->subconfigs) ==
258 smartlist_len((*suite)->configs));
259
260 return smartlist_get((*suite)->configs, idx);
261}
262
263/** As config_mgr_get_obj_mutable(), but return a const pointer. */
264const void *
265config_mgr_get_obj(const config_mgr_t *mgr, const void *toplevel, int idx)
266{
267 return config_mgr_get_obj_mutable(mgr, (void*)toplevel, idx);
268}
269
270/** Sorting helper for smartlist of managed_var_t */
271static int
272managed_var_cmp(const void **a, const void **b)
273{
274 const managed_var_t *mv1 = *(const managed_var_t**)a;
275 const managed_var_t *mv2 = *(const managed_var_t**)b;
276
277 return strcasecmp(mv1->cvar->member.name, mv2->cvar->member.name);
278}
279
280/**
281 * Mark a configuration manager as "frozen", so that no more formats can be
282 * added, and so that it can be used for manipulating configuration objects.
283 **/
284void
286{
287 static uint64_t mgr_count = 0;
288
290 memcpy(&mgr->toplevel_magic, &mgr->toplevel->magic,
291 sizeof(struct_magic_decl_t));
292 uint64_t magic_input[3] = { mgr->toplevel_magic.magic_val,
293 (uint64_t) (uintptr_t) mgr,
294 ++mgr_count };
296 (uint32_t)siphash24g(magic_input, sizeof(magic_input));
297 mgr->frozen = true;
298}
299
300/** Release all storage held in <b>mgr</b> */
301void
303{
304 if (!mgr)
305 return;
306 SMARTLIST_FOREACH(mgr->all_vars, managed_var_t *, mv, managed_var_free(mv));
307 smartlist_free(mgr->all_vars);
308 smartlist_free(mgr->all_abbrevs);
309 smartlist_free(mgr->all_deprecations);
310 smartlist_free(mgr->subconfigs);
311 memset(mgr, 0, sizeof(*mgr));
312 tor_free(mgr);
313}
314
315/** Return a new smartlist_t containing a config_var_t for every variable that
316 * <b>mgr</b> knows about. The elements of this smartlist do not need
317 * to be freed; they have the same lifespan as <b>mgr</b>. */
320{
321 smartlist_t *result = smartlist_new();
322 tor_assert(mgr);
324 smartlist_add(result, (void*) mv->cvar));
325 return result;
326}
327
328/** Return a new smartlist_t containing the names of all deprecated variables.
329 * The elements of this smartlist do not need to be freed; they have the same
330 * lifespan as <b>mgr</b>.
331 */
334{
335 smartlist_t *result = smartlist_new();
336 tor_assert(mgr);
338 smartlist_add(result, (char*)d->name));
339 return result;
340}
341
342/**
343 * Check the magic number on <b>object</b> to make sure it's a valid toplevel
344 * object, created with <b>mgr</b>. Exit with an assertion if it isn't.
345 **/
346void
348 const void *object)
349{
350 struct_check_magic(object, &mgr->toplevel_magic);
351}
352
353/** Assert that the magic fields in <b>options</b> and its subsidiary
354 * objects are all okay. */
355static void
357 const void *options)
358{
359 tor_assert(mgr);
360 tor_assert(options);
361 tor_assert(mgr->frozen);
362 struct_check_magic(options, &mgr->toplevel_magic);
363
364 config_suite_t **suitep = config_mgr_get_suite_ptr(mgr, (void*)options);
365 if (suitep == NULL) {
366 tor_assert(smartlist_len(mgr->subconfigs) == 0);
367 return;
368 }
369
370 tor_assert(smartlist_len((*suitep)->configs) ==
371 smartlist_len(mgr->subconfigs));
373 void *obj = smartlist_get((*suitep)->configs, fmt_sl_idx);
374 tor_assert(obj);
375 struct_check_magic(obj, &fmt->magic);
376 } SMARTLIST_FOREACH_END(fmt);
377}
378
379/** Macro: assert that <b>cfg</b> has the right magic field for
380 * <b>mgr</b>. */
381#define CONFIG_CHECK(mgr, cfg) STMT_BEGIN \
382 config_mgr_assert_magic_ok((mgr), (cfg)); \
383 STMT_END
384
385/** Allocate an empty configuration object of a given format type. */
386void *
388{
389 tor_assert(mgr->frozen);
390 void *opts = tor_malloc_zero(mgr->toplevel->size);
391 struct_set_magic(opts, &mgr->toplevel_magic);
392 config_suite_t **suitep = config_mgr_get_suite_ptr(mgr, opts);
393 if (suitep) {
394 *suitep = config_suite_new();
396 void *obj = tor_malloc_zero(fmt->size);
397 struct_set_magic(obj, &fmt->magic);
398 smartlist_add((*suitep)->configs, obj);
399 } SMARTLIST_FOREACH_END(fmt);
400 }
401 CONFIG_CHECK(mgr, opts);
402 return opts;
403}
404
405/*
406 * Functions to parse config options
407 */
408
409/** If <b>option</b> is an official abbreviation for a longer option,
410 * return the longer option. Otherwise return <b>option</b>.
411 * If <b>command_line</b> is set, apply all abbreviations. Otherwise, only
412 * apply abbreviations that work for the config file and the command line.
413 * If <b>warn_obsolete</b> is set, warn about deprecated names. */
414const char *
415config_expand_abbrev(const config_mgr_t *mgr, const char *option,
416 int command_line, int warn_obsolete)
417{
419 /* Abbreviations are case insensitive. */
420 if (!strcasecmp(option, abbrev->abbreviated) &&
421 (command_line || !abbrev->commandline_only)) {
422 if (warn_obsolete && abbrev->warn) {
423 log_warn(LD_CONFIG,
424 "The configuration option '%s' is deprecated; "
425 "use '%s' instead.",
426 abbrev->abbreviated,
427 abbrev->full);
428 }
429 /* Keep going through the list in case we want to rewrite it more.
430 * (We could imagine recursing here, but I don't want to get the
431 * user into an infinite loop if we craft our list wrong.) */
432 option = abbrev->full;
433 }
434 } SMARTLIST_FOREACH_END(abbrev);
435 return option;
436}
437
438/** If <b>key</b> is a deprecated configuration option, return the message
439 * explaining why it is deprecated (which may be an empty string). Return NULL
440 * if it is not deprecated. The <b>key</b> field must be fully expanded. */
441const char *
442config_find_deprecation(const config_mgr_t *mgr, const char *key)
443{
444 if (BUG(mgr == NULL) || BUG(key == NULL))
445 return NULL; // LCOV_EXCL_LINE
446
448 d) {
449 if (!strcasecmp(d->name, key)) {
450 return d->why_deprecated ? d->why_deprecated : "";
451 }
452 } SMARTLIST_FOREACH_END(d);
453 return NULL;
454}
455
456/**
457 * Find the managed_var_t object for a variable whose name is <b>name</b>
458 * according to <b>mgr</b>. Return that object, or NULL if none exists.
459 *
460 * If <b>allow_truncated</b> is true, then accept any variable whose
461 * name begins with <b>name</b>.
462 *
463 * If <b>idx_out</b> is not NULL, set *<b>idx_out</b> to the position of
464 * that variable within mgr-&gt;all_vars, or to -1 if the variable is
465 * not found.
466 */
467static const managed_var_t *
469 const char *key,
470 bool allow_truncated, int *idx_out)
471{
472 const size_t keylen = strlen(key);
473 if (idx_out)
474 *idx_out = -1;
475
476 if (!keylen)
477 return NULL; /* if they say "--" on the command line, it's not an option */
478
479 /* First, check for an exact (case-insensitive) match */
481 if (!strcasecmp(mv->cvar->member.name, key)) {
482 if (idx_out)
483 *idx_out = mv_sl_idx;
484 return mv;
485 }
486 } SMARTLIST_FOREACH_END(mv);
487
488 if (!allow_truncated)
489 return NULL;
490
491 /* If none, check for an abbreviated match */
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);
497 if (idx_out)
498 *idx_out = mv_sl_idx;
499 return mv;
500 }
501 } SMARTLIST_FOREACH_END(mv);
502
503 /* Okay, unrecognized option */
504 return NULL;
505}
506
507/**
508 * If <b>key</b> is a name or an abbreviation configuration option, return
509 * the corresponding canonical name for it. Warn if the abbreviation is
510 * non-standard. Return NULL if the option does not exist.
511 */
512const char *
513config_find_option_name(const config_mgr_t *mgr, const char *key)
514{
515 key = config_expand_abbrev(mgr, key, 0, 0);
516 const managed_var_t *mv = config_mgr_find_var(mgr, key, true, NULL);
517 if (mv)
518 return mv->cvar->member.name;
519 else
520 return NULL;
521}
522
523/** Return the number of option entries in <b>fmt</b>. */
524static int
526{
527 return smartlist_len(mgr->all_vars);
528}
529
530/**
531 * Return true iff at least one bit from <b>flag</b> is set on <b>var</b>,
532 * either in <b>var</b>'s flags, or on the flags of its type.
533 **/
534static bool
535config_var_has_flag(const config_var_t *var, uint32_t flag)
536{
537 uint32_t have_flags = var->flags | struct_var_get_flags(&var->member);
538
539 return (have_flags & flag) != 0;
540}
541
542/**
543 * Return true if assigning a value to <b>var</b> replaces the previous
544 * value. Return false if assigning a value to <b>var</b> appends
545 * to the previous value.
546 **/
547static bool
549{
550 return ! config_var_has_flag(var, CFLG_NOREPLACE);
551}
552
553/**
554 * Return true iff <b>var</b> may be assigned by name (e.g., via the
555 * CLI, the configuration files, or the controller API).
556 **/
557bool
559{
560 return ! config_var_has_flag(var, CFLG_NOSET);
561}
562
563/**
564 * Return true iff the controller is allowed to fetch the value of
565 * <b>var</b>.
566 **/
567static bool
569{
570 /* Arguably, invisible or obsolete options should not be gettable. However,
571 * they have been gettable for a long time, and making them ungettable could
572 * have compatibility effects. For now, let's leave them alone.
573 */
574
575 // return ! config_var_has_flag(var, CVFLAG_OBSOLETE|CFGLAGS_INVISIBLE);
576 (void)var;
577 return true;
578}
579
580/**
581 * Return true iff we need to check <b>var</b> for changes when we are
582 * comparing config options for changes.
583 *
584 * A false result might mean that the variable is a derived variable, and that
585 * comparing the variable it derives from compares this one too-- or it might
586 * mean that there is no data to compare.
587 **/
588static bool
590{
591 return ! config_var_has_flag(var, CFLG_NOCMP);
592}
593
594/**
595 * Return true iff we need to copy the data for <b>var</b> when we are
596 * copying a config option.
597 *
598 * A false option might mean that the variable is a derived variable, and that
599 * copying the variable it derives from copies it-- or it might mean that
600 * there is no data to copy.
601 **/
602static bool
604{
605 return ! config_var_has_flag(var, CFLG_NOCOPY);
606}
607
608/**
609 * Return true iff variable <b>var</b> should appear on list of variable
610 * names given to the controller or the CLI.
611 *
612 * (Note that this option is imperfectly obeyed. The
613 * --list-torrc-options command looks at the "settable" flag, whereas
614 * "GETINFO config/defaults" and "list_deprecated_*()" do not filter
615 * their results. It would be good for consistency to try to converge
616 * these behaviors in the future.)
617 **/
618bool
620{
621 return ! config_var_has_flag(var, CFLG_NOLIST);
622}
623
624/**
625 * Return true iff variable <b>var</b> should be written out when we
626 * are writing our configuration to disk, to a controller, or via the
627 * --dump-config command.
628 *
629 * This option may be set because a variable is hidden, or because it is
630 * derived from another variable which will already be written out.
631 **/
632static bool
634{
635 return ! config_var_has_flag(var, CFLG_NODUMP);
636}
637
638/*
639 * Functions to assign config options.
640 */
641
642/** <b>c</b>->key is known to be a real key. Update <b>options</b>
643 * with <b>c</b>->value and return 0, or return -1 if bad value.
644 *
645 * Called from config_assign_line() and option_reset().
646 */
647static int
648config_assign_value(const config_mgr_t *mgr, void *options,
649 config_line_t *c, char **msg)
650{
651 const managed_var_t *var;
652
653 CONFIG_CHECK(mgr, options);
654
655 var = config_mgr_find_var(mgr, c->key, true, NULL);
656 tor_assert(var);
657 tor_assert(!strcmp(c->key, var->cvar->member.name));
658 void *object = config_mgr_get_obj_mutable(mgr, options, var->object_idx);
659
661 log_warn(LD_GENERAL, "Skipping obsolete configuration option \"%s\".",
662 var->cvar->member.name);
663 } else if (config_var_has_flag(var->cvar, CFLG_WARN_DISABLED)) {
664 log_warn(LD_GENERAL, "This copy of Tor was built without support for "
665 "the option \"%s\". Skipping.", var->cvar->member.name);
666 }
667
668 return struct_var_kvassign(object, c, msg, &var->cvar->member);
669}
670
671/** Mark every linelist in <b>options</b> "fragile", so that fresh assignments
672 * to it will replace old ones. */
673static void
674config_mark_lists_fragile(const config_mgr_t *mgr, void *options)
675{
676 tor_assert(mgr);
677 tor_assert(options);
678
680 void *object = config_mgr_get_obj_mutable(mgr, options, mv->object_idx);
681 struct_var_mark_fragile(object, &mv->cvar->member);
682 } SMARTLIST_FOREACH_END(mv);
683}
684
685/**
686 * Log a warning that declaring that the option called <b>what</b>
687 * is deprecated because of the reason in <b>why</b>.
688 *
689 * (Both arguments must be non-NULL.)
690 **/
691void
692warn_deprecated_option(const char *what, const char *why)
693{
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!)",
698 what, space, why);
699}
700
701/** If <b>c</b> is a syntactically valid configuration line, update
702 * <b>options</b> with its value and return 0. Otherwise return -1 for bad
703 * key, -2 for bad value.
704 *
705 * If <b>clear_first</b> is set, clear the value first. Then if
706 * <b>use_defaults</b> is set, set the value to the default.
707 *
708 * Called from config_assign().
709 */
710static int
711config_assign_line(const config_mgr_t *mgr, void *options,
712 config_line_t *c, unsigned flags,
713 bitarray_t *options_seen, char **msg)
714{
715 const unsigned use_defaults = flags & CAL_USE_DEFAULTS;
716 const unsigned clear_first = flags & CAL_CLEAR_FIRST;
717 const unsigned warn_deprecations = flags & CAL_WARN_DEPRECATIONS;
718 const managed_var_t *mvar;
719
720 CONFIG_CHECK(mgr, options);
721
722 int var_index = -1;
723 mvar = config_mgr_find_var(mgr, c->key, true, &var_index);
724 if (!mvar) {
725 const config_format_t *fmt = mgr->toplevel;
726 if (fmt->extra) {
727 void *lvalue = STRUCT_VAR_P(options, fmt->extra->offset);
728 log_info(LD_CONFIG,
729 "Found unrecognized option '%s'; saving it.", c->key);
730 config_line_append((config_line_t**)lvalue, c->key, c->value);
731 return 0;
732 } else {
733 tor_asprintf(msg,
734 "Unknown option '%s'. Failing.", c->key);
735 return -1;
736 }
737 }
738
739 const config_var_t *cvar = mvar->cvar;
740 tor_assert(cvar);
741
742 /* Put keyword into canonical case. */
743 if (strcmp(cvar->member.name, c->key)) {
744 tor_free(c->key);
745 c->key = tor_strdup(cvar->member.name);
746 }
747
748 const char *deprecation_msg;
749 if (warn_deprecations &&
750 (deprecation_msg = config_find_deprecation(mgr, cvar->member.name))) {
751 warn_deprecated_option(cvar->member.name, deprecation_msg);
752 }
753
754 if (!strlen(c->value)) {
755 /* reset or clear it, then return */
756 if (!clear_first) {
757 if (! config_var_is_replaced_on_set(cvar) &&
758 c->command != CONFIG_LINE_CLEAR) {
759 /* We got an empty linelist from the torrc or command line.
760 As a special case, call this an error. Warn and ignore. */
761 log_warn(LD_CONFIG,
762 "Linelist option '%s' has no value. Skipping.", c->key);
763 } else { /* not already cleared */
764 config_reset(mgr, options, mvar, use_defaults);
765 }
766 }
767 return 0;
768 } else if (c->command == CONFIG_LINE_CLEAR && !clear_first) {
769 // This block is unreachable, since a CLEAR line always has an
770 // empty value, and so will trigger be handled by the previous
771 // "if (!strlen(c->value))" block.
772
773 // LCOV_EXCL_START
775 config_reset(mgr, options, mvar, use_defaults);
776 // LCOV_EXCL_STOP
777 }
778
779 if (options_seen && config_var_is_replaced_on_set(cvar)) {
780 /* We're tracking which options we've seen, and this option is not
781 * supposed to occur more than once. */
782 tor_assert(var_index >= 0);
783 if (bitarray_is_set(options_seen, var_index)) {
784 log_warn(LD_CONFIG, "Option '%s' used more than once; all but the last "
785 "value will be ignored.", cvar->member.name);
786 }
787 bitarray_set(options_seen, var_index);
788 }
789
790 if (config_assign_value(mgr, options, c, msg) < 0)
791 return -2;
792 return 0;
793}
794
795/** Restore the option named <b>key</b> in options to its default value.
796 * Called from config_assign(). */
797STATIC void
798config_reset_line(const config_mgr_t *mgr, void *options,
799 const char *key, int use_defaults)
800{
801 const managed_var_t *var;
802
803 CONFIG_CHECK(mgr, options);
804
805 var = config_mgr_find_var(mgr, key, true, NULL);
806 if (!var)
807 return; /* give error on next pass. */
808
809 config_reset(mgr, options, var, use_defaults);
810}
811
812/** Return true iff value needs to be quoted and escaped to be used in
813 * a configuration file. */
814static int
816{
817 if (*value == '\"')
818 return 1;
819 while (*value) {
820 switch (*value)
821 {
822 case '\r':
823 case '\n':
824 case '#':
825 /* Note: quotes and backspaces need special handling when we are using
826 * quotes, not otherwise, so they don't trigger escaping on their
827 * own. */
828 return 1;
829 default:
830 if (!TOR_ISPRINT(*value))
831 return 1;
832 }
833 ++value;
834 }
835 return 0;
836}
837
838/** Return newly allocated line or lines corresponding to <b>key</b> in the
839 * configuration <b>options</b>. If <b>escape_val</b> is true and a
840 * value needs to be quoted before it's put in a config file, quote and
841 * escape that value. Return NULL if no such key exists. */
843config_get_assigned_option(const config_mgr_t *mgr, const void *options,
844 const char *key, int escape_val)
845{
846 const managed_var_t *var;
847 config_line_t *result;
848
849 tor_assert(options && key);
850
851 CONFIG_CHECK(mgr, options);
852
853 var = config_mgr_find_var(mgr, key, true, NULL);
854 if (!var) {
855 log_warn(LD_CONFIG, "Unknown option '%s'. Failing.", key);
856 return NULL;
857 }
858 if (! config_var_is_gettable(var->cvar)) {
859 log_warn(LD_CONFIG, "Option '%s' is obsolete or unfetchable. Failing.",
860 key);
861 return NULL;
862 }
863 const void *object = config_mgr_get_obj(mgr, options, var->object_idx);
864
865 result = struct_var_kvencode(object, &var->cvar->member);
866
867 if (escape_val) {
868 config_line_t *line;
869 for (line = result; line; line = line->next) {
870 if (line->value && config_value_needs_escape(line->value)) {
871 char *newval = esc_for_log(line->value);
872 tor_free(line->value);
873 line->value = newval;
874 }
875 }
876 }
877
878 return result;
879}
880/** Iterate through the linked list of requested options <b>list</b>.
881 * For each item, convert as appropriate and assign to <b>options</b>.
882 * If an item is unrecognized, set *msg and return -1 immediately,
883 * else return 0 for success.
884 *
885 * If <b>clear_first</b>, interpret config options as replacing (not
886 * extending) their previous values. If <b>clear_first</b> is set,
887 * then <b>use_defaults</b> to decide if you set to defaults after
888 * clearing, or make the value 0 or NULL.
889 *
890 * Here are the use cases:
891 * 1. A non-empty AllowInvalid line in your torrc. Appends to current
892 * if linelist, replaces current if csv.
893 * 2. An empty AllowInvalid line in your torrc. Should clear it.
894 * 3. "RESETCONF AllowInvalid" sets it to default.
895 * 4. "SETCONF AllowInvalid" makes it NULL.
896 * 5. "SETCONF AllowInvalid=foo" clears it and sets it to "foo".
897 *
898 * Use_defaults Clear_first
899 * 0 0 "append"
900 * 1 0 undefined, don't use
901 * 0 1 "set to null first"
902 * 1 1 "set to defaults first"
903 * Return 0 on success, -1 on bad key, -2 on bad value.
904 *
905 * As an additional special case, if a LINELIST config option has
906 * no value and clear_first is 0, then warn and ignore it.
907 */
908
909/*
910There are three call cases for config_assign() currently.
911
912Case one: Torrc entry
913options_init_from_torrc() calls config_assign(0, 0)
914 calls config_assign_line(0, 0).
915 if value is empty, calls config_reset(0) and returns.
916 calls config_assign_value(), appends.
917
918Case two: setconf
919options_trial_assign() calls config_assign(0, 1)
920 calls config_reset_line(0)
921 calls config_reset(0)
922 calls option_clear().
923 calls config_assign_line(0, 1).
924 if value is empty, returns.
925 calls config_assign_value(), appends.
926
927Case three: resetconf
928options_trial_assign() calls config_assign(1, 1)
929 calls config_reset_line(1)
930 calls config_reset(1)
931 calls option_clear().
932 calls config_assign_value(default)
933 calls config_assign_line(1, 1).
934 returns.
935*/
936int
937config_assign(const config_mgr_t *mgr, void *options, config_line_t *list,
938 unsigned config_assign_flags, char **msg)
939{
940 config_line_t *p;
941 bitarray_t *options_seen;
942 const int n_options = config_count_options(mgr);
943 const unsigned clear_first = config_assign_flags & CAL_CLEAR_FIRST;
944 const unsigned use_defaults = config_assign_flags & CAL_USE_DEFAULTS;
945
946 CONFIG_CHECK(mgr, options);
947
948 /* pass 1: normalize keys */
949 for (p = list; p; p = p->next) {
950 const char *full = config_expand_abbrev(mgr, p->key, 0, 1);
951 if (strcmp(full,p->key)) {
952 tor_free(p->key);
953 p->key = tor_strdup(full);
954 }
955 }
956
957 /* pass 2: if we're reading from a resetting source, clear all
958 * mentioned config options, and maybe set to their defaults. */
959 if (clear_first) {
960 for (p = list; p; p = p->next)
961 config_reset_line(mgr, options, p->key, use_defaults);
962 }
963
964 options_seen = bitarray_init_zero(n_options);
965 /* pass 3: assign. */
966 while (list) {
967 int r;
968 if ((r=config_assign_line(mgr, options, list, config_assign_flags,
969 options_seen, msg))) {
970 bitarray_free(options_seen);
971 return r;
972 }
973 list = list->next;
974 }
975 bitarray_free(options_seen);
976
977 /** Now we're done assigning a group of options to the configuration.
978 * Subsequent group assignments should _replace_ linelists, not extend
979 * them. */
980 config_mark_lists_fragile(mgr, options);
981
982 return 0;
983}
984
985/** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent.
986 * Called from config_reset() and config_free(). */
987static void
988config_clear(const config_mgr_t *mgr, void *options, const managed_var_t *var)
989{
990 void *object = config_mgr_get_obj_mutable(mgr, options, var->object_idx);
991 struct_var_free(object, &var->cvar->member);
992}
993
994/** Clear the option indexed by <b>var</b> in <b>options</b>. Then if
995 * <b>use_defaults</b>, set it to its default value.
996 * Called by config_init() and option_reset_line() and option_assign_line(). */
997static void
998config_reset(const config_mgr_t *mgr, void *options,
999 const managed_var_t *var, int use_defaults)
1000{
1001 config_line_t *c;
1002 char *msg = NULL;
1003 CONFIG_CHECK(mgr, options);
1004 config_clear(mgr, options, var); /* clear it first */
1005
1006 if (!use_defaults)
1007 return; /* all done */
1008
1009 if (var->cvar->initvalue) {
1010 c = tor_malloc_zero(sizeof(config_line_t));
1011 c->key = tor_strdup(var->cvar->member.name);
1012 c->value = tor_strdup(var->cvar->initvalue);
1013 if (config_assign_value(mgr, options, c, &msg) < 0) {
1014 // LCOV_EXCL_START
1015 log_warn(LD_BUG, "Failed to assign default: %s", msg);
1016 tor_free(msg); /* if this happens it's a bug */
1017 // LCOV_EXCL_STOP
1018 }
1019 config_free_lines(c);
1020 }
1021}
1022
1023/** Release storage held by <b>options</b>. */
1024void
1025config_free_(const config_mgr_t *mgr, void *options)
1026{
1027 if (!options)
1028 return;
1029
1030 tor_assert(mgr);
1031
1032 if (mgr->toplevel->clear_fn) {
1033 mgr->toplevel->clear_fn(mgr, options);
1034 }
1035 config_suite_t **suitep = config_mgr_get_suite_ptr(mgr, options);
1036 if (suitep) {
1037 tor_assert(smartlist_len((*suitep)->configs) ==
1038 smartlist_len(mgr->subconfigs));
1040 void *obj = smartlist_get((*suitep)->configs, fmt_sl_idx);
1041 if (fmt->clear_fn) {
1042 fmt->clear_fn(mgr, obj);
1043 }
1044 } SMARTLIST_FOREACH_END(fmt);
1045 }
1046
1048 config_clear(mgr, options, mv);
1049 } SMARTLIST_FOREACH_END(mv);
1050
1051 if (mgr->toplevel->extra) {
1052 config_line_t **linep = STRUCT_VAR_P(options,
1053 mgr->toplevel->extra->offset);
1054 config_free_lines(*linep);
1055 *linep = NULL;
1056 }
1057
1058 if (suitep) {
1059 SMARTLIST_FOREACH((*suitep)->configs, void *, obj, tor_free(obj));
1060 config_suite_free(*suitep);
1061 }
1062
1063 tor_free(options);
1064}
1065
1066/** Return true iff the option <b>name</b> has the same value in <b>o1</b>
1067 * and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options.
1068 */
1069int
1071 const void *o1, const void *o2,
1072 const char *name)
1073{
1074 CONFIG_CHECK(mgr, o1);
1075 CONFIG_CHECK(mgr, o2);
1076
1077 const managed_var_t *var = config_mgr_find_var(mgr, name, true, NULL);
1078 if (!var) {
1079 return true;
1080 }
1081 const void *obj1 = config_mgr_get_obj(mgr, o1, var->object_idx);
1082 const void *obj2 = config_mgr_get_obj(mgr, o2, var->object_idx);
1083
1084 return struct_var_eq(obj1, obj2, &var->cvar->member);
1085}
1086
1087/**
1088 * Return a list of the options which have changed between <b>options1</b> and
1089 * <b>options2</b>. If an option has reverted to its default value, it has a
1090 * value entry of NULL.
1091 *
1092 * <b>options1</b> and <b>options2</b> must be top-level configuration objects
1093 * of the type managed by <b>mgr</b>.
1094 **/
1097 const void *options1, const void *options2)
1098{
1099 config_line_t *result = NULL;
1100 config_line_t **next = &result;
1102 if (! config_var_should_list_changes(mv->cvar)) {
1103 /* something else will check this var, or it doesn't need checking */
1104 continue;
1105 }
1106 const void *obj1 = config_mgr_get_obj(mgr, options1, mv->object_idx);
1107 const void *obj2 = config_mgr_get_obj(mgr, options2, mv->object_idx);
1108
1109 if (struct_var_eq(obj1, obj2, &mv->cvar->member)) {
1110 continue;
1111 }
1112
1113 const char *varname = mv->cvar->member.name;
1114 config_line_t *line =
1115 config_get_assigned_option(mgr, options2, varname, 1);
1116
1117 if (line) {
1118 *next = line;
1119 } else {
1120 *next = tor_malloc_zero(sizeof(config_line_t));
1121 (*next)->key = tor_strdup(varname);
1122 }
1123 while (*next)
1124 next = &(*next)->next;
1125 } SMARTLIST_FOREACH_END(mv);
1126
1127 return result;
1128}
1129
1130/** Copy storage held by <b>old</b> into a new or_options_t and return it. */
1131void *
1132config_dup(const config_mgr_t *mgr, const void *old)
1133{
1134 void *newopts;
1135
1136 newopts = config_new(mgr);
1138 if (! config_var_needs_copy(mv->cvar)) {
1139 // Something else will copy this option, or it doesn't need copying.
1140 continue;
1141 }
1142 const void *oldobj = config_mgr_get_obj(mgr, old, mv->object_idx);
1143 void *newobj = config_mgr_get_obj_mutable(mgr, newopts, mv->object_idx);
1144 if (struct_var_copy(newobj, oldobj, &mv->cvar->member) < 0) {
1145 // LCOV_EXCL_START
1146 log_err(LD_BUG, "Unable to copy value for %s.",
1147 mv->cvar->member.name);
1148 tor_assert_unreached();
1149 // LCOV_EXCL_STOP
1150 }
1151 } SMARTLIST_FOREACH_END(mv);
1152
1153 return newopts;
1154}
1155/** Set all vars in the configuration object <b>options</b> to their default
1156 * values. */
1157void
1158config_init(const config_mgr_t *mgr, void *options)
1159{
1160 CONFIG_CHECK(mgr, options);
1161
1163 if (!mv->cvar->initvalue)
1164 continue; /* defaults to NULL or 0 */
1165 config_reset(mgr, options, mv, 1);
1166 } SMARTLIST_FOREACH_END(mv);
1167}
1168
1169/**
1170 * Helper for config_validate_single: see whether any immutable option
1171 * has changed between old_options and new_options.
1172 *
1173 * On success return 0; on failure set *msg_out to a newly allocated
1174 * string explaining what is wrong, and return -1.
1175 */
1176static int
1178 const void *old_options,
1179 const void *new_options,
1180 char **msg_out)
1181{
1182 tor_assert(fmt);
1183 tor_assert(new_options);
1184 if (BUG(! old_options))
1185 return 0;
1186
1187 unsigned i;
1188 for (i = 0; fmt->vars[i].member.name; ++i) {
1189 const config_var_t *v = &fmt->vars[i];
1191 continue;
1192
1193 if (! struct_var_eq(old_options, new_options, &v->member)) {
1194 tor_asprintf(msg_out,
1195 "While Tor is running, changing %s is not allowed",
1196 v->member.name);
1197 return -1;
1198 }
1199 }
1200
1201 return 0;
1202}
1203
1204/**
1205 * Normalize and validate a single object `options` within a configuration
1206 * suite, according to its format. `options` may be modified as appropriate
1207 * in order to set ancillary data. If `old_options` is provided, make sure
1208 * that the transition from `old_options` to `options` is permitted.
1209 *
1210 * On success return VSTAT_OK; on failure set *msg_out to a newly allocated
1211 * string explaining what is wrong, and return a different validation_status_t
1212 * to describe which step failed.
1213 **/
1216 const void *old_options, void *options,
1217 char **msg_out)
1218{
1219 tor_assert(fmt);
1220 tor_assert(options);
1221
1222 if (fmt->pre_normalize_fn) {
1223 if (fmt->pre_normalize_fn(options, msg_out) < 0) {
1224 return VSTAT_PRE_NORMALIZE_ERR;
1225 }
1226 }
1227
1228 if (fmt->legacy_validate_fn) {
1229 if (fmt->legacy_validate_fn(old_options, options, msg_out) < 0) {
1230 return VSTAT_LEGACY_ERR;
1231 }
1232 }
1233
1234 if (fmt->validate_fn) {
1235 if (fmt->validate_fn(options, msg_out) < 0) {
1236 return VSTAT_VALIDATE_ERR;
1237 }
1238 }
1239
1240 if (old_options) {
1241 if (config_check_immutable_flags(fmt, old_options, options, msg_out) < 0) {
1242 return VSTAT_TRANSITION_ERR;
1243 }
1244
1245 if (fmt->check_transition_fn) {
1246 if (fmt->check_transition_fn(old_options, options, msg_out) < 0) {
1247 return VSTAT_TRANSITION_ERR;
1248 }
1249 }
1250 }
1251
1252 if (fmt->post_normalize_fn) {
1253 if (fmt->post_normalize_fn(options, msg_out) < 0) {
1254 return VSTAT_POST_NORMALIZE_ERR;
1255 }
1256 }
1257
1258 return VSTAT_OK;
1259}
1260
1261/**
1262 * Normalize and validate all the options in configuration object `options`
1263 * and its sub-objects. `options` may be modified as appropriate in order to
1264 * set ancillary data. If `old_options` is provided, make sure that the
1265 * transition from `old_options` to `options` is permitted.
1266 *
1267 * On success return VSTAT_OK; on failure set *msg_out to a newly allocated
1268 * string explaining what is wrong, and return a different validation_status_t
1269 * to describe which step failed.
1270 **/
1273 const void *old_options, void *options,
1274 char **msg_out)
1275{
1277 CONFIG_CHECK(mgr, options);
1278 if (old_options) {
1279 CONFIG_CHECK(mgr, old_options);
1280 }
1281
1282 config_suite_t **suitep_new = config_mgr_get_suite_ptr(mgr, options);
1283 config_suite_t **suitep_old = NULL;
1284 if (old_options)
1285 suitep_old = config_mgr_get_suite_ptr(mgr, (void*) old_options);
1286
1287 /* Validate the sub-objects */
1288 if (suitep_new) {
1290 void *obj = smartlist_get((*suitep_new)->configs, fmt_sl_idx);
1291 const void *obj_old=NULL;
1292 if (suitep_old)
1293 obj_old = smartlist_get((*suitep_old)->configs, fmt_sl_idx);
1294
1295 rv = config_validate_single(fmt, obj_old, obj, msg_out);
1296 if (rv < 0)
1297 return rv;
1298 } SMARTLIST_FOREACH_END(fmt);
1299 }
1300
1301 /* Validate the top-level object. */
1302 rv = config_validate_single(mgr->toplevel, old_options, options, msg_out);
1303 if (rv < 0)
1304 return rv;
1305
1306 return VSTAT_OK;
1307}
1308
1309/** Allocate and return a new string holding the written-out values of the vars
1310 * in 'options'. If 'minimal', do not write out any default-valued vars.
1311 * Else, if comment_defaults, write default values as comments.
1312 */
1313char *
1314config_dump(const config_mgr_t *mgr, const void *default_options,
1315 const void *options, int minimal,
1316 int comment_defaults)
1317{
1318 const config_format_t *fmt = mgr->toplevel;
1319 smartlist_t *elements;
1320 const void *defaults = default_options;
1321 void *defaults_tmp = NULL;
1322 config_line_t *line, *assigned;
1323 char *result;
1324 char *msg = NULL;
1325
1326 if (defaults == NULL) {
1327 defaults = defaults_tmp = config_new(mgr);
1328 config_init(mgr, defaults_tmp);
1329 }
1330
1331 /* XXX use a 1 here so we don't add a new log line while dumping */
1332 if (default_options == NULL) {
1333 if (config_validate(mgr, NULL, defaults_tmp, &msg) < 0) {
1334 // LCOV_EXCL_START
1335 log_err(LD_BUG, "Failed to validate default config: %s", msg);
1336 tor_free(msg);
1337 tor_assert(0);
1338 // LCOV_EXCL_STOP
1339 }
1340 }
1341
1342 elements = smartlist_new();
1344 int comment_option = 0;
1345 /* Don't save 'hidden' control variables. */
1346 if (! config_var_is_dumpable(mv->cvar))
1347 continue;
1348 const char *name = mv->cvar->member.name;
1349 if (minimal && config_is_same(mgr, options, defaults, name))
1350 continue;
1351 else if (comment_defaults &&
1352 config_is_same(mgr, options, defaults, name))
1353 comment_option = 1;
1354
1355 line = assigned =
1356 config_get_assigned_option(mgr, options, name, 1);
1357
1358 for (; line; line = line->next) {
1359 if (!strcmpstart(line->key, "__")) {
1360 /* This check detects "hidden" variables inside LINELIST_V structures.
1361 */
1362 continue;
1363 }
1364 int value_exists = line->value && *(line->value);
1365 smartlist_add_asprintf(elements, "%s%s%s%s\n",
1366 comment_option ? "# " : "",
1367 line->key, value_exists ? " " : "", line->value);
1368 }
1369 config_free_lines(assigned);
1370 } SMARTLIST_FOREACH_END(mv);
1371
1372 if (fmt->extra) {
1373 line = *(config_line_t**)STRUCT_VAR_P(options, fmt->extra->offset);
1374 for (; line; line = line->next) {
1375 int value_exists = line->value && *(line->value);
1376 smartlist_add_asprintf(elements, "%s%s%s\n",
1377 line->key, value_exists ? " " : "", line->value);
1378 }
1379 }
1380
1381 result = smartlist_join_strings(elements, "", 0, NULL);
1382 SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
1383 smartlist_free(elements);
1384 config_free(mgr, defaults_tmp);
1385 return result;
1386}
1387
1388/**
1389 * Return true if every member of <b>options</b> is in-range and well-formed.
1390 * Return false otherwise. Log errors at level <b>severity</b>.
1391 */
1392bool
1393config_check_ok(const config_mgr_t *mgr, const void *options, int severity)
1394{
1395 bool all_ok = true;
1396
1398 if (!struct_var_ok(options, &mv->cvar->member)) {
1399 log_fn(severity, LD_BUG, "Invalid value for %s",
1400 mv->cvar->member.name);
1401 all_ok = false;
1402 }
1403 } SMARTLIST_FOREACH_END(mv);
1404
1405 return all_ok;
1406}
Implements a variable-sized (but non-resizeable) bit-array.
unsigned int bitarray_t
Definition: bitarray.h:30
static bitarray_t * bitarray_init_zero(unsigned int n_bits)
Definition: bitarray.h:33
static void bitarray_set(bitarray_t *b, int bit)
Definition: bitarray.h:68
static unsigned int bitarray_is_set(bitarray_t *b, int bit)
Definition: bitarray.h:81
#define STRUCT_VAR_P(st, off)
Locale-independent character-type inspection (header)
const char * name
Definition: config.c:2462
void config_line_append(config_line_t **lst, const char *key, const char *val)
Definition: confline.c:32
Header for confline.c.
const void * config_mgr_get_obj(const config_mgr_t *mgr, const void *toplevel, int idx)
Definition: confmgt.c:265
static void config_clear(const config_mgr_t *mgr, void *options, const managed_var_t *var)
Definition: confmgt.c:988
static void config_mgr_register_fmt(config_mgr_t *mgr, const config_format_t *fmt, int object_idx)
Definition: confmgt.c:161
void config_init(const config_mgr_t *mgr, void *options)
Definition: confmgt.c:1158
static bool config_var_needs_copy(const config_var_t *var)
Definition: confmgt.c:603
static bool config_var_has_flag(const config_var_t *var, uint32_t flag)
Definition: confmgt.c:535
static int config_count_options(const config_mgr_t *mgr)
Definition: confmgt.c:525
static int config_check_immutable_flags(const config_format_t *fmt, const void *old_options, const void *new_options, char **msg_out)
Definition: confmgt.c:1177
void config_mgr_freeze(config_mgr_t *mgr)
Definition: confmgt.c:285
void warn_deprecated_option(const char *what, const char *why)
Definition: confmgt.c:692
config_line_t * config_get_changes(const config_mgr_t *mgr, const void *options1, const void *options2)
Definition: confmgt.c:1096
bool config_var_is_listable(const config_var_t *var)
Definition: confmgt.c:619
static int managed_var_cmp(const void **a, const void **b)
Definition: confmgt.c:272
static int config_assign_line(const config_mgr_t *mgr, void *options, config_line_t *c, unsigned flags, bitarray_t *options_seen, char **msg)
Definition: confmgt.c:711
bool config_check_ok(const config_mgr_t *mgr, const void *options, int severity)
Definition: confmgt.c:1393
static config_suite_t * config_suite_new(void)
Definition: confmgt.c:86
const char * config_find_option_name(const config_mgr_t *mgr, const char *key)
Definition: confmgt.c:513
void config_free_(const config_mgr_t *mgr, void *options)
Definition: confmgt.c:1025
static int config_assign_value(const config_mgr_t *mgr, void *options, config_line_t *c, char **msg)
Definition: confmgt.c:648
int config_is_same(const config_mgr_t *mgr, const void *o1, const void *o2, const char *name)
Definition: confmgt.c:1070
void config_check_toplevel_magic(const config_mgr_t *mgr, const void *object)
Definition: confmgt.c:347
const char * config_expand_abbrev(const config_mgr_t *mgr, const char *option, int command_line, int warn_obsolete)
Definition: confmgt.c:415
static bool config_var_is_replaced_on_set(const config_var_t *var)
Definition: confmgt.c:548
static void config_reset(const config_mgr_t *fmt, void *options, const managed_var_t *var, int use_defaults)
Definition: confmgt.c:998
bool config_var_is_settable(const config_var_t *var)
Definition: confmgt.c:558
static void managed_var_free_(managed_var_t *mv)
Definition: confmgt.c:66
static void config_mgr_assert_magic_ok(const config_mgr_t *mgr, const void *options)
Definition: confmgt.c:356
void * config_dup(const config_mgr_t *mgr, const void *old)
Definition: confmgt.c:1132
static bool config_var_should_list_changes(const config_var_t *var)
Definition: confmgt.c:589
static void config_mark_lists_fragile(const config_mgr_t *mgr, void *options)
Definition: confmgt.c:674
static void config_suite_free_(config_suite_t *suite)
Definition: confmgt.c:96
static const managed_var_t * config_mgr_find_var(const config_mgr_t *mgr, const char *key, bool allow_truncated, int *idx_out)
Definition: confmgt.c:468
smartlist_t * config_mgr_list_deprecated_vars(const config_mgr_t *mgr)
Definition: confmgt.c:333
void * config_mgr_get_obj_mutable(const config_mgr_t *mgr, void *toplevel, int idx)
Definition: confmgt.c:246
static int config_value_needs_escape(const char *value)
Definition: confmgt.c:815
config_line_t * config_get_assigned_option(const config_mgr_t *mgr, const void *options, const char *key, int escape_val)
Definition: confmgt.c:843
const char * config_find_deprecation(const config_mgr_t *mgr, const char *key)
Definition: confmgt.c:442
static config_suite_t ** config_mgr_get_suite_ptr(const config_mgr_t *mgr, void *toplevel)
Definition: confmgt.c:229
smartlist_t * config_mgr_list_vars(const config_mgr_t *mgr)
Definition: confmgt.c:319
validation_status_t config_validate(const config_mgr_t *mgr, const void *old_options, void *options, char **msg_out)
Definition: confmgt.c:1272
int config_assign(const config_mgr_t *mgr, void *options, config_line_t *list, unsigned config_assign_flags, char **msg)
Definition: confmgt.c:937
static bool config_var_is_dumpable(const config_var_t *var)
Definition: confmgt.c:633
static bool config_var_is_gettable(const config_var_t *var)
Definition: confmgt.c:568
static validation_status_t config_validate_single(const config_format_t *fmt, const void *old_options, void *options, char **msg_out)
Definition: confmgt.c:1215
STATIC void config_reset_line(const config_mgr_t *mgr, void *options, const char *key, int use_defaults)
Definition: confmgt.c:798
char * config_dump(const config_mgr_t *mgr, const void *default_options, const void *options, int minimal, int comment_defaults)
Definition: confmgt.c:1314
config_mgr_t * config_mgr_new(const config_format_t *toplevel_fmt)
Definition: confmgt.c:145
#define CONFIG_CHECK(mgr, cfg)
Definition: confmgt.c:381
void config_mgr_free_(config_mgr_t *mgr)
Definition: confmgt.c:302
int config_mgr_add_format(config_mgr_t *mgr, const config_format_t *fmt)
Definition: confmgt.c:216
void * config_new(const config_mgr_t *mgr)
Definition: confmgt.c:387
Header for confmgt.c.
#define CAL_WARN_DEPRECATIONS
Definition: confmgt.h:63
validation_status_t
Definition: confmgt.h:83
#define CAL_USE_DEFAULTS
Definition: confmgt.h:50
#define CAL_CLEAR_FIRST
Definition: confmgt.h:59
#define CFLG_IMMUTABLE
Definition: conftypes.h:199
#define CFLG_NODUMP
Definition: conftypes.h:154
#define CFLG_WARN_DISABLED
Definition: conftypes.h:209
#define CFLG_NOCMP
Definition: conftypes.h:186
#define CFLG_WARN_OBSOLETE
Definition: conftypes.h:204
#define CFLG_NOCOPY
Definition: conftypes.h:176
#define CFLG_NOREPLACE
Definition: conftypes.h:194
#define CFLG_NOSET
Definition: conftypes.h:167
#define CFLG_NOLIST
Definition: conftypes.h:161
char * esc_for_log(const char *s)
Definition: escape.c:30
Header for escape.c.
Headers for log.c.
#define log_fn(severity, domain, args,...)
Definition: log.h:283
#define LD_BUG
Definition: log.h:86
#define LD_GENERAL
Definition: log.h:62
#define LD_CONFIG
Definition: log.h:68
#define tor_free(p)
Definition: malloc.h:56
int tor_asprintf(char **strp, const char *fmt,...)
Definition: printf.c:75
Header for printf.c.
void smartlist_add_asprintf(struct smartlist_t *sl, const char *pattern,...)
Definition: smartlist.c:36
char * smartlist_join_strings(smartlist_t *sl, const char *join, int terminate, size_t *len_out)
Definition: smartlist.c:279
void smartlist_sort(smartlist_t *sl, int(*compare)(const void **a, const void **b))
Definition: smartlist.c:334
Header for smartlist.c.
int smartlist_contains(const smartlist_t *sl, const void *element)
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
const char * name
Definition: conftypes.h:258
const struct_member_t * extra
Definition: conftypes.h:371
ptrdiff_t config_suite_offset
Definition: conftypes.h:380
bool has_config_suite
Definition: conftypes.h:376
struct_magic_decl_t magic
Definition: conftypes.h:349
clear_cfg_fn_t clear_fn
Definition: conftypes.h:368
unsigned int command
Definition: confline.h:35
smartlist_t * subconfigs
Definition: confmgt.c:119
smartlist_t * all_deprecations
Definition: confmgt.c:127
smartlist_t * all_abbrevs
Definition: confmgt.c:125
const config_format_t * toplevel
Definition: confmgt.c:114
bool frozen
Definition: confmgt.c:131
struct_magic_decl_t toplevel_magic
Definition: confmgt.c:137
smartlist_t * all_vars
Definition: confmgt.c:121
smartlist_t * configs
Definition: confmgt.c:79
const char * initvalue
Definition: conftypes.h:229
uint32_t flags
Definition: conftypes.h:230
int object_idx
Definition: confmgt.c:55
const config_var_t * cvar
Definition: confmgt.c:50
uint32_t magic_val
Definition: conftypes.h:142
ptrdiff_t offset
Definition: conftypes.h:125
const char * name
Definition: conftypes.h:98
void struct_set_magic(void *object, const struct_magic_decl_t *decl)
Definition: structvar.c:48
void struct_check_magic(const void *object, const struct_magic_decl_t *decl)
Definition: structvar.c:63
bool struct_var_eq(const void *a, const void *b, const struct_member_t *member)
Definition: structvar.c:145
int struct_var_kvassign(void *object, const struct config_line_t *line, char **errmsg, const struct_member_t *member)
Definition: structvar.c:172
int struct_var_copy(void *dest, const void *src, const struct_member_t *member)
Definition: structvar.c:131
void struct_var_free(void *object, const struct_member_t *member)
Definition: structvar.c:118
void struct_var_mark_fragile(void *object, const struct_member_t *member)
Definition: structvar.c:201
bool struct_var_ok(const void *object, const struct_member_t *member)
Definition: structvar.c:159
uint32_t struct_var_get_flags(const struct_member_t *member)
Definition: structvar.c:234
struct config_line_t * struct_var_kvencode(const void *object, const struct_member_t *member)
Definition: structvar.c:187
Header for lib/confmgt/structvar.c.
#define STATIC
Definition: testsupport.h:32
Header for lib/confmgt/unitparse.c.
Macros to manage assertions, fatal and non-fatal.
#define tor_assert_nonfatal_unreached()
Definition: util_bug.h:177
#define tor_assert(expr)
Definition: util_bug.h:103
int strcmpstart(const char *s1, const char *s2)
Definition: util_string.c:217
Header for util_string.c.