summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2012-01-31 11:25:29 -0500
committerNick Mathewson <nickm@torproject.org>2012-01-31 11:25:29 -0500
commit23054543278a8ee5db6d8dae3b3a96e2b2fd5377 (patch)
tree87510491013834371d243fff4d7312baf729c327
parent48424772aa9a7b3ed4710471a205a841d69337bd (diff)
parentb1ee1927b124aa63d91cdc8feda7fb7e3d4bd05f (diff)
downloadtor-23054543278a8ee5db6d8dae3b3a96e2b2fd5377.tar.gz
tor-23054543278a8ee5db6d8dae3b3a96e2b2fd5377.zip
Merge remote-tracking branch 'arma/bug4013'
-rw-r--r--changes/bug40136
-rw-r--r--src/or/circuitbuild.c30
-rw-r--r--src/or/circuitbuild.h2
-rw-r--r--src/or/directory.c14
-rw-r--r--src/or/microdesc.c11
-rw-r--r--src/or/routerparse.c15
-rw-r--r--src/or/routerparse.h3
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);