Browse Source

Merge remote-tracking branch 'arma/bug4013'

Nick Mathewson 12 years ago
parent
commit
2305454327
7 changed files with 65 additions and 16 deletions
  1. 6 0
      changes/bug4013
  2. 29 1
      src/or/circuitbuild.c
  3. 2 0
      src/or/circuitbuild.h
  4. 9 5
      src/or/directory.c
  5. 9 2
      src/or/microdesc.c
  6. 8 7
      src/or/routerparse.c
  7. 2 1
      src/or/routerparse.h

+ 6 - 0
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.
+

+ 29 - 1
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

+ 2 - 0
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;

+ 9 - 5
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. */

+ 9 - 2
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;

+ 8 - 7
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.

+ 2 - 1
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);