浏览代码

Merge remote branch 'origin/maint-0.2.2'

Resolved nontrivial conflict around rewrite_x_address_for_bridge and
learned_bridge_descriptor.  Now, since leanred_bridge_descriptor works
on nodes, we must make sure that rewrite_node_address_for_bridge also
works on nodes.

Conflicts:
	src/or/circuitbuild.c
Nick Mathewson 14 年之前
父节点
当前提交
e91a8c5589
共有 5 个文件被更改,包括 84 次插入3 次删除
  1. 8 0
      changes/bug2510
  2. 6 0
      changes/bug2511
  3. 53 2
      src/or/circuitbuild.c
  4. 1 0
      src/or/or.h
  5. 16 1
      src/or/routerlist.c

+ 8 - 0
changes/bug2510

@@ -0,0 +1,8 @@
+  o Major bugfixes:
+    - Fix a bug where bridge users who configure the non-canonical
+      address of a bridge automatically switch to its canonical
+      address. If a bridge listens at more than one address, it should be
+      able to advertise those addresses independently and any non-blocked
+      addresses should continue to work. Bugfix on Tor 0.2.0.x. Fixes
+      bug 2510.
+

+ 6 - 0
changes/bug2511

@@ -0,0 +1,6 @@
+  o Major bugfixes:
+    - If you configured Tor to use bridge A, and then quit and
+      configured Tor to use bridge B instead, it would happily continue
+      to use bridge A if it's still reachable. While this behavior is
+      a feature if your goal is connectivity, in some scenarios it's a
+      dangerous bug. Bugfix on Tor 0.2.0.1-alpha; fixes bug 2511.

+ 53 - 2
src/or/circuitbuild.c

@@ -4688,6 +4688,55 @@ fetch_bridge_descriptors(or_options_t *options, time_t now)
   SMARTLIST_FOREACH_END(bridge);
 }
 
+/** If our <b>bridge</b> is configured to be a different address than
+ * the bridge gives in <b>node</b>, rewrite the routerinfo
+ * we received to use the address we meant to use. Now we handle
+ * multihomed bridges better.
+ */
+static void
+rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
+{
+  /* XXXX move this function. */
+  /* XXXX overridden addresses should really live in the node_t, so that the
+   *   routerinfo_t and the microdesc_t can be immutable.  But we can only
+   *   do that safely if
+   */
+  tor_addr_t addr;
+
+  if (node->ri) {
+    routerinfo_t *ri = node->ri;
+    tor_addr_from_ipv4h(&addr, ri->addr);
+
+    if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
+        bridge->port == ri->or_port) {
+      /* they match, so no need to do anything */
+    } else {
+      ri->addr = tor_addr_to_ipv4h(&bridge->addr);
+      tor_free(ri->address);
+      ri->address = tor_dup_ip(ri->addr);
+      ri->or_port = bridge->port;
+      log_info(LD_DIR,
+               "Adjusted bridge '%s' to match configured address %s:%d.",
+               ri->nickname, ri->address, ri->or_port);
+    }
+  }
+  if (node->rs) {
+    routerstatus_t *rs = node->rs;
+    tor_addr_from_ipv4h(&addr, rs->addr);
+
+    if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
+        bridge->port == rs->or_port) {
+      /* they match, so no need to do anything */
+    } else {
+      rs->addr = tor_addr_to_ipv4h(&bridge->addr);
+      rs->or_port = bridge->port;
+      log_info(LD_DIR,
+               "Adjusted bridge '%s' to match configured address %s:%d.",
+               rs->nickname, fmt_addr(&bridge->addr), rs->or_port);
+    }
+  }
+}
+
 /** We just learned a descriptor for a bridge. See if that
  * digest is in our entry guard list, and add it if not. */
 void
@@ -4702,14 +4751,16 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
     router_set_status(ri->cache_info.identity_digest, 1);
 
     if (bridge) { /* if we actually want to use this one */
-      const node_t *node;
+      node_t *node;
       /* it's here; schedule its re-fetch for a long time from now. */
       if (!from_cache)
         download_status_reset(&bridge->fetch_status);
 
-      node = node_get_by_id(ri->cache_info.identity_digest);
+      node = node_get_mutable_by_id(ri->cache_info.identity_digest);
       tor_assert(node);
+      rewrite_node_address_for_bridge(bridge, node);
       add_an_entry_guard(node, 1);
+
       log_notice(LD_DIR, "new bridge descriptor '%s' (%s)", ri->nickname,
                  from_cache ? "cached" : "fresh");
       /* set entry->made_contact so if it goes down we don't drop it from

+ 1 - 0
src/or/or.h

@@ -3687,6 +3687,7 @@ typedef enum was_router_added_t {
   ROUTER_NOT_IN_CONSENSUS = -3,
   ROUTER_NOT_IN_CONSENSUS_OR_NETWORKSTATUS = -4,
   ROUTER_AUTHDIR_REJECTS = -5,
+  ROUTER_WAS_NOT_WANTED = -6
 } was_router_added_t;
 
 /********************************* routerparse.c ************************/

+ 16 - 1
src/or/routerlist.c

@@ -3233,7 +3233,8 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
                          int from_cache, int from_fetch)
 {
   const char *id_digest;
-  int authdir = authdir_mode_handles_descs(get_options(), router->purpose);
+  or_options_t *options = get_options();
+  int authdir = authdir_mode_handles_descs(options, router->purpose);
   int authdir_believes_valid = 0;
   routerinfo_t *old_router;
   networkstatus_t *consensus = networkstatus_get_latest_consensus();
@@ -3339,6 +3340,20 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
     return ROUTER_NOT_IN_CONSENSUS;
   }
 
+  /* If we're reading a bridge descriptor from our cache, and we don't
+   * recognize it as one of our currently configured bridges, drop the
+   * descriptor. Otherwise we could end up using it as one of our entry
+   * guards even if it isn't in our Bridge config lines. */
+  if (router->purpose == ROUTER_PURPOSE_BRIDGE && from_cache &&
+      !authdir_mode_bridge(options) &&
+      !routerinfo_is_a_configured_bridge(router)) {
+    log_info(LD_DIR, "Dropping bridge descriptor for '%s' because we have "
+             "no bridge configured at that address.", router->nickname);
+    *msg = "Router descriptor was not a configured bridge.";
+    routerinfo_free(router);
+    return ROUTER_WAS_NOT_WANTED;
+  }
+
   /* If we have a router with the same identity key, choose the newer one. */
   if (old_router) {
     if (!in_consensus && (router->cache_info.published_on <=