|
@@ -0,0 +1,727 @@
|
|
|
+
|
|
|
+ * Copyright (c) 2001-2004, Roger Dingledine.
|
|
|
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
|
|
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ * @file type_defs.c
|
|
|
+ * @brief Definitions for various low-level configuration types.
|
|
|
+ *
|
|
|
+ * This module creates a number of var_type_def_t objects, to be used by
|
|
|
+ * typedvar.c in manipulating variables.
|
|
|
+ *
|
|
|
+ * The types here are common types that can be implemented with Tor's
|
|
|
+ * low-level functionality. To define new types, see var_type_def_st.h.
|
|
|
+ **/
|
|
|
+
|
|
|
+#include "orconfig.h"
|
|
|
+#include "lib/conf/conftypes.h"
|
|
|
+#include "lib/confmgt/typedvar.h"
|
|
|
+#include "lib/confmgt/type_defs.h"
|
|
|
+#include "lib/confmgt/unitparse.h"
|
|
|
+
|
|
|
+#include "lib/cc/compat_compiler.h"
|
|
|
+#include "lib/conf/conftypes.h"
|
|
|
+#include "lib/container/smartlist.h"
|
|
|
+#include "lib/encoding/confline.h"
|
|
|
+#include "lib/encoding/time_fmt.h"
|
|
|
+#include "lib/log/escape.h"
|
|
|
+#include "lib/log/log.h"
|
|
|
+#include "lib/log/util_bug.h"
|
|
|
+#include "lib/malloc/malloc.h"
|
|
|
+#include "lib/string/parse_int.h"
|
|
|
+#include "lib/string/printf.h"
|
|
|
+
|
|
|
+#include "lib/confmgt/var_type_def_st.h"
|
|
|
+
|
|
|
+#include <stddef.h>
|
|
|
+#include <string.h>
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+static int
|
|
|
+string_parse(void *target, const char *value, char **errmsg,
|
|
|
+ const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ (void)errmsg;
|
|
|
+ char **p = (char**)target;
|
|
|
+ *p = tor_strdup(value);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static char *
|
|
|
+string_encode(const void *value, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ const char **p = (const char**)value;
|
|
|
+ return *p ? tor_strdup(*p) : NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+string_clear(void *value, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ char **p = (char**)value;
|
|
|
+ tor_free(*p);
|
|
|
+}
|
|
|
+
|
|
|
+static const var_type_fns_t string_fns = {
|
|
|
+ .parse = string_parse,
|
|
|
+ .encode = string_encode,
|
|
|
+ .clear = string_clear,
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+typedef struct int_type_params_t {
|
|
|
+ int minval;
|
|
|
+ int maxval;
|
|
|
+} int_parse_params_t;
|
|
|
+
|
|
|
+static const int_parse_params_t INT_PARSE_UNRESTRICTED = {
|
|
|
+ .minval = INT_MIN,
|
|
|
+ .maxval = INT_MAX,
|
|
|
+};
|
|
|
+
|
|
|
+static const int_parse_params_t INT_PARSE_POSINT = {
|
|
|
+ .minval = 0,
|
|
|
+ .maxval = INT_MAX,
|
|
|
+};
|
|
|
+
|
|
|
+static int
|
|
|
+int_parse(void *target, const char *value, char **errmsg, const void *params)
|
|
|
+{
|
|
|
+ const int_parse_params_t *pp;
|
|
|
+ if (params) {
|
|
|
+ pp = params;
|
|
|
+ } else {
|
|
|
+ pp = &INT_PARSE_UNRESTRICTED;
|
|
|
+ }
|
|
|
+ int *p = target;
|
|
|
+ int ok=0;
|
|
|
+ *p = (int)tor_parse_long(value, 10, pp->minval, pp->maxval, &ok, NULL);
|
|
|
+ if (!ok) {
|
|
|
+ tor_asprintf(errmsg, "Integer %s is malformed or out of bounds.",
|
|
|
+ value);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static char *
|
|
|
+int_encode(const void *value, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ int v = *(int*)value;
|
|
|
+ char *result;
|
|
|
+ tor_asprintf(&result, "%d", v);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+int_clear(void *value, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ *(int*)value = 0;
|
|
|
+}
|
|
|
+
|
|
|
+static bool
|
|
|
+int_ok(const void *value, const void *params)
|
|
|
+{
|
|
|
+ const int_parse_params_t *pp = params;
|
|
|
+ if (pp) {
|
|
|
+ int v = *(int*)value;
|
|
|
+ return pp->minval <= v && v <= pp->maxval;
|
|
|
+ } else {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static const var_type_fns_t int_fns = {
|
|
|
+ .parse = int_parse,
|
|
|
+ .encode = int_encode,
|
|
|
+ .clear = int_clear,
|
|
|
+ .ok = int_ok,
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+static int
|
|
|
+uint64_parse(void *target, const char *value, char **errmsg,
|
|
|
+ const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ (void)errmsg;
|
|
|
+ uint64_t *p = target;
|
|
|
+ int ok=0;
|
|
|
+ *p = tor_parse_uint64(value, 10, 0, UINT64_MAX, &ok, NULL);
|
|
|
+ if (!ok) {
|
|
|
+ tor_asprintf(errmsg, "Integer %s is malformed or out of bounds.",
|
|
|
+ value);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static char *
|
|
|
+uint64_encode(const void *value, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ uint64_t v = *(uint64_t*)value;
|
|
|
+ char *result;
|
|
|
+ tor_asprintf(&result, "%"PRIu64, v);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+uint64_clear(void *value, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ *(uint64_t*)value = 0;
|
|
|
+}
|
|
|
+
|
|
|
+static const var_type_fns_t uint64_fns = {
|
|
|
+ .parse = uint64_parse,
|
|
|
+ .encode = uint64_encode,
|
|
|
+ .clear = uint64_clear,
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+static int
|
|
|
+units_parse_u64(void *target, const char *value, char **errmsg,
|
|
|
+ const void *params)
|
|
|
+{
|
|
|
+ const unit_table_t *table = params;
|
|
|
+ tor_assert(table);
|
|
|
+ uint64_t *v = (uint64_t*)target;
|
|
|
+ int ok=1;
|
|
|
+ *v = config_parse_units(value, table, &ok);
|
|
|
+ if (!ok) {
|
|
|
+ *errmsg = tor_strdup("Provided value is malformed or out of bounds.");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+units_parse_int(void *target, const char *value, char **errmsg,
|
|
|
+ const void *params)
|
|
|
+{
|
|
|
+ const unit_table_t *table = params;
|
|
|
+ tor_assert(table);
|
|
|
+ int *v = (int*)target;
|
|
|
+ int ok=1;
|
|
|
+ uint64_t u64 = config_parse_units(value, table, &ok);
|
|
|
+ if (!ok) {
|
|
|
+ *errmsg = tor_strdup("Provided value is malformed or out of bounds.");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if (u64 > INT_MAX) {
|
|
|
+ tor_asprintf(errmsg, "Provided value %s is too large", value);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ *v = (int) u64;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static bool
|
|
|
+units_ok_int(const void *value, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ int v = *(int*)value;
|
|
|
+ return v >= 0;
|
|
|
+}
|
|
|
+
|
|
|
+static const var_type_fns_t memunit_fns = {
|
|
|
+ .parse = units_parse_u64,
|
|
|
+ .encode = uint64_encode,
|
|
|
+ .clear = uint64_clear,
|
|
|
+};
|
|
|
+
|
|
|
+static const var_type_fns_t interval_fns = {
|
|
|
+ .parse = units_parse_int,
|
|
|
+ .encode = int_encode,
|
|
|
+ .clear = int_clear,
|
|
|
+ .ok = units_ok_int
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+static int
|
|
|
+double_parse(void *target, const char *value, char **errmsg,
|
|
|
+ const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ (void)errmsg;
|
|
|
+ double *v = (double*)target;
|
|
|
+
|
|
|
+ *v = atof(value);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static char *
|
|
|
+double_encode(const void *value, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ double v = *(double*)value;
|
|
|
+ char *result;
|
|
|
+ tor_asprintf(&result, "%f", v);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+double_clear(void *value, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ double *v = (double *)value;
|
|
|
+ *v = 0.0;
|
|
|
+}
|
|
|
+
|
|
|
+static const var_type_fns_t double_fns = {
|
|
|
+ .parse = double_parse,
|
|
|
+ .encode = double_encode,
|
|
|
+ .clear = double_clear,
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+typedef struct enumeration_table_t {
|
|
|
+ const char *name;
|
|
|
+ int value;
|
|
|
+} enumeration_table_t;
|
|
|
+
|
|
|
+static int
|
|
|
+enum_parse(void *target, const char *value, char **errmsg,
|
|
|
+ const void *params)
|
|
|
+{
|
|
|
+ const enumeration_table_t *table = params;
|
|
|
+ int *p = (int *)target;
|
|
|
+ for (; table->name; ++table) {
|
|
|
+ if (!strcasecmp(value, table->name)) {
|
|
|
+ *p = table->value;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ tor_asprintf(errmsg, "Unrecognized value %s.", value);
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
+static char *
|
|
|
+enum_encode(const void *value, const void *params)
|
|
|
+{
|
|
|
+ int v = *(const int*)value;
|
|
|
+ const enumeration_table_t *table = params;
|
|
|
+ for (; table->name; ++table) {
|
|
|
+ if (v == table->value)
|
|
|
+ return tor_strdup(table->name);
|
|
|
+ }
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+enum_clear(void *value, const void *params)
|
|
|
+{
|
|
|
+ int *p = (int*)value;
|
|
|
+ const enumeration_table_t *table = params;
|
|
|
+ tor_assert(table->name);
|
|
|
+ *p = table->value;
|
|
|
+}
|
|
|
+
|
|
|
+static bool
|
|
|
+enum_ok(const void *value, const void *params)
|
|
|
+{
|
|
|
+ int v = *(const int*)value;
|
|
|
+ const enumeration_table_t *table = params;
|
|
|
+ for (; table->name; ++table) {
|
|
|
+ if (v == table->value)
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+static const enumeration_table_t enum_table_bool[] = {
|
|
|
+ { "0", 0 },
|
|
|
+ { "1", 1 },
|
|
|
+ { NULL, 0 },
|
|
|
+};
|
|
|
+
|
|
|
+static const enumeration_table_t enum_table_autobool[] = {
|
|
|
+ { "0", 0 },
|
|
|
+ { "1", 1 },
|
|
|
+ { "auto", -1 },
|
|
|
+ { NULL, 0 },
|
|
|
+};
|
|
|
+
|
|
|
+static const var_type_fns_t enum_fns = {
|
|
|
+ .parse = enum_parse,
|
|
|
+ .encode = enum_encode,
|
|
|
+ .clear = enum_clear,
|
|
|
+ .ok = enum_ok,
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+static int
|
|
|
+time_parse(void *target, const char *value, char **errmsg,
|
|
|
+ const void *params)
|
|
|
+{
|
|
|
+ (void) params;
|
|
|
+ time_t *p = target;
|
|
|
+ if (parse_iso_time(value, p) < 0) {
|
|
|
+ tor_asprintf(errmsg, "Invalid time %s", escaped(value));
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static char *
|
|
|
+time_encode(const void *value, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ time_t v = *(const time_t *)value;
|
|
|
+ char *result = tor_malloc(ISO_TIME_LEN+1);
|
|
|
+ format_iso_time(result, v);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+time_clear(void *value, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ time_t *t = value;
|
|
|
+ *t = 0;
|
|
|
+}
|
|
|
+
|
|
|
+static const var_type_fns_t time_fns = {
|
|
|
+ .parse = time_parse,
|
|
|
+ .encode = time_encode,
|
|
|
+ .clear = time_clear,
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+static int
|
|
|
+csv_parse(void *target, const char *value, char **errmsg,
|
|
|
+ const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ (void)errmsg;
|
|
|
+ smartlist_t **sl = (smartlist_t**)target;
|
|
|
+ *sl = smartlist_new();
|
|
|
+ smartlist_split_string(*sl, value, ",",
|
|
|
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static char *
|
|
|
+csv_encode(const void *value, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ const smartlist_t *sl = *(const smartlist_t **)value;
|
|
|
+ if (! sl)
|
|
|
+ return tor_strdup("");
|
|
|
+
|
|
|
+ return smartlist_join_strings(*(smartlist_t**)value, ",", 0, NULL);
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+csv_clear(void *value, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ smartlist_t **sl = (smartlist_t**)value;
|
|
|
+ if (!*sl)
|
|
|
+ return;
|
|
|
+ SMARTLIST_FOREACH(*sl, char *, cp, tor_free(cp));
|
|
|
+ smartlist_free(*sl);
|
|
|
+}
|
|
|
+
|
|
|
+static const var_type_fns_t csv_fns = {
|
|
|
+ .parse = csv_parse,
|
|
|
+ .encode = csv_encode,
|
|
|
+ .clear = csv_clear,
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+static int
|
|
|
+legacy_csv_interval_parse(void *target, const char *value, char **errmsg,
|
|
|
+ const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+
|
|
|
+ * download schedules use exponential backoff, only the first part
|
|
|
+ * matters. */
|
|
|
+ const char *comma = strchr(value, ',');
|
|
|
+ const char *val = value;
|
|
|
+ char *tmp = NULL;
|
|
|
+ if (comma) {
|
|
|
+ tmp = tor_strndup(val, comma - val);
|
|
|
+ val = tmp;
|
|
|
+ }
|
|
|
+
|
|
|
+ int rv = units_parse_int(target, val, errmsg, &time_units);
|
|
|
+ tor_free(tmp);
|
|
|
+ return rv;
|
|
|
+}
|
|
|
+
|
|
|
+static const var_type_fns_t legacy_csv_interval_fns = {
|
|
|
+ .parse = legacy_csv_interval_parse,
|
|
|
+ .encode = int_encode,
|
|
|
+ .clear = int_clear,
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+static int
|
|
|
+linelist_kv_parse(void *target, const struct config_line_t *line,
|
|
|
+ char **errmsg, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ (void)errmsg;
|
|
|
+ config_line_t **lines = target;
|
|
|
+
|
|
|
+ if (*lines && (*lines)->fragile) {
|
|
|
+ if (line->command == CONFIG_LINE_APPEND) {
|
|
|
+ (*lines)->fragile = 0;
|
|
|
+ } else {
|
|
|
+ config_free_lines(*lines);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ config_line_append(lines, line->key, line->value);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+linelist_kv_virt_noparse(void *target, const struct config_line_t *line,
|
|
|
+ char **errmsg, const void *params)
|
|
|
+{
|
|
|
+ (void)target;
|
|
|
+ (void)line;
|
|
|
+ (void)params;
|
|
|
+ *errmsg = tor_strdup("Cannot assign directly to virtual option.");
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+
|
|
|
+static struct config_line_t *
|
|
|
+linelist_kv_encode(const char *key, const void *value,
|
|
|
+ const void *params)
|
|
|
+{
|
|
|
+ (void)key;
|
|
|
+ (void)params;
|
|
|
+ config_line_t *lines = *(config_line_t **)value;
|
|
|
+ return config_lines_dup(lines);
|
|
|
+}
|
|
|
+
|
|
|
+static struct config_line_t *
|
|
|
+linelist_s_kv_encode(const char *key, const void *value,
|
|
|
+ const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ config_line_t *lines = *(config_line_t **)value;
|
|
|
+ return config_lines_dup_and_filter(lines, key);
|
|
|
+}
|
|
|
+
|
|
|
+static void
|
|
|
+linelist_clear(void *target, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ config_line_t **lines = target;
|
|
|
+ config_free_lines(*lines);
|
|
|
+}
|
|
|
+
|
|
|
+static bool
|
|
|
+linelist_eq(const void *a, const void *b, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ const config_line_t *lines_a = *(const config_line_t **)a;
|
|
|
+ const config_line_t *lines_b = *(const config_line_t **)b;
|
|
|
+ return config_lines_eq(lines_a, lines_b);
|
|
|
+}
|
|
|
+
|
|
|
+static int
|
|
|
+linelist_copy(void *target, const void *value, const void *params)
|
|
|
+{
|
|
|
+ (void)params;
|
|
|
+ config_line_t **ptr = (config_line_t **)target;
|
|
|
+ const config_line_t *val = *(const config_line_t **)value;
|
|
|
+ config_free_lines(*ptr);
|
|
|
+ *ptr = config_lines_dup(val);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static const var_type_fns_t linelist_fns = {
|
|
|
+ .kv_parse = linelist_kv_parse,
|
|
|
+ .kv_encode = linelist_kv_encode,
|
|
|
+ .clear = linelist_clear,
|
|
|
+ .eq = linelist_eq,
|
|
|
+ .copy = linelist_copy,
|
|
|
+};
|
|
|
+
|
|
|
+static const var_type_fns_t linelist_v_fns = {
|
|
|
+ .kv_parse = linelist_kv_virt_noparse,
|
|
|
+ .kv_encode = linelist_kv_encode,
|
|
|
+ .clear = linelist_clear,
|
|
|
+ .eq = linelist_eq,
|
|
|
+ .copy = linelist_copy,
|
|
|
+};
|
|
|
+
|
|
|
+static const var_type_fns_t linelist_s_fns = {
|
|
|
+ .kv_parse = linelist_kv_parse,
|
|
|
+ .kv_encode = linelist_s_kv_encode,
|
|
|
+ .clear = linelist_clear,
|
|
|
+ .eq = linelist_eq,
|
|
|
+ .copy = linelist_copy,
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+static int
|
|
|
+ignore_parse(void *target, const char *value, char **errmsg,
|
|
|
+ const void *params)
|
|
|
+{
|
|
|
+ (void)target;
|
|
|
+ (void)value;
|
|
|
+ (void)errmsg;
|
|
|
+ (void)params;
|
|
|
+
|
|
|
+ log_warn(LD_GENERAL, "Skipping obsolete configuration option.");
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static char *
|
|
|
+ignore_encode(const void *value, const void *params)
|
|
|
+{
|
|
|
+ (void)value;
|
|
|
+ (void)params;
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static const var_type_fns_t ignore_fns = {
|
|
|
+ .parse = ignore_parse,
|
|
|
+ .encode = ignore_encode,
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+ * Table mapping conf_type_t values to var_type_def_t objects.
|
|
|
+ **/
|
|
|
+static const var_type_def_t type_definitions_table[] = {
|
|
|
+ [CONFIG_TYPE_STRING] = { "String", &string_fns, NULL },
|
|
|
+ [CONFIG_TYPE_FILENAME] = { "Filename", &string_fns, NULL },
|
|
|
+ [CONFIG_TYPE_INT] = { "SignedInteger", &int_fns, &INT_PARSE_UNRESTRICTED },
|
|
|
+ [CONFIG_TYPE_POSINT] = { "Integer", &int_fns, &INT_PARSE_POSINT },
|
|
|
+ [CONFIG_TYPE_UINT64] = { "Integer", &uint64_fns, NULL, },
|
|
|
+ [CONFIG_TYPE_MEMUNIT] = { "DataSize", &memunit_fns, &memory_units },
|
|
|
+ [CONFIG_TYPE_INTERVAL] = { "TimeInterval", &interval_fns, &time_units },
|
|
|
+ [CONFIG_TYPE_MSEC_INTERVAL] = { "TimeMsecInterval", &interval_fns,
|
|
|
+ &time_msec_units },
|
|
|
+ [CONFIG_TYPE_DOUBLE] = { "Float", &double_fns, NULL },
|
|
|
+ [CONFIG_TYPE_BOOL] = { "Boolean", &enum_fns, &enum_table_bool },
|
|
|
+ [CONFIG_TYPE_AUTOBOOL] = { "Boolean+Auto", &enum_fns, &enum_table_autobool },
|
|
|
+ [CONFIG_TYPE_ISOTIME] = { "Time", &time_fns, NULL },
|
|
|
+ [CONFIG_TYPE_CSV] = { "CommaList", &csv_fns, NULL },
|
|
|
+ [CONFIG_TYPE_CSV_INTERVAL] = { "TimeInterval", &legacy_csv_interval_fns,
|
|
|
+ NULL },
|
|
|
+ [CONFIG_TYPE_LINELIST] = { "LineList", &linelist_fns, NULL },
|
|
|
+ [CONFIG_TYPE_LINELIST_S] = { "Dependent", &linelist_s_fns, NULL },
|
|
|
+ [CONFIG_TYPE_LINELIST_V] = { "Virtual", &linelist_v_fns, NULL },
|
|
|
+ [CONFIG_TYPE_OBSOLETE] = { "Obsolete", &ignore_fns, NULL }
|
|
|
+};
|
|
|
+
|
|
|
+
|
|
|
+ * Return a pointer to the var_type_def_t object for the given
|
|
|
+ * config_type_t value, or NULL if no such type definition exists.
|
|
|
+ **/
|
|
|
+const var_type_def_t *
|
|
|
+lookup_type_def(config_type_t type)
|
|
|
+{
|
|
|
+ int t = type;
|
|
|
+ tor_assert(t >= 0);
|
|
|
+ if (t >= (int)ARRAY_LENGTH(type_definitions_table))
|
|
|
+ return NULL;
|
|
|
+ return &type_definitions_table[t];
|
|
|
+}
|