Make "GETCONF SocksPort" work again

I broke "GETCONF *Port" in 20956, when I made SocksPort a
subordinate option of the virtual option SocksPortLines, so that I
could make SocksPort and __SocksPort provide qthe same
functionality.  The problem was that you can't pass a subordinate
option to GETCONF.

So, this patch fixes that by letting you fetch subordinate options.

It won't always be meaningful to consider these options
out-of-context, but that can be the controller-user's
responsibility to check.

Closes ticket 21300.
This commit is contained in:
Nick Mathewson 2017-01-30 10:09:47 -05:00
parent 088cc3604b
commit 4d83999213
2 changed files with 24 additions and 4 deletions

6
changes/bug21300 Normal file
View File

@ -0,0 +1,6 @@
o Minor features (controller):
- The GETCONF command can now query options that may only be meaningful
in context-sensitive lists. This allows the controller to query
the mixed SocksPort/__SocksPort style options introduced in
feature 20956. Implements ticket 21300.

View File

@ -31,6 +31,8 @@ static int config_parse_msec_interval(const char *s, int *ok);
static int config_parse_interval(const char *s, int *ok); static int config_parse_interval(const char *s, int *ok);
static void config_reset(const config_format_t *fmt, void *options, static void config_reset(const config_format_t *fmt, void *options,
const config_var_t *var, int use_defaults); const config_var_t *var, int use_defaults);
static config_line_t *config_lines_dup_and_filter(const config_line_t *inp,
const char *key);
/** Allocate an empty configuration object of a given format type. */ /** Allocate an empty configuration object of a given format type. */
void * void *
@ -634,10 +636,23 @@ config_value_needs_escape(const char *value)
/** Return a newly allocated deep copy of the lines in <b>inp</b>. */ /** Return a newly allocated deep copy of the lines in <b>inp</b>. */
config_line_t * config_line_t *
config_lines_dup(const config_line_t *inp) config_lines_dup(const config_line_t *inp)
{
return config_lines_dup_and_filter(inp, NULL);
}
/** Return a newly allocated deep copy of the lines in <b>inp</b>,
* but only the ones that match <b>key</b>. */
static config_line_t *
config_lines_dup_and_filter(const config_line_t *inp,
const char *key)
{ {
config_line_t *result = NULL; config_line_t *result = NULL;
config_line_t **next_out = &result; config_line_t **next_out = &result;
while (inp) { while (inp) {
if (key && strcasecmpstart(inp->key, key)) {
inp = inp->next;
continue;
}
*next_out = tor_malloc_zero(sizeof(config_line_t)); *next_out = tor_malloc_zero(sizeof(config_line_t));
(*next_out)->key = tor_strdup(inp->key); (*next_out)->key = tor_strdup(inp->key);
(*next_out)->value = tor_strdup(inp->value); (*next_out)->value = tor_strdup(inp->value);
@ -764,11 +779,10 @@ config_get_assigned_option(const config_format_t *fmt, const void *options,
tor_free(result); tor_free(result);
return NULL; return NULL;
case CONFIG_TYPE_LINELIST_S: case CONFIG_TYPE_LINELIST_S:
log_warn(LD_CONFIG,
"Can't return context-sensitive '%s' on its own", key);
tor_free(result->key);
tor_free(result); tor_free(result);
return NULL; result = config_lines_dup_and_filter(*(const config_line_t **)value,
key);
break;
case CONFIG_TYPE_LINELIST: case CONFIG_TYPE_LINELIST:
case CONFIG_TYPE_LINELIST_V: case CONFIG_TYPE_LINELIST_V:
tor_free(result->key); tor_free(result->key);