diff options
-rw-r--r-- | changes/bug4013 | 6 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 30 | ||||
-rw-r--r-- | src/or/circuitbuild.h | 2 | ||||
-rw-r--r-- | src/or/directory.c | 14 | ||||
-rw-r--r-- | src/or/microdesc.c | 11 | ||||
-rw-r--r-- | src/or/routerparse.c | 15 | ||||
-rw-r--r-- | src/or/routerparse.h | 3 |
7 files changed, 65 insertions, 16 deletions
diff --git a/changes/bug4013 b/changes/bug4013 new file mode 100644 index 0000000000..4a41968bc6 --- /dev/null +++ b/changes/bug4013 @@ -0,0 +1,6 @@ + o Major bugfixes: + - Allow 0.2.3.x clients to use 0.2.2.x bridges. Previously the client + would ask the bridge for microdescriptors, which are only supported + in 0.2.3.x and later, and then fail to bootstrap when it didn't + get the answers it wanted. Fixes bug 4013; bugfix on 0.2.3.2-alpha. + diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index d35c08e203..07598e242f 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -3339,7 +3339,7 @@ extend_info_from_router(const routerinfo_t *r, int for_direct_connect) } /** Allocate and return a new extend_info that can be used to build a - * ircuit to or through the node <b>node</b>. Use the primary address + * circuit to or through the node <b>node</b>. Use the primary address * of the node unless <b>for_direct_connect</b> is true, in which case * the preferred address is used instead. May return NULL if there is * not enough info about <b>node</b> to extend to it--for example, if @@ -5328,6 +5328,34 @@ entries_retry_all(const or_options_t *options) entries_retry_helper(options, 1); } +/** Return true if we've ever had a bridge running a Tor version that can't + * provide microdescriptors to us. In that case fall back to asking for + * full descriptors. Eventually all bridges will support microdescriptors + * and we can take this check out; see bug 4013. */ +int +any_bridges_dont_support_microdescriptors(void) +{ + const node_t *node; + static int ever_answered_yes = 0; + if (!get_options()->UseBridges || !entry_guards) + return 0; + if (ever_answered_yes) + return 1; /* if we ever answer 'yes', always answer 'yes' */ + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { + node = node_get_by_id(e->identity); + if (node && node->ri && + node_is_bridge(node) && node_is_a_configured_bridge(node) && + !tor_version_supports_microdescriptors(node->ri->platform)) { + /* This is one of our current bridges, and we know enough about + * it to know that it won't be able to answer our microdescriptor + * questions. */ + ever_answered_yes = 1; + return 1; + } + } SMARTLIST_FOREACH_END(e); + return 0; +} + /** Release all storage held by the list of entry guards and related * memory structs. */ void diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h index cded3993c4..a7fd208305 100644 --- a/src/or/circuitbuild.h +++ b/src/or/circuitbuild.h @@ -100,6 +100,8 @@ int any_pending_bridge_descriptor_fetches(void); int entries_known_but_down(const or_options_t *options); void entries_retry_all(const or_options_t *options); +int any_bridges_dont_support_microdescriptors(void); + void entry_guards_free_all(void); extern circuit_build_times_t circ_times; diff --git a/src/or/directory.c b/src/or/directory.c index 149e692f07..c6a527cb3c 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -421,11 +421,15 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, if (!get_via_tor) { 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 */ - /* It certainly is not true with conditional consensus downloading, - * so, for now, never assume the server supports that. */ + /* We want to ask a running bridge for which we have a descriptor. + * + * Be careful here: we should only ask questions that we know our + * bridges can answer. So far we're solving that by backing off to + * the behavior supported by our oldest bridge; see for example + * any_bridges_dont_support_microdescriptors(). + */ + /* XXX024 Not all bridges handle conditional consensus downloading, + * so, for now, never assume the server supports that. -PP */ const node_t *node = choose_random_entry(NULL); if (node && node->ri) { /* every bridge has a routerinfo. */ diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 0a1ae91cce..be9b99759c 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -2,6 +2,7 @@ /* See LICENSE for licensing information */ #include "or.h" +#include "circuitbuild.h" #include "config.h" #include "directory.h" #include "dirserv.h" @@ -720,8 +721,14 @@ we_use_microdescriptors_for_circuits(const 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, - * and we're not autofetching everything. */ + /* If we are configured to use bridges and one of our bridges doesn't + * know what a microdescriptor is, the answer is no. */ + if (options->UseBridges && any_bridges_dont_support_microdescriptors()) + return 0; + /* Otherwise, we decide that we'll use microdescriptors iff we are + * not a server, and we're not autofetching everything. */ + /* XXX023 what does not being a server have to do with it? also there's + * a partitioning issue here where bridges differ from clients. */ ret = !server_mode(options) && !options->FetchUselessDescriptors; } return ret; diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 7a0fd17c21..28ec9452ca 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -2125,14 +2125,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"); - /* 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"); + tor_version_supports_microdescriptors(tok->args[0]); rs->version_supports_optimistic_data = tor_version_as_new_as(tok->args[0], "0.2.3.1-alpha"); } @@ -4431,6 +4425,13 @@ microdescs_parse_from_string(const char *s, const char *eos, return result; } +/** Return true iff this Tor version can answer directory questions + * about microdescriptors. */ +int tor_version_supports_microdescriptors(const char *platform) +{ + return tor_version_as_new_as(platform, "0.2.3.1-alpha"); +} + /** Parse the Tor version of the platform string <b>platform</b>, * and compare it to the version in <b>cutoff</b>. Return 1 if * the router is at least as new as the cutoff, else return 0. diff --git a/src/or/routerparse.h b/src/or/routerparse.h index 65f6c42418..b274d2196c 100644 --- a/src/or/routerparse.h +++ b/src/or/routerparse.h @@ -44,8 +44,9 @@ addr_policy_t *router_parse_addr_policy_item_from_string(const char *s, int assume_action); version_status_t tor_version_is_obsolete(const char *myversion, const char *versionlist); -int tor_version_parse(const char *s, tor_version_t *out); +int tor_version_supports_microdescriptors(const char *platform); int tor_version_as_new_as(const char *platform, const char *cutoff); +int tor_version_parse(const char *s, tor_version_t *out); int tor_version_compare(tor_version_t *a, tor_version_t *b); int tor_version_same_series(tor_version_t *a, tor_version_t *b); void sort_version_list(smartlist_t *lst, int remove_duplicates); |