summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Dingledine <arma@torproject.org>2012-01-25 18:54:59 -0500
committerRoger Dingledine <arma@torproject.org>2012-01-25 18:54:59 -0500
commita0f0897795c45d22ad2d2dde98c81195a9db24dc (patch)
tree715f4ce9819073bca879b40f01c7030a7b4bc603
parent247a21379af1cf90896d9818cf448d9687f6277c (diff)
downloadtor-a0f0897795c45d22ad2d2dde98c81195a9db24dc.tar.gz
tor-a0f0897795c45d22ad2d2dde98c81195a9db24dc.zip
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. The fix here is to revert to using normal descriptors if any of our bridges are known to not support microdescs. This is not ideal, a) because we'll start downloading a microdesc consensus as soon as we get a bridge descriptor, and that will waste time if we later get a bridge descriptor that tells us we don't like microdescriptors; and b) by changing our mind we're leaking to our other bridges that we have an old-version bridge. The alternate fix would have been to change we_use_microdescriptors_for_circuits() to ask if *any* of our bridges can support microdescriptors, and then change the directory logic that picks a bridge to only select from those that do. For people living in the future, where 0.2.2.x is obsolete, there won't be a difference. Note that in either of these potential fixes, we have risk of oscillation if our one funny-looking bridges goes away / comes back.
-rw-r--r--changes/bug40136
-rw-r--r--src/or/circuitbuild.c26
-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, 61 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..70e35967e6 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,30 @@ entries_retry_all(const or_options_t *options)
entries_retry_helper(options, 1);
}
+/** Return true if one of our bridges is 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;
+ if (!get_options()->UseBridges || !entry_guards)
+ return 0;
+ 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. */
+ 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);