Merge branch 'microdesc-use-v2-squashed'

This commit is contained in:
Nick Mathewson 2011-05-05 21:01:03 -04:00
commit ad35b8f40d
17 changed files with 338 additions and 224 deletions

10
changes/microdesc_use Normal file
View File

@ -0,0 +1,10 @@
o Major features
- Clients can now use microdescriptors instead of regular descriptors
to build circuits. Microdescriptors are authority-generated and
-authenticated summaries of regular descriptors' contents, designed
to change very rarely. This feature is designed to save bandwidth,
especially for clients on slow internet connections. It's off
by default for now, since nearly no caches support it, but it will
be on-by-default for clients in a future version. You can use the
UseMicrodescriptors option to turn it on.

View File

@ -4649,7 +4649,7 @@ retry_bridge_descriptor_fetch_directly(const char *digest)
void
fetch_bridge_descriptors(or_options_t *options, time_t now)
{
int num_bridge_auths = get_n_authorities(BRIDGE_AUTHORITY);
int num_bridge_auths = get_n_authorities(BRIDGE_DIRINFO);
int ask_bridge_directly;
int can_use_bridge_authority;

View File

@ -49,6 +49,8 @@ typedef enum config_type_t {
CONFIG_TYPE_MEMUNIT, /**< A number of bytes, with optional units*/
CONFIG_TYPE_DOUBLE, /**< A floating-point value */
CONFIG_TYPE_BOOL, /**< A boolean value, expressed as 0 or 1. */
CONFIG_TYPE_AUTOBOOL, /**< A boolean+auto value, expressed 0 for false,
* 1 for true, and -1 for auto */
CONFIG_TYPE_ISOTIME, /**< An ISO-formatted time relative to GMT. */
CONFIG_TYPE_CSV, /**< A list of strings, separated by commas and
* optional whitespace. */
@ -338,7 +340,7 @@ static config_var_t _option_vars[] = {
V(RecommendedClientVersions, LINELIST, NULL),
V(RecommendedServerVersions, LINELIST, NULL),
OBSOLETE("RedirectExit"),
V(RefuseUnknownExits, STRING, "auto"),
V(RefuseUnknownExits, AUTOBOOL, "auto"),
V(RejectPlaintextPorts, CSV, ""),
V(RelayBandwidthBurst, MEMUNIT, "0"),
V(RelayBandwidthRate, MEMUNIT, "0"),
@ -379,6 +381,7 @@ static config_var_t _option_vars[] = {
V(UpdateBridgesFromAuthority, BOOL, "0"),
V(UseBridges, BOOL, "0"),
V(UseEntryGuards, BOOL, "1"),
V(UseMicrodescriptors, AUTOBOOL, "0"),
V(User, STRING, NULL),
VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
VAR("V2AuthoritativeDirectory",BOOL, V2AuthoritativeDir, "0"),
@ -559,7 +562,7 @@ static void config_register_addressmaps(or_options_t *options);
static int parse_bridge_line(const char *line, int validate_only);
static int parse_dir_server_line(const char *line,
authority_type_t required_type,
dirinfo_type_t required_type,
int validate_only);
static int validate_data_directory(or_options_t *options);
static int write_configuration_file(const char *fname, or_options_t *options);
@ -799,7 +802,7 @@ escaped_safe_str(const char *address)
/** Add the default directory authorities directly into the trusted dir list,
* but only add them insofar as they share bits with <b>type</b>. */
static void
add_default_trusted_dir_authorities(authority_type_t type)
add_default_trusted_dir_authorities(dirinfo_type_t type)
{
int i;
const char *dirservers[] = {
@ -873,16 +876,16 @@ validate_dir_authorities(or_options_t *options, or_options_t *old_options)
/* Now go through the four ways you can configure an alternate
* set of directory authorities, and make sure none are broken. */
for (cl = options->DirServers; cl; cl = cl->next)
if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next)
if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
for (cl = options->AlternateDirAuthority; cl; cl = cl->next)
if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
for (cl = options->AlternateHSAuthority; cl; cl = cl->next)
if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
return 0;
}
@ -913,27 +916,28 @@ consider_adding_dir_authorities(or_options_t *options,
if (!options->DirServers) {
/* then we may want some of the defaults */
authority_type_t type = NO_AUTHORITY;
dirinfo_type_t type = NO_DIRINFO;
if (!options->AlternateBridgeAuthority)
type |= BRIDGE_AUTHORITY;
type |= BRIDGE_DIRINFO;
if (!options->AlternateDirAuthority)
type |= V1_AUTHORITY | V2_AUTHORITY | V3_AUTHORITY;
type |= V1_DIRINFO | V2_DIRINFO | V3_DIRINFO | EXTRAINFO_DIRINFO |
MICRODESC_DIRINFO;
if (!options->AlternateHSAuthority)
type |= HIDSERV_AUTHORITY;
type |= HIDSERV_DIRINFO;
add_default_trusted_dir_authorities(type);
}
for (cl = options->DirServers; cl; cl = cl->next)
if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next)
if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
for (cl = options->AlternateDirAuthority; cl; cl = cl->next)
if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
for (cl = options->AlternateHSAuthority; cl; cl = cl->next)
if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
return 0;
}
@ -1271,18 +1275,6 @@ options_act(or_options_t *old_options)
connection_bucket_init();
#endif
/* parse RefuseUnknownExits tristate */
if (!strcmp(options->RefuseUnknownExits, "0"))
options->RefuseUnknownExits_ = 0;
else if (!strcmp(options->RefuseUnknownExits, "1"))
options->RefuseUnknownExits_ = 1;
else if (!strcmp(options->RefuseUnknownExits, "auto"))
options->RefuseUnknownExits_ = -1;
else {
/* Should have caught this in options_validate */
return -1;
}
/* Change the cell EWMA settings */
cell_ewma_set_scale_factor(options, networkstatus_get_latest_consensus());
@ -1788,6 +1780,20 @@ config_assign_value(config_format_t *fmt, or_options_t *options,
*(int *)lvalue = i;
break;
case CONFIG_TYPE_AUTOBOOL:
if (!strcmp(c->value, "auto"))
*(int *)lvalue = -1;
else if (!strcmp(c->value, "0"))
*(int *)lvalue = 0;
else if (!strcmp(c->value, "1"))
*(int *)lvalue = 1;
else {
tor_asprintf(msg, "Boolean '%s %s' expects 0, 1, or 'auto'.",
c->key, c->value);
return -1;
}
break;
case CONFIG_TYPE_STRING:
case CONFIG_TYPE_FILENAME:
tor_free(*(char **)lvalue);
@ -2068,6 +2074,14 @@ get_assigned_option(config_format_t *fmt, void *options,
tor_asprintf(&result->value, "%f", *(double*)value);
escape_val = 0; /* Can't need escape. */
break;
case CONFIG_TYPE_AUTOBOOL:
if (*(int*)value == -1) {
result->value = tor_strdup("auto");
escape_val = 0;
break;
}
/* fall through */
case CONFIG_TYPE_BOOL:
result->value = tor_strdup(*(int*)value ? "1" : "0");
escape_val = 0; /* Can't need escape. */
@ -2285,6 +2299,9 @@ option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var)
case CONFIG_TYPE_BOOL:
*(int*)lvalue = 0;
break;
case CONFIG_TYPE_AUTOBOOL:
*(int*)lvalue = -1;
break;
case CONFIG_TYPE_MEMUNIT:
*(uint64_t*)lvalue = 0;
break;
@ -2833,24 +2850,24 @@ static int
compute_publishserverdescriptor(or_options_t *options)
{
smartlist_t *list = options->PublishServerDescriptor;
authority_type_t *auth = &options->_PublishServerDescriptor;
*auth = NO_AUTHORITY;
dirinfo_type_t *auth = &options->_PublishServerDescriptor;
*auth = NO_DIRINFO;
if (!list) /* empty list, answer is none */
return 0;
SMARTLIST_FOREACH(list, const char *, string, {
if (!strcasecmp(string, "v1"))
*auth |= V1_AUTHORITY;
*auth |= V1_DIRINFO;
else if (!strcmp(string, "1"))
if (options->BridgeRelay)
*auth |= BRIDGE_AUTHORITY;
*auth |= BRIDGE_DIRINFO;
else
*auth |= V2_AUTHORITY | V3_AUTHORITY;
*auth |= V2_DIRINFO | V3_DIRINFO;
else if (!strcasecmp(string, "v2"))
*auth |= V2_AUTHORITY;
*auth |= V2_DIRINFO;
else if (!strcasecmp(string, "v3"))
*auth |= V3_AUTHORITY;
*auth |= V3_DIRINFO;
else if (!strcasecmp(string, "bridge"))
*auth |= BRIDGE_AUTHORITY;
*auth |= BRIDGE_DIRINFO;
else if (!strcasecmp(string, "hidserv"))
log_warn(LD_CONFIG,
"PublishServerDescriptor hidserv is invalid. See "
@ -3014,12 +3031,6 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("Failed to resolve/guess local address. See logs for details.");
}
if (strcmp(options->RefuseUnknownExits, "0") &&
strcmp(options->RefuseUnknownExits, "1") &&
strcmp(options->RefuseUnknownExits, "auto")) {
REJECT("RefuseUnknownExits must be 0, 1, or auto");
}
#ifndef MS_WINDOWS
if (options->RunAsDaemon && torrc_fname && path_is_relative(torrc_fname))
REJECT("Can't use a relative path to torrc when RunAsDaemon is set.");
@ -3302,9 +3313,9 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
if ((options->BridgeRelay
|| options->_PublishServerDescriptor & BRIDGE_AUTHORITY)
|| options->_PublishServerDescriptor & BRIDGE_DIRINFO)
&& (options->_PublishServerDescriptor
& (V1_AUTHORITY|V2_AUTHORITY|V3_AUTHORITY))) {
& (V1_DIRINFO|V2_DIRINFO|V3_DIRINFO))) {
REJECT("Bridges are not supposed to publish router descriptors to the "
"directory authorities. Please correct your "
"PublishServerDescriptor line.");
@ -4543,7 +4554,7 @@ parse_bridge_line(const char *line, int validate_only)
* bits it's missing) as a valid authority. Return 0 on success,
* or -1 if the line isn't well-formed or if we can't add it. */
static int
parse_dir_server_line(const char *line, authority_type_t required_type,
parse_dir_server_line(const char *line, dirinfo_type_t required_type,
int validate_only)
{
smartlist_t *items = NULL;
@ -4552,7 +4563,7 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
uint16_t dir_port = 0, or_port = 0;
char digest[DIGEST_LEN];
char v3_digest[DIGEST_LEN];
authority_type_t type = V2_AUTHORITY;
dirinfo_type_t type = V2_DIRINFO;
int is_not_hidserv_authority = 0, is_not_v2_authority = 0;
items = smartlist_create();
@ -4573,13 +4584,13 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
if (TOR_ISDIGIT(flag[0]))
break;
if (!strcasecmp(flag, "v1")) {
type |= (V1_AUTHORITY | HIDSERV_AUTHORITY);
type |= (V1_DIRINFO | HIDSERV_DIRINFO);
} else if (!strcasecmp(flag, "hs")) {
type |= HIDSERV_AUTHORITY;
type |= HIDSERV_DIRINFO;
} else if (!strcasecmp(flag, "no-hs")) {
is_not_hidserv_authority = 1;
} else if (!strcasecmp(flag, "bridge")) {
type |= BRIDGE_AUTHORITY;
type |= BRIDGE_DIRINFO;
} else if (!strcasecmp(flag, "no-v2")) {
is_not_v2_authority = 1;
} else if (!strcasecmpstart(flag, "orport=")) {
@ -4596,7 +4607,7 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
log_warn(LD_CONFIG, "Bad v3 identity digest '%s' on DirServer line",
flag);
} else {
type |= V3_AUTHORITY;
type |= V3_DIRINFO|EXTRAINFO_DIRINFO|MICRODESC_DIRINFO;
}
} else {
log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirServer line",
@ -4606,9 +4617,9 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
smartlist_del_keeporder(items, 0);
}
if (is_not_hidserv_authority)
type &= ~HIDSERV_AUTHORITY;
type &= ~HIDSERV_DIRINFO;
if (is_not_v2_authority)
type &= ~V2_AUTHORITY;
type &= ~V2_DIRINFO;
if (smartlist_len(items) < 2) {
log_warn(LD_CONFIG, "Too few arguments to DirServer line.");
@ -5408,6 +5419,7 @@ getinfo_helper_config(control_connection_t *conn,
case CONFIG_TYPE_MEMUNIT: type = "DataSize"; break;
case CONFIG_TYPE_DOUBLE: type = "Float"; break;
case CONFIG_TYPE_BOOL: type = "Boolean"; break;
case CONFIG_TYPE_AUTOBOOL: type = "Boolean+Auto"; break;
case CONFIG_TYPE_ISOTIME: type = "Time"; break;
case CONFIG_TYPE_ROUTERSET: type = "RouterList"; break;
case CONFIG_TYPE_CSV: type = "CommaList"; break;

View File

@ -1847,7 +1847,7 @@ getinfo_helper_events(control_connection_t *control_conn,
} else if (!strcmp(question, "status/version/num-versioning") ||
!strcmp(question, "status/version/num-concurring")) {
char s[33];
tor_snprintf(s, sizeof(s), "%d", get_n_authorities(V3_AUTHORITY));
tor_snprintf(s, sizeof(s), "%d", get_n_authorities(V3_DIRINFO));
*answer = tor_strdup(s);
log_warn(LD_GENERAL, "%s is deprecated; it no longer gives useful "
"information", question);

View File

@ -147,21 +147,22 @@ purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
return 1;
}
/** Return a newly allocated string describing <b>auth</b>. */
char *
authority_type_to_string(authority_type_t auth)
/** Return a newly allocated string describing <b>auth</b>. Only describes
* authority features. */
static char *
authdir_type_to_string(dirinfo_type_t auth)
{
char *result;
smartlist_t *lst = smartlist_create();
if (auth & V1_AUTHORITY)
if (auth & V1_DIRINFO)
smartlist_add(lst, (void*)"V1");
if (auth & V2_AUTHORITY)
if (auth & V2_DIRINFO)
smartlist_add(lst, (void*)"V2");
if (auth & V3_AUTHORITY)
if (auth & V3_DIRINFO)
smartlist_add(lst, (void*)"V3");
if (auth & BRIDGE_AUTHORITY)
if (auth & BRIDGE_DIRINFO)
smartlist_add(lst, (void*)"Bridge");
if (auth & HIDSERV_AUTHORITY)
if (auth & HIDSERV_DIRINFO)
smartlist_add(lst, (void*)"Hidden service");
if (smartlist_len(lst)) {
result = smartlist_join_strings(lst, ", ", 0, NULL);
@ -280,7 +281,7 @@ directories_have_accepted_server_descriptor(void)
*/
void
directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
authority_type_t type,
dirinfo_type_t type,
const char *payload,
size_t payload_len, size_t extrainfo_len)
{
@ -328,7 +329,7 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
NULL, payload, upload_len, 0);
} SMARTLIST_FOREACH_END(ds);
if (!found) {
char *s = authority_type_to_string(type);
char *s = authdir_type_to_string(type);
log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
"of type '%s', but no authorities of that type listed!", s);
tor_free(s);
@ -349,37 +350,37 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
or_options_t *options = get_options();
int prefer_authority = directory_fetches_from_authorities(options);
int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
authority_type_t type;
dirinfo_type_t type;
time_t if_modified_since = 0;
/* FFFF we could break this switch into its own function, and call
* it elsewhere in directory.c. -RD */
switch (dir_purpose) {
case DIR_PURPOSE_FETCH_EXTRAINFO:
type = EXTRAINFO_CACHE |
(router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
V3_AUTHORITY);
type = EXTRAINFO_DIRINFO |
(router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
V3_DIRINFO);
break;
case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
type = V2_AUTHORITY;
type = V2_DIRINFO;
break;
case DIR_PURPOSE_FETCH_SERVERDESC:
type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
V3_AUTHORITY);
type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
V3_DIRINFO);
break;
case DIR_PURPOSE_FETCH_RENDDESC:
type = HIDSERV_AUTHORITY;
type = HIDSERV_DIRINFO;
break;
case DIR_PURPOSE_FETCH_STATUS_VOTE:
case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
type = V3_AUTHORITY;
type = V3_DIRINFO;
break;
case DIR_PURPOSE_FETCH_CONSENSUS:
case DIR_PURPOSE_FETCH_CERTIFICATE:
type = V3_AUTHORITY;
type = V3_DIRINFO;
break;
case DIR_PURPOSE_FETCH_MICRODESC:
type = V3_AUTHORITY;
type = MICRODESC_DIRINFO;
break;
default:
log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
@ -407,11 +408,11 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
}
}
if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
if (!options->FetchServerDescriptors && type != HIDSERV_DIRINFO)
return;
if (!get_via_tor) {
if (options->UseBridges && type != BRIDGE_AUTHORITY) {
if (options->UseBridges && type != BRIDGE_DIRINFO) {
/* want to ask a running bridge for which we have a descriptor. */
/* XXX023 we assume that all of our bridges can answer any
* possible directory question. This won't be true forever. -RD */
@ -435,7 +436,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
"nodes are available yet.");
return;
} else {
if (prefer_authority || type == BRIDGE_AUTHORITY) {
if (prefer_authority || type == BRIDGE_DIRINFO) {
/* only ask authdirservers, and don't ask myself */
rs = router_pick_trusteddirserver(type, pds_flags);
if (rs == NULL && (pds_flags & (PDS_NO_EXISTING_SERVERDESC_FETCH|
@ -457,7 +458,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
}
}
}
if (!rs && type != BRIDGE_AUTHORITY) {
if (!rs && type != BRIDGE_DIRINFO) {
/* anybody with a non-zero dirport will do */
rs = router_pick_directory_server(type, pds_flags);
if (!rs) {
@ -474,7 +475,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
/* only ask hidserv authorities, any of them will do */
pds_flags |= PDS_IGNORE_FASCISTFIREWALL|PDS_ALLOW_SELF;
rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, pds_flags);
rs = router_pick_trusteddirserver(HIDSERV_DIRINFO, pds_flags);
} else {
/* anybody with a non-zero dirport will do. Disregard firewalls. */
pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
@ -520,7 +521,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose,
routerstatus_t *rs;
if (router_digest_is_me(ds->digest))
continue;
if (!(ds->type & V3_AUTHORITY))
if (!(ds->type & V3_DIRINFO))
continue;
rs = &ds->fake_status;
directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose,
@ -1047,7 +1048,7 @@ directory_get_consensus_url(int supports_conditional_consensus,
trusted_dir_server_t *, ds,
{
char *hex;
if (!(ds->type & V3_AUTHORITY))
if (!(ds->type & V3_DIRINFO))
continue;
hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1);

View File

@ -13,9 +13,8 @@
#define _TOR_DIRECTORY_H
int directories_have_accepted_server_descriptor(void);
char *authority_type_to_string(authority_type_t auth);
void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
authority_type_t type, const char *payload,
dirinfo_type_t type, const char *payload,
size_t payload_len, size_t extrainfo_len);
void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
const char *resource,

View File

@ -1552,11 +1552,11 @@ dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
cached_dir_t *auth_src,
time_t dirty, cached_dir_t *(*regenerate)(void),
const char *name,
authority_type_t auth_type)
dirinfo_type_t auth_type)
{
or_options_t *options = get_options();
int authority = (auth_type == V1_AUTHORITY && authdir_mode_v1(options)) ||
(auth_type == V2_AUTHORITY && authdir_mode_v2(options));
int authority = (auth_type == V1_DIRINFO && authdir_mode_v1(options)) ||
(auth_type == V2_DIRINFO && authdir_mode_v2(options));
if (!authority || authdir_mode_bridge(options)) {
return cache_src;
@ -1585,7 +1585,7 @@ dirserv_get_directory(void)
return dirserv_pick_cached_dir_obj(cached_directory, the_directory,
the_directory_is_dirty,
dirserv_regenerate_directory,
"v1 server directory", V1_AUTHORITY);
"v1 server directory", V1_DIRINFO);
}
/** Only called by v1 auth dirservers.
@ -1678,7 +1678,7 @@ dirserv_get_runningrouters(void)
&cached_runningrouters, &the_runningrouters,
runningrouters_is_dirty,
generate_runningrouters,
"v1 network status list", V1_AUTHORITY);
"v1 network status list", V1_DIRINFO);
}
/** Return the latest downloaded consensus networkstatus in encoded, signed,
@ -2967,7 +2967,7 @@ dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
} else {
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
if (ds->type & V2_AUTHORITY)
if (ds->type & V2_DIRINFO)
smartlist_add(result, tor_memdup(ds->digest, DIGEST_LEN)));
}
smartlist_sort_digests(result);

View File

@ -2742,7 +2742,7 @@ dirvote_perform_vote(void)
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_VOTE,
ROUTER_PURPOSE_GENERAL,
V3_AUTHORITY,
V3_DIRINFO,
pending_vote->vote_body->dir,
pending_vote->vote_body->dir_len, 0);
log_notice(LD_DIR, "Vote posted.");
@ -2761,7 +2761,7 @@ dirvote_fetch_missing_votes(void)
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
{
if (!(ds->type & V3_AUTHORITY))
if (!(ds->type & V3_DIRINFO))
continue;
if (!dirvote_get_vote(ds->v3_identity_digest,
DGV_BY_ID|DGV_INCLUDE_PENDING)) {
@ -2874,7 +2874,7 @@ list_v3_auth_ids(void)
char *keys;
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
if ((ds->type & V3_AUTHORITY) &&
if ((ds->type & V3_DIRINFO) &&
!tor_digest_is_zero(ds->v3_identity_digest))
smartlist_add(known_v3_keys,
tor_strdup(hex_str(ds->v3_identity_digest, DIGEST_LEN))));
@ -3069,7 +3069,7 @@ dirvote_compute_consensuses(void)
if (!pending_vote_list)
pending_vote_list = smartlist_create();
n_voters = get_n_authorities(V3_AUTHORITY);
n_voters = get_n_authorities(V3_DIRINFO);
n_votes = smartlist_len(pending_vote_list);
if (n_votes <= n_voters/2) {
log_warn(LD_DIR, "We don't have enough votes to generate a consensus: "
@ -3208,7 +3208,7 @@ dirvote_compute_consensuses(void)
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_SIGNATURES,
ROUTER_PURPOSE_GENERAL,
V3_AUTHORITY,
V3_DIRINFO,
pending_consensus_signatures,
strlen(pending_consensus_signatures), 0);
log_notice(LD_DIR, "Signature(s) posted.");

View File

@ -872,13 +872,11 @@ directory_info_has_arrived(time_t now, int from_cache)
log(quiet ? LOG_INFO : LOG_NOTICE, LD_DIR,
"I learned some more directory information, but not enough to "
"build a circuit: %s", get_dir_info_status_string());
update_router_descriptor_downloads(now);
update_microdesc_downloads(now);
update_all_descriptor_downloads(now);
return;
} else {
if (directory_fetches_from_authorities(options)) {
update_router_descriptor_downloads(now);
update_microdesc_downloads(now);
update_all_descriptor_downloads(now);
}
/* if we have enough dir info, then update our guard status with
@ -1110,9 +1108,8 @@ run_scheduled_events(time_t now)
}
if (time_to_try_getting_descriptors < now) {
update_router_descriptor_downloads(now);
update_all_descriptor_downloads(now);
update_extrainfo_downloads(now);
update_microdesc_downloads(now);
if (options->UseBridges)
fetch_bridge_descriptors(options, now);
if (router_have_minimum_dir_info())

View File

@ -9,6 +9,7 @@
#include "networkstatus.h"
#include "nodelist.h"
#include "policies.h"
#include "router.h"
#include "routerlist.h"
#include "routerparse.h"
@ -251,6 +252,9 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache,
SMARTLIST_FOREACH(added, microdesc_t *, md, nodelist_add_microdesc(md));
}
if (smartlist_len(added))
router_dir_info_changed();
return added;
}
@ -570,6 +574,8 @@ microdesc_list_missing_digest256(networkstatus_t *ns, microdesc_cache_t *cache,
continue;
if (skip && digestmap_get(skip, rs->descriptor_digest))
continue;
if (tor_mem_is_zero(rs->descriptor_digest, DIGEST256_LEN))
continue; /* This indicates a bug somewhere XXXX023*/
/* XXXX Also skip if we're a noncache and wouldn't use this router.
* XXXX NM Microdesc
*/
@ -602,11 +608,8 @@ update_microdesc_downloads(time_t now)
if (!consensus)
return;
if (!directory_caches_dir_info(options)) {
/* Right now, only caches fetch microdescriptors.
* XXXX NM Microdescs */
if (!we_fetch_microdescriptors(options))
return;
}
pending = digestmap_new();
list_pending_microdesc_downloads(pending);
@ -647,3 +650,51 @@ update_microdescs_from_networkstatus(time_t now)
} SMARTLIST_FOREACH_END(rs);
}
/** Return true iff we should prefer to use microdescriptors rather than
* routerdescs for building circuits. */
int
we_use_microdescriptors_for_circuits(or_options_t *options)
{
int ret = options->UseMicrodescriptors;
if (ret == -1) {
/* UseMicrodescriptors is "auto"; we need to decide: */
#if 0
/* So we decide that we'll use microdescriptors iff we are not a server */
ret = ! server_mode(options);
#else
/* We don't use microdescs for now: not enough caches are running
* 0.2.3.1-alpha */
ret = 0;
#endif
}
return ret;
}
/** Return true iff we should try to download microdescriptors at all. */
int
we_fetch_microdescriptors(or_options_t *options)
{
if (directory_caches_dir_info(options))
return 1;
return we_use_microdescriptors_for_circuits(options);
}
/** Return true iff we should try to download router descriptors at all. */
int
we_fetch_router_descriptors(or_options_t *options)
{
if (directory_caches_dir_info(options))
return 1;
return ! we_use_microdescriptors_for_circuits(options);
}
/** Return the consensus flavor we actually want to use to build circuits. */
int
usable_consensus_flavor(void)
{
if (we_use_microdescriptors_for_circuits(get_options())) {
return FLAV_MICRODESC;
} else {
return FLAV_NS;
}
}

View File

@ -43,5 +43,10 @@ void microdesc_free_all(void);
void update_microdesc_downloads(time_t now);
void update_microdescs_from_networkstatus(time_t now);
int usable_consensus_flavor(void);
int we_fetch_microdescriptors(or_options_t *options);
int we_fetch_router_descriptors(or_options_t *options);
int we_use_microdescriptors_for_circuits(or_options_t *options);
#endif

View File

@ -50,7 +50,9 @@ static strmap_t *unnamed_server_map = NULL;
* of whichever type we are using for our own circuits. This will be the same
* as one of current_ns_consensus or current_md_consensus.
*/
#define current_consensus current_ns_consensus
#define current_consensus \
(we_use_microdescriptors_for_circuits(get_options()) ? \
current_md_consensus : current_ns_consensus)
/** Most recently received and validated v3 "ns"-flavored consensus network
* status. */
@ -482,7 +484,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus,
int n_bad = 0;
int n_unknown = 0;
int n_no_signature = 0;
int n_v3_authorities = get_n_authorities(V3_AUTHORITY);
int n_v3_authorities = get_n_authorities(V3_DIRINFO);
int n_required = n_v3_authorities/2 + 1;
smartlist_t *need_certs_from = smartlist_create();
smartlist_t *unrecognized = smartlist_create();
@ -553,7 +555,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus,
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
{
if ((ds->type & V3_AUTHORITY) &&
if ((ds->type & V3_DIRINFO) &&
!networkstatus_get_voter_by_id(consensus, ds->v3_identity_digest))
smartlist_add(missing_authorities, ds);
});
@ -736,7 +738,7 @@ router_set_networkstatus_v2(const char *s, time_t arrived_at,
base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN);
if (!(trusted_dir =
router_get_trusteddirserver_by_digest(ns->identity_digest)) ||
!(trusted_dir->type & V2_AUTHORITY)) {
!(trusted_dir->type & V2_DIRINFO)) {
log_info(LD_DIR, "Network status was signed, but not by an authoritative "
"directory we recognize.");
source_desc = fp;
@ -1130,7 +1132,7 @@ update_v2_networkstatus_cache_downloads(time_t now)
{
char resource[HEX_DIGEST_LEN+6]; /* fp/hexdigit.z\0 */
tor_addr_t addr;
if (!(ds->type & V2_AUTHORITY))
if (!(ds->type & V2_DIRINFO))
continue;
if (router_digest_is_me(ds->digest))
continue;
@ -1187,7 +1189,7 @@ we_want_to_fetch_flavor(or_options_t *options, int flavor)
}
/* Otherwise, we want the flavor only if we want to use it to build
* circuits. */
return (flavor == USABLE_CONSENSUS_FLAVOR);
return flavor == usable_consensus_flavor();
}
/** How many times will we try to fetch a consensus before we give up? */
@ -1392,7 +1394,7 @@ update_certificate_downloads(time_t now)
int
consensus_is_waiting_for_certs(void)
{
return consensus_waiting_for_certs[USABLE_CONSENSUS_FLAVOR].consensus
return consensus_waiting_for_certs[usable_consensus_flavor()].consensus
? 1 : 0;
}
@ -1621,7 +1623,7 @@ networkstatus_set_current_consensus(const char *consensus,
flavor = networkstatus_get_flavor_name(flav);
}
if (flav != USABLE_CONSENSUS_FLAVOR &&
if (flav != usable_consensus_flavor() &&
!directory_caches_dir_info(options)) {
/* This consensus is totally boring to us: we won't use it, and we won't
* serve it. Drop it. */
@ -1726,14 +1728,14 @@ networkstatus_set_current_consensus(const char *consensus,
}
}
if (!from_cache && flav == USABLE_CONSENSUS_FLAVOR)
if (!from_cache && flav == usable_consensus_flavor())
control_event_client_status(LOG_NOTICE, "CONSENSUS_ARRIVED");
/* Are we missing any certificates at all? */
if (r != 1 && dl_certs)
authority_certs_fetch_missing(c, now);
if (flav == USABLE_CONSENSUS_FLAVOR) {
if (flav == usable_consensus_flavor()) {
notify_control_networkstatus_changed(current_consensus, c);
}
if (flav == FLAV_NS) {
@ -1780,8 +1782,8 @@ networkstatus_set_current_consensus(const char *consensus,
download_status_failed(&consensus_dl_status[flav], 0);
}
if (flav == USABLE_CONSENSUS_FLAVOR) {
/* XXXXNM Microdescs: needs a non-ns variant. */
if (flav == usable_consensus_flavor()) {
/* XXXXNM Microdescs: needs a non-ns variant. ???? NM*/
update_consensus_networkstatus_fetch_time(now);
nodelist_set_consensus(current_consensus);

View File

@ -1641,6 +1641,9 @@ typedef struct routerstatus_t {
/** True iff this router is a version that, if it caches directory info,
* we can get v3 downloads from. */
unsigned int version_supports_v3_dir:1;
/** True iff this router is a version that, if it caches directory info,
* we can get microdescriptors from. */
unsigned int version_supports_microdesc_cache:1;
unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */
unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */
@ -1918,9 +1921,6 @@ typedef enum {
FLAV_MICRODESC = 1,
} consensus_flavor_t;
/** Which consensus flavor do we actually want to use to build circuits? */
#define USABLE_CONSENSUS_FLAVOR FLAV_NS
/** How many different consensus flavors are there? */
#define N_CONSENSUS_FLAVORS ((int)(FLAV_MICRODESC)+1)
@ -2090,24 +2090,33 @@ typedef struct authority_cert_t {
uint8_t is_cross_certified;
} authority_cert_t;
/** Bitfield enum type listing types of directory authority/directory
* server. */
/** Bitfield enum type listing types of information that directory authorities
* can be authoritative about, and that directory caches may or may not cache.
*
* Note that the granularity here is based on authority granularity and on
* cache capabilities. Thus, one particular bit may correspond in practice to
* a few types of directory info, so long as every authority that pronounces
* officially about one of the types prounounces officially about all of them,
* and so long as every cache that caches one of them caches all of them.
*/
typedef enum {
NO_AUTHORITY = 0,
NO_DIRINFO = 0,
/** Serves/signs v1 directory information: Big lists of routers, and short
* routerstatus documents. */
V1_AUTHORITY = 1 << 0,
V1_DIRINFO = 1 << 0,
/** Serves/signs v2 directory information: i.e. v2 networkstatus documents */
V2_AUTHORITY = 1 << 1,
V2_DIRINFO = 1 << 1,
/** Serves/signs v3 directory information: votes, consensuses, certs */
V3_AUTHORITY = 1 << 2,
V3_DIRINFO = 1 << 2,
/** Serves hidden service descriptors. */
HIDSERV_AUTHORITY = 1 << 3,
HIDSERV_DIRINFO = 1 << 3,
/** Serves bridge descriptors. */
BRIDGE_AUTHORITY = 1 << 4,
/** Serves extrainfo documents. (XXX Not precisely an authority type)*/
EXTRAINFO_CACHE = 1 << 5,
} authority_type_t;
BRIDGE_DIRINFO = 1 << 4,
/** Serves extrainfo documents. */
EXTRAINFO_DIRINFO=1 << 5,
/** Serves microdescriptors. */
MICRODESC_DIRINFO=1 << 6,
} dirinfo_type_t;
#define CRYPT_PATH_MAGIC 0x70127012u
@ -2641,8 +2650,8 @@ typedef struct {
/** To what authority types do we publish our descriptor? Choices are
* "v1", "v2", "v3", "bridge", or "". */
smartlist_t *PublishServerDescriptor;
/** An authority type, derived from PublishServerDescriptor. */
authority_type_t _PublishServerDescriptor;
/** A bitfield of authority types, derived from PublishServerDescriptor. */
dirinfo_type_t _PublishServerDescriptor;
/** Boolean: do we publish hidden service descriptors to the HS auths? */
int PublishHidServDescriptors;
int FetchServerDescriptors; /**< Do we fetch server descriptors as normal? */
@ -2669,12 +2678,10 @@ typedef struct {
uint64_t ConstrainedSockSize; /**< Size of constrained buffers. */
/** Whether we should drop exit streams from Tors that we don't know are
* relays. One of "0" (never refuse), "1" (always refuse), or "auto" (do
* relays. One of "0" (never refuse), "1" (always refuse), or "-1" (do
* what the consensus says, defaulting to 'refuse' if the consensus says
* nothing). */
char *RefuseUnknownExits;
/** Parsed version of RefuseUnknownExits. -1 for auto. */
int RefuseUnknownExits_;
int RefuseUnknownExits;
/** Application ports that require all nodes in circ to have sufficient
* uptime. */
@ -3044,6 +3051,10 @@ typedef struct {
* the defaults have changed. */
int _UsingTestNetworkDefaults;
/** If 1, we try to use microdescriptors to build circuits. If 0, we don't.
* If -1, Tor decides. */
int UseMicrodescriptors;
} or_options_t;
/** Persistent state for an onion router, as saved to disk. */
@ -3650,7 +3661,7 @@ typedef struct trusted_dir_server_t {
unsigned int has_accepted_serverdesc:1;
/** What kind of authority is this? (Bitfield.) */
authority_type_t type;
dirinfo_type_t type;
download_status_t v2_ns_dl_status; /**< Status of downloading this server's
* v2 network status. */

View File

@ -497,7 +497,7 @@ init_keys(void)
char v3_digest[20];
char *cp;
or_options_t *options = get_options();
authority_type_t type;
dirinfo_type_t type;
time_t now = time(NULL);
trusted_dir_server_t *ds;
int v3_digest_set = 0;
@ -697,11 +697,12 @@ init_keys(void)
}
/* 6b. [authdirserver only] add own key to approved directories. */
crypto_pk_get_digest(get_server_identity_key(), digest);
type = ((options->V1AuthoritativeDir ? V1_AUTHORITY : NO_AUTHORITY) |
(options->V2AuthoritativeDir ? V2_AUTHORITY : NO_AUTHORITY) |
(options->V3AuthoritativeDir ? V3_AUTHORITY : NO_AUTHORITY) |
(options->BridgeAuthoritativeDir ? BRIDGE_AUTHORITY : NO_AUTHORITY) |
(options->HSAuthoritativeDir ? HIDSERV_AUTHORITY : NO_AUTHORITY));
type = ((options->V1AuthoritativeDir ? V1_DIRINFO : NO_DIRINFO) |
(options->V2AuthoritativeDir ? V2_DIRINFO : NO_DIRINFO) |
(options->V3AuthoritativeDir ?
(V3_DIRINFO|MICRODESC_DIRINFO|EXTRAINFO_DIRINFO) : NO_DIRINFO) |
(options->BridgeAuthoritativeDir ? BRIDGE_DIRINFO : NO_DIRINFO) |
(options->HSAuthoritativeDir ? HIDSERV_DIRINFO : NO_DIRINFO));
ds = router_get_trusteddirserver_by_digest(digest);
if (!ds) {
@ -723,7 +724,7 @@ init_keys(void)
type, ds->type);
ds->type = type;
}
if (v3_digest_set && (ds->type & V3_AUTHORITY) &&
if (v3_digest_set && (ds->type & V3_DIRINFO) &&
memcmp(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) {
log_warn(LD_DIR, "V3 identity key does not match identity declared in "
"DirServer line. Adjusting.");
@ -910,7 +911,7 @@ router_orport_found_reachable(void)
if (!can_reach_or_port && me) {
log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from "
"the outside. Excellent.%s",
get_options()->_PublishServerDescriptor != NO_AUTHORITY ?
get_options()->_PublishServerDescriptor != NO_DIRINFO ?
" Publishing server descriptor." : "");
can_reach_or_port = 1;
mark_my_descriptor_dirty();
@ -1080,8 +1081,8 @@ public_server_mode(or_options_t *options)
int
should_refuse_unknown_exits(or_options_t *options)
{
if (options->RefuseUnknownExits_ != -1) {
return options->RefuseUnknownExits_;
if (options->RefuseUnknownExits != -1) {
return options->RefuseUnknownExits;
} else {
return networkstatus_get_param(NULL, "refuseunknownexits", 1, 0, 1);
}
@ -1135,7 +1136,7 @@ decide_if_publishable_server(void)
if (options->ClientOnly)
return 0;
if (options->_PublishServerDescriptor == NO_AUTHORITY)
if (options->_PublishServerDescriptor == NO_DIRINFO)
return 0;
if (!server_mode(options))
return 0;
@ -1195,7 +1196,7 @@ router_upload_dir_desc_to_dirservers(int force)
extrainfo_t *ei;
char *msg;
size_t desc_len, extra_len = 0, total_len;
authority_type_t auth = get_options()->_PublishServerDescriptor;
dirinfo_type_t auth = get_options()->_PublishServerDescriptor;
ri = router_get_my_routerinfo();
if (!ri) {
@ -1203,7 +1204,7 @@ router_upload_dir_desc_to_dirservers(int force)
return;
}
ei = router_get_my_extrainfo();
if (auth == NO_AUTHORITY)
if (auth == NO_DIRINFO)
return;
if (!force && !desc_needs_upload)
return;
@ -1220,7 +1221,7 @@ router_upload_dir_desc_to_dirservers(int force)
msg[desc_len+extra_len] = 0;
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_DIR,
(auth & BRIDGE_AUTHORITY) ?
(auth & BRIDGE_DIRINFO) ?
ROUTER_PURPOSE_BRIDGE :
ROUTER_PURPOSE_GENERAL,
auth, msg, desc_len, extra_len);

View File

@ -40,9 +40,9 @@
/* static function prototypes */
static const routerstatus_t *router_pick_directory_server_impl(
authority_type_t auth, int flags);
dirinfo_type_t auth, int flags);
static const routerstatus_t *router_pick_trusteddirserver_impl(
authority_type_t auth, int flags, int *n_busy_out);
dirinfo_type_t auth, int flags, int *n_busy_out);
static void mark_all_trusteddirservers_up(void);
static int router_nickname_matches(const routerinfo_t *router,
const char *nickname);
@ -56,6 +56,8 @@ static const char *signed_descriptor_get_body_impl(
int with_annotations);
static void list_pending_downloads(digestmap_t *result,
int purpose, const char *prefix);
static void launch_dummy_descriptor_download_as_needed(time_t now,
or_options_t *options);
DECLARE_TYPED_DIGESTMAP_FNS(sdmap_, digest_sd_map_t, signed_descriptor_t)
DECLARE_TYPED_DIGESTMAP_FNS(rimap_, digest_ri_map_t, routerinfo_t)
@ -97,7 +99,7 @@ static smartlist_t *warned_nicknames = NULL;
/** The last time we tried to download any routerdesc, or 0 for "never". We
* use this to rate-limit download attempts when the number of routerdescs to
* download is low. */
static time_t last_routerdesc_download_attempted = 0;
static time_t last_descriptor_download_attempted = 0;
/** When we last computed the weights to use for bandwidths on directory
* requests, what were the total weighted bandwidth, and our share of that
@ -109,7 +111,7 @@ static uint64_t sl_last_total_weighted_bw = 0,
/** Return the number of directory authorities whose type matches some bit set
* in <b>type</b> */
int
get_n_authorities(authority_type_t type)
get_n_authorities(dirinfo_type_t type)
{
int n = 0;
if (!trusted_dir_servers)
@ -120,7 +122,7 @@ get_n_authorities(authority_type_t type)
return n;
}
#define get_n_v2_authorities() get_n_authorities(V2_AUTHORITY)
#define get_n_v2_authorities() get_n_authorities(V2_DIRINFO)
/** Helper: Return the cert_list_t for an authority whose authority ID is
* <b>id_digest</b>, allocating a new list if necessary. */
@ -518,7 +520,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now)
}
SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, trusted_dir_server_t *, ds) {
int found = 0;
if (!(ds->type & V3_AUTHORITY))
if (!(ds->type & V3_DIRINFO))
continue;
if (smartlist_digest_isin(missing_digests, ds->v3_identity_digest))
continue;
@ -931,7 +933,7 @@ router_get_trusted_dir_servers(void)
* servers that have returned 503 recently.
*/
const routerstatus_t *
router_pick_directory_server(authority_type_t type, int flags)
router_pick_directory_server(dirinfo_type_t type, int flags)
{
const routerstatus_t *choice;
if (get_options()->PreferTunneledDirConns)
@ -976,7 +978,7 @@ router_get_my_share_of_directory_requests(double *v2_share_out,
/* XXXX This is a bit of a kludge */
if (rs->is_v2_dir) {
sl_last_total_weighted_bw = 0;
router_pick_directory_server(V2_AUTHORITY, pds_flags);
router_pick_directory_server(V2_DIRINFO, pds_flags);
if (sl_last_total_weighted_bw != 0) {
*v2_share_out = U64_TO_DBL(sl_last_weighted_bw_of_me) /
U64_TO_DBL(sl_last_total_weighted_bw);
@ -985,7 +987,7 @@ router_get_my_share_of_directory_requests(double *v2_share_out,
if (rs->version_supports_v3_dir) {
sl_last_total_weighted_bw = 0;
router_pick_directory_server(V3_AUTHORITY, pds_flags);
router_pick_directory_server(V3_DIRINFO, pds_flags);
if (sl_last_total_weighted_bw != 0) {
*v3_share_out = U64_TO_DBL(sl_last_weighted_bw_of_me) /
U64_TO_DBL(sl_last_total_weighted_bw);
@ -1026,7 +1028,7 @@ trusteddirserver_get_by_v3_auth_digest(const char *digest)
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
{
if (!memcmp(ds->v3_identity_digest, digest, DIGEST_LEN) &&
(ds->type & V3_AUTHORITY))
(ds->type & V3_DIRINFO))
return ds;
});
@ -1037,7 +1039,7 @@ trusteddirserver_get_by_v3_auth_digest(const char *digest)
* router_pick_directory_server.
*/
const routerstatus_t *
router_pick_trusteddirserver(authority_type_t type, int flags)
router_pick_trusteddirserver(dirinfo_type_t type, int flags)
{
const routerstatus_t *choice;
int busy = 0;
@ -1073,7 +1075,7 @@ router_pick_trusteddirserver(authority_type_t type, int flags)
* that we can use with BEGINDIR.
*/
static const routerstatus_t *
router_pick_directory_server_impl(authority_type_t type, int flags)
router_pick_directory_server_impl(dirinfo_type_t type, int flags)
{
or_options_t *options = get_options();
const node_t *result;
@ -1115,18 +1117,21 @@ router_pick_directory_server_impl(authority_type_t type, int flags)
continue;
if (requireother && router_digest_is_me(node->identity))
continue;
if (type & V3_AUTHORITY) {
if (type & V3_DIRINFO) {
if (!(status->version_supports_v3_dir ||
router_digest_is_trusted_dir_type(node->identity,
V3_AUTHORITY)))
V3_DIRINFO)))
continue;
}
is_trusted = router_digest_is_trusted_dir(node->identity);
if ((type & V2_AUTHORITY) && !(node->rs->is_v2_dir || is_trusted))
if ((type & V2_DIRINFO) && !(node->rs->is_v2_dir || is_trusted))
continue;
if ((type & EXTRAINFO_CACHE) &&
if ((type & EXTRAINFO_DIRINFO) &&
!router_supports_extrainfo(node->identity, 0))
continue;
if ((type & MICRODESC_DIRINFO) && !is_trusted &&
!node->rs->version_supports_microdesc_cache)
continue;
if (try_excluding && options->ExcludeNodes &&
routerset_contains_routerstatus(options->ExcludeNodes, status,
country)) {
@ -1192,7 +1197,7 @@ router_pick_directory_server_impl(authority_type_t type, int flags)
* are as for router_pick_directory_server_impl().
*/
static const routerstatus_t *
router_pick_trusteddirserver_impl(authority_type_t type, int flags,
router_pick_trusteddirserver_impl(dirinfo_type_t type, int flags,
int *n_busy_out)
{
or_options_t *options = get_options();
@ -1227,7 +1232,7 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags,
if (!d->is_running) continue;
if ((type & d->type) == 0)
continue;
if ((type & EXTRAINFO_CACHE) &&
if ((type & EXTRAINFO_DIRINFO) &&
!router_supports_extrainfo(d->digest, 1))
continue;
if (requireother && me && router_digest_is_me(d->digest))
@ -2443,23 +2448,11 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
#endif
}
/** Try to find a routerinfo for <b>digest</b>. If we don't have one,
* return 1. If we do, ask tor_version_as_new_as() for the answer.
*/
int
router_digest_version_as_new_as(const char *digest, const char *cutoff)
{
const routerinfo_t *router = router_get_by_id_digest(digest);
if (!router)
return 1;
return tor_version_as_new_as(router->platform, cutoff);
}
/** Return true iff <b>digest</b> is the digest of the identity key of a
* trusted directory matching at least one bit of <b>type</b>. If <b>type</b>
* is zero, any authority is okay. */
int
router_digest_is_trusted_dir_type(const char *digest, authority_type_t type)
router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type)
{
if (!trusted_dir_servers)
return 0;
@ -4000,6 +3993,16 @@ signed_desc_digest_is_recognized(signed_descriptor_t *desc)
return 0;
}
/** Update downloads for router descriptors and/or microdescriptors as
* appropriate. */
void
update_all_descriptor_downloads(time_t now)
{
update_router_descriptor_downloads(now);
update_microdesc_downloads(now);
launch_dummy_descriptor_download_as_needed(now, get_options());
}
/** Clear all our timeouts for fetching v2 and v3 directory stuff, and then
* give it all a try again. */
void
@ -4008,8 +4011,7 @@ routerlist_retry_directory_downloads(time_t now)
router_reset_status_download_failures();
router_reset_descriptor_download_failures();
update_networkstatus_downloads(now);
update_router_descriptor_downloads(now);
update_microdesc_downloads(now);
update_all_descriptor_downloads(now);
}
/** Return 1 if all running sufficiently-stable routers we can use will reject
@ -4049,7 +4051,7 @@ trusted_dir_server_t *
add_trusted_dir_server(const char *nickname, const char *address,
uint16_t dir_port, uint16_t or_port,
const char *digest, const char *v3_auth_digest,
authority_type_t type)
dirinfo_type_t type)
{
trusted_dir_server_t *ent;
uint32_t a;
@ -4084,7 +4086,7 @@ add_trusted_dir_server(const char *nickname, const char *address,
ent->is_running = 1;
ent->type = type;
memcpy(ent->digest, digest, DIGEST_LEN);
if (v3_auth_digest && (type & V3_AUTHORITY))
if (v3_auth_digest && (type & V3_DIRINFO))
memcpy(ent->v3_identity_digest, v3_auth_digest, DIGEST_LEN);
dlen = 64 + strlen(hostname) + (nickname?strlen(nickname):0);
@ -4163,7 +4165,7 @@ int
any_trusted_dir_is_v1_authority(void)
{
if (trusted_dir_servers)
return get_n_authorities(V1_AUTHORITY) > 0;
return get_n_authorities(V1_DIRINFO) > 0;
return 0;
}
@ -4363,15 +4365,15 @@ launch_descriptor_downloads(int purpose,
descname);
should_delay = 0;
} else {
should_delay = (last_routerdesc_download_attempted +
should_delay = (last_descriptor_download_attempted +
MAX_CLIENT_INTERVAL_WITHOUT_REQUEST) > now;
if (!should_delay && n_downloadable) {
if (last_routerdesc_download_attempted) {
if (last_descriptor_download_attempted) {
log_info(LD_DIR,
"There are not many downloadable %ss, but we've "
"been waiting long enough (%d seconds). Downloading.",
descname,
(int)(now-last_routerdesc_download_attempted));
(int)(now-last_descriptor_download_attempted));
} else {
log_info(LD_DIR,
"There are not many downloadable %ss, but we haven't "
@ -4434,7 +4436,7 @@ launch_descriptor_downloads(int purpose,
downloadable, i, i+n_per_request,
pds_flags);
}
last_routerdesc_download_attempted = now;
last_descriptor_download_attempted = now;
}
}
@ -4718,36 +4720,42 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
* do this only when we aren't seeing incoming data. see bug 652. */
#define DUMMY_DOWNLOAD_INTERVAL (20*60)
/** As needed, launch a dummy router descriptor fetch to see if our
* address has changed. */
static void
launch_dummy_descriptor_download_as_needed(time_t now, or_options_t *options)
{
static time_t last_dummy_download = 0;
/* XXXX023 we could be smarter here; see notes on bug 652. */
/* If we're a server that doesn't have a configured address, we rely on
* directory fetches to learn when our address changes. So if we haven't
* tried to get any routerdescs in a long time, try a dummy fetch now. */
if (!options->Address &&
server_mode(options) &&
last_descriptor_download_attempted + DUMMY_DOWNLOAD_INTERVAL < now &&
last_dummy_download + DUMMY_DOWNLOAD_INTERVAL < now) {
last_dummy_download = now;
directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC,
ROUTER_PURPOSE_GENERAL, "authority.z",
PDS_RETRY_IF_NO_SERVERS);
}
}
/** Launch downloads for router status as needed. */
void
update_router_descriptor_downloads(time_t now)
{
or_options_t *options = get_options();
static time_t last_dummy_download = 0;
if (should_delay_dir_fetches(options))
return;
if (!we_fetch_router_descriptors(options))
return;
if (directory_fetches_dir_info_early(options)) {
update_router_descriptor_cache_downloads_v2(now);
}
update_consensus_router_descriptor_downloads(now, 0,
networkstatus_get_reasonably_live_consensus(now, FLAV_NS));
/* XXXX023 we could be smarter here; see notes on bug 652. */
/* XXXX NM Microdescs: if we're not fetching microdescriptors, we need
* to make something else invoke this. */
/* If we're a server that doesn't have a configured address, we rely on
* directory fetches to learn when our address changes. So if we haven't
* tried to get any routerdescs in a long time, try a dummy fetch now. */
if (!options->Address &&
server_mode(options) &&
last_routerdesc_download_attempted + DUMMY_DOWNLOAD_INTERVAL < now &&
last_dummy_download + DUMMY_DOWNLOAD_INTERVAL < now) {
last_dummy_download = now;
directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC,
ROUTER_PURPOSE_GENERAL, "authority.z",
PDS_RETRY_IF_NO_SERVERS);
}
}
/** Launch extrainfo downloads as needed. */
@ -4879,20 +4887,28 @@ count_usable_descriptors(int *num_present, int *num_usable,
or_options_t *options, time_t now,
routerset_t *in_set)
{
const int md = (consensus->flavor == FLAV_MICRODESC);
*num_present = 0, *num_usable=0;
SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
{
SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *, rs)
{
if (in_set && ! routerset_contains_routerstatus(in_set, rs, -1))
continue;
if (client_would_use_router(rs, now, options)) {
const char * const digest = rs->descriptor_digest;
int present;
++*num_usable; /* the consensus says we want it. */
if (router_get_by_descriptor_digest(rs->descriptor_digest)) {
if (md)
present = NULL != (microdesc_cache_lookup_by_digest256(NULL, digest));
else
present = NULL != router_get_by_descriptor_digest(digest);
if (present) {
/* we have the descriptor listed in the consensus. */
++*num_present;
}
}
});
}
SMARTLIST_FOREACH_END(rs);
log_debug(LD_DIR, "%d usable, %d present.", *num_usable, *num_present);
}
@ -4906,7 +4922,7 @@ count_loading_descriptors_progress(void)
int num_present = 0, num_usable=0;
time_t now = time(NULL);
const networkstatus_t *consensus =
networkstatus_get_reasonably_live_consensus(now, FLAV_NS);
networkstatus_get_reasonably_live_consensus(now, usable_consensus_flavor());
double fraction;
if (!consensus)
@ -4936,14 +4952,14 @@ update_router_have_minimum_dir_info(void)
int res;
or_options_t *options = get_options();
const networkstatus_t *consensus =
networkstatus_get_reasonably_live_consensus(now, FLAV_NS);
networkstatus_get_reasonably_live_consensus(now, usable_consensus_flavor());
if (!consensus) {
if (!networkstatus_get_latest_consensus())
strlcpy(dir_info_status, "We have no network-status consensus.",
strlcpy(dir_info_status, "We have no usable consensus.",
sizeof(dir_info_status));
else
strlcpy(dir_info_status, "We have no recent network-status consensus.",
strlcpy(dir_info_status, "We have no recent usable consensus.",
sizeof(dir_info_status));
res = 0;
goto done;
@ -5022,7 +5038,7 @@ void
router_reset_descriptor_download_failures(void)
{
networkstatus_reset_download_failures();
last_routerdesc_download_attempted = 0;
last_descriptor_download_attempted = 0;
if (!routerlist)
return;
SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,

View File

@ -11,7 +11,7 @@
#ifndef _TOR_ROUTERLIST_H
#define _TOR_ROUTERLIST_H
int get_n_authorities(authority_type_t type);
int get_n_authorities(dirinfo_type_t type);
int trusted_dirs_reload_certs(void);
int trusted_dirs_load_certs_from_string(const char *contents, int from_store,
int flush);
@ -27,11 +27,11 @@ int router_reload_router_list(void);
int authority_cert_dl_looks_uncertain(const char *id_digest);
smartlist_t *router_get_trusted_dir_servers(void);
const routerstatus_t *router_pick_directory_server(authority_type_t type,
const routerstatus_t *router_pick_directory_server(dirinfo_type_t type,
int flags);
trusted_dir_server_t *router_get_trusteddirserver_by_digest(const char *d);
trusted_dir_server_t *trusteddirserver_get_by_v3_auth_digest(const char *d);
const routerstatus_t *router_pick_trusteddirserver(authority_type_t type,
const routerstatus_t *router_pick_trusteddirserver(dirinfo_type_t type,
int flags);
int router_get_my_share_of_directory_requests(double *v2_share_out,
double *v3_share_out);
@ -56,11 +56,10 @@ const node_t *router_choose_random_node(smartlist_t *excludedsmartlist,
const routerinfo_t *router_get_by_nickname(const char *nickname,
int warn_if_unnamed);
int router_digest_version_as_new_as(const char *digest, const char *cutoff);
int router_digest_is_trusted_dir_type(const char *digest,
authority_type_t type);
dirinfo_type_t type);
#define router_digest_is_trusted_dir(d) \
router_digest_is_trusted_dir_type((d), NO_AUTHORITY)
router_digest_is_trusted_dir_type((d), NO_DIRINFO)
int router_addr_is_trusted_dir(uint32_t addr);
int hexdigest_to_digest(const char *hexdigest, char *digest);
@ -138,13 +137,14 @@ trusted_dir_server_t *add_trusted_dir_server(const char *nickname,
const char *address,
uint16_t dir_port, uint16_t or_port,
const char *digest, const char *v3_auth_digest,
authority_type_t type);
dirinfo_type_t type);
void authority_cert_free(authority_cert_t *cert);
void clear_trusted_dir_servers(void);
int any_trusted_dir_is_v1_authority(void);
void update_consensus_router_descriptor_downloads(time_t now, int is_vote,
networkstatus_t *consensus);
void update_router_descriptor_downloads(time_t now);
void update_all_descriptor_downloads(time_t now);
void update_extrainfo_downloads(time_t now);
int router_have_minimum_dir_info(void);
void router_dir_info_changed(void);

View File

@ -2085,6 +2085,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
rs->version_supports_begindir = 1;
rs->version_supports_extrainfo_upload = 1;
rs->version_supports_conditional_consensus = 1;
rs->version_supports_microdesc_cache = 1;
} else {
rs->version_supports_begindir =
tor_version_as_new_as(tok->args[0], "0.2.0.1-alpha");
@ -2094,6 +2095,14 @@ routerstatus_parse_entry_from_string(memarea_t *area,
tor_version_as_new_as(tok->args[0], "0.2.0.8-alpha");
rs->version_supports_conditional_consensus =
tor_version_as_new_as(tok->args[0], "0.2.1.1-alpha");
/* XXXX023 NM microdescs: 0.2.3.1-alpha isn't widely used yet, but
* not all 0.2.3.0-alpha "versions" actually support microdesc cacheing
* right. There's a compromise here. Since this is 5 May, let's
* err on the side of having some possible caches to use. Once more
* caches are running 0.2.3.1-alpha, we can bump this version number.
*/
rs->version_supports_microdesc_cache =
tor_version_as_new_as(tok->args[0], "0.2.3.0-alpha");
}
if (vote_rs) {
vote_rs->version = tor_strdup(tok->args[0]);