mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-30 23:53:32 +01:00
Implement some more GETINFO goodness: expose helper nodes, config options, getinfo keys.
svn:r4694
This commit is contained in:
parent
5b3286179c
commit
4cb89fd557
14
doc/TODO
14
doc/TODO
@ -78,12 +78,16 @@ for 0.1.1.x:
|
|||||||
o Implement main controller interface
|
o Implement main controller interface
|
||||||
o Glue code
|
o Glue code
|
||||||
o Testing
|
o Testing
|
||||||
N - Additional controller features
|
N . Additional controller features
|
||||||
- Expose more information via getinfo
|
. Expose more information via getinfo:
|
||||||
o Accounting status
|
o Accounting status
|
||||||
- Helper node status
|
o Helper node status
|
||||||
- Review all static fields for candidates
|
o Document
|
||||||
- List of available getinfo/getconf fields.
|
o Implement
|
||||||
|
o List of available getinfo/getconf fields.
|
||||||
|
o Document
|
||||||
|
o Implement
|
||||||
|
- Review all static fields for additional candidates
|
||||||
- Allow EXTENDCIRCUIT to unknown server.
|
- Allow EXTENDCIRCUIT to unknown server.
|
||||||
- We need some way to adjust server status, and to tell tor not to
|
- We need some way to adjust server status, and to tell tor not to
|
||||||
download directories/network-status, and a way to force a download.
|
download directories/network-status, and a way to force a download.
|
||||||
|
@ -325,6 +325,45 @@ $Id$
|
|||||||
form:
|
form:
|
||||||
ServerID SP ORStatus CRLF
|
ServerID SP ORStatus CRLF
|
||||||
|
|
||||||
|
"helper-nodes"
|
||||||
|
A series of lines listing the currently chosen helper nodes, if any.
|
||||||
|
Each is of the form:
|
||||||
|
ServerID SP ((("down" / "unlisted") ISOTime) / "up") CRLF
|
||||||
|
|
||||||
|
"accounting/enabled"
|
||||||
|
"accounting/hibernating"
|
||||||
|
"accounting/bytes"
|
||||||
|
"accounting/bytes-left"
|
||||||
|
"accounting/interval-start"
|
||||||
|
"accounting/interval-wake"
|
||||||
|
"accounting/interval-end"
|
||||||
|
Information about accounting status. If accounting is enabled,
|
||||||
|
"enabled" is 1; otherwise it is 0. The "hibernating" field is "hard"
|
||||||
|
if we are accepting no data; "soft" if we're accepting no new
|
||||||
|
connections, and "awake" if we're not hibernating at all. The "bytes"
|
||||||
|
and "bytes-left" fields contain (read-bytes SP write-bytes), for the
|
||||||
|
start and the rest of the interval respectively. The 'interval-start'
|
||||||
|
and 'interval-end' fields are the borders of the current interval; the
|
||||||
|
'interval-wake' field is the time within the current interval (if any)
|
||||||
|
where we plan[ned] to start being active.
|
||||||
|
|
||||||
|
"config/names"
|
||||||
|
A series of lines listing the available configuration options. Each is
|
||||||
|
of the form:
|
||||||
|
OptionName SP OptionType [ SP Documentation ] CRLF
|
||||||
|
OptionName = Keyword
|
||||||
|
OptionType = "Integer" / "TimeInterval" / "DataSize" / "Float" /
|
||||||
|
"Boolean" / "Time" / "CommaList" / "Dependant" / "Virtual" /
|
||||||
|
"String" / "LineList"
|
||||||
|
Documentation = Text
|
||||||
|
|
||||||
|
"info/names"
|
||||||
|
A series of lines listing the available GETINFO options. Each is of
|
||||||
|
one of thes forms:
|
||||||
|
OptionName SP Documentation CRLF
|
||||||
|
OptionPrefix SP Documentation CRLF
|
||||||
|
OptionPrefix = OptionName "/*"
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
C: GETINFO version desc/name/moria1
|
C: GETINFO version desc/name/moria1
|
||||||
S: 250+desc/name/moria=
|
S: 250+desc/name/moria=
|
||||||
|
@ -1621,11 +1621,12 @@ static void
|
|||||||
pick_helper_nodes(void)
|
pick_helper_nodes(void)
|
||||||
{
|
{
|
||||||
or_options_t *options = get_options();
|
or_options_t *options = get_options();
|
||||||
|
int changed = 0;
|
||||||
|
|
||||||
if (! options->UseHelperNodes)
|
if (! options->UseHelperNodes)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (helper_nodes == NULL)
|
if (!helper_nodes)
|
||||||
helper_nodes = smartlist_create();
|
helper_nodes = smartlist_create();
|
||||||
|
|
||||||
while (smartlist_len(helper_nodes) < options->NumHelperNodes) {
|
while (smartlist_len(helper_nodes) < options->NumHelperNodes) {
|
||||||
@ -1637,8 +1638,10 @@ pick_helper_nodes(void)
|
|||||||
strlcpy(helper->nickname, entry->nickname, sizeof(helper->nickname));
|
strlcpy(helper->nickname, entry->nickname, sizeof(helper->nickname));
|
||||||
memcpy(helper->identity, entry->identity_digest, DIGEST_LEN);
|
memcpy(helper->identity, entry->identity_digest, DIGEST_LEN);
|
||||||
smartlist_add(helper_nodes, helper);
|
smartlist_add(helper_nodes, helper);
|
||||||
helper_nodes_changed();
|
changed = 1;
|
||||||
}
|
}
|
||||||
|
if (changed)
|
||||||
|
helper_nodes_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Remove all elements from the list of helper nodes */
|
/** Remove all elements from the list of helper nodes */
|
||||||
@ -1810,8 +1813,9 @@ choose_random_helper(void)
|
|||||||
retry:
|
retry:
|
||||||
SMARTLIST_FOREACH(helper_nodes, helper_node_t *, helper,
|
SMARTLIST_FOREACH(helper_nodes, helper_node_t *, helper,
|
||||||
if (! helper->down_since && ! helper->unlisted_since) {
|
if (! helper->down_since && ! helper->unlisted_since) {
|
||||||
if ((r = router_get_by_digest(helper->identity)))
|
if ((r = router_get_by_digest(helper->identity))) {
|
||||||
smartlist_add(live_helpers, r);
|
smartlist_add(live_helpers, r);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (! smartlist_len(live_helpers)) {
|
if (! smartlist_len(live_helpers)) {
|
||||||
@ -1909,6 +1913,8 @@ helper_nodes_update_state(or_state_t *state)
|
|||||||
config_free_lines(state->HelperNodes);
|
config_free_lines(state->HelperNodes);
|
||||||
next = &state->HelperNodes;
|
next = &state->HelperNodes;
|
||||||
*next = NULL;
|
*next = NULL;
|
||||||
|
if (!helper_nodes)
|
||||||
|
helper_nodes = smartlist_create();
|
||||||
SMARTLIST_FOREACH(helper_nodes, helper_node_t *, h,
|
SMARTLIST_FOREACH(helper_nodes, helper_node_t *, h,
|
||||||
{
|
{
|
||||||
char dbuf[HEX_DIGEST_LEN+1];
|
char dbuf[HEX_DIGEST_LEN+1];
|
||||||
@ -1939,3 +1945,44 @@ helper_nodes_update_state(or_state_t *state)
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** DOCDOC */
|
||||||
|
int
|
||||||
|
helper_nodes_getinfo_helper(const char *question, char **answer)
|
||||||
|
{
|
||||||
|
if (!strcmp(question,"helper-nodes")) {
|
||||||
|
smartlist_t *sl = smartlist_create();
|
||||||
|
char tbuf[ISO_TIME_LEN+1];
|
||||||
|
char dbuf[HEX_DIGEST_LEN+1];
|
||||||
|
if (!helper_nodes)
|
||||||
|
helper_nodes = smartlist_create();
|
||||||
|
SMARTLIST_FOREACH(helper_nodes, helper_node_t *, h,
|
||||||
|
{
|
||||||
|
size_t len = HEX_DIGEST_LEN+ISO_TIME_LEN+16;
|
||||||
|
char *c = tor_malloc(len);
|
||||||
|
const char *status = NULL;
|
||||||
|
time_t when = 0;
|
||||||
|
if (h->unlisted_since) {
|
||||||
|
when = h->unlisted_since;
|
||||||
|
status = "unlisted";
|
||||||
|
} else if (h->down_since) {
|
||||||
|
when = h->down_since;
|
||||||
|
status = "down";
|
||||||
|
} else {
|
||||||
|
status = "up";
|
||||||
|
}
|
||||||
|
base16_encode(dbuf, sizeof(dbuf), h->identity, DIGEST_LEN);
|
||||||
|
if (when) {
|
||||||
|
format_iso_time(tbuf, when);
|
||||||
|
tor_snprintf(c, len, "$%s %s %s\n", dbuf, status, tbuf);
|
||||||
|
} else {
|
||||||
|
tor_snprintf(c, len, "$%s %s\n", dbuf, status);
|
||||||
|
}
|
||||||
|
smartlist_add(sl, c);
|
||||||
|
});
|
||||||
|
*answer = smartlist_join_strings(sl, "", 0, NULL);
|
||||||
|
SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
|
||||||
|
smartlist_free(sl);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
118
src/or/config.c
118
src/or/config.c
@ -218,7 +218,7 @@ typedef struct config_var_description_t {
|
|||||||
} config_var_description_t;
|
} config_var_description_t;
|
||||||
|
|
||||||
static config_var_description_t options_description[] = {
|
static config_var_description_t options_description[] = {
|
||||||
{ "Address", "The advertised (external) address we should use" },
|
{ "Address", "The advertised (external) address we should use." },
|
||||||
// { "AccountingStart", ""},
|
// { "AccountingStart", ""},
|
||||||
{ NULL, NULL },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
@ -294,7 +294,7 @@ static void check_libevent_version(const char *m, const char *v, int server);
|
|||||||
|
|
||||||
#define OR_OPTIONS_MAGIC 9090909
|
#define OR_OPTIONS_MAGIC 9090909
|
||||||
|
|
||||||
static config_format_t config_format = {
|
static config_format_t options_format = {
|
||||||
sizeof(or_options_t),
|
sizeof(or_options_t),
|
||||||
OR_OPTIONS_MAGIC,
|
OR_OPTIONS_MAGIC,
|
||||||
STRUCT_OFFSET(or_options_t, _magic),
|
STRUCT_OFFSET(or_options_t, _magic),
|
||||||
@ -351,14 +351,14 @@ void
|
|||||||
set_options(or_options_t *new_val)
|
set_options(or_options_t *new_val)
|
||||||
{
|
{
|
||||||
if (global_options)
|
if (global_options)
|
||||||
config_free(&config_format, global_options);
|
config_free(&options_format, global_options);
|
||||||
global_options = new_val;
|
global_options = new_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
config_free_all(void)
|
config_free_all(void)
|
||||||
{
|
{
|
||||||
config_free(&config_format, global_options);
|
config_free(&options_format, global_options);
|
||||||
tor_free(config_fname);
|
tor_free(config_fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,7 +568,7 @@ config_get_commandlines(int argc, char **argv)
|
|||||||
while (*s == '-')
|
while (*s == '-')
|
||||||
s++;
|
s++;
|
||||||
|
|
||||||
(*new)->key = tor_strdup(expand_abbrev(&config_format, s, 1));
|
(*new)->key = tor_strdup(expand_abbrev(&options_format, s, 1));
|
||||||
(*new)->value = tor_strdup(argv[i+1]);
|
(*new)->value = tor_strdup(argv[i+1]);
|
||||||
(*new)->next = NULL;
|
(*new)->next = NULL;
|
||||||
log(LOG_DEBUG,"Commandline: parsed keyword '%s', value '%s'",
|
log(LOG_DEBUG,"Commandline: parsed keyword '%s', value '%s'",
|
||||||
@ -650,6 +650,18 @@ config_free_lines(config_line_t *front)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** DOCDOC */
|
||||||
|
static const char *
|
||||||
|
config_find_description(config_format_t *fmt, const char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i=0; fmt->descriptions[i].name; ++i) {
|
||||||
|
if (!strcasecmp(name, fmt->descriptions[i].name))
|
||||||
|
return fmt->descriptions[i].description;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/** If <b>key</b> is a configuration option, return the corresponding
|
/** If <b>key</b> is a configuration option, return the corresponding
|
||||||
* config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
|
* config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
|
||||||
* warn, and return the corresponding config_var_t. Otherwise return NULL.
|
* warn, and return the corresponding config_var_t. Otherwise return NULL.
|
||||||
@ -663,8 +675,9 @@ config_find_option(config_format_t *fmt, const char *key)
|
|||||||
return NULL; /* if they say "--" on the commandline, it's not an option */
|
return NULL; /* if they say "--" on the commandline, it's not an option */
|
||||||
/* First, check for an exact (case-insensitive) match */
|
/* First, check for an exact (case-insensitive) match */
|
||||||
for (i=0; fmt->vars[i].name; ++i) {
|
for (i=0; fmt->vars[i].name; ++i) {
|
||||||
if (!strcasecmp(key, fmt->vars[i].name))
|
if (!strcasecmp(key, fmt->vars[i].name)) {
|
||||||
return &fmt->vars[i];
|
return &fmt->vars[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* If none, check for an abbreviated match */
|
/* If none, check for an abbreviated match */
|
||||||
for (i=0; fmt->vars[i].name; ++i) {
|
for (i=0; fmt->vars[i].name; ++i) {
|
||||||
@ -817,7 +830,7 @@ config_reset_line(config_format_t *fmt, or_options_t *options, const char *key)
|
|||||||
int
|
int
|
||||||
option_is_recognized(const char *key)
|
option_is_recognized(const char *key)
|
||||||
{
|
{
|
||||||
config_var_t *var = config_find_option(&config_format, key);
|
config_var_t *var = config_find_option(&options_format, key);
|
||||||
return (var != NULL);
|
return (var != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -825,7 +838,7 @@ option_is_recognized(const char *key)
|
|||||||
const char *
|
const char *
|
||||||
option_get_canonical_name(const char *key)
|
option_get_canonical_name(const char *key)
|
||||||
{
|
{
|
||||||
config_var_t *var = config_find_option(&config_format, key);
|
config_var_t *var = config_find_option(&options_format, key);
|
||||||
return var->name;
|
return var->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -834,7 +847,7 @@ option_get_canonical_name(const char *key)
|
|||||||
config_line_t *
|
config_line_t *
|
||||||
option_get_assignment(or_options_t *options, const char *key)
|
option_get_assignment(or_options_t *options, const char *key)
|
||||||
{
|
{
|
||||||
return get_assigned_option(&config_format, options, key);
|
return get_assigned_option(&options_format, options, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static config_line_t *
|
static config_line_t *
|
||||||
@ -990,20 +1003,20 @@ int
|
|||||||
options_trial_assign(config_line_t *list, int reset)
|
options_trial_assign(config_line_t *list, int reset)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
or_options_t *trial_options = options_dup(&config_format, get_options());
|
or_options_t *trial_options = options_dup(&options_format, get_options());
|
||||||
|
|
||||||
if ((r=config_assign(&config_format, trial_options, list, reset)) < 0) {
|
if ((r=config_assign(&options_format, trial_options, list, reset)) < 0) {
|
||||||
config_free(&config_format, trial_options);
|
config_free(&options_format, trial_options);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options_validate(trial_options) < 0) {
|
if (options_validate(trial_options) < 0) {
|
||||||
config_free(&config_format, trial_options);
|
config_free(&options_format, trial_options);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options_transition_allowed(get_options(), trial_options) < 0) {
|
if (options_transition_allowed(get_options(), trial_options) < 0) {
|
||||||
config_free(&config_format, trial_options);
|
config_free(&options_format, trial_options);
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1320,7 +1333,7 @@ options_dup(config_format_t *fmt, or_options_t *old)
|
|||||||
void
|
void
|
||||||
options_init(or_options_t *options)
|
options_init(or_options_t *options)
|
||||||
{
|
{
|
||||||
config_init(&config_format, options);
|
config_init(&options_format, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DOCDOC */
|
/* DOCDOC */
|
||||||
@ -1347,7 +1360,8 @@ config_dump(config_format_t *fmt, void *options, int minimal)
|
|||||||
or_options_t *defaults;
|
or_options_t *defaults;
|
||||||
config_line_t *line;
|
config_line_t *line;
|
||||||
char *result;
|
char *result;
|
||||||
int i, j;
|
int i;
|
||||||
|
const char *desc;
|
||||||
|
|
||||||
defaults = config_alloc(fmt);
|
defaults = config_alloc(fmt);
|
||||||
config_init(fmt, defaults);
|
config_init(fmt, defaults);
|
||||||
@ -1364,15 +1378,13 @@ config_dump(config_format_t *fmt, void *options, int minimal)
|
|||||||
if (minimal && option_is_same(fmt, options, defaults, fmt->vars[i].name))
|
if (minimal && option_is_same(fmt, options, defaults, fmt->vars[i].name))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (j=0; fmt->descriptions[j].name; ++j) {
|
|
||||||
if (!strcasecmp(fmt->vars[i].name, fmt->descriptions[j].name)) {
|
desc = config_find_description(fmt, fmt->vars[i].name);
|
||||||
const char *desc = fmt->descriptions[j].description;
|
if (desc) {
|
||||||
size_t len = strlen(desc)+8;
|
size_t len = strlen(desc)+8;
|
||||||
char *tmp = tor_malloc(len);
|
char *tmp = tor_malloc(len);
|
||||||
tor_snprintf(tmp, len, "# %s\n",desc);
|
tor_snprintf(tmp, len, "# %s\n",desc);
|
||||||
smartlist_add(elements, tmp);
|
smartlist_add(elements, tmp);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
line = get_assigned_option(fmt, options, fmt->vars[i].name);
|
line = get_assigned_option(fmt, options, fmt->vars[i].name);
|
||||||
@ -1402,7 +1414,7 @@ config_dump(config_format_t *fmt, void *options, int minimal)
|
|||||||
char *
|
char *
|
||||||
options_dump(or_options_t *options, int minimal)
|
options_dump(or_options_t *options, int minimal)
|
||||||
{
|
{
|
||||||
return config_dump(&config_format, options, minimal);
|
return config_dump(&options_format, options, minimal);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -2053,7 +2065,7 @@ options_init_from_torrc(int argc, char **argv)
|
|||||||
tor_free(cf);
|
tor_free(cf);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
goto err;
|
goto err;
|
||||||
retval = config_assign(&config_format, newoptions, cl, 0);
|
retval = config_assign(&options_format, newoptions, cl, 0);
|
||||||
config_free_lines(cl);
|
config_free_lines(cl);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
goto err;
|
goto err;
|
||||||
@ -2061,7 +2073,7 @@ options_init_from_torrc(int argc, char **argv)
|
|||||||
|
|
||||||
/* Go through command-line variables too */
|
/* Go through command-line variables too */
|
||||||
cl = config_get_commandlines(argc,argv);
|
cl = config_get_commandlines(argc,argv);
|
||||||
retval = config_assign(&config_format, newoptions,cl,0);
|
retval = config_assign(&options_format, newoptions,cl,0);
|
||||||
config_free_lines(cl);
|
config_free_lines(cl);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
goto err;
|
goto err;
|
||||||
@ -2083,7 +2095,7 @@ options_init_from_torrc(int argc, char **argv)
|
|||||||
return 0;
|
return 0;
|
||||||
err:
|
err:
|
||||||
tor_free(fname);
|
tor_free(fname);
|
||||||
config_free(&config_format, newoptions);
|
config_free(&options_format, newoptions);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3050,6 +3062,54 @@ or_state_save(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** DOCDOC */
|
||||||
|
int
|
||||||
|
config_getinfo_helper(const char *question, char **answer)
|
||||||
|
{
|
||||||
|
if (!strcmp(question, "config/names")) {
|
||||||
|
smartlist_t *sl = smartlist_create();
|
||||||
|
int i;
|
||||||
|
for (i = 0; _option_vars[i].name; ++i) {
|
||||||
|
config_var_t *var = &_option_vars[i];
|
||||||
|
const char *type, *desc;
|
||||||
|
char *line;
|
||||||
|
size_t len;
|
||||||
|
desc = config_find_description(&options_format, var->name);
|
||||||
|
switch (var->type) {
|
||||||
|
case CONFIG_TYPE_STRING: type = "String"; break;
|
||||||
|
case CONFIG_TYPE_UINT: type = "Integer"; break;
|
||||||
|
case CONFIG_TYPE_INTERVAL: type = "TimeInterval"; break;
|
||||||
|
case CONFIG_TYPE_MEMUNIT: type = "DataSize"; break;
|
||||||
|
case CONFIG_TYPE_DOUBLE: type = "Float"; break;
|
||||||
|
case CONFIG_TYPE_BOOL: type = "Boolean"; break;
|
||||||
|
case CONFIG_TYPE_ISOTIME: type = "Time"; break;
|
||||||
|
case CONFIG_TYPE_CSV: type = "CommaList"; break;
|
||||||
|
case CONFIG_TYPE_LINELIST: type = "LineList"; break;
|
||||||
|
case CONFIG_TYPE_LINELIST_S: type = "Dependant"; break;
|
||||||
|
case CONFIG_TYPE_LINELIST_V: type = "Virtual"; break;
|
||||||
|
default:
|
||||||
|
case CONFIG_TYPE_OBSOLETE:
|
||||||
|
type = NULL; break;
|
||||||
|
}
|
||||||
|
if (!type)
|
||||||
|
continue;
|
||||||
|
len = strlen(var->name)+strlen(type)+16;
|
||||||
|
if (desc)
|
||||||
|
len += strlen(desc);
|
||||||
|
line = tor_malloc(len);
|
||||||
|
if (desc)
|
||||||
|
tor_snprintf(line, len, "%s %s %s\n",var->name,type,desc);
|
||||||
|
else
|
||||||
|
tor_snprintf(line, len, "%s %s\n",var->name,type);
|
||||||
|
smartlist_add(sl, line);
|
||||||
|
}
|
||||||
|
*answer = smartlist_join_strings(sl, "", 0, NULL);
|
||||||
|
SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
|
||||||
|
smartlist_free(sl);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/** Dump the version of every file to the log. */
|
/** Dump the version of every file to the log. */
|
||||||
static void
|
static void
|
||||||
print_cvs_version(void)
|
print_cvs_version(void)
|
||||||
|
@ -1112,6 +1112,34 @@ handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** DOCDOC */
|
||||||
|
static char *
|
||||||
|
list_getinfo_options(void)
|
||||||
|
{
|
||||||
|
return tor_strdup(
|
||||||
|
"accounting/bytes Number of bytes read/written so far in interval.\n"
|
||||||
|
"accounting/bytes-left Number of bytes left to read/write in interval.\n"
|
||||||
|
"accounting/enabled Is accounting currently enabled?\n"
|
||||||
|
"accounting/hibernating Are we hibernating or awake?\n"
|
||||||
|
"accounting/interval-end Time when interval ends.\n"
|
||||||
|
"accounting/interval-start Time when interval starts.\n"
|
||||||
|
"accounting/interval-wake Time to wake up in this interval.\n"
|
||||||
|
"addr-mappings/all All current remapped addresses.\n"
|
||||||
|
"addr-mappings/cache Addresses remapped by DNS cache.\n"
|
||||||
|
"addr-mappings/configl Addresses remapped from configuration options.\n"
|
||||||
|
"addr-mappings/control Addresses remapped by a controller.\n"
|
||||||
|
"circuit-status Status of each current circuit.\n"
|
||||||
|
"config/names List of configuration options, types, and documentation.\n"
|
||||||
|
"desc/id/* Server descriptor by hex ID\n"
|
||||||
|
"desc/name/* Server descriptor by nickname.\n"
|
||||||
|
"helper-nodes Which nodes will we use as helpers?\n"
|
||||||
|
"info/names List of GETINFO options, types, and documentation.\n"
|
||||||
|
"network-status List of hex IDs, nicknames, server statuses.\n"
|
||||||
|
"orconn-status Status of each current OR connection.\n"
|
||||||
|
"stream-status Status of each current application stream.\n"
|
||||||
|
"version The current version of Tor.\n");
|
||||||
|
}
|
||||||
|
|
||||||
/** Lookup the 'getinfo' entry <b>question</b>, and return
|
/** Lookup the 'getinfo' entry <b>question</b>, and return
|
||||||
* the answer in <b>*answer</b> (or NULL if key not recognized).
|
* the answer in <b>*answer</b> (or NULL if key not recognized).
|
||||||
* Return 0 if success, or -1 if internal error. */
|
* Return 0 if success, or -1 if internal error. */
|
||||||
@ -1123,6 +1151,12 @@ handle_getinfo_helper(const char *question, char **answer)
|
|||||||
*answer = tor_strdup(VERSION);
|
*answer = tor_strdup(VERSION);
|
||||||
} else if (!strcmpstart(question, "accounting/")) {
|
} else if (!strcmpstart(question, "accounting/")) {
|
||||||
return accounting_getinfo_helper(question, answer);
|
return accounting_getinfo_helper(question, answer);
|
||||||
|
} else if (!strcmpstart(question, "helper-nodes")) {
|
||||||
|
return helper_nodes_getinfo_helper(question, answer);
|
||||||
|
} else if (!strcmpstart(question, "config/")) {
|
||||||
|
return config_getinfo_helper(question, answer);
|
||||||
|
} else if (!strcmp(question, "info/names")) {
|
||||||
|
*answer = list_getinfo_options();
|
||||||
} else if (!strcmpstart(question, "desc/id/")) {
|
} else if (!strcmpstart(question, "desc/id/")) {
|
||||||
routerinfo_t *ri = router_get_by_hexdigest(question+strlen("desc/id/"));
|
routerinfo_t *ri = router_get_by_hexdigest(question+strlen("desc/id/"));
|
||||||
if (ri && ri->signed_descriptor)
|
if (ri && ri->signed_descriptor)
|
||||||
|
@ -1279,6 +1279,7 @@ void helper_node_set_status(const char *digest, int succeeded);
|
|||||||
void helper_nodes_set_status_from_directory(void);
|
void helper_nodes_set_status_from_directory(void);
|
||||||
int helper_nodes_update_state(or_state_t *state);
|
int helper_nodes_update_state(or_state_t *state);
|
||||||
int helper_nodes_parse_state(or_state_t *state, int set, const char **err);
|
int helper_nodes_parse_state(or_state_t *state, int set, const char **err);
|
||||||
|
int helper_nodes_getinfo_helper(const char *question, char **answer);
|
||||||
|
|
||||||
/********************************* circuitlist.c ***********************/
|
/********************************* circuitlist.c ***********************/
|
||||||
|
|
||||||
@ -1372,6 +1373,8 @@ or_state_t *get_or_state(void);
|
|||||||
int or_state_load(void);
|
int or_state_load(void);
|
||||||
int or_state_save(void);
|
int or_state_save(void);
|
||||||
|
|
||||||
|
int config_getinfo_helper(const char *question, char **answer);
|
||||||
|
|
||||||
/********************************* connection.c ***************************/
|
/********************************* connection.c ***************************/
|
||||||
|
|
||||||
const char *conn_type_to_string(int type);
|
const char *conn_type_to_string(int type);
|
||||||
|
Loading…
Reference in New Issue
Block a user