aboutsummaryrefslogtreecommitdiff
path: root/src/or/routerlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/routerlist.c')
-rw-r--r--src/or/routerlist.c416
1 files changed, 209 insertions, 207 deletions
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index f73ec9baa1..203895c867 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -1,7 +1,7 @@
/* Copyright (c) 2001 Matej Pfajfar.
* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -93,6 +93,7 @@
#define ROUTERLIST_PRIVATE
#include "or.h"
#include "backtrace.h"
+#include "bridges.h"
#include "crypto_ed25519.h"
#include "circuitstats.h"
#include "config.h"
@@ -142,6 +143,10 @@ DECLARE_TYPED_DIGESTMAP_FNS(dsmap_, digest_ds_map_t, download_status_t)
#define DSMAP_FOREACH(map, keyvar, valvar) \
DIGESTMAP_FOREACH(dsmap_to_digestmap(map), keyvar, download_status_t *, \
valvar)
+#define eimap_free(map, fn) MAP_FREE_AND_NULL(eimap, (map), (fn))
+#define rimap_free(map, fn) MAP_FREE_AND_NULL(rimap, (map), (fn))
+#define dsmap_free(map, fn) MAP_FREE_AND_NULL(dsmap, (map), (fn))
+#define sdmap_free(map, fn) MAP_FREE_AND_NULL(sdmap, (map), (fn))
/* Forward declaration for cert_list_t */
typedef struct cert_list_t cert_list_t;
@@ -158,7 +163,6 @@ static const routerstatus_t *router_pick_dirserver_generic(
smartlist_t *sourcelist,
dirinfo_type_t type, int flags);
static void mark_all_dirservers_up(smartlist_t *server_list);
-static void dir_server_free(dir_server_t *ds);
static int signed_desc_digest_is_recognized(signed_descriptor_t *desc);
static const char *signed_descriptor_get_body_impl(
const signed_descriptor_t *desc,
@@ -173,7 +177,7 @@ static void download_status_reset_by_sk_in_cl(cert_list_t *cl,
const char *digest);
static int download_status_is_ready_by_sk_in_cl(cert_list_t *cl,
const char *digest,
- time_t now, int max_failures);
+ time_t now);
/****************************************************************************/
@@ -231,7 +235,7 @@ get_n_authorities(dirinfo_type_t type)
return n;
}
-/** Initialise schedule, want_authority, and increment on in the download
+/** Initialise schedule, want_authority, and increment_on in the download
* status dlstatus, then call download_status_reset() on it.
* It is safe to call this function or download_status_reset() multiple times
* on a new dlstatus. But it should *not* be called after a dlstatus has been
@@ -242,7 +246,6 @@ download_status_cert_init(download_status_t *dlstatus)
dlstatus->schedule = DL_SCHED_CONSENSUS;
dlstatus->want_authority = DL_WANT_ANY_DIRSERVER;
dlstatus->increment_on = DL_SCHED_INCREMENT_FAILURE;
- dlstatus->backoff = DL_SCHED_RANDOM_EXPONENTIAL;
dlstatus->last_backoff_position = 0;
dlstatus->last_delay_used = 0;
@@ -284,7 +287,7 @@ download_status_reset_by_sk_in_cl(cert_list_t *cl, const char *digest)
static int
download_status_is_ready_by_sk_in_cl(cert_list_t *cl,
const char *digest,
- time_t now, int max_failures)
+ time_t now)
{
int rv = 0;
download_status_t *dlstatus = NULL;
@@ -301,7 +304,7 @@ download_status_is_ready_by_sk_in_cl(cert_list_t *cl,
/* Got one? */
if (dlstatus) {
/* Use download_status_is_ready() */
- rv = download_status_is_ready(dlstatus, now, max_failures);
+ rv = download_status_is_ready(dlstatus, now);
} else {
/*
* If we don't know anything about it, return 1, since we haven't
@@ -363,7 +366,7 @@ list_authority_ids_with_downloads, (void))
smartlist_add(ids, tmp);
}
}
- /* else definitely no downlaods going since nothing even has a cert list */
+ /* else definitely no downloads going since nothing even has a cert list */
return ids;
}
@@ -426,8 +429,8 @@ list_sk_digests_for_authority_id, (const char *digest))
* download_status_t or NULL if none exists. */
MOCK_IMPL(download_status_t *,
- download_status_for_authority_id_and_sk,
- (const char *id_digest, const char *sk_digest))
+download_status_for_authority_id_and_sk,(const char *id_digest,
+ const char *sk_digest))
{
download_status_t *dl = NULL;
cert_list_t *cl = NULL;
@@ -442,9 +445,12 @@ MOCK_IMPL(download_status_t *,
return dl;
}
+#define cert_list_free(val) \
+ FREE_AND_NULL(cert_list_t, cert_list_free_, (val))
+
/** Release all space held by a cert_list_t */
static void
-cert_list_free(cert_list_t *cl)
+cert_list_free_(cert_list_t *cl)
{
if (!cl)
return;
@@ -458,9 +464,9 @@ cert_list_free(cert_list_t *cl)
/** Wrapper for cert_list_free so we can pass it to digestmap_free */
static void
-cert_list_free_(void *cl)
+cert_list_free_void(void *cl)
{
- cert_list_free(cl);
+ cert_list_free_(cl);
}
/** Reload the cached v3 key certificates from the cached-certs file in
@@ -472,7 +478,7 @@ trusted_dirs_reload_certs(void)
char *contents;
int r;
- filename = get_datadir_fname("cached-certs");
+ filename = get_cachedir_fname("cached-certs");
contents = read_file_to_str(filename, RFTS_IGNORE_MISSING, NULL);
tor_free(filename);
if (!contents)
@@ -587,7 +593,7 @@ trusted_dirs_load_certs_from_string(const char *contents, int source,
"signing key %s", from_store ? "cached" : "downloaded",
ds->nickname, hex_str(cert->signing_key_digest,DIGEST_LEN));
} else {
- int adding = directory_caches_unknown_auth_certs(get_options());
+ int adding = we_want_to_fetch_unknown_auth_certs(get_options());
log_info(LD_DIR, "%s %s certificate for unrecognized directory "
"authority with signing key %s",
adding ? "Adding" : "Not adding",
@@ -661,7 +667,7 @@ trusted_dirs_flush_certs_to_disk(void)
});
} DIGESTMAP_FOREACH_END;
- filename = get_datadir_fname("cached-certs");
+ filename = get_cachedir_fname("cached-certs");
if (write_chunks_to_file(filename, chunks, 0, 0)) {
log_warn(LD_FS, "Error writing certificates to disk.");
}
@@ -930,7 +936,8 @@ authority_certs_fetch_resource_impl(const char *resource,
const routerstatus_t *rs)
{
const or_options_t *options = get_options();
- int get_via_tor = purpose_needs_anonymity(DIR_PURPOSE_FETCH_CERTIFICATE, 0);
+ int get_via_tor = purpose_needs_anonymity(DIR_PURPOSE_FETCH_CERTIFICATE, 0,
+ resource);
/* Make sure bridge clients never connect to anything but a bridge */
if (options->UseBridges) {
@@ -946,31 +953,34 @@ authority_certs_fetch_resource_impl(const char *resource,
const dir_indirection_t indirection = get_via_tor ? DIRIND_ANONYMOUS
: DIRIND_ONEHOP;
+ directory_request_t *req = NULL;
/* If we've just downloaded a consensus from a bridge, re-use that
* bridge */
- if (options->UseBridges && node && !get_via_tor) {
+ if (options->UseBridges && node && node->ri && !get_via_tor) {
/* clients always make OR connections to bridges */
tor_addr_port_t or_ap;
/* we are willing to use a non-preferred address if we need to */
fascist_firewall_choose_address_node(node, FIREWALL_OR_CONNECTION, 0,
&or_ap);
- directory_initiate_command(&or_ap.addr, or_ap.port,
- NULL, 0, /*no dirport*/
- dir_hint,
- DIR_PURPOSE_FETCH_CERTIFICATE,
- 0,
- indirection,
- resource, NULL, 0, 0);
- return;
- }
- if (rs) {
- /* If we've just downloaded a consensus from a directory, re-use that
+ req = directory_request_new(DIR_PURPOSE_FETCH_CERTIFICATE);
+ directory_request_set_or_addr_port(req, &or_ap);
+ if (dir_hint)
+ directory_request_set_directory_id_digest(req, dir_hint);
+ } else if (rs) {
+ /* And if we've just downloaded a consensus from a directory, re-use that
* directory */
- directory_initiate_command_routerstatus(rs,
- DIR_PURPOSE_FETCH_CERTIFICATE,
- 0, indirection, resource, NULL,
- 0, 0);
+ req = directory_request_new(DIR_PURPOSE_FETCH_CERTIFICATE);
+ directory_request_set_routerstatus(req, rs);
+ }
+
+ if (req) {
+ /* We've set up a request object -- fill in the other request fields, and
+ * send the request. */
+ directory_request_set_indirection(req, indirection);
+ directory_request_set_resource(req, resource);
+ directory_initiate_request(req);
+ directory_request_free(req);
return;
}
@@ -1012,7 +1022,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now,
char *resource = NULL;
cert_list_t *cl;
const or_options_t *options = get_options();
- const int cache = directory_caches_unknown_auth_certs(options);
+ const int keep_unknown = we_want_to_fetch_unknown_auth_certs(options);
fp_pair_t *fp_tmp = NULL;
char id_digest_str[2*DIGEST_LEN+1];
char sk_digest_str[2*DIGEST_LEN+1];
@@ -1057,8 +1067,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now,
}
} SMARTLIST_FOREACH_END(cert);
if (!found &&
- download_status_is_ready(&(cl->dl_status_by_id), now,
- options->TestingCertMaxDownloadTries) &&
+ download_status_is_ready(&(cl->dl_status_by_id), now) &&
!digestmap_get(pending_id, ds->v3_identity_digest)) {
log_info(LD_DIR,
"No current certificate known for authority %s "
@@ -1084,9 +1093,10 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now,
if (!smartlist_len(voter->sigs))
continue; /* This authority never signed this consensus, so don't
* go looking for a cert with key digest 0000000000. */
- if (!cache &&
+ if (!keep_unknown &&
!trusteddirserver_get_by_v3_auth_digest(voter->identity_digest))
- continue; /* We are not a cache, and we don't know this authority.*/
+ continue; /* We don't want unknown certs, and we don't know this
+ * authority.*/
/*
* If we don't know *any* cert for this authority, and a download by ID
@@ -1120,8 +1130,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now,
continue;
}
if (download_status_is_ready_by_sk_in_cl(
- cl, sig->signing_key_digest,
- now, options->TestingCertMaxDownloadTries) &&
+ cl, sig->signing_key_digest, now) &&
!fp_pair_map_get_by_digests(pending_cert,
voter->identity_digest,
sig->signing_key_digest)) {
@@ -1158,7 +1167,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now,
} SMARTLIST_FOREACH_END(voter);
}
- /* Bridge clients look up the node for the dir_hint */
+ /* Bridge clients look up the node for the dir_hint */
const node_t *node = NULL;
/* All clients, including bridge clients, look up the routerstatus for the
* dir_hint */
@@ -1203,7 +1212,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now,
int need_plus = 0;
smartlist_t *fps = smartlist_new();
- smartlist_add(fps, tor_strdup("fp/"));
+ smartlist_add_strdup(fps, "fp/");
SMARTLIST_FOREACH_BEGIN(missing_id_digests, const char *, d) {
char *fp = NULL;
@@ -1243,7 +1252,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now,
int need_plus = 0;
smartlist_t *fp_pairs = smartlist_new();
- smartlist_add(fp_pairs, tor_strdup("fp-sk/"));
+ smartlist_add_strdup(fp_pairs, "fp-sk/");
SMARTLIST_FOREACH_BEGIN(missing_cert_digests, const fp_pair_t *, d) {
char *fp_pair = NULL;
@@ -1333,7 +1342,7 @@ static int
signed_desc_append_to_journal(signed_descriptor_t *desc,
desc_store_t *store)
{
- char *fname = get_datadir_fname_suffix(store->fname_base, ".new");
+ char *fname = get_cachedir_fname_suffix(store->fname_base, ".new");
const char *body = signed_descriptor_get_body_impl(desc,1);
size_t len = desc->signed_descriptor_len + desc->annotations_len;
@@ -1404,8 +1413,8 @@ router_rebuild_store(int flags, desc_store_t *store)
log_info(LD_DIR, "Rebuilding %s cache", store->description);
- fname = get_datadir_fname(store->fname_base);
- fname_tmp = get_datadir_fname_suffix(store->fname_base, ".tmp");
+ fname = get_cachedir_fname(store->fname_base);
+ fname_tmp = get_cachedir_fname_suffix(store->fname_base, ".tmp");
chunk_list = smartlist_new();
@@ -1502,7 +1511,7 @@ router_rebuild_store(int flags, desc_store_t *store)
} SMARTLIST_FOREACH_END(sd);
tor_free(fname);
- fname = get_datadir_fname_suffix(store->fname_base, ".new");
+ fname = get_cachedir_fname_suffix(store->fname_base, ".new");
write_str_to_file(fname, "", 1);
r = 0;
@@ -1532,7 +1541,7 @@ router_reload_router_list_impl(desc_store_t *store)
int extrainfo = (store->type == EXTRAINFO_STORE);
store->journal_len = store->store_len = 0;
- fname = get_datadir_fname(store->fname_base);
+ fname = get_cachedir_fname(store->fname_base);
if (store->mmap) {
/* get rid of it first */
@@ -1559,7 +1568,7 @@ router_reload_router_list_impl(desc_store_t *store)
}
tor_free(fname);
- fname = get_datadir_fname_suffix(store->fname_base, ".new");
+ fname = get_cachedir_fname_suffix(store->fname_base, ".new");
/* don't load empty files - we wouldn't get any data, even if we tried */
if (file_status(fname) == FN_FILE)
contents = read_file_to_str(fname, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
@@ -1824,43 +1833,24 @@ router_is_already_dir_fetching(const tor_addr_port_t *ap, int serverdesc,
return 0;
}
-/* Check if we already have a directory fetch from ds, for serverdesc
- * (including extrainfo) or microdesc documents.
- * If so, return 1, if not, return 0.
- */
-static int
-router_is_already_dir_fetching_ds(const dir_server_t *ds,
- int serverdesc,
- int microdesc)
-{
- tor_addr_port_t ipv4_dir_ap, ipv6_dir_ap;
-
- /* Assume IPv6 DirPort is the same as IPv4 DirPort */
- tor_addr_from_ipv4h(&ipv4_dir_ap.addr, ds->addr);
- ipv4_dir_ap.port = ds->dir_port;
- tor_addr_copy(&ipv6_dir_ap.addr, &ds->ipv6_addr);
- ipv6_dir_ap.port = ds->dir_port;
-
- return (router_is_already_dir_fetching(&ipv4_dir_ap, serverdesc, microdesc)
- || router_is_already_dir_fetching(&ipv6_dir_ap, serverdesc, microdesc));
-}
-
-/* Check if we already have a directory fetch from rs, for serverdesc
- * (including extrainfo) or microdesc documents.
+/* Check if we already have a directory fetch from the ipv4 or ipv6
+ * router, for serverdesc (including extrainfo) or microdesc documents.
* If so, return 1, if not, return 0.
*/
static int
-router_is_already_dir_fetching_rs(const routerstatus_t *rs,
- int serverdesc,
- int microdesc)
+router_is_already_dir_fetching_(uint32_t ipv4_addr,
+ const tor_addr_t *ipv6_addr,
+ uint16_t dir_port,
+ int serverdesc,
+ int microdesc)
{
tor_addr_port_t ipv4_dir_ap, ipv6_dir_ap;
/* Assume IPv6 DirPort is the same as IPv4 DirPort */
- tor_addr_from_ipv4h(&ipv4_dir_ap.addr, rs->addr);
- ipv4_dir_ap.port = rs->dir_port;
- tor_addr_copy(&ipv6_dir_ap.addr, &rs->ipv6_addr);
- ipv6_dir_ap.port = rs->dir_port;
+ tor_addr_from_ipv4h(&ipv4_dir_ap.addr, ipv4_addr);
+ ipv4_dir_ap.port = dir_port;
+ tor_addr_copy(&ipv6_dir_ap.addr, ipv6_addr);
+ ipv6_dir_ap.port = dir_port;
return (router_is_already_dir_fetching(&ipv4_dir_ap, serverdesc, microdesc)
|| router_is_already_dir_fetching(&ipv6_dir_ap, serverdesc, microdesc));
@@ -1886,7 +1876,7 @@ router_picked_poor_directory_log(const routerstatus_t *rs)
|| !router_have_minimum_dir_info()) {
return;
}
-#endif
+#endif /* !LOG_FALSE_POSITIVES_DURING_BOOTSTRAP */
/* We couldn't find a node, or the one we have doesn't fit our preferences.
* Sometimes this is normal, sometimes it can be a reachability issue. */
@@ -1952,6 +1942,21 @@ router_picked_poor_directory_log(const routerstatus_t *rs)
} \
STMT_END
+/* Common code used in the loop within router_pick_directory_server_impl and
+ * router_pick_trusteddirserver_impl.
+ *
+ * Check if the given <b>identity</b> supports extrainfo. If not, skip further
+ * checks.
+ */
+#define SKIP_MISSING_TRUSTED_EXTRAINFO(type, identity) \
+ STMT_BEGIN \
+ int is_trusted_extrainfo = router_digest_is_trusted_dir_type( \
+ (identity), EXTRAINFO_DIRINFO); \
+ if (((type) & EXTRAINFO_DIRINFO) && \
+ !router_supports_extrainfo((identity), is_trusted_extrainfo)) \
+ continue; \
+ STMT_END
+
/* When iterating through the routerlist, can OR address/port preference
* and reachability checks be skipped?
*/
@@ -1998,7 +2003,6 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags,
const int fascistfirewall = ! (flags & PDS_IGNORE_FASCISTFIREWALL);
const int no_serverdesc_fetching =(flags & PDS_NO_EXISTING_SERVERDESC_FETCH);
const int no_microdesc_fetching = (flags & PDS_NO_EXISTING_MICRODESC_FETCH);
- const int for_guard = (flags & PDS_FOR_GUARD);
int try_excluding = 1, n_excluded = 0, n_busy = 0;
int try_ip_pref = 1;
@@ -2020,7 +2024,7 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags,
/* Find all the running dirservers we know about. */
SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
- int is_trusted, is_trusted_extrainfo;
+ int is_trusted;
int is_overloaded;
const routerstatus_t *status = node->rs;
const country_t country = node->country;
@@ -2031,20 +2035,9 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags,
continue;
if (requireother && router_digest_is_me(node->identity))
continue;
- is_trusted = router_digest_is_trusted_dir(node->identity);
- is_trusted_extrainfo = router_digest_is_trusted_dir_type(
- node->identity, EXTRAINFO_DIRINFO);
- if ((type & EXTRAINFO_DIRINFO) &&
- !router_supports_extrainfo(node->identity, is_trusted_extrainfo))
- continue;
- /* Don't make the same node a guard twice */
- if (for_guard && node->using_as_guard) {
- continue;
- }
- /* Ensure that a directory guard is actually a guard node. */
- if (for_guard && !node->is_possible_guard) {
- continue;
- }
+
+ SKIP_MISSING_TRUSTED_EXTRAINFO(type, node->identity);
+
if (try_excluding &&
routerset_contains_routerstatus(options->ExcludeNodes, status,
country)) {
@@ -2052,14 +2045,17 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags,
continue;
}
- if (router_is_already_dir_fetching_rs(status,
- no_serverdesc_fetching,
- no_microdesc_fetching)) {
+ if (router_is_already_dir_fetching_(status->addr,
+ &status->ipv6_addr,
+ status->dir_port,
+ no_serverdesc_fetching,
+ no_microdesc_fetching)) {
++n_busy;
continue;
}
is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now;
+ is_trusted = router_digest_is_trusted_dir(node->identity);
/* Clients use IPv6 addresses if the server has one and the client
* prefers IPv6.
@@ -2191,11 +2187,9 @@ router_pick_trusteddirserver_impl(const smartlist_t *sourcelist,
if (!d->is_running) continue;
if ((type & d->type) == 0)
continue;
- int is_trusted_extrainfo = router_digest_is_trusted_dir_type(
- d->digest, EXTRAINFO_DIRINFO);
- if ((type & EXTRAINFO_DIRINFO) &&
- !router_supports_extrainfo(d->digest, is_trusted_extrainfo))
- continue;
+
+ SKIP_MISSING_TRUSTED_EXTRAINFO(type, d->digest);
+
if (requireother && me && router_digest_is_me(d->digest))
continue;
if (try_excluding &&
@@ -2205,8 +2199,11 @@ router_pick_trusteddirserver_impl(const smartlist_t *sourcelist,
continue;
}
- if (router_is_already_dir_fetching_ds(d, no_serverdesc_fetching,
- no_microdesc_fetching)) {
+ if (router_is_already_dir_fetching_(d->addr,
+ &d->ipv6_addr,
+ d->dir_port,
+ no_serverdesc_fetching,
+ no_microdesc_fetching)) {
++n_busy;
continue;
}
@@ -2313,7 +2310,7 @@ routerlist_add_node_and_family(smartlist_t *sl, const routerinfo_t *router)
{
/* XXXX MOVE ? */
node_t fake_node;
- const node_t *node = node_get_by_id(router->cache_info.identity_digest);;
+ const node_t *node = node_get_by_id(router->cache_info.identity_digest);
if (node == NULL) {
memset(&fake_node, 0, sizeof(fake_node));
fake_node.ri = (routerinfo_t *)router;
@@ -2327,19 +2324,18 @@ routerlist_add_node_and_family(smartlist_t *sl, const routerinfo_t *router)
* we can pick a node for a circuit.
*/
void
-router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid,
- int need_uptime, int need_capacity,
- int need_guard, int need_desc,
- int pref_addr, int direct_conn)
+router_add_running_nodes_to_smartlist(smartlist_t *sl, int need_uptime,
+ int need_capacity, int need_guard,
+ int need_desc, int pref_addr,
+ int direct_conn)
{
const int check_reach = !router_skip_or_reachability(get_options(),
pref_addr);
/* XXXX MOVE */
SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
- if (!node->is_running ||
- (!node->is_valid && !allow_invalid))
+ if (!node->is_running || !node->is_valid)
continue;
- if (need_desc && !(node->ri || (node->rs && node->md)))
+ if (need_desc && !node_has_preferred_descriptor(node, direct_conn))
continue;
if (node->ri && node->ri->purpose != ROUTER_PURPOSE_GENERAL)
continue;
@@ -2653,7 +2649,7 @@ compute_weighted_bandwidths(const smartlist_t *sl,
is_dir = node_is_dir(node);
if (node->rs) {
if (!node->rs->has_bandwidth) {
- /* This should never happen, unless all the authorites downgrade
+ /* This should never happen, unless all the authorities downgrade
* to 0.2.0 or rogue routerstatuses get inserted into our consensus. */
if (! warned_missing_bw) {
log_warn(LD_BUG,
@@ -2762,7 +2758,7 @@ frac_nodes_with_descriptors(const smartlist_t *sl,
total <= 0.0) {
int n_with_descs = 0;
SMARTLIST_FOREACH(sl, const node_t *, node, {
- if (node_has_descriptor(node))
+ if (node_has_any_descriptor(node))
n_with_descs++;
});
@@ -2772,7 +2768,7 @@ frac_nodes_with_descriptors(const smartlist_t *sl,
present = 0.0;
SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) {
- if (node_has_descriptor(node))
+ if (node_has_any_descriptor(node))
present += bandwidths[node_sl_idx];
} SMARTLIST_FOREACH_END(node);
@@ -2798,8 +2794,6 @@ node_sl_choose_by_bandwidth(const smartlist_t *sl,
* a minimum uptime, return one of those.
* If <b>CRN_NEED_CAPACITY</b> is set in flags, weight your choice by the
* advertised capacity of each router.
- * If <b>CRN_ALLOW_INVALID</b> is not set in flags, consider only Valid
- * routers.
* If <b>CRN_NEED_GUARD</b> is set in flags, consider only Guard routers.
* If <b>CRN_WEIGHT_AS_EXIT</b> is set in flags, we weight bandwidths as if
* picking an exit node, otherwise we weight bandwidths for picking a relay
@@ -2820,11 +2814,11 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
const int need_uptime = (flags & CRN_NEED_UPTIME) != 0;
const int need_capacity = (flags & CRN_NEED_CAPACITY) != 0;
const int need_guard = (flags & CRN_NEED_GUARD) != 0;
- const int allow_invalid = (flags & CRN_ALLOW_INVALID) != 0;
const int weight_for_exit = (flags & CRN_WEIGHT_AS_EXIT) != 0;
const int need_desc = (flags & CRN_NEED_DESC) != 0;
const int pref_addr = (flags & CRN_PREF_ADDR) != 0;
const int direct_conn = (flags & CRN_DIRECT_CONN) != 0;
+ const int rendezvous_v3 = (flags & CRN_RENDEZVOUS_V3) != 0;
smartlist_t *sl=smartlist_new(),
*excludednodes=smartlist_new();
@@ -2836,14 +2830,19 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
rule = weight_for_exit ? WEIGHT_FOR_EXIT :
(need_guard ? WEIGHT_FOR_GUARD : WEIGHT_FOR_MID);
- /* Exclude relays that allow single hop exit circuits, if the user
- * wants to (such relays might be risky) */
- if (get_options()->ExcludeSingleHopRelays) {
- SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node,
- if (node_allows_single_hop_exits(node)) {
- smartlist_add(excludednodes, node);
- });
- }
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
+ if (node_allows_single_hop_exits(node)) {
+ /* Exclude relays that allow single hop exit circuits. This is an
+ * obsolete option since 0.2.9.2-alpha and done by default in
+ * 0.3.1.0-alpha. */
+ smartlist_add(excludednodes, node);
+ } else if (rendezvous_v3 &&
+ !node_supports_v3_rendezvous_point(node)) {
+ /* Exclude relays that do not support to rendezvous for a hidden service
+ * version 3. */
+ smartlist_add(excludednodes, node);
+ }
+ } SMARTLIST_FOREACH_END(node);
/* If the node_t is not found we won't be to exclude ourself but we
* won't be able to pick ourself in router_choose_random_node() so
@@ -2851,8 +2850,7 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
if ((r = router_get_my_routerinfo()))
routerlist_add_node_and_family(excludednodes, r);
- router_add_running_nodes_to_smartlist(sl, allow_invalid,
- need_uptime, need_capacity,
+ router_add_running_nodes_to_smartlist(sl, need_uptime, need_capacity,
need_guard, need_desc, pref_addr,
direct_conn);
log_debug(LD_CIRC,
@@ -2958,7 +2956,7 @@ hex_digest_nickname_decode(const char *hexdigest,
* <b>hexdigest</b> is malformed, or it doesn't match. */
int
hex_digest_nickname_matches(const char *hexdigest, const char *identity_digest,
- const char *nickname, int is_named)
+ const char *nickname)
{
char digest[DIGEST_LEN];
char nn_char='\0';
@@ -2967,30 +2965,20 @@ hex_digest_nickname_matches(const char *hexdigest, const char *identity_digest,
if (hex_digest_nickname_decode(hexdigest, digest, &nn_char, nn_buf) == -1)
return 0;
- if (nn_char == '=' || nn_char == '~') {
- if (!nickname)
+ if (nn_char == '=') {
+ return 0;
+ }
+
+ if (nn_char == '~') {
+ if (!nickname) // XXX This seems wrong. -NM
return 0;
if (strcasecmp(nn_buf, nickname))
return 0;
- if (nn_char == '=' && !is_named)
- return 0;
}
return tor_memeq(digest, identity_digest, DIGEST_LEN);
}
-/** Return true iff <b>router</b> is listed as named in the current
- * consensus. */
-int
-router_is_named(const routerinfo_t *router)
-{
- const char *digest =
- networkstatus_get_router_digest_by_nickname(router->nickname);
-
- return (digest &&
- tor_memeq(digest, router->cache_info.identity_digest, DIGEST_LEN));
-}
-
/** 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 (NO_DIRINFO), or ALL_DIRINFO, any authority is okay. */
@@ -3008,20 +2996,6 @@ router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type)
return 0;
}
-/** Return true iff <b>addr</b> is the address of one of our trusted
- * directory authorities. */
-int
-router_addr_is_trusted_dir(uint32_t addr)
-{
- if (!trusted_dir_servers)
- return 0;
- SMARTLIST_FOREACH(trusted_dir_servers, dir_server_t *, ent,
- if (ent->addr == addr)
- return 1;
- );
- return 0;
-}
-
/** If hexdigest is correctly formed, base16_decode it into
* digest, which must have DIGEST_LEN space in it.
* Return 0 on success, -1 on failure.
@@ -3087,8 +3061,8 @@ router_get_by_extrainfo_digest,(const char *digest))
/** Return the signed descriptor for the extrainfo_t in our routerlist whose
* extra-info-digest is <b>digest</b>. Return NULL if no such extra-info
* document is known. */
-signed_descriptor_t *
-extrainfo_get_by_descriptor_digest(const char *digest)
+MOCK_IMPL(signed_descriptor_t *,
+extrainfo_get_by_descriptor_digest,(const char *digest))
{
extrainfo_t *ei;
tor_assert(digest);
@@ -3130,7 +3104,7 @@ signed_descriptor_get_body_impl(const signed_descriptor_t *desc,
log_err(LD_DIR, "We couldn't read a descriptor that is supposedly "
"mmaped in our cache. Is another process running in our data "
"directory? Exiting.");
- exit(1);
+ exit(1); // XXXX bad exit: should recover.
}
}
if (!r) /* no mmap, or not in cache. */
@@ -3144,7 +3118,7 @@ signed_descriptor_get_body_impl(const signed_descriptor_t *desc,
log_err(LD_DIR, "descriptor at %p begins with unexpected string %s. "
"Is another process running in our data directory? Exiting.",
desc, escaped(cp));
- exit(1);
+ exit(1); // XXXX bad exit: should recover.
}
}
@@ -3198,7 +3172,7 @@ router_get_routerlist(void)
/** Free all storage held by <b>router</b>. */
void
-routerinfo_free(routerinfo_t *router)
+routerinfo_free_(routerinfo_t *router)
{
if (!router)
return;
@@ -3228,7 +3202,7 @@ routerinfo_free(routerinfo_t *router)
/** Release all storage held by <b>extrainfo</b> */
void
-extrainfo_free(extrainfo_t *extrainfo)
+extrainfo_free_(extrainfo_t *extrainfo)
{
if (!extrainfo)
return;
@@ -3240,9 +3214,12 @@ extrainfo_free(extrainfo_t *extrainfo)
tor_free(extrainfo);
}
+#define signed_descriptor_free(val) \
+ FREE_AND_NULL(signed_descriptor_t, signed_descriptor_free_, (val))
+
/** Release storage held by <b>sd</b>. */
static void
-signed_descriptor_free(signed_descriptor_t *sd)
+signed_descriptor_free_(signed_descriptor_t *sd)
{
if (!sd)
return;
@@ -3296,21 +3273,21 @@ signed_descriptor_from_routerinfo(routerinfo_t *ri)
/** Helper: free the storage held by the extrainfo_t in <b>e</b>. */
static void
-extrainfo_free_(void *e)
+extrainfo_free_void(void *e)
{
- extrainfo_free(e);
+ extrainfo_free_(e);
}
/** Free all storage held by a routerlist <b>rl</b>. */
void
-routerlist_free(routerlist_t *rl)
+routerlist_free_(routerlist_t *rl)
{
if (!rl)
return;
rimap_free(rl->identity_map, NULL);
sdmap_free(rl->desc_digest_map, NULL);
sdmap_free(rl->desc_by_eid_map, NULL);
- eimap_free(rl->extra_info_map, extrainfo_free_);
+ eimap_free(rl->extra_info_map, extrainfo_free_void);
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
routerinfo_free(r));
SMARTLIST_FOREACH(rl->old_routers, signed_descriptor_t *, sd,
@@ -3802,7 +3779,7 @@ routerlist_free_all(void)
smartlist_free(fallback_dir_servers);
trusted_dir_servers = fallback_dir_servers = NULL;
if (trusted_dir_certs) {
- digestmap_free(trusted_dir_certs, cert_list_free_);
+ digestmap_free(trusted_dir_certs, cert_list_free_void);
trusted_dir_certs = NULL;
}
}
@@ -3926,7 +3903,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
router_describe(router));
*msg = "Router descriptor is not referenced by any network-status.";
- /* Only journal this desc if we'll be serving it. */
+ /* Only journal this desc if we want to keep old descriptors */
if (!from_cache && should_cache_old_descriptors())
signed_desc_append_to_journal(&router->cache_info,
&routerlist->desc_store);
@@ -4100,7 +4077,7 @@ routerlist_remove_old_cached_routers_with_id(time_t now,
signed_descriptor_t *r = smartlist_get(lst, i);
tor_assert(tor_memeq(ident, r->identity_digest, DIGEST_LEN));
}
-#endif
+#endif /* 1 */
/* Check whether we need to do anything at all. */
{
int mdpr = directory_caches_dir_info(get_options()) ? 2 : 1;
@@ -4513,7 +4490,7 @@ router_load_extrainfo_from_string(const char *s, const char *eos,
ei->cache_info.identity_digest,
DIGEST_LEN);
smartlist_string_remove(requested_fingerprints, fp);
- /* We silently let people stuff us with extrainfos we didn't ask for,
+ /* We silently let relays stuff us with extrainfos we didn't ask for,
* so long as we would have wanted them anyway. Since we always fetch
* all the extrainfos we want, and we never actually act on them
* inside Tor, this should be harmless. */
@@ -4556,13 +4533,14 @@ router_load_extrainfo_from_string(const char *s, const char *eos,
smartlist_free(extrainfo_list);
}
-/** Return true iff any networkstatus includes a descriptor whose digest
- * is that of <b>desc</b>. */
+/** Return true iff the latest ns-flavored consensus includes a descriptor
+ * whose digest is that of <b>desc</b>. */
static int
signed_desc_digest_is_recognized(signed_descriptor_t *desc)
{
const routerstatus_t *rs;
- networkstatus_t *consensus = networkstatus_get_latest_consensus();
+ networkstatus_t *consensus = networkstatus_get_latest_consensus_by_flavor(
+ FLAV_NS);
if (consensus) {
rs = networkstatus_vote_find_entry(consensus, desc->identity_digest);
@@ -4578,7 +4556,7 @@ signed_desc_digest_is_recognized(signed_descriptor_t *desc)
void
update_all_descriptor_downloads(time_t now)
{
- if (get_options()->DisableNetwork)
+ if (should_delay_dir_fetches(get_options(), NULL))
return;
update_router_descriptor_downloads(now);
update_microdesc_downloads(now);
@@ -4608,7 +4586,7 @@ router_exit_policy_rejects_all(const routerinfo_t *router)
return router->policy_is_reject_star;
}
-/** Create an directory server at <b>address</b>:<b>port</b>, with OR identity
+/** Create a directory server at <b>address</b>:<b>port</b>, with OR identity
* key <b>digest</b> which has DIGEST_LEN bytes. If <b>address</b> is NULL,
* add ourself. If <b>is_authority</b>, this is a directory authority. Return
* the new directory server entry on success or NULL on failure. */
@@ -4769,7 +4747,7 @@ dir_server_add(dir_server_t *ent)
/** Free storage held in <b>cert</b>. */
void
-authority_cert_free(authority_cert_t *cert)
+authority_cert_free_(authority_cert_t *cert)
{
if (!cert)
return;
@@ -4781,9 +4759,12 @@ authority_cert_free(authority_cert_t *cert)
tor_free(cert);
}
+#define dir_server_free(val) \
+ FREE_AND_NULL(dir_server_t, dir_server_free_, (val))
+
/** Free storage held in <b>ds</b>. */
static void
-dir_server_free(dir_server_t *ds)
+dir_server_free_(dir_server_t *ds)
{
if (!ds)
return;
@@ -4919,9 +4900,10 @@ list_pending_fpsk_downloads(fp_pair_map_t *result)
* range.) If <b>source</b> is given, download from <b>source</b>;
* otherwise, download from an appropriate random directory server.
*/
-MOCK_IMPL(STATIC void, initiate_descriptor_downloads,
- (const routerstatus_t *source, int purpose, smartlist_t *digests,
- int lo, int hi, int pds_flags))
+MOCK_IMPL(STATIC void,
+initiate_descriptor_downloads,(const routerstatus_t *source,
+ int purpose, smartlist_t *digests,
+ int lo, int hi, int pds_flags))
{
char *resource, *cp;
int digest_len, enc_digest_len;
@@ -4973,10 +4955,11 @@ MOCK_IMPL(STATIC void, initiate_descriptor_downloads,
if (source) {
/* We know which authority or directory mirror we want. */
- directory_initiate_command_routerstatus(source, purpose,
- ROUTER_PURPOSE_GENERAL,
- DIRIND_ONEHOP,
- resource, NULL, 0, 0);
+ directory_request_t *req = directory_request_new(purpose);
+ directory_request_set_routerstatus(req, source);
+ directory_request_set_resource(req, resource);
+ directory_initiate_request(req);
+ directory_request_free(req);
} else {
directory_get_from_dirserver(purpose, ROUTER_PURPOSE_GENERAL, resource,
pds_flags, DL_WANT_ANY_DIRSERVER);
@@ -5014,8 +4997,9 @@ max_dl_per_request(const or_options_t *options, int purpose)
}
/** Don't split our requests so finely that we are requesting fewer than
- * this number per server. */
-#define MIN_DL_PER_REQUEST 4
+ * this number per server. (Grouping more than this at once leads to
+ * diminishing returns.) */
+#define MIN_DL_PER_REQUEST 32
/** To prevent a single screwy cache from confusing us by selective reply,
* try to split our requests into at least this many requests. */
#define MIN_REQUESTS 3
@@ -5081,7 +5065,7 @@ launch_descriptor_downloads(int purpose,
}
}
- if (!authdir_mode_any_nonhidserv(options)) {
+ if (!authdir_mode(options)) {
/* If we wind up going to the authorities, we want to only open one
* connection to each authority at a time, so that we don't overload
* them. We do this by setting PDS_NO_EXISTING_SERVERDESC_FETCH
@@ -5103,8 +5087,9 @@ launch_descriptor_downloads(int purpose,
if (n_per_request > max_dl_per_req)
n_per_request = max_dl_per_req;
- if (n_per_request < MIN_DL_PER_REQUEST)
- n_per_request = MIN_DL_PER_REQUEST;
+ if (n_per_request < MIN_DL_PER_REQUEST) {
+ n_per_request = MIN(MIN_DL_PER_REQUEST, n_downloadable);
+ }
if (n_downloadable > n_per_request)
req_plural = rtr_plural = "s";
@@ -5181,8 +5166,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
++n_inprogress;
continue; /* We have an in-progress download. */
}
- if (!download_status_is_ready(&rs->dl_status, now,
- options->TestingDescriptorMaxDownloadTries)) {
+ if (!download_status_is_ready(&rs->dl_status, now)) {
++n_delayed; /* Not ready for retry. */
continue;
}
@@ -5190,8 +5174,8 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
++n_would_reject;
continue; /* We would throw it out immediately. */
}
- if (!directory_caches_dir_info(options) &&
- !client_would_use_router(rs, now, options)) {
+ if (!we_want_to_fetch_flavor(options, consensus->flavor) &&
+ !client_would_use_router(rs, now)) {
++n_wouldnt_use;
continue; /* We would never use it ourself. */
}
@@ -5212,7 +5196,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
smartlist_add(downloadable, rs->descriptor_digest);
} SMARTLIST_FOREACH_END(rsp);
- if (!authdir_mode_handles_descs(options, ROUTER_PURPOSE_GENERAL)
+ if (!authdir_mode_v3(options)
&& smartlist_len(no_longer_old)) {
routerlist_t *rl = router_get_routerlist();
log_info(LD_DIR, "%d router descriptors listed in consensus are "
@@ -5221,15 +5205,30 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
SMARTLIST_FOREACH_BEGIN(no_longer_old, signed_descriptor_t *, sd) {
const char *msg;
was_router_added_t r;
+ time_t tmp_cert_expiration_time;
routerinfo_t *ri = routerlist_reparse_old(rl, sd);
if (!ri) {
log_warn(LD_BUG, "Failed to re-parse a router.");
continue;
}
+ /* need to remember for below, since add_to_routerlist may free. */
+ tmp_cert_expiration_time = ri->cert_expiration_time;
+
r = router_add_to_routerlist(ri, &msg, 1, 0);
if (WRA_WAS_OUTDATED(r)) {
- log_warn(LD_DIR, "Couldn't add re-parsed router: %s",
+ log_warn(LD_DIR, "Couldn't add re-parsed router: %s. This isn't "
+ "usually a big deal, but you should make sure that your "
+ "clock and timezone are set correctly.",
msg?msg:"???");
+ if (r == ROUTER_CERTS_EXPIRED) {
+ char time_cons[ISO_TIME_LEN+1];
+ char time_cert_expires[ISO_TIME_LEN+1];
+ format_iso_time(time_cons, consensus->valid_after);
+ format_iso_time(time_cert_expires, tmp_cert_expiration_time);
+ log_warn(LD_DIR, " (I'm looking at a consensus from %s; This "
+ "router's certificates began expiring at %s.)",
+ time_cons, time_cert_expires);
+ }
}
} SMARTLIST_FOREACH_END(sd);
routerlist_assert_ok(rl);
@@ -5343,8 +5342,7 @@ update_extrainfo_downloads(time_t now)
++n_have;
continue;
}
- if (!download_status_is_ready(&sd->ei_dl_status, now,
- options->TestingDescriptorMaxDownloadTries)) {
+ if (!download_status_is_ready(&sd->ei_dl_status, now)) {
++n_delay;
continue;
}
@@ -5406,8 +5404,10 @@ update_extrainfo_downloads(time_t now)
smartlist_free(wanted);
}
-/** Reset the descriptor download failure count on all routers, so that we
- * can retry any long-failed routers immediately.
+/** Reset the consensus and extra-info download failure count on all routers.
+ * When we get a new consensus,
+ * routers_update_status_from_consensus_networkstatus() will reset the
+ * download statuses on the descriptors in that consensus.
*/
void
router_reset_descriptor_download_failures(void)
@@ -5419,6 +5419,8 @@ router_reset_descriptor_download_failures(void)
last_descriptor_download_attempted = 0;
if (!routerlist)
return;
+ /* We want to download *all* extra-info descriptors, not just those in
+ * the consensus we currently have (or are about to have) */
SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
{
download_status_reset(&ri->cache_info.ei_dl_status);
@@ -5660,11 +5662,11 @@ routerstatus_version_supports_extend2_cells(const routerstatus_t *rs,
return allow_unknown_versions;
}
- if (!rs->protocols_known) {
+ if (!rs->pv.protocols_known) {
return allow_unknown_versions;
}
- return rs->supports_extend2_cells;
+ return rs->pv.supports_extend2_cells;
}
/** Assert that the internal representation of <b>rl</b> is