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