2 /* Copyright (c) 2001 Matej Pfajfar.
3 * Copyright (c) 2001-2004, Roger Dingledine.
4 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
5 * Copyright (c) 2007-2017, The Tor Project, Inc. */
6 /* See LICENSE for licensing information */
11 * \brief Back-end for parsing and generating key-value files, used to
12 * implement the torrc file format and the state file.
14 * This module is used by config.c to parse and encode torrc
15 * configuration files, and by statefile.c to parse and encode the
16 * $DATADIR/state file.
18 * To use this module, its callers provide an instance of
19 * config_format_t to describe the mappings from a set of configuration
20 * options to a number of fields in a C structure. With this mapping,
21 * the functions here can convert back and forth between the C structure
22 * specified, and a linked list of key-value pairs.
26 #include "confparse.h"
27 #include "routerset.h"
29 static uint64_t config_parse_memunit(const char *s
, int *ok
);
30 static int config_parse_msec_interval(const char *s
, int *ok
);
31 static int config_parse_interval(const char *s
, int *ok
);
32 static void config_reset(const config_format_t
*fmt
, void *options
,
33 const config_var_t
*var
, int use_defaults
);
35 /** Allocate an empty configuration object of a given format type. */
37 config_new(const config_format_t
*fmt
)
39 void *opts
= tor_malloc_zero(fmt
->size
);
40 *(uint32_t*)STRUCT_VAR_P(opts
, fmt
->magic_offset
) = fmt
->magic
;
41 CONFIG_CHECK(fmt
, opts
);
46 * Functions to parse config options
49 /** If <b>option</b> is an official abbreviation for a longer option,
50 * return the longer option. Otherwise return <b>option</b>.
51 * If <b>command_line</b> is set, apply all abbreviations. Otherwise, only
52 * apply abbreviations that work for the config file and the command line.
53 * If <b>warn_obsolete</b> is set, warn about deprecated names. */
55 config_expand_abbrev(const config_format_t
*fmt
, const char *option
,
56 int command_line
, int warn_obsolete
)
61 for (i
=0; fmt
->abbrevs
[i
].abbreviated
; ++i
) {
62 /* Abbreviations are case insensitive. */
63 if (!strcasecmp(option
,fmt
->abbrevs
[i
].abbreviated
) &&
64 (command_line
|| !fmt
->abbrevs
[i
].commandline_only
)) {
65 if (warn_obsolete
&& fmt
->abbrevs
[i
].warn
) {
67 "The configuration option '%s' is deprecated; "
69 fmt
->abbrevs
[i
].abbreviated
,
70 fmt
->abbrevs
[i
].full
);
72 /* Keep going through the list in case we want to rewrite it more.
73 * (We could imagine recursing here, but I don't want to get the
74 * user into an infinite loop if we craft our list wrong.) */
75 option
= fmt
->abbrevs
[i
].full
;
81 /** If <b>key</b> is a deprecated configuration option, return the message
82 * explaining why it is deprecated (which may be an empty string). Return NULL
83 * if it is not deprecated. The <b>key</b> field must be fully expanded. */
85 config_find_deprecation(const config_format_t
*fmt
, const char *key
)
87 if (BUG(fmt
== NULL
) || BUG(key
== NULL
))
89 if (fmt
->deprecations
== NULL
)
92 const config_deprecation_t
*d
;
93 for (d
= fmt
->deprecations
; d
->name
; ++d
) {
94 if (!strcasecmp(d
->name
, key
)) {
95 return d
->why_deprecated
? d
->why_deprecated
: "";
101 /** As config_find_option, but return a non-const pointer. */
103 config_find_option_mutable(config_format_t
*fmt
, const char *key
)
106 size_t keylen
= strlen(key
);
108 return NULL
; /* if they say "--" on the command line, it's not an option */
109 /* First, check for an exact (case-insensitive) match */
110 for (i
=0; fmt
->vars
[i
].name
; ++i
) {
111 if (!strcasecmp(key
, fmt
->vars
[i
].name
)) {
112 return &fmt
->vars
[i
];
115 /* If none, check for an abbreviated match */
116 for (i
=0; fmt
->vars
[i
].name
; ++i
) {
117 if (!strncasecmp(key
, fmt
->vars
[i
].name
, keylen
)) {
118 log_warn(LD_CONFIG
, "The abbreviation '%s' is deprecated. "
119 "Please use '%s' instead",
120 key
, fmt
->vars
[i
].name
);
121 return &fmt
->vars
[i
];
124 /* Okay, unrecognized option */
128 /** If <b>key</b> is a configuration option, return the corresponding const
129 * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
130 * warn, and return the corresponding const config_var_t. Otherwise return
134 config_find_option(const config_format_t
*fmt
, const char *key
)
136 return config_find_option_mutable((config_format_t
*)fmt
, key
);
139 /** Return the number of option entries in <b>fmt</b>. */
141 config_count_options(const config_format_t
*fmt
)
144 for (i
=0; fmt
->vars
[i
].name
; ++i
)
150 * Functions to assign config options.
153 /** <b>c</b>-\>key is known to be a real key. Update <b>options</b>
154 * with <b>c</b>-\>value and return 0, or return -1 if bad value.
156 * Called from config_assign_line() and option_reset().
159 config_assign_value(const config_format_t
*fmt
, void *options
,
160 config_line_t
*c
, char **msg
)
163 const config_var_t
*var
;
166 smartlist_t
*csv_str
;
168 CONFIG_CHECK(fmt
, options
);
170 var
= config_find_option(fmt
, c
->key
);
173 lvalue
= STRUCT_VAR_P(options
, var
->var_offset
);
177 case CONFIG_TYPE_PORT
:
178 if (!strcasecmp(c
->value
, "auto")) {
179 *(int *)lvalue
= CFG_AUTO_PORT
;
183 case CONFIG_TYPE_INT
:
184 case CONFIG_TYPE_UINT
:
185 i
= (int)tor_parse_long(c
->value
, 10,
186 var
->type
==CONFIG_TYPE_INT
? INT_MIN
: 0,
187 var
->type
==CONFIG_TYPE_PORT
? 65535 : INT_MAX
,
191 "Int keyword '%s %s' is malformed or out of bounds.",
198 case CONFIG_TYPE_INTERVAL
: {
199 i
= config_parse_interval(c
->value
, &ok
);
202 "Interval '%s %s' is malformed or out of bounds.",
210 case CONFIG_TYPE_MSEC_INTERVAL
: {
211 i
= config_parse_msec_interval(c
->value
, &ok
);
214 "Msec interval '%s %s' is malformed or out of bounds.",
222 case CONFIG_TYPE_MEMUNIT
: {
223 uint64_t u64
= config_parse_memunit(c
->value
, &ok
);
226 "Value '%s %s' is malformed or out of bounds.",
230 *(uint64_t *)lvalue
= u64
;
234 case CONFIG_TYPE_BOOL
:
235 i
= (int)tor_parse_long(c
->value
, 10, 0, 1, &ok
, NULL
);
238 "Boolean '%s %s' expects 0 or 1.",
245 case CONFIG_TYPE_AUTOBOOL
:
246 if (!strcmp(c
->value
, "auto"))
248 else if (!strcmp(c
->value
, "0"))
250 else if (!strcmp(c
->value
, "1"))
253 tor_asprintf(msg
, "Boolean '%s %s' expects 0, 1, or 'auto'.",
259 case CONFIG_TYPE_STRING
:
260 case CONFIG_TYPE_FILENAME
:
261 tor_free(*(char **)lvalue
);
262 *(char **)lvalue
= tor_strdup(c
->value
);
265 case CONFIG_TYPE_DOUBLE
:
266 *(double *)lvalue
= atof(c
->value
);
269 case CONFIG_TYPE_ISOTIME
:
270 if (parse_iso_time(c
->value
, (time_t *)lvalue
)) {
272 "Invalid time '%s' for keyword '%s'", c
->value
, c
->key
);
277 case CONFIG_TYPE_ROUTERSET
:
278 if (*(routerset_t
**)lvalue
) {
279 routerset_free(*(routerset_t
**)lvalue
);
281 *(routerset_t
**)lvalue
= routerset_new();
282 if (routerset_parse(*(routerset_t
**)lvalue
, c
->value
, c
->key
)<0) {
283 tor_asprintf(msg
, "Invalid exit list '%s' for option '%s'",
289 case CONFIG_TYPE_CSV
:
290 if (*(smartlist_t
**)lvalue
) {
291 SMARTLIST_FOREACH(*(smartlist_t
**)lvalue
, char *, cp
, tor_free(cp
));
292 smartlist_clear(*(smartlist_t
**)lvalue
);
294 *(smartlist_t
**)lvalue
= smartlist_new();
297 smartlist_split_string(*(smartlist_t
**)lvalue
, c
->value
, ",",
298 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 0);
301 case CONFIG_TYPE_CSV_INTERVAL
:
302 if (*(smartlist_t
**)lvalue
) {
303 SMARTLIST_FOREACH(*(smartlist_t
**)lvalue
, int *, cp
, tor_free(cp
));
304 smartlist_clear(*(smartlist_t
**)lvalue
);
306 *(smartlist_t
**)lvalue
= smartlist_new();
308 csv_str
= smartlist_new();
309 smartlist_split_string(csv_str
, c
->value
, ",",
310 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 0);
311 SMARTLIST_FOREACH_BEGIN(csv_str
, char *, str
)
313 i
= config_parse_interval(str
, &ok
);
316 "Interval in '%s %s' is malformed or out of bounds.",
318 SMARTLIST_FOREACH(csv_str
, char *, cp
, tor_free(cp
));
319 smartlist_free(csv_str
);
322 csv_int
= tor_malloc_zero(sizeof(int));
324 smartlist_add(*(smartlist_t
**)lvalue
, csv_int
);
326 SMARTLIST_FOREACH_END(str
);
327 SMARTLIST_FOREACH(csv_str
, char *, cp
, tor_free(cp
));
328 smartlist_free(csv_str
);
331 case CONFIG_TYPE_LINELIST
:
332 case CONFIG_TYPE_LINELIST_S
:
334 config_line_t
*lastval
= *(config_line_t
**)lvalue
;
335 if (lastval
&& lastval
->fragile
) {
336 if (c
->command
!= CONFIG_LINE_APPEND
) {
337 config_free_lines(lastval
);
338 *(config_line_t
**)lvalue
= NULL
;
340 lastval
->fragile
= 0;
344 config_line_append((config_line_t
**)lvalue
, c
->key
, c
->value
);
347 case CONFIG_TYPE_OBSOLETE
:
348 log_warn(LD_CONFIG
, "Skipping obsolete configuration option '%s'", c
->key
);
350 case CONFIG_TYPE_LINELIST_V
:
352 "You may not provide a value for virtual option '%s'", c
->key
);
361 /** Mark every linelist in <b>options</b> "fragile", so that fresh assignments
362 * to it will replace old ones. */
364 config_mark_lists_fragile(const config_format_t
*fmt
, void *options
)
370 for (i
= 0; fmt
->vars
[i
].name
; ++i
) {
371 const config_var_t
*var
= &fmt
->vars
[i
];
373 if (var
->type
!= CONFIG_TYPE_LINELIST
&&
374 var
->type
!= CONFIG_TYPE_LINELIST_V
)
377 list
= *(config_line_t
**)STRUCT_VAR_P(options
, var
->var_offset
);
384 warn_deprecated_option(const char *what
, const char *why
)
386 const char *space
= (why
&& strlen(why
)) ? " " : "";
387 log_warn(LD_CONFIG
, "The %s option is deprecated, and will most likely "
388 "be removed in a future version of Tor.%s%s (If you think this is "
389 "a mistake, please let us know!)",
393 /** If <b>c</b> is a syntactically valid configuration line, update
394 * <b>options</b> with its value and return 0. Otherwise return -1 for bad
395 * key, -2 for bad value.
397 * If <b>clear_first</b> is set, clear the value first. Then if
398 * <b>use_defaults</b> is set, set the value to the default.
400 * Called from config_assign().
403 config_assign_line(const config_format_t
*fmt
, void *options
,
404 config_line_t
*c
, unsigned flags
,
405 bitarray_t
*options_seen
, char **msg
)
407 const unsigned use_defaults
= flags
& CAL_USE_DEFAULTS
;
408 const unsigned clear_first
= flags
& CAL_CLEAR_FIRST
;
409 const unsigned warn_deprecations
= flags
& CAL_WARN_DEPRECATIONS
;
410 const config_var_t
*var
;
412 CONFIG_CHECK(fmt
, options
);
414 var
= config_find_option(fmt
, c
->key
);
417 void *lvalue
= STRUCT_VAR_P(options
, fmt
->extra
->var_offset
);
419 "Found unrecognized option '%s'; saving it.", c
->key
);
420 config_line_append((config_line_t
**)lvalue
, c
->key
, c
->value
);
424 "Unknown option '%s'. Failing.", c
->key
);
429 /* Put keyword into canonical case. */
430 if (strcmp(var
->name
, c
->key
)) {
432 c
->key
= tor_strdup(var
->name
);
435 const char *deprecation_msg
;
436 if (warn_deprecations
&&
437 (deprecation_msg
= config_find_deprecation(fmt
, var
->name
))) {
438 warn_deprecated_option(var
->name
, deprecation_msg
);
441 if (!strlen(c
->value
)) {
442 /* reset or clear it, then return */
444 if ((var
->type
== CONFIG_TYPE_LINELIST
||
445 var
->type
== CONFIG_TYPE_LINELIST_S
) &&
446 c
->command
!= CONFIG_LINE_CLEAR
) {
447 /* We got an empty linelist from the torrc or command line.
448 As a special case, call this an error. Warn and ignore. */
450 "Linelist option '%s' has no value. Skipping.", c
->key
);
451 } else { /* not already cleared */
452 config_reset(fmt
, options
, var
, use_defaults
);
456 } else if (c
->command
== CONFIG_LINE_CLEAR
&& !clear_first
) {
457 config_reset(fmt
, options
, var
, use_defaults
);
460 if (options_seen
&& (var
->type
!= CONFIG_TYPE_LINELIST
&&
461 var
->type
!= CONFIG_TYPE_LINELIST_S
)) {
462 /* We're tracking which options we've seen, and this option is not
463 * supposed to occur more than once. */
464 int var_index
= (int)(var
- fmt
->vars
);
465 if (bitarray_is_set(options_seen
, var_index
)) {
466 log_warn(LD_CONFIG
, "Option '%s' used more than once; all but the last "
467 "value will be ignored.", var
->name
);
469 bitarray_set(options_seen
, var_index
);
472 if (config_assign_value(fmt
, options
, c
, msg
) < 0)
477 /** Restore the option named <b>key</b> in options to its default value.
478 * Called from config_assign(). */
480 config_reset_line(const config_format_t
*fmt
, void *options
,
481 const char *key
, int use_defaults
)
483 const config_var_t
*var
;
485 CONFIG_CHECK(fmt
, options
);
487 var
= config_find_option(fmt
, key
);
489 return; /* give error on next pass. */
491 config_reset(fmt
, options
, var
, use_defaults
);
494 /** Return true iff value needs to be quoted and escaped to be used in
495 * a configuration file. */
497 config_value_needs_escape(const char *value
)
507 /* Note: quotes and backspaces need special handling when we are using
508 * quotes, not otherwise, so they don't trigger escaping on their
512 if (!TOR_ISPRINT(*value
))
520 /** Return newly allocated line or lines corresponding to <b>key</b> in the
521 * configuration <b>options</b>. If <b>escape_val</b> is true and a
522 * value needs to be quoted before it's put in a config file, quote and
523 * escape that value. Return NULL if no such key exists. */
525 config_get_assigned_option(const config_format_t
*fmt
, const void *options
,
526 const char *key
, int escape_val
)
528 const config_var_t
*var
;
530 config_line_t
*result
;
531 smartlist_t
*csv_str
;
532 tor_assert(options
&& key
);
534 CONFIG_CHECK(fmt
, options
);
536 var
= config_find_option(fmt
, key
);
538 log_warn(LD_CONFIG
, "Unknown option '%s'. Failing.", key
);
541 value
= STRUCT_VAR_P(options
, var
->var_offset
);
543 result
= tor_malloc_zero(sizeof(config_line_t
));
544 result
->key
= tor_strdup(var
->name
);
547 case CONFIG_TYPE_STRING
:
548 case CONFIG_TYPE_FILENAME
:
549 if (*(char**)value
) {
550 result
->value
= tor_strdup(*(char**)value
);
552 tor_free(result
->key
);
557 case CONFIG_TYPE_ISOTIME
:
558 if (*(time_t*)value
) {
559 result
->value
= tor_malloc(ISO_TIME_LEN
+1);
560 format_iso_time(result
->value
, *(time_t*)value
);
562 tor_free(result
->key
);
565 escape_val
= 0; /* Can't need escape. */
567 case CONFIG_TYPE_PORT
:
568 if (*(int*)value
== CFG_AUTO_PORT
) {
569 result
->value
= tor_strdup("auto");
574 case CONFIG_TYPE_INTERVAL
:
575 case CONFIG_TYPE_MSEC_INTERVAL
:
576 case CONFIG_TYPE_UINT
:
577 case CONFIG_TYPE_INT
:
578 /* This means every or_options_t uint or bool element
579 * needs to be an int. Not, say, a uint16_t or char. */
580 tor_asprintf(&result
->value
, "%d", *(int*)value
);
581 escape_val
= 0; /* Can't need escape. */
583 case CONFIG_TYPE_MEMUNIT
:
584 tor_asprintf(&result
->value
, U64_FORMAT
,
585 U64_PRINTF_ARG(*(uint64_t*)value
));
586 escape_val
= 0; /* Can't need escape. */
588 case CONFIG_TYPE_DOUBLE
:
589 tor_asprintf(&result
->value
, "%f", *(double*)value
);
590 escape_val
= 0; /* Can't need escape. */
593 case CONFIG_TYPE_AUTOBOOL
:
594 if (*(int*)value
== -1) {
595 result
->value
= tor_strdup("auto");
600 case CONFIG_TYPE_BOOL
:
601 result
->value
= tor_strdup(*(int*)value
? "1" : "0");
602 escape_val
= 0; /* Can't need escape. */
604 case CONFIG_TYPE_ROUTERSET
:
605 result
->value
= routerset_to_string(*(routerset_t
**)value
);
607 case CONFIG_TYPE_CSV
:
608 if (*(smartlist_t
**)value
)
610 smartlist_join_strings(*(smartlist_t
**)value
, ",", 0, NULL
);
612 result
->value
= tor_strdup("");
614 case CONFIG_TYPE_CSV_INTERVAL
:
615 if (*(smartlist_t
**)value
) {
616 csv_str
= smartlist_new();
617 SMARTLIST_FOREACH_BEGIN(*(smartlist_t
**)value
, int *, i
)
619 smartlist_add_asprintf(csv_str
, "%d", *i
);
621 SMARTLIST_FOREACH_END(i
);
622 result
->value
= smartlist_join_strings(csv_str
, ",", 0, NULL
);
623 SMARTLIST_FOREACH(csv_str
, char *, cp
, tor_free(cp
));
624 smartlist_free(csv_str
);
626 result
->value
= tor_strdup("");
628 case CONFIG_TYPE_OBSOLETE
:
629 log_fn(LOG_INFO
, LD_CONFIG
,
630 "You asked me for the value of an obsolete config option '%s'.",
632 tor_free(result
->key
);
635 case CONFIG_TYPE_LINELIST_S
:
636 tor_free(result
->key
);
638 result
= config_lines_dup_and_filter(*(const config_line_t
**)value
,
641 case CONFIG_TYPE_LINELIST
:
642 case CONFIG_TYPE_LINELIST_V
:
643 tor_free(result
->key
);
645 result
= config_lines_dup(*(const config_line_t
**)value
);
648 tor_free(result
->key
);
650 log_warn(LD_BUG
,"Unknown type %d for known key '%s'",
657 for (line
= result
; line
; line
= line
->next
) {
658 if (line
->value
&& config_value_needs_escape(line
->value
)) {
659 char *newval
= esc_for_log(line
->value
);
660 tor_free(line
->value
);
661 line
->value
= newval
;
668 /** Iterate through the linked list of requested options <b>list</b>.
669 * For each item, convert as appropriate and assign to <b>options</b>.
670 * If an item is unrecognized, set *msg and return -1 immediately,
671 * else return 0 for success.
673 * If <b>clear_first</b>, interpret config options as replacing (not
674 * extending) their previous values. If <b>clear_first</b> is set,
675 * then <b>use_defaults</b> to decide if you set to defaults after
676 * clearing, or make the value 0 or NULL.
678 * Here are the use cases:
679 * 1. A non-empty AllowInvalid line in your torrc. Appends to current
680 * if linelist, replaces current if csv.
681 * 2. An empty AllowInvalid line in your torrc. Should clear it.
682 * 3. "RESETCONF AllowInvalid" sets it to default.
683 * 4. "SETCONF AllowInvalid" makes it NULL.
684 * 5. "SETCONF AllowInvalid=foo" clears it and sets it to "foo".
686 * Use_defaults Clear_first
688 * 1 0 undefined, don't use
689 * 0 1 "set to null first"
690 * 1 1 "set to defaults first"
691 * Return 0 on success, -1 on bad key, -2 on bad value.
693 * As an additional special case, if a LINELIST config option has
694 * no value and clear_first is 0, then warn and ignore it.
698 There are three call cases for config_assign() currently.
700 Case one: Torrc entry
701 options_init_from_torrc() calls config_assign(0, 0)
702 calls config_assign_line(0, 0).
703 if value is empty, calls config_reset(0) and returns.
704 calls config_assign_value(), appends.
707 options_trial_assign() calls config_assign(0, 1)
708 calls config_reset_line(0)
709 calls config_reset(0)
710 calls option_clear().
711 calls config_assign_line(0, 1).
712 if value is empty, returns.
713 calls config_assign_value(), appends.
715 Case three: resetconf
716 options_trial_assign() calls config_assign(1, 1)
717 calls config_reset_line(1)
718 calls config_reset(1)
719 calls option_clear().
720 calls config_assign_value(default)
721 calls config_assign_line(1, 1).
725 config_assign(const config_format_t
*fmt
, void *options
, config_line_t
*list
,
726 unsigned config_assign_flags
, char **msg
)
729 bitarray_t
*options_seen
;
730 const int n_options
= config_count_options(fmt
);
731 const unsigned clear_first
= config_assign_flags
& CAL_CLEAR_FIRST
;
732 const unsigned use_defaults
= config_assign_flags
& CAL_USE_DEFAULTS
;
734 CONFIG_CHECK(fmt
, options
);
736 /* pass 1: normalize keys */
737 for (p
= list
; p
; p
= p
->next
) {
738 const char *full
= config_expand_abbrev(fmt
, p
->key
, 0, 1);
739 if (strcmp(full
,p
->key
)) {
741 p
->key
= tor_strdup(full
);
745 /* pass 2: if we're reading from a resetting source, clear all
746 * mentioned config options, and maybe set to their defaults. */
748 for (p
= list
; p
; p
= p
->next
)
749 config_reset_line(fmt
, options
, p
->key
, use_defaults
);
752 options_seen
= bitarray_init_zero(n_options
);
753 /* pass 3: assign. */
756 if ((r
=config_assign_line(fmt
, options
, list
, config_assign_flags
,
757 options_seen
, msg
))) {
758 bitarray_free(options_seen
);
763 bitarray_free(options_seen
);
765 /** Now we're done assigning a group of options to the configuration.
766 * Subsequent group assignments should _replace_ linelists, not extend
768 config_mark_lists_fragile(fmt
, options
);
773 /** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent.
774 * Called from config_reset() and config_free(). */
776 config_clear(const config_format_t
*fmt
, void *options
,
777 const config_var_t
*var
)
779 void *lvalue
= STRUCT_VAR_P(options
, var
->var_offset
);
780 (void)fmt
; /* unused */
782 case CONFIG_TYPE_STRING
:
783 case CONFIG_TYPE_FILENAME
:
784 tor_free(*(char**)lvalue
);
786 case CONFIG_TYPE_DOUBLE
:
787 *(double*)lvalue
= 0.0;
789 case CONFIG_TYPE_ISOTIME
:
790 *(time_t*)lvalue
= 0;
792 case CONFIG_TYPE_INTERVAL
:
793 case CONFIG_TYPE_MSEC_INTERVAL
:
794 case CONFIG_TYPE_UINT
:
795 case CONFIG_TYPE_INT
:
796 case CONFIG_TYPE_PORT
:
797 case CONFIG_TYPE_BOOL
:
800 case CONFIG_TYPE_AUTOBOOL
:
803 case CONFIG_TYPE_MEMUNIT
:
804 *(uint64_t*)lvalue
= 0;
806 case CONFIG_TYPE_ROUTERSET
:
807 if (*(routerset_t
**)lvalue
) {
808 routerset_free(*(routerset_t
**)lvalue
);
809 *(routerset_t
**)lvalue
= NULL
;
812 case CONFIG_TYPE_CSV
:
813 if (*(smartlist_t
**)lvalue
) {
814 SMARTLIST_FOREACH(*(smartlist_t
**)lvalue
, char *, cp
, tor_free(cp
));
815 smartlist_free(*(smartlist_t
**)lvalue
);
816 *(smartlist_t
**)lvalue
= NULL
;
819 case CONFIG_TYPE_CSV_INTERVAL
:
820 if (*(smartlist_t
**)lvalue
) {
821 SMARTLIST_FOREACH(*(smartlist_t
**)lvalue
, int *, cp
, tor_free(cp
));
822 smartlist_free(*(smartlist_t
**)lvalue
);
823 *(smartlist_t
**)lvalue
= NULL
;
826 case CONFIG_TYPE_LINELIST
:
827 case CONFIG_TYPE_LINELIST_S
:
828 config_free_lines(*(config_line_t
**)lvalue
);
829 *(config_line_t
**)lvalue
= NULL
;
831 case CONFIG_TYPE_LINELIST_V
:
832 /* handled by linelist_s. */
834 case CONFIG_TYPE_OBSOLETE
:
839 /** Clear the option indexed by <b>var</b> in <b>options</b>. Then if
840 * <b>use_defaults</b>, set it to its default value.
841 * Called by config_init() and option_reset_line() and option_assign_line(). */
843 config_reset(const config_format_t
*fmt
, void *options
,
844 const config_var_t
*var
, int use_defaults
)
848 CONFIG_CHECK(fmt
, options
);
849 config_clear(fmt
, options
, var
); /* clear it first */
851 return; /* all done */
852 if (var
->initvalue
) {
853 c
= tor_malloc_zero(sizeof(config_line_t
));
854 c
->key
= tor_strdup(var
->name
);
855 c
->value
= tor_strdup(var
->initvalue
);
856 if (config_assign_value(fmt
, options
, c
, &msg
) < 0) {
857 log_warn(LD_BUG
, "Failed to assign default: %s", msg
);
858 tor_free(msg
); /* if this happens it's a bug */
860 config_free_lines(c
);
864 /** Release storage held by <b>options</b>. */
866 config_free(const config_format_t
*fmt
, void *options
)
875 for (i
=0; fmt
->vars
[i
].name
; ++i
)
876 config_clear(fmt
, options
, &(fmt
->vars
[i
]));
878 config_line_t
**linep
= STRUCT_VAR_P(options
, fmt
->extra
->var_offset
);
879 config_free_lines(*linep
);
885 /** Return true iff the option <b>name</b> has the same value in <b>o1</b>
886 * and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options.
889 config_is_same(const config_format_t
*fmt
,
890 const void *o1
, const void *o2
,
893 config_line_t
*c1
, *c2
;
895 CONFIG_CHECK(fmt
, o1
);
896 CONFIG_CHECK(fmt
, o2
);
898 c1
= config_get_assigned_option(fmt
, o1
, name
, 0);
899 c2
= config_get_assigned_option(fmt
, o2
, name
, 0);
900 r
= config_lines_eq(c1
, c2
);
901 config_free_lines(c1
);
902 config_free_lines(c2
);
906 /** Copy storage held by <b>old</b> into a new or_options_t and return it. */
908 config_dup(const config_format_t
*fmt
, const void *old
)
914 newopts
= config_new(fmt
);
915 for (i
=0; fmt
->vars
[i
].name
; ++i
) {
916 if (fmt
->vars
[i
].type
== CONFIG_TYPE_LINELIST_S
)
918 if (fmt
->vars
[i
].type
== CONFIG_TYPE_OBSOLETE
)
920 line
= config_get_assigned_option(fmt
, old
, fmt
->vars
[i
].name
, 0);
923 if (config_assign(fmt
, newopts
, line
, 0, &msg
) < 0) {
924 log_err(LD_BUG
, "config_get_assigned_option() generated "
925 "something we couldn't config_assign(): %s", msg
);
930 config_free_lines(line
);
934 /** Set all vars in the configuration object <b>options</b> to their default
937 config_init(const config_format_t
*fmt
, void *options
)
940 const config_var_t
*var
;
941 CONFIG_CHECK(fmt
, options
);
943 for (i
=0; fmt
->vars
[i
].name
; ++i
) {
946 continue; /* defaults to NULL or 0 */
947 config_reset(fmt
, options
, var
, 1);
951 /** Allocate and return a new string holding the written-out values of the vars
952 * in 'options'. If 'minimal', do not write out any default-valued vars.
953 * Else, if comment_defaults, write default values as comments.
956 config_dump(const config_format_t
*fmt
, const void *default_options
,
957 const void *options
, int minimal
,
958 int comment_defaults
)
960 smartlist_t
*elements
;
961 const void *defaults
= default_options
;
962 void *defaults_tmp
= NULL
;
963 config_line_t
*line
, *assigned
;
968 if (defaults
== NULL
) {
969 defaults
= defaults_tmp
= config_new(fmt
);
970 config_init(fmt
, defaults_tmp
);
973 /* XXX use a 1 here so we don't add a new log line while dumping */
974 if (default_options
== NULL
) {
975 if (fmt
->validate_fn(NULL
, defaults_tmp
, defaults_tmp
, 1, &msg
) < 0) {
976 log_err(LD_BUG
, "Failed to validate default config: %s", msg
);
982 elements
= smartlist_new();
983 for (i
=0; fmt
->vars
[i
].name
; ++i
) {
984 int comment_option
= 0;
985 if (fmt
->vars
[i
].type
== CONFIG_TYPE_OBSOLETE
||
986 fmt
->vars
[i
].type
== CONFIG_TYPE_LINELIST_S
)
988 /* Don't save 'hidden' control variables. */
989 if (!strcmpstart(fmt
->vars
[i
].name
, "__"))
991 if (minimal
&& config_is_same(fmt
, options
, defaults
, fmt
->vars
[i
].name
))
993 else if (comment_defaults
&&
994 config_is_same(fmt
, options
, defaults
, fmt
->vars
[i
].name
))
998 config_get_assigned_option(fmt
, options
, fmt
->vars
[i
].name
, 1);
1000 for (; line
; line
= line
->next
) {
1001 if (!strcmpstart(line
->key
, "__")) {
1002 /* This check detects "hidden" variables inside LINELIST_V structures.
1006 smartlist_add_asprintf(elements
, "%s%s %s\n",
1007 comment_option
? "# " : "",
1008 line
->key
, line
->value
);
1010 config_free_lines(assigned
);
1014 line
= *(config_line_t
**)STRUCT_VAR_P(options
, fmt
->extra
->var_offset
);
1015 for (; line
; line
= line
->next
) {
1016 smartlist_add_asprintf(elements
, "%s %s\n", line
->key
, line
->value
);
1020 result
= smartlist_join_strings(elements
, "", 0, NULL
);
1021 SMARTLIST_FOREACH(elements
, char *, cp
, tor_free(cp
));
1022 smartlist_free(elements
);
1024 config_free(fmt
, defaults_tmp
);
1028 /** Mapping from a unit name to a multiplier for converting that unit into a
1029 * base unit. Used by config_parse_unit. */
1030 struct unit_table_t
{
1031 const char *unit
; /**< The name of the unit */
1032 uint64_t multiplier
; /**< How many of the base unit appear in this unit */
1035 /** Table to map the names of memory units to the number of bytes they
1037 static struct unit_table_t memory_units
[] = {
1044 { "kbytes", 1<<10 },
1045 { "kilobyte", 1<<10 },
1046 { "kilobytes", 1<<10 },
1047 { "kilobits", 1<<7 },
1048 { "kilobit", 1<<7 },
1054 { "mbytes", 1<<20 },
1055 { "megabyte", 1<<20 },
1056 { "megabytes", 1<<20 },
1057 { "megabits", 1<<17 },
1058 { "megabit", 1<<17 },
1063 { "gbytes", 1<<30 },
1064 { "gigabyte", 1<<30 },
1065 { "gigabytes", 1<<30 },
1066 { "gigabits", 1<<27 },
1067 { "gigabit", 1<<27 },
1070 { "tb", U64_LITERAL(1)<<40 },
1071 { "tbyte", U64_LITERAL(1)<<40 },
1072 { "tbytes", U64_LITERAL(1)<<40 },
1073 { "terabyte", U64_LITERAL(1)<<40 },
1074 { "terabytes", U64_LITERAL(1)<<40 },
1075 { "terabits", U64_LITERAL(1)<<37 },
1076 { "terabit", U64_LITERAL(1)<<37 },
1077 { "tbits", U64_LITERAL(1)<<37 },
1078 { "tbit", U64_LITERAL(1)<<37 },
1082 /** Table to map the names of time units to the number of seconds they
1084 static struct unit_table_t time_units
[] = {
1092 { "day", 24*60*60 },
1093 { "days", 24*60*60 },
1094 { "week", 7*24*60*60 },
1095 { "weeks", 7*24*60*60 },
1096 { "month", 2629728, }, /* about 30.437 days */
1097 { "months", 2629728, },
1101 /** Table to map the names of time units to the number of milliseconds
1103 static struct unit_table_t time_msec_units
[] = {
1106 { "millisecond", 1 },
1107 { "milliseconds", 1 },
1109 { "seconds", 1000 },
1110 { "minute", 60*1000 },
1111 { "minutes", 60*1000 },
1112 { "hour", 60*60*1000 },
1113 { "hours", 60*60*1000 },
1114 { "day", 24*60*60*1000 },
1115 { "days", 24*60*60*1000 },
1116 { "week", 7*24*60*60*1000 },
1117 { "weeks", 7*24*60*60*1000 },
1121 /** Parse a string <b>val</b> containing a number, zero or more
1122 * spaces, and an optional unit string. If the unit appears in the
1123 * table <b>u</b>, then multiply the number by the unit multiplier.
1124 * On success, set *<b>ok</b> to 1 and return this product.
1125 * Otherwise, set *<b>ok</b> to 0.
1128 config_parse_units(const char *val
, struct unit_table_t
*u
, int *ok
)
1137 v
= tor_parse_uint64(val
, 10, 0, UINT64_MAX
, ok
, &cp
);
1138 if (!*ok
|| (cp
&& *cp
== '.')) {
1139 d
= tor_parse_double(val
, 0, (double)UINT64_MAX
, ok
, &cp
);
1147 v
= use_float
? DBL_TO_U64(d
) : v
;
1151 cp
= (char*) eat_whitespace(cp
);
1153 for ( ;u
->unit
;++u
) {
1154 if (!strcasecmp(u
->unit
, cp
)) {
1156 v
= (uint64_t)(u
->multiplier
* d
);
1163 log_warn(LD_CONFIG
, "Unknown unit '%s'.", cp
);
1173 /** Parse a string in the format "number unit", where unit is a unit of
1174 * information (byte, KB, M, etc). On success, set *<b>ok</b> to true
1175 * and return the number of bytes specified. Otherwise, set
1176 * *<b>ok</b> to false and return 0. */
1178 config_parse_memunit(const char *s
, int *ok
)
1180 uint64_t u
= config_parse_units(s
, memory_units
, ok
);
1184 /** Parse a string in the format "number unit", where unit is a unit of
1185 * time in milliseconds. On success, set *<b>ok</b> to true and return
1186 * the number of milliseconds in the provided interval. Otherwise, set
1187 * *<b>ok</b> to 0 and return -1. */
1189 config_parse_msec_interval(const char *s
, int *ok
)
1192 r
= config_parse_units(s
, time_msec_units
, ok
);
1194 log_warn(LD_CONFIG
, "Msec interval '%s' is too long", s
);
1201 /** Parse a string in the format "number unit", where unit is a unit of time.
1202 * On success, set *<b>ok</b> to true and return the number of seconds in
1203 * the provided interval. Otherwise, set *<b>ok</b> to 0 and return -1.
1206 config_parse_interval(const char *s
, int *ok
)
1209 r
= config_parse_units(s
, time_units
, ok
);
1211 log_warn(LD_CONFIG
, "Interval '%s' is too long", s
);