From 53f248f6c9d71784c271cf14501ec4c28e5e885d Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 29 Nov 2016 10:14:42 -0500 Subject: [PATCH] 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 f16acfa28a..8090bae268 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 addr:port, * return that bridge. Else return NULL. If digest 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 routerset contains the bridge bridge. */ -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 digest 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 d01794f573..74c5113231 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 e725d4e5ae..dcaab352d0 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 gs contains a sampled entry guard matching bridge, + * 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 guard, 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 * rsa_id. */ @@ -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 cbc3f89cb4..21dab6ea18 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 4182dbc5c4..d0df0a74e6 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 routerset contains the bridge bridge. */ +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 routerset to * out, but never add any that are part of excludeset. * If running_only, only add the running ones. */ diff --git a/src/or/routerset.h b/src/or/routerset.h index c2f7205c3e..2e3b4b0fe0 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);