tor-commits
Threads by month
- ----- 2025 -----
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
December 2016
- 18 participants
- 2010 discussions

16 Dec '16
commit 6a02f9f35a824ced871de7bb80c8266b873a0710
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Tue Nov 15 08:38:33 2016 -0500
Add parameters for new (prop271) guard algorithm.
These are taken from the proposal, and defined there. Some of them
should turn into consensus parameters.
Also, remove some dead code that was there to make compilation work,
and use ATTR_UNUSED like a normal person.
---
src/or/entrynodes.c | 34 ++++++++++++++++++++++++----------
src/or/networkstatus.h | 4 ----
2 files changed, 24 insertions(+), 14 deletions(-)
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 461d29f..c6ed59d 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -151,6 +151,26 @@ should_apply_guardfraction(const networkstatus_t *ns)
}
/**@}*/
+/**
+ * @name Parameters for new (prop271) entry guard algorithm.
+ */
+/* XXXX prop271 some of these should be networkstatus parameters */
+#define MIN_SAMPLE_THRESHOLD 15
+#define MAX_SAMPLE_THRESHOLD 50
+#define GUARD_LIFETIME_DAYS 120
+#define REMOVE_UNLISTED_GUARDS_AFTER_DAYS 20
+#define MIN_FILTERED_SAMPLE_SIZE 20
+#define N_PRIMARY_GUARDS 3
+#define PRIMARY_GUARDS_RETRY_SCHEDULE /* XXX prop271 */
+#define OTHER_GUARDS_RETRY_SCHEDULE /* XXX prop271 */
+#define INTERNET_LIKELY_DOWN_INTERVAL (10*60)
+#define NONPRIMARY_GUARD_CONNECT_TIMEOUT 15
+#define NONPRIMARY_GUARD_IDLE_TIMEOUT (10*60)
+#define MEANINGFUL_RESTRICTION_FRAC 0.2
+#define EXTREME_RESTRICTION_FRAC 0.01
+#define GUARD_CONFIRMED_MIN_LIFETIME_DAYS 60
+/**}@*/
+
/** Allocate a new guard_selection_t */
static guard_selection_t *
@@ -254,12 +274,11 @@ randomize_time(time_t now, time_t max_backdate)
/**
* DOCDOC
*/
-STATIC void
+ATTR_UNUSED STATIC void
entry_guard_add_to_sample(guard_selection_t *gs,
node_t *node)
{
- (void) entry_guard_add_to_sample; // XXXX prop271 remove -- unused
- const int GUARD_LIFETIME = 90 * 86400; // xxxx prop271
+ const int GUARD_LIFETIME = GUARD_LIFETIME_DAYS * 86400;
tor_assert(gs);
tor_assert(node);
@@ -296,7 +315,7 @@ entry_guard_add_to_sample(guard_selection_t *gs,
* Return a newly allocated string for encoding the persistent parts of
* <b>guard</b> to the state file.
*/
-STATIC char *
+ATTR_UNUSED STATIC char *
entry_guard_encode_for_state(entry_guard_t *guard)
{
/*
@@ -356,7 +375,7 @@ entry_guard_encode_for_state(entry_guard_t *guard)
* (if possible) and return an entry_guard_t object for it. Return NULL
* on complete failure.
*/
-STATIC entry_guard_t *
+ATTR_UNUSED STATIC entry_guard_t *
entry_guard_parse_from_state(const char *s)
{
/* Unrecognized entries get put in here. */
@@ -1776,9 +1795,6 @@ entry_guards_parse_state_for_guard_selection(
const char *state_version = state->TorVersion;
digestmap_t *added_by = digestmap_new();
- if (0) entry_guard_parse_from_state(NULL); // XXXX prop271 remove -- unused
- if (0) entry_guard_add_to_sample(NULL, NULL); // XXXX prop271 remove
-
tor_assert(gs != NULL);
*msg = NULL;
@@ -2104,8 +2120,6 @@ entry_guards_update_state(or_state_t *state)
config_line_t **next, *line;
guard_selection_t *gs = get_guard_selection_info();
- if (0) entry_guard_encode_for_state(NULL); // XXXX prop271 remove -- unused
-
tor_assert(gs != NULL);
tor_assert(gs->chosen_entry_guards != NULL);
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index 96f8347..71f36b6 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -111,10 +111,6 @@ int32_t networkstatus_get_param(const networkstatus_t *ns,
const char *param_name,
int32_t default_val, int32_t min_val,
int32_t max_val);
-int32_t networkstatus_get_param(const networkstatus_t *ns,
- const char *param_name,
- int32_t default_val, int32_t min_val,
- int32_t max_val);
int getinfo_helper_networkstatus(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg);
1
0
commit 238828c92b1cc186577e44490caf4fa3870e724d
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Nov 21 16:59:00 2016 -0500
Add a new GUARD_WAIT state for circuits
This state corresponds to the WAITING_FOR_BETTER_GUARD state; it's
for circuits that are 100% constructed, but which we won't use until
we are sure that we wouldn't use circuits with a better guard.
---
src/or/circuitlist.c | 20 ++++++++++++++++----
src/or/control.c | 5 ++++-
src/or/or.h | 6 +++++-
3 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index f13126d..0189412 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -439,7 +439,13 @@ circuit_set_state(circuit_t *circ, uint8_t state)
/* add to waiting-circuit list. */
smartlist_add(circuits_pending_chans, circ);
}
- if (state == CIRCUIT_STATE_OPEN)
+ if (circ->state == CIRCUIT_STATE_GUARD_WAIT) {
+ smartlist_remove(circuits_pending_other_guards, circ);
+ }
+ if (state == CIRCUIT_STATE_GUARD_WAIT) {
+ smartlist_add(circuits_pending_other_guards, circ);
+ }
+ if (state == CIRCUIT_STATE_GUARD_WAIT || state == CIRCUIT_STATE_OPEN)
tor_assert(!circ->n_chan_create_cell);
circ->state = state;
}
@@ -542,6 +548,8 @@ circuit_state_to_string(int state)
case CIRCUIT_STATE_BUILDING: return "doing handshakes";
case CIRCUIT_STATE_ONIONSKIN_PENDING: return "processing the onion";
case CIRCUIT_STATE_CHAN_WAIT: return "connecting to server";
+ case CIRCUIT_STATE_GUARD_WAIT: return "waiting to see how other "
+ "guards perform";
case CIRCUIT_STATE_OPEN: return "open";
default:
log_warn(LD_BUG, "Unknown circuit state %d", state);
@@ -1868,7 +1876,8 @@ circuit_about_to_free(circuit_t *circ)
* module then. If it isn't OPEN, we send it there now to remember which
* links worked and which didn't.
*/
- if (circ->state != CIRCUIT_STATE_OPEN) {
+ if (circ->state != CIRCUIT_STATE_OPEN &&
+ circ->state != CIRCUIT_STATE_GUARD_WAIT) {
if (CIRCUIT_IS_ORIGIN(circ)) {
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
circuit_build_failed(ocirc); /* take actions if necessary */
@@ -1881,7 +1890,9 @@ circuit_about_to_free(circuit_t *circ)
}
if (CIRCUIT_IS_ORIGIN(circ)) {
control_event_circuit_status(TO_ORIGIN_CIRCUIT(circ),
- (circ->state == CIRCUIT_STATE_OPEN)?CIRC_EVENT_CLOSED:CIRC_EVENT_FAILED,
+ (circ->state == CIRCUIT_STATE_OPEN ||
+ circ->state == CIRCUIT_STATE_GUARD_WAIT) ?
+ CIRC_EVENT_CLOSED:CIRC_EVENT_FAILED,
orig_reason);
}
@@ -2403,7 +2414,8 @@ assert_circuit_ok(const circuit_t *c)
tor_assert(c->deliver_window >= 0);
tor_assert(c->package_window >= 0);
- if (c->state == CIRCUIT_STATE_OPEN) {
+ if (c->state == CIRCUIT_STATE_OPEN ||
+ c->state == CIRCUIT_STATE_GUARD_WAIT) {
tor_assert(!c->n_chan_create_cell);
if (or_circ) {
tor_assert(or_circ->n_crypto);
diff --git a/src/or/control.c b/src/or/control.c
index 1d7ec1b..9cc99b6 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -2596,6 +2596,8 @@ getinfo_helper_events(control_connection_t *control_conn,
if (circ->base_.state == CIRCUIT_STATE_OPEN)
state = "BUILT";
+ else if (circ->base_.state == CIRCUIT_STATE_GUARD_WAIT)
+ state = "GUARD_WAIT"; // XXXX prop271 must specify this.
else if (circ->cpath)
state = "EXTENDED";
else
@@ -3379,7 +3381,8 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
goto done;
}
} else {
- if (circ->base_.state == CIRCUIT_STATE_OPEN) {
+ if (circ->base_.state == CIRCUIT_STATE_OPEN ||
+ circ->base_.state == CIRCUIT_STATE_GUARD_WAIT) {
int err_reason = 0;
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) {
diff --git a/src/or/or.h b/src/or/or.h
index 4bc8066..eb0025d 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -438,8 +438,12 @@ typedef enum {
/** Circuit state: I'd like to deliver a create, but my n_chan is still
* connecting. */
#define CIRCUIT_STATE_CHAN_WAIT 2
+/** Circuit state: the circuit is open but we don't want to actually use it
+ * until we find out if a better guard will be available.
+ */
+#define CIRCUIT_STATE_GUARD_WAIT 3
/** Circuit state: onionskin(s) processed, ready to send/receive cells. */
-#define CIRCUIT_STATE_OPEN 3
+#define CIRCUIT_STATE_OPEN 4
#define CIRCUIT_PURPOSE_MIN_ 1
1
0

[tor/master] New function to tell the guard module "We're on the net!"
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit 1fd0a547bb6af73cbc32be06ffbf6233eb9050a6
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Nov 21 17:14:04 2016 -0500
New function to tell the guard module "We're on the net!"
(Call it whenever we read a cell.)
---
src/or/channeltls.c | 9 +++++++++
src/or/entrynodes.c | 8 ++++++++
src/or/entrynodes.h | 12 +++++++++++-
3 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index 9fb309d..02b783a 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -49,6 +49,7 @@
#include "connection.h"
#include "connection_or.h"
#include "control.h"
+#include "entrynodes.h"
#include "link_handshake.h"
#include "relay.h"
#include "rephist.h"
@@ -1095,6 +1096,10 @@ channel_tls_handle_cell(cell_t *cell, or_connection_t *conn)
if (conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3)
or_handshake_state_record_cell(conn, conn->handshake_state, cell, 1);
+ /* We note that we're on the internet whenever we read a cell. This is
+ * a fast operation. */
+ entry_guards_note_internet_connectivity(get_guard_selection_info());
+
switch (cell->command) {
case CELL_PADDING:
++stats_n_padding_cells_processed;
@@ -1273,6 +1278,10 @@ channel_tls_handle_var_cell(var_cell_t *var_cell, or_connection_t *conn)
return;
}
+ /* We note that we're on the internet whenever we read a cell. This is
+ * a fast operation. */
+ entry_guards_note_internet_connectivity(get_guard_selection_info());
+
/* Now handle the cell */
switch (var_cell->command) {
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 959b422..4a99897 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -1039,6 +1039,14 @@ entry_guard_consider_retry(entry_guard_t *guard)
}
}
+/** Tell the entry guards subsystem that we have confirmed that as of
+ * just now, we're on the internet. */
+void
+entry_guards_note_internet_connectivity(guard_selection_t *gs)
+{
+ gs->last_time_on_internet = approx_time();
+}
+
/**
* Get a guard for use with a circuit. Prefer to pick a running primary
* guard; then a non-pending running filtered confirmed guard; then a
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 5b3aa66..7119d54 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -283,6 +283,13 @@ struct circuit_guard_state_t {
};
#endif
+/* Common entry points for old and new guard code */
+void guards_update_all(void);
+const node_t *guards_choose_guard(cpath_build_state_t *state,
+ circuit_guard_state_t **guard_state_out);
+const node_t *guards_choose_dirguard(dirinfo_type_t info,
+ circuit_guard_state_t **guard_state_out);
+
#if 1
/* XXXX NM I would prefer that all of this stuff be private to
* entrynodes.c. */
@@ -313,12 +320,15 @@ int entry_guard_pick_for_circuit(guard_selection_t *gs,
circuit_guard_state_t **guard_state_out);
int entry_guard_succeeded(guard_selection_t *gs,
circuit_guard_state_t **guard_state_p);
-int entry_guard_failed(guard_selection_t *gs,
+void entry_guard_failed(guard_selection_t *gs,
circuit_guard_state_t **guard_state_p);
+void entry_guard_chan_failed(guard_selection_t *gs,
+ channel_t *chan);
void entry_guards_update_all(guard_selection_t *gs);
int entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
smartlist_t *all_circuits,
smartlist_t *newly_complete_out);
+void entry_guards_note_internet_connectivity(guard_selection_t *gs);
/* Used by bridges.c only. */
void add_bridge_as_entry_guard(guard_selection_t *gs,
1
0

16 Dec '16
commit dd6def5daf5b0b579a61c9e83cfa905b333f99a1
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Nov 14 15:46:09 2016 -0500
Initial code to parse/encode/sample prop271 guards
The encoding code is very straightforward. The decoding code is a
bit tricky, but clean-ish. The sampling code is untested and
probably needs more work.
---
src/or/entrynodes.c | 310 ++++++++++++++++++++++++++++++++++++++++++++-
src/or/entrynodes.h | 14 +-
src/test/test_entrynodes.c | 243 +++++++++++++++++++++++++++++++++++
3 files changed, 564 insertions(+), 3 deletions(-)
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index c96ff09..9af7140 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -77,6 +77,11 @@ struct guard_selection_s {
int dirty;
/**
+ * A list of the sampled entry guards, as entry_guard_t structures.
+ * Not in any particular order. */
+ smartlist_t *sampled_entry_guards;
+
+ /**
* A list of our chosen entry guards, as entry_guard_t structures; this
* preserves the pre-Prop271 behavior.
*/
@@ -87,6 +92,8 @@ struct guard_selection_s {
* config's EntryNodes first? This was formerly a global.
*/
int should_add_entry_nodes;
+
+ int filtered_up_to_date;
};
static smartlist_t *guard_contexts = NULL;
@@ -118,6 +125,7 @@ guard_selection_new(void)
gs = tor_malloc_zero(sizeof(*gs));
gs->chosen_entry_guards = smartlist_new();
+ gs->sampled_entry_guards = smartlist_new();
return gs;
}
@@ -191,6 +199,293 @@ entry_guard_get_pathbias_state(entry_guard_t *guard)
return &guard->pb;
}
+/** Return an interval betweeen 'now' and 'max_backdate' seconds in the past,
+ * chosen uniformly at random. */
+STATIC time_t
+randomize_time(time_t now, time_t max_backdate)
+{
+ tor_assert(max_backdate > 0);
+
+ time_t earliest = now - max_backdate;
+ time_t latest = now;
+ if (earliest <= 0)
+ earliest = 1;
+ if (latest <= earliest)
+ latest = earliest + 1;
+
+ return crypto_rand_time_range(earliest, latest);
+}
+
+/**
+ * DOCDOC
+ */
+STATIC void
+entry_guard_add_to_sample(guard_selection_t *gs,
+ node_t *node)
+{
+ (void) entry_guard_add_to_sample; // XXXX prop271 remove -- unused
+ const int GUARD_LIFETIME = 90 * 86400; // xxxx prop271
+ tor_assert(gs);
+ tor_assert(node);
+
+ // XXXX prop271 take ed25519 identity here too.
+
+ /* make sure that the guard is not already sampled. */
+ SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards,
+ entry_guard_t *, sampled) {
+ if (BUG(tor_memeq(node->identity, sampled->identity, DIGEST_LEN))) {
+ return;
+ }
+ } SMARTLIST_FOREACH_END(sampled);
+
+ entry_guard_t *guard = tor_malloc_zero(sizeof(entry_guard_t));
+
+ /* persistent fields */
+ memcpy(guard->identity, node->identity, DIGEST_LEN);
+ strlcpy(guard->nickname, node_get_nickname(node), sizeof(guard->nickname));
+ guard->sampled_on_date = randomize_time(approx_time(), GUARD_LIFETIME/10);
+ tor_free(guard->sampled_by_version);
+ guard->sampled_by_version = tor_strdup(VERSION);
+ guard->confirmed_idx = -1;
+
+ /* non-persistent fields */
+ guard->is_reachable = GUARD_REACHABLE_MAYBE;
+
+ smartlist_add(gs->sampled_entry_guards, guard);
+ gs->filtered_up_to_date = 0;
+
+ entry_guards_changed_for_guard_selection(gs);
+}
+
+/**
+ * Return a newly allocated string for encoding the persistent parts of
+ * <b>guard</b> to the state file.
+ */
+STATIC char *
+entry_guard_encode_for_state(entry_guard_t *guard)
+{
+ /*
+ * The meta-format we use is K=V K=V K=V... where K can be any
+ * characters excepts space and =, and V can be any characters except
+ * space. The order of entries is not allowed to matter.
+ * Unrecognized K=V entries are persisted; recognized but erroneous
+ * entries are corrected.
+ */
+
+ smartlist_t *result = smartlist_new();
+ char tbuf[ISO_TIME_LEN+1];
+
+ tor_assert(guard);
+
+ smartlist_add_asprintf(result, "rsa_id=%s",
+ hex_str(guard->identity, DIGEST_LEN));
+ if (strlen(guard->nickname)) {
+ smartlist_add_asprintf(result, "nickname=%s", guard->nickname);
+ }
+
+ format_iso_time_nospace(tbuf, guard->sampled_on_date);
+ smartlist_add_asprintf(result, "sampled_on=%s", tbuf);
+
+ if (guard->sampled_by_version) {
+ smartlist_add_asprintf(result, "sampled_by=%s",
+ guard->sampled_by_version);
+ }
+
+ if (guard->unlisted_since_date > 0) {
+ format_iso_time_nospace(tbuf, guard->unlisted_since_date);
+ smartlist_add_asprintf(result, "unlisted_since=%s", tbuf);
+ }
+
+ smartlist_add_asprintf(result, "listed=%d",
+ (int)guard->currently_listed);
+
+ if (guard->confirmed_idx >= 0) {
+ format_iso_time_nospace(tbuf, guard->confirmed_on_date);
+ smartlist_add_asprintf(result, "confirmed_on=%s", tbuf);
+
+ smartlist_add_asprintf(result, "confirmed_idx=%d", guard->confirmed_idx);
+ }
+
+ if (guard->extra_state_fields)
+ smartlist_add_strdup(result, guard->extra_state_fields);
+
+ char *joined = smartlist_join_strings(result, " ", 0, NULL);
+ SMARTLIST_FOREACH(result, char *, cp, tor_free(cp));
+ smartlist_free(result);
+
+ return joined;
+}
+
+/**
+ * Given a string generated by entry_guard_encode_for_state(), parse it
+ * (if possible) and return an entry_guard_t object for it. Return NULL
+ * on complete failure.
+ */
+STATIC entry_guard_t *
+entry_guard_parse_from_state(const char *s)
+{
+ /* Unrecognized entries get put in here. */
+ smartlist_t *extra = smartlist_new();
+
+ /* These fields get parsed from the string. */
+ char *rsa_id = NULL;
+ char *nickname = NULL;
+ char *sampled_on = NULL;
+ char *sampled_by = NULL;
+ char *unlisted_since = NULL;
+ char *listed = NULL;
+ char *confirmed_on = NULL;
+ char *confirmed_idx = NULL;
+
+ /* Split up the entries. Put the ones we know about in strings and the
+ * rest in "extra". */
+ {
+ smartlist_t *entries = smartlist_new();
+
+ strmap_t *vals = strmap_new(); // Maps keyword to location
+ strmap_set(vals, "rsa_id", &rsa_id);
+ strmap_set(vals, "nickname", &nickname);
+ strmap_set(vals, "sampled_on", &sampled_on);
+ strmap_set(vals, "sampled_by", &sampled_by);
+ strmap_set(vals, "unlisted_since", &unlisted_since);
+ strmap_set(vals, "listed", &listed);
+ strmap_set(vals, "confirmed_on", &confirmed_on);
+ strmap_set(vals, "confirmed_idx", &confirmed_idx);
+
+ smartlist_split_string(entries, s, " ",
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+
+ SMARTLIST_FOREACH_BEGIN(entries, char *, entry) {
+ const char *eq = strchr(entry, '=');
+ if (!eq) {
+ smartlist_add(extra, entry);
+ continue;
+ }
+ char *key = tor_strndup(entry, eq-entry);
+ char **target = strmap_get(vals, key);
+ if (target == NULL || *target != NULL) {
+ /* unrecognized or already set */
+ smartlist_add(extra, entry);
+ tor_free(key);
+ continue;
+ }
+
+ *target = tor_strdup(eq+1);
+ tor_free(key);
+ tor_free(entry);
+ } SMARTLIST_FOREACH_END(entry);
+
+ smartlist_free(entries);
+ strmap_free(vals, NULL);
+ }
+
+ entry_guard_t *guard = tor_malloc_zero(sizeof(entry_guard_t));
+
+ if (rsa_id == NULL) {
+ log_warn(LD_CIRC, "Guard missing RSA ID field");
+ goto err;
+ }
+
+ /* Process the identity and nickname. */
+ if (base16_decode(guard->identity, sizeof(guard->identity),
+ rsa_id, strlen(rsa_id)) != DIGEST_LEN) {
+ log_warn(LD_CIRC, "Unable to decode guard identity %s", escaped(rsa_id));
+ goto err;
+ }
+
+ if (nickname) {
+ strlcpy(guard->nickname, nickname, sizeof(guard->nickname));
+ } else {
+ guard->nickname[0]='$';
+ base16_encode(guard->nickname+1, sizeof(guard->nickname)-1,
+ guard->identity, DIGEST_LEN);
+ }
+
+ /* Process the various time fields. */
+
+#define HANDLE_TIME(field) do { \
+ if (field) { \
+ int r = parse_iso_time_nospace(field, &field ## _time); \
+ if (r < 0) { \
+ log_warn(LD_CIRC, "Unable to parse %s %s from guard", \
+ #field, escaped(field)); \
+ field##_time = -1; \
+ } \
+ } \
+ } while (0)
+
+ time_t sampled_on_time = 0;
+ time_t unlisted_since_time = 0;
+ time_t confirmed_on_time = 0;
+
+ HANDLE_TIME(sampled_on);
+ HANDLE_TIME(unlisted_since);
+ HANDLE_TIME(confirmed_on);
+
+ if (sampled_on_time <= 0)
+ sampled_on_time = approx_time();
+ if (unlisted_since_time < 0)
+ unlisted_since_time = 0;
+ if (confirmed_on_time < 0)
+ confirmed_on_time = 0;
+
+ #undef HANDLE_TIME
+
+ guard->sampled_on_date = sampled_on_time;
+ guard->unlisted_since_date = unlisted_since_time;
+ guard->confirmed_on_date = confirmed_on_time;
+
+ /* Take sampled_by_version verbatim. */
+ guard->sampled_by_version = sampled_by;
+ sampled_by = NULL; /* prevent free */
+
+ /* Listed is a boolean */
+ if (listed && strcmp(listed, "0"))
+ guard->currently_listed = 1;
+
+ /* The index is a nonnegative integer. */
+ guard->confirmed_idx = -1;
+ if (confirmed_idx) {
+ int ok=1;
+ long idx = tor_parse_long(confirmed_idx, 10, 0, INT_MAX, &ok, NULL);
+ if (! ok) {
+ log_warn(LD_CIRC, "Guard has invalid confirmed_idx %s",
+ escaped(confirmed_idx));
+ } else {
+ guard->confirmed_idx = (int)idx;
+ }
+ }
+
+ /* Anything we didn't recognize gets crammed together */
+ if (smartlist_len(extra) > 0) {
+ guard->extra_state_fields = smartlist_join_strings(extra, " ", 0, NULL);
+ }
+
+ /* initialize non-persistent fields */
+ guard->is_reachable = GUARD_REACHABLE_MAYBE;
+
+ goto done;
+
+ err:
+ // only consider it an error if the guard state was totally unparseable.
+ entry_guard_free(guard);
+ guard = NULL;
+
+ done:
+ tor_free(rsa_id);
+ tor_free(nickname);
+ tor_free(sampled_on);
+ tor_free(sampled_by);
+ tor_free(unlisted_since);
+ tor_free(listed);
+ tor_free(confirmed_on);
+ tor_free(confirmed_idx);
+ SMARTLIST_FOREACH(extra, char *, cp, tor_free(cp));
+ smartlist_free(extra);
+
+ return guard;
+}
+
/** Check whether the entry guard <b>e</b> is usable, given the directory
* authorities' opinion about the router (stored in <b>ri</b>) and the user's
* configuration (in <b>options</b>). Set <b>e</b>->bad_since
@@ -677,13 +972,14 @@ pick_entry_guards(guard_selection_t *gs,
#define ENTRY_GUARD_REMOVE_AFTER (30*24*60*60)
/** Release all storage held by <b>e</b>. */
-static void
+STATIC void
entry_guard_free(entry_guard_t *e)
{
if (!e)
return;
tor_free(e->chosen_by_version);
tor_free(e->sampled_by_version);
+ tor_free(e->extra_state_fields);
tor_free(e);
}
@@ -1452,6 +1748,9 @@ entry_guards_parse_state_for_guard_selection(
const char *state_version = state->TorVersion;
digestmap_t *added_by = digestmap_new();
+ if (0) entry_guard_parse_from_state(NULL); // XXXX prop271 remove -- unused
+ if (0) entry_guard_add_to_sample(NULL, NULL); // XXXX prop271 remove
+
tor_assert(gs != NULL);
*msg = NULL;
@@ -1777,6 +2076,8 @@ entry_guards_update_state(or_state_t *state)
config_line_t **next, *line;
guard_selection_t *gs = get_guard_selection_info();
+ if (0) entry_guard_encode_for_state(NULL); // XXXX prop271 remove -- unused
+
tor_assert(gs != NULL);
tor_assert(gs->chosen_entry_guards != NULL);
@@ -2837,6 +3138,13 @@ guard_selection_free(guard_selection_t *gs)
gs->chosen_entry_guards = NULL;
}
+ if (gs->sampled_entry_guards) {
+ SMARTLIST_FOREACH(gs->sampled_entry_guards, entry_guard_t *, e,
+ entry_guard_free(e));
+ smartlist_free(gs->sampled_entry_guards);
+ gs->sampled_entry_guards = NULL;
+ }
+
tor_free(gs);
}
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 4f39a09..5c0857b 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -63,7 +63,7 @@ typedef struct guard_pathbias_t {
* use a node_t, since we want to remember these even when we
* don't have any directory info. */
struct entry_guard_t {
- char nickname[MAX_NICKNAME_LEN+1];
+ char nickname[MAX_HEX_NICKNAME_LEN+1];
char identity[DIGEST_LEN];
ed25519_public_key_t ed_id;
@@ -71,7 +71,7 @@ struct entry_guard_t {
/* Persistent fields, present for all sampled guards. */
time_t sampled_on_date;
- time_t unlisted_since_date;
+ time_t unlisted_since_date; // can be zero
char *sampled_by_version;
unsigned currently_listed : 1;
@@ -93,6 +93,9 @@ struct entry_guard_t {
unsigned is_filtered_guard : 1;
unsigned is_usable_filtered_guard : 1;
+ /** This string holds any fields that we are maintaining because
+ * we saw them in the state, even if we don't understand them. */
+ char *extra_state_fields;
/**
* @name legacy guard selection algorithm fields
*
@@ -152,6 +155,13 @@ const char *entry_guard_describe(const entry_guard_t *guard);
guard_pathbias_t *entry_guard_get_pathbias_state(entry_guard_t *guard);
#ifdef ENTRYNODES_PRIVATE
+STATIC time_t randomize_time(time_t now, time_t max_backdate);
+STATIC void entry_guard_add_to_sample(guard_selection_t *gs,
+ node_t *node);
+STATIC char *entry_guard_encode_for_state(entry_guard_t *guard);
+STATIC entry_guard_t *entry_guard_parse_from_state(const char *s);
+STATIC void entry_guard_free(entry_guard_t *e);
+
STATIC const node_t *add_an_entry_guard(guard_selection_t *gs,
const node_t *chosen,
int reset_status, int prepend,
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index aa1b455..45b730c 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -859,6 +859,236 @@ test_entry_guard_describe(void *arg)
;
}
+static void
+test_entry_guard_randomize_time(void *arg)
+{
+ const time_t now = 1479153573;
+ const int delay = 86400;
+ const int N = 1000;
+ (void)arg;
+
+ time_t t;
+ int i;
+ for (i = 0; i < N; ++i) {
+ t = randomize_time(now, delay);
+ tt_int_op(t, OP_LE, now);
+ tt_int_op(t, OP_GE, now-delay);
+ }
+
+ /* now try the corner cases */
+ for (i = 0; i < N; ++i) {
+ t = randomize_time(100, delay);
+ tt_int_op(t, OP_GE, 1);
+ tt_int_op(t, OP_LE, 100);
+
+ t = randomize_time(0, delay);
+ tt_int_op(t, OP_EQ, 1);
+ }
+
+ done:
+ ;
+}
+
+static void
+test_entry_guard_encode_for_state_minimal(void *arg)
+{
+ (void) arg;
+ entry_guard_t *eg = tor_malloc_zero(sizeof(entry_guard_t));
+
+ memcpy(eg->identity, "plurpyflurpyslurpydo", DIGEST_LEN);
+ eg->sampled_on_date = 1479081600;
+ eg->confirmed_idx = -1;
+
+ char *s = NULL;
+ s = entry_guard_encode_for_state(eg);
+
+ tt_str_op(s, OP_EQ,
+ "rsa_id=706C75727079666C75727079736C75727079646F "
+ "sampled_on=2016-11-14T00:00:00 "
+ "listed=0");
+
+ done:
+ entry_guard_free(eg);
+ tor_free(s);
+}
+
+static void
+test_entry_guard_encode_for_state_maximal(void *arg)
+{
+ (void) arg;
+ entry_guard_t *eg = tor_malloc_zero(sizeof(entry_guard_t));
+
+ strlcpy(eg->nickname, "Fred", sizeof(eg->nickname));
+ memcpy(eg->identity, "plurpyflurpyslurpydo", DIGEST_LEN);
+ eg->sampled_on_date = 1479081600;
+ eg->sampled_by_version = tor_strdup("1.2.3");
+ eg->unlisted_since_date = 1479081645;
+ eg->currently_listed = 1;
+ eg->confirmed_on_date = 1479081690;
+ eg->confirmed_idx = 333;
+ eg->extra_state_fields = tor_strdup("and the green grass grew all around");
+
+ char *s = NULL;
+ s = entry_guard_encode_for_state(eg);
+
+ tt_str_op(s, OP_EQ,
+ "rsa_id=706C75727079666C75727079736C75727079646F "
+ "nickname=Fred "
+ "sampled_on=2016-11-14T00:00:00 "
+ "sampled_by=1.2.3 "
+ "unlisted_since=2016-11-14T00:00:45 "
+ "listed=1 "
+ "confirmed_on=2016-11-14T00:01:30 "
+ "confirmed_idx=333 "
+ "and the green grass grew all around");
+
+ done:
+ entry_guard_free(eg);
+ tor_free(s);
+}
+
+static void
+test_entry_guard_parse_from_state_minimal(void *arg)
+{
+ (void)arg;
+ char *mem_op_hex_tmp = NULL;
+ entry_guard_t *eg = NULL;
+ time_t t = approx_time();
+
+ eg = entry_guard_parse_from_state(
+ "rsa_id=596f75206d6179206e656564206120686f626279");
+ tt_assert(eg);
+
+ test_mem_op_hex(eg->identity, OP_EQ,
+ "596f75206d6179206e656564206120686f626279");
+ tt_str_op(eg->nickname, OP_EQ, "$596F75206D6179206E656564206120686F626279");
+ tt_i64_op(eg->sampled_on_date, OP_GE, t);
+ tt_i64_op(eg->sampled_on_date, OP_LE, t+86400);
+ tt_i64_op(eg->unlisted_since_date, OP_EQ, 0);
+ tt_ptr_op(eg->sampled_by_version, OP_EQ, NULL);
+ tt_int_op(eg->currently_listed, OP_EQ, 0);
+ tt_i64_op(eg->confirmed_on_date, OP_EQ, 0);
+ tt_int_op(eg->confirmed_idx, OP_EQ, -1);
+
+ tt_int_op(eg->last_tried_to_connect, OP_EQ, 0);
+ tt_int_op(eg->is_reachable, OP_EQ, GUARD_REACHABLE_MAYBE);
+
+ done:
+ entry_guard_free(eg);
+ tor_free(mem_op_hex_tmp);
+}
+
+static void
+test_entry_guard_parse_from_state_maximal(void *arg)
+{
+ (void)arg;
+ char *mem_op_hex_tmp = NULL;
+ entry_guard_t *eg = NULL;
+
+ eg = entry_guard_parse_from_state(
+ "rsa_id=706C75727079666C75727079736C75727079646F "
+ "nickname=Fred "
+ "sampled_on=2016-11-14T00:00:00 "
+ "sampled_by=1.2.3 "
+ "unlisted_since=2016-11-14T00:00:45 "
+ "listed=1 "
+ "confirmed_on=2016-11-14T00:01:30 "
+ "confirmed_idx=333 "
+ "and the green grass grew all around "
+ "rsa_id=all,around");
+ tt_assert(eg);
+
+ test_mem_op_hex(eg->identity, OP_EQ,
+ "706C75727079666C75727079736C75727079646F");
+ tt_str_op(eg->nickname, OP_EQ, "Fred");
+ tt_i64_op(eg->sampled_on_date, OP_EQ, 1479081600);
+ tt_i64_op(eg->unlisted_since_date, OP_EQ, 1479081645);
+ tt_str_op(eg->sampled_by_version, OP_EQ, "1.2.3");
+ tt_int_op(eg->currently_listed, OP_EQ, 1);
+ tt_i64_op(eg->confirmed_on_date, OP_EQ, 1479081690);
+ tt_int_op(eg->confirmed_idx, OP_EQ, 333);
+ tt_str_op(eg->extra_state_fields, OP_EQ,
+ "and the green grass grew all around rsa_id=all,around");
+
+ tt_int_op(eg->last_tried_to_connect, OP_EQ, 0);
+ tt_int_op(eg->is_reachable, OP_EQ, GUARD_REACHABLE_MAYBE);
+
+ done:
+ entry_guard_free(eg);
+ tor_free(mem_op_hex_tmp);
+}
+
+static void
+test_entry_guard_parse_from_state_failure(void *arg)
+{
+ (void)arg;
+ entry_guard_t *eg = NULL;
+
+ /* no RSA ID. */
+ eg = entry_guard_parse_from_state("nickname=Fred");
+ tt_assert(! eg);
+
+ /* Bad RSA ID: bad character. */
+ eg = entry_guard_parse_from_state(
+ "rsa_id=596f75206d6179206e656564206120686f62627q");
+ tt_assert(! eg);
+
+ /* Bad RSA ID: too long.*/
+ eg = entry_guard_parse_from_state(
+ "rsa_id=596f75206d6179206e656564206120686f6262703");
+ tt_assert(! eg);
+
+ /* Bad RSA ID: too short.*/
+ eg = entry_guard_parse_from_state(
+ "rsa_id=596f75206d6179206e65656420612");
+ tt_assert(! eg);
+
+ done:
+ entry_guard_free(eg);
+}
+
+static void
+test_entry_guard_parse_from_state_partial_failure(void *arg)
+{
+ (void)arg;
+ char *mem_op_hex_tmp = NULL;
+ entry_guard_t *eg = NULL;
+ time_t t = approx_time();
+
+ eg = entry_guard_parse_from_state(
+ "rsa_id=706C75727079666C75727079736C75727079646F "
+ "nickname=FredIsANodeWithAStrangeNicknameThatIsTooLong "
+ "sampled_on=2016-11-14T00:00:99 "
+ "sampled_by=1.2.3 stuff in the middle "
+ "unlisted_since=2016-xx-14T00:00:45 "
+ "listed=0 "
+ "confirmed_on=2016-11-14T00:01:30zz "
+ "confirmed_idx=idx "
+ "and the green grass grew all around "
+ "rsa_id=all,around");
+ tt_assert(eg);
+
+ test_mem_op_hex(eg->identity, OP_EQ,
+ "706C75727079666C75727079736C75727079646F");
+ tt_str_op(eg->nickname, OP_EQ, "FredIsANodeWithAStrangeNicknameThatIsTooL");
+ tt_i64_op(eg->sampled_on_date, OP_EQ, t);
+ tt_i64_op(eg->unlisted_since_date, OP_EQ, 0);
+ tt_str_op(eg->sampled_by_version, OP_EQ, "1.2.3");
+ tt_int_op(eg->currently_listed, OP_EQ, 0);
+ tt_i64_op(eg->confirmed_on_date, OP_EQ, 0);
+ tt_int_op(eg->confirmed_idx, OP_EQ, -1);
+ tt_str_op(eg->extra_state_fields, OP_EQ,
+ "stuff in the middle and the green grass grew all around "
+ "rsa_id=all,around");
+
+ tt_int_op(eg->last_tried_to_connect, OP_EQ, 0);
+ tt_int_op(eg->is_reachable, OP_EQ, GUARD_REACHABLE_MAYBE);
+
+ done:
+ entry_guard_free(eg);
+ tor_free(mem_op_hex_tmp);
+}
+
static const struct testcase_setup_t fake_network = {
fake_network_setup, fake_network_cleanup
};
@@ -893,6 +1123,19 @@ struct testcase_t entrynodes_tests[] = {
test_node_preferred_orport,
0, NULL, NULL },
{ "entry_guard_describe", test_entry_guard_describe, 0, NULL, NULL },
+ { "randomize_time", test_entry_guard_randomize_time, 0, NULL, NULL },
+ { "encode_for_state_minimal",
+ test_entry_guard_encode_for_state_minimal, 0, NULL, NULL },
+ { "encode_for_state_maximal",
+ test_entry_guard_encode_for_state_maximal, 0, NULL, NULL },
+ { "parse_from_state_minimal",
+ test_entry_guard_parse_from_state_minimal, 0, NULL, NULL },
+ { "parse_from_state_maximal",
+ test_entry_guard_parse_from_state_maximal, 0, NULL, NULL },
+ { "parse_from_state_failure",
+ test_entry_guard_parse_from_state_failure, 0, NULL, NULL },
+ { "parse_from_state_partial_failure",
+ test_entry_guard_parse_from_state_partial_failure, 0, NULL, NULL },
END_OF_TESTCASES
};
1
0

[tor/master] Write the easy parts of the public entryguard interface.
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit dd6bdab3f6254e7245f8ee76b2c6b4314f0472fa
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Fri Nov 18 16:05:09 2016 -0500
Write the easy parts of the public entryguard interface.
Here we add a little bit of state to origin circuits, and set up
the necessary functions for the circuit code to call in order to
find guards, use guards, and decide when circuits can be used.
There's also an incomplete function for the hard part of the
circuit-maintenance code, where we figure out whether any waiting
guards are ready to become usable.
(This patch finally uses the handle.c code to make safe handles to
entry_guard_t objects, so that we are allowed to free an
entry_guard_t without checking whether any origin_circuit_t is
holding a reference to it.)
---
src/or/circuitbuild.c | 7 ++
src/or/circuitbuild.h | 2 +
src/or/circuitlist.c | 2 +
src/or/entrynodes.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++----
src/or/entrynodes.h | 38 ++++++++++
src/or/or.h | 5 ++
6 files changed, 241 insertions(+), 13 deletions(-)
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index b482e78..a33c2ca 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -519,6 +519,13 @@ circuit_establish_circuit(uint8_t purpose, extend_info_t *exit_ei, int flags)
return circ;
}
+/** Return the guard state associated with <b>circ</b>, which may be NULL. */
+circuit_guard_state_t *
+origin_circuit_get_guard_state(origin_circuit_t *circ)
+{
+ return circ->guard_state;
+}
+
/** Start establishing the first hop of our circuit. Figure out what
* OR we should connect to, and if necessary start the connection to
* it. If we're already connected, then send the 'create' cell.
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index 1244601..56f66a1 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -21,6 +21,8 @@ origin_circuit_t *origin_circuit_init(uint8_t purpose, int flags);
origin_circuit_t *circuit_establish_circuit(uint8_t purpose,
extend_info_t *exit,
int flags);
+struct circuit_guard_state_t *origin_circuit_get_guard_state(
+ origin_circuit_t *circ);
int circuit_handle_first_hop(origin_circuit_t *circ);
void circuit_n_chan_done(channel_t *chan, int status,
int close_origin_circuits);
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index dee103e..f13126d 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -63,6 +63,7 @@
#include "connection_edge.h"
#include "connection_or.h"
#include "control.h"
+#include "entrynodes.h"
#include "main.h"
#include "hs_common.h"
#include "networkstatus.h"
@@ -834,6 +835,7 @@ circuit_free(circuit_t *circ)
cpath_ref_decref(ocirc->build_state->service_pending_final_cpath_ref);
}
tor_free(ocirc->build_state);
+ circuit_guard_state_free(ocirc->guard_state);
circuit_clear_cpath(ocirc);
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 958aba4..260b3d6 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -263,6 +263,8 @@ entry_guard_get_pathbias_state(entry_guard_t *guard)
return &guard->pb;
}
+HANDLE_IMPL(entry_guard, entry_guard_t, ATTR_UNUSED STATIC)
+
/** Return an interval betweeen 'now' and 'max_backdate' seconds in the past,
* chosen uniformly at random. We use this before recording persistent
* dates, so that we aren't leaking exactly when we recorded it.
@@ -1249,6 +1251,186 @@ entry_guard_has_higher_priority(entry_guard_t *a, entry_guard_t *b)
}
/**
+ * Release all storage held in <b>state</b>.
+ */
+void
+circuit_guard_state_free(circuit_guard_state_t *state)
+{
+ /* XXXX prop271 -- do we want to inline this structure? */
+ if (!state)
+ return;
+ entry_guard_handle_free(state->guard);
+ tor_free(state);
+}
+
+/**
+ * Pick a suitable entry guard for a circuit in, and place that guard
+ * in *<b>chosen_node_out</b>. Set *<b>guard_state_out</b> to an opaque
+ * state object that will record whether the circuit is ready to be used
+ * or not. Return 0 on success; on failure, return -1.
+ */
+int
+entry_guard_pick_for_circuit(guard_selection_t *gs,
+ const node_t **chosen_node_out,
+ circuit_guard_state_t **guard_state_out)
+{
+ tor_assert(gs);
+ tor_assert(chosen_node_out);
+ tor_assert(guard_state_out);
+ *chosen_node_out = NULL;
+ *guard_state_out = NULL;
+
+ unsigned state = 0;
+ entry_guard_t *guard = select_entry_guard_for_circuit(gs, &state);
+ if (! guard)
+ return -1;
+ if (BUG(state == 0))
+ return -1;
+ const node_t *node = node_get_by_id(guard->identity);
+ // XXXX prop271 check Ed ID.
+ if (! node)
+ return -1;
+
+ *chosen_node_out = node;
+ *guard_state_out = tor_malloc_zero(sizeof(circuit_guard_state_t));
+ (*guard_state_out)->guard = entry_guard_handle_new(guard);
+ (*guard_state_out)->state = state;
+ (*guard_state_out)->state_set_at = approx_time();
+
+ return 0;
+}
+
+/**
+ * Called by the circuit building module when a circuit has succeeded:
+ * informs the guards code that the guard in *<b>guard_state_p</b> is
+ * working, and advances the state of the guard module. On a -1 return
+ * value, the circuit is broken and should not be used. On a 1 return
+ * value, the circuit is ready to use. On a 0 return value, the circuit
+ * should not be used until we find out whether preferred guards will
+ * work for us.
+ *
+ * XXXXX prop271 tristates are ugly; reconsider that interface.
+ */
+int
+entry_guard_succeeded(guard_selection_t *gs,
+ circuit_guard_state_t **guard_state_p)
+{
+ if (BUG(*guard_state_p == NULL))
+ return -1;
+
+ entry_guard_t *guard = entry_guard_handle_get((*guard_state_p)->guard);
+ if (! guard)
+ return -1;
+
+ unsigned newstate =
+ entry_guards_note_guard_success(gs, guard, (*guard_state_p)->state);
+
+ (*guard_state_p)->state = newstate;
+ (*guard_state_p)->state_set_at = approx_time();
+
+ if (newstate == GUARD_CIRC_STATE_COMPLETE) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/**
+ * Called by the circuit building module when a circuit has succeeded:
+ * informs the guards code that the guard in *<b>guard_state_p</b> is
+ * not working, and advances the state of the guard module. Return -1 on
+ * bug or inconsistency; 0 on success.
+ */
+int
+entry_guard_failed(guard_selection_t *gs,
+ circuit_guard_state_t **guard_state_p)
+{
+ if (BUG(*guard_state_p == NULL))
+ return -1;
+
+ entry_guard_t *guard = entry_guard_handle_get((*guard_state_p)->guard);
+ if (! guard)
+ return -1;
+
+ entry_guards_note_guard_failure(gs, guard);
+
+ (*guard_state_p)->state = GUARD_CIRC_STATE_DEAD;
+ (*guard_state_p)->state_set_at = approx_time();
+
+ return 0;
+}
+
+/**
+ * Return true iff every primary guard in <b>gs</b> is believed to
+ * be unreachable.
+ */
+static int
+entry_guards_all_primary_guards_are_down(guard_selection_t *gs)
+{
+ /* XXXXX prop271 do we have to call entry_guards_update_primary() ?? */
+ tor_assert(gs);
+ SMARTLIST_FOREACH_BEGIN(gs->primary_entry_guards, entry_guard_t *, guard) {
+ entry_guard_consider_retry(guard);
+ if (guard->is_reachable != GUARD_REACHABLE_NO)
+ return 0;
+ } SMARTLIST_FOREACH_END(guard);
+ return 1;
+}
+
+/**
+ * Look at all of the origin_circuit_t * objects in <b>all_circuits</b>,
+ * and see if any of them that were previously not ready to use for
+ * guard-related reasons are now ready to use. Place those circuits
+ * in <b>newly_complete_out</b>, and mark them COMPLETE.
+ *
+ * Return 1 if we upgraded any circuits, and 0 otherwise.
+ */
+int
+entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
+ smartlist_t *all_circuits,
+ smartlist_t *newly_complete_out)
+{
+ tor_assert(gs);
+ tor_assert(all_circuits);
+ tor_assert(newly_complete_out);
+
+ if (! entry_guards_all_primary_guards_are_down(gs)) {
+ /* We only upgrade a waiting circuit if the primary guards are all
+ * down. */
+ return 0;
+ }
+
+ /* XXXX finish implementing. prop271 */
+
+ /* "If any circuit is <waiting_for_better_guard>, and every currently
+ {is_pending} circuit whose guard has higher priority has been
+ in state <usable_if_no_better_guard> for at least
+ {NONPRIMARY_GUARD_CONNECT_TIMEOUT} seconds, and all primary
+ guards have reachable status of <no>, then call that circuit
+ <complete>."
+ */
+
+ /* "If any circuit is <complete>, then do not use any
+ <waiting_for_better_guard> or <usable_if_no_better_guard> circuits
+ circuits whose guards have lower priority. (Time them out
+ after a {NONPRIMARY_GUARD_IDLE_TIMEOUT} seconds.)"
+ */
+ return 0;
+}
+
+/**
+ * Update all derived pieces of the guard selection state in <b>gs</b>.
+ */
+void
+entry_guards_update_all(guard_selection_t *gs)
+{
+ sampled_guards_update_from_consensus(gs);
+ entry_guards_update_filtered_sets(gs);
+ entry_guards_update_confirmed(gs);
+ entry_guards_update_primary(gs);
+}
+
+/**
* Return a newly allocated string for encoding the persistent parts of
* <b>guard</b> to the state file.
*/
@@ -1487,19 +1669,10 @@ __attribute__((noreturn)) void
entry_guards_DUMMY_ENTRY_POINT(void)
{
// prop271 XXXXX kludge; remove this
- sampled_guards_update_from_consensus(NULL);
- sample_reachable_filtered_entry_guards(NULL, 0);
- entry_guards_update_confirmed(NULL);
- entry_guards_update_primary(NULL);
- select_entry_guard_for_circuit(NULL, NULL);
- entry_guards_note_guard_failure(NULL, NULL);
- entry_guards_note_guard_success(NULL, NULL, 0);
- entry_guard_has_higher_priority(NULL, NULL);
- entry_guard_encode_for_state(NULL);
- entry_guard_parse_from_state(NULL);
- compare_guards_by_confirmed_idx(NULL, NULL);
- entry_guards_update_filtered_sets(NULL);
- tor_assert(0);
+ entry_guard_has_higher_priority(NULL, NULL);
+ entry_guard_encode_for_state(NULL);
+ entry_guard_parse_from_state(NULL);
+ tor_assert(0);
}
/* XXXXX ----------------------------------------------- */
@@ -2050,6 +2223,7 @@ entry_guard_free(entry_guard_t *e)
{
if (!e)
return;
+ entry_guard_handles_clear(e);
tor_free(e->chosen_by_version);
tor_free(e->sampled_by_version);
tor_free(e->extra_state_fields);
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 5501e62..5b3aa66 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -12,12 +12,18 @@
#ifndef TOR_ENTRYNODES_H
#define TOR_ENTRYNODES_H
+#include "handles.h"
+
/* Forward declare for guard_selection_t; entrynodes.c has the real struct */
typedef struct guard_selection_s guard_selection_t;
/* Forward declare for entry_guard_t; the real declaration is private. */
typedef struct entry_guard_t entry_guard_t;
+/* Forward declaration for circuit_guard_state_t; the real declaration is
+ private. */
+typedef struct circuit_guard_state_t circuit_guard_state_t;
+
/* Information about a guard's pathbias status.
* These fields are used in circpathbias.c to try to detect entry
* nodes that are failing circuits at a suspicious frequency.
@@ -70,6 +76,8 @@ typedef struct guard_pathbias_t {
* use a node_t, since we want to remember these even when we
* don't have any directory info. */
struct entry_guard_t {
+ HANDLE_ENTRY(entry_guard, entry_guard_t);
+
char nickname[MAX_HEX_NICKNAME_LEN+1];
char identity[DIGEST_LEN];
ed25519_public_key_t ed_id;
@@ -259,6 +267,20 @@ struct guard_selection_s {
*/
int should_add_entry_nodes;
};
+
+struct entry_guard_handle_t;
+
+/**
+ * Per-circuit state to track whether we'll be able to use the circuit.
+ */
+struct circuit_guard_state_t {
+ /** Handle to the entry guard object for this circuit. */
+ struct entry_guard_handle_t *guard;
+ /** The time at which <b>state</b> last changed. */
+ time_t state_set_at;
+ /** One of GUARD_CIRC_STATE_* */
+ uint8_t state;
+};
#endif
#if 1
@@ -285,6 +307,19 @@ const char *entry_guard_get_rsa_id_digest(const entry_guard_t *guard);
const char *entry_guard_describe(const entry_guard_t *guard);
guard_pathbias_t *entry_guard_get_pathbias_state(entry_guard_t *guard);
+void circuit_guard_state_free(circuit_guard_state_t *state);
+int entry_guard_pick_for_circuit(guard_selection_t *gs,
+ const node_t **chosen_node_out,
+ circuit_guard_state_t **guard_state_out);
+int entry_guard_succeeded(guard_selection_t *gs,
+ circuit_guard_state_t **guard_state_p);
+int entry_guard_failed(guard_selection_t *gs,
+ circuit_guard_state_t **guard_state_p);
+void entry_guards_update_all(guard_selection_t *gs);
+int entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
+ smartlist_t *all_circuits,
+ smartlist_t *newly_complete_out);
+
/* Used by bridges.c only. */
void add_bridge_as_entry_guard(guard_selection_t *gs,
const node_t *chosen);
@@ -350,6 +385,7 @@ int num_bridges_usable(void);
/**@}*/
// ---------- XXXX these functions and definitions are post-prop271.
+HANDLE_DECL(entry_guard, entry_guard_t, STATIC)
STATIC guard_selection_t *guard_selection_new(void);
STATIC void guard_selection_free(guard_selection_t *gs);
STATIC entry_guard_t *get_sampled_guard_with_id(guard_selection_t *gs,
@@ -398,6 +434,8 @@ STATIC void sampled_guards_update_from_consensus(guard_selection_t *gs);
/** State for a circuit that can (so far as the guard subsystem is
* concerned) be used for actual traffic. */
#define GUARD_CIRC_STATE_COMPLETE 4
+/** State for a circuit that is unusable, and will not become usable. */
+#define GUARD_CIRC_STATE_DEAD 5
/**@}*/
STATIC void entry_guards_note_guard_failure(guard_selection_t *gs,
entry_guard_t *guard);
diff --git a/src/or/or.h b/src/or/or.h
index eb94f63..4bc8066 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3148,6 +3148,11 @@ typedef struct origin_circuit_t {
/** Holds all rendezvous data on either client or service side. */
rend_data_t *rend_data;
+ /** Holds the data that the entry guard system uses to track the
+ * status of the guard this circuit is using, and thereby to determine
+ * whether this circuit can be used. */
+ struct circuit_guard_state_t *guard_state;
+
/** How many more relay_early cells can we send on this circuit, according
* to the specification? */
unsigned int remaining_relay_early_cells : 4;
1
0

16 Dec '16
commit c74542c51a2ce75e602e3e237bd41d1fd08a2fb0
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Tue Nov 15 08:15:29 2016 -0500
Add accessors as needed to repair compilation
The previous commit, in moving a bunch of functions to bridges.c,
broke compilation because bridges.c required two entry points to
entrynodes.c it didn't have.
---
src/or/bridges.c | 16 +---------------
src/or/entrynodes.c | 23 +++++++++++++++++++++++
src/or/entrynodes.h | 5 +++++
3 files changed, 29 insertions(+), 15 deletions(-)
diff --git a/src/or/bridges.c b/src/or/bridges.c
index 73510cf..508c77f 100644
--- a/src/or/bridges.c
+++ b/src/or/bridges.c
@@ -52,7 +52,6 @@ typedef struct {
} bridge_info_t;
static void bridge_free(bridge_info_t *bridge);
-static int num_bridges_usable(void);
/** 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
@@ -719,7 +718,7 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
fmt_and_decorate_addr(&bridge->addr),
(int) bridge->port);
}
- add_an_entry_guard(get_guard_selection_info(), node, 1, 1, 0, 0);
+ add_bridge_as_entry_guard(get_guard_selection_info(), node);
log_notice(LD_DIR, "new bridge descriptor '%s' (%s): %s", ri->nickname,
from_cache ? "cached" : "fresh", router_describe(ri));
@@ -747,19 +746,6 @@ any_bridge_descriptors_known(void)
return choose_random_entry(NULL) != NULL;
}
-/** Return the number of bridges that have descriptors that are marked with
- * purpose 'bridge' and are running.
- */
-static int
-num_bridges_usable(void)
-{
- int n_options = 0;
- tor_assert(get_options()->UseBridges);
- (void) choose_random_entry_impl(get_guard_selection_info(),
- NULL, 0, 0, &n_options);
- return n_options;
-}
-
/** Return a smartlist containing all bridge identity digests */
MOCK_IMPL(smartlist_t *,
list_bridge_identities, (void))
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 886e653..95b3c5a 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -893,6 +893,16 @@ add_an_entry_guard(guard_selection_t *gs,
return node;
}
+/** Entry point for bridges.c to add a bridge as guard.
+ *
+ * XXXX prop271 refactor.*/
+void
+add_bridge_as_entry_guard(guard_selection_t *gs,
+ const node_t *chosen)
+{
+ add_an_entry_guard(gs, chosen, 1, 1, 0, 0);
+}
+
/** Choose how many entry guards or directory guards we'll use. If
* <b>for_directory</b> is true, we return how many directory guards to
* use; else we return how many entry guards to use. */
@@ -1490,6 +1500,19 @@ choose_random_dirguard(dirinfo_type_t type)
NULL, 1, type, NULL);
}
+/** Return the number of bridges that have descriptors that are marked with
+ * purpose 'bridge' and are running.
+ */
+int
+num_bridges_usable(void)
+{
+ int n_options = 0;
+ tor_assert(get_options()->UseBridges);
+ (void) choose_random_entry_impl(get_guard_selection_info(),
+ NULL, 0, 0, &n_options);
+ return n_options;
+}
+
/** Filter <b>all_entry_guards</b> for usable entry guards and put them
* in <b>live_entry_guards</b>. We filter based on whether the node is
* currently alive, and on whether it satisfies the restrictions
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 8407945..f07f843 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -154,6 +154,11 @@ const char *entry_guard_get_rsa_id_digest(const entry_guard_t *guard);
const char *entry_guard_describe(const entry_guard_t *guard);
guard_pathbias_t *entry_guard_get_pathbias_state(entry_guard_t *guard);
+/* Used by bridges.c only. */
+void add_bridge_as_entry_guard(guard_selection_t *gs,
+ const node_t *chosen);
+int num_bridges_usable(void);
+
#ifdef ENTRYNODES_PRIVATE
STATIC time_t randomize_time(time_t now, time_t max_backdate);
STATIC void entry_guard_add_to_sample(guard_selection_t *gs,
1
0

[tor/master] Add a GUARD log domain, for use with new guards code
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit bf64564e37c5fc01111bc476d1b93890b15a18bf
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Tue Nov 15 18:57:17 2016 -0500
Add a GUARD log domain, for use with new guards code
---
src/common/log.c | 2 +-
src/common/torlog.h | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/common/log.c b/src/common/log.c
index 3b0eb88..d031364 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -1177,7 +1177,7 @@ static const char *domain_list[] = {
"GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
"HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
"OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", "CHANNEL",
- "SCHED", NULL
+ "SCHED", "GUARD", NULL
};
/** Return a bitmask for the log domain for which <b>domain</b> is the name,
diff --git a/src/common/torlog.h b/src/common/torlog.h
index 6732a42..bc95785 100644
--- a/src/common/torlog.h
+++ b/src/common/torlog.h
@@ -99,8 +99,10 @@
#define LD_CHANNEL (1u<<21)
/** Scheduler */
#define LD_SCHED (1u<<22)
+/** Guard nodes */
+#define LD_GUARD (1u<<23)
/** Number of logging domains in the code. */
-#define N_LOGGING_DOMAINS 23
+#define N_LOGGING_DOMAINS 24
/** This log message is not safe to send to a callback-based logger
* immediately. Used as a flag, not a log domain. */
1
0

16 Dec '16
commit f66f9c82e9b8aaac04dc01ee3bbcf60019864c9b
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Nov 14 12:57:05 2016 -0500
Make entry_guard_t opaque to circpathbias.c
This was a relatively mechanical change. First, I added an accessor
function for the pathbias-state field of a guard. Then I did a
search-and-replace in circpathbias.c to replace "guard->pb." with
"pb->". Finally, I made sure that "pb" was declared whenever it was
needed.
---
src/or/circpathbias.c | 249 +++++++++++++++++++++++++++-----------------------
src/or/entrynodes.c | 7 ++
src/or/entrynodes.h | 3 +-
3 files changed, 143 insertions(+), 116 deletions(-)
diff --git a/src/or/circpathbias.c b/src/or/circpathbias.c
index 7a9af82..3df68b8 100644
--- a/src/or/circpathbias.c
+++ b/src/or/circpathbias.c
@@ -21,9 +21,6 @@
* each guard, and stored persistently in the state file.
*/
-/* XXXX prop271 I would like to remove this. */
-#define ENTRYNODES_EXPOSE_STRUCT
-
#include "or.h"
#include "channel.h"
#include "circpathbias.h"
@@ -54,18 +51,20 @@ static int entry_guard_inc_circ_attempt_count(entry_guard_t *guard);
static int
entry_guard_inc_circ_attempt_count(entry_guard_t *guard)
{
+ guard_pathbias_t *pb = entry_guard_get_pathbias_state(guard);
+
entry_guards_changed();
pathbias_measure_close_rate(guard);
- if (guard->pb.path_bias_disabled)
+ if (pb->path_bias_disabled)
return -1;
pathbias_scale_close_rates(guard);
- guard->pb.circ_attempts++;
+ pb->circ_attempts++;
log_info(LD_CIRC, "Got success count %f/%f for guard %s",
- guard->pb.circ_successes, guard->pb.circ_attempts,
+ pb->circ_successes, pb->circ_attempts,
entry_guard_describe(guard));
return 0;
}
@@ -516,13 +515,15 @@ pathbias_count_build_success(origin_circuit_t *circ)
}
if (guard) {
+ guard_pathbias_t *pb = entry_guard_get_pathbias_state(guard);
+
if (circ->path_state == PATH_STATE_BUILD_ATTEMPTED) {
circ->path_state = PATH_STATE_BUILD_SUCCEEDED;
- guard->pb.circ_successes++;
+ pb->circ_successes++;
entry_guards_changed();
log_info(LD_CIRC, "Got success count %f/%f for guard %s",
- guard->pb.circ_successes, guard->pb.circ_attempts,
+ pb->circ_successes, pb->circ_attempts,
entry_guard_describe(guard));
} else {
if ((rate_msg = rate_limit_log(&success_notice_limit,
@@ -538,10 +539,10 @@ pathbias_count_build_success(origin_circuit_t *circ)
}
}
- if (guard->pb.circ_attempts < guard->pb.circ_successes) {
+ if (pb->circ_attempts < pb->circ_successes) {
log_notice(LD_BUG, "Unexpectedly high successes counts (%f/%f) "
"for guard %s",
- guard->pb.circ_successes, guard->pb.circ_attempts,
+ pb->circ_successes, pb->circ_attempts,
entry_guard_describe(guard));
}
/* In rare cases, CIRCUIT_PURPOSE_TESTING can get converted to
@@ -585,8 +586,6 @@ pathbias_count_build_success(origin_circuit_t *circ)
void
pathbias_count_use_attempt(origin_circuit_t *circ)
{
- entry_guard_t *guard;
-
if (!pathbias_should_count(circ)) {
return;
}
@@ -599,18 +598,20 @@ pathbias_count_use_attempt(origin_circuit_t *circ)
circuit_purpose_to_string(circ->base_.purpose),
circuit_state_to_string(circ->base_.state));
} else if (circ->path_state < PATH_STATE_USE_ATTEMPTED) {
- guard = entry_guard_get_by_id_digest(
+ entry_guard_t *guard = entry_guard_get_by_id_digest(
circ->cpath->extend_info->identity_digest);
if (guard) {
+ guard_pathbias_t *pb = entry_guard_get_pathbias_state(guard);
+
pathbias_measure_use_rate(guard);
pathbias_scale_use_rates(guard);
- guard->pb.use_attempts++;
+ pb->use_attempts++;
entry_guards_changed();
log_debug(LD_CIRC,
"Marked circuit %d (%f/%f) as used for guard %s.",
circ->global_identifier,
- guard->pb.use_successes, guard->pb.use_attempts,
+ pb->use_successes, pb->use_attempts,
entry_guard_describe(guard));
}
@@ -713,20 +714,22 @@ pathbias_count_use_success(origin_circuit_t *circ)
guard = entry_guard_get_by_id_digest(
circ->cpath->extend_info->identity_digest);
if (guard) {
- guard->pb.use_successes++;
+ guard_pathbias_t *pb = entry_guard_get_pathbias_state(guard);
+
+ pb->use_successes++;
entry_guards_changed();
- if (guard->pb.use_attempts < guard->pb.use_successes) {
+ if (pb->use_attempts < pb->use_successes) {
log_notice(LD_BUG, "Unexpectedly high use successes counts (%f/%f) "
"for guard %s",
- guard->pb.use_successes, guard->pb.use_attempts,
+ pb->use_successes, pb->use_attempts,
entry_guard_describe(guard));
}
log_debug(LD_CIRC,
"Marked circuit %d (%f/%f) as used successfully for guard %s",
- circ->global_identifier, guard->pb.use_successes,
- guard->pb.use_attempts,
+ circ->global_identifier, pb->use_successes,
+ pb->use_attempts,
entry_guard_describe(guard));
}
}
@@ -1028,9 +1031,11 @@ pathbias_count_successful_close(origin_circuit_t *circ)
}
if (guard) {
+ guard_pathbias_t *pb = entry_guard_get_pathbias_state(guard);
+
/* In the long run: circuit_success ~= successful_circuit_close +
* circ_failure + stream_failure */
- guard->pb.successful_circuits_closed++;
+ pb->successful_circuits_closed++;
entry_guards_changed();
} else if (circ->base_.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) {
/* In rare cases, CIRCUIT_PURPOSE_TESTING can get converted to
@@ -1067,7 +1072,9 @@ pathbias_count_collapse(origin_circuit_t *circ)
}
if (guard) {
- guard->pb.collapsed_circuits++;
+ guard_pathbias_t *pb = entry_guard_get_pathbias_state(guard);
+
+ pb->collapsed_circuits++;
entry_guards_changed();
} else if (circ->base_.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) {
/* In rare cases, CIRCUIT_PURPOSE_TESTING can get converted to
@@ -1100,7 +1107,9 @@ pathbias_count_use_failed(origin_circuit_t *circ)
}
if (guard) {
- guard->pb.unusable_circuits++;
+ guard_pathbias_t *pb = entry_guard_get_pathbias_state(guard);
+
+ pb->unusable_circuits++;
entry_guards_changed();
} else if (circ->base_.purpose != CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) {
/* In rare cases, CIRCUIT_PURPOSE_TESTING can get converted to
@@ -1143,7 +1152,9 @@ pathbias_count_timeout(origin_circuit_t *circ)
}
if (guard) {
- guard->pb.timeouts++;
+ guard_pathbias_t *pb = entry_guard_get_pathbias_state(guard);
+
+ pb->timeouts++;
entry_guards_changed();
}
}
@@ -1199,7 +1210,9 @@ pathbias_count_circs_in_states(entry_guard_t *guard,
double
pathbias_get_close_success_count(entry_guard_t *guard)
{
- return guard->pb.successful_circuits_closed +
+ guard_pathbias_t *pb = entry_guard_get_pathbias_state(guard);
+
+ return pb->successful_circuits_closed +
pathbias_count_circs_in_states(guard,
PATH_STATE_BUILD_SUCCEEDED,
PATH_STATE_USE_SUCCEEDED);
@@ -1215,7 +1228,9 @@ pathbias_get_close_success_count(entry_guard_t *guard)
double
pathbias_get_use_success_count(entry_guard_t *guard)
{
- return guard->pb.use_successes +
+ guard_pathbias_t *pb = entry_guard_get_pathbias_state(guard);
+
+ return pb->use_successes +
pathbias_count_circs_in_states(guard,
PATH_STATE_USE_ATTEMPTED,
PATH_STATE_USE_SUCCEEDED);
@@ -1233,16 +1248,17 @@ static void
pathbias_measure_use_rate(entry_guard_t *guard)
{
const or_options_t *options = get_options();
+ guard_pathbias_t *pb = entry_guard_get_pathbias_state(guard);
- if (guard->pb.use_attempts > pathbias_get_min_use(options)) {
+ if (pb->use_attempts > pathbias_get_min_use(options)) {
/* Note: We rely on the < comparison here to allow us to set a 0
* rate and disable the feature entirely. If refactoring, don't
* change to <= */
- if (pathbias_get_use_success_count(guard)/guard->pb.use_attempts
+ if (pathbias_get_use_success_count(guard)/pb->use_attempts
< pathbias_get_extreme_use_rate(options)) {
/* Dropping is currently disabled by default. */
if (pathbias_get_dropguards(options)) {
- if (!guard->pb.path_bias_disabled) {
+ if (!pb->path_bias_disabled) {
log_warn(LD_CIRC,
"Your Guard %s is failing to carry an extremely large "
"amount of stream on its circuits. "
@@ -1254,20 +1270,20 @@ pathbias_measure_use_rate(entry_guard_t *guard)
"For reference, your timeout cutoff is %ld seconds.",
entry_guard_describe(guard),
tor_lround(pathbias_get_use_success_count(guard)),
- tor_lround(guard->pb.use_attempts),
+ tor_lround(pb->use_attempts),
tor_lround(pathbias_get_close_success_count(guard)),
- tor_lround(guard->pb.circ_attempts),
- tor_lround(guard->pb.circ_successes),
- tor_lround(guard->pb.unusable_circuits),
- tor_lround(guard->pb.collapsed_circuits),
- tor_lround(guard->pb.timeouts),
+ tor_lround(pb->circ_attempts),
+ tor_lround(pb->circ_successes),
+ tor_lround(pb->unusable_circuits),
+ tor_lround(pb->collapsed_circuits),
+ tor_lround(pb->timeouts),
tor_lround(get_circuit_build_close_time_ms()/1000));
- guard->pb.path_bias_disabled = 1;
+ pb->path_bias_disabled = 1;
entry_guard_mark_bad(guard);
return;
}
- } else if (!guard->pb.path_bias_use_extreme) {
- guard->pb.path_bias_use_extreme = 1;
+ } else if (!pb->path_bias_use_extreme) {
+ pb->path_bias_use_extreme = 1;
log_warn(LD_CIRC,
"Your Guard %s is failing to carry an extremely large "
"amount of streams on its circuits. "
@@ -1279,19 +1295,19 @@ pathbias_measure_use_rate(entry_guard_t *guard)
"For reference, your timeout cutoff is %ld seconds.",
entry_guard_describe(guard),
tor_lround(pathbias_get_use_success_count(guard)),
- tor_lround(guard->pb.use_attempts),
+ tor_lround(pb->use_attempts),
tor_lround(pathbias_get_close_success_count(guard)),
- tor_lround(guard->pb.circ_attempts),
- tor_lround(guard->pb.circ_successes),
- tor_lround(guard->pb.unusable_circuits),
- tor_lround(guard->pb.collapsed_circuits),
- tor_lround(guard->pb.timeouts),
+ tor_lround(pb->circ_attempts),
+ tor_lround(pb->circ_successes),
+ tor_lround(pb->unusable_circuits),
+ tor_lround(pb->collapsed_circuits),
+ tor_lround(pb->timeouts),
tor_lround(get_circuit_build_close_time_ms()/1000));
}
- } else if (pathbias_get_use_success_count(guard)/guard->pb.use_attempts
+ } else if (pathbias_get_use_success_count(guard)/pb->use_attempts
< pathbias_get_notice_use_rate(options)) {
- if (!guard->pb.path_bias_use_noticed) {
- guard->pb.path_bias_use_noticed = 1;
+ if (!pb->path_bias_use_noticed) {
+ pb->path_bias_use_noticed = 1;
log_notice(LD_CIRC,
"Your Guard %s is failing to carry more streams on its "
"circuits than usual. "
@@ -1303,13 +1319,13 @@ pathbias_measure_use_rate(entry_guard_t *guard)
"For reference, your timeout cutoff is %ld seconds.",
entry_guard_describe(guard),
tor_lround(pathbias_get_use_success_count(guard)),
- tor_lround(guard->pb.use_attempts),
+ tor_lround(pb->use_attempts),
tor_lround(pathbias_get_close_success_count(guard)),
- tor_lround(guard->pb.circ_attempts),
- tor_lround(guard->pb.circ_successes),
- tor_lround(guard->pb.unusable_circuits),
- tor_lround(guard->pb.collapsed_circuits),
- tor_lround(guard->pb.timeouts),
+ tor_lround(pb->circ_attempts),
+ tor_lround(pb->circ_successes),
+ tor_lround(pb->unusable_circuits),
+ tor_lround(pb->collapsed_circuits),
+ tor_lround(pb->timeouts),
tor_lround(get_circuit_build_close_time_ms()/1000));
}
}
@@ -1338,16 +1354,17 @@ static void
pathbias_measure_close_rate(entry_guard_t *guard)
{
const or_options_t *options = get_options();
-
- if (guard->pb.circ_attempts > pathbias_get_min_circs(options)) {
+ guard_pathbias_t *pb = entry_guard_get_pathbias_state(guard);
+
+ if (pb->circ_attempts > pathbias_get_min_circs(options)) {
/* Note: We rely on the < comparison here to allow us to set a 0
* rate and disable the feature entirely. If refactoring, don't
* change to <= */
- if (pathbias_get_close_success_count(guard)/guard->pb.circ_attempts
+ if (pathbias_get_close_success_count(guard)/pb->circ_attempts
< pathbias_get_extreme_rate(options)) {
/* Dropping is currently disabled by default. */
if (pathbias_get_dropguards(options)) {
- if (!guard->pb.path_bias_disabled) {
+ if (!pb->path_bias_disabled) {
log_warn(LD_CIRC,
"Your Guard %s is failing an extremely large "
"amount of circuits. "
@@ -1359,20 +1376,20 @@ pathbias_measure_close_rate(entry_guard_t *guard)
"For reference, your timeout cutoff is %ld seconds.",
entry_guard_describe(guard),
tor_lround(pathbias_get_close_success_count(guard)),
- tor_lround(guard->pb.circ_attempts),
+ tor_lround(pb->circ_attempts),
tor_lround(pathbias_get_use_success_count(guard)),
- tor_lround(guard->pb.use_attempts),
- tor_lround(guard->pb.circ_successes),
- tor_lround(guard->pb.unusable_circuits),
- tor_lround(guard->pb.collapsed_circuits),
- tor_lround(guard->pb.timeouts),
+ tor_lround(pb->use_attempts),
+ tor_lround(pb->circ_successes),
+ tor_lround(pb->unusable_circuits),
+ tor_lround(pb->collapsed_circuits),
+ tor_lround(pb->timeouts),
tor_lround(get_circuit_build_close_time_ms()/1000));
- guard->pb.path_bias_disabled = 1;
+ pb->path_bias_disabled = 1;
entry_guard_mark_bad(guard);
return;
}
- } else if (!guard->pb.path_bias_extreme) {
- guard->pb.path_bias_extreme = 1;
+ } else if (!pb->path_bias_extreme) {
+ pb->path_bias_extreme = 1;
log_warn(LD_CIRC,
"Your Guard %s is failing an extremely large "
"amount of circuits. "
@@ -1384,19 +1401,19 @@ pathbias_measure_close_rate(entry_guard_t *guard)
"For reference, your timeout cutoff is %ld seconds.",
entry_guard_describe(guard),
tor_lround(pathbias_get_close_success_count(guard)),
- tor_lround(guard->pb.circ_attempts),
+ tor_lround(pb->circ_attempts),
tor_lround(pathbias_get_use_success_count(guard)),
- tor_lround(guard->pb.use_attempts),
- tor_lround(guard->pb.circ_successes),
- tor_lround(guard->pb.unusable_circuits),
- tor_lround(guard->pb.collapsed_circuits),
- tor_lround(guard->pb.timeouts),
+ tor_lround(pb->use_attempts),
+ tor_lround(pb->circ_successes),
+ tor_lround(pb->unusable_circuits),
+ tor_lround(pb->collapsed_circuits),
+ tor_lround(pb->timeouts),
tor_lround(get_circuit_build_close_time_ms()/1000));
}
- } else if (pathbias_get_close_success_count(guard)/guard->pb.circ_attempts
+ } else if (pathbias_get_close_success_count(guard)/pb->circ_attempts
< pathbias_get_warn_rate(options)) {
- if (!guard->pb.path_bias_warned) {
- guard->pb.path_bias_warned = 1;
+ if (!pb->path_bias_warned) {
+ pb->path_bias_warned = 1;
log_warn(LD_CIRC,
"Your Guard %s is failing a very large "
"amount of circuits. "
@@ -1409,19 +1426,19 @@ pathbias_measure_close_rate(entry_guard_t *guard)
"For reference, your timeout cutoff is %ld seconds.",
entry_guard_describe(guard),
tor_lround(pathbias_get_close_success_count(guard)),
- tor_lround(guard->pb.circ_attempts),
+ tor_lround(pb->circ_attempts),
tor_lround(pathbias_get_use_success_count(guard)),
- tor_lround(guard->pb.use_attempts),
- tor_lround(guard->pb.circ_successes),
- tor_lround(guard->pb.unusable_circuits),
- tor_lround(guard->pb.collapsed_circuits),
- tor_lround(guard->pb.timeouts),
+ tor_lround(pb->use_attempts),
+ tor_lround(pb->circ_successes),
+ tor_lround(pb->unusable_circuits),
+ tor_lround(pb->collapsed_circuits),
+ tor_lround(pb->timeouts),
tor_lround(get_circuit_build_close_time_ms()/1000));
}
- } else if (pathbias_get_close_success_count(guard)/guard->pb.circ_attempts
+ } else if (pathbias_get_close_success_count(guard)/pb->circ_attempts
< pathbias_get_notice_rate(options)) {
- if (!guard->pb.path_bias_noticed) {
- guard->pb.path_bias_noticed = 1;
+ if (!pb->path_bias_noticed) {
+ pb->path_bias_noticed = 1;
log_notice(LD_CIRC,
"Your Guard %s is failing more circuits than "
"usual. "
@@ -1432,13 +1449,13 @@ pathbias_measure_close_rate(entry_guard_t *guard)
"For reference, your timeout cutoff is %ld seconds.",
entry_guard_describe(guard),
tor_lround(pathbias_get_close_success_count(guard)),
- tor_lround(guard->pb.circ_attempts),
+ tor_lround(pb->circ_attempts),
tor_lround(pathbias_get_use_success_count(guard)),
- tor_lround(guard->pb.use_attempts),
- tor_lround(guard->pb.circ_successes),
- tor_lround(guard->pb.unusable_circuits),
- tor_lround(guard->pb.collapsed_circuits),
- tor_lround(guard->pb.timeouts),
+ tor_lround(pb->use_attempts),
+ tor_lround(pb->circ_successes),
+ tor_lround(pb->unusable_circuits),
+ tor_lround(pb->collapsed_circuits),
+ tor_lround(pb->timeouts),
tor_lround(get_circuit_build_close_time_ms()/1000));
}
}
@@ -1458,9 +1475,10 @@ static void
pathbias_scale_close_rates(entry_guard_t *guard)
{
const or_options_t *options = get_options();
+ guard_pathbias_t *pb = entry_guard_get_pathbias_state(guard);
/* If we get a ton of circuits, just scale everything down */
- if (guard->pb.circ_attempts > pathbias_get_scale_threshold(options)) {
+ if (pb->circ_attempts > pathbias_get_scale_threshold(options)) {
double scale_ratio = pathbias_get_scale_ratio(options);
int opened_attempts = pathbias_count_circs_in_states(guard,
PATH_STATE_BUILD_ATTEMPTED, PATH_STATE_BUILD_ATTEMPTED);
@@ -1468,36 +1486,36 @@ pathbias_scale_close_rates(entry_guard_t *guard)
PATH_STATE_BUILD_SUCCEEDED,
PATH_STATE_USE_FAILED);
/* Verify that the counts are sane before and after scaling */
- int counts_are_sane = (guard->pb.circ_attempts >= guard->pb.circ_successes);
+ int counts_are_sane = (pb->circ_attempts >= pb->circ_successes);
- guard->pb.circ_attempts -= (opened_attempts+opened_built);
- guard->pb.circ_successes -= opened_built;
+ pb->circ_attempts -= (opened_attempts+opened_built);
+ pb->circ_successes -= opened_built;
- guard->pb.circ_attempts *= scale_ratio;
- guard->pb.circ_successes *= scale_ratio;
- guard->pb.timeouts *= scale_ratio;
- guard->pb.successful_circuits_closed *= scale_ratio;
- guard->pb.collapsed_circuits *= scale_ratio;
- guard->pb.unusable_circuits *= scale_ratio;
+ pb->circ_attempts *= scale_ratio;
+ pb->circ_successes *= scale_ratio;
+ pb->timeouts *= scale_ratio;
+ pb->successful_circuits_closed *= scale_ratio;
+ pb->collapsed_circuits *= scale_ratio;
+ pb->unusable_circuits *= scale_ratio;
- guard->pb.circ_attempts += (opened_attempts+opened_built);
- guard->pb.circ_successes += opened_built;
+ pb->circ_attempts += (opened_attempts+opened_built);
+ pb->circ_successes += opened_built;
entry_guards_changed();
log_info(LD_CIRC,
"Scaled pathbias counts to (%f,%f)/%f (%d/%d open) for guard "
"%s",
- guard->pb.circ_successes, guard->pb.successful_circuits_closed,
- guard->pb.circ_attempts, opened_built, opened_attempts,
+ pb->circ_successes, pb->successful_circuits_closed,
+ pb->circ_attempts, opened_built, opened_attempts,
entry_guard_describe(guard));
/* Have the counts just become invalid by this scaling attempt? */
- if (counts_are_sane && guard->pb.circ_attempts < guard->pb.circ_successes) {
+ if (counts_are_sane && pb->circ_attempts < pb->circ_successes) {
log_notice(LD_BUG,
"Scaling has mangled pathbias counts to %f/%f (%d/%d open) "
"for guard %s",
- guard->pb.circ_successes, guard->pb.circ_attempts, opened_built,
+ pb->circ_successes, pb->circ_attempts, opened_built,
opened_attempts,
entry_guard_describe(guard));
}
@@ -1517,33 +1535,34 @@ void
pathbias_scale_use_rates(entry_guard_t *guard)
{
const or_options_t *options = get_options();
+ guard_pathbias_t *pb = entry_guard_get_pathbias_state(guard);
/* If we get a ton of circuits, just scale everything down */
- if (guard->pb.use_attempts > pathbias_get_scale_use_threshold(options)) {
+ if (pb->use_attempts > pathbias_get_scale_use_threshold(options)) {
double scale_ratio = pathbias_get_scale_ratio(options);
int opened_attempts = pathbias_count_circs_in_states(guard,
PATH_STATE_USE_ATTEMPTED, PATH_STATE_USE_SUCCEEDED);
/* Verify that the counts are sane before and after scaling */
- int counts_are_sane = (guard->pb.use_attempts >= guard->pb.use_successes);
+ int counts_are_sane = (pb->use_attempts >= pb->use_successes);
- guard->pb.use_attempts -= opened_attempts;
+ pb->use_attempts -= opened_attempts;
- guard->pb.use_attempts *= scale_ratio;
- guard->pb.use_successes *= scale_ratio;
+ pb->use_attempts *= scale_ratio;
+ pb->use_successes *= scale_ratio;
- guard->pb.use_attempts += opened_attempts;
+ pb->use_attempts += opened_attempts;
log_info(LD_CIRC,
"Scaled pathbias use counts to %f/%f (%d open) for guard %s",
- guard->pb.use_successes, guard->pb.use_attempts, opened_attempts,
+ pb->use_successes, pb->use_attempts, opened_attempts,
entry_guard_describe(guard));
/* Have the counts just become invalid by this scaling attempt? */
- if (counts_are_sane && guard->pb.use_attempts < guard->pb.use_successes) {
+ if (counts_are_sane && pb->use_attempts < pb->use_successes) {
log_notice(LD_BUG,
"Scaling has mangled pathbias usage counts to %f/%f "
"(%d open) for guard %s",
- guard->pb.circ_successes, guard->pb.circ_attempts,
+ pb->circ_successes, pb->circ_attempts,
opened_attempts, entry_guard_describe(guard));
}
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 1324e31..90918fa 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -184,6 +184,13 @@ entry_guard_get_rsa_id_digest(const entry_guard_t *guard)
return guard->identity;
}
+/** Return the pathbias state associated with <b>guard</b>. */
+guard_pathbias_t *
+entry_guard_get_pathbias_state(entry_guard_t *guard)
+{
+ return &guard->pb;
+}
+
/** Check whether the entry guard <b>e</b> is usable, given the directory
* authorities' opinion about the router (stored in <b>ri</b>) and the user's
* configuration (in <b>options</b>). Set <b>e</b>->bad_since
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index ba8cd9f..2e18a2f 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -53,7 +53,7 @@ typedef struct guard_pathbias_t {
* this guard as first hop. */
} guard_pathbias_t;
-#if defined(ENTRYNODES_PRIVATE) || defined(ENTRYNODES_EXPOSE_STRUCT)
+#if defined(ENTRYNODES_PRIVATE)
/** An entry_guard_t represents our information about a chosen long-term
* first hop, known as a "helper" node in the literature. We can't just
* use a node_t, since we want to remember these even when we
@@ -106,6 +106,7 @@ const node_t *entry_guard_find_node(const entry_guard_t *guard);
void entry_guard_mark_bad(entry_guard_t *guard);
const char *entry_guard_get_rsa_id_digest(const entry_guard_t *guard);
const char *entry_guard_describe(const entry_guard_t *guard);
+guard_pathbias_t *entry_guard_get_pathbias_state(entry_guard_t *guard);
#ifdef ENTRYNODES_PRIVATE
STATIC const node_t *add_an_entry_guard(guard_selection_t *gs,
1
0
commit 823357dbe4874e9726749f1d9d16d85fab949ee5
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Nov 14 12:04:42 2016 -0500
Add an entry_guard_describe() function
This function helpfully removes all but one remaining use of
an entry_guard_t private field in pathbias.c
---
src/or/circpathbias.c | 82 ++++++++++++++++++++++------------------------
src/or/entrynodes.c | 20 +++++++++++
src/or/entrynodes.h | 3 +-
src/test/test_entrynodes.c | 17 ++++++++++
4 files changed, 78 insertions(+), 44 deletions(-)
diff --git a/src/or/circpathbias.c b/src/or/circpathbias.c
index 6e2589c..a2e1641 100644
--- a/src/or/circpathbias.c
+++ b/src/or/circpathbias.c
@@ -64,9 +64,9 @@ entry_guard_inc_circ_attempt_count(entry_guard_t *guard)
pathbias_scale_close_rates(guard);
guard->pb.circ_attempts++;
- log_info(LD_CIRC, "Got success count %f/%f for guard %s ($%s)",
- guard->pb.circ_successes, guard->pb.circ_attempts, guard->nickname,
- hex_str(guard->identity, DIGEST_LEN));
+ log_info(LD_CIRC, "Got success count %f/%f for guard %s",
+ guard->pb.circ_successes, guard->pb.circ_attempts,
+ entry_guard_describe(guard));
return 0;
}
@@ -521,9 +521,9 @@ pathbias_count_build_success(origin_circuit_t *circ)
guard->pb.circ_successes++;
entry_guards_changed();
- log_info(LD_CIRC, "Got success count %f/%f for guard %s ($%s)",
+ log_info(LD_CIRC, "Got success count %f/%f for guard %s",
guard->pb.circ_successes, guard->pb.circ_attempts,
- guard->nickname, hex_str(guard->identity, DIGEST_LEN));
+ entry_guard_describe(guard));
} else {
if ((rate_msg = rate_limit_log(&success_notice_limit,
approx_time()))) {
@@ -540,9 +540,9 @@ pathbias_count_build_success(origin_circuit_t *circ)
if (guard->pb.circ_attempts < guard->pb.circ_successes) {
log_notice(LD_BUG, "Unexpectedly high successes counts (%f/%f) "
- "for guard %s ($%s)",
+ "for guard %s",
guard->pb.circ_successes, guard->pb.circ_attempts,
- guard->nickname, hex_str(guard->identity, DIGEST_LEN));
+ entry_guard_describe(guard));
}
/* In rare cases, CIRCUIT_PURPOSE_TESTING can get converted to
* CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT and have no guards here.
@@ -608,10 +608,10 @@ pathbias_count_use_attempt(origin_circuit_t *circ)
entry_guards_changed();
log_debug(LD_CIRC,
- "Marked circuit %d (%f/%f) as used for guard %s ($%s).",
+ "Marked circuit %d (%f/%f) as used for guard %s.",
circ->global_identifier,
guard->pb.use_successes, guard->pb.use_attempts,
- guard->nickname, hex_str(guard->identity, DIGEST_LEN));
+ entry_guard_describe(guard));
}
circ->path_state = PATH_STATE_USE_ATTEMPTED;
@@ -718,17 +718,16 @@ pathbias_count_use_success(origin_circuit_t *circ)
if (guard->pb.use_attempts < guard->pb.use_successes) {
log_notice(LD_BUG, "Unexpectedly high use successes counts (%f/%f) "
- "for guard %s=%s",
+ "for guard %s",
guard->pb.use_successes, guard->pb.use_attempts,
- guard->nickname, hex_str(guard->identity, DIGEST_LEN));
+ entry_guard_describe(guard));
}
log_debug(LD_CIRC,
- "Marked circuit %d (%f/%f) as used successfully for guard "
- "%s ($%s).",
+ "Marked circuit %d (%f/%f) as used successfully for guard %s",
circ->global_identifier, guard->pb.use_successes,
- guard->pb.use_attempts, guard->nickname,
- hex_str(guard->identity, DIGEST_LEN));
+ guard->pb.use_attempts,
+ entry_guard_describe(guard));
}
}
@@ -1245,7 +1244,7 @@ pathbias_measure_use_rate(entry_guard_t *guard)
if (pathbias_get_dropguards(options)) {
if (!guard->pb.path_bias_disabled) {
log_warn(LD_CIRC,
- "Your Guard %s ($%s) is failing to carry an extremely large "
+ "Your Guard %s is failing to carry an extremely large "
"amount of stream on its circuits. "
"To avoid potential route manipulation attacks, Tor has "
"disabled use of this guard. "
@@ -1253,7 +1252,7 @@ pathbias_measure_use_rate(entry_guard_t *guard)
"%ld circuits completed, %ld were unusable, %ld collapsed, "
"and %ld timed out. "
"For reference, your timeout cutoff is %ld seconds.",
- guard->nickname, hex_str(guard->identity, DIGEST_LEN),
+ entry_guard_describe(guard),
tor_lround(pathbias_get_use_success_count(guard)),
tor_lround(guard->pb.use_attempts),
tor_lround(pathbias_get_close_success_count(guard)),
@@ -1264,14 +1263,13 @@ pathbias_measure_use_rate(entry_guard_t *guard)
tor_lround(guard->pb.timeouts),
tor_lround(get_circuit_build_close_time_ms()/1000));
guard->pb.path_bias_disabled = 1;
- guard->bad_since = approx_time();
- entry_guards_changed();
+ entry_guard_mark_bad(guard);
return;
}
} else if (!guard->pb.path_bias_use_extreme) {
guard->pb.path_bias_use_extreme = 1;
log_warn(LD_CIRC,
- "Your Guard %s ($%s) is failing to carry an extremely large "
+ "Your Guard %s is failing to carry an extremely large "
"amount of streams on its circuits. "
"This could indicate a route manipulation attack, network "
"overload, bad local network connectivity, or a bug. "
@@ -1279,7 +1277,7 @@ pathbias_measure_use_rate(entry_guard_t *guard)
"%ld circuits completed, %ld were unusable, %ld collapsed, "
"and %ld timed out. "
"For reference, your timeout cutoff is %ld seconds.",
- guard->nickname, hex_str(guard->identity, DIGEST_LEN),
+ entry_guard_describe(guard),
tor_lround(pathbias_get_use_success_count(guard)),
tor_lround(guard->pb.use_attempts),
tor_lround(pathbias_get_close_success_count(guard)),
@@ -1295,7 +1293,7 @@ pathbias_measure_use_rate(entry_guard_t *guard)
if (!guard->pb.path_bias_use_noticed) {
guard->pb.path_bias_use_noticed = 1;
log_notice(LD_CIRC,
- "Your Guard %s ($%s) is failing to carry more streams on its "
+ "Your Guard %s is failing to carry more streams on its "
"circuits than usual. "
"Most likely this means the Tor network is overloaded "
"or your network connection is poor. "
@@ -1303,7 +1301,7 @@ pathbias_measure_use_rate(entry_guard_t *guard)
"%ld circuits completed, %ld were unusable, %ld collapsed, "
"and %ld timed out. "
"For reference, your timeout cutoff is %ld seconds.",
- guard->nickname, hex_str(guard->identity, DIGEST_LEN),
+ entry_guard_describe(guard),
tor_lround(pathbias_get_use_success_count(guard)),
tor_lround(guard->pb.use_attempts),
tor_lround(pathbias_get_close_success_count(guard)),
@@ -1351,7 +1349,7 @@ pathbias_measure_close_rate(entry_guard_t *guard)
if (pathbias_get_dropguards(options)) {
if (!guard->pb.path_bias_disabled) {
log_warn(LD_CIRC,
- "Your Guard %s ($%s) is failing an extremely large "
+ "Your Guard %s is failing an extremely large "
"amount of circuits. "
"To avoid potential route manipulation attacks, Tor has "
"disabled use of this guard. "
@@ -1359,7 +1357,7 @@ pathbias_measure_close_rate(entry_guard_t *guard)
"%ld circuits completed, %ld were unusable, %ld collapsed, "
"and %ld timed out. "
"For reference, your timeout cutoff is %ld seconds.",
- guard->nickname, hex_str(guard->identity, DIGEST_LEN),
+ entry_guard_describe(guard),
tor_lround(pathbias_get_close_success_count(guard)),
tor_lround(guard->pb.circ_attempts),
tor_lround(pathbias_get_use_success_count(guard)),
@@ -1370,14 +1368,13 @@ pathbias_measure_close_rate(entry_guard_t *guard)
tor_lround(guard->pb.timeouts),
tor_lround(get_circuit_build_close_time_ms()/1000));
guard->pb.path_bias_disabled = 1;
- guard->bad_since = approx_time();
- entry_guards_changed();
+ entry_guard_mark_bad(guard);
return;
}
} else if (!guard->pb.path_bias_extreme) {
guard->pb.path_bias_extreme = 1;
log_warn(LD_CIRC,
- "Your Guard %s ($%s) is failing an extremely large "
+ "Your Guard %s is failing an extremely large "
"amount of circuits. "
"This could indicate a route manipulation attack, "
"extreme network overload, or a bug. "
@@ -1385,7 +1382,7 @@ pathbias_measure_close_rate(entry_guard_t *guard)
"%ld circuits completed, %ld were unusable, %ld collapsed, "
"and %ld timed out. "
"For reference, your timeout cutoff is %ld seconds.",
- guard->nickname, hex_str(guard->identity, DIGEST_LEN),
+ entry_guard_describe(guard),
tor_lround(pathbias_get_close_success_count(guard)),
tor_lround(guard->pb.circ_attempts),
tor_lround(pathbias_get_use_success_count(guard)),
@@ -1401,7 +1398,7 @@ pathbias_measure_close_rate(entry_guard_t *guard)
if (!guard->pb.path_bias_warned) {
guard->pb.path_bias_warned = 1;
log_warn(LD_CIRC,
- "Your Guard %s ($%s) is failing a very large "
+ "Your Guard %s is failing a very large "
"amount of circuits. "
"Most likely this means the Tor network is "
"overloaded, but it could also mean an attack against "
@@ -1410,7 +1407,7 @@ pathbias_measure_close_rate(entry_guard_t *guard)
"%ld circuits completed, %ld were unusable, %ld collapsed, "
"and %ld timed out. "
"For reference, your timeout cutoff is %ld seconds.",
- guard->nickname, hex_str(guard->identity, DIGEST_LEN),
+ entry_guard_describe(guard),
tor_lround(pathbias_get_close_success_count(guard)),
tor_lround(guard->pb.circ_attempts),
tor_lround(pathbias_get_use_success_count(guard)),
@@ -1426,14 +1423,14 @@ pathbias_measure_close_rate(entry_guard_t *guard)
if (!guard->pb.path_bias_noticed) {
guard->pb.path_bias_noticed = 1;
log_notice(LD_CIRC,
- "Your Guard %s ($%s) is failing more circuits than "
+ "Your Guard %s is failing more circuits than "
"usual. "
"Most likely this means the Tor network is overloaded. "
"Success counts are %ld/%ld. Use counts are %ld/%ld. "
"%ld circuits completed, %ld were unusable, %ld collapsed, "
"and %ld timed out. "
"For reference, your timeout cutoff is %ld seconds.",
- guard->nickname, hex_str(guard->identity, DIGEST_LEN),
+ entry_guard_describe(guard),
tor_lround(pathbias_get_close_success_count(guard)),
tor_lround(guard->pb.circ_attempts),
tor_lround(pathbias_get_use_success_count(guard)),
@@ -1490,19 +1487,19 @@ pathbias_scale_close_rates(entry_guard_t *guard)
log_info(LD_CIRC,
"Scaled pathbias counts to (%f,%f)/%f (%d/%d open) for guard "
- "%s ($%s)",
+ "%s",
guard->pb.circ_successes, guard->pb.successful_circuits_closed,
guard->pb.circ_attempts, opened_built, opened_attempts,
- guard->nickname, hex_str(guard->identity, DIGEST_LEN));
+ entry_guard_describe(guard));
/* Have the counts just become invalid by this scaling attempt? */
if (counts_are_sane && guard->pb.circ_attempts < guard->pb.circ_successes) {
log_notice(LD_BUG,
"Scaling has mangled pathbias counts to %f/%f (%d/%d open) "
- "for guard %s ($%s)",
+ "for guard %s",
guard->pb.circ_successes, guard->pb.circ_attempts, opened_built,
- opened_attempts, guard->nickname,
- hex_str(guard->identity, DIGEST_LEN));
+ opened_attempts,
+ entry_guard_describe(guard));
}
}
}
@@ -1537,18 +1534,17 @@ pathbias_scale_use_rates(entry_guard_t *guard)
guard->pb.use_attempts += opened_attempts;
log_info(LD_CIRC,
- "Scaled pathbias use counts to %f/%f (%d open) for guard %s ($%s)",
+ "Scaled pathbias use counts to %f/%f (%d open) for guard %s",
guard->pb.use_successes, guard->pb.use_attempts, opened_attempts,
- guard->nickname, hex_str(guard->identity, DIGEST_LEN));
+ entry_guard_describe(guard));
/* Have the counts just become invalid by this scaling attempt? */
if (counts_are_sane && guard->pb.use_attempts < guard->pb.use_successes) {
log_notice(LD_BUG,
"Scaling has mangled pathbias usage counts to %f/%f "
- "(%d open) for guard %s ($%s)",
+ "(%d open) for guard %s",
guard->pb.circ_successes, guard->pb.circ_attempts,
- opened_attempts, guard->nickname,
- hex_str(guard->identity, DIGEST_LEN));
+ opened_attempts, entry_guard_describe(guard));
}
entry_guards_changed();
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index c1940a1..32d198a 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -157,6 +157,26 @@ get_entry_guards(void)
return get_entry_guards_for_guard_selection(get_guard_selection_info());
}
+/** Helper: mark an entry guard as not usable. */
+void
+entry_guard_mark_bad(entry_guard_t *guard)
+{
+ guard->bad_since = approx_time();
+ entry_guards_changed();
+}
+
+/** Return a statically allocated human-readable description of <b>guard</b>
+ */
+const char *
+entry_guard_describe(const entry_guard_t *guard)
+{
+ static char buf[256];
+ tor_snprintf(buf, sizeof(buf),
+ "%s ($%s)",
+ guard->nickname, hex_str(guard->identity, DIGEST_LEN));
+ return buf;
+}
+
/** Check whether the entry guard <b>e</b> is usable, given the directory
* authorities' opinion about the router (stored in <b>ri</b>) and the user's
* configuration (in <b>options</b>). Set <b>e</b>->bad_since
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 3320c5c..97ae3ac 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -100,10 +100,11 @@ int num_live_entry_guards_for_guard_selection(
guard_selection_t *gs,
int for_directory);
int num_live_entry_guards(int for_directory);
-
#endif
const node_t *entry_guard_find_node(const entry_guard_t *guard);
+void entry_guard_mark_bad(entry_guard_t *guard);
+const char *entry_guard_describe(const entry_guard_t *guard);
#ifdef ENTRYNODES_PRIVATE
STATIC const node_t *add_an_entry_guard(guard_selection_t *gs,
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index 781fa4d..aa1b455 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -843,6 +843,22 @@ test_node_preferred_orport(void *arg)
UNMOCK(get_options);
}
+static void
+test_entry_guard_describe(void *arg)
+{
+ (void)arg;
+ entry_guard_t g;
+ memset(&g, 0, sizeof(g));
+ strlcpy(g.nickname, "okefenokee", sizeof(g.nickname));
+ memcpy(g.identity, "theforestprimeval---", DIGEST_LEN);
+
+ tt_str_op(entry_guard_describe(&g), OP_EQ,
+ "okefenokee ($746865666F726573747072696D6576616C2D2D2D)");
+
+ done:
+ ;
+}
+
static const struct testcase_setup_t fake_network = {
fake_network_setup, fake_network_cleanup
};
@@ -876,6 +892,7 @@ struct testcase_t entrynodes_tests[] = {
{ "node_preferred_orport",
test_node_preferred_orport,
0, NULL, NULL },
+ { "entry_guard_describe", test_entry_guard_describe, 0, NULL, NULL },
END_OF_TESTCASES
};
1
0

[tor/master] Add an (as yet) unused UseDeprecatedGuardAlgorithm_ option.
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit 8dc6048c02806e8d30740c5a2a0dd11476909ce4
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Nov 21 17:02:51 2016 -0500
Add an (as yet) unused UseDeprecatedGuardAlgorithm_ option.
I expect we'll be ripping this out somewhere in 0.3.0, but let's
keep it around for a little while in case it turns out to be the
only way to avert disaster?
---
src/or/config.c | 11 +++++++++++
src/or/entrynodes.c | 19 +++++++++++++++++++
src/or/or.h | 8 ++++++++
src/test/test_entrynodes.c | 11 ++++++++++-
4 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/src/or/config.c b/src/or/config.c
index 79a5847..f77f4d1 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -307,6 +307,10 @@ static config_var_t option_vars_[] = {
V(ExtORPortCookieAuthFileGroupReadable, BOOL, "0"),
V(ExtraInfoStatistics, BOOL, "1"),
V(FallbackDir, LINELIST, NULL),
+ /* XXXX prop271 -- this has an ugly name to remind us to remove it. */
+ VAR("UseDeprecatedGuardAlgorithm_", BOOL,
+ UseDeprecatedGuardAlgorithm, "0"),
+
V(UseDefaultFallbackDirs, BOOL, "1"),
OBSOLETE("FallbackNetworkstatusFile"),
@@ -4489,6 +4493,13 @@ options_transition_allowed(const or_options_t *old,
return -1;
}
+ if (old->UseDeprecatedGuardAlgorithm !=
+ new_val->UseDeprecatedGuardAlgorithm) {
+ *msg = tor_strdup("While Tor is running, changing "
+ "UseDeprecatedGuardAlgorithm is not allowed.");
+ return -1;
+ }
+
if (sandbox_is_active()) {
#define SB_NOCHANGE_STR(opt) \
do { \
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 0e56147..959b422 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -1315,6 +1315,9 @@ int
entry_guard_succeeded(guard_selection_t *gs,
circuit_guard_state_t **guard_state_p)
{
+ if (get_options()->UseDeprecatedGuardAlgorithm)
+ return 1;
+
if (BUG(*guard_state_p == NULL))
return -1;
@@ -1345,6 +1348,9 @@ int
entry_guard_failed(guard_selection_t *gs,
circuit_guard_state_t **guard_state_p)
{
+ if (get_options()->UseDeprecatedGuardAlgorithm)
+ return;
+
if (BUG(*guard_state_p == NULL))
return -1;
@@ -2490,6 +2496,9 @@ entry_guards_compute_status_for_guard_selection(guard_selection_t *gs,
if ((!gs) || !(gs->chosen_entry_guards))
return;
+ if (!get_options()->UseDeprecatedGuardAlgorithm)
+ return;
+
if (options->EntryNodes) /* reshuffle the entry guard list if needed */
entry_nodes_should_be_added();
@@ -2582,6 +2591,10 @@ entry_guard_register_connect_status_for_guard_selection(
return 0;
}
+ if (! get_options()->UseDeprecatedGuardAlgorithm) {
+ return 0;
+ }
+
SMARTLIST_FOREACH_BEGIN(gs->chosen_entry_guards, entry_guard_t *, e) {
tor_assert(e);
if (tor_memeq(e->identity, digest, DIGEST_LEN)) {
@@ -2842,6 +2855,8 @@ entry_list_is_constrained(const or_options_t *options)
const node_t *
choose_random_entry(cpath_build_state_t *state)
{
+ tor_assert(get_options()->UseDeprecatedGuardAlgorithm);
+
return choose_random_entry_impl(get_guard_selection_info(),
state, 0, NO_DIRINFO, NULL);
}
@@ -2851,6 +2866,8 @@ choose_random_entry(cpath_build_state_t *state)
const node_t *
choose_random_dirguard(dirinfo_type_t type)
{
+ tor_assert(get_options()->UseDeprecatedGuardAlgorithm);
+
return choose_random_entry_impl(get_guard_selection_info(),
NULL, 1, type, NULL);
}
@@ -2861,6 +2878,8 @@ choose_random_dirguard(dirinfo_type_t type)
int
num_bridges_usable(void)
{
+ tor_assert(get_options()->UseDeprecatedGuardAlgorithm);
+
int n_options = 0;
tor_assert(get_options()->UseBridges);
(void) choose_random_entry_impl(get_guard_selection_info(),
diff --git a/src/or/or.h b/src/or/or.h
index eb0025d..8282731 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -4579,6 +4579,14 @@ typedef struct {
/** If 1, we skip all OOS checks. */
int DisableOOSCheck;
+
+ /** If 1, we use the old (pre-prop271) guard selection algorithm.
+ *
+ * XXXX prop271 This option is only here as a stopgap while we're
+ * XXXX tuning and debugging the new (post-prop271) algorithm. Eventually
+ * we should remove it entirely.
+ */
+ int UseDeprecatedGuardAlgorithm;
} or_options_t;
/** Persistent state for an onion router, as saved to disk. */
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index 8e90b00..6511859 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -212,6 +212,7 @@ test_choose_random_entry_no_guards(void *arg)
memset(&mocked_options, 0, sizeof(mocked_options));
mocked_options.ClientUseIPv4 = 1;
mocked_options.ClientPreferIPv6ORPort = 0;
+ mocked_options.UseDeprecatedGuardAlgorithm = 1;
/* Try to pick an entry even though none of our routers are guards. */
chosen_entry = choose_random_entry(NULL);
@@ -236,6 +237,7 @@ test_choose_random_entry_no_guards(void *arg)
memset(&mocked_options, 0, sizeof(mocked_options));
mocked_options.ClientUseIPv4 = 0;
mocked_options.ClientPreferIPv6ORPort = 0;
+ mocked_options.UseDeprecatedGuardAlgorithm = 1;
chosen_entry = choose_random_entry(NULL);
@@ -248,6 +250,7 @@ test_choose_random_entry_no_guards(void *arg)
mocked_options.ClientUseIPv4 = 1;
mocked_options.ClientUseIPv6 = 1;
mocked_options.ClientPreferIPv6ORPort = 1;
+ mocked_options.UseDeprecatedGuardAlgorithm = 1;
chosen_entry = choose_random_entry(NULL);
tt_assert(chosen_entry);
@@ -257,6 +260,7 @@ test_choose_random_entry_no_guards(void *arg)
memset(&mocked_options, 0, sizeof(mocked_options));
mocked_options.ClientUseIPv4 = 1;
mocked_options.ClientPreferIPv6ORPort = -1;
+ mocked_options.UseDeprecatedGuardAlgorithm = 1;
chosen_entry = choose_random_entry(NULL);
tt_assert(chosen_entry);
@@ -295,6 +299,7 @@ test_choose_random_entry_one_possible_guard(void *arg)
memset(&mocked_options, 0, sizeof(mocked_options));
mocked_options.ClientUseIPv4 = 1;
mocked_options.ClientPreferIPv6ORPort = 0;
+ mocked_options.UseDeprecatedGuardAlgorithm = 1;
/* Pick an entry. Make sure we pick the node we marked as guard. */
chosen_entry = choose_random_entry(NULL);
@@ -315,6 +320,7 @@ test_choose_random_entry_one_possible_guard(void *arg)
memset(&mocked_options, 0, sizeof(mocked_options));
mocked_options.ClientUseIPv4 = 0;
mocked_options.ClientPreferIPv6ORPort = 0;
+ mocked_options.UseDeprecatedGuardAlgorithm = 1;
chosen_entry = choose_random_entry(NULL);
@@ -327,6 +333,7 @@ test_choose_random_entry_one_possible_guard(void *arg)
mocked_options.ClientUseIPv4 = 1;
mocked_options.ClientUseIPv6 = 1;
mocked_options.ClientPreferIPv6ORPort = 1;
+ mocked_options.UseDeprecatedGuardAlgorithm = 1;
chosen_entry = choose_random_entry(NULL);
@@ -339,6 +346,7 @@ test_choose_random_entry_one_possible_guard(void *arg)
memset(&mocked_options, 0, sizeof(mocked_options));
mocked_options.ClientUseIPv4 = 1;
mocked_options.ClientPreferIPv6ORPort = -1;
+ mocked_options.UseDeprecatedGuardAlgorithm = 1;
chosen_entry = choose_random_entry(NULL);
@@ -701,6 +709,7 @@ static void
test_entry_guards_set_from_config(void *arg)
{
or_options_t *options = get_options_mutable();
+ options->UseDeprecatedGuardAlgorithm = 1;
guard_selection_t *gs = get_guard_selection_info();
const smartlist_t *all_entry_guards =
get_entry_guards_for_guard_selection(gs);
@@ -2177,7 +2186,7 @@ struct testcase_t entrynodes_tests[] = {
TT_FORK, NULL, NULL },
{ "choose_random_entry_no_guards", test_choose_random_entry_no_guards,
TT_FORK, &fake_network, NULL },
- { "choose_random_entry_one_possibleguard",
+ { "choose_random_entry_one_possible_guard",
test_choose_random_entry_one_possible_guard,
TT_FORK, &fake_network, NULL },
{ "populate_live_entry_guards_1guard",
1
0