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.
This commit is contained in:
George Kadianakis 2015-01-29 14:57:00 +00:00 committed by Nick Mathewson
parent db805b9170
commit f4a63f8eab
7 changed files with 108 additions and 0 deletions

View File

@ -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

View File

@ -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),

View File

@ -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

View File

@ -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

View File

@ -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? */

View File

@ -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;
}
}
}
}

View File

@ -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