TOR: update to v0.2.5.12
[tomato.git] / release / src-rt-6.x.4708 / router / tor / src / or / confparse.c
blobc5400a6512bd2fa6e7bb0a1b56c787c8db921390
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-2013, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
7 #include "or.h"
8 #include "confparse.h"
9 #include "routerset.h"
11 static uint64_t config_parse_memunit(const char *s, int *ok);
12 static int config_parse_msec_interval(const char *s, int *ok);
13 static int config_parse_interval(const char *s, int *ok);
14 static void config_reset(const config_format_t *fmt, void *options,
15 const config_var_t *var, int use_defaults);
17 /** Allocate an empty configuration object of a given format type. */
18 void *
19 config_new(const config_format_t *fmt)
21 void *opts = tor_malloc_zero(fmt->size);
22 *(uint32_t*)STRUCT_VAR_P(opts, fmt->magic_offset) = fmt->magic;
23 CONFIG_CHECK(fmt, opts);
24 return opts;
28 * Functions to parse config options
31 /** If <b>option</b> is an official abbreviation for a longer option,
32 * return the longer option. Otherwise return <b>option</b>.
33 * If <b>command_line</b> is set, apply all abbreviations. Otherwise, only
34 * apply abbreviations that work for the config file and the command line.
35 * If <b>warn_obsolete</b> is set, warn about deprecated names. */
36 const char *
37 config_expand_abbrev(const config_format_t *fmt, const char *option,
38 int command_line, int warn_obsolete)
40 int i;
41 if (! fmt->abbrevs)
42 return option;
43 for (i=0; fmt->abbrevs[i].abbreviated; ++i) {
44 /* Abbreviations are case insensitive. */
45 if (!strcasecmp(option,fmt->abbrevs[i].abbreviated) &&
46 (command_line || !fmt->abbrevs[i].commandline_only)) {
47 if (warn_obsolete && fmt->abbrevs[i].warn) {
48 log_warn(LD_CONFIG,
49 "The configuration option '%s' is deprecated; "
50 "use '%s' instead.",
51 fmt->abbrevs[i].abbreviated,
52 fmt->abbrevs[i].full);
54 /* Keep going through the list in case we want to rewrite it more.
55 * (We could imagine recursing here, but I don't want to get the
56 * user into an infinite loop if we craft our list wrong.) */
57 option = fmt->abbrevs[i].full;
60 return option;
63 /** Helper: allocate a new configuration option mapping 'key' to 'val',
64 * append it to *<b>lst</b>. */
65 void
66 config_line_append(config_line_t **lst,
67 const char *key,
68 const char *val)
70 config_line_t *newline;
72 newline = tor_malloc_zero(sizeof(config_line_t));
73 newline->key = tor_strdup(key);
74 newline->value = tor_strdup(val);
75 newline->next = NULL;
76 while (*lst)
77 lst = &((*lst)->next);
79 (*lst) = newline;
82 /** Return the line in <b>lines</b> whose key is exactly <b>key</b>, or NULL
83 * if no such key exists. For handling commandline-only options only; other
84 * options should be looked up in the appropriate data structure. */
85 const config_line_t *
86 config_line_find(const config_line_t *lines,
87 const char *key)
89 const config_line_t *cl;
90 for (cl = lines; cl; cl = cl->next) {
91 if (!strcmp(cl->key, key))
92 return cl;
94 return NULL;
97 /** Helper: parse the config string and strdup into key/value
98 * strings. Set *result to the list, or NULL if parsing the string
99 * failed. Return 0 on success, -1 on failure. Warn and ignore any
100 * misformatted lines.
102 * If <b>extended</b> is set, then treat keys beginning with / and with + as
103 * indicating "clear" and "append" respectively. */
105 config_get_lines(const char *string, config_line_t **result, int extended)
107 config_line_t *list = NULL, **next;
108 char *k, *v;
109 const char *parse_err;
111 next = &list;
112 do {
113 k = v = NULL;
114 string = parse_config_line_from_str_verbose(string, &k, &v, &parse_err);
115 if (!string) {
116 log_warn(LD_CONFIG, "Error while parsing configuration: %s",
117 parse_err?parse_err:"<unknown>");
118 config_free_lines(list);
119 tor_free(k);
120 tor_free(v);
121 return -1;
123 if (k && v) {
124 unsigned command = CONFIG_LINE_NORMAL;
125 if (extended) {
126 if (k[0] == '+') {
127 char *k_new = tor_strdup(k+1);
128 tor_free(k);
129 k = k_new;
130 command = CONFIG_LINE_APPEND;
131 } else if (k[0] == '/') {
132 char *k_new = tor_strdup(k+1);
133 tor_free(k);
134 k = k_new;
135 tor_free(v);
136 v = tor_strdup("");
137 command = CONFIG_LINE_CLEAR;
140 /* This list can get long, so we keep a pointer to the end of it
141 * rather than using config_line_append over and over and getting
142 * n^2 performance. */
143 *next = tor_malloc_zero(sizeof(config_line_t));
144 (*next)->key = k;
145 (*next)->value = v;
146 (*next)->next = NULL;
147 (*next)->command = command;
148 next = &((*next)->next);
149 } else {
150 tor_free(k);
151 tor_free(v);
153 } while (*string);
155 *result = list;
156 return 0;
160 * Free all the configuration lines on the linked list <b>front</b>.
162 void
163 config_free_lines(config_line_t *front)
165 config_line_t *tmp;
167 while (front) {
168 tmp = front;
169 front = tmp->next;
171 tor_free(tmp->key);
172 tor_free(tmp->value);
173 tor_free(tmp);
177 /** As config_find_option, but return a non-const pointer. */
178 config_var_t *
179 config_find_option_mutable(config_format_t *fmt, const char *key)
181 int i;
182 size_t keylen = strlen(key);
183 if (!keylen)
184 return NULL; /* if they say "--" on the command line, it's not an option */
185 /* First, check for an exact (case-insensitive) match */
186 for (i=0; fmt->vars[i].name; ++i) {
187 if (!strcasecmp(key, fmt->vars[i].name)) {
188 return &fmt->vars[i];
191 /* If none, check for an abbreviated match */
192 for (i=0; fmt->vars[i].name; ++i) {
193 if (!strncasecmp(key, fmt->vars[i].name, keylen)) {
194 log_warn(LD_CONFIG, "The abbreviation '%s' is deprecated. "
195 "Please use '%s' instead",
196 key, fmt->vars[i].name);
197 return &fmt->vars[i];
200 /* Okay, unrecognized option */
201 return NULL;
204 /** If <b>key</b> is a configuration option, return the corresponding const
205 * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
206 * warn, and return the corresponding const config_var_t. Otherwise return
207 * NULL.
209 const config_var_t *
210 config_find_option(const config_format_t *fmt, const char *key)
212 return config_find_option_mutable((config_format_t*)fmt, key);
215 /** Return the number of option entries in <b>fmt</b>. */
216 static int
217 config_count_options(const config_format_t *fmt)
219 int i;
220 for (i=0; fmt->vars[i].name; ++i)
222 return i;
226 * Functions to assign config options.
229 /** <b>c</b>-\>key is known to be a real key. Update <b>options</b>
230 * with <b>c</b>-\>value and return 0, or return -1 if bad value.
232 * Called from config_assign_line() and option_reset().
234 static int
235 config_assign_value(const config_format_t *fmt, void *options,
236 config_line_t *c, char **msg)
238 int i, ok;
239 const config_var_t *var;
240 void *lvalue;
241 int *csv_int;
242 smartlist_t *csv_str;
244 CONFIG_CHECK(fmt, options);
246 var = config_find_option(fmt, c->key);
247 tor_assert(var);
249 lvalue = STRUCT_VAR_P(options, var->var_offset);
251 switch (var->type) {
253 case CONFIG_TYPE_PORT:
254 if (!strcasecmp(c->value, "auto")) {
255 *(int *)lvalue = CFG_AUTO_PORT;
256 break;
258 /* fall through */
259 case CONFIG_TYPE_INT:
260 case CONFIG_TYPE_UINT:
261 i = (int)tor_parse_long(c->value, 10,
262 var->type==CONFIG_TYPE_INT ? INT_MIN : 0,
263 var->type==CONFIG_TYPE_PORT ? 65535 : INT_MAX,
264 &ok, NULL);
265 if (!ok) {
266 tor_asprintf(msg,
267 "Int keyword '%s %s' is malformed or out of bounds.",
268 c->key, c->value);
269 return -1;
271 *(int *)lvalue = i;
272 break;
274 case CONFIG_TYPE_INTERVAL: {
275 i = config_parse_interval(c->value, &ok);
276 if (!ok) {
277 tor_asprintf(msg,
278 "Interval '%s %s' is malformed or out of bounds.",
279 c->key, c->value);
280 return -1;
282 *(int *)lvalue = i;
283 break;
286 case CONFIG_TYPE_MSEC_INTERVAL: {
287 i = config_parse_msec_interval(c->value, &ok);
288 if (!ok) {
289 tor_asprintf(msg,
290 "Msec interval '%s %s' is malformed or out of bounds.",
291 c->key, c->value);
292 return -1;
294 *(int *)lvalue = i;
295 break;
298 case CONFIG_TYPE_MEMUNIT: {
299 uint64_t u64 = config_parse_memunit(c->value, &ok);
300 if (!ok) {
301 tor_asprintf(msg,
302 "Value '%s %s' is malformed or out of bounds.",
303 c->key, c->value);
304 return -1;
306 *(uint64_t *)lvalue = u64;
307 break;
310 case CONFIG_TYPE_BOOL:
311 i = (int)tor_parse_long(c->value, 10, 0, 1, &ok, NULL);
312 if (!ok) {
313 tor_asprintf(msg,
314 "Boolean '%s %s' expects 0 or 1.",
315 c->key, c->value);
316 return -1;
318 *(int *)lvalue = i;
319 break;
321 case CONFIG_TYPE_AUTOBOOL:
322 if (!strcmp(c->value, "auto"))
323 *(int *)lvalue = -1;
324 else if (!strcmp(c->value, "0"))
325 *(int *)lvalue = 0;
326 else if (!strcmp(c->value, "1"))
327 *(int *)lvalue = 1;
328 else {
329 tor_asprintf(msg, "Boolean '%s %s' expects 0, 1, or 'auto'.",
330 c->key, c->value);
331 return -1;
333 break;
335 case CONFIG_TYPE_STRING:
336 case CONFIG_TYPE_FILENAME:
337 tor_free(*(char **)lvalue);
338 *(char **)lvalue = tor_strdup(c->value);
339 break;
341 case CONFIG_TYPE_DOUBLE:
342 *(double *)lvalue = atof(c->value);
343 break;
345 case CONFIG_TYPE_ISOTIME:
346 if (parse_iso_time(c->value, (time_t *)lvalue)) {
347 tor_asprintf(msg,
348 "Invalid time '%s' for keyword '%s'", c->value, c->key);
349 return -1;
351 break;
353 case CONFIG_TYPE_ROUTERSET:
354 if (*(routerset_t**)lvalue) {
355 routerset_free(*(routerset_t**)lvalue);
357 *(routerset_t**)lvalue = routerset_new();
358 if (routerset_parse(*(routerset_t**)lvalue, c->value, c->key)<0) {
359 tor_asprintf(msg, "Invalid exit list '%s' for option '%s'",
360 c->value, c->key);
361 return -1;
363 break;
365 case CONFIG_TYPE_CSV:
366 if (*(smartlist_t**)lvalue) {
367 SMARTLIST_FOREACH(*(smartlist_t**)lvalue, char *, cp, tor_free(cp));
368 smartlist_clear(*(smartlist_t**)lvalue);
369 } else {
370 *(smartlist_t**)lvalue = smartlist_new();
373 smartlist_split_string(*(smartlist_t**)lvalue, c->value, ",",
374 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
375 break;
377 case CONFIG_TYPE_CSV_INTERVAL:
378 if (*(smartlist_t**)lvalue) {
379 SMARTLIST_FOREACH(*(smartlist_t**)lvalue, int *, cp, tor_free(cp));
380 smartlist_clear(*(smartlist_t**)lvalue);
381 } else {
382 *(smartlist_t**)lvalue = smartlist_new();
384 csv_str = smartlist_new();
385 smartlist_split_string(csv_str, c->value, ",",
386 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
387 SMARTLIST_FOREACH_BEGIN(csv_str, char *, str)
389 i = config_parse_interval(str, &ok);
390 if (!ok) {
391 tor_asprintf(msg,
392 "Interval in '%s %s' is malformed or out of bounds.",
393 c->key, c->value);
394 SMARTLIST_FOREACH(csv_str, char *, cp, tor_free(cp));
395 smartlist_free(csv_str);
396 return -1;
398 csv_int = tor_malloc_zero(sizeof(int));
399 *csv_int = i;
400 smartlist_add(*(smartlist_t**)lvalue, csv_int);
402 SMARTLIST_FOREACH_END(str);
403 SMARTLIST_FOREACH(csv_str, char *, cp, tor_free(cp));
404 smartlist_free(csv_str);
405 break;
407 case CONFIG_TYPE_LINELIST:
408 case CONFIG_TYPE_LINELIST_S:
410 config_line_t *lastval = *(config_line_t**)lvalue;
411 if (lastval && lastval->fragile) {
412 if (c->command != CONFIG_LINE_APPEND) {
413 config_free_lines(lastval);
414 *(config_line_t**)lvalue = NULL;
415 } else {
416 lastval->fragile = 0;
420 config_line_append((config_line_t**)lvalue, c->key, c->value);
422 break;
423 case CONFIG_TYPE_OBSOLETE:
424 log_warn(LD_CONFIG, "Skipping obsolete configuration option '%s'", c->key);
425 break;
426 case CONFIG_TYPE_LINELIST_V:
427 tor_asprintf(msg,
428 "You may not provide a value for virtual option '%s'", c->key);
429 return -1;
430 default:
431 tor_assert(0);
432 break;
434 return 0;
437 /** Mark every linelist in <b>options</b> "fragile", so that fresh assignments
438 * to it will replace old ones. */
439 static void
440 config_mark_lists_fragile(const config_format_t *fmt, void *options)
442 int i;
443 tor_assert(fmt);
444 tor_assert(options);
446 for (i = 0; fmt->vars[i].name; ++i) {
447 const config_var_t *var = &fmt->vars[i];
448 config_line_t *list;
449 if (var->type != CONFIG_TYPE_LINELIST &&
450 var->type != CONFIG_TYPE_LINELIST_V)
451 continue;
453 list = *(config_line_t **)STRUCT_VAR_P(options, var->var_offset);
454 if (list)
455 list->fragile = 1;
459 /** If <b>c</b> is a syntactically valid configuration line, update
460 * <b>options</b> with its value and return 0. Otherwise return -1 for bad
461 * key, -2 for bad value.
463 * If <b>clear_first</b> is set, clear the value first. Then if
464 * <b>use_defaults</b> is set, set the value to the default.
466 * Called from config_assign().
468 static int
469 config_assign_line(const config_format_t *fmt, void *options,
470 config_line_t *c, int use_defaults,
471 int clear_first, bitarray_t *options_seen, char **msg)
473 const config_var_t *var;
475 CONFIG_CHECK(fmt, options);
477 var = config_find_option(fmt, c->key);
478 if (!var) {
479 if (fmt->extra) {
480 void *lvalue = STRUCT_VAR_P(options, fmt->extra->var_offset);
481 log_info(LD_CONFIG,
482 "Found unrecognized option '%s'; saving it.", c->key);
483 config_line_append((config_line_t**)lvalue, c->key, c->value);
484 return 0;
485 } else {
486 tor_asprintf(msg,
487 "Unknown option '%s'. Failing.", c->key);
488 return -1;
492 /* Put keyword into canonical case. */
493 if (strcmp(var->name, c->key)) {
494 tor_free(c->key);
495 c->key = tor_strdup(var->name);
498 if (!strlen(c->value)) {
499 /* reset or clear it, then return */
500 if (!clear_first) {
501 if ((var->type == CONFIG_TYPE_LINELIST ||
502 var->type == CONFIG_TYPE_LINELIST_S) &&
503 c->command != CONFIG_LINE_CLEAR) {
504 /* We got an empty linelist from the torrc or command line.
505 As a special case, call this an error. Warn and ignore. */
506 log_warn(LD_CONFIG,
507 "Linelist option '%s' has no value. Skipping.", c->key);
508 } else { /* not already cleared */
509 config_reset(fmt, options, var, use_defaults);
512 return 0;
513 } else if (c->command == CONFIG_LINE_CLEAR && !clear_first) {
514 config_reset(fmt, options, var, use_defaults);
517 if (options_seen && (var->type != CONFIG_TYPE_LINELIST &&
518 var->type != CONFIG_TYPE_LINELIST_S)) {
519 /* We're tracking which options we've seen, and this option is not
520 * supposed to occur more than once. */
521 int var_index = (int)(var - fmt->vars);
522 if (bitarray_is_set(options_seen, var_index)) {
523 log_warn(LD_CONFIG, "Option '%s' used more than once; all but the last "
524 "value will be ignored.", var->name);
526 bitarray_set(options_seen, var_index);
529 if (config_assign_value(fmt, options, c, msg) < 0)
530 return -2;
531 return 0;
534 /** Restore the option named <b>key</b> in options to its default value.
535 * Called from config_assign(). */
536 static void
537 config_reset_line(const config_format_t *fmt, void *options,
538 const char *key, int use_defaults)
540 const config_var_t *var;
542 CONFIG_CHECK(fmt, options);
544 var = config_find_option(fmt, key);
545 if (!var)
546 return; /* give error on next pass. */
548 config_reset(fmt, options, var, use_defaults);
551 /** Return true iff value needs to be quoted and escaped to be used in
552 * a configuration file. */
553 static int
554 config_value_needs_escape(const char *value)
556 if (*value == '\"')
557 return 1;
558 while (*value) {
559 switch (*value)
561 case '\r':
562 case '\n':
563 case '#':
564 /* Note: quotes and backspaces need special handling when we are using
565 * quotes, not otherwise, so they don't trigger escaping on their
566 * own. */
567 return 1;
568 default:
569 if (!TOR_ISPRINT(*value))
570 return 1;
572 ++value;
574 return 0;
577 /** Return a newly allocated deep copy of the lines in <b>inp</b>. */
578 config_line_t *
579 config_lines_dup(const config_line_t *inp)
581 config_line_t *result = NULL;
582 config_line_t **next_out = &result;
583 while (inp) {
584 *next_out = tor_malloc_zero(sizeof(config_line_t));
585 (*next_out)->key = tor_strdup(inp->key);
586 (*next_out)->value = tor_strdup(inp->value);
587 inp = inp->next;
588 next_out = &((*next_out)->next);
590 (*next_out) = NULL;
591 return result;
594 /** Return newly allocated line or lines corresponding to <b>key</b> in the
595 * configuration <b>options</b>. If <b>escape_val</b> is true and a
596 * value needs to be quoted before it's put in a config file, quote and
597 * escape that value. Return NULL if no such key exists. */
598 config_line_t *
599 config_get_assigned_option(const config_format_t *fmt, const void *options,
600 const char *key, int escape_val)
602 const config_var_t *var;
603 const void *value;
604 config_line_t *result;
605 smartlist_t *csv_str;
606 tor_assert(options && key);
608 CONFIG_CHECK(fmt, options);
610 var = config_find_option(fmt, key);
611 if (!var) {
612 log_warn(LD_CONFIG, "Unknown option '%s'. Failing.", key);
613 return NULL;
615 value = STRUCT_VAR_P(options, var->var_offset);
617 result = tor_malloc_zero(sizeof(config_line_t));
618 result->key = tor_strdup(var->name);
619 switch (var->type)
621 case CONFIG_TYPE_STRING:
622 case CONFIG_TYPE_FILENAME:
623 if (*(char**)value) {
624 result->value = tor_strdup(*(char**)value);
625 } else {
626 tor_free(result->key);
627 tor_free(result);
628 return NULL;
630 break;
631 case CONFIG_TYPE_ISOTIME:
632 if (*(time_t*)value) {
633 result->value = tor_malloc(ISO_TIME_LEN+1);
634 format_iso_time(result->value, *(time_t*)value);
635 } else {
636 tor_free(result->key);
637 tor_free(result);
639 escape_val = 0; /* Can't need escape. */
640 break;
641 case CONFIG_TYPE_PORT:
642 if (*(int*)value == CFG_AUTO_PORT) {
643 result->value = tor_strdup("auto");
644 escape_val = 0;
645 break;
647 /* fall through */
648 case CONFIG_TYPE_INTERVAL:
649 case CONFIG_TYPE_MSEC_INTERVAL:
650 case CONFIG_TYPE_UINT:
651 case CONFIG_TYPE_INT:
652 /* This means every or_options_t uint or bool element
653 * needs to be an int. Not, say, a uint16_t or char. */
654 tor_asprintf(&result->value, "%d", *(int*)value);
655 escape_val = 0; /* Can't need escape. */
656 break;
657 case CONFIG_TYPE_MEMUNIT:
658 tor_asprintf(&result->value, U64_FORMAT,
659 U64_PRINTF_ARG(*(uint64_t*)value));
660 escape_val = 0; /* Can't need escape. */
661 break;
662 case CONFIG_TYPE_DOUBLE:
663 tor_asprintf(&result->value, "%f", *(double*)value);
664 escape_val = 0; /* Can't need escape. */
665 break;
667 case CONFIG_TYPE_AUTOBOOL:
668 if (*(int*)value == -1) {
669 result->value = tor_strdup("auto");
670 escape_val = 0;
671 break;
673 /* fall through */
674 case CONFIG_TYPE_BOOL:
675 result->value = tor_strdup(*(int*)value ? "1" : "0");
676 escape_val = 0; /* Can't need escape. */
677 break;
678 case CONFIG_TYPE_ROUTERSET:
679 result->value = routerset_to_string(*(routerset_t**)value);
680 break;
681 case CONFIG_TYPE_CSV:
682 if (*(smartlist_t**)value)
683 result->value =
684 smartlist_join_strings(*(smartlist_t**)value, ",", 0, NULL);
685 else
686 result->value = tor_strdup("");
687 break;
688 case CONFIG_TYPE_CSV_INTERVAL:
689 if (*(smartlist_t**)value) {
690 csv_str = smartlist_new();
691 SMARTLIST_FOREACH_BEGIN(*(smartlist_t**)value, int *, i)
693 smartlist_add_asprintf(csv_str, "%d", *i);
695 SMARTLIST_FOREACH_END(i);
696 result->value = smartlist_join_strings(csv_str, ",", 0, NULL);
697 SMARTLIST_FOREACH(csv_str, char *, cp, tor_free(cp));
698 smartlist_free(csv_str);
699 } else
700 result->value = tor_strdup("");
701 break;
702 case CONFIG_TYPE_OBSOLETE:
703 log_fn(LOG_INFO, LD_CONFIG,
704 "You asked me for the value of an obsolete config option '%s'.",
705 key);
706 tor_free(result->key);
707 tor_free(result);
708 return NULL;
709 case CONFIG_TYPE_LINELIST_S:
710 log_warn(LD_CONFIG,
711 "Can't return context-sensitive '%s' on its own", key);
712 tor_free(result->key);
713 tor_free(result);
714 return NULL;
715 case CONFIG_TYPE_LINELIST:
716 case CONFIG_TYPE_LINELIST_V:
717 tor_free(result->key);
718 tor_free(result);
719 result = config_lines_dup(*(const config_line_t**)value);
720 break;
721 default:
722 tor_free(result->key);
723 tor_free(result);
724 log_warn(LD_BUG,"Unknown type %d for known key '%s'",
725 var->type, key);
726 return NULL;
729 if (escape_val) {
730 config_line_t *line;
731 for (line = result; line; line = line->next) {
732 if (line->value && config_value_needs_escape(line->value)) {
733 char *newval = esc_for_log(line->value);
734 tor_free(line->value);
735 line->value = newval;
740 return result;
742 /** Iterate through the linked list of requested options <b>list</b>.
743 * For each item, convert as appropriate and assign to <b>options</b>.
744 * If an item is unrecognized, set *msg and return -1 immediately,
745 * else return 0 for success.
747 * If <b>clear_first</b>, interpret config options as replacing (not
748 * extending) their previous values. If <b>clear_first</b> is set,
749 * then <b>use_defaults</b> to decide if you set to defaults after
750 * clearing, or make the value 0 or NULL.
752 * Here are the use cases:
753 * 1. A non-empty AllowInvalid line in your torrc. Appends to current
754 * if linelist, replaces current if csv.
755 * 2. An empty AllowInvalid line in your torrc. Should clear it.
756 * 3. "RESETCONF AllowInvalid" sets it to default.
757 * 4. "SETCONF AllowInvalid" makes it NULL.
758 * 5. "SETCONF AllowInvalid=foo" clears it and sets it to "foo".
760 * Use_defaults Clear_first
761 * 0 0 "append"
762 * 1 0 undefined, don't use
763 * 0 1 "set to null first"
764 * 1 1 "set to defaults first"
765 * Return 0 on success, -1 on bad key, -2 on bad value.
767 * As an additional special case, if a LINELIST config option has
768 * no value and clear_first is 0, then warn and ignore it.
772 There are three call cases for config_assign() currently.
774 Case one: Torrc entry
775 options_init_from_torrc() calls config_assign(0, 0)
776 calls config_assign_line(0, 0).
777 if value is empty, calls config_reset(0) and returns.
778 calls config_assign_value(), appends.
780 Case two: setconf
781 options_trial_assign() calls config_assign(0, 1)
782 calls config_reset_line(0)
783 calls config_reset(0)
784 calls option_clear().
785 calls config_assign_line(0, 1).
786 if value is empty, returns.
787 calls config_assign_value(), appends.
789 Case three: resetconf
790 options_trial_assign() calls config_assign(1, 1)
791 calls config_reset_line(1)
792 calls config_reset(1)
793 calls option_clear().
794 calls config_assign_value(default)
795 calls config_assign_line(1, 1).
796 returns.
799 config_assign(const config_format_t *fmt, void *options, config_line_t *list,
800 int use_defaults, int clear_first, char **msg)
802 config_line_t *p;
803 bitarray_t *options_seen;
804 const int n_options = config_count_options(fmt);
806 CONFIG_CHECK(fmt, options);
808 /* pass 1: normalize keys */
809 for (p = list; p; p = p->next) {
810 const char *full = config_expand_abbrev(fmt, p->key, 0, 1);
811 if (strcmp(full,p->key)) {
812 tor_free(p->key);
813 p->key = tor_strdup(full);
817 /* pass 2: if we're reading from a resetting source, clear all
818 * mentioned config options, and maybe set to their defaults. */
819 if (clear_first) {
820 for (p = list; p; p = p->next)
821 config_reset_line(fmt, options, p->key, use_defaults);
824 options_seen = bitarray_init_zero(n_options);
825 /* pass 3: assign. */
826 while (list) {
827 int r;
828 if ((r=config_assign_line(fmt, options, list, use_defaults,
829 clear_first, options_seen, msg))) {
830 bitarray_free(options_seen);
831 return r;
833 list = list->next;
835 bitarray_free(options_seen);
837 /** Now we're done assigning a group of options to the configuration.
838 * Subsequent group assignments should _replace_ linelists, not extend
839 * them. */
840 config_mark_lists_fragile(fmt, options);
842 return 0;
845 /** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent.
846 * Called from config_reset() and config_free(). */
847 static void
848 config_clear(const config_format_t *fmt, void *options,
849 const config_var_t *var)
851 void *lvalue = STRUCT_VAR_P(options, var->var_offset);
852 (void)fmt; /* unused */
853 switch (var->type) {
854 case CONFIG_TYPE_STRING:
855 case CONFIG_TYPE_FILENAME:
856 tor_free(*(char**)lvalue);
857 break;
858 case CONFIG_TYPE_DOUBLE:
859 *(double*)lvalue = 0.0;
860 break;
861 case CONFIG_TYPE_ISOTIME:
862 *(time_t*)lvalue = 0;
863 break;
864 case CONFIG_TYPE_INTERVAL:
865 case CONFIG_TYPE_MSEC_INTERVAL:
866 case CONFIG_TYPE_UINT:
867 case CONFIG_TYPE_INT:
868 case CONFIG_TYPE_PORT:
869 case CONFIG_TYPE_BOOL:
870 *(int*)lvalue = 0;
871 break;
872 case CONFIG_TYPE_AUTOBOOL:
873 *(int*)lvalue = -1;
874 break;
875 case CONFIG_TYPE_MEMUNIT:
876 *(uint64_t*)lvalue = 0;
877 break;
878 case CONFIG_TYPE_ROUTERSET:
879 if (*(routerset_t**)lvalue) {
880 routerset_free(*(routerset_t**)lvalue);
881 *(routerset_t**)lvalue = NULL;
883 break;
884 case CONFIG_TYPE_CSV:
885 if (*(smartlist_t**)lvalue) {
886 SMARTLIST_FOREACH(*(smartlist_t **)lvalue, char *, cp, tor_free(cp));
887 smartlist_free(*(smartlist_t **)lvalue);
888 *(smartlist_t **)lvalue = NULL;
890 break;
891 case CONFIG_TYPE_CSV_INTERVAL:
892 if (*(smartlist_t**)lvalue) {
893 SMARTLIST_FOREACH(*(smartlist_t **)lvalue, int *, cp, tor_free(cp));
894 smartlist_free(*(smartlist_t **)lvalue);
895 *(smartlist_t **)lvalue = NULL;
897 break;
898 case CONFIG_TYPE_LINELIST:
899 case CONFIG_TYPE_LINELIST_S:
900 config_free_lines(*(config_line_t **)lvalue);
901 *(config_line_t **)lvalue = NULL;
902 break;
903 case CONFIG_TYPE_LINELIST_V:
904 /* handled by linelist_s. */
905 break;
906 case CONFIG_TYPE_OBSOLETE:
907 break;
911 /** Clear the option indexed by <b>var</b> in <b>options</b>. Then if
912 * <b>use_defaults</b>, set it to its default value.
913 * Called by config_init() and option_reset_line() and option_assign_line(). */
914 static void
915 config_reset(const config_format_t *fmt, void *options,
916 const config_var_t *var, int use_defaults)
918 config_line_t *c;
919 char *msg = NULL;
920 CONFIG_CHECK(fmt, options);
921 config_clear(fmt, options, var); /* clear it first */
922 if (!use_defaults)
923 return; /* all done */
924 if (var->initvalue) {
925 c = tor_malloc_zero(sizeof(config_line_t));
926 c->key = tor_strdup(var->name);
927 c->value = tor_strdup(var->initvalue);
928 if (config_assign_value(fmt, options, c, &msg) < 0) {
929 log_warn(LD_BUG, "Failed to assign default: %s", msg);
930 tor_free(msg); /* if this happens it's a bug */
932 config_free_lines(c);
936 /** Release storage held by <b>options</b>. */
937 void
938 config_free(const config_format_t *fmt, void *options)
940 int i;
942 if (!options)
943 return;
945 tor_assert(fmt);
947 for (i=0; fmt->vars[i].name; ++i)
948 config_clear(fmt, options, &(fmt->vars[i]));
949 if (fmt->extra) {
950 config_line_t **linep = STRUCT_VAR_P(options, fmt->extra->var_offset);
951 config_free_lines(*linep);
952 *linep = NULL;
954 tor_free(options);
957 /** Return true iff a and b contain identical keys and values in identical
958 * order. */
960 config_lines_eq(config_line_t *a, config_line_t *b)
962 while (a && b) {
963 if (strcasecmp(a->key, b->key) || strcmp(a->value, b->value))
964 return 0;
965 a = a->next;
966 b = b->next;
968 if (a || b)
969 return 0;
970 return 1;
973 /** Return the number of lines in <b>a</b> whose key is <b>key</b>. */
975 config_count_key(const config_line_t *a, const char *key)
977 int n = 0;
978 while (a) {
979 if (!strcasecmp(a->key, key)) {
980 ++n;
982 a = a->next;
984 return n;
987 /** Return true iff the option <b>name</b> has the same value in <b>o1</b>
988 * and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options.
991 config_is_same(const config_format_t *fmt,
992 const void *o1, const void *o2,
993 const char *name)
995 config_line_t *c1, *c2;
996 int r = 1;
997 CONFIG_CHECK(fmt, o1);
998 CONFIG_CHECK(fmt, o2);
1000 c1 = config_get_assigned_option(fmt, o1, name, 0);
1001 c2 = config_get_assigned_option(fmt, o2, name, 0);
1002 r = config_lines_eq(c1, c2);
1003 config_free_lines(c1);
1004 config_free_lines(c2);
1005 return r;
1008 /** Copy storage held by <b>old</b> into a new or_options_t and return it. */
1009 void *
1010 config_dup(const config_format_t *fmt, const void *old)
1012 void *newopts;
1013 int i;
1014 config_line_t *line;
1016 newopts = config_new(fmt);
1017 for (i=0; fmt->vars[i].name; ++i) {
1018 if (fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
1019 continue;
1020 if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE)
1021 continue;
1022 line = config_get_assigned_option(fmt, old, fmt->vars[i].name, 0);
1023 if (line) {
1024 char *msg = NULL;
1025 if (config_assign(fmt, newopts, line, 0, 0, &msg) < 0) {
1026 log_err(LD_BUG, "config_get_assigned_option() generated "
1027 "something we couldn't config_assign(): %s", msg);
1028 tor_free(msg);
1029 tor_assert(0);
1032 config_free_lines(line);
1034 return newopts;
1036 /** Set all vars in the configuration object <b>options</b> to their default
1037 * values. */
1038 void
1039 config_init(const config_format_t *fmt, void *options)
1041 int i;
1042 const config_var_t *var;
1043 CONFIG_CHECK(fmt, options);
1045 for (i=0; fmt->vars[i].name; ++i) {
1046 var = &fmt->vars[i];
1047 if (!var->initvalue)
1048 continue; /* defaults to NULL or 0 */
1049 config_reset(fmt, options, var, 1);
1053 /** Allocate and return a new string holding the written-out values of the vars
1054 * in 'options'. If 'minimal', do not write out any default-valued vars.
1055 * Else, if comment_defaults, write default values as comments.
1057 char *
1058 config_dump(const config_format_t *fmt, const void *default_options,
1059 const void *options, int minimal,
1060 int comment_defaults)
1062 smartlist_t *elements;
1063 const void *defaults = default_options;
1064 void *defaults_tmp = NULL;
1065 config_line_t *line, *assigned;
1066 char *result;
1067 int i;
1068 char *msg = NULL;
1070 if (defaults == NULL) {
1071 defaults = defaults_tmp = config_new(fmt);
1072 config_init(fmt, defaults_tmp);
1075 /* XXX use a 1 here so we don't add a new log line while dumping */
1076 if (default_options == NULL) {
1077 if (fmt->validate_fn(NULL, defaults_tmp, defaults_tmp, 1, &msg) < 0) {
1078 log_err(LD_BUG, "Failed to validate default config: %s", msg);
1079 tor_free(msg);
1080 tor_assert(0);
1084 elements = smartlist_new();
1085 for (i=0; fmt->vars[i].name; ++i) {
1086 int comment_option = 0;
1087 if (fmt->vars[i].type == CONFIG_TYPE_OBSOLETE ||
1088 fmt->vars[i].type == CONFIG_TYPE_LINELIST_S)
1089 continue;
1090 /* Don't save 'hidden' control variables. */
1091 if (!strcmpstart(fmt->vars[i].name, "__"))
1092 continue;
1093 if (minimal && config_is_same(fmt, options, defaults, fmt->vars[i].name))
1094 continue;
1095 else if (comment_defaults &&
1096 config_is_same(fmt, options, defaults, fmt->vars[i].name))
1097 comment_option = 1;
1099 line = assigned =
1100 config_get_assigned_option(fmt, options, fmt->vars[i].name, 1);
1102 for (; line; line = line->next) {
1103 smartlist_add_asprintf(elements, "%s%s %s\n",
1104 comment_option ? "# " : "",
1105 line->key, line->value);
1107 config_free_lines(assigned);
1110 if (fmt->extra) {
1111 line = *(config_line_t**)STRUCT_VAR_P(options, fmt->extra->var_offset);
1112 for (; line; line = line->next) {
1113 smartlist_add_asprintf(elements, "%s %s\n", line->key, line->value);
1117 result = smartlist_join_strings(elements, "", 0, NULL);
1118 SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
1119 smartlist_free(elements);
1120 if (defaults_tmp)
1121 config_free(fmt, defaults_tmp);
1122 return result;
1125 /** Mapping from a unit name to a multiplier for converting that unit into a
1126 * base unit. Used by config_parse_unit. */
1127 struct unit_table_t {
1128 const char *unit; /**< The name of the unit */
1129 uint64_t multiplier; /**< How many of the base unit appear in this unit */
1132 /** Table to map the names of memory units to the number of bytes they
1133 * contain. */
1134 static struct unit_table_t memory_units[] = {
1135 { "", 1 },
1136 { "b", 1<< 0 },
1137 { "byte", 1<< 0 },
1138 { "bytes", 1<< 0 },
1139 { "kb", 1<<10 },
1140 { "kbyte", 1<<10 },
1141 { "kbytes", 1<<10 },
1142 { "kilobyte", 1<<10 },
1143 { "kilobytes", 1<<10 },
1144 { "kilobits", 1<<7 },
1145 { "kilobit", 1<<7 },
1146 { "kbits", 1<<7 },
1147 { "kbit", 1<<7 },
1148 { "m", 1<<20 },
1149 { "mb", 1<<20 },
1150 { "mbyte", 1<<20 },
1151 { "mbytes", 1<<20 },
1152 { "megabyte", 1<<20 },
1153 { "megabytes", 1<<20 },
1154 { "megabits", 1<<17 },
1155 { "megabit", 1<<17 },
1156 { "mbits", 1<<17 },
1157 { "mbit", 1<<17 },
1158 { "gb", 1<<30 },
1159 { "gbyte", 1<<30 },
1160 { "gbytes", 1<<30 },
1161 { "gigabyte", 1<<30 },
1162 { "gigabytes", 1<<30 },
1163 { "gigabits", 1<<27 },
1164 { "gigabit", 1<<27 },
1165 { "gbits", 1<<27 },
1166 { "gbit", 1<<27 },
1167 { "tb", U64_LITERAL(1)<<40 },
1168 { "terabyte", U64_LITERAL(1)<<40 },
1169 { "terabytes", U64_LITERAL(1)<<40 },
1170 { "terabits", U64_LITERAL(1)<<37 },
1171 { "terabit", U64_LITERAL(1)<<37 },
1172 { "tbits", U64_LITERAL(1)<<37 },
1173 { "tbit", U64_LITERAL(1)<<37 },
1174 { NULL, 0 },
1177 /** Table to map the names of time units to the number of seconds they
1178 * contain. */
1179 static struct unit_table_t time_units[] = {
1180 { "", 1 },
1181 { "second", 1 },
1182 { "seconds", 1 },
1183 { "minute", 60 },
1184 { "minutes", 60 },
1185 { "hour", 60*60 },
1186 { "hours", 60*60 },
1187 { "day", 24*60*60 },
1188 { "days", 24*60*60 },
1189 { "week", 7*24*60*60 },
1190 { "weeks", 7*24*60*60 },
1191 { "month", 2629728, }, /* about 30.437 days */
1192 { "months", 2629728, },
1193 { NULL, 0 },
1196 /** Table to map the names of time units to the number of milliseconds
1197 * they contain. */
1198 static struct unit_table_t time_msec_units[] = {
1199 { "", 1 },
1200 { "msec", 1 },
1201 { "millisecond", 1 },
1202 { "milliseconds", 1 },
1203 { "second", 1000 },
1204 { "seconds", 1000 },
1205 { "minute", 60*1000 },
1206 { "minutes", 60*1000 },
1207 { "hour", 60*60*1000 },
1208 { "hours", 60*60*1000 },
1209 { "day", 24*60*60*1000 },
1210 { "days", 24*60*60*1000 },
1211 { "week", 7*24*60*60*1000 },
1212 { "weeks", 7*24*60*60*1000 },
1213 { NULL, 0 },
1216 /** Parse a string <b>val</b> containing a number, zero or more
1217 * spaces, and an optional unit string. If the unit appears in the
1218 * table <b>u</b>, then multiply the number by the unit multiplier.
1219 * On success, set *<b>ok</b> to 1 and return this product.
1220 * Otherwise, set *<b>ok</b> to 0.
1222 static uint64_t
1223 config_parse_units(const char *val, struct unit_table_t *u, int *ok)
1225 uint64_t v = 0;
1226 double d = 0;
1227 int use_float = 0;
1228 char *cp;
1230 tor_assert(ok);
1232 v = tor_parse_uint64(val, 10, 0, UINT64_MAX, ok, &cp);
1233 if (!*ok || (cp && *cp == '.')) {
1234 d = tor_parse_double(val, 0, UINT64_MAX, ok, &cp);
1235 if (!*ok)
1236 goto done;
1237 use_float = 1;
1240 if (!cp) {
1241 *ok = 1;
1242 v = use_float ? DBL_TO_U64(d) : v;
1243 goto done;
1246 cp = (char*) eat_whitespace(cp);
1248 for ( ;u->unit;++u) {
1249 if (!strcasecmp(u->unit, cp)) {
1250 if (use_float)
1251 v = u->multiplier * d;
1252 else
1253 v *= u->multiplier;
1254 *ok = 1;
1255 goto done;
1258 log_warn(LD_CONFIG, "Unknown unit '%s'.", cp);
1259 *ok = 0;
1260 done:
1262 if (*ok)
1263 return v;
1264 else
1265 return 0;
1268 /** Parse a string in the format "number unit", where unit is a unit of
1269 * information (byte, KB, M, etc). On success, set *<b>ok</b> to true
1270 * and return the number of bytes specified. Otherwise, set
1271 * *<b>ok</b> to false and return 0. */
1272 static uint64_t
1273 config_parse_memunit(const char *s, int *ok)
1275 uint64_t u = config_parse_units(s, memory_units, ok);
1276 return u;
1279 /** Parse a string in the format "number unit", where unit is a unit of
1280 * time in milliseconds. On success, set *<b>ok</b> to true and return
1281 * the number of milliseconds in the provided interval. Otherwise, set
1282 * *<b>ok</b> to 0 and return -1. */
1283 static int
1284 config_parse_msec_interval(const char *s, int *ok)
1286 uint64_t r;
1287 r = config_parse_units(s, time_msec_units, ok);
1288 if (!ok)
1289 return -1;
1290 if (r > INT_MAX) {
1291 log_warn(LD_CONFIG, "Msec interval '%s' is too long", s);
1292 *ok = 0;
1293 return -1;
1295 return (int)r;
1298 /** Parse a string in the format "number unit", where unit is a unit of time.
1299 * On success, set *<b>ok</b> to true and return the number of seconds in
1300 * the provided interval. Otherwise, set *<b>ok</b> to 0 and return -1.
1302 static int
1303 config_parse_interval(const char *s, int *ok)
1305 uint64_t r;
1306 r = config_parse_units(s, time_units, ok);
1307 if (!ok)
1308 return -1;
1309 if (r > INT_MAX) {
1310 log_warn(LD_CONFIG, "Interval '%s' is too long", s);
1311 *ok = 0;
1312 return -1;
1314 return (int)r;