confmgt.c (44489B)
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 28 #include "lib/confmgt/structvar.h" 29 #include "lib/confmgt/unitparse.h" 30 #include "lib/container/bitarray.h" 31 #include "lib/container/smartlist.h" 32 #include "lib/encoding/confline.h" 33 #include "lib/log/escape.h" 34 #include "lib/log/log.h" 35 #include "lib/log/util_bug.h" 36 #include "lib/string/compat_ctype.h" 37 #include "lib/string/printf.h" 38 #include "lib/string/util_string.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. */ 46 typedef struct managed_var_t { 47 /** 48 * A pointer to the config_var_t for this option. 49 */ 50 const config_var_t *cvar; 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 **/ 55 int object_idx; 56 } managed_var_t; 57 58 static void config_reset(const config_mgr_t *fmt, void *options, 59 const managed_var_t *var, int use_defaults); 60 static void config_mgr_register_fmt(config_mgr_t *mgr, 61 const config_format_t *fmt, 62 int object_idx); 63 64 /** Release all storage held in a managed_var_t. */ 65 static void 66 managed_var_free_(managed_var_t *mv) 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 75 struct config_suite_t { 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. */ 79 smartlist_t *configs; 80 }; 81 82 /** 83 * Allocate a new empty config_suite_t. 84 **/ 85 static config_suite_t * 86 config_suite_new(void) 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.) */ 95 static void 96 config_suite_free_(config_suite_t *suite) 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 107 struct config_mgr_t { 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 */ 114 const config_format_t *toplevel; 115 /** 116 * List of second-level configuration format objects that this manager 117 * also knows about. 118 */ 119 smartlist_t *subconfigs; 120 /** A smartlist of managed_var_t objects for all configuration formats. */ 121 smartlist_t *all_vars; 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. */ 125 smartlist_t *all_abbrevs; 126 /** A smartlist of config_deprecation_t for all configuration formats. */ 127 smartlist_t *all_deprecations; 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 */ 137 struct_magic_decl_t toplevel_magic; 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>. */ 144 config_mgr_t * 145 config_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(); 151 mgr->all_deprecations = 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. */ 160 static void 161 config_mgr_register_fmt(config_mgr_t *mgr, 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 **/ 215 int 216 config_mgr_add_format(config_mgr_t *mgr, 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. */ 228 static inline config_suite_t ** 229 config_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 */ 245 void * 246 config_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. */ 264 const void * 265 config_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 */ 271 static int 272 managed_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 **/ 284 void 285 config_mgr_freeze(config_mgr_t *mgr) 286 { 287 static uint64_t mgr_count = 0; 288 289 smartlist_sort(mgr->all_vars, managed_var_cmp); 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 }; 295 mgr->toplevel_magic.magic_val = 296 (uint32_t)siphash24g(magic_input, sizeof(magic_input)); 297 mgr->frozen = true; 298 } 299 300 /** Release all storage held in <b>mgr</b> */ 301 void 302 config_mgr_free_(config_mgr_t *mgr) 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>. */ 318 smartlist_t * 319 config_mgr_list_vars(const config_mgr_t *mgr) 320 { 321 smartlist_t *result = smartlist_new(); 322 tor_assert(mgr); 323 SMARTLIST_FOREACH(mgr->all_vars, managed_var_t *, mv, 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 */ 332 smartlist_t * 333 config_mgr_list_deprecated_vars(const config_mgr_t *mgr) 334 { 335 smartlist_t *result = smartlist_new(); 336 tor_assert(mgr); 337 SMARTLIST_FOREACH(mgr->all_deprecations, config_deprecation_t *, d, 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 **/ 346 void 347 config_check_toplevel_magic(const config_mgr_t *mgr, 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. */ 355 static void 356 config_mgr_assert_magic_ok(const config_mgr_t *mgr, 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)); 372 SMARTLIST_FOREACH_BEGIN(mgr->subconfigs, const config_format_t *, fmt) { 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. */ 386 void * 387 config_new(const config_mgr_t *mgr) 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(); 395 SMARTLIST_FOREACH_BEGIN(mgr->subconfigs, const config_format_t *, fmt) { 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. */ 414 const char * 415 config_expand_abbrev(const config_mgr_t *mgr, const char *option, 416 int command_line, int warn_obsolete) 417 { 418 SMARTLIST_FOREACH_BEGIN(mgr->all_abbrevs, const config_abbrev_t *, abbrev) { 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. */ 441 const char * 442 config_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 447 SMARTLIST_FOREACH_BEGIN(mgr->all_deprecations, const config_deprecation_t *, 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->all_vars, or to -1 if the variable is 465 * not found. 466 */ 467 static const managed_var_t * 468 config_mgr_find_var(const config_mgr_t *mgr, 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 */ 480 SMARTLIST_FOREACH_BEGIN(mgr->all_vars, const managed_var_t *, mv) { 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 */ 492 SMARTLIST_FOREACH_BEGIN(mgr->all_vars, const managed_var_t *, mv) { 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 */ 512 const char * 513 config_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>. */ 524 static int 525 config_count_options(const config_mgr_t *mgr) 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 **/ 534 static bool 535 config_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 **/ 547 static bool 548 config_var_is_replaced_on_set(const config_var_t *var) 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 **/ 557 bool 558 config_var_is_settable(const config_var_t *var) 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 **/ 567 static bool 568 config_var_is_gettable(const config_var_t *var) 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 **/ 588 static bool 589 config_var_should_list_changes(const config_var_t *var) 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 **/ 602 static bool 603 config_var_needs_copy(const config_var_t *var) 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 **/ 618 bool 619 config_var_is_listable(const config_var_t *var) 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 **/ 632 static bool 633 config_var_is_dumpable(const config_var_t *var) 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 */ 647 static int 648 config_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 660 if (config_var_has_flag(var->cvar, CFLG_WARN_OBSOLETE)) { 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. */ 673 static void 674 config_mark_lists_fragile(const config_mgr_t *mgr, void *options) 675 { 676 tor_assert(mgr); 677 tor_assert(options); 678 679 SMARTLIST_FOREACH_BEGIN(mgr->all_vars, const managed_var_t *, mv) { 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 **/ 691 void 692 warn_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 */ 710 static int 711 config_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 774 tor_assert_nonfatal_unreached(); 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(). */ 797 STATIC void 798 config_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. */ 814 static int 815 config_value_needs_escape(const char *value) 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. */ 842 config_line_t * 843 config_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 /* 910 There are three call cases for config_assign() currently. 911 912 Case one: Torrc entry 913 options_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 918 Case two: setconf 919 options_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 927 Case three: resetconf 928 options_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 */ 936 int 937 config_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(). */ 987 static void 988 config_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(). */ 997 static void 998 config_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>. */ 1024 void 1025 config_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)); 1039 SMARTLIST_FOREACH_BEGIN(mgr->subconfigs, const config_format_t *, fmt) { 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 1047 SMARTLIST_FOREACH_BEGIN(mgr->all_vars, const managed_var_t *, mv) { 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 */ 1069 int 1070 config_is_same(const config_mgr_t *mgr, 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 **/ 1095 config_line_t * 1096 config_get_changes(const config_mgr_t *mgr, 1097 const void *options1, const void *options2) 1098 { 1099 config_line_t *result = NULL; 1100 config_line_t **next = &result; 1101 SMARTLIST_FOREACH_BEGIN(mgr->all_vars, managed_var_t *, mv) { 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. */ 1131 void * 1132 config_dup(const config_mgr_t *mgr, const void *old) 1133 { 1134 void *newopts; 1135 1136 newopts = config_new(mgr); 1137 SMARTLIST_FOREACH_BEGIN(mgr->all_vars, managed_var_t *, mv) { 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. */ 1157 void 1158 config_init(const config_mgr_t *mgr, void *options) 1159 { 1160 CONFIG_CHECK(mgr, options); 1161 1162 SMARTLIST_FOREACH_BEGIN(mgr->all_vars, const managed_var_t *, mv) { 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 */ 1176 static int 1177 config_check_immutable_flags(const config_format_t *fmt, 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]; 1190 if (! config_var_has_flag(v, CFLG_IMMUTABLE)) 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 **/ 1214 static validation_status_t 1215 config_validate_single(const config_format_t *fmt, 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 **/ 1271 validation_status_t 1272 config_validate(const config_mgr_t *mgr, 1273 const void *old_options, void *options, 1274 char **msg_out) 1275 { 1276 validation_status_t rv; 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) { 1289 SMARTLIST_FOREACH_BEGIN(mgr->subconfigs, const config_format_t *, fmt) { 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 */ 1313 char * 1314 config_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(); 1343 SMARTLIST_FOREACH_BEGIN(mgr->all_vars, managed_var_t *, mv) { 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 */ 1392 bool 1393 config_check_ok(const config_mgr_t *mgr, const void *options, int severity) 1394 { 1395 bool all_ok = true; 1396 1397 SMARTLIST_FOREACH_BEGIN(mgr->all_vars, const managed_var_t *, mv) { 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 }