Code to make clients fetch and use microdescriptors for circuit building

To turn this on, set UseMicrodescriptors to "1" (or "auto" if you
want it on-if-you're-a-client).  It should go auto-by-default once
0.2.3.1-alpha is released.

Because of our node logic, directory caches will never use
microdescriptors when they have the right routerinfo available.
This commit is contained in:
Nick Mathewson
2010-11-08 14:21:32 -05:00
parent 3df22887a3
commit 4cc348e896
12 changed files with 127 additions and 47 deletions
+4 -2
View File
@@ -381,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"),
@@ -919,7 +920,8 @@ consider_adding_dir_authorities(or_options_t *options,
if (!options->AlternateBridgeAuthority)
type |= BRIDGE_DIRINFO;
if (!options->AlternateDirAuthority)
type |= V1_DIRINFO | V2_DIRINFO | V3_DIRINFO;
type |= V1_DIRINFO | V2_DIRINFO | V3_DIRINFO | EXTRAINFO_DIRINFO |
MICRODESC_DIRINFO;
if (!options->AlternateHSAuthority)
type |= HIDSERV_DIRINFO;
add_default_trusted_dir_authorities(type);
@@ -4605,7 +4607,7 @@ parse_dir_server_line(const char *line, dirinfo_type_t required_type,
log_warn(LD_CONFIG, "Bad v3 identity digest '%s' on DirServer line",
flag);
} else {
type |= V3_DIRINFO;
type |= V3_DIRINFO|EXTRAINFO_DIRINFO|MICRODESC_DIRINFO;
}
} else {
log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirServer line",
+6 -5
View File
@@ -147,9 +147,10 @@ purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
return 1;
}
/** Return a newly allocated string describing <b>auth</b>. */
char *
dirinfo_type_to_string(dirinfo_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();
@@ -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 = dirinfo_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);
@@ -379,7 +380,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
type = V3_DIRINFO;
break;
case DIR_PURPOSE_FETCH_MICRODESC:
type = V3_DIRINFO;
type = MICRODESC_DIRINFO;
break;
default:
log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
-1
View File
@@ -13,7 +13,6 @@
#define _TOR_DIRECTORY_H
int directories_have_accepted_server_descriptor(void);
char *dirinfo_type_to_string(dirinfo_type_t auth);
void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
dirinfo_type_t type, const char *payload,
size_t payload_len, size_t extrainfo_len);
+49 -4
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,45 @@ 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: */
/* So we decide that we'll use microdescriptors iff we are not a server */
ret = ! server_mode(options);
}
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;
}
}
+5
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
+10 -8
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. */
@@ -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);
+17 -5
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)
@@ -2092,6 +2092,12 @@ typedef struct authority_cert_t {
/** 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_DIRINFO = 0,
@@ -2107,7 +2113,9 @@ typedef enum {
/** Serves bridge descriptors. */
BRIDGE_DIRINFO = 1 << 4,
/** Serves extrainfo documents. */
EXTRAINFO_DIRINFO = 1 << 5,
EXTRAINFO_DIRINFO=1 << 5,
/** Serves microdescriptors. */
MICRODESC_DIRINFO=1 << 6,
} dirinfo_type_t;
#define CRYPT_PATH_MAGIC 0x70127012u
@@ -2642,7 +2650,7 @@ 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. */
/** 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;
@@ -3043,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. */
+2 -1
View File
@@ -699,7 +699,8 @@ init_keys(void)
crypto_pk_get_digest(get_server_identity_key(), digest);
type = ((options->V1AuthoritativeDir ? V1_DIRINFO : NO_DIRINFO) |
(options->V2AuthoritativeDir ? V2_DIRINFO : NO_DIRINFO) |
(options->V3AuthoritativeDir ? V3_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));
+21 -20
View File
@@ -1127,6 +1127,9 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags)
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)) {
@@ -2443,18 +2446,6 @@ 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. */
@@ -4726,6 +4717,8 @@ update_router_descriptor_downloads(time_t now)
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);
}
@@ -4879,20 +4872,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 +4907,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 +4937,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;
-1
View File
@@ -56,7 +56,6 @@ 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,
dirinfo_type_t type);
#define router_digest_is_trusted_dir(d) \
+3
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,8 @@ 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");
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]);