mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
Merge branch 'ticket31240v2' into ticket31240v2_merged_2
This commit is contained in:
+75
-82
@@ -843,15 +843,15 @@ static void config_maybe_load_geoip_files_(const or_options_t *options,
|
||||
static int options_validate_cb(void *old_options, void *options,
|
||||
void *default_options,
|
||||
int from_setconf, char **msg);
|
||||
static void options_free_cb(void *options);
|
||||
static void cleanup_protocol_warning_severity_level(void);
|
||||
static void set_protocol_warning_severity_level(int warning_severity);
|
||||
static void options_clear_cb(const config_mgr_t *mgr, void *opts);
|
||||
|
||||
/** Magic value for or_options_t. */
|
||||
#define OR_OPTIONS_MAGIC 9090909
|
||||
|
||||
/** Configuration format for or_options_t. */
|
||||
STATIC const config_format_t options_format = {
|
||||
static const config_format_t options_format = {
|
||||
sizeof(or_options_t),
|
||||
{
|
||||
"or_options_t",
|
||||
@@ -862,8 +862,9 @@ STATIC const config_format_t options_format = {
|
||||
option_deprecation_notes_,
|
||||
option_vars_,
|
||||
options_validate_cb,
|
||||
options_free_cb,
|
||||
NULL
|
||||
options_clear_cb,
|
||||
NULL,
|
||||
offsetof(or_options_t, subconfigs_),
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -895,6 +896,20 @@ static int in_option_validation = 0;
|
||||
/* True iff we've initialized libevent */
|
||||
static int libevent_initialized = 0;
|
||||
|
||||
/* A global configuration manager to handle all configuration objects. */
|
||||
static config_mgr_t *options_mgr = NULL;
|
||||
|
||||
/** Return the global configuration manager object for torrc options. */
|
||||
STATIC const config_mgr_t *
|
||||
get_options_mgr(void)
|
||||
{
|
||||
if (PREDICT_UNLIKELY(options_mgr == NULL)) {
|
||||
options_mgr = config_mgr_new(&options_format);
|
||||
config_mgr_freeze(options_mgr);
|
||||
}
|
||||
return options_mgr;
|
||||
}
|
||||
|
||||
/** Return the contents of our frontpage string, or NULL if not configured. */
|
||||
MOCK_IMPL(const char*,
|
||||
get_dirportfrontpage, (void))
|
||||
@@ -951,9 +966,6 @@ get_options_defaults(void)
|
||||
int
|
||||
set_options(or_options_t *new_val, char **msg)
|
||||
{
|
||||
int i;
|
||||
smartlist_t *elements;
|
||||
config_line_t *line;
|
||||
or_options_t *old_options = global_options;
|
||||
global_options = new_val;
|
||||
/* Note that we pass the *old* options below, for comparison. It
|
||||
@@ -975,35 +987,16 @@ set_options(or_options_t *new_val, char **msg)
|
||||
/* Issues a CONF_CHANGED event to notify controller of the change. If Tor is
|
||||
* just starting up then the old_options will be undefined. */
|
||||
if (old_options && old_options != global_options) {
|
||||
elements = smartlist_new();
|
||||
for (i=0; options_format.vars[i].member.name; ++i) {
|
||||
const config_var_t *var = &options_format.vars[i];
|
||||
const char *var_name = var->member.name;
|
||||
if (config_var_is_contained(var)) {
|
||||
/* something else will check this var, or it doesn't need checking */
|
||||
continue;
|
||||
}
|
||||
if (!config_is_same(&options_format, new_val, old_options, var_name)) {
|
||||
line = config_get_assigned_option(&options_format, new_val,
|
||||
var_name, 1);
|
||||
|
||||
if (line) {
|
||||
config_line_t *next;
|
||||
for (; line; line = next) {
|
||||
next = line->next;
|
||||
smartlist_add(elements, line->key);
|
||||
smartlist_add(elements, line->value);
|
||||
tor_free(line);
|
||||
}
|
||||
} else {
|
||||
smartlist_add_strdup(elements, options_format.vars[i].member.name);
|
||||
smartlist_add(elements, NULL);
|
||||
}
|
||||
}
|
||||
smartlist_t *elements = smartlist_new();
|
||||
config_line_t *changes =
|
||||
config_get_changes(get_options_mgr(), old_options, new_val);
|
||||
for (config_line_t *line = changes; line; line = line->next) {
|
||||
smartlist_add(elements, line->key);
|
||||
smartlist_add(elements, line->value);
|
||||
}
|
||||
control_event_conf_changed(elements);
|
||||
SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
|
||||
smartlist_free(elements);
|
||||
config_free_lines(changes);
|
||||
}
|
||||
|
||||
if (old_options != global_options) {
|
||||
@@ -1019,11 +1012,11 @@ set_options(or_options_t *new_val, char **msg)
|
||||
|
||||
/** Release additional memory allocated in options
|
||||
*/
|
||||
STATIC void
|
||||
or_options_free_(or_options_t *options)
|
||||
static void
|
||||
options_clear_cb(const config_mgr_t *mgr, void *opts)
|
||||
{
|
||||
if (!options)
|
||||
return;
|
||||
(void)mgr;
|
||||
or_options_t *options = opts;
|
||||
|
||||
routerset_free(options->ExcludeExitNodesUnion_);
|
||||
if (options->NodeFamilySets) {
|
||||
@@ -1046,7 +1039,14 @@ or_options_free_(or_options_t *options)
|
||||
tor_free(options->command_arg);
|
||||
tor_free(options->master_key_fname);
|
||||
config_free_lines(options->MyFamily);
|
||||
config_free(&options_format, options);
|
||||
}
|
||||
|
||||
/** Release all memory allocated in options
|
||||
*/
|
||||
STATIC void
|
||||
or_options_free_(or_options_t *options)
|
||||
{
|
||||
config_free(get_options_mgr(), options);
|
||||
}
|
||||
|
||||
/** Release all memory and resources held by global configuration structures.
|
||||
@@ -1080,6 +1080,8 @@ config_free_all(void)
|
||||
|
||||
have_parsed_cmdline = 0;
|
||||
libevent_initialized = 0;
|
||||
|
||||
config_mgr_free(options_mgr);
|
||||
}
|
||||
|
||||
/** Make <b>address</b> -- a piece of information related to our operation as
|
||||
@@ -2547,7 +2549,7 @@ config_parse_commandline(int argc, char **argv, int ignore_errors,
|
||||
|
||||
param = tor_malloc_zero(sizeof(config_line_t));
|
||||
param->key = is_cmdline ? tor_strdup(argv[i]) :
|
||||
tor_strdup(config_expand_abbrev(&options_format, s, 1, 1));
|
||||
tor_strdup(config_expand_abbrev(get_options_mgr(), s, 1, 1));
|
||||
param->value = arg;
|
||||
param->command = command;
|
||||
param->next = NULL;
|
||||
@@ -2573,8 +2575,7 @@ config_parse_commandline(int argc, char **argv, int ignore_errors,
|
||||
int
|
||||
option_is_recognized(const char *key)
|
||||
{
|
||||
const config_var_t *var = config_find_option(&options_format, key);
|
||||
return (var != NULL);
|
||||
return config_find_option_name(get_options_mgr(), key) != NULL;
|
||||
}
|
||||
|
||||
/** Return the canonical name of a configuration option, or NULL
|
||||
@@ -2582,8 +2583,7 @@ option_is_recognized(const char *key)
|
||||
const char *
|
||||
option_get_canonical_name(const char *key)
|
||||
{
|
||||
const config_var_t *var = config_find_option(&options_format, key);
|
||||
return var ? var->member.name : NULL;
|
||||
return config_find_option_name(get_options_mgr(), key);
|
||||
}
|
||||
|
||||
/** Return a canonical list of the options assigned for key.
|
||||
@@ -2591,7 +2591,7 @@ option_get_canonical_name(const char *key)
|
||||
config_line_t *
|
||||
option_get_assignment(const or_options_t *options, const char *key)
|
||||
{
|
||||
return config_get_assigned_option(&options_format, options, key, 1);
|
||||
return config_get_assigned_option(get_options_mgr(), options, key, 1);
|
||||
}
|
||||
|
||||
/** Try assigning <b>list</b> to the global options. You do this by duping
|
||||
@@ -2607,9 +2607,9 @@ setopt_err_t
|
||||
options_trial_assign(config_line_t *list, unsigned flags, char **msg)
|
||||
{
|
||||
int r;
|
||||
or_options_t *trial_options = config_dup(&options_format, get_options());
|
||||
or_options_t *trial_options = config_dup(get_options_mgr(), get_options());
|
||||
|
||||
if ((r=config_assign(&options_format, trial_options,
|
||||
if ((r=config_assign(get_options_mgr(), trial_options,
|
||||
list, flags, msg)) < 0) {
|
||||
or_options_free(trial_options);
|
||||
return r;
|
||||
@@ -2664,25 +2664,25 @@ print_usage(void)
|
||||
static void
|
||||
list_torrc_options(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; option_vars_[i].member.name; ++i) {
|
||||
const config_var_t *var = &option_vars_[i];
|
||||
smartlist_t *vars = config_mgr_list_vars(get_options_mgr());
|
||||
SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) {
|
||||
if (! config_var_is_settable(var)) {
|
||||
/* This variable cannot be set, or cannot be set by this name. */
|
||||
continue;
|
||||
}
|
||||
printf("%s\n", var->member.name);
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(var);
|
||||
smartlist_free(vars);
|
||||
}
|
||||
|
||||
/** Print all deprecated but non-obsolete torrc options. */
|
||||
static void
|
||||
list_deprecated_options(void)
|
||||
{
|
||||
const config_deprecation_t *d;
|
||||
for (d = option_deprecation_notes_; d->name; ++d) {
|
||||
printf("%s\n", d->name);
|
||||
}
|
||||
smartlist_t *deps = config_mgr_list_deprecated_vars(get_options_mgr());
|
||||
SMARTLIST_FOREACH(deps, const char *, name,
|
||||
printf("%s\n", name));
|
||||
smartlist_free(deps);
|
||||
}
|
||||
|
||||
/** Print all compile-time modules and their enabled/disabled status. */
|
||||
@@ -2992,7 +2992,7 @@ is_local_addr, (const tor_addr_t *addr))
|
||||
or_options_t *
|
||||
options_new(void)
|
||||
{
|
||||
return config_new(&options_format);
|
||||
return config_new(get_options_mgr());
|
||||
}
|
||||
|
||||
/** Set <b>options</b> to hold reasonable defaults for most options.
|
||||
@@ -3000,10 +3000,10 @@ options_new(void)
|
||||
void
|
||||
options_init(or_options_t *options)
|
||||
{
|
||||
config_init(&options_format, options);
|
||||
config_init(get_options_mgr(), options);
|
||||
config_line_t *dflts = get_options_defaults();
|
||||
char *msg=NULL;
|
||||
if (config_assign(&options_format, options, dflts,
|
||||
if (config_assign(get_options_mgr(), options, dflts,
|
||||
CAL_WARN_DEPRECATIONS, &msg)<0) {
|
||||
log_err(LD_BUG, "Unable to set default options: %s", msg);
|
||||
tor_free(msg);
|
||||
@@ -3040,7 +3040,7 @@ options_dump(const or_options_t *options, int how_to_dump)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return config_dump(&options_format, use_defaults, options, minimal, 0);
|
||||
return config_dump(get_options_mgr(), use_defaults, options, minimal, 0);
|
||||
}
|
||||
|
||||
/** Return 0 if every element of sl is a string holding a decimal
|
||||
@@ -3172,13 +3172,6 @@ options_validate_cb(void *old_options, void *options, void *default_options,
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** Callback to free an or_options_t */
|
||||
static void
|
||||
options_free_cb(void *options)
|
||||
{
|
||||
or_options_free_(options);
|
||||
}
|
||||
|
||||
#define REJECT(arg) \
|
||||
STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
|
||||
#if defined(__GNUC__) && __GNUC__ <= 3
|
||||
@@ -4435,7 +4428,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
|
||||
STMT_BEGIN \
|
||||
if (!options->TestingTorNetwork && \
|
||||
!options->UsingTestNetworkDefaults_ && \
|
||||
!config_is_same(&options_format,options, \
|
||||
!config_is_same(get_options_mgr(),options, \
|
||||
default_options,#arg)) { \
|
||||
REJECT(#arg " may only be changed in testing Tor " \
|
||||
"networks!"); \
|
||||
@@ -5411,8 +5404,7 @@ options_init_from_string(const char *cf_defaults, const char *cf,
|
||||
oldoptions = global_options; /* get_options unfortunately asserts if
|
||||
this is the first time we run*/
|
||||
|
||||
newoptions = tor_malloc_zero(sizeof(or_options_t));
|
||||
newoptions->magic_ = OR_OPTIONS_MAGIC;
|
||||
newoptions = options_new();
|
||||
options_init(newoptions);
|
||||
newoptions->command = command;
|
||||
newoptions->command_arg = command_arg ? tor_strdup(command_arg) : NULL;
|
||||
@@ -5431,7 +5423,7 @@ options_init_from_string(const char *cf_defaults, const char *cf,
|
||||
err = SETOPT_ERR_PARSE;
|
||||
goto err;
|
||||
}
|
||||
retval = config_assign(&options_format, newoptions, cl,
|
||||
retval = config_assign(get_options_mgr(), newoptions, cl,
|
||||
CAL_WARN_DEPRECATIONS, msg);
|
||||
config_free_lines(cl);
|
||||
if (retval < 0) {
|
||||
@@ -5439,15 +5431,15 @@ options_init_from_string(const char *cf_defaults, const char *cf,
|
||||
goto err;
|
||||
}
|
||||
if (i==0)
|
||||
newdefaultoptions = config_dup(&options_format, newoptions);
|
||||
newdefaultoptions = config_dup(get_options_mgr(), newoptions);
|
||||
}
|
||||
|
||||
if (newdefaultoptions == NULL) {
|
||||
newdefaultoptions = config_dup(&options_format, global_default_options);
|
||||
newdefaultoptions = config_dup(get_options_mgr(), global_default_options);
|
||||
}
|
||||
|
||||
/* Go through command-line variables too */
|
||||
retval = config_assign(&options_format, newoptions,
|
||||
retval = config_assign(get_options_mgr(), newoptions,
|
||||
global_cmdline_options, CAL_WARN_DEPRECATIONS, msg);
|
||||
if (retval < 0) {
|
||||
err = SETOPT_ERR_PARSE;
|
||||
@@ -8133,9 +8125,8 @@ getinfo_helper_config(control_connection_t *conn,
|
||||
(void) errmsg;
|
||||
if (!strcmp(question, "config/names")) {
|
||||
smartlist_t *sl = smartlist_new();
|
||||
int i;
|
||||
for (i = 0; option_vars_[i].member.name; ++i) {
|
||||
const config_var_t *var = &option_vars_[i];
|
||||
smartlist_t *vars = config_mgr_list_vars(get_options_mgr());
|
||||
SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) {
|
||||
/* don't tell controller about invisible options */
|
||||
if (config_var_is_invisible(var))
|
||||
continue;
|
||||
@@ -8143,26 +8134,27 @@ getinfo_helper_config(control_connection_t *conn,
|
||||
if (!type)
|
||||
continue;
|
||||
smartlist_add_asprintf(sl, "%s %s\n",var->member.name,type);
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(var);
|
||||
*answer = smartlist_join_strings(sl, "", 0, NULL);
|
||||
SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
|
||||
smartlist_free(sl);
|
||||
smartlist_free(vars);
|
||||
} else if (!strcmp(question, "config/defaults")) {
|
||||
smartlist_t *sl = smartlist_new();
|
||||
int dirauth_lines_seen = 0, fallback_lines_seen = 0;
|
||||
for (int i = 0; option_vars_[i].member.name; ++i) {
|
||||
const config_var_t *var = &option_vars_[i];
|
||||
smartlist_t *vars = config_mgr_list_vars(get_options_mgr());
|
||||
SMARTLIST_FOREACH_BEGIN(vars, const config_var_t *, var) {
|
||||
if (var->initvalue != NULL) {
|
||||
if (strcmp(option_vars_[i].member.name, "DirAuthority") == 0) {
|
||||
if (strcmp(var->member.name, "DirAuthority") == 0) {
|
||||
/*
|
||||
* Count dirauth lines we have a default for; we'll use the
|
||||
* count later to decide whether to add the defaults manually
|
||||
*/
|
||||
++dirauth_lines_seen;
|
||||
}
|
||||
if (strcmp(option_vars_[i].member.name, "FallbackDir") == 0) {
|
||||
if (strcmp(var->member.name, "FallbackDir") == 0) {
|
||||
/*
|
||||
* Similarly count fallback lines, so that we can decided later
|
||||
* Similarly count fallback lines, so that we can decide later
|
||||
* to add the defaults manually.
|
||||
*/
|
||||
++fallback_lines_seen;
|
||||
@@ -8171,7 +8163,8 @@ getinfo_helper_config(control_connection_t *conn,
|
||||
smartlist_add_asprintf(sl, "%s %s\n",var->member.name,val);
|
||||
tor_free(val);
|
||||
}
|
||||
}
|
||||
} SMARTLIST_FOREACH_END(var);
|
||||
smartlist_free(vars);
|
||||
|
||||
if (dirauth_lines_seen == 0) {
|
||||
/*
|
||||
|
||||
@@ -247,9 +247,8 @@ int options_any_client_port_set(const or_options_t *options);
|
||||
#define CL_PORT_DFLT_GROUP_WRITABLE (1u<<7)
|
||||
|
||||
STATIC int options_act(const or_options_t *old_options);
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
extern const struct config_format_t options_format;
|
||||
#endif
|
||||
struct config_mgr_t;
|
||||
STATIC const struct config_mgr_t *get_options_mgr(void);
|
||||
|
||||
STATIC port_cfg_t *port_cfg_new(size_t namelen);
|
||||
#define port_cfg_free(port) \
|
||||
|
||||
+589
-157
File diff suppressed because it is too large
Load Diff
+57
-26
@@ -39,8 +39,16 @@ typedef struct config_deprecation_t {
|
||||
* of arguments. */
|
||||
typedef int (*validate_fn_t)(void*,void*,void*,int,char**);
|
||||
|
||||
/** Callback to free a configuration object. */
|
||||
typedef void (*free_cfg_fn_t)(void*);
|
||||
struct config_mgr_t;
|
||||
|
||||
/**
|
||||
* Callback to clear all non-managed fields of a configuration object.
|
||||
*
|
||||
* (Regular fields get cleared by config_reset(), but you might have fields
|
||||
* in the object that do not correspond to configuration variables. If those
|
||||
* fields need to be cleared or freed, this is where to do it.)
|
||||
*/
|
||||
typedef void (*clear_cfg_fn_t)(const struct config_mgr_t *mgr, void*);
|
||||
|
||||
/** Information on the keys, value types, key-to-struct-member mappings,
|
||||
* variable descriptions, validation functions, and abbreviations for a
|
||||
@@ -55,51 +63,70 @@ typedef struct config_format_t {
|
||||
* values, and where we stick them in the
|
||||
* structure. */
|
||||
validate_fn_t validate_fn; /**< Function to validate config. */
|
||||
free_cfg_fn_t free_fn; /**< Function to free the configuration. */
|
||||
clear_cfg_fn_t clear_fn; /**< Function to clear the configuration. */
|
||||
/** If present, extra denotes a LINELIST variable for unrecognized
|
||||
* lines. Otherwise, unrecognized lines are an error. */
|
||||
const struct_member_t *extra;
|
||||
/** The position of a config_suite_t pointer within the toplevel object,
|
||||
* or -1 if there is no such pointer. */
|
||||
int config_suite_offset;
|
||||
} config_format_t;
|
||||
|
||||
/** Macro: assert that <b>cfg</b> has the right magic field for format
|
||||
* <b>fmt</b>. */
|
||||
#define CONFIG_CHECK(fmt, cfg) STMT_BEGIN \
|
||||
tor_assert(fmt); \
|
||||
struct_check_magic((cfg), &fmt->magic); \
|
||||
STMT_END
|
||||
/**
|
||||
* A collection of config_format_t objects to describe several objects
|
||||
* that are all configured with the same configuration file.
|
||||
*
|
||||
* (NOTE: for now, this only handles a single config_format_t.)
|
||||
**/
|
||||
typedef struct config_mgr_t config_mgr_t;
|
||||
|
||||
config_mgr_t *config_mgr_new(const config_format_t *toplevel_fmt);
|
||||
void config_mgr_free_(config_mgr_t *mgr);
|
||||
int config_mgr_add_format(config_mgr_t *mgr,
|
||||
const config_format_t *fmt);
|
||||
void config_mgr_freeze(config_mgr_t *mgr);
|
||||
#define config_mgr_free(mgr) \
|
||||
FREE_AND_NULL(config_mgr_t, config_mgr_free_, (mgr))
|
||||
struct smartlist_t *config_mgr_list_vars(const config_mgr_t *mgr);
|
||||
struct smartlist_t *config_mgr_list_deprecated_vars(const config_mgr_t *mgr);
|
||||
|
||||
/** A collection of managed configuration objects. */
|
||||
typedef struct config_suite_t config_suite_t;
|
||||
|
||||
#define CAL_USE_DEFAULTS (1u<<0)
|
||||
#define CAL_CLEAR_FIRST (1u<<1)
|
||||
#define CAL_WARN_DEPRECATIONS (1u<<2)
|
||||
|
||||
void *config_new(const config_format_t *fmt);
|
||||
void config_free_(const config_format_t *fmt, void *options);
|
||||
#define config_free(fmt, options) do { \
|
||||
config_free_((fmt), (options)); \
|
||||
void *config_new(const config_mgr_t *fmt);
|
||||
void config_free_(const config_mgr_t *fmt, void *options);
|
||||
#define config_free(mgr, options) do { \
|
||||
config_free_((mgr), (options)); \
|
||||
(options) = NULL; \
|
||||
} while (0)
|
||||
|
||||
struct config_line_t *config_get_assigned_option(const config_format_t *fmt,
|
||||
struct config_line_t *config_get_assigned_option(const config_mgr_t *mgr,
|
||||
const void *options, const char *key,
|
||||
int escape_val);
|
||||
int config_is_same(const config_format_t *fmt,
|
||||
int config_is_same(const config_mgr_t *fmt,
|
||||
const void *o1, const void *o2,
|
||||
const char *name);
|
||||
void config_init(const config_format_t *fmt, void *options);
|
||||
void *config_dup(const config_format_t *fmt, const void *old);
|
||||
char *config_dump(const config_format_t *fmt, const void *default_options,
|
||||
struct config_line_t *config_get_changes(const config_mgr_t *mgr,
|
||||
const void *options1, const void *options2);
|
||||
void config_init(const config_mgr_t *mgr, void *options);
|
||||
void *config_dup(const config_mgr_t *mgr, const void *old);
|
||||
char *config_dump(const config_mgr_t *mgr, const void *default_options,
|
||||
const void *options, int minimal,
|
||||
int comment_defaults);
|
||||
bool config_check_ok(const config_format_t *fmt, const void *options,
|
||||
bool config_check_ok(const config_mgr_t *mgr, const void *options,
|
||||
int severity);
|
||||
int config_assign(const config_format_t *fmt, void *options,
|
||||
int config_assign(const config_mgr_t *mgr, void *options,
|
||||
struct config_line_t *list,
|
||||
unsigned flags, char **msg);
|
||||
const char *config_find_deprecation(const config_format_t *fmt,
|
||||
const char *key);
|
||||
const config_var_t *config_find_option(const config_format_t *fmt,
|
||||
const char *key);
|
||||
const char *config_expand_abbrev(const config_format_t *fmt,
|
||||
const char *config_find_deprecation(const config_mgr_t *mgr,
|
||||
const char *key);
|
||||
const char *config_find_option_name(const config_mgr_t *mgr,
|
||||
const char *key);
|
||||
const char *config_expand_abbrev(const config_mgr_t *mgr,
|
||||
const char *option,
|
||||
int command_line, int warn_obsolete);
|
||||
void warn_deprecated_option(const char *what, const char *why);
|
||||
@@ -119,8 +146,12 @@ bool config_var_is_dumpable(const config_var_t *var);
|
||||
#define CFG_EQ_ROUTERSET(a,b,opt) routerset_equal((a)->opt, (b)->opt)
|
||||
|
||||
#ifdef CONFPARSE_PRIVATE
|
||||
STATIC void config_reset_line(const config_format_t *fmt, void *options,
|
||||
STATIC void config_reset_line(const config_mgr_t *mgr, void *options,
|
||||
const char *key, int use_defaults);
|
||||
STATIC void *config_mgr_get_obj_mutable(const config_mgr_t *mgr,
|
||||
void *toplevel, int idx);
|
||||
STATIC const void *config_mgr_get_obj(const config_mgr_t *mgr,
|
||||
const void *toplevel, int idx);
|
||||
#endif
|
||||
|
||||
#endif /* !defined(TOR_CONFPARSE_H) */
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
struct smartlist_t;
|
||||
struct config_line_t;
|
||||
struct config_suite_t;
|
||||
|
||||
/** Enumeration of outbound address configuration types:
|
||||
* Exit-only, OR-only, or both */
|
||||
@@ -1107,6 +1108,14 @@ struct or_options_t {
|
||||
* a possible previous dormant state.
|
||||
**/
|
||||
int DormantCanceledByStartup;
|
||||
|
||||
/**
|
||||
* Configuration objects for individual modules.
|
||||
*
|
||||
* Never access this field or its members directly: instead, use the module
|
||||
* in question to get its relevant configuration object.
|
||||
*/
|
||||
struct config_suite_t *subconfigs_;
|
||||
};
|
||||
|
||||
#endif /* !defined(TOR_OR_OPTIONS_ST_H) */
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "lib/cc/torint.h"
|
||||
struct smartlist_t;
|
||||
struct config_suite_t;
|
||||
|
||||
/** Persistent state for an onion router, as saved to disk. */
|
||||
struct or_state_t {
|
||||
@@ -94,6 +95,14 @@ struct or_state_t {
|
||||
/** True if we were dormant when we last wrote the file; false if we
|
||||
* weren't. "auto" on initial startup. */
|
||||
int Dormant;
|
||||
|
||||
/**
|
||||
* State objects for individual modules.
|
||||
*
|
||||
* Never access this field or its members directly: instead, use the module
|
||||
* in question to get its relevant state object if you must.
|
||||
*/
|
||||
struct config_suite_t *substates_;
|
||||
};
|
||||
|
||||
#endif /* !defined(TOR_OR_STATE_ST_H) */
|
||||
|
||||
+25
-18
@@ -145,8 +145,6 @@ static int or_state_validate_cb(void *old_options, void *options,
|
||||
void *default_options,
|
||||
int from_setconf, char **msg);
|
||||
|
||||
static void or_state_free_cb(void *state);
|
||||
|
||||
/** Magic value for or_state_t. */
|
||||
#define OR_STATE_MAGIC 0x57A73f57
|
||||
|
||||
@@ -170,10 +168,25 @@ static const config_format_t state_format = {
|
||||
NULL,
|
||||
state_vars_,
|
||||
or_state_validate_cb,
|
||||
or_state_free_cb,
|
||||
NULL,
|
||||
&state_extra_var,
|
||||
offsetof(or_state_t, substates_),
|
||||
};
|
||||
|
||||
/* A global configuration manager for state-file objects */
|
||||
static config_mgr_t *state_mgr = NULL;
|
||||
|
||||
/** Return the configuration manager for state-file objects. */
|
||||
static const config_mgr_t *
|
||||
get_state_mgr(void)
|
||||
{
|
||||
if (PREDICT_UNLIKELY(state_mgr == NULL)) {
|
||||
state_mgr = config_mgr_new(&state_format);
|
||||
config_mgr_freeze(state_mgr);
|
||||
}
|
||||
return state_mgr;
|
||||
}
|
||||
|
||||
/** Persistent serialized state. */
|
||||
static or_state_t *global_state = NULL;
|
||||
|
||||
@@ -268,12 +281,6 @@ or_state_validate_cb(void *old_state, void *state, void *default_state,
|
||||
return or_state_validate(state, msg);
|
||||
}
|
||||
|
||||
static void
|
||||
or_state_free_cb(void *state)
|
||||
{
|
||||
or_state_free_(state);
|
||||
}
|
||||
|
||||
/** Return 0 if every setting in <b>state</b> is reasonable, and a
|
||||
* permissible transition from <b>old_state</b>. Else warn and return -1.
|
||||
* Should have no side effects, except for normalizing the contents of
|
||||
@@ -298,7 +305,7 @@ or_state_set(or_state_t *new_state)
|
||||
char *err = NULL;
|
||||
int ret = 0;
|
||||
tor_assert(new_state);
|
||||
config_free(&state_format, global_state);
|
||||
config_free(get_state_mgr(), global_state);
|
||||
global_state = new_state;
|
||||
if (entry_guards_parse_state(global_state, 1, &err)<0) {
|
||||
log_warn(LD_GENERAL,"%s",err);
|
||||
@@ -361,9 +368,8 @@ or_state_save_broken(char *fname)
|
||||
STATIC or_state_t *
|
||||
or_state_new(void)
|
||||
{
|
||||
or_state_t *new_state = tor_malloc_zero(sizeof(or_state_t));
|
||||
new_state->magic_ = OR_STATE_MAGIC;
|
||||
config_init(&state_format, new_state);
|
||||
or_state_t *new_state = config_new(get_state_mgr());
|
||||
config_init(get_state_mgr(), new_state);
|
||||
|
||||
return new_state;
|
||||
}
|
||||
@@ -404,7 +410,7 @@ or_state_load(void)
|
||||
int assign_retval;
|
||||
if (config_get_lines(contents, &lines, 0)<0)
|
||||
goto done;
|
||||
assign_retval = config_assign(&state_format, new_state,
|
||||
assign_retval = config_assign(get_state_mgr(), new_state,
|
||||
lines, 0, &errmsg);
|
||||
config_free_lines(lines);
|
||||
if (assign_retval<0)
|
||||
@@ -431,7 +437,7 @@ or_state_load(void)
|
||||
or_state_save_broken(fname);
|
||||
|
||||
tor_free(contents);
|
||||
config_free(&state_format, new_state);
|
||||
config_free(get_state_mgr(), new_state);
|
||||
|
||||
new_state = or_state_new();
|
||||
} else if (contents) {
|
||||
@@ -464,7 +470,7 @@ or_state_load(void)
|
||||
tor_free(fname);
|
||||
tor_free(contents);
|
||||
if (new_state)
|
||||
config_free(&state_format, new_state);
|
||||
config_free(get_state_mgr(), new_state);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -517,7 +523,7 @@ or_state_save(time_t now)
|
||||
tor_free(global_state->TorVersion);
|
||||
tor_asprintf(&global_state->TorVersion, "Tor %s", get_version());
|
||||
|
||||
state = config_dump(&state_format, NULL, global_state, 1, 0);
|
||||
state = config_dump(get_state_mgr(), NULL, global_state, 1, 0);
|
||||
format_local_iso_time(tbuf, now);
|
||||
tor_asprintf(&contents,
|
||||
"# Tor state file last generated on %s local time\n"
|
||||
@@ -727,7 +733,7 @@ or_state_free_(or_state_t *state)
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
config_free(&state_format, state);
|
||||
config_free(get_state_mgr(), state);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -735,4 +741,5 @@ or_state_free_all(void)
|
||||
{
|
||||
or_state_free(global_state);
|
||||
global_state = NULL;
|
||||
config_mgr_free(state_mgr);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user