[tor-commits] [tor/master] Parse GuardFraction info from consensuses and votes.

nickm at torproject.org nickm at torproject.org
Wed Feb 18 14:20:13 UTC 2015


commit f4a63f8eabbdd842ebeb97aabba92ea47c37a607
Author: George Kadianakis <desnacked at riseup.net>
Date:   Thu Jan 29 14:57:00 2015 +0000

    Parse GuardFraction info from consensuses and votes.
    
    Also introduce the UseGuardFraction torrc option which decides whether
    clients should use guardfraction information found in the consensus.
---
 doc/tor.1.txt        |    6 +++++
 src/or/config.c      |    1 +
 src/or/entrynodes.c  |   21 ++++++++++++++++
 src/or/entrynodes.h  |    2 ++
 src/or/or.h          |    6 +++++
 src/or/routerparse.c |   65 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/or/routerparse.h |    7 ++++++
 7 files changed, 108 insertions(+)

diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 3de3048..8ecece0 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -1122,6 +1122,12 @@ The following options are useful only for clients (that is, if
     guardfraction file which contains information about how long relays
     have been guards. (Default: unset)
 
+[[UseGuardFraction]] **UseGuardFraction** **0**|**1**|**auto**::
+    This torrc option specifies whether clients should use the
+    guardfraction information found in the consensus during path
+    selection. If it's set to 'auto', clients will do what the
+    UseGuardFraction consensus parameter tells them to do.
+
 [[NumEntryGuards]] **NumEntryGuards** __NUM__::
     If UseEntryGuards is set to 1, we will try to pick a total of NUM routers
     as long-term entries for our circuits. If NUM is 0, we try to learn
diff --git a/src/or/config.c b/src/or/config.c
index 6349445..230ea7f 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -411,6 +411,7 @@ static config_var_t option_vars_[] = {
   V(UseBridges,                  BOOL,     "0"),
   V(UseEntryGuards,              BOOL,     "1"),
   V(UseEntryGuardsAsDirGuards,   BOOL,     "1"),
+  V(UseGuardFraction,            AUTOBOOL, "auto"),
   V(UseMicrodescriptors,         AUTOBOOL, "auto"),
   V(UseNTorHandshake,            AUTOBOOL, "1"),
   V(User,                        STRING,   NULL),
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 5b0e342..a766f6c 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -1694,6 +1694,27 @@ getinfo_helper_entry_guards(control_connection_t *conn,
   return 0;
 }
 
+/** Return 0 if we should apply guardfraction information found in the
+ *  consensus. A specific consensus can be specified with the
+ *  <b>ns</b> argument, if NULL the most recent one will be picked.*/
+int
+should_apply_guardfraction(const networkstatus_t *ns)
+{
+  /* We need to check the corresponding torrc option and the consensus
+   * parameter if we need to. */
+  const or_options_t *options = get_options();
+
+  /* If UseGuardFraction is 'auto' then check the same-named consensus
+   * parameter. If the consensus parameter is not present, default to
+   * "off". */
+  if (options->UseGuardFraction == -1) {
+    return networkstatus_get_param(ns, "UseGuardFraction",
+                                   0, /* default to "off" */
+                                   0, 1);
+  }
+
+  return options->UseGuardFraction;
+}
 /** A list of configured bridges. Whenever we actually get a descriptor
  * for one, we add it as an entry guard.  Note that the order of bridges
  * in this list does not necessarily correspond to the order of bridges
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 7f3a4fb..96d832e 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -160,5 +160,7 @@ int validate_pluggable_transports_config(void);
 double pathbias_get_close_success_count(entry_guard_t *guard);
 double pathbias_get_use_success_count(entry_guard_t *guard);
 
+int should_apply_guardfraction(const networkstatus_t *ns);
+
 #endif
 
diff --git a/src/or/or.h b/src/or/or.h
index 1f2231e..b8d4e1a 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3818,6 +3818,12 @@ typedef struct {
   int NumEntryGuards; /**< How many entry guards do we try to establish? */
   int UseEntryGuardsAsDirGuards; /** Boolean: Do we try to get directory info
                                   * from a smallish number of fixed nodes? */
+
+  /** If 1, we use any guardfraction information we see in the
+   * consensus.  If 0, we don't.  If -1, let the consensus parameter
+   * decide. */
+  int UseGuardFraction;
+
   int NumDirectoryGuards; /**< How many dir guards do we try to establish?
                            * If 0, use value from NumEntryGuards. */
   int RephistTrackTime; /**< How many seconds do we keep rephist info? */
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index a2bc8fb..8a00544 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -9,6 +9,8 @@
  * \brief Code to parse and validate router descriptors and directories.
  **/
 
+#define ROUTERPARSE_PRIVATE
+
 #include "or.h"
 #include "config.h"
 #include "circuitstats.h"
@@ -23,6 +25,7 @@
 #include "networkstatus.h"
 #include "rephist.h"
 #include "routerparse.h"
+#include "entrynodes.h"
 #undef log
 #include <math.h>
 
@@ -1792,6 +1795,63 @@ find_start_of_next_routerstatus(const char *s)
     return eos;
 }
 
+/** Parse the GuardFraction string from a consensus or vote.
+ *
+ *  If <b>vote</b> or <b>vote_rs</b> are set the document getting
+ *  parsed is a vote routerstatus. Otherwise it's a consensus. This is
+ *  the same semantic as in routerstatus_parse_entry_from_string(). */
+STATIC int
+routerstatus_parse_guardfraction(const char *guardfraction_str,
+                                 networkstatus_t *vote,
+                                 vote_routerstatus_t *vote_rs,
+                                 routerstatus_t *rs)
+{
+  int ok;
+  const char *end_of_header = NULL;
+  int is_consensus = !vote_rs;
+  uint32_t guardfraction;
+
+  tor_assert(bool_eq(vote, vote_rs));
+
+  /* If this info comes from a consensus, but we should't apply
+     guardfraction, just exit. */
+  if (is_consensus && !should_apply_guardfraction(NULL)) {
+    return 0;
+  }
+
+  end_of_header = strchr(guardfraction_str, '=');
+  if (!end_of_header) {
+    return -1;
+  }
+
+  guardfraction = (uint32_t)tor_parse_ulong(end_of_header+1,
+                                         10, 0, 100, &ok, NULL);
+  if (!ok) {
+    log_warn(LD_DIR, "Invalid GuardFraction %s", escaped(guardfraction_str));
+    return -1;
+  }
+
+  log_warn(LD_GENERAL, "[*] Parsed %s guardfraction '%s' for '%s'.",
+           is_consensus ? "consensus" : "vote",
+           guardfraction_str, rs->nickname);
+
+  if (!is_consensus) { /* We are parsing a vote */
+    vote_rs->status.guardfraction_percentage = guardfraction;
+    vote_rs->status.has_guardfraction = 1;
+  } else {
+    /* We are parsing a consensus. Only apply guardfraction to guards. */
+    if (rs->is_possible_guard) {
+      rs->guardfraction_percentage = guardfraction;
+      rs->has_guardfraction = 1;
+    } else {
+      log_warn(LD_BUG, "Got GuardFraction for non-guard %s. "
+               "This is not supposed to happen. Not applying. ", rs->nickname);
+    }
+  }
+
+  return 0;
+}
+
 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
  * empty smartlist at <b>tokens</b>, parse and return the first router status
  * object in the string, and advance *<b>s</b> to just after the end of the
@@ -1994,6 +2054,11 @@ routerstatus_parse_entry_from_string(memarea_t *area,
         vote->has_measured_bws = 1;
       } else if (!strcmpstart(tok->args[i], "Unmeasured=1")) {
         rs->bw_is_unmeasured = 1;
+      } else if (!strcmpstart(tok->args[i], "GuardFraction=")) {
+        if (routerstatus_parse_guardfraction(tok->args[i],
+                                             vote, vote_rs, rs) < 0) {
+          goto err;
+        }
       }
     }
   }
diff --git a/src/or/routerparse.h b/src/or/routerparse.h
index 18a7d25..fc21cb1 100644
--- a/src/or/routerparse.h
+++ b/src/or/routerparse.h
@@ -85,5 +85,12 @@ int rend_parse_introduction_points(rend_service_descriptor_t *parsed,
                                    size_t intro_points_encoded_size);
 int rend_parse_client_keys(strmap_t *parsed_clients, const char *str);
 
+#ifdef ROUTERPARSE_PRIVATE
+STATIC int routerstatus_parse_guardfraction(const char *guardfraction_str,
+                                            networkstatus_t *vote,
+                                            vote_routerstatus_t *vote_rs,
+                                            routerstatus_t *rs);
+#endif
+
 #endif
 





More information about the tor-commits mailing list