]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Allow 0.2.3.x clients to use 0.2.2.x bridges.
authorRoger Dingledine <arma@torproject.org>
Wed, 25 Jan 2012 23:54:59 +0000 (18:54 -0500)
committerRoger Dingledine <arma@torproject.org>
Wed, 25 Jan 2012 23:54:59 +0000 (18:54 -0500)
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.

changes/bug4013 [new file with mode: 0644]
src/or/circuitbuild.c
src/or/circuitbuild.h
src/or/directory.c
src/or/microdesc.c
src/or/routerparse.c
src/or/routerparse.h

diff --git a/changes/bug4013 b/changes/bug4013
new file mode 100644 (file)
index 0000000..4a41968
--- /dev/null
@@ -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.
+
index d35c08e20329296a2d285cb1cd1deb8d94619d07..70e35967e6743cb81455bb3151293b9cf4537a4e 100644 (file)
@@ -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
index cded3993c4f312d9685a7ca526d0172dbeadca7a..a7fd2083055aac14695cac52371bee40cb54148f 100644 (file)
@@ -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;
index 149e692f07044ad4b51c952e9d905b3f92f9b4df..c6a527cb3c873011016a2122b1e3aee21d172f19 100644 (file)
@@ -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. */
index 0a1ae91cce3c94d2c19c1e8d50b113b3ba99be6d..be9b99759c997bb5b290ebcc05b518c6d74262fd 100644 (file)
@@ -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;
index 7a0fd17c21e040e6edee5b964fb0196b690183c3..28ec9452ca65c0bfb5683684e5d553341d946b39 100644 (file)
@@ -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.
index 65f6c424180983d486bfbfc80f3c9d39e10bd586..b274d2196cb738bdd58e51089beee4abb596b712 100644 (file)
@@ -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);