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

[tor/master] Implement bridge backends for sampling, filtering guards.
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit 82fa71610de1c7d7faed78490a3cb90ce917a3e2
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Tue Nov 29 10:19:10 2016 -0500
Implement bridge backends for sampling, filtering guards.
Still missing is functionality for picking bridges when we don't
know a descriptor for them yet, and functionality for learning a
bridge ID.
Everything else remains (basically) the same. Neat!
---
src/or/entrynodes.c | 185 +++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 139 insertions(+), 46 deletions(-)
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index dcaab35..6ac3166 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -802,12 +802,10 @@ entry_guard_add_to_sample_impl(guard_selection_t *gs,
* Add an entry guard to the "bridges" guard selection sample, with
* information taken from <b>bridge</b>. Return that entry guard.
*/
-entry_guard_t *
-entry_guard_add_bridge_to_sample(const bridge_info_t *bridge)
+static entry_guard_t *
+entry_guard_add_bridge_to_sample(guard_selection_t *gs,
+ const bridge_info_t *bridge)
{
- guard_selection_t *gs = get_guard_selection_by_name("bridges",
- GS_TYPE_BRIDGE,
- 1);
const uint8_t *id_digest = bridge_get_rsa_id_digest(bridge);
const tor_addr_port_t *addrport = bridge_get_addr_port(bridge);
@@ -896,24 +894,34 @@ num_reachable_filtered_guards(guard_selection_t *gs)
}
/**
- * Add new guards to the sampled guards in <b>gs</b> until there are
- * enough usable filtered guards, but never grow the sample beyond its
- * maximum size. Return the last guard added, or NULL if none were
- * added.
+ * Return a smartlist of the all the guards that are not currently
+ * members of the sample (GUARDS - SAMPLED_GUARDS). The elements of
+ * this list are node_t pointers in the non-bridge case, and
+ * bridge_info_t pointers in the bridge case. Set *<b>n_guards_out/b>
+ * to the number of guards that we found in GUARDS, including those
+ * that were already sampled.
*/
-STATIC entry_guard_t *
-entry_guards_expand_sample(guard_selection_t *gs)
+static smartlist_t *
+get_eligible_guards(guard_selection_t *gs,
+ int *n_guards_out)
{
- tor_assert(gs);
- int n_sampled = smartlist_len(gs->sampled_entry_guards);
- entry_guard_t *added_guard = NULL;
-
- const smartlist_t *nodes = nodelist_get_list();
/* Construct eligible_guards as GUARDS - SAMPLED_GUARDS */
smartlist_t *eligible_guards = smartlist_new();
int n_guards = 0; // total size of "GUARDS"
- int n_usable_filtered_guards = num_reachable_filtered_guards(gs);
- {
+
+ if (gs->type == GS_TYPE_BRIDGE) {
+ const smartlist_t *bridges = bridge_list_get();
+ SMARTLIST_FOREACH_BEGIN(bridges, bridge_info_t *, bridge) {
+ ++n_guards;
+ if (NULL != get_sampled_guard_for_bridge(gs, bridge)) {
+ continue;
+ }
+ smartlist_add(eligible_guards, bridge);
+ } SMARTLIST_FOREACH_END(bridge);
+ } else {
+ const smartlist_t *nodes = nodelist_get_list();
+ const int n_sampled = smartlist_len(gs->sampled_entry_guards);
+
/* Build a bloom filter of our current guards: let's keep this O(N). */
digestset_t *sampled_guard_ids = digestset_new(n_sampled);
SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, const entry_guard_t *,
@@ -934,11 +942,58 @@ entry_guards_expand_sample(guard_selection_t *gs)
digestset_free(sampled_guard_ids);
}
- /* Is there at least one guard we haven't sampled? */
- if (! smartlist_len(eligible_guards))
- goto done;
+ *n_guards_out = n_guards;
+ return eligible_guards;
+}
+
+/** Helper: given a smartlist of either bridge_info_t (if gs->type is
+ * GS_TYPE_BRIDGE) or node_t (otherwise), pick one that can be a guard,
+ * add it as a guard, remove it from the list, and return a new
+ * entry_guard_t. Return NULL on failure. */
+static entry_guard_t *
+select_and_add_guard_item_for_sample(guard_selection_t *gs,
+ smartlist_t *eligible_guards)
+{
+ entry_guard_t *added_guard;
+ if (gs->type == GS_TYPE_BRIDGE) {
+ const bridge_info_t *bridge = smartlist_choose(eligible_guards);
+ if (BUG(!bridge))
+ return NULL; // LCOV_EXCL_LINE
+ smartlist_remove(eligible_guards, bridge);
+ added_guard = entry_guard_add_bridge_to_sample(gs, bridge);
+ } else {
+ const node_t *node =
+ node_sl_choose_by_bandwidth(eligible_guards, WEIGHT_FOR_GUARD);
+ if (BUG(!node))
+ return NULL; // LCOV_EXCL_LINE
+ smartlist_remove(eligible_guards, node);
+ added_guard = entry_guard_add_to_sample(gs, node);
+ }
- const int max_sample = (int)(n_guards * get_max_sample_threshold());
+ return added_guard;
+}
+
+/**
+ * Add new guards to the sampled guards in <b>gs</b> until there are
+ * enough usable filtered guards, but never grow the sample beyond its
+ * maximum size. Return the last guard added, or NULL if none were
+ * added.
+ */
+STATIC entry_guard_t *
+entry_guards_expand_sample(guard_selection_t *gs)
+{
+ tor_assert(gs);
+ int n_sampled = smartlist_len(gs->sampled_entry_guards);
+ entry_guard_t *added_guard = NULL;
+ int n_usable_filtered_guards = num_reachable_filtered_guards(gs);
+ int n_guards = 0;
+ smartlist_t *eligible_guards = get_eligible_guards(gs, &n_guards);
+
+ const int using_bridges = (gs->type == GS_TYPE_BRIDGE);
+
+ /* XXXX prop271 spec deviation with bridges, max_sample is "all of them" */
+ const int max_sample = using_bridges ? n_guards :
+ (int)(n_guards * get_max_sample_threshold());
const int min_filtered_sample = get_min_filtered_sample_size();
log_info(LD_GUARD, "Expanding the sample guard set. We have %d guards "
@@ -967,12 +1022,7 @@ entry_guards_expand_sample(guard_selection_t *gs)
}
/* Otherwise we can add at least one new guard. */
- const node_t *node =
- node_sl_choose_by_bandwidth(eligible_guards, WEIGHT_FOR_GUARD);
- if (BUG(! node))
- goto done; // LCOV_EXCL_LINE -- should be impossible.
-
- added_guard = entry_guard_add_to_sample(gs, node);
+ added_guard = select_and_add_guard_item_for_sample(gs, eligible_guards);
if (!added_guard)
goto done; // LCOV_EXCL_LINE -- only fails on BUG.
@@ -980,8 +1030,6 @@ entry_guards_expand_sample(guard_selection_t *gs)
if (added_guard->is_usable_filtered_guard)
++n_usable_filtered_guards;
-
- smartlist_remove(eligible_guards, node);
}
done:
@@ -1029,6 +1077,21 @@ remove_guard_from_confirmed_and_primary_lists(guard_selection_t *gs,
}
}
+/** Return true iff <b>guard</b> is currently "listed" -- that is, it
+ * appears in the consensus, or as a configured bridge (as
+ * appropriate) */
+static int
+entry_guard_is_listed(guard_selection_t *gs, const entry_guard_t *guard)
+{
+ if (gs->type == GS_TYPE_BRIDGE) {
+ return NULL != get_bridge_info_for_guard(guard);
+ } else {
+ const node_t *node = node_get_by_id(guard->identity);
+
+ return node && node_is_possible_guard(gs, node);
+ }
+}
+
/**
* Update the status of all sampled guards based on the arrival of a
* new consensus networkstatus document. This will include marking
@@ -1059,11 +1122,8 @@ sampled_guards_update_from_consensus(guard_selection_t *gs)
/* First: Update listed/unlisted. */
SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, guard) {
- /* XXXX prop271 handle bridges right? */
/* XXXX prop271 check ed ID too */
- const node_t *node = node_get_by_id(guard->identity);
-
- const unsigned is_listed = node && node_is_possible_guard(gs, node);
+ const int is_listed = entry_guard_is_listed(gs, guard);
if (is_listed && ! guard->currently_listed) {
++n_changes;
@@ -1113,8 +1173,6 @@ sampled_guards_update_from_consensus(guard_selection_t *gs)
/* Then: remove the ones that have been junk for too long */
SMARTLIST_FOREACH_BEGIN(gs->sampled_entry_guards, entry_guard_t *, guard) {
- /* XXXX prop271 handle bridges right? */
-
int remove = 0;
if (guard->currently_listed == 0 &&
@@ -1180,20 +1238,48 @@ node_passes_guard_filter(const or_options_t *options, guard_selection_t *gs,
/* NOTE: Make sure that this function stays in sync with
* options_transition_affects_entry_guards */
+ tor_assert(! options->UseBridges);
+
(void)gs;
if (routerset_contains_node(options->ExcludeNodes, node))
return 0;
/* XXXX -- prop271 spec deviation -- add entrynodes to spec. */
if (options->EntryNodes &&
- !options->UseBridges &&
!routerset_contains_node(options->EntryNodes, node))
return 0;
if (!fascist_firewall_allows_node(node, FIREWALL_OR_CONNECTION, 0))
return 0;
- if (bool_neq(options->UseBridges, node_is_a_configured_bridge(node)))
+ if (node_is_a_configured_bridge(node))
+ return 0;
+
+ return 1;
+}
+
+/** Helper: Return true iff <b>bridge</b> passes our configuration
+ * filter-- if it is a relay that we are configured to be able to
+ * connect to. */
+static int
+bridge_passes_guard_filter(const or_options_t *options,
+ const bridge_info_t *bridge)
+{
+ tor_assert(options->UseBridges);
+ tor_assert(bridge);
+ if (!bridge)
+ return 0;
+
+ if (routerset_contains_bridge(options->ExcludeNodes, bridge))
+ return 0;
+
+ /* Ignore entrynodes */
+ const tor_addr_port_t *addrport = bridge_get_addr_port(bridge);
+
+ if (!fascist_firewall_allows_address_addr(&addrport->addr,
+ addrport->port,
+ FIREWALL_OR_CONNECTION,
+ 0, 0))
return 0;
return 1;
@@ -1212,14 +1298,21 @@ entry_guard_passes_filter(const or_options_t *options, guard_selection_t *gs,
if (guard->pb.path_bias_disabled)
return 0;
- const node_t *node = node_get_by_id(guard->identity);
- if (node == NULL) {
- // This can happen when currently_listed is true, and we're not updating
- // it because we don't have a live consensus.
- return 0;
- }
+ if (gs->type == GS_TYPE_BRIDGE) {
+ const bridge_info_t *bridge = get_bridge_info_for_guard(guard);
+ if (bridge == NULL)
+ return 0;
+ return bridge_passes_guard_filter(options, bridge);
+ } else {
+ const node_t *node = node_get_by_id(guard->identity);
+ if (node == NULL) {
+ // This can happen when currently_listed is true, and we're not updating
+ // it because we don't have a live consensus.
+ return 0;
+ }
- return node_passes_guard_filter(options, gs, node);
+ return node_passes_guard_filter(options, gs, node);
+ }
}
/**
@@ -3126,7 +3219,7 @@ add_an_entry_guard(guard_selection_t *gs,
/** Entry point for bridges.c to add a bridge as guard.
*
- * XXXX prop271 refactor.*/
+ * XXXX prop271 refactor, bridge.*/
void
add_bridge_as_entry_guard(guard_selection_t *gs,
const node_t *chosen)
1
0

[tor/master] Add some needed accessors/inspectors for bridge/guard convergence
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit 53f248f6c9d71784c271cf14501ec4c28e5e885d
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Tue Nov 29 10:14:42 2016 -0500
Add some needed accessors/inspectors for bridge/guard convergence
---
src/or/bridges.c | 24 ++++--------------------
src/or/bridges.h | 5 +++++
src/or/entrynodes.c | 48 +++++++++++++++++++++++++++++++++++++++++++++---
src/or/entrynodes.h | 4 ----
src/or/routerset.c | 13 +++++++++++++
src/or/routerset.h | 5 ++++-
6 files changed, 71 insertions(+), 28 deletions(-)
diff --git a/src/or/bridges.c b/src/or/bridges.c
index f16acfa..8090bae 100644
--- a/src/or/bridges.c
+++ b/src/or/bridges.c
@@ -179,7 +179,7 @@ get_configured_bridge_by_orports_digest(const char *digest,
* bridge with no known digest whose address matches <b>addr</b>:<b>port</b>,
* return that bridge. Else return NULL. If <b>digest</b> is NULL, check for
* address/port matches only. */
-static bridge_info_t *
+bridge_info_t *
get_configured_bridge_by_addr_port_digest(const tor_addr_t *addr,
uint16_t port,
const char *digest)
@@ -416,28 +416,12 @@ bridge_add_from_config(bridge_line_t *bridge_line)
smartlist_add(bridge_list, b);
}
-/** Return true iff <b>routerset</b> contains the bridge <b>bridge</b>. */
-static int
-routerset_contains_bridge(const routerset_t *routerset,
- const bridge_info_t *bridge)
-{
- int result;
- extend_info_t *extinfo;
- tor_assert(bridge);
- if (!routerset)
- return 0;
-
- extinfo = extend_info_new(
- NULL, bridge->identity, NULL, NULL, &bridge->addr, bridge->port);
- result = routerset_contains_extendinfo(routerset, extinfo);
- extend_info_free(extinfo);
- return result;
-}
-
/** If <b>digest</b> is one of our known bridges, return it. */
-static bridge_info_t *
+bridge_info_t *
find_bridge_by_digest(const char *digest)
{
+ if (! bridge_list)
+ return NULL;
SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge,
{
if (tor_memeq(bridge->identity, digest, DIGEST_LEN))
diff --git a/src/or/bridges.h b/src/or/bridges.h
index d01794f..74c5113 100644
--- a/src/or/bridges.h
+++ b/src/or/bridges.h
@@ -20,8 +20,13 @@ typedef struct bridge_info_t bridge_info_t;
void mark_bridge_list(void);
void sweep_bridge_list(void);
const smartlist_t *bridge_list_get(void);
+bridge_info_t *find_bridge_by_digest(const char *digest);
const uint8_t *bridge_get_rsa_id_digest(const bridge_info_t *bridge);
const tor_addr_port_t * bridge_get_addr_port(const bridge_info_t *bridge);
+bridge_info_t *get_configured_bridge_by_addr_port_digest(
+ const tor_addr_t *addr,
+ uint16_t port,
+ const char *digest);
int addr_is_a_configured_bridge(const tor_addr_t *addr, uint16_t port,
const char *digest);
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index e725d4e..dcaab35 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -167,6 +167,8 @@ static entry_guard_t *entry_guard_add_to_sample_impl(guard_selection_t *gs,
const uint8_t *rsa_id_digest,
const char *nickname,
const tor_addr_port_t *bridge_addrport);
+static entry_guard_t *get_sampled_guard_by_bridge_addr(guard_selection_t *gs,
+ const tor_addr_port_t *addrport);
/** Return 0 if we should apply guardfraction information found in the
* consensus. A specific consensus can be specified with the
@@ -679,6 +681,46 @@ get_sampled_guard_with_id(guard_selection_t *gs,
return NULL;
}
+/** If <b>gs</b> contains a sampled entry guard matching <b>bridge</b>,
+ * return that guard. Otherwise return NULL. */
+static entry_guard_t *
+get_sampled_guard_for_bridge(guard_selection_t *gs,
+ const bridge_info_t *bridge)
+{
+ const uint8_t *id = bridge_get_rsa_id_digest(bridge);
+ const tor_addr_port_t *addrport = bridge_get_addr_port(bridge);
+ entry_guard_t *guard;
+ if (id) {
+ guard = get_sampled_guard_with_id(gs, id);
+ if (guard)
+ return guard;
+ }
+ if (BUG(!addrport))
+ return NULL; // LCOV_EXCL_LINE
+ guard = get_sampled_guard_by_bridge_addr(gs, addrport);
+ if (! guard || (id && tor_memneq(id, guard->identity, DIGEST_LEN)))
+ return NULL;
+ else
+ return guard;
+}
+
+/** If we know a bridge_info_t matching <b>guard</b>, return that
+ * bridge. Otherwise return NULL. */
+static bridge_info_t *
+get_bridge_info_for_guard(const entry_guard_t *guard)
+{
+ if (! tor_digest_is_zero(guard->identity)) {
+ bridge_info_t *bridge = find_bridge_by_digest(guard->identity);
+ if (bridge)
+ return bridge;
+ }
+ if (BUG(guard->bridge_addr == NULL))
+ return NULL;
+ return get_configured_bridge_by_addr_port_digest(&guard->bridge_addr->addr,
+ guard->bridge_addr->port,
+ NULL);
+}
+
/**
* Return true iff we have a sampled guard with the RSA identity digest
* <b>rsa_id</b>. */
@@ -779,8 +821,8 @@ entry_guard_add_bridge_to_sample(const bridge_info_t *bridge)
* or NULL if none exists.
*/
static entry_guard_t *
-entry_guard_get_by_bridge_addr(guard_selection_t *gs,
- const tor_addr_port_t *addrport)
+get_sampled_guard_by_bridge_addr(guard_selection_t *gs,
+ const tor_addr_port_t *addrport)
{
if (! gs)
return NULL;
@@ -806,7 +848,7 @@ entry_guard_learned_bridge_identity(const tor_addr_port_t *addrport,
if (!gs)
return;
- entry_guard_t *g = entry_guard_get_by_bridge_addr(gs, addrport);
+ entry_guard_t *g = get_sampled_guard_by_bridge_addr(gs, addrport);
if (!g)
return;
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index cbc3f89..21dab6e 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -563,10 +563,6 @@ void remove_all_entry_guards_for_guard_selection(guard_selection_t *gs);
void remove_all_entry_guards(void);
struct bridge_info_t;
-// XXXX prop271 should this be a public API?
-entry_guard_t *entry_guard_add_bridge_to_sample(
- const struct bridge_info_t *bridge);
-
void entry_guard_learned_bridge_identity(const tor_addr_port_t *addrport,
const uint8_t *rsa_id_digest);
diff --git a/src/or/routerset.c b/src/or/routerset.c
index 4182dbc..d0df0a7 100644
--- a/src/or/routerset.c
+++ b/src/or/routerset.c
@@ -28,6 +28,7 @@
#define ROUTERSET_PRIVATE
#include "or.h"
+#include "bridges.h"
#include "geoip.h"
#include "nodelist.h"
#include "policies.h"
@@ -334,6 +335,18 @@ routerset_contains_node(const routerset_t *set, const node_t *node)
return 0;
}
+/** Return true iff <b>routerset</b> contains the bridge <b>bridge</b>. */
+int
+routerset_contains_bridge(const routerset_t *set, const bridge_info_t *bridge)
+{
+ const char *id = (const char*)bridge_get_rsa_id_digest(bridge);
+ const tor_addr_port_t *addrport = bridge_get_addr_port(bridge);
+
+ tor_assert(addrport);
+ return routerset_contains(set, &addrport->addr, addrport->port,
+ NULL, id, -1);
+}
+
/** Add every known node_t that is a member of <b>routerset</b> to
* <b>out</b>, but never add any that are part of <b>excludeset</b>.
* If <b>running_only</b>, only add the running ones. */
diff --git a/src/or/routerset.h b/src/or/routerset.h
index c2f7205..2e3b4b0 100644
--- a/src/or/routerset.h
+++ b/src/or/routerset.h
@@ -26,8 +26,11 @@ int routerset_contains_routerstatus(const routerset_t *set,
country_t country);
int routerset_contains_extendinfo(const routerset_t *set,
const extend_info_t *ei);
-
+struct bridge_info_t;
+int routerset_contains_bridge(const routerset_t *set,
+ const struct bridge_info_t *bridge);
int routerset_contains_node(const routerset_t *set, const node_t *node);
+
void routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
const routerset_t *excludeset,
int running_only);
1
0

16 Dec '16
commit be447bc7700bc91c3b0f2475c06d1e9e64c90804
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Nov 14 11:51:38 2016 -0500
Move path-bias fields into a separate structure
(Other than the field movement, the code changes here are just
search-and-replace)
---
src/or/circpathbias.c | 216 ++++++++++++++++++++++-----------------------
src/or/entrynodes.c | 52 +++++------
src/or/entrynodes.h | 69 ++++++++-------
src/test/test_entrynodes.c | 24 ++---
4 files changed, 181 insertions(+), 180 deletions(-)
diff --git a/src/or/circpathbias.c b/src/or/circpathbias.c
index 2968607..6e2589c 100644
--- a/src/or/circpathbias.c
+++ b/src/or/circpathbias.c
@@ -58,14 +58,14 @@ entry_guard_inc_circ_attempt_count(entry_guard_t *guard)
pathbias_measure_close_rate(guard);
- if (guard->path_bias_disabled)
+ if (guard->pb.path_bias_disabled)
return -1;
pathbias_scale_close_rates(guard);
- guard->circ_attempts++;
+ guard->pb.circ_attempts++;
log_info(LD_CIRC, "Got success count %f/%f for guard %s ($%s)",
- guard->circ_successes, guard->circ_attempts, guard->nickname,
+ guard->pb.circ_successes, guard->pb.circ_attempts, guard->nickname,
hex_str(guard->identity, DIGEST_LEN));
return 0;
}
@@ -518,11 +518,11 @@ pathbias_count_build_success(origin_circuit_t *circ)
if (guard) {
if (circ->path_state == PATH_STATE_BUILD_ATTEMPTED) {
circ->path_state = PATH_STATE_BUILD_SUCCEEDED;
- guard->circ_successes++;
+ guard->pb.circ_successes++;
entry_guards_changed();
log_info(LD_CIRC, "Got success count %f/%f for guard %s ($%s)",
- guard->circ_successes, guard->circ_attempts,
+ guard->pb.circ_successes, guard->pb.circ_attempts,
guard->nickname, hex_str(guard->identity, DIGEST_LEN));
} else {
if ((rate_msg = rate_limit_log(&success_notice_limit,
@@ -538,10 +538,10 @@ pathbias_count_build_success(origin_circuit_t *circ)
}
}
- if (guard->circ_attempts < guard->circ_successes) {
+ if (guard->pb.circ_attempts < guard->pb.circ_successes) {
log_notice(LD_BUG, "Unexpectedly high successes counts (%f/%f) "
"for guard %s ($%s)",
- guard->circ_successes, guard->circ_attempts,
+ guard->pb.circ_successes, guard->pb.circ_attempts,
guard->nickname, hex_str(guard->identity, DIGEST_LEN));
}
/* In rare cases, CIRCUIT_PURPOSE_TESTING can get converted to
@@ -604,13 +604,13 @@ pathbias_count_use_attempt(origin_circuit_t *circ)
if (guard) {
pathbias_measure_use_rate(guard);
pathbias_scale_use_rates(guard);
- guard->use_attempts++;
+ guard->pb.use_attempts++;
entry_guards_changed();
log_debug(LD_CIRC,
"Marked circuit %d (%f/%f) as used for guard %s ($%s).",
circ->global_identifier,
- guard->use_successes, guard->use_attempts,
+ guard->pb.use_successes, guard->pb.use_attempts,
guard->nickname, hex_str(guard->identity, DIGEST_LEN));
}
@@ -713,21 +713,21 @@ pathbias_count_use_success(origin_circuit_t *circ)
guard = entry_guard_get_by_id_digest(
circ->cpath->extend_info->identity_digest);
if (guard) {
- guard->use_successes++;
+ guard->pb.use_successes++;
entry_guards_changed();
- if (guard->use_attempts < guard->use_successes) {
+ if (guard->pb.use_attempts < guard->pb.use_successes) {
log_notice(LD_BUG, "Unexpectedly high use successes counts (%f/%f) "
"for guard %s=%s",
- guard->use_successes, guard->use_attempts,
+ guard->pb.use_successes, guard->pb.use_attempts,
guard->nickname, hex_str(guard->identity, DIGEST_LEN));
}
log_debug(LD_CIRC,
"Marked circuit %d (%f/%f) as used successfully for guard "
"%s ($%s).",
- circ->global_identifier, guard->use_successes,
- guard->use_attempts, guard->nickname,
+ circ->global_identifier, guard->pb.use_successes,
+ guard->pb.use_attempts, guard->nickname,
hex_str(guard->identity, DIGEST_LEN));
}
}
@@ -1031,7 +1031,7 @@ pathbias_count_successful_close(origin_circuit_t *circ)
if (guard) {
/* In the long run: circuit_success ~= successful_circuit_close +
* circ_failure + stream_failure */
- guard->successful_circuits_closed++;
+ guard->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
@@ -1068,7 +1068,7 @@ pathbias_count_collapse(origin_circuit_t *circ)
}
if (guard) {
- guard->collapsed_circuits++;
+ 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
@@ -1101,7 +1101,7 @@ pathbias_count_use_failed(origin_circuit_t *circ)
}
if (guard) {
- guard->unusable_circuits++;
+ 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
@@ -1144,7 +1144,7 @@ pathbias_count_timeout(origin_circuit_t *circ)
}
if (guard) {
- guard->timeouts++;
+ guard->pb.timeouts++;
entry_guards_changed();
}
}
@@ -1200,7 +1200,7 @@ pathbias_count_circs_in_states(entry_guard_t *guard,
double
pathbias_get_close_success_count(entry_guard_t *guard)
{
- return guard->successful_circuits_closed +
+ return guard->pb.successful_circuits_closed +
pathbias_count_circs_in_states(guard,
PATH_STATE_BUILD_SUCCEEDED,
PATH_STATE_USE_SUCCEEDED);
@@ -1216,7 +1216,7 @@ pathbias_get_close_success_count(entry_guard_t *guard)
double
pathbias_get_use_success_count(entry_guard_t *guard)
{
- return guard->use_successes +
+ return guard->pb.use_successes +
pathbias_count_circs_in_states(guard,
PATH_STATE_USE_ATTEMPTED,
PATH_STATE_USE_SUCCEEDED);
@@ -1235,15 +1235,15 @@ pathbias_measure_use_rate(entry_guard_t *guard)
{
const or_options_t *options = get_options();
- if (guard->use_attempts > pathbias_get_min_use(options)) {
+ if (guard->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->use_attempts
+ if (pathbias_get_use_success_count(guard)/guard->pb.use_attempts
< pathbias_get_extreme_use_rate(options)) {
/* Dropping is currently disabled by default. */
if (pathbias_get_dropguards(options)) {
- if (!guard->path_bias_disabled) {
+ if (!guard->pb.path_bias_disabled) {
log_warn(LD_CIRC,
"Your Guard %s ($%s) is failing to carry an extremely large "
"amount of stream on its circuits. "
@@ -1255,21 +1255,21 @@ pathbias_measure_use_rate(entry_guard_t *guard)
"For reference, your timeout cutoff is %ld seconds.",
guard->nickname, hex_str(guard->identity, DIGEST_LEN),
tor_lround(pathbias_get_use_success_count(guard)),
- tor_lround(guard->use_attempts),
+ tor_lround(guard->pb.use_attempts),
tor_lround(pathbias_get_close_success_count(guard)),
- tor_lround(guard->circ_attempts),
- tor_lround(guard->circ_successes),
- tor_lround(guard->unusable_circuits),
- tor_lround(guard->collapsed_circuits),
- tor_lround(guard->timeouts),
+ 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(get_circuit_build_close_time_ms()/1000));
- guard->path_bias_disabled = 1;
+ guard->pb.path_bias_disabled = 1;
guard->bad_since = approx_time();
entry_guards_changed();
return;
}
- } else if (!guard->path_bias_use_extreme) {
- guard->path_bias_use_extreme = 1;
+ } 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 "
"amount of streams on its circuits. "
@@ -1281,19 +1281,19 @@ pathbias_measure_use_rate(entry_guard_t *guard)
"For reference, your timeout cutoff is %ld seconds.",
guard->nickname, hex_str(guard->identity, DIGEST_LEN),
tor_lround(pathbias_get_use_success_count(guard)),
- tor_lround(guard->use_attempts),
+ tor_lround(guard->pb.use_attempts),
tor_lround(pathbias_get_close_success_count(guard)),
- tor_lround(guard->circ_attempts),
- tor_lround(guard->circ_successes),
- tor_lround(guard->unusable_circuits),
- tor_lround(guard->collapsed_circuits),
- tor_lround(guard->timeouts),
+ 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(get_circuit_build_close_time_ms()/1000));
}
- } else if (pathbias_get_use_success_count(guard)/guard->use_attempts
+ } else if (pathbias_get_use_success_count(guard)/guard->pb.use_attempts
< pathbias_get_notice_use_rate(options)) {
- if (!guard->path_bias_use_noticed) {
- guard->path_bias_use_noticed = 1;
+ 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 "
"circuits than usual. "
@@ -1305,13 +1305,13 @@ pathbias_measure_use_rate(entry_guard_t *guard)
"For reference, your timeout cutoff is %ld seconds.",
guard->nickname, hex_str(guard->identity, DIGEST_LEN),
tor_lround(pathbias_get_use_success_count(guard)),
- tor_lround(guard->use_attempts),
+ tor_lround(guard->pb.use_attempts),
tor_lround(pathbias_get_close_success_count(guard)),
- tor_lround(guard->circ_attempts),
- tor_lround(guard->circ_successes),
- tor_lround(guard->unusable_circuits),
- tor_lround(guard->collapsed_circuits),
- tor_lround(guard->timeouts),
+ 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(get_circuit_build_close_time_ms()/1000));
}
}
@@ -1341,15 +1341,15 @@ pathbias_measure_close_rate(entry_guard_t *guard)
{
const or_options_t *options = get_options();
- if (guard->circ_attempts > pathbias_get_min_circs(options)) {
+ if (guard->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->circ_attempts
+ if (pathbias_get_close_success_count(guard)/guard->pb.circ_attempts
< pathbias_get_extreme_rate(options)) {
/* Dropping is currently disabled by default. */
if (pathbias_get_dropguards(options)) {
- if (!guard->path_bias_disabled) {
+ if (!guard->pb.path_bias_disabled) {
log_warn(LD_CIRC,
"Your Guard %s ($%s) is failing an extremely large "
"amount of circuits. "
@@ -1361,21 +1361,21 @@ pathbias_measure_close_rate(entry_guard_t *guard)
"For reference, your timeout cutoff is %ld seconds.",
guard->nickname, hex_str(guard->identity, DIGEST_LEN),
tor_lround(pathbias_get_close_success_count(guard)),
- tor_lround(guard->circ_attempts),
+ tor_lround(guard->pb.circ_attempts),
tor_lround(pathbias_get_use_success_count(guard)),
- tor_lround(guard->use_attempts),
- tor_lround(guard->circ_successes),
- tor_lround(guard->unusable_circuits),
- tor_lround(guard->collapsed_circuits),
- tor_lround(guard->timeouts),
+ 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(get_circuit_build_close_time_ms()/1000));
- guard->path_bias_disabled = 1;
+ guard->pb.path_bias_disabled = 1;
guard->bad_since = approx_time();
entry_guards_changed();
return;
}
- } else if (!guard->path_bias_extreme) {
- guard->path_bias_extreme = 1;
+ } 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 "
"amount of circuits. "
@@ -1387,19 +1387,19 @@ pathbias_measure_close_rate(entry_guard_t *guard)
"For reference, your timeout cutoff is %ld seconds.",
guard->nickname, hex_str(guard->identity, DIGEST_LEN),
tor_lround(pathbias_get_close_success_count(guard)),
- tor_lround(guard->circ_attempts),
+ tor_lround(guard->pb.circ_attempts),
tor_lround(pathbias_get_use_success_count(guard)),
- tor_lround(guard->use_attempts),
- tor_lround(guard->circ_successes),
- tor_lround(guard->unusable_circuits),
- tor_lround(guard->collapsed_circuits),
- tor_lround(guard->timeouts),
+ 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(get_circuit_build_close_time_ms()/1000));
}
- } else if (pathbias_get_close_success_count(guard)/guard->circ_attempts
+ } else if (pathbias_get_close_success_count(guard)/guard->pb.circ_attempts
< pathbias_get_warn_rate(options)) {
- if (!guard->path_bias_warned) {
- guard->path_bias_warned = 1;
+ 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 "
"amount of circuits. "
@@ -1412,19 +1412,19 @@ pathbias_measure_close_rate(entry_guard_t *guard)
"For reference, your timeout cutoff is %ld seconds.",
guard->nickname, hex_str(guard->identity, DIGEST_LEN),
tor_lround(pathbias_get_close_success_count(guard)),
- tor_lround(guard->circ_attempts),
+ tor_lround(guard->pb.circ_attempts),
tor_lround(pathbias_get_use_success_count(guard)),
- tor_lround(guard->use_attempts),
- tor_lround(guard->circ_successes),
- tor_lround(guard->unusable_circuits),
- tor_lround(guard->collapsed_circuits),
- tor_lround(guard->timeouts),
+ 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(get_circuit_build_close_time_ms()/1000));
}
- } else if (pathbias_get_close_success_count(guard)/guard->circ_attempts
+ } else if (pathbias_get_close_success_count(guard)/guard->pb.circ_attempts
< pathbias_get_notice_rate(options)) {
- if (!guard->path_bias_noticed) {
- guard->path_bias_noticed = 1;
+ 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 "
"usual. "
@@ -1435,13 +1435,13 @@ pathbias_measure_close_rate(entry_guard_t *guard)
"For reference, your timeout cutoff is %ld seconds.",
guard->nickname, hex_str(guard->identity, DIGEST_LEN),
tor_lround(pathbias_get_close_success_count(guard)),
- tor_lround(guard->circ_attempts),
+ tor_lround(guard->pb.circ_attempts),
tor_lround(pathbias_get_use_success_count(guard)),
- tor_lround(guard->use_attempts),
- tor_lround(guard->circ_successes),
- tor_lround(guard->unusable_circuits),
- tor_lround(guard->collapsed_circuits),
- tor_lround(guard->timeouts),
+ 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(get_circuit_build_close_time_ms()/1000));
}
}
@@ -1463,7 +1463,7 @@ pathbias_scale_close_rates(entry_guard_t *guard)
const or_options_t *options = get_options();
/* If we get a ton of circuits, just scale everything down */
- if (guard->circ_attempts > pathbias_get_scale_threshold(options)) {
+ if (guard->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);
@@ -1471,36 +1471,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->circ_attempts >= guard->circ_successes);
+ int counts_are_sane = (guard->pb.circ_attempts >= guard->pb.circ_successes);
- guard->circ_attempts -= (opened_attempts+opened_built);
- guard->circ_successes -= opened_built;
+ guard->pb.circ_attempts -= (opened_attempts+opened_built);
+ guard->pb.circ_successes -= opened_built;
- guard->circ_attempts *= scale_ratio;
- guard->circ_successes *= scale_ratio;
- guard->timeouts *= scale_ratio;
- guard->successful_circuits_closed *= scale_ratio;
- guard->collapsed_circuits *= scale_ratio;
- guard->unusable_circuits *= scale_ratio;
+ 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;
- guard->circ_attempts += (opened_attempts+opened_built);
- guard->circ_successes += opened_built;
+ guard->pb.circ_attempts += (opened_attempts+opened_built);
+ guard->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 ($%s)",
- guard->circ_successes, guard->successful_circuits_closed,
- guard->circ_attempts, opened_built, opened_attempts,
+ 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));
/* Have the counts just become invalid by this scaling attempt? */
- if (counts_are_sane && guard->circ_attempts < guard->circ_successes) {
+ 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)",
- guard->circ_successes, guard->circ_attempts, opened_built,
+ guard->pb.circ_successes, guard->pb.circ_attempts, opened_built,
opened_attempts, guard->nickname,
hex_str(guard->identity, DIGEST_LEN));
}
@@ -1522,31 +1522,31 @@ pathbias_scale_use_rates(entry_guard_t *guard)
const or_options_t *options = get_options();
/* If we get a ton of circuits, just scale everything down */
- if (guard->use_attempts > pathbias_get_scale_use_threshold(options)) {
+ if (guard->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->use_attempts >= guard->use_successes);
+ int counts_are_sane = (guard->pb.use_attempts >= guard->pb.use_successes);
- guard->use_attempts -= opened_attempts;
+ guard->pb.use_attempts -= opened_attempts;
- guard->use_attempts *= scale_ratio;
- guard->use_successes *= scale_ratio;
+ guard->pb.use_attempts *= scale_ratio;
+ guard->pb.use_successes *= scale_ratio;
- guard->use_attempts += opened_attempts;
+ guard->pb.use_attempts += opened_attempts;
log_info(LD_CIRC,
"Scaled pathbias use counts to %f/%f (%d open) for guard %s ($%s)",
- guard->use_successes, guard->use_attempts, opened_attempts,
+ guard->pb.use_successes, guard->pb.use_attempts, opened_attempts,
guard->nickname, hex_str(guard->identity, DIGEST_LEN));
/* Have the counts just become invalid by this scaling attempt? */
- if (counts_are_sane && guard->use_attempts < guard->use_successes) {
+ 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)",
- guard->circ_successes, guard->circ_attempts,
+ guard->pb.circ_successes, guard->pb.circ_attempts,
opened_attempts, guard->nickname,
hex_str(guard->identity, DIGEST_LEN));
}
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 434f2f6..c1940a1 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -192,7 +192,7 @@ entry_guard_set_status(entry_guard_t *e, const node_t *node,
/* We only care about OR connection connectivity for entry guards. */
else if (!fascist_firewall_allows_node(node, FIREWALL_OR_CONNECTION, 0))
*reason = "unreachable by config";
- else if (e->path_bias_disabled)
+ else if (e->pb.path_bias_disabled)
*reason = "path-biased";
if (*reason && ! e->bad_since) {
@@ -297,7 +297,7 @@ entry_is_live(const entry_guard_t *e, entry_is_live_flags_t flags,
tor_assert(msg);
- if (e->path_bias_disabled) {
+ if (e->pb.path_bias_disabled) {
*msg = "path-biased";
return NULL;
}
@@ -748,7 +748,7 @@ remove_dead_entry_guards(guard_selection_t *gs, time_t now)
for (i = 0; i < smartlist_len(gs->chosen_entry_guards); ) {
entry_guard_t *entry = smartlist_get(gs->chosen_entry_guards, i);
if (entry->bad_since &&
- ! entry->path_bias_disabled &&
+ ! entry->pb.path_bias_disabled &&
entry->bad_since + ENTRY_GUARD_REMOVE_AFTER < now) {
base16_encode(dbuf, sizeof(dbuf), entry->identity, DIGEST_LEN);
@@ -1534,22 +1534,22 @@ entry_guards_parse_state_for_guard_selection(
success_cnt = use_cnt;
}
- node->use_attempts = use_cnt;
- node->use_successes = success_cnt;
+ node->pb.use_attempts = use_cnt;
+ node->pb.use_successes = success_cnt;
log_info(LD_GENERAL, "Read %f/%f path use bias for node %s",
- node->use_successes, node->use_attempts, node->nickname);
+ node->pb.use_successes, node->pb.use_attempts, node->nickname);
/* 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(node)/node->use_attempts
+ if (pathbias_get_use_success_count(node)/node->pb.use_attempts
< pathbias_get_extreme_use_rate(options) &&
pathbias_get_dropguards(options)) {
- node->path_bias_disabled = 1;
+ node->pb.path_bias_disabled = 1;
log_info(LD_GENERAL,
"Path use bias is too high (%f/%f); disabling node %s",
- node->circ_successes, node->circ_attempts, node->nickname);
+ node->pb.circ_successes, node->pb.circ_attempts, node->nickname);
}
} else if (!strcasecmp(line->key, "EntryGuardPathBias")) {
const or_options_t *options = get_options();
@@ -1599,26 +1599,26 @@ entry_guards_parse_state_for_guard_selection(
success_cnt = hop_cnt;
}
- node->circ_attempts = hop_cnt;
- node->circ_successes = success_cnt;
+ node->pb.circ_attempts = hop_cnt;
+ node->pb.circ_successes = success_cnt;
- node->successful_circuits_closed = successful_closed;
- node->timeouts = timeouts;
- node->collapsed_circuits = collapsed;
- node->unusable_circuits = unusable;
+ node->pb.successful_circuits_closed = successful_closed;
+ node->pb.timeouts = timeouts;
+ node->pb.collapsed_circuits = collapsed;
+ node->pb.unusable_circuits = unusable;
log_info(LD_GENERAL, "Read %f/%f path bias for node %s",
- node->circ_successes, node->circ_attempts, node->nickname);
+ node->pb.circ_successes, node->pb.circ_attempts, node->nickname);
/* 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(node)/node->circ_attempts
+ if (pathbias_get_close_success_count(node)/node->pb.circ_attempts
< pathbias_get_extreme_rate(options) &&
pathbias_get_dropguards(options)) {
- node->path_bias_disabled = 1;
+ node->pb.path_bias_disabled = 1;
log_info(LD_GENERAL,
"Path bias is too high (%f/%f); disabling node %s",
- node->circ_successes, node->circ_attempts, node->nickname);
+ node->pb.circ_successes, node->pb.circ_attempts, node->nickname);
}
} else {
@@ -1644,7 +1644,7 @@ entry_guards_parse_state_for_guard_selection(
e->chosen_by_version = tor_strdup(state_version);
}
}
- if (e->path_bias_disabled && !e->bad_since)
+ if (e->pb.path_bias_disabled && !e->bad_since)
e->bad_since = time(NULL);
}
SMARTLIST_FOREACH_END(e);
@@ -1788,25 +1788,25 @@ entry_guards_update_state(or_state_t *state)
d, e->chosen_by_version, t);
next = &(line->next);
}
- if (e->circ_attempts > 0) {
+ if (e->pb.circ_attempts > 0) {
*next = line = tor_malloc_zero(sizeof(config_line_t));
line->key = tor_strdup("EntryGuardPathBias");
/* In the long run: circuit_success ~= successful_circuit_close +
* collapsed_circuits +
* unusable_circuits */
tor_asprintf(&line->value, "%f %f %f %f %f %f",
- e->circ_attempts, e->circ_successes,
+ e->pb.circ_attempts, e->pb.circ_successes,
pathbias_get_close_success_count(e),
- e->collapsed_circuits,
- e->unusable_circuits, e->timeouts);
+ e->pb.collapsed_circuits,
+ e->pb.unusable_circuits, e->pb.timeouts);
next = &(line->next);
}
- if (e->use_attempts > 0) {
+ if (e->pb.use_attempts > 0) {
*next = line = tor_malloc_zero(sizeof(config_line_t));
line->key = tor_strdup("EntryGuardPathUseBias");
tor_asprintf(&line->value, "%f %f",
- e->use_attempts,
+ e->pb.use_attempts,
pathbias_get_use_success_count(e));
next = &(line->next);
}
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 7f5a911..3320c5c 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -18,22 +18,11 @@ 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;
-#if defined(ENTRYNODES_PRIVATE) || defined(ENTRYNODES_EXPOSE_STRUCT)
-/** 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
- * don't have any directory info. */
-struct entry_guard_t {
- char nickname[MAX_NICKNAME_LEN+1];
- char identity[DIGEST_LEN];
- time_t chosen_on_date; /**< Approximately when was this guard added?
- * "0" if we don't know. */
- char *chosen_by_version; /**< What tor version added this guard? NULL
- * if we don't know. */
- unsigned int made_contact : 1; /**< 0 if we have never connected to this
- * router, 1 if we have. */
- unsigned int can_retry : 1; /**< Should we retry connecting to this entry,
- * in spite of having it marked as unreachable?*/
+/* 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.
+ */
+typedef struct guard_pathbias_t {
unsigned int path_bias_noticed : 1; /**< Did we alert the user about path
* bias for this node already? */
unsigned int path_bias_warned : 1; /**< Did we alert the user about path bias
@@ -46,23 +35,6 @@ struct entry_guard_t {
* use bias for this node already? */
unsigned int path_bias_use_extreme : 1; /**< Did we alert the user about path
* use bias for this node already? */
- unsigned int is_dir_cache : 1; /**< Is this node a directory cache? */
- time_t bad_since; /**< 0 if this guard is currently usable, or the time at
- * which it was observed to become (according to the
- * directory or the user configuration) unusable. */
- time_t unreachable_since; /**< 0 if we can connect to this guard, or the
- * time at which we first noticed we couldn't
- * connect to it. */
- time_t last_attempted; /**< 0 if we can connect to this guard, or the time
- * at which we last failed to connect to it. */
-
- /**
- * @name circpathbias fields
- *
- * These fields are used in circpathbias.c to try to detect entry
- * nodes that are failing circuits at a suspicious frequency.
- */
- /**@{*/
double circ_attempts; /**< Number of circuits this guard has "attempted" */
double circ_successes; /**< Number of successfully built circuits using
@@ -79,7 +51,36 @@ struct entry_guard_t {
double use_attempts; /**< Number of circuits we tried to use with streams */
double use_successes; /**< Number of successfully used circuits using
* this guard as first hop. */
- /**@}*/
+} guard_pathbias_t;
+
+#if defined(ENTRYNODES_PRIVATE) || defined(ENTRYNODES_EXPOSE_STRUCT)
+/** 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
+ * don't have any directory info. */
+struct entry_guard_t {
+ char nickname[MAX_NICKNAME_LEN+1];
+ char identity[DIGEST_LEN];
+ time_t chosen_on_date; /**< Approximately when was this guard added?
+ * "0" if we don't know. */
+ char *chosen_by_version; /**< What tor version added this guard? NULL
+ * if we don't know. */
+ unsigned int made_contact : 1; /**< 0 if we have never connected to this
+ * router, 1 if we have. */
+ unsigned int can_retry : 1; /**< Should we retry connecting to this entry,
+ * in spite of having it marked as unreachable?*/
+ unsigned int is_dir_cache : 1; /**< Is this node a directory cache? */
+ time_t bad_since; /**< 0 if this guard is currently usable, or the time at
+ * which it was observed to become (according to the
+ * directory or the user configuration) unusable. */
+ time_t unreachable_since; /**< 0 if we can connect to this guard, or the
+ * time at which we first noticed we couldn't
+ * connect to it. */
+ time_t last_attempted; /**< 0 if we can connect to this guard, or the time
+ * at which we last failed to connect to it. */
+
+ /** Path bias information for this guard. */
+ guard_pathbias_t pb;
};
#endif
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index 8e4f406..781fa4d 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -477,12 +477,12 @@ test_entry_guards_parse_state_simple(void *arg)
/* The rest should be unset */
tt_assert(!e->unreachable_since);
tt_assert(!e->can_retry);
- tt_assert(!e->path_bias_noticed);
- tt_assert(!e->path_bias_warned);
- tt_assert(!e->path_bias_extreme);
- tt_assert(!e->path_bias_disabled);
- tt_assert(!e->path_bias_use_noticed);
- tt_assert(!e->path_bias_use_extreme);
+ tt_assert(!e->pb.path_bias_noticed);
+ tt_assert(!e->pb.path_bias_warned);
+ tt_assert(!e->pb.path_bias_extreme);
+ tt_assert(!e->pb.path_bias_disabled);
+ tt_assert(!e->pb.path_bias_use_noticed);
+ tt_assert(!e->pb.path_bias_use_extreme);
tt_assert(!e->last_attempted);
}
@@ -563,13 +563,13 @@ test_entry_guards_parse_state_pathbias(void *arg)
tt_assert(!e->can_retry);
/* XXX tt_double_op doesn't support equality. Cast to int for now. */
- tt_int_op((int)e->circ_attempts, OP_EQ, (int)circ_attempts);
- tt_int_op((int)e->circ_successes, OP_EQ, (int)circ_successes);
- tt_int_op((int)e->successful_circuits_closed, OP_EQ,
+ tt_int_op((int)e->pb.circ_attempts, OP_EQ, (int)circ_attempts);
+ tt_int_op((int)e->pb.circ_successes, OP_EQ, (int)circ_successes);
+ tt_int_op((int)e->pb.successful_circuits_closed, OP_EQ,
(int)successful_closed);
- tt_int_op((int)e->timeouts, OP_EQ, (int)timeouts);
- tt_int_op((int)e->collapsed_circuits, OP_EQ, (int)collapsed);
- tt_int_op((int)e->unusable_circuits, OP_EQ, (int)unusable);
+ tt_int_op((int)e->pb.timeouts, OP_EQ, (int)timeouts);
+ tt_int_op((int)e->pb.collapsed_circuits, OP_EQ, (int)collapsed);
+ tt_int_op((int)e->pb.unusable_circuits, OP_EQ, (int)unusable);
}
done:
1
0

16 Dec '16
commit 22f2f13f81407cffd46d5b17eca4bcead347fe58
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Nov 14 11:41:37 2016 -0500
prop271: make entry_guard_t mostly-private
The entry_guard_t structure should really be opaque, so that we
can change its contents and have the rest of Tor not care.
This commit makes it "mostly opaque" -- circpathbias.c can still see
inside it. (I'm making circpathbias.c exempt since it's the only
part of Tor outside of entrynodes.c that made serious use of
entry_guard_t internals.)
---
src/or/circpathbias.c | 3 +++
src/or/circuitbuild.c | 2 +-
src/or/entrynodes.c | 9 +++++++++
src/or/entrynodes.h | 18 ++++++++++++------
4 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/src/or/circpathbias.c b/src/or/circpathbias.c
index 6ee69aa..2968607 100644
--- a/src/or/circpathbias.c
+++ b/src/or/circpathbias.c
@@ -21,6 +21,9 @@
* 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"
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 0881f23..2998f5c 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -2238,7 +2238,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
)) {
SMARTLIST_FOREACH(get_entry_guards(), const entry_guard_t *, entry,
{
- if ((node = node_get_by_id(entry->identity))) {
+ if ((node = entry_guard_find_node(entry))) {
nodelist_add_node_and_family(excluded, node);
}
});
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index b3fa31d..434f2f6 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -405,6 +405,15 @@ entry_guard_get_by_id_digest_for_guard_selection(guard_selection_t *gs,
return NULL;
}
+/** Return the node_t associated with a single entry_guard_t. May
+ * return NULL if the guard is not currently in the consensus. */
+const node_t *
+entry_guard_find_node(const entry_guard_t *guard)
+{
+ tor_assert(guard);
+ return node_get_by_id(guard->identity);
+}
+
/** If <b>digest</b> matches the identity of any node in the
* entry_guards list for the default guard selection state,
return that node. Else return NULL. */
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 00f9691..7f5a911 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -12,18 +12,18 @@
#ifndef TOR_ENTRYNODES_H
#define TOR_ENTRYNODES_H
-#if 1
-/* XXXX NM I would prefer that all of this stuff be private to
- * entrynodes.c. */
-
/* 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;
+
+#if defined(ENTRYNODES_PRIVATE) || defined(ENTRYNODES_EXPOSE_STRUCT)
/** 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
* don't have any directory info. */
-typedef struct entry_guard_t {
+struct entry_guard_t {
char nickname[MAX_NICKNAME_LEN+1];
char identity[DIGEST_LEN];
time_t chosen_on_date; /**< Approximately when was this guard added?
@@ -80,8 +80,12 @@ typedef struct entry_guard_t {
double use_successes; /**< Number of successfully used circuits using
* this guard as first hop. */
/**@}*/
-} entry_guard_t;
+};
+#endif
+#if 1
+/* XXXX NM I would prefer that all of this stuff be private to
+ * entrynodes.c. */
entry_guard_t *entry_guard_get_by_id_digest_for_guard_selection(
guard_selection_t *gs, const char *digest);
entry_guard_t *entry_guard_get_by_id_digest(const char *digest);
@@ -98,6 +102,8 @@ int num_live_entry_guards(int for_directory);
#endif
+const node_t *entry_guard_find_node(const entry_guard_t *guard);
+
#ifdef ENTRYNODES_PRIVATE
STATIC const node_t *add_an_entry_guard(guard_selection_t *gs,
const node_t *chosen,
1
0

[tor/master] Whitespace fixes from previous mechanical search-and-replaces
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit 043e9b01516c7cdcff939f2724b75155458da1b1
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Nov 14 13:01:19 2016 -0500
Whitespace fixes from previous mechanical search-and-replaces
---
src/or/circpathbias.c | 2 +-
src/or/entrynodes.c | 9 ++++++---
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/or/circpathbias.c b/src/or/circpathbias.c
index 3df68b8..be11465 100644
--- a/src/or/circpathbias.c
+++ b/src/or/circpathbias.c
@@ -1355,7 +1355,7 @@ pathbias_measure_close_rate(entry_guard_t *guard)
{
const or_options_t *options = get_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
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 90918fa..7890f83 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -1583,7 +1583,8 @@ entry_guards_parse_state_for_guard_selection(
node->pb.path_bias_disabled = 1;
log_info(LD_GENERAL,
"Path use bias is too high (%f/%f); disabling node %s",
- node->pb.circ_successes, node->pb.circ_attempts, node->nickname);
+ node->pb.circ_successes, node->pb.circ_attempts,
+ node->nickname);
}
} else if (!strcasecmp(line->key, "EntryGuardPathBias")) {
const or_options_t *options = get_options();
@@ -1642,7 +1643,8 @@ entry_guards_parse_state_for_guard_selection(
node->pb.unusable_circuits = unusable;
log_info(LD_GENERAL, "Read %f/%f path bias for node %s",
- node->pb.circ_successes, node->pb.circ_attempts, node->nickname);
+ node->pb.circ_successes, node->pb.circ_attempts,
+ node->nickname);
/* 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 <= */
@@ -1652,7 +1654,8 @@ entry_guards_parse_state_for_guard_selection(
node->pb.path_bias_disabled = 1;
log_info(LD_GENERAL,
"Path bias is too high (%f/%f); disabling node %s",
- node->pb.circ_successes, node->pb.circ_attempts, node->nickname);
+ node->pb.circ_successes, node->pb.circ_attempts,
+ node->nickname);
}
} else {
1
0

[tor/master] Collect old guard algorithm parameters into one place
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit 3c12133038f5a9213b13beca50d91ddac2f9d7fb
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Tue Nov 15 08:28:41 2016 -0500
Collect old guard algorithm parameters into one place
---
src/or/entrynodes.c | 156 ++++++++++++++++++++++++++-----------------------
src/or/networkstatus.h | 4 ++
2 files changed, 87 insertions(+), 73 deletions(-)
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 95b3c5a..461d29f 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -81,6 +81,12 @@ static const node_t *choose_random_entry_impl(guard_selection_t *gs,
int *n_options_out);
static guard_selection_t * guard_selection_new(void);
+/**
+ * @name Constants for old (pre-prop271) guard selection algorithm.
+ */
+
+/**@{*/
+
/* Default number of entry guards in the case where the NumEntryGuards
* consensus parameter is not set */
#define DEFAULT_N_GUARDS 1
@@ -88,6 +94,62 @@ static guard_selection_t * guard_selection_new(void);
* consensus parameter is set). */
#define MIN_N_GUARDS 1
#define MAX_N_GUARDS 10
+/** Largest amount that we'll backdate chosen_on_date */
+#define CHOSEN_ON_DATE_SLOP (30*86400)
+/** How long (in seconds) do we allow an entry guard to be nonfunctional,
+ * unlisted, excluded, or otherwise nonusable before we give up on it? */
+#define ENTRY_GUARD_REMOVE_AFTER (30*24*60*60)
+/**}@*/
+
+/**
+ * @name Networkstatus parameters for old (pre-prop271) guard selection
+ */
+/**@}*/
+/** 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. */
+STATIC int
+decide_num_guards(const or_options_t *options, int for_directory)
+{
+ if (for_directory) {
+ int answer;
+ if (options->NumDirectoryGuards != 0)
+ return options->NumDirectoryGuards;
+ answer = networkstatus_get_param(NULL, "NumDirectoryGuards", 0, 0, 10);
+ if (answer) /* non-zero means use the consensus value */
+ return answer;
+ }
+
+ if (options->NumEntryGuards)
+ return options->NumEntryGuards;
+
+ /* Use the value from the consensus, or 3 if no guidance. */
+ return networkstatus_get_param(NULL, "NumEntryGuards", DEFAULT_N_GUARDS,
+ MIN_N_GUARDS, MAX_N_GUARDS);
+}
+
+/** Return 0 if we should apply guardfraction information found in the
+ * consensus. A specific consensus can be specified with the
+ * <b>ns</b> argument, if NULL the most recent one will be picked.*/
+int
+should_apply_guardfraction(const networkstatus_t *ns)
+{
+ /* We need to check the corresponding torrc option and the consensus
+ * parameter if we need to. */
+ const or_options_t *options = get_options();
+
+ /* If UseGuardFraction is 'auto' then check the same-named consensus
+ * parameter. If the consensus parameter is not present, default to
+ * "off". */
+ if (options->UseGuardFraction == -1) {
+ return networkstatus_get_param(ns, "UseGuardFraction",
+ 0, /* default to "off" */
+ 0, 1);
+ }
+
+ return options->UseGuardFraction;
+}
+/**@}*/
/** Allocate a new guard_selection_t */
@@ -795,9 +857,6 @@ control_event_guard_deferred(void)
#endif
}
-/** Largest amount that we'll backdate chosen_on_date */
-#define CHOSEN_ON_DATE_SLOP (30*86400)
-
/** Add a new (preferably stable and fast) router to our chosen_entry_guards
* list for the supplied guard selection. Return a pointer to the router if
* we succeed, or NULL if we can't find any more suitable entries.
@@ -903,27 +962,30 @@ add_bridge_as_entry_guard(guard_selection_t *gs,
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. */
-STATIC int
-decide_num_guards(const or_options_t *options, int for_directory)
+/**
+ * Return the minimum lifetime of working entry guard, in seconds,
+ * as given in the consensus networkstatus. (Plus CHOSEN_ON_DATE_SLOP,
+ * so that we can do the chosen_on_date randomization while achieving the
+ * desired minimum lifetime.)
+ */
+static int32_t
+guards_get_lifetime(void)
{
- if (for_directory) {
- int answer;
- if (options->NumDirectoryGuards != 0)
- return options->NumDirectoryGuards;
- answer = networkstatus_get_param(NULL, "NumDirectoryGuards", 0, 0, 10);
- if (answer) /* non-zero means use the consensus value */
- return answer;
- }
+ const or_options_t *options = get_options();
+#define DFLT_GUARD_LIFETIME (86400 * 60) /* Two months. */
+#define MIN_GUARD_LIFETIME (86400 * 30) /* One months. */
+#define MAX_GUARD_LIFETIME (86400 * 1826) /* Five years. */
- if (options->NumEntryGuards)
- return options->NumEntryGuards;
+ if (options->GuardLifetime >= 1) {
+ return CLAMP(MIN_GUARD_LIFETIME,
+ options->GuardLifetime,
+ MAX_GUARD_LIFETIME) + CHOSEN_ON_DATE_SLOP;
+ }
- /* Use the value from the consensus, or 3 if no guidance. */
- return networkstatus_get_param(NULL, "NumEntryGuards", DEFAULT_N_GUARDS,
- MIN_N_GUARDS, MAX_N_GUARDS);
+ return networkstatus_get_param(NULL, "GuardLifetime",
+ DFLT_GUARD_LIFETIME,
+ MIN_GUARD_LIFETIME,
+ MAX_GUARD_LIFETIME) + CHOSEN_ON_DATE_SLOP;
}
/** If the use of entry guards is configured, choose more entry guards
@@ -950,10 +1012,6 @@ pick_entry_guards(guard_selection_t *gs,
entry_guards_changed_for_guard_selection(gs);
}
-/** How long (in seconds) do we allow an entry guard to be nonfunctional,
- * unlisted, excluded, or otherwise nonusable before we give up on it? */
-#define ENTRY_GUARD_REMOVE_AFTER (30*24*60*60)
-
/** Release all storage held by <b>e</b>. */
STATIC void
entry_guard_free(entry_guard_t *e)
@@ -966,32 +1024,6 @@ entry_guard_free(entry_guard_t *e)
tor_free(e);
}
-/**
- * Return the minimum lifetime of working entry guard, in seconds,
- * as given in the consensus networkstatus. (Plus CHOSEN_ON_DATE_SLOP,
- * so that we can do the chosen_on_date randomization while achieving the
- * desired minimum lifetime.)
- */
-static int32_t
-guards_get_lifetime(void)
-{
- const or_options_t *options = get_options();
-#define DFLT_GUARD_LIFETIME (86400 * 60) /* Two months. */
-#define MIN_GUARD_LIFETIME (86400 * 30) /* One months. */
-#define MAX_GUARD_LIFETIME (86400 * 1826) /* Five years. */
-
- if (options->GuardLifetime >= 1) {
- return CLAMP(MIN_GUARD_LIFETIME,
- options->GuardLifetime,
- MAX_GUARD_LIFETIME) + CHOSEN_ON_DATE_SLOP;
- }
-
- return networkstatus_get_param(NULL, "GuardLifetime",
- DFLT_GUARD_LIFETIME,
- MIN_GUARD_LIFETIME,
- MAX_GUARD_LIFETIME) + CHOSEN_ON_DATE_SLOP;
-}
-
/** Remove from a guard selection context any entry guard which was selected
* by an unknown version of Tor, or which was selected by a version of Tor
* that's known to select entry guards badly, or which was selected more 2
@@ -2221,28 +2253,6 @@ getinfo_helper_entry_guards(control_connection_t *conn,
return 0;
}
-/** Return 0 if we should apply guardfraction information found in the
- * consensus. A specific consensus can be specified with the
- * <b>ns</b> argument, if NULL the most recent one will be picked.*/
-int
-should_apply_guardfraction(const networkstatus_t *ns)
-{
- /* We need to check the corresponding torrc option and the consensus
- * parameter if we need to. */
- const or_options_t *options = get_options();
-
- /* If UseGuardFraction is 'auto' then check the same-named consensus
- * parameter. If the consensus parameter is not present, default to
- * "off". */
- if (options->UseGuardFraction == -1) {
- return networkstatus_get_param(ns, "UseGuardFraction",
- 0, /* default to "off" */
- 0, 1);
- }
-
- return options->UseGuardFraction;
-}
-
/* Given the original bandwidth of a guard and its guardfraction,
* calculate how much bandwidth the guard should have as a guard and
* as a non-guard.
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index 71f36b6..96f8347 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -111,6 +111,10 @@ 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

[tor/master] Add the prop271 fields to entry_guard_t. Not used yet.
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit df8256a931099767d9f70997c9eb1ef934afd392
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Nov 14 13:27:35 2016 -0500
Add the prop271 fields to entry_guard_t. Not used yet.
---
src/or/entrynodes.c | 1 +
src/or/entrynodes.h | 43 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+)
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 7890f83..bd4d83c 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -683,6 +683,7 @@ 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);
}
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 2e18a2f..4f39a09 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -18,6 +18,10 @@ 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;
+#define GUARD_REACHABLE_NO 0
+#define GUARD_REACHABLE_YES 1
+#define GUARD_REACHABLE_MAYBE 2
+
/* 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.
@@ -61,6 +65,43 @@ typedef struct guard_pathbias_t {
struct entry_guard_t {
char nickname[MAX_NICKNAME_LEN+1];
char identity[DIGEST_LEN];
+ ed25519_public_key_t ed_id;
+
+ /* XXXX prop271 DOCDOC document all these fields better */
+
+ /* Persistent fields, present for all sampled guards. */
+ time_t sampled_on_date;
+ time_t unlisted_since_date;
+ char *sampled_by_version;
+ unsigned currently_listed : 1;
+
+ /* Persistent fields, for confirmed guards. */
+ time_t confirmed_on_date; /* 0 if not confirmed */
+ int confirmed_idx; /* -1 if not confirmed; otherwise the order that this
+ * item should occur in the CONFIRMED_GUARDS ordered
+ * list */
+
+ /* ==== Non-persistent fields. */
+ /* == These are used by sampled guards */
+ time_t last_tried_to_connect;
+ unsigned is_reachable : 2; /* One of GUARD_REACHABLE_{NO,YES,MAYBE} */
+ unsigned is_pending : 1;
+ time_t failing_since;
+
+ /* These determine presence in filtered guards and usable-filtered-guards
+ * respectively. */
+ unsigned is_filtered_guard : 1;
+ unsigned is_usable_filtered_guard : 1;
+
+ /**
+ * @name legacy guard selection algorithm fields
+ *
+ * These are used and maintained by the legacy (pre-prop271) entry guard
+ * algorithm. Most of them we will remove as prop271 gets implemented.
+ * The rest we'll migrate over, if they are 100% semantically identical to
+ * their prop271 equivalents. XXXXprop271
+ */
+ /**@{*/
time_t chosen_on_date; /**< Approximately when was this guard added?
* "0" if we don't know. */
char *chosen_by_version; /**< What tor version added this guard? NULL
@@ -79,6 +120,8 @@ struct entry_guard_t {
time_t last_attempted; /**< 0 if we can connect to this guard, or the time
* at which we last failed to connect to it. */
+ /**}@*/
+
/** Path bias information for this guard. */
guard_pathbias_t pb;
};
1
0

16 Dec '16
commit 8da24c99bdb90b04a05d5bccf5bcff1218174b75
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Tue Nov 15 07:49:06 2016 -0500
Split bridge functions into a new module.
This patch is just:
* Code movement
* Adding headers here and there as needed
* Adding a bridges_free_all() with a call to it.
It breaks compilation, since the bridge code needed to make exactly
2 calls into entrynodes.c internals. I'll fix those in the next
commit.
---
src/or/bridges.c | 809 +++++++++++++++++++++++++++++++++++++++++++++
src/or/bridges.h | 54 +++
src/or/circuitbuild.c | 1 +
src/or/circuituse.c | 1 +
src/or/config.c | 1 +
src/or/connection.c | 1 +
src/or/connection_or.c | 1 +
src/or/control.c | 1 +
src/or/directory.c | 1 +
src/or/entrynodes.c | 776 +------------------------------------------
src/or/entrynodes.h | 34 --
src/or/include.am | 2 +
src/or/main.c | 2 +
src/or/networkstatus.c | 1 +
src/or/routerlist.c | 1 +
src/or/transports.c | 2 +-
src/test/test_config.c | 1 +
src/test/test_controller.c | 1 +
18 files changed, 880 insertions(+), 810 deletions(-)
diff --git a/src/or/bridges.c b/src/or/bridges.c
new file mode 100644
index 0000000..73510cf
--- /dev/null
+++ b/src/or/bridges.c
@@ -0,0 +1,809 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2016, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file bridges.c
+ * \brief Code to manage bridges and bridge selection.
+ *
+ * Bridges are fixed entry nodes, used for censorship circumvention.
+ **/
+
+#include "or.h"
+#include "bridges.h"
+#include "circuitbuild.h"
+#include "config.h"
+#include "connection.h"
+#include "directory.h"
+#include "entrynodes.h"
+#include "nodelist.h"
+#include "policies.h"
+#include "router.h"
+#include "routerlist.h"
+#include "routerset.h"
+#include "transports.h"
+
+/** Information about a configured bridge. Currently this just matches the
+ * ones in the torrc file, but one day we may be able to learn about new
+ * bridges on our own, and remember them in the state file. */
+typedef struct {
+ /** Address of the bridge. */
+ tor_addr_t addr;
+ /** TLS port for the bridge. */
+ uint16_t port;
+ /** Boolean: We are re-parsing our bridge list, and we are going to remove
+ * this one if we don't find it in the list of configured bridges. */
+ unsigned marked_for_removal : 1;
+ /** Expected identity digest, or all zero bytes if we don't know what the
+ * digest should be. */
+ char identity[DIGEST_LEN];
+
+ /** Name of pluggable transport protocol taken from its config line. */
+ char *transport_name;
+
+ /** When should we next try to fetch a descriptor for this bridge? */
+ download_status_t fetch_status;
+
+ /** A smartlist of k=v values to be passed to the SOCKS proxy, if
+ transports are used for this bridge. */
+ smartlist_t *socks_args;
+} 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
+ * in this list does not necessarily correspond to the order of bridges
+ * in the torrc. */
+static smartlist_t *bridge_list = NULL;
+
+/** Mark every entry of the bridge list to be removed on our next call to
+ * sweep_bridge_list unless it has first been un-marked. */
+void
+mark_bridge_list(void)
+{
+ if (!bridge_list)
+ bridge_list = smartlist_new();
+ SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b,
+ b->marked_for_removal = 1);
+}
+
+/** Remove every entry of the bridge list that was marked with
+ * mark_bridge_list if it has not subsequently been un-marked. */
+void
+sweep_bridge_list(void)
+{
+ if (!bridge_list)
+ bridge_list = smartlist_new();
+ SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) {
+ if (b->marked_for_removal) {
+ SMARTLIST_DEL_CURRENT(bridge_list, b);
+ bridge_free(b);
+ }
+ } SMARTLIST_FOREACH_END(b);
+}
+
+/** Initialize the bridge list to empty, creating it if needed. */
+static void
+clear_bridge_list(void)
+{
+ if (!bridge_list)
+ bridge_list = smartlist_new();
+ SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b, bridge_free(b));
+ smartlist_clear(bridge_list);
+}
+
+/** Free the bridge <b>bridge</b>. */
+static void
+bridge_free(bridge_info_t *bridge)
+{
+ if (!bridge)
+ return;
+
+ tor_free(bridge->transport_name);
+ if (bridge->socks_args) {
+ SMARTLIST_FOREACH(bridge->socks_args, char*, s, tor_free(s));
+ smartlist_free(bridge->socks_args);
+ }
+
+ tor_free(bridge);
+}
+
+/** If we have a bridge configured whose digest matches <b>digest</b>, or a
+ * bridge with no known digest whose address matches any of the
+ * tor_addr_port_t's in <b>orports</b>, return that bridge. Else return
+ * NULL. */
+static bridge_info_t *
+get_configured_bridge_by_orports_digest(const char *digest,
+ const smartlist_t *orports)
+{
+ if (!bridge_list)
+ return NULL;
+ SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge)
+ {
+ if (tor_digest_is_zero(bridge->identity)) {
+ SMARTLIST_FOREACH_BEGIN(orports, tor_addr_port_t *, ap)
+ {
+ if (tor_addr_compare(&bridge->addr, &ap->addr, CMP_EXACT) == 0 &&
+ bridge->port == ap->port)
+ return bridge;
+ }
+ SMARTLIST_FOREACH_END(ap);
+ }
+ if (digest && tor_memeq(bridge->identity, digest, DIGEST_LEN))
+ return bridge;
+ }
+ SMARTLIST_FOREACH_END(bridge);
+ return NULL;
+}
+
+/** If we have a bridge configured whose digest matches <b>digest</b>, or a
+ * bridge with no known digest whose address matches <b>addr</b>:<b>port</b>,
+ * return that bridge. Else return NULL. If <b>digest</b> is NULL, check for
+ * address/port matches only. */
+static bridge_info_t *
+get_configured_bridge_by_addr_port_digest(const tor_addr_t *addr,
+ uint16_t port,
+ const char *digest)
+{
+ if (!bridge_list)
+ return NULL;
+ SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge)
+ {
+ if ((tor_digest_is_zero(bridge->identity) || digest == NULL) &&
+ !tor_addr_compare(&bridge->addr, addr, CMP_EXACT) &&
+ bridge->port == port)
+ return bridge;
+ if (digest && tor_memeq(bridge->identity, digest, DIGEST_LEN))
+ return bridge;
+ }
+ SMARTLIST_FOREACH_END(bridge);
+ return NULL;
+}
+
+/** If we have a bridge configured whose digest matches <b>digest</b>, or a
+ * bridge with no known digest whose address matches <b>addr</b>:<b>port</b>,
+ * return 1. Else return 0. If <b>digest</b> is NULL, check for
+ * address/port matches only. */
+int
+addr_is_a_configured_bridge(const tor_addr_t *addr,
+ uint16_t port,
+ const char *digest)
+{
+ tor_assert(addr);
+ return get_configured_bridge_by_addr_port_digest(addr, port, digest) ? 1 : 0;
+}
+
+/** If we have a bridge configured whose digest matches
+ * <b>ei->identity_digest</b>, or a bridge with no known digest whose address
+ * matches <b>ei->addr</b>:<b>ei->port</b>, return 1. Else return 0.
+ * If <b>ei->onion_key</b> is NULL, check for address/port matches only. */
+int
+extend_info_is_a_configured_bridge(const extend_info_t *ei)
+{
+ const char *digest = ei->onion_key ? ei->identity_digest : NULL;
+ return addr_is_a_configured_bridge(&ei->addr, ei->port, digest);
+}
+
+/** Wrapper around get_configured_bridge_by_addr_port_digest() to look
+ * it up via router descriptor <b>ri</b>. */
+static bridge_info_t *
+get_configured_bridge_by_routerinfo(const routerinfo_t *ri)
+{
+ bridge_info_t *bi = NULL;
+ smartlist_t *orports = router_get_all_orports(ri);
+ bi = get_configured_bridge_by_orports_digest(ri->cache_info.identity_digest,
+ orports);
+ SMARTLIST_FOREACH(orports, tor_addr_port_t *, p, tor_free(p));
+ smartlist_free(orports);
+ return bi;
+}
+
+/** Return 1 if <b>ri</b> is one of our known bridges, else 0. */
+int
+routerinfo_is_a_configured_bridge(const routerinfo_t *ri)
+{
+ return get_configured_bridge_by_routerinfo(ri) ? 1 : 0;
+}
+
+/** Return 1 if <b>node</b> is one of our configured bridges, else 0. */
+int
+node_is_a_configured_bridge(const node_t *node)
+{
+ int retval = 0;
+ smartlist_t *orports = node_get_all_orports(node);
+ retval = get_configured_bridge_by_orports_digest(node->identity,
+ orports) != NULL;
+ SMARTLIST_FOREACH(orports, tor_addr_port_t *, p, tor_free(p));
+ smartlist_free(orports);
+ return retval;
+}
+
+/** We made a connection to a router at <b>addr</b>:<b>port</b>
+ * without knowing its digest. Its digest turned out to be <b>digest</b>.
+ * If it was a bridge, and we still don't know its digest, record it.
+ */
+void
+learned_router_identity(const tor_addr_t *addr, uint16_t port,
+ const char *digest)
+{
+ bridge_info_t *bridge =
+ get_configured_bridge_by_addr_port_digest(addr, port, digest);
+ if (bridge && tor_digest_is_zero(bridge->identity)) {
+ char *transport_info = NULL;
+ const char *transport_name =
+ find_transport_name_by_bridge_addrport(addr, port);
+ if (transport_name)
+ tor_asprintf(&transport_info, " (with transport '%s')", transport_name);
+
+ memcpy(bridge->identity, digest, DIGEST_LEN);
+ log_notice(LD_DIR, "Learned fingerprint %s for bridge %s%s.",
+ hex_str(digest, DIGEST_LEN), fmt_addrport(addr, port),
+ transport_info ? transport_info : "");
+ tor_free(transport_info);
+ }
+}
+
+/** Return true if <b>bridge</b> has the same identity digest as
+ * <b>digest</b>. If <b>digest</b> is NULL, it matches
+ * bridges with unspecified identity digests. */
+static int
+bridge_has_digest(const bridge_info_t *bridge, const char *digest)
+{
+ if (digest)
+ return tor_memeq(digest, bridge->identity, DIGEST_LEN);
+ else
+ return tor_digest_is_zero(bridge->identity);
+}
+
+/** We are about to add a new bridge at <b>addr</b>:<b>port</b>, with optional
+ * <b>digest</b> and <b>transport_name</b>. Mark for removal any previously
+ * existing bridge with the same address and port, and warn the user as
+ * appropriate.
+ */
+static void
+bridge_resolve_conflicts(const tor_addr_t *addr, uint16_t port,
+ const char *digest, const char *transport_name)
+{
+ /* Iterate the already-registered bridge list:
+
+ If you find a bridge with the same adress and port, mark it for
+ removal. It doesn't make sense to have two active bridges with
+ the same IP:PORT. If the bridge in question has a different
+ digest or transport than <b>digest</b>/<b>transport_name</b>,
+ it's probably a misconfiguration and we should warn the user.
+ */
+ SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge) {
+ if (bridge->marked_for_removal)
+ continue;
+
+ if (tor_addr_eq(&bridge->addr, addr) && (bridge->port == port)) {
+
+ bridge->marked_for_removal = 1;
+
+ if (!bridge_has_digest(bridge, digest) ||
+ strcmp_opt(bridge->transport_name, transport_name)) {
+ /* warn the user */
+ char *bridge_description_new, *bridge_description_old;
+ tor_asprintf(&bridge_description_new, "%s:%s:%s",
+ fmt_addrport(addr, port),
+ digest ? hex_str(digest, DIGEST_LEN) : "",
+ transport_name ? transport_name : "");
+ tor_asprintf(&bridge_description_old, "%s:%s:%s",
+ fmt_addrport(&bridge->addr, bridge->port),
+ tor_digest_is_zero(bridge->identity) ?
+ "" : hex_str(bridge->identity,DIGEST_LEN),
+ bridge->transport_name ? bridge->transport_name : "");
+
+ log_warn(LD_GENERAL,"Tried to add bridge '%s', but we found a conflict"
+ " with the already registered bridge '%s'. We will discard"
+ " the old bridge and keep '%s'. If this is not what you"
+ " wanted, please change your configuration file accordingly.",
+ bridge_description_new, bridge_description_old,
+ bridge_description_new);
+
+ tor_free(bridge_description_new);
+ tor_free(bridge_description_old);
+ }
+ }
+ } SMARTLIST_FOREACH_END(bridge);
+}
+
+/** Return True if we have a bridge that uses a transport with name
+ * <b>transport_name</b>. */
+MOCK_IMPL(int,
+transport_is_needed, (const char *transport_name))
+{
+ if (!bridge_list)
+ return 0;
+
+ SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) {
+ if (bridge->transport_name &&
+ !strcmp(bridge->transport_name, transport_name))
+ return 1;
+ } SMARTLIST_FOREACH_END(bridge);
+
+ return 0;
+}
+
+/** Register the bridge information in <b>bridge_line</b> to the
+ * bridge subsystem. Steals reference of <b>bridge_line</b>. */
+void
+bridge_add_from_config(bridge_line_t *bridge_line)
+{
+ bridge_info_t *b;
+
+ { /* Log the bridge we are about to register: */
+ log_debug(LD_GENERAL, "Registering bridge at %s (transport: %s) (%s)",
+ fmt_addrport(&bridge_line->addr, bridge_line->port),
+ bridge_line->transport_name ?
+ bridge_line->transport_name : "no transport",
+ tor_digest_is_zero(bridge_line->digest) ?
+ "no key listed" : hex_str(bridge_line->digest, DIGEST_LEN));
+
+ if (bridge_line->socks_args) { /* print socks arguments */
+ int i = 0;
+
+ tor_assert(smartlist_len(bridge_line->socks_args) > 0);
+
+ log_debug(LD_GENERAL, "Bridge uses %d SOCKS arguments:",
+ smartlist_len(bridge_line->socks_args));
+ SMARTLIST_FOREACH(bridge_line->socks_args, const char *, arg,
+ log_debug(LD_CONFIG, "%d: %s", ++i, arg));
+ }
+ }
+
+ bridge_resolve_conflicts(&bridge_line->addr,
+ bridge_line->port,
+ bridge_line->digest,
+ bridge_line->transport_name);
+
+ b = tor_malloc_zero(sizeof(bridge_info_t));
+ tor_addr_copy(&b->addr, &bridge_line->addr);
+ b->port = bridge_line->port;
+ memcpy(b->identity, bridge_line->digest, DIGEST_LEN);
+ if (bridge_line->transport_name)
+ b->transport_name = bridge_line->transport_name;
+ b->fetch_status.schedule = DL_SCHED_BRIDGE;
+ b->fetch_status.backoff = DL_SCHED_RANDOM_EXPONENTIAL;
+ b->socks_args = bridge_line->socks_args;
+ if (!bridge_list)
+ bridge_list = smartlist_new();
+
+ tor_free(bridge_line); /* Deallocate bridge_line now. */
+
+ smartlist_add(bridge_list, b);
+}
+
+/** Return true iff <b>routerset</b> contains the bridge <b>bridge</b>. */
+static int
+routerset_contains_bridge(const routerset_t *routerset,
+ const bridge_info_t *bridge)
+{
+ int result;
+ extend_info_t *extinfo;
+ tor_assert(bridge);
+ if (!routerset)
+ return 0;
+
+ extinfo = extend_info_new(
+ NULL, bridge->identity, NULL, NULL, &bridge->addr, bridge->port);
+ result = routerset_contains_extendinfo(routerset, extinfo);
+ extend_info_free(extinfo);
+ return result;
+}
+
+/** If <b>digest</b> is one of our known bridges, return it. */
+static bridge_info_t *
+find_bridge_by_digest(const char *digest)
+{
+ SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge,
+ {
+ if (tor_memeq(bridge->identity, digest, DIGEST_LEN))
+ return bridge;
+ });
+ return NULL;
+}
+
+/** Given the <b>addr</b> and <b>port</b> of a bridge, if that bridge
+ * supports a pluggable transport, return its name. Otherwise, return
+ * NULL. */
+const char *
+find_transport_name_by_bridge_addrport(const tor_addr_t *addr, uint16_t port)
+{
+ if (!bridge_list)
+ return NULL;
+
+ SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) {
+ if (tor_addr_eq(&bridge->addr, addr) &&
+ (bridge->port == port))
+ return bridge->transport_name;
+ } SMARTLIST_FOREACH_END(bridge);
+
+ return NULL;
+}
+
+/** If <b>addr</b> and <b>port</b> match the address and port of a
+ * bridge of ours that uses pluggable transports, place its transport
+ * in <b>transport</b>.
+ *
+ * Return 0 on success (found a transport, or found a bridge with no
+ * transport, or found no bridge); return -1 if we should be using a
+ * transport, but the transport could not be found.
+ */
+int
+get_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
+ const transport_t **transport)
+{
+ *transport = NULL;
+ if (!bridge_list)
+ return 0;
+
+ SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) {
+ if (tor_addr_eq(&bridge->addr, addr) &&
+ (bridge->port == port)) { /* bridge matched */
+ if (bridge->transport_name) { /* it also uses pluggable transports */
+ *transport = transport_get_by_name(bridge->transport_name);
+ if (*transport == NULL) { /* it uses pluggable transports, but
+ the transport could not be found! */
+ return -1;
+ }
+ return 0;
+ } else { /* bridge matched, but it doesn't use transports. */
+ break;
+ }
+ }
+ } SMARTLIST_FOREACH_END(bridge);
+
+ *transport = NULL;
+ return 0;
+}
+
+/** Return a smartlist containing all the SOCKS arguments that we
+ * should pass to the SOCKS proxy. */
+const smartlist_t *
+get_socks_args_by_bridge_addrport(const tor_addr_t *addr, uint16_t port)
+{
+ bridge_info_t *bridge = get_configured_bridge_by_addr_port_digest(addr,
+ port,
+ NULL);
+ return bridge ? bridge->socks_args : NULL;
+}
+
+/** We need to ask <b>bridge</b> for its server descriptor. */
+static void
+launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge)
+{
+ const or_options_t *options = get_options();
+
+ if (connection_get_by_type_addr_port_purpose(
+ CONN_TYPE_DIR, &bridge->addr, bridge->port,
+ DIR_PURPOSE_FETCH_SERVERDESC))
+ return; /* it's already on the way */
+
+ if (routerset_contains_bridge(options->ExcludeNodes, bridge)) {
+ download_status_mark_impossible(&bridge->fetch_status);
+ log_warn(LD_APP, "Not using bridge at %s: it is in ExcludeNodes.",
+ safe_str_client(fmt_and_decorate_addr(&bridge->addr)));
+ return;
+ }
+
+ /* Until we get a descriptor for the bridge, we only know one address for
+ * it. */
+ if (!fascist_firewall_allows_address_addr(&bridge->addr, bridge->port,
+ FIREWALL_OR_CONNECTION, 0, 0)) {
+ log_notice(LD_CONFIG, "Tried to fetch a descriptor directly from a "
+ "bridge, but that bridge is not reachable through our "
+ "firewall.");
+ return;
+ }
+
+ directory_initiate_command(&bridge->addr, bridge->port,
+ NULL, 0, /*no dirport*/
+ bridge->identity,
+ DIR_PURPOSE_FETCH_SERVERDESC,
+ ROUTER_PURPOSE_BRIDGE,
+ DIRIND_ONEHOP, "authority.z", NULL, 0, 0);
+}
+
+/** Fetching the bridge descriptor from the bridge authority returned a
+ * "not found". Fall back to trying a direct fetch. */
+void
+retry_bridge_descriptor_fetch_directly(const char *digest)
+{
+ bridge_info_t *bridge = find_bridge_by_digest(digest);
+ if (!bridge)
+ return; /* not found? oh well. */
+
+ launch_direct_bridge_descriptor_fetch(bridge);
+}
+
+/** For each bridge in our list for which we don't currently have a
+ * descriptor, fetch a new copy of its descriptor -- either directly
+ * from the bridge or via a bridge authority. */
+void
+fetch_bridge_descriptors(const or_options_t *options, time_t now)
+{
+ int num_bridge_auths = get_n_authorities(BRIDGE_DIRINFO);
+ int ask_bridge_directly;
+ int can_use_bridge_authority;
+
+ if (!bridge_list)
+ return;
+
+ /* If we still have unconfigured managed proxies, don't go and
+ connect to a bridge. */
+ if (pt_proxies_configuration_pending())
+ return;
+
+ SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge)
+ {
+ if (!download_status_is_ready(&bridge->fetch_status, now,
+ IMPOSSIBLE_TO_DOWNLOAD))
+ continue; /* don't bother, no need to retry yet */
+ if (routerset_contains_bridge(options->ExcludeNodes, bridge)) {
+ download_status_mark_impossible(&bridge->fetch_status);
+ log_warn(LD_APP, "Not using bridge at %s: it is in ExcludeNodes.",
+ safe_str_client(fmt_and_decorate_addr(&bridge->addr)));
+ continue;
+ }
+
+ /* schedule another fetch as if this one will fail, in case it does */
+ download_status_failed(&bridge->fetch_status, 0);
+
+ can_use_bridge_authority = !tor_digest_is_zero(bridge->identity) &&
+ num_bridge_auths;
+ ask_bridge_directly = !can_use_bridge_authority ||
+ !options->UpdateBridgesFromAuthority;
+ log_debug(LD_DIR, "ask_bridge_directly=%d (%d, %d, %d)",
+ ask_bridge_directly, tor_digest_is_zero(bridge->identity),
+ !options->UpdateBridgesFromAuthority, !num_bridge_auths);
+
+ if (ask_bridge_directly &&
+ !fascist_firewall_allows_address_addr(&bridge->addr, bridge->port,
+ FIREWALL_OR_CONNECTION, 0,
+ 0)) {
+ log_notice(LD_DIR, "Bridge at '%s' isn't reachable by our "
+ "firewall policy. %s.",
+ fmt_addrport(&bridge->addr, bridge->port),
+ can_use_bridge_authority ?
+ "Asking bridge authority instead" : "Skipping");
+ if (can_use_bridge_authority)
+ ask_bridge_directly = 0;
+ else
+ continue;
+ }
+
+ if (ask_bridge_directly) {
+ /* we need to ask the bridge itself for its descriptor. */
+ launch_direct_bridge_descriptor_fetch(bridge);
+ } else {
+ /* We have a digest and we want to ask an authority. We could
+ * combine all the requests into one, but that may give more
+ * hints to the bridge authority than we want to give. */
+ char resource[10 + HEX_DIGEST_LEN];
+ memcpy(resource, "fp/", 3);
+ base16_encode(resource+3, HEX_DIGEST_LEN+1,
+ bridge->identity, DIGEST_LEN);
+ memcpy(resource+3+HEX_DIGEST_LEN, ".z", 3);
+ log_info(LD_DIR, "Fetching bridge info '%s' from bridge authority.",
+ resource);
+ directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC,
+ ROUTER_PURPOSE_BRIDGE, resource, 0, DL_WANT_AUTHORITY);
+ }
+ }
+ SMARTLIST_FOREACH_END(bridge);
+}
+
+/** If our <b>bridge</b> is configured to be a different address than
+ * the bridge gives in <b>node</b>, rewrite the routerinfo
+ * we received to use the address we meant to use. Now we handle
+ * multihomed bridges better.
+ */
+static void
+rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
+{
+ /* XXXX move this function. */
+ /* XXXX overridden addresses should really live in the node_t, so that the
+ * routerinfo_t and the microdesc_t can be immutable. But we can only
+ * do that safely if we know that no function that connects to an OR
+ * does so through an address from any source other than node_get_addr().
+ */
+ tor_addr_t addr;
+ const or_options_t *options = get_options();
+
+ if (node->ri) {
+ routerinfo_t *ri = node->ri;
+ tor_addr_from_ipv4h(&addr, ri->addr);
+
+ if ((!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
+ bridge->port == ri->or_port) ||
+ (!tor_addr_compare(&bridge->addr, &ri->ipv6_addr, CMP_EXACT) &&
+ bridge->port == ri->ipv6_orport)) {
+ /* they match, so no need to do anything */
+ } else {
+ if (tor_addr_family(&bridge->addr) == AF_INET) {
+ ri->addr = tor_addr_to_ipv4h(&bridge->addr);
+ ri->or_port = bridge->port;
+ log_info(LD_DIR,
+ "Adjusted bridge routerinfo for '%s' to match configured "
+ "address %s:%d.",
+ ri->nickname, fmt_addr32(ri->addr), ri->or_port);
+ } else if (tor_addr_family(&bridge->addr) == AF_INET6) {
+ tor_addr_copy(&ri->ipv6_addr, &bridge->addr);
+ ri->ipv6_orport = bridge->port;
+ log_info(LD_DIR,
+ "Adjusted bridge routerinfo for '%s' to match configured "
+ "address %s.",
+ ri->nickname, fmt_addrport(&ri->ipv6_addr, ri->ipv6_orport));
+ } else {
+ log_err(LD_BUG, "Address family not supported: %d.",
+ tor_addr_family(&bridge->addr));
+ return;
+ }
+ }
+
+ if (options->ClientPreferIPv6ORPort == -1) {
+ /* Mark which address to use based on which bridge_t we got. */
+ node->ipv6_preferred = (tor_addr_family(&bridge->addr) == AF_INET6 &&
+ !tor_addr_is_null(&node->ri->ipv6_addr));
+ } else {
+ /* Mark which address to use based on user preference */
+ node->ipv6_preferred = (fascist_firewall_prefer_ipv6_orport(options) &&
+ !tor_addr_is_null(&node->ri->ipv6_addr));
+ }
+
+ /* XXXipv6 we lack support for falling back to another address for
+ the same relay, warn the user */
+ if (!tor_addr_is_null(&ri->ipv6_addr)) {
+ tor_addr_port_t ap;
+ node_get_pref_orport(node, &ap);
+ log_notice(LD_CONFIG,
+ "Bridge '%s' has both an IPv4 and an IPv6 address. "
+ "Will prefer using its %s address (%s) based on %s.",
+ ri->nickname,
+ node->ipv6_preferred ? "IPv6" : "IPv4",
+ fmt_addrport(&ap.addr, ap.port),
+ options->ClientPreferIPv6ORPort == -1 ?
+ "the configured Bridge address" :
+ "ClientPreferIPv6ORPort");
+ }
+ }
+ if (node->rs) {
+ routerstatus_t *rs = node->rs;
+ tor_addr_from_ipv4h(&addr, rs->addr);
+
+ if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
+ bridge->port == rs->or_port) {
+ /* they match, so no need to do anything */
+ } else {
+ rs->addr = tor_addr_to_ipv4h(&bridge->addr);
+ rs->or_port = bridge->port;
+ log_info(LD_DIR,
+ "Adjusted bridge routerstatus for '%s' to match "
+ "configured address %s.",
+ rs->nickname, fmt_addrport(&bridge->addr, rs->or_port));
+ }
+ }
+}
+
+/** We just learned a descriptor for a bridge. See if that
+ * digest is in our entry guard list, and add it if not. */
+void
+learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
+{
+ tor_assert(ri);
+ tor_assert(ri->purpose == ROUTER_PURPOSE_BRIDGE);
+ if (get_options()->UseBridges) {
+ int first = num_bridges_usable() <= 1;
+ bridge_info_t *bridge = get_configured_bridge_by_routerinfo(ri);
+ time_t now = time(NULL);
+ router_set_status(ri->cache_info.identity_digest, 1);
+
+ if (bridge) { /* if we actually want to use this one */
+ node_t *node;
+ /* it's here; schedule its re-fetch for a long time from now. */
+ if (!from_cache)
+ download_status_reset(&bridge->fetch_status);
+
+ node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ tor_assert(node);
+ rewrite_node_address_for_bridge(bridge, node);
+ if (tor_digest_is_zero(bridge->identity)) {
+ memcpy(bridge->identity,ri->cache_info.identity_digest, DIGEST_LEN);
+ log_notice(LD_DIR, "Learned identity %s for bridge at %s:%d",
+ hex_str(bridge->identity, DIGEST_LEN),
+ fmt_and_decorate_addr(&bridge->addr),
+ (int) bridge->port);
+ }
+ add_an_entry_guard(get_guard_selection_info(), node, 1, 1, 0, 0);
+
+ log_notice(LD_DIR, "new bridge descriptor '%s' (%s): %s", ri->nickname,
+ from_cache ? "cached" : "fresh", router_describe(ri));
+ /* set entry->made_contact so if it goes down we don't drop it from
+ * our entry node list */
+ entry_guard_register_connect_status(ri->cache_info.identity_digest,
+ 1, 0, now);
+ if (first) {
+ routerlist_retry_directory_downloads(now);
+ }
+ }
+ }
+}
+
+/** Return the number of bridges that have descriptors that
+ * are marked with purpose 'bridge' and are running.
+ *
+ * We use this function to decide if we're ready to start building
+ * circuits through our bridges, or if we need to wait until the
+ * directory "server/authority" requests finish. */
+int
+any_bridge_descriptors_known(void)
+{
+ tor_assert(get_options()->UseBridges);
+ 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))
+{
+ smartlist_t *result = NULL;
+ char *digest_tmp;
+
+ if (get_options()->UseBridges && bridge_list) {
+ result = smartlist_new();
+
+ SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) {
+ digest_tmp = tor_malloc(DIGEST_LEN);
+ memcpy(digest_tmp, b->identity, DIGEST_LEN);
+ smartlist_add(result, digest_tmp);
+ } SMARTLIST_FOREACH_END(b);
+ }
+
+ return result;
+}
+
+/** Get the download status for a bridge descriptor given its identity */
+MOCK_IMPL(download_status_t *,
+get_bridge_dl_status_by_id, (const char *digest))
+{
+ download_status_t *dl = NULL;
+
+ if (digest && get_options()->UseBridges && bridge_list) {
+ SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) {
+ if (tor_memeq(digest, b->identity, DIGEST_LEN)) {
+ dl = &(b->fetch_status);
+ break;
+ }
+ } SMARTLIST_FOREACH_END(b);
+ }
+
+ return dl;
+}
+
+/** Release all storage held in bridges.c */
+void
+bridges_free_all(void)
+{
+ clear_bridge_list();
+ smartlist_free(bridge_list);
+ bridge_list = NULL;
+}
+
diff --git a/src/or/bridges.h b/src/or/bridges.h
new file mode 100644
index 0000000..738b1a6
--- /dev/null
+++ b/src/or/bridges.h
@@ -0,0 +1,54 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2016, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file bridges.h
+ * \brief Header file for circuitbuild.c.
+ **/
+
+#ifndef TOR_BRIDGES_H
+#define TOR_BRIDGES_H
+
+struct bridge_line_t;
+
+void mark_bridge_list(void);
+void sweep_bridge_list(void);
+
+int addr_is_a_configured_bridge(const tor_addr_t *addr, uint16_t port,
+ const char *digest);
+int extend_info_is_a_configured_bridge(const extend_info_t *ei);
+int routerinfo_is_a_configured_bridge(const routerinfo_t *ri);
+int node_is_a_configured_bridge(const node_t *node);
+void learned_router_identity(const tor_addr_t *addr, uint16_t port,
+ const char *digest);
+
+void bridge_add_from_config(struct bridge_line_t *bridge_line);
+void retry_bridge_descriptor_fetch_directly(const char *digest);
+void fetch_bridge_descriptors(const or_options_t *options, time_t now);
+void learned_bridge_descriptor(routerinfo_t *ri, int from_cache);
+int any_bridge_descriptors_known(void);
+const smartlist_t *get_socks_args_by_bridge_addrport(const tor_addr_t *addr,
+ uint16_t port);
+
+int any_bridges_dont_support_microdescriptors(void);
+
+const char *find_transport_name_by_bridge_addrport(const tor_addr_t *addr,
+ uint16_t port);
+struct transport_t;
+int get_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
+ const struct transport_t **transport);
+
+MOCK_DECL(int, transport_is_needed, (const char *transport_name));
+int validate_pluggable_transports_config(void);
+
+MOCK_DECL(smartlist_t *, list_bridge_identities, (void));
+MOCK_DECL(download_status_t *, get_bridge_dl_status_by_id,
+ (const char *digest));
+
+void bridges_free_all(void);
+
+#endif
+
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 2998f5c..b482e78 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -28,6 +28,7 @@
#define CIRCUITBUILD_PRIVATE
#include "or.h"
+#include "bridges.h"
#include "channel.h"
#include "circpathbias.h"
#define CIRCUITBUILD_PRIVATE
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index ba7b75f..2f972d1 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -29,6 +29,7 @@
#include "or.h"
#include "addressmap.h"
+#include "bridges.h"
#include "channel.h"
#include "circpathbias.h"
#include "circuitbuild.h"
diff --git a/src/or/config.c b/src/or/config.c
index 9553822..79a5847 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -60,6 +60,7 @@
#define CONFIG_PRIVATE
#include "or.h"
+#include "bridges.h"
#include "compat.h"
#include "addressmap.h"
#include "channel.h"
diff --git a/src/or/connection.c b/src/or/connection.c
index 2e3df34..2964c30 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -56,6 +56,7 @@
#define CONNECTION_PRIVATE
#include "or.h"
+#include "bridges.h"
#include "buffers.h"
/*
* Define this so we get channel internal functions, since we're implementing
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index eb67f06..ecc5a45 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -21,6 +21,7 @@
* This module also implements the client side of the v3 Tor link handshake,
**/
#include "or.h"
+#include "bridges.h"
#include "buffers.h"
/*
* Define this so we get channel internal functions, since we're implementing
diff --git a/src/or/control.c b/src/or/control.c
index f0cb435..1d7ec1b 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -36,6 +36,7 @@
#include "or.h"
#include "addressmap.h"
+#include "bridges.h"
#include "buffers.h"
#include "channel.h"
#include "channeltls.h"
diff --git a/src/or/directory.c b/src/or/directory.c
index 65ddd7d..efa5a31 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -7,6 +7,7 @@
#include "or.h"
#include "backtrace.h"
+#include "bridges.h"
#include "buffers.h"
#include "circuitbuild.h"
#include "config.h"
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 9af7140..886e653 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -15,6 +15,7 @@
#define ENTRYNODES_PRIVATE
#include "or.h"
+#include "bridges.h"
#include "circpathbias.h"
#include "circuitbuild.h"
#include "circuitstats.h"
@@ -37,32 +38,6 @@
#include "transports.h"
#include "statefile.h"
-/** Information about a configured bridge. Currently this just matches the
- * ones in the torrc file, but one day we may be able to learn about new
- * bridges on our own, and remember them in the state file. */
-typedef struct {
- /** Address of the bridge. */
- tor_addr_t addr;
- /** TLS port for the bridge. */
- uint16_t port;
- /** Boolean: We are re-parsing our bridge list, and we are going to remove
- * this one if we don't find it in the list of configured bridges. */
- unsigned marked_for_removal : 1;
- /** Expected identity digest, or all zero bytes if we don't know what the
- * digest should be. */
- char identity[DIGEST_LEN];
-
- /** Name of pluggable transport protocol taken from its config line. */
- char *transport_name;
-
- /** When should we next try to fetch a descriptor for this bridge? */
- download_status_t fetch_status;
-
- /** A smartlist of k=v values to be passed to the SOCKS proxy, if
- transports are used for this bridge. */
- smartlist_t *socks_args;
-} bridge_info_t;
-
/** All the context for guard selection on a particular client */
struct guard_selection_s {
@@ -99,14 +74,12 @@ struct guard_selection_s {
static smartlist_t *guard_contexts = NULL;
static guard_selection_t *curr_guard_context = NULL;
-static void bridge_free(bridge_info_t *bridge);
static const node_t *choose_random_entry_impl(guard_selection_t *gs,
cpath_build_state_t *state,
int for_directory,
dirinfo_type_t dirtype,
int *n_options_out);
static guard_selection_t * guard_selection_new(void);
-static int num_bridges_usable(void);
/* Default number of entry guards in the case where the NumEntryGuards
* consensus parameter is not set */
@@ -2282,330 +2255,6 @@ guard_get_guardfraction_bandwidth(guardfraction_bandwidth_t *guardfraction_bw,
guardfraction_bw->non_guard_bw = orig_bandwidth - (int) guard_bw;
}
-/** A list of configured bridges. Whenever we actually get a descriptor
- * for one, we add it as an entry guard. Note that the order of bridges
- * in this list does not necessarily correspond to the order of bridges
- * in the torrc. */
-static smartlist_t *bridge_list = NULL;
-
-/** Mark every entry of the bridge list to be removed on our next call to
- * sweep_bridge_list unless it has first been un-marked. */
-void
-mark_bridge_list(void)
-{
- if (!bridge_list)
- bridge_list = smartlist_new();
- SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b,
- b->marked_for_removal = 1);
-}
-
-/** Remove every entry of the bridge list that was marked with
- * mark_bridge_list if it has not subsequently been un-marked. */
-void
-sweep_bridge_list(void)
-{
- if (!bridge_list)
- bridge_list = smartlist_new();
- SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) {
- if (b->marked_for_removal) {
- SMARTLIST_DEL_CURRENT(bridge_list, b);
- bridge_free(b);
- }
- } SMARTLIST_FOREACH_END(b);
-}
-
-/** Initialize the bridge list to empty, creating it if needed. */
-static void
-clear_bridge_list(void)
-{
- if (!bridge_list)
- bridge_list = smartlist_new();
- SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b, bridge_free(b));
- smartlist_clear(bridge_list);
-}
-
-/** Free the bridge <b>bridge</b>. */
-static void
-bridge_free(bridge_info_t *bridge)
-{
- if (!bridge)
- return;
-
- tor_free(bridge->transport_name);
- if (bridge->socks_args) {
- SMARTLIST_FOREACH(bridge->socks_args, char*, s, tor_free(s));
- smartlist_free(bridge->socks_args);
- }
-
- tor_free(bridge);
-}
-
-/** If we have a bridge configured whose digest matches <b>digest</b>, or a
- * bridge with no known digest whose address matches any of the
- * tor_addr_port_t's in <b>orports</b>, return that bridge. Else return
- * NULL. */
-static bridge_info_t *
-get_configured_bridge_by_orports_digest(const char *digest,
- const smartlist_t *orports)
-{
- if (!bridge_list)
- return NULL;
- SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge)
- {
- if (tor_digest_is_zero(bridge->identity)) {
- SMARTLIST_FOREACH_BEGIN(orports, tor_addr_port_t *, ap)
- {
- if (tor_addr_compare(&bridge->addr, &ap->addr, CMP_EXACT) == 0 &&
- bridge->port == ap->port)
- return bridge;
- }
- SMARTLIST_FOREACH_END(ap);
- }
- if (digest && tor_memeq(bridge->identity, digest, DIGEST_LEN))
- return bridge;
- }
- SMARTLIST_FOREACH_END(bridge);
- return NULL;
-}
-
-/** If we have a bridge configured whose digest matches <b>digest</b>, or a
- * bridge with no known digest whose address matches <b>addr</b>:<b>port</b>,
- * return that bridge. Else return NULL. If <b>digest</b> is NULL, check for
- * address/port matches only. */
-static bridge_info_t *
-get_configured_bridge_by_addr_port_digest(const tor_addr_t *addr,
- uint16_t port,
- const char *digest)
-{
- if (!bridge_list)
- return NULL;
- SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge)
- {
- if ((tor_digest_is_zero(bridge->identity) || digest == NULL) &&
- !tor_addr_compare(&bridge->addr, addr, CMP_EXACT) &&
- bridge->port == port)
- return bridge;
- if (digest && tor_memeq(bridge->identity, digest, DIGEST_LEN))
- return bridge;
- }
- SMARTLIST_FOREACH_END(bridge);
- return NULL;
-}
-
-/** If we have a bridge configured whose digest matches <b>digest</b>, or a
- * bridge with no known digest whose address matches <b>addr</b>:<b>port</b>,
- * return 1. Else return 0. If <b>digest</b> is NULL, check for
- * address/port matches only. */
-int
-addr_is_a_configured_bridge(const tor_addr_t *addr,
- uint16_t port,
- const char *digest)
-{
- tor_assert(addr);
- return get_configured_bridge_by_addr_port_digest(addr, port, digest) ? 1 : 0;
-}
-
-/** If we have a bridge configured whose digest matches
- * <b>ei->identity_digest</b>, or a bridge with no known digest whose address
- * matches <b>ei->addr</b>:<b>ei->port</b>, return 1. Else return 0.
- * If <b>ei->onion_key</b> is NULL, check for address/port matches only. */
-int
-extend_info_is_a_configured_bridge(const extend_info_t *ei)
-{
- const char *digest = ei->onion_key ? ei->identity_digest : NULL;
- return addr_is_a_configured_bridge(&ei->addr, ei->port, digest);
-}
-
-/** Wrapper around get_configured_bridge_by_addr_port_digest() to look
- * it up via router descriptor <b>ri</b>. */
-static bridge_info_t *
-get_configured_bridge_by_routerinfo(const routerinfo_t *ri)
-{
- bridge_info_t *bi = NULL;
- smartlist_t *orports = router_get_all_orports(ri);
- bi = get_configured_bridge_by_orports_digest(ri->cache_info.identity_digest,
- orports);
- SMARTLIST_FOREACH(orports, tor_addr_port_t *, p, tor_free(p));
- smartlist_free(orports);
- return bi;
-}
-
-/** Return 1 if <b>ri</b> is one of our known bridges, else 0. */
-int
-routerinfo_is_a_configured_bridge(const routerinfo_t *ri)
-{
- return get_configured_bridge_by_routerinfo(ri) ? 1 : 0;
-}
-
-/** Return 1 if <b>node</b> is one of our configured bridges, else 0. */
-int
-node_is_a_configured_bridge(const node_t *node)
-{
- int retval = 0;
- smartlist_t *orports = node_get_all_orports(node);
- retval = get_configured_bridge_by_orports_digest(node->identity,
- orports) != NULL;
- SMARTLIST_FOREACH(orports, tor_addr_port_t *, p, tor_free(p));
- smartlist_free(orports);
- return retval;
-}
-
-/** We made a connection to a router at <b>addr</b>:<b>port</b>
- * without knowing its digest. Its digest turned out to be <b>digest</b>.
- * If it was a bridge, and we still don't know its digest, record it.
- */
-void
-learned_router_identity(const tor_addr_t *addr, uint16_t port,
- const char *digest)
-{
- bridge_info_t *bridge =
- get_configured_bridge_by_addr_port_digest(addr, port, digest);
- if (bridge && tor_digest_is_zero(bridge->identity)) {
- char *transport_info = NULL;
- const char *transport_name =
- find_transport_name_by_bridge_addrport(addr, port);
- if (transport_name)
- tor_asprintf(&transport_info, " (with transport '%s')", transport_name);
-
- memcpy(bridge->identity, digest, DIGEST_LEN);
- log_notice(LD_DIR, "Learned fingerprint %s for bridge %s%s.",
- hex_str(digest, DIGEST_LEN), fmt_addrport(addr, port),
- transport_info ? transport_info : "");
- tor_free(transport_info);
- }
-}
-
-/** Return true if <b>bridge</b> has the same identity digest as
- * <b>digest</b>. If <b>digest</b> is NULL, it matches
- * bridges with unspecified identity digests. */
-static int
-bridge_has_digest(const bridge_info_t *bridge, const char *digest)
-{
- if (digest)
- return tor_memeq(digest, bridge->identity, DIGEST_LEN);
- else
- return tor_digest_is_zero(bridge->identity);
-}
-
-/** We are about to add a new bridge at <b>addr</b>:<b>port</b>, with optional
- * <b>digest</b> and <b>transport_name</b>. Mark for removal any previously
- * existing bridge with the same address and port, and warn the user as
- * appropriate.
- */
-static void
-bridge_resolve_conflicts(const tor_addr_t *addr, uint16_t port,
- const char *digest, const char *transport_name)
-{
- /* Iterate the already-registered bridge list:
-
- If you find a bridge with the same adress and port, mark it for
- removal. It doesn't make sense to have two active bridges with
- the same IP:PORT. If the bridge in question has a different
- digest or transport than <b>digest</b>/<b>transport_name</b>,
- it's probably a misconfiguration and we should warn the user.
- */
- SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge) {
- if (bridge->marked_for_removal)
- continue;
-
- if (tor_addr_eq(&bridge->addr, addr) && (bridge->port == port)) {
-
- bridge->marked_for_removal = 1;
-
- if (!bridge_has_digest(bridge, digest) ||
- strcmp_opt(bridge->transport_name, transport_name)) {
- /* warn the user */
- char *bridge_description_new, *bridge_description_old;
- tor_asprintf(&bridge_description_new, "%s:%s:%s",
- fmt_addrport(addr, port),
- digest ? hex_str(digest, DIGEST_LEN) : "",
- transport_name ? transport_name : "");
- tor_asprintf(&bridge_description_old, "%s:%s:%s",
- fmt_addrport(&bridge->addr, bridge->port),
- tor_digest_is_zero(bridge->identity) ?
- "" : hex_str(bridge->identity,DIGEST_LEN),
- bridge->transport_name ? bridge->transport_name : "");
-
- log_warn(LD_GENERAL,"Tried to add bridge '%s', but we found a conflict"
- " with the already registered bridge '%s'. We will discard"
- " the old bridge and keep '%s'. If this is not what you"
- " wanted, please change your configuration file accordingly.",
- bridge_description_new, bridge_description_old,
- bridge_description_new);
-
- tor_free(bridge_description_new);
- tor_free(bridge_description_old);
- }
- }
- } SMARTLIST_FOREACH_END(bridge);
-}
-
-/** Return True if we have a bridge that uses a transport with name
- * <b>transport_name</b>. */
-MOCK_IMPL(int,
-transport_is_needed, (const char *transport_name))
-{
- if (!bridge_list)
- return 0;
-
- SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) {
- if (bridge->transport_name &&
- !strcmp(bridge->transport_name, transport_name))
- return 1;
- } SMARTLIST_FOREACH_END(bridge);
-
- return 0;
-}
-
-/** Register the bridge information in <b>bridge_line</b> to the
- * bridge subsystem. Steals reference of <b>bridge_line</b>. */
-void
-bridge_add_from_config(bridge_line_t *bridge_line)
-{
- bridge_info_t *b;
-
- { /* Log the bridge we are about to register: */
- log_debug(LD_GENERAL, "Registering bridge at %s (transport: %s) (%s)",
- fmt_addrport(&bridge_line->addr, bridge_line->port),
- bridge_line->transport_name ?
- bridge_line->transport_name : "no transport",
- tor_digest_is_zero(bridge_line->digest) ?
- "no key listed" : hex_str(bridge_line->digest, DIGEST_LEN));
-
- if (bridge_line->socks_args) { /* print socks arguments */
- int i = 0;
-
- tor_assert(smartlist_len(bridge_line->socks_args) > 0);
-
- log_debug(LD_GENERAL, "Bridge uses %d SOCKS arguments:",
- smartlist_len(bridge_line->socks_args));
- SMARTLIST_FOREACH(bridge_line->socks_args, const char *, arg,
- log_debug(LD_CONFIG, "%d: %s", ++i, arg));
- }
- }
-
- bridge_resolve_conflicts(&bridge_line->addr,
- bridge_line->port,
- bridge_line->digest,
- bridge_line->transport_name);
-
- b = tor_malloc_zero(sizeof(bridge_info_t));
- tor_addr_copy(&b->addr, &bridge_line->addr);
- b->port = bridge_line->port;
- memcpy(b->identity, bridge_line->digest, DIGEST_LEN);
- if (bridge_line->transport_name)
- b->transport_name = bridge_line->transport_name;
- b->fetch_status.schedule = DL_SCHED_BRIDGE;
- b->fetch_status.backoff = DL_SCHED_RANDOM_EXPONENTIAL;
- b->socks_args = bridge_line->socks_args;
- if (!bridge_list)
- bridge_list = smartlist_new();
-
- tor_free(bridge_line); /* Deallocate bridge_line now. */
-
- smartlist_add(bridge_list, b);
-}
-
/** Returns true iff the node is used as a guard in the specified guard
* context */
int
@@ -2642,426 +2291,6 @@ is_node_used_as_guard, (const node_t *node))
get_guard_selection_info(), node);
}
-/** Return true iff <b>routerset</b> contains the bridge <b>bridge</b>. */
-static int
-routerset_contains_bridge(const routerset_t *routerset,
- const bridge_info_t *bridge)
-{
- int result;
- extend_info_t *extinfo;
- tor_assert(bridge);
- if (!routerset)
- return 0;
-
- extinfo = extend_info_new(
- NULL, bridge->identity, NULL, NULL, &bridge->addr, bridge->port);
- result = routerset_contains_extendinfo(routerset, extinfo);
- extend_info_free(extinfo);
- return result;
-}
-
-/** If <b>digest</b> is one of our known bridges, return it. */
-static bridge_info_t *
-find_bridge_by_digest(const char *digest)
-{
- SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge,
- {
- if (tor_memeq(bridge->identity, digest, DIGEST_LEN))
- return bridge;
- });
- return NULL;
-}
-
-/** Given the <b>addr</b> and <b>port</b> of a bridge, if that bridge
- * supports a pluggable transport, return its name. Otherwise, return
- * NULL. */
-const char *
-find_transport_name_by_bridge_addrport(const tor_addr_t *addr, uint16_t port)
-{
- if (!bridge_list)
- return NULL;
-
- SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) {
- if (tor_addr_eq(&bridge->addr, addr) &&
- (bridge->port == port))
- return bridge->transport_name;
- } SMARTLIST_FOREACH_END(bridge);
-
- return NULL;
-}
-
-/** If <b>addr</b> and <b>port</b> match the address and port of a
- * bridge of ours that uses pluggable transports, place its transport
- * in <b>transport</b>.
- *
- * Return 0 on success (found a transport, or found a bridge with no
- * transport, or found no bridge); return -1 if we should be using a
- * transport, but the transport could not be found.
- */
-int
-get_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
- const transport_t **transport)
-{
- *transport = NULL;
- if (!bridge_list)
- return 0;
-
- SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) {
- if (tor_addr_eq(&bridge->addr, addr) &&
- (bridge->port == port)) { /* bridge matched */
- if (bridge->transport_name) { /* it also uses pluggable transports */
- *transport = transport_get_by_name(bridge->transport_name);
- if (*transport == NULL) { /* it uses pluggable transports, but
- the transport could not be found! */
- return -1;
- }
- return 0;
- } else { /* bridge matched, but it doesn't use transports. */
- break;
- }
- }
- } SMARTLIST_FOREACH_END(bridge);
-
- *transport = NULL;
- return 0;
-}
-
-/** Return a smartlist containing all the SOCKS arguments that we
- * should pass to the SOCKS proxy. */
-const smartlist_t *
-get_socks_args_by_bridge_addrport(const tor_addr_t *addr, uint16_t port)
-{
- bridge_info_t *bridge = get_configured_bridge_by_addr_port_digest(addr,
- port,
- NULL);
- return bridge ? bridge->socks_args : NULL;
-}
-
-/** We need to ask <b>bridge</b> for its server descriptor. */
-static void
-launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge)
-{
- const or_options_t *options = get_options();
-
- if (connection_get_by_type_addr_port_purpose(
- CONN_TYPE_DIR, &bridge->addr, bridge->port,
- DIR_PURPOSE_FETCH_SERVERDESC))
- return; /* it's already on the way */
-
- if (routerset_contains_bridge(options->ExcludeNodes, bridge)) {
- download_status_mark_impossible(&bridge->fetch_status);
- log_warn(LD_APP, "Not using bridge at %s: it is in ExcludeNodes.",
- safe_str_client(fmt_and_decorate_addr(&bridge->addr)));
- return;
- }
-
- /* Until we get a descriptor for the bridge, we only know one address for
- * it. */
- if (!fascist_firewall_allows_address_addr(&bridge->addr, bridge->port,
- FIREWALL_OR_CONNECTION, 0, 0)) {
- log_notice(LD_CONFIG, "Tried to fetch a descriptor directly from a "
- "bridge, but that bridge is not reachable through our "
- "firewall.");
- return;
- }
-
- directory_initiate_command(&bridge->addr, bridge->port,
- NULL, 0, /*no dirport*/
- bridge->identity,
- DIR_PURPOSE_FETCH_SERVERDESC,
- ROUTER_PURPOSE_BRIDGE,
- DIRIND_ONEHOP, "authority.z", NULL, 0, 0);
-}
-
-/** Fetching the bridge descriptor from the bridge authority returned a
- * "not found". Fall back to trying a direct fetch. */
-void
-retry_bridge_descriptor_fetch_directly(const char *digest)
-{
- bridge_info_t *bridge = find_bridge_by_digest(digest);
- if (!bridge)
- return; /* not found? oh well. */
-
- launch_direct_bridge_descriptor_fetch(bridge);
-}
-
-/** For each bridge in our list for which we don't currently have a
- * descriptor, fetch a new copy of its descriptor -- either directly
- * from the bridge or via a bridge authority. */
-void
-fetch_bridge_descriptors(const or_options_t *options, time_t now)
-{
- int num_bridge_auths = get_n_authorities(BRIDGE_DIRINFO);
- int ask_bridge_directly;
- int can_use_bridge_authority;
-
- if (!bridge_list)
- return;
-
- /* If we still have unconfigured managed proxies, don't go and
- connect to a bridge. */
- if (pt_proxies_configuration_pending())
- return;
-
- SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge)
- {
- if (!download_status_is_ready(&bridge->fetch_status, now,
- IMPOSSIBLE_TO_DOWNLOAD))
- continue; /* don't bother, no need to retry yet */
- if (routerset_contains_bridge(options->ExcludeNodes, bridge)) {
- download_status_mark_impossible(&bridge->fetch_status);
- log_warn(LD_APP, "Not using bridge at %s: it is in ExcludeNodes.",
- safe_str_client(fmt_and_decorate_addr(&bridge->addr)));
- continue;
- }
-
- /* schedule another fetch as if this one will fail, in case it does */
- download_status_failed(&bridge->fetch_status, 0);
-
- can_use_bridge_authority = !tor_digest_is_zero(bridge->identity) &&
- num_bridge_auths;
- ask_bridge_directly = !can_use_bridge_authority ||
- !options->UpdateBridgesFromAuthority;
- log_debug(LD_DIR, "ask_bridge_directly=%d (%d, %d, %d)",
- ask_bridge_directly, tor_digest_is_zero(bridge->identity),
- !options->UpdateBridgesFromAuthority, !num_bridge_auths);
-
- if (ask_bridge_directly &&
- !fascist_firewall_allows_address_addr(&bridge->addr, bridge->port,
- FIREWALL_OR_CONNECTION, 0,
- 0)) {
- log_notice(LD_DIR, "Bridge at '%s' isn't reachable by our "
- "firewall policy. %s.",
- fmt_addrport(&bridge->addr, bridge->port),
- can_use_bridge_authority ?
- "Asking bridge authority instead" : "Skipping");
- if (can_use_bridge_authority)
- ask_bridge_directly = 0;
- else
- continue;
- }
-
- if (ask_bridge_directly) {
- /* we need to ask the bridge itself for its descriptor. */
- launch_direct_bridge_descriptor_fetch(bridge);
- } else {
- /* We have a digest and we want to ask an authority. We could
- * combine all the requests into one, but that may give more
- * hints to the bridge authority than we want to give. */
- char resource[10 + HEX_DIGEST_LEN];
- memcpy(resource, "fp/", 3);
- base16_encode(resource+3, HEX_DIGEST_LEN+1,
- bridge->identity, DIGEST_LEN);
- memcpy(resource+3+HEX_DIGEST_LEN, ".z", 3);
- log_info(LD_DIR, "Fetching bridge info '%s' from bridge authority.",
- resource);
- directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC,
- ROUTER_PURPOSE_BRIDGE, resource, 0, DL_WANT_AUTHORITY);
- }
- }
- SMARTLIST_FOREACH_END(bridge);
-}
-
-/** If our <b>bridge</b> is configured to be a different address than
- * the bridge gives in <b>node</b>, rewrite the routerinfo
- * we received to use the address we meant to use. Now we handle
- * multihomed bridges better.
- */
-static void
-rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
-{
- /* XXXX move this function. */
- /* XXXX overridden addresses should really live in the node_t, so that the
- * routerinfo_t and the microdesc_t can be immutable. But we can only
- * do that safely if we know that no function that connects to an OR
- * does so through an address from any source other than node_get_addr().
- */
- tor_addr_t addr;
- const or_options_t *options = get_options();
-
- if (node->ri) {
- routerinfo_t *ri = node->ri;
- tor_addr_from_ipv4h(&addr, ri->addr);
-
- if ((!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
- bridge->port == ri->or_port) ||
- (!tor_addr_compare(&bridge->addr, &ri->ipv6_addr, CMP_EXACT) &&
- bridge->port == ri->ipv6_orport)) {
- /* they match, so no need to do anything */
- } else {
- if (tor_addr_family(&bridge->addr) == AF_INET) {
- ri->addr = tor_addr_to_ipv4h(&bridge->addr);
- ri->or_port = bridge->port;
- log_info(LD_DIR,
- "Adjusted bridge routerinfo for '%s' to match configured "
- "address %s:%d.",
- ri->nickname, fmt_addr32(ri->addr), ri->or_port);
- } else if (tor_addr_family(&bridge->addr) == AF_INET6) {
- tor_addr_copy(&ri->ipv6_addr, &bridge->addr);
- ri->ipv6_orport = bridge->port;
- log_info(LD_DIR,
- "Adjusted bridge routerinfo for '%s' to match configured "
- "address %s.",
- ri->nickname, fmt_addrport(&ri->ipv6_addr, ri->ipv6_orport));
- } else {
- log_err(LD_BUG, "Address family not supported: %d.",
- tor_addr_family(&bridge->addr));
- return;
- }
- }
-
- if (options->ClientPreferIPv6ORPort == -1) {
- /* Mark which address to use based on which bridge_t we got. */
- node->ipv6_preferred = (tor_addr_family(&bridge->addr) == AF_INET6 &&
- !tor_addr_is_null(&node->ri->ipv6_addr));
- } else {
- /* Mark which address to use based on user preference */
- node->ipv6_preferred = (fascist_firewall_prefer_ipv6_orport(options) &&
- !tor_addr_is_null(&node->ri->ipv6_addr));
- }
-
- /* XXXipv6 we lack support for falling back to another address for
- the same relay, warn the user */
- if (!tor_addr_is_null(&ri->ipv6_addr)) {
- tor_addr_port_t ap;
- node_get_pref_orport(node, &ap);
- log_notice(LD_CONFIG,
- "Bridge '%s' has both an IPv4 and an IPv6 address. "
- "Will prefer using its %s address (%s) based on %s.",
- ri->nickname,
- node->ipv6_preferred ? "IPv6" : "IPv4",
- fmt_addrport(&ap.addr, ap.port),
- options->ClientPreferIPv6ORPort == -1 ?
- "the configured Bridge address" :
- "ClientPreferIPv6ORPort");
- }
- }
- if (node->rs) {
- routerstatus_t *rs = node->rs;
- tor_addr_from_ipv4h(&addr, rs->addr);
-
- if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
- bridge->port == rs->or_port) {
- /* they match, so no need to do anything */
- } else {
- rs->addr = tor_addr_to_ipv4h(&bridge->addr);
- rs->or_port = bridge->port;
- log_info(LD_DIR,
- "Adjusted bridge routerstatus for '%s' to match "
- "configured address %s.",
- rs->nickname, fmt_addrport(&bridge->addr, rs->or_port));
- }
- }
-}
-
-/** We just learned a descriptor for a bridge. See if that
- * digest is in our entry guard list, and add it if not. */
-void
-learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
-{
- tor_assert(ri);
- tor_assert(ri->purpose == ROUTER_PURPOSE_BRIDGE);
- if (get_options()->UseBridges) {
- int first = num_bridges_usable() <= 1;
- bridge_info_t *bridge = get_configured_bridge_by_routerinfo(ri);
- time_t now = time(NULL);
- router_set_status(ri->cache_info.identity_digest, 1);
-
- if (bridge) { /* if we actually want to use this one */
- node_t *node;
- /* it's here; schedule its re-fetch for a long time from now. */
- if (!from_cache)
- download_status_reset(&bridge->fetch_status);
-
- node = node_get_mutable_by_id(ri->cache_info.identity_digest);
- tor_assert(node);
- rewrite_node_address_for_bridge(bridge, node);
- if (tor_digest_is_zero(bridge->identity)) {
- memcpy(bridge->identity,ri->cache_info.identity_digest, DIGEST_LEN);
- log_notice(LD_DIR, "Learned identity %s for bridge at %s:%d",
- hex_str(bridge->identity, DIGEST_LEN),
- fmt_and_decorate_addr(&bridge->addr),
- (int) bridge->port);
- }
- add_an_entry_guard(get_guard_selection_info(), node, 1, 1, 0, 0);
-
- log_notice(LD_DIR, "new bridge descriptor '%s' (%s): %s", ri->nickname,
- from_cache ? "cached" : "fresh", router_describe(ri));
- /* set entry->made_contact so if it goes down we don't drop it from
- * our entry node list */
- entry_guard_register_connect_status(ri->cache_info.identity_digest,
- 1, 0, now);
- if (first) {
- routerlist_retry_directory_downloads(now);
- }
- }
- }
-}
-
-/** Return the number of bridges that have descriptors that
- * are marked with purpose 'bridge' and are running.
- *
- * We use this function to decide if we're ready to start building
- * circuits through our bridges, or if we need to wait until the
- * directory "server/authority" requests finish. */
-int
-any_bridge_descriptors_known(void)
-{
- tor_assert(get_options()->UseBridges);
- 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))
-{
- smartlist_t *result = NULL;
- char *digest_tmp;
-
- if (get_options()->UseBridges && bridge_list) {
- result = smartlist_new();
-
- SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) {
- digest_tmp = tor_malloc(DIGEST_LEN);
- memcpy(digest_tmp, b->identity, DIGEST_LEN);
- smartlist_add(result, digest_tmp);
- } SMARTLIST_FOREACH_END(b);
- }
-
- return result;
-}
-
-/** Get the download status for a bridge descriptor given its identity */
-MOCK_IMPL(download_status_t *,
-get_bridge_dl_status_by_id, (const char *digest))
-{
- download_status_t *dl = NULL;
-
- if (digest && get_options()->UseBridges && bridge_list) {
- SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) {
- if (tor_memeq(digest, b->identity, DIGEST_LEN)) {
- dl = &(b->fetch_status);
- break;
- }
- } SMARTLIST_FOREACH_END(b);
- }
-
- return dl;
-}
-
/** Return 1 if we have at least one descriptor for an entry guard
* (bridge or member of EntryNodes) and all descriptors we know are
* down. Else return 0. If <b>act</b> is 1, then mark the down guards
@@ -3163,9 +2392,6 @@ entry_guards_free_all(void)
smartlist_free(guard_contexts);
guard_contexts = NULL;
}
- clear_bridge_list();
- smartlist_free(bridge_list);
- bridge_list = NULL;
circuit_build_times_free_timeouts(get_circuit_build_times_mutable());
}
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 5c0857b..8407945 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -221,41 +221,11 @@ int is_node_used_as_guard_for_guard_selection(guard_selection_t *gs,
const node_t *node);
MOCK_DECL(int, is_node_used_as_guard, (const node_t *node));
-void mark_bridge_list(void);
-void sweep_bridge_list(void);
-
-int addr_is_a_configured_bridge(const tor_addr_t *addr, uint16_t port,
- const char *digest);
-int extend_info_is_a_configured_bridge(const extend_info_t *ei);
-int routerinfo_is_a_configured_bridge(const routerinfo_t *ri);
-int node_is_a_configured_bridge(const node_t *node);
-void learned_router_identity(const tor_addr_t *addr, uint16_t port,
- const char *digest);
-struct bridge_line_t;
-void bridge_add_from_config(struct bridge_line_t *bridge_line);
-void retry_bridge_descriptor_fetch_directly(const char *digest);
-void fetch_bridge_descriptors(const or_options_t *options, time_t now);
-void learned_bridge_descriptor(routerinfo_t *ri, int from_cache);
-int any_bridge_descriptors_known(void);
int entries_known_but_down(const or_options_t *options);
void entries_retry_all(const or_options_t *options);
-const smartlist_t *get_socks_args_by_bridge_addrport(const tor_addr_t *addr,
- uint16_t port);
-
-int any_bridges_dont_support_microdescriptors(void);
-
void entry_guards_free_all(void);
-const char *find_transport_name_by_bridge_addrport(const tor_addr_t *addr,
- uint16_t port);
-struct transport_t;
-int get_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
- const struct transport_t **transport);
-
-MOCK_DECL(int, transport_is_needed, (const char *transport_name));
-int validate_pluggable_transports_config(void);
-
double pathbias_get_close_success_count(entry_guard_t *guard);
double pathbias_get_use_success_count(entry_guard_t *guard);
@@ -275,9 +245,5 @@ guard_get_guardfraction_bandwidth(guardfraction_bandwidth_t *guardfraction_bw,
int orig_bandwidth,
uint32_t guardfraction_percentage);
-MOCK_DECL(smartlist_t *, list_bridge_identities, (void));
-MOCK_DECL(download_status_t *, get_bridge_dl_status_by_id,
- (const char *digest));
-
#endif
diff --git a/src/or/include.am b/src/or/include.am
index 10f8b85..278aa9b 100644
--- a/src/or/include.am
+++ b/src/or/include.am
@@ -19,6 +19,7 @@ EXTRA_DIST+= src/or/ntmain.c src/or/Makefile.nmake
LIBTOR_A_SOURCES = \
src/or/addressmap.c \
+ src/or/bridges.c \
src/or/buffers.c \
src/or/channel.c \
src/or/channeltls.c \
@@ -130,6 +131,7 @@ endif
ORHEADERS = \
src/or/addressmap.h \
+ src/or/bridges.h \
src/or/buffers.h \
src/or/channel.h \
src/or/channeltls.h \
diff --git a/src/or/main.c b/src/or/main.c
index c10f627..a508003 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -50,6 +50,7 @@
#include "or.h"
#include "addressmap.h"
#include "backtrace.h"
+#include "bridges.h"
#include "buffers.h"
#include "channel.h"
#include "channeltls.h"
@@ -3114,6 +3115,7 @@ tor_free_all(int postfork)
control_free_all();
sandbox_free_getaddrinfo_cache();
protover_free_all();
+ bridges_free_all();
if (!postfork) {
config_free_all();
or_state_free_all();
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 316ce48..ec8f77f 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -38,6 +38,7 @@
#define NETWORKSTATUS_PRIVATE
#include "or.h"
+#include "bridges.h"
#include "channel.h"
#include "circuitmux.h"
#include "circuitmux_ewma.h"
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index c99d22e..f51b50e 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -93,6 +93,7 @@
#define ROUTERLIST_PRIVATE
#include "or.h"
#include "backtrace.h"
+#include "bridges.h"
#include "crypto_ed25519.h"
#include "circuitstats.h"
#include "config.h"
diff --git a/src/or/transports.c b/src/or/transports.c
index f755882..feeff6e 100644
--- a/src/or/transports.c
+++ b/src/or/transports.c
@@ -91,13 +91,13 @@
#define PT_PRIVATE
#include "or.h"
+#include "bridges.h"
#include "config.h"
#include "circuitbuild.h"
#include "transports.h"
#include "util.h"
#include "router.h"
#include "statefile.h"
-#include "entrynodes.h"
#include "connection_or.h"
#include "ext_orport.h"
#include "control.h"
diff --git a/src/test/test_config.c b/src/test/test_config.c
index 2fc37b0..cf047f0 100644
--- a/src/test/test_config.c
+++ b/src/test/test_config.c
@@ -11,6 +11,7 @@
#include "or.h"
#include "address.h"
#include "addressmap.h"
+#include "bridges.h"
#include "circuitmux_ewma.h"
#include "circuitbuild.h"
#include "config.h"
diff --git a/src/test/test_controller.c b/src/test/test_controller.c
index f19c846..4e65d76 100644
--- a/src/test/test_controller.c
+++ b/src/test/test_controller.c
@@ -3,6 +3,7 @@
#define CONTROL_PRIVATE
#include "or.h"
+#include "bridges.h"
#include "control.h"
#include "entrynodes.h"
#include "networkstatus.h"
1
0

[tor/master] Add a smartlist_remove_keeporder() function, with tests.
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit 21c47c44109a9de373f40c454e653953ba21312e
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Wed Nov 23 14:07:53 2016 -0500
Add a smartlist_remove_keeporder() function, with tests.
---
src/common/container.c | 18 ++++++++++++++++++
src/common/container.h | 1 +
src/test/test_containers.c | 41 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 60 insertions(+)
diff --git a/src/common/container.c b/src/common/container.c
index ec59dcc..1448ab4 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -132,6 +132,24 @@ smartlist_remove(smartlist_t *sl, const void *element)
}
}
+/** As <b>smartlist_remove</b>, but do not change the order of
+ * any elements not removed */
+void
+smartlist_remove_keeporder(smartlist_t *sl, const void *element)
+{
+ int i, j, num_used_orig = sl->num_used;
+ if (element == NULL)
+ return;
+
+ for (i=j=0; j < num_used_orig; ++j) {
+ if (sl->list[j] == element) {
+ --sl->num_used;
+ } else {
+ sl->list[i++] = sl->list[j];
+ }
+ }
+}
+
/** If <b>sl</b> is nonempty, remove and return the final element. Otherwise,
* return NULL. */
void *
diff --git a/src/common/container.h b/src/common/container.h
index 71495b6..00c3ca8 100644
--- a/src/common/container.h
+++ b/src/common/container.h
@@ -33,6 +33,7 @@ void smartlist_clear(smartlist_t *sl);
void smartlist_add(smartlist_t *sl, void *element);
void smartlist_add_all(smartlist_t *sl, const smartlist_t *s2);
void smartlist_remove(smartlist_t *sl, const void *element);
+void smartlist_remove_keeporder(smartlist_t *sl, const void *element);
void *smartlist_pop_last(smartlist_t *sl);
void smartlist_reverse(smartlist_t *sl);
void smartlist_string_remove(smartlist_t *sl, const char *element);
diff --git a/src/test/test_containers.c b/src/test/test_containers.c
index d7291a2..41f3f87 100644
--- a/src/test/test_containers.c
+++ b/src/test/test_containers.c
@@ -882,6 +882,46 @@ test_container_strmap(void *arg)
tor_free(v105);
}
+static void
+test_container_smartlist_remove(void *arg)
+{
+ (void) arg;
+ int array[5];
+ smartlist_t *sl = smartlist_new();
+ int i,j;
+
+ for (j=0; j < 2; ++j)
+ for (i=0; i < 5; ++i)
+ smartlist_add(sl, &array[i]);
+
+ smartlist_remove(sl, &array[0]);
+ smartlist_remove(sl, &array[3]);
+ smartlist_remove(sl, &array[4]);
+ tt_assert(! smartlist_contains(sl, &array[0]));
+ tt_assert(smartlist_contains(sl, &array[1]));
+ tt_assert(smartlist_contains(sl, &array[2]));
+ tt_assert(! smartlist_contains(sl, &array[3]));
+ tt_assert(! smartlist_contains(sl, &array[4]));
+ tt_int_op(smartlist_len(sl), OP_EQ, 4);
+
+ smartlist_clear(sl);
+ for (j=0; j < 2; ++j)
+ for (i=0; i < 5; ++i)
+ smartlist_add(sl, &array[i]);
+
+ smartlist_remove_keeporder(sl, &array[0]);
+ smartlist_remove_keeporder(sl, &array[3]);
+ smartlist_remove_keeporder(sl, &array[4]);
+ tt_int_op(smartlist_len(sl), OP_EQ, 4);
+ tt_ptr_op(smartlist_get(sl, 0), OP_EQ, &array[1]);
+ tt_ptr_op(smartlist_get(sl, 1), OP_EQ, &array[2]);
+ tt_ptr_op(smartlist_get(sl, 2), OP_EQ, &array[1]);
+ tt_ptr_op(smartlist_get(sl, 3), OP_EQ, &array[2]);
+
+ done:
+ smartlist_free(sl);
+}
+
/** Run unit tests for getting the median of a list. */
static void
test_container_order_functions(void *arg)
@@ -1239,6 +1279,7 @@ struct testcase_t container_tests[] = {
CONTAINER_LEGACY(smartlist_digests),
CONTAINER_LEGACY(smartlist_join),
CONTAINER_LEGACY(smartlist_pos),
+ CONTAINER(smartlist_remove, 0),
CONTAINER(smartlist_ints_eq, 0),
CONTAINER_LEGACY(bitarray),
CONTAINER_LEGACY(digestset),
1
0

[tor/master] Backend for upgrading 'waiting' circuits to 'complete'
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit 36e9fbd7522fcee54b9f048bf506bfddc4bffc95
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Mon Nov 21 09:40:45 2016 -0500
Backend for upgrading 'waiting' circuits to 'complete'
When a nonprimary guard's circuit is complete, we don't call it
actually usable until we are pretty sure that every better guard
is indeed not going to give us a working circuit.
---
src/or/entrynodes.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 130 insertions(+), 13 deletions(-)
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 260b3d6..0e56147 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -1377,6 +1377,33 @@ entry_guards_all_primary_guards_are_down(guard_selection_t *gs)
return 1;
}
+/** Wrapper for entry_guard_has_higher_priority that compares the
+ * guard-priorities of a pair of circuits. */
+static int
+circ_state_has_higher_priority(origin_circuit_t *a,
+ origin_circuit_t *b)
+{
+ circuit_guard_state_t *state_a = origin_circuit_get_guard_state(a);
+ circuit_guard_state_t *state_b = origin_circuit_get_guard_state(b);
+
+ tor_assert(state_a);
+ tor_assert(state_b);
+
+ entry_guard_t *guard_a = entry_guard_handle_get(state_a->guard);
+ entry_guard_t *guard_b = entry_guard_handle_get(state_b->guard);
+
+ if (! guard_a) {
+ /* Unknown guard -- never higher priority. */
+ return 0;
+ } else if (! guard_b) {
+ /* Known guard -- higher priority than any unknown guard. */
+ return 1;
+ } else {
+ /* Both known -- compare.*/
+ return entry_guard_has_higher_priority(guard_a, guard_b);
+ }
+}
+
/**
* 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
@@ -1397,25 +1424,116 @@ entry_guards_upgrade_waiting_circuits(guard_selection_t *gs,
if (! entry_guards_all_primary_guards_are_down(gs)) {
/* We only upgrade a waiting circuit if the primary guards are all
* down. */
+ log_debug(LD_GUARD, "Considered upgrading guard-stalled circuits, "
+ "but not all primary guards were definitely down.");
+ return 0;
+ }
+
+ int n_waiting = 0;
+ int n_complete = 0;
+ origin_circuit_t *best_waiting_circuit = NULL;
+ origin_circuit_t *best_complete_circuit = NULL;
+ SMARTLIST_FOREACH_BEGIN(all_circuits, origin_circuit_t *, circ) {
+ circuit_guard_state_t *state = origin_circuit_get_guard_state(circ);
+ if (state == NULL)
+ continue;
+
+ if (state->state == GUARD_CIRC_STATE_WAITING_FOR_BETTER_GUARD) {
+ ++n_waiting;
+ if (! best_waiting_circuit ||
+ circ_state_has_higher_priority(circ, best_waiting_circuit)) {
+ best_waiting_circuit = circ;
+ }
+ } else if (state->state == GUARD_CIRC_STATE_COMPLETE) {
+ ++n_complete;
+ if (! best_complete_circuit ||
+ circ_state_has_higher_priority(circ, best_complete_circuit)) {
+ best_complete_circuit = circ;
+ }
+ }
+ } SMARTLIST_FOREACH_END(circ);
+
+ if (! best_waiting_circuit) {
+ log_debug(LD_GUARD, "Considered upgrading guard-stalled circuits, "
+ "but didn't find any.");
return 0;
}
- /* XXXX finish implementing. prop271 */
+ if (best_complete_circuit) {
+ if (circ_state_has_higher_priority(best_complete_circuit,
+ best_waiting_circuit)) {
+ /* "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." */
+ log_debug(LD_GUARD, "Considered upgrading guard-stalled circuits: found "
+ "%d complete and %d guard-stalled. At least one complete "
+ "circuit had higher priority, so not upgrading.",
+ n_complete, n_waiting);
+
+ /* XXXX prop271 implement: "(Time them out after a
+ {NONPRIMARY_GUARD_IDLE_TIMEOUT} seconds.)"
+ */
+ return 0;
+ }
+ }
/* "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>."
- */
+ {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.)"
+ XXXX --- prop271 deviation. there's no such thing in the spec as
+ an {is_pending circuit}; fix the spec.
*/
- return 0;
+ int n_blockers_found = 0;
+ const time_t state_set_at_cutoff =
+ approx_time() - NONPRIMARY_GUARD_CONNECT_TIMEOUT;
+ SMARTLIST_FOREACH_BEGIN(all_circuits, origin_circuit_t *, circ) {
+ circuit_guard_state_t *state = origin_circuit_get_guard_state(circ);
+ if (state == NULL)
+ continue;
+ if (state->state != GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD)
+ continue;
+ if (state->state_set_at > state_set_at_cutoff &&
+ circ_state_has_higher_priority(circ, best_waiting_circuit))
+ ++n_blockers_found;
+ } SMARTLIST_FOREACH_END(circ);
+
+ if (n_blockers_found) {
+ log_debug(LD_GUARD, "Considered upgrading guard-stalled circuits: found "
+ "%d guard-stalled, but %d pending circuit(s) had higher "
+ "guard priority, so not upgrading.",
+ n_waiting, n_blockers_found);
+ return 0;
+ }
+
+ /* Okay. We have a best waiting circuit, and we aren't waiting for
+ anything better. Add all circuits with that priority to the
+ list, and call them COMPLETE. */
+ int n_succeeded = 0;
+ SMARTLIST_FOREACH_BEGIN(all_circuits, origin_circuit_t *, circ) {
+ circuit_guard_state_t *state = origin_circuit_get_guard_state(circ);
+ if (state == NULL)
+ continue;
+ if (state->state != GUARD_CIRC_STATE_WAITING_FOR_BETTER_GUARD)
+ continue;
+ if (circ_state_has_higher_priority(best_waiting_circuit, circ))
+ continue;
+
+ state->state = GUARD_CIRC_STATE_COMPLETE;
+ state->state_set_at = approx_time();
+ smartlist_add(newly_complete_out, circ);
+ ++n_succeeded;
+ } SMARTLIST_FOREACH_END(circ);
+
+ log_info(LD_GUARD, "Considered upgrading guard-stalled circuits: found "
+ "%d guard-stalled, %d complete. %d of the guard-stalled "
+ "circuit(s) had high enough priority to upgrade.",
+ n_waiting, n_complete, n_succeeded);
+
+ tor_assert_nonfatal(n_succeeded >= 1);
+ return 1;
}
/**
@@ -1669,7 +1787,6 @@ __attribute__((noreturn)) void
entry_guards_DUMMY_ENTRY_POINT(void)
{
// prop271 XXXXX kludge; remove this
- entry_guard_has_higher_priority(NULL, NULL);
entry_guard_encode_for_state(NULL);
entry_guard_parse_from_state(NULL);
tor_assert(0);
1
0