[tor-commits] [tor/master] Check if there are exits in the consensus

nickm at torproject.org nickm at torproject.org
Tue Dec 30 14:08:00 UTC 2014


commit 9b2d106e49ba4ea12f31af9cea02910869f19a4b
Author: teor <teor2345 at gmail.com>
Date:   Fri Dec 26 00:10:40 2014 +1100

    Check if there are exits in the consensus
    
    Add router_have_consensus_path() which reports whether
    the consensus has exit paths, internal paths, or whether it
    just doesn't know.
    
    Used by #13718 and #13814.
---
 changes/bug13718-check-consensus-exits |    6 ++++
 src/or/nodelist.c                      |   59 ++++++++++++++++++++++++++++++--
 src/or/nodelist.h                      |   22 ++++++++++++
 3 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/changes/bug13718-check-consensus-exits b/changes/bug13718-check-consensus-exits
new file mode 100644
index 0000000..5ca4b11
--- /dev/null
+++ b/changes/bug13718-check-consensus-exits
@@ -0,0 +1,6 @@
+  o Minor enhancement:
+    - Check if there are exits in the consensus.
+      Add router_have_consensus_path() which reports whether
+      the consensus has exit paths, internal paths, or whether it
+      just doesn't know.
+      Used by #13718 and #13814.
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
index 796d0ec..77196a4 100644
--- a/src/or/nodelist.c
+++ b/src/or/nodelist.c
@@ -1275,6 +1275,10 @@ router_set_status(const char *digest, int up)
 /** True iff, the last time we checked whether we had enough directory info
  * to build circuits, the answer was "yes". */
 static int have_min_dir_info = 0;
+
+/** Does the consensus contain nodes that can exit? */
+static consensus_path_type_t have_consensus_path = CONSENSUS_PATH_UNKNOWN;
+
 /** True iff enough has changed since the last time we checked whether we had
  * enough directory info to build circuits that our old answer can no longer
  * be trusted. */
@@ -1308,6 +1312,24 @@ router_have_minimum_dir_info(void)
   return have_min_dir_info;
 }
 
+/** Set to CONSENSUS_PATH_EXIT if there is at least one exit node
+ * in the consensus. We update this flag in compute_frac_paths_available if
+ * there is at least one relay that has an Exit flag in the consensus.
+ * Used to avoid building exit circuits when they will almost certainly fail.
+ * Set to CONSENSUS_PATH_INTERNAL if there are no exits in the consensus.
+ * (This situation typically occurs during bootstrap of a test network.)
+ * Set to CONSENSUS_PATH_UNKNOWN if we have never checked, or have
+ * reason to believe our last known value was invalid or has expired.
+ * If we're in a network with TestingDirAuthVoteExit set,
+ * this can cause router_have_consensus_path() to be set to
+ * CONSENSUS_PATH_EXIT, even if there are no nodes with accept exit policies.
+ */
+consensus_path_type_t
+router_have_consensus_path(void)
+{
+  return have_consensus_path;
+}
+
 /** Called when our internal view of the directory has changed.  This can be
  * when the authorities change, networkstatuses change, the list of routerdescs
  * changes, or number of running routers changes.
@@ -1396,7 +1418,11 @@ compute_frac_paths_available(const networkstatus_t *consensus,
   smartlist_t *myexits= smartlist_new();
   smartlist_t *myexits_unflagged = smartlist_new();
   double f_guard, f_mid, f_exit, f_myexit, f_myexit_unflagged;
-  int np, nu; /* Ignored */
+  double f_path = 0.0;
+  /* Used to determine whether there are any exits in the consensus */
+  int np = 0;
+  /* Used to determine whether there are any exits with descriptors */
+  int nu = 0;
   const int authdir = authdir_mode_v3(options);
 
   count_usable_descriptors(num_present_out, num_usable_out,
@@ -1417,7 +1443,13 @@ compute_frac_paths_available(const networkstatus_t *consensus,
     });
   }
 
-  /* All nodes with exit flag */
+  /* All nodes with exit flag
+   * If we're in a network with TestingDirAuthVoteExit set,
+   * this can cause false positives on have_consensus_path,
+   * incorrectly setting it to CONSENSUS_PATH_EXIT. This is
+   * an unavoidable feature of forcing authorities to declare
+   * certain nodes as exits.
+   */
   count_usable_descriptors(&np, &nu, exits, consensus, options, now,
                            NULL, USABLE_DESCRIPTOR_EXIT_ONLY);
   log_debug(LD_NET,
@@ -1426,6 +1458,27 @@ compute_frac_paths_available(const networkstatus_t *consensus,
             np,
             nu);
 
+  /* We need at least 1 exit present in the consensus to consider
+   * building exit paths */
+  /* Update our understanding of whether the consensus has exits */
+  consensus_path_type_t old_have_consensus_path = have_consensus_path;
+  have_consensus_path = ((np > 0) ?
+                         CONSENSUS_PATH_EXIT :
+                         CONSENSUS_PATH_INTERNAL);
+
+  if (have_consensus_path == CONSENSUS_PATH_INTERNAL
+      && old_have_consensus_path != have_consensus_path) {
+    log_notice(LD_NET,
+               "The current consensus has no exit nodes. "
+               "Tor can only build internal paths, "
+               "such as paths to hidden services.");
+
+    /* However, exit nodes can reachability self-test using this consensus,
+     * join the network, and appear in a later consensus. This will allow
+     * the network to build exit paths, such as paths for world wide web
+     * browsing (as distinct from hidden service web browsing). */
+  }
+
   /* All nodes with exit flag in ExitNodes option */
   count_usable_descriptors(&np, &nu, myexits, consensus, options, now,
                            options->ExitNodes, USABLE_DESCRIPTOR_EXIT_ONLY);
@@ -1620,7 +1673,7 @@ update_router_have_minimum_dir_info(void)
      * should only do while circuits are working, like reachability tests
      * and fetching bridge descriptors only over circuits. */
     note_that_we_maybe_cant_complete_circuits();
-
+    have_consensus_path = CONSENSUS_PATH_UNKNOWN;
     control_event_client_status(LOG_NOTICE, "NOT_ENOUGH_DIR_INFO");
   }
   have_min_dir_info = res;
diff --git a/src/or/nodelist.h b/src/or/nodelist.h
index 48b0e94..56cfffa 100644
--- a/src/or/nodelist.h
+++ b/src/or/nodelist.h
@@ -80,6 +80,28 @@ int router_exit_policy_all_nodes_reject(const tor_addr_t *addr, uint16_t port,
                                         int need_uptime);
 void router_set_status(const char *digest, int up);
 int router_have_minimum_dir_info(void);
+
+/** Set to CONSENSUS_PATH_EXIT if there is at least one exit node
+ * in the consensus. We update this flag in compute_frac_paths_available if
+ * there is at least one relay that has an Exit flag in the consensus.
+ * Used to avoid building exit circuits when they will almost certainly fail.
+ * Set to CONSENSUS_PATH_INTERNAL if there are no exits in the consensus.
+ * (This situation typically occurs during bootstrap of a test network.)
+ * Set to CONSENSUS_PATH_UNKNOWN if we have never checked, or have
+ * reason to believe our last known value was invalid or has expired.
+ */
+typedef enum {
+  /* we haven't checked yet, or we have invalidated our previous check */
+  CONSENSUS_PATH_UNKNOWN = -1,
+  /* The consensus only has internal relays, and we should only
+   * create internal paths, circuits, streams, ... */
+  CONSENSUS_PATH_INTERNAL = 0,
+  /* The consensus has at least one exit, and can therefore (potentially)
+   * create exit and internal paths, circuits, streams, ... */
+  CONSENSUS_PATH_EXIT = 1
+} consensus_path_type_t;
+consensus_path_type_t router_have_consensus_path(void);
+
 void router_dir_info_changed(void);
 const char *get_dir_info_status_string(void);
 int count_loading_descriptors_progress(void);





More information about the tor-commits mailing list