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

16 Dec '16
commit 171981f8a0eebf3f00feabe36dc66e031d51c5bd
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Wed Nov 30 11:28:18 2016 -0500
Add a test for entry_guard_state_should_expire()
---
src/test/test_entrynodes.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index 5fff1d6..5360b0e 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -2926,6 +2926,37 @@ …
[View More]test_entry_guard_upgrade_not_blocked_by_worse_circ_pending(void *arg)
smartlist_free(result);
}
+static void
+test_enty_guard_should_expire_waiting(void *arg)
+{
+ (void)arg;
+ circuit_guard_state_t *fake_state = tor_malloc_zero(sizeof(*fake_state));
+ /* We'll leave "guard" unset -- it won't matter here. */
+
+ /* No state? Can't expire. */
+ tt_assert(! entry_guard_state_should_expire(NULL));
+
+ /* Let's try one that expires. */
+ fake_state->state = GUARD_CIRC_STATE_WAITING_FOR_BETTER_GUARD;
+ fake_state->state_set_at =
+ approx_time() - DFLT_NONPRIMARY_GUARD_IDLE_TIMEOUT - 1;
+
+ tt_assert(entry_guard_state_should_expire(fake_state));
+
+ /* But it wouldn't expire if we changed the state. */
+ fake_state->state = GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD;
+ tt_assert(! entry_guard_state_should_expire(fake_state));
+
+ /* And it wouldn't have expired a few seconds ago. */
+ fake_state->state = GUARD_CIRC_STATE_WAITING_FOR_BETTER_GUARD;
+ fake_state->state_set_at =
+ approx_time() - DFLT_NONPRIMARY_GUARD_IDLE_TIMEOUT + 5;
+ tt_assert(! entry_guard_state_should_expire(fake_state));
+
+ done:
+ tor_free(fake_state);
+}
+
static const struct testcase_setup_t fake_network = {
fake_network_setup, fake_network_cleanup
};
@@ -3017,6 +3048,8 @@ struct testcase_t entrynodes_tests[] = {
UPGRADE_TEST(upgrade_not_blocked_by_worse_circ_complete, "c1-done c2-done"),
UPGRADE_TEST(upgrade_blocked_by_better_circ_pending, "c2-done"),
UPGRADE_TEST(upgrade_not_blocked_by_worse_circ_pending, "c1-done"),
+ { "should_expire_waiting", test_enty_guard_should_expire_waiting, TT_FORK,
+ NULL, NULL },
END_OF_TESTCASES
};
[View Less]
1
0
commit 2cee38f76a46860e2fb29fbd95ba36b332aa38c6
Merge: b310929 20292ec
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Fri Dec 16 11:20:59 2016 -0500
Merge branch 'prop271_030_v1_squashed'
src/common/address.c | 8 +
src/common/address.h | 2 +
src/common/container.c | 18 +
src/common/container.h | 1 +
src/common/log.c | 2 +-
src/common/torlog.h | 4 +-
src/common/util.c | 32 +-
src/common/util.h |…
[View More] 3 +-
src/or/bridges.c | 866 +++++++++
src/or/bridges.h | 66 +
src/or/channel.c | 3 +
src/or/channeltls.c | 9 +
src/or/circpathbias.c | 330 ++--
src/or/circuitbuild.c | 105 +-
src/or/circuitbuild.h | 9 +-
src/or/circuitlist.c | 121 +-
src/or/circuitlist.h | 3 +
src/or/circuituse.c | 40 +-
src/or/circuituse.h | 1 +
src/or/config.c | 57 +
src/or/connection.c | 6 +
src/or/connection_or.c | 11 +
src/or/control.c | 11 +-
src/or/directory.c | 101 +-
src/or/directory.h | 6 +-
src/or/entrynodes.c | 4347 +++++++++++++++++++++++++++++++++-----------
src/or/entrynodes.h | 617 ++++++-
src/or/include.am | 2 +
src/or/main.c | 14 +-
src/or/networkstatus.c | 20 +
src/or/networkstatus.h | 5 +
src/or/or.h | 32 +-
src/or/rendclient.c | 2 +-
src/or/rendservice.c | 2 +-
src/or/routerlist.c | 11 +-
src/or/routerparse.c | 3 +-
src/or/routerset.c | 13 +
src/or/routerset.h | 5 +-
src/or/statefile.c | 2 +
src/or/transports.c | 2 +-
src/test/test_config.c | 1 +
src/test/test_containers.c | 41 +
src/test/test_controller.c | 1 +
src/test/test_dir.c | 17 +-
src/test/test_entrynodes.c | 2599 +++++++++++++++++++++++++-
src/test/test_routerlist.c | 10 +
src/test/test_util.c | 17 +
47 files changed, 8206 insertions(+), 1372 deletions(-)
diff --cc src/or/bridges.c
index 0000000,4058979..7d1acdf
mode 000000,100644..100644
--- a/src/or/bridges.c
+++ b/src/or/bridges.c
@@@ -1,0 -1,847 +1,866 @@@
+ /* 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. */
+ struct bridge_info_t {
+ /** Address and port of the bridge, as configured by the user.*/
+ tor_addr_port_t addrport_configured;
+ /** 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;
+ };
+
+ static void bridge_free(bridge_info_t *bridge);
+
+ /** 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);
+ }
+
+ /** Return a list of all the configured bridges, as bridge_info_t pointers. */
+ const smartlist_t *
+ bridge_list_get(void)
+ {
+ if (!bridge_list)
+ bridge_list = smartlist_new();
+ return bridge_list;
+ }
+
+ /**
+ * Given a <b>bridge</b>, return a pointer to its RSA identity digest, or
+ * NULL if we don't know one for it.
+ */
+ const uint8_t *
+ bridge_get_rsa_id_digest(const bridge_info_t *bridge)
+ {
+ tor_assert(bridge);
+ if (tor_digest_is_zero(bridge->identity))
+ return NULL;
+ else
+ return (const uint8_t *) bridge->identity;
+ }
+
+ /**
+ * Given a <b>bridge</b>, return a pointer to its configured addr:port
+ * combination.
+ */
+ const tor_addr_port_t *
+ bridge_get_addr_port(const bridge_info_t *bridge)
+ {
+ tor_assert(bridge);
+ return &bridge->addrport_configured;
+ }
+
+ /** 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. */
+ 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)
++ const char *digest,
++ const ed25519_public_key_t *ed_id)
+ {
++ // XXXX prop220 use ed_id here, once there is some way to specify
++ (void)ed_id;
++ int learned = 0;
+ bridge_info_t *bridge =
+ get_configured_bridge_by_addr_port_digest(addr, port, digest);
+ if (bridge && tor_digest_is_zero(bridge->identity)) {
++ memcpy(bridge->identity, digest, DIGEST_LEN);
++ learned = 1;
++ }
++ /* XXXX prop220 remember bridge ed25519 identities -- add a field */
++#if 0
++ if (bridge && ed_id &&
++ ed25519_public_key_is_zero(&bridge->ed25519_identity) &&
++ !ed25519_public_key_is_zero(ed_id)) {
++ memcpy(&bridge->ed25519_identity, ed_id, sizeof(*ed_id));
++ learned = 1;
++ }
++#endif
++ if (learned) {
+ 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);
++ // XXXX prop220 log both fingerprints.
+ 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);
+ entry_guard_learned_bridge_identity(&bridge->addrport_configured,
+ (const uint8_t *)digest);
+ }
+ }
+
+ /** 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;
+
++ // XXXX prop220 add a way to specify ed25519 ID to bridge_line_t.
++
+ { /* 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->addrport_configured.addr, &bridge_line->addr);
+ b->addrport_configured.port = bridge_line->port;
+ 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);
+ }
+
+ /** If <b>digest</b> is one of our known bridges, return it. */
+ 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))
+ 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);
+ }
+ if (get_options()->UseDeprecatedGuardAlgorithm) {
+ #ifdef ENABLE_LEGACY_GUARD_ALGORITHM
+ add_bridge_as_entry_guard(get_guard_selection_info(), node);
+ #else
+ tor_assert_nonfatal_unreached();
+ #endif
+ } else {
+ entry_guard_learned_bridge_identity(&bridge->addrport_configured,
+ (const uint8_t*)ri->cache_info.identity_digest);
+ }
+
+ 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 */
+ if (get_options()->UseDeprecatedGuardAlgorithm) {
+ #ifdef ENABLE_LEGACY_GUARD_ALGORITHM
+ entry_guard_register_connect_status(ri->cache_info.identity_digest,
+ 1, 0, now);
+ #else
+ tor_assert_nonfatal_unreached();
+ #endif
+ }
+ 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);
+
+ if (!bridge_list)
+ return 0;
+
+ SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge) {
+ const node_t *node;
+ if (!tor_digest_is_zero(bridge->identity) &&
+ (node = node_get_by_id(bridge->identity)) != NULL &&
+ node->ri) {
+ return 1;
+ }
+ } SMARTLIST_FOREACH_END(bridge);
+
+ return 0;
+ }
+
+ /** 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 --cc src/or/bridges.h
index 0000000,74c5113..de23fe6
mode 000000,100644..100644
--- a/src/or/bridges.h
+++ b/src/or/bridges.h
@@@ -1,0 -1,65 +1,66 @@@
+ /* 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;
+
+ /* Opaque handle to a configured bridge */
+ 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);
+ 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);
++ const char *digest,
++ const ed25519_public_key_t *ed_id);
+
+ 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 --cc src/or/circuitlist.c
index b7ae3f5,ab38b54..5943e51
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@@ -63,8 -63,8 +63,9 @@@
#include "connection_edge.h"
#include "connection_or.h"
#include "control.h"
- #include "hs_circuitmap.h"
+ #include "entrynodes.h"
#include "main.h"
++#include "hs_circuitmap.h"
#include "hs_common.h"
#include "networkstatus.h"
#include "nodelist.h"
diff --cc src/or/config.c
index 5dcdf93,2ec96d3..aba567a
--- a/src/or/config.c
+++ b/src/or/config.c
@@@ -305,8 -306,11 +306,12 @@@ static config_var_t option_vars_[] =
V(ExtORPortCookieAuthFile, STRING, NULL),
V(ExtORPortCookieAuthFileGroupReadable, BOOL, "0"),
V(ExtraInfoStatistics, BOOL, "1"),
+ V(ExtendByEd25519ID, AUTOBOOL, "auto"),
V(FallbackDir, LINELIST, NULL),
+ /* XXXX prop271 -- this has an ugly name to remind us to remove it. */
+ VAR("UseDeprecatedGuardAlgorithm_", BOOL,
+ UseDeprecatedGuardAlgorithm, "0"),
+
V(UseDefaultFallbackDirs, BOOL, "1"),
OBSOLETE("FallbackNetworkstatusFile"),
diff --cc src/or/connection_or.c
index 635d3e4,6233fb7..b3ae291
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@@ -1715,13 -1675,16 +1721,18 @@@ connection_or_client_learned_peer_id(or
}
log_fn(severity, LD_HANDSHAKE,
- "Tried connecting to router at %s:%d, but identity key was not "
- "as expected: wanted %s but got %s.%s",
- conn->base_.address, conn->base_.port, expected, seen, extra_log);
+ "Tried connecting to router at %s:%d, but RSA identity key was not "
+ "as expected: wanted %s + %s but got %s + %s.%s",
+ conn->base_.address, conn->base_.port,
+ expected_rsa, expected_ed, seen_rsa, seen_ed, extra_log);
+
+ /* Tell the new guard API about the channel failure */
+ entry_guard_chan_failed(TLS_CHAN_TO_BASE(conn->chan));
+ #ifdef ENABLE_LEGACY_GUARD_ALGORITHM
+ /* Tell the old guard API about the channel failure */
entry_guard_register_connect_status(conn->identity_digest, 0, 1,
time(NULL));
+ #endif
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED,
END_OR_CONN_REASON_OR_IDENTITY);
if (!authdir_mode_tests_reachability(options))
diff --cc src/or/entrynodes.c
index af1b1a3,ac5398f..4c68247
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@@ -15,9 -118,10 +118,11 @@@
#define ENTRYNODES_PRIVATE
#include "or.h"
+#include "channel.h"
+ #include "bridges.h"
#include "circpathbias.h"
#include "circuitbuild.h"
+ #include "circuitlist.h"
#include "circuitstats.h"
#include "config.h"
#include "confparse.h"
diff --cc src/or/or.h
index f63fe06,04ff548..d45dc68
--- a/src/or/or.h
+++ b/src/or/or.h
@@@ -4563,14 -4588,13 +4580,22 @@@ typedef struct
/** If 1, we skip all OOS checks. */
int DisableOOSCheck;
+ /** Autobool: Should we include Ed25519 identities in extend2 cells?
+ * If -1, we should do whatever the consensus parameter says. */
+ int ExtendByEd25519ID;
+
+ /** Bool (default: 1): When testing routerinfos as a directory authority,
+ * do we enforce Ed25519 identity match? */
+ /* NOTE: remove this option someday. */
+ int AuthDirTestEd25519LinkKeys;
++
+ /** If 1, we use the old (pre-prop271) guard selection algorithm.
+ *
+ * XXXX prop271 This option is only here as a stopgap while we're
+ * XXXX tuning and debugging the new (post-prop271) algorithm. Eventually
+ * we should remove it entirely.
+ */
+ int UseDeprecatedGuardAlgorithm;
} or_options_t;
/** Persistent state for an onion router, as saved to disk. */
[View Less]
1
0

[tor/master] Per suggestion, increase the retry frequency for primary guards.
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit 20292ec4974b777d430e7962cc38349c5f82b220
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Thu Dec 8 13:10:22 2016 -0500
Per suggestion, increase the retry frequency for primary guards.
---
src/or/entrynodes.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index cf85dad..ac5398f 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -1708,8 +1708,8 @@ get_retry_schedule(time_t failing_since, …
[View More]time_t now,
const struct {
time_t maximum; int primary_delay; int nonprimary_delay;
} delays[] = {
- { SIX_HOURS, 30*60, 1*60*60 },
- { FOUR_DAYS, 2*60*60, 4*60*60 },
+ { SIX_HOURS, 10*60, 1*60*60 },
+ { FOUR_DAYS, 90*60, 4*60*60 },
{ SEVEN_DAYS, 4*60*60, 18*60*60 },
{ TIME_MAX, 9*60*60, 36*60*60 }
};
[View Less]
1
0

[tor/master] prop271: Tests for the highlevel or_state_t encode/decode functions
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit 79d3e94f8b1769ee8d1957cb1d6dd35bd02a7271
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Wed Nov 30 12:35:16 2016 -0500
prop271: Tests for the highlevel or_state_t encode/decode functions
---
src/or/entrynodes.c | 4 +-
src/or/entrynodes.h | 2 +
src/test/test_entrynodes.c | 238 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 242 insertions(+), 2 deletions(-)
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 9441be4..…
[View More]1f6d562 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -1115,8 +1115,8 @@ 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)
+MOCK_IMPL(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);
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index b676172..c05a3e3 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -498,6 +498,8 @@ STATIC guard_selection_t *guard_selection_new(const char *name,
STATIC guard_selection_t *get_guard_selection_by_name(
const char *name, guard_selection_type_t type, int create_if_absent);
STATIC void guard_selection_free(guard_selection_t *gs);
+MOCK_DECL(STATIC int, entry_guard_is_listed,
+ (guard_selection_t *gs, const entry_guard_t *guard));
STATIC const char *choose_guard_selection(const or_options_t *options,
const networkstatus_t *ns,
const char *old_selection,
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index 5360b0e..1fbb8f8 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -14,6 +14,7 @@
#include "bridges.h"
#include "circuitlist.h"
#include "config.h"
+#include "confparse.h"
#include "entrynodes.h"
#include "nodelist.h"
#include "networkstatus.h"
@@ -1247,6 +1248,239 @@ test_entry_guard_parse_from_state_partial_failure(void *arg)
tor_free(mem_op_hex_tmp);
}
+static int
+mock_entry_guard_is_listed(guard_selection_t *gs, const entry_guard_t *guard)
+{
+ (void)gs;
+ (void)guard;
+ return 1;
+}
+
+static void
+test_entry_guard_parse_from_state_full(void *arg)
+{
+ (void)arg;
+ /* Here's a state I made while testing. The identities and locations for
+ * the bridges are redacted. */
+ const char STATE[] =
+ "Guard in=default rsa_id=214F44BD5B638E8C817D47FF7C97397790BF0345 "
+ "nickname=TotallyNinja sampled_on=2016-11-12T19:32:49 "
+ "sampled_by=0.3.0.0-alpha-dev "
+ "listed=1\n"
+ "Guard in=default rsa_id=052900AB0EA3ED54BAB84AE8A99E74E8693CE2B2 "
+ "nickname=5OfNovember sampled_on=2016-11-20T04:32:05 "
+ "sampled_by=0.3.0.0-alpha-dev "
+ "listed=1 confirmed_on=2016-11-22T08:13:28 confirmed_idx=0 "
+ "pb_circ_attempts=4.000000 pb_circ_successes=2.000000 "
+ "pb_successful_circuits_closed=2.000000\n"
+ "Guard in=default rsa_id=7B700C0C207EBD0002E00F499BE265519AC3C25A "
+ "nickname=dc6jgk11 sampled_on=2016-11-28T11:50:13 "
+ "sampled_by=0.3.0.0-alpha-dev "
+ "listed=1 confirmed_on=2016-11-24T08:45:30 confirmed_idx=4 "
+ "pb_circ_attempts=5.000000 pb_circ_successes=5.000000 "
+ "pb_successful_circuits_closed=5.000000\n"
+ "Guard in=wobblesome rsa_id=7B700C0C207EBD0002E00F499BE265519AC3C25A "
+ "nickname=dc6jgk11 sampled_on=2016-11-28T11:50:13 "
+ "sampled_by=0.3.0.0-alpha-dev "
+ "listed=1\n"
+ "Guard in=default rsa_id=E9025AD60D86875D5F11548D536CC6AF60F0EF5E "
+ "nickname=maibrunn sampled_on=2016-11-25T22:36:38 "
+ "sampled_by=0.3.0.0-alpha-dev listed=1\n"
+ "Guard in=default rsa_id=DCD30B90BA3A792DA75DC54A327EF353FB84C38E "
+ "nickname=Unnamed sampled_on=2016-11-25T14:34:00 "
+ "sampled_by=0.3.0.0-alpha-dev listed=1\n"
+ "Guard in=bridges rsa_id=8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E "
+ "bridge_addr=24.1.1.1:443 sampled_on=2016-11-25T06:44:14 "
+ "sampled_by=0.3.0.0-alpha-dev listed=1 "
+ "confirmed_on=2016-11-29T10:36:06 confirmed_idx=0 "
+ "pb_circ_attempts=8.000000 pb_circ_successes=8.000000 "
+ "pb_successful_circuits_closed=13.000000\n"
+ "Guard in=bridges rsa_id=5800000000000000000000000000000000000000 "
+ "bridge_addr=37.218.246.143:28366 "
+ "sampled_on=2016-11-18T15:07:34 sampled_by=0.3.0.0-alpha-dev listed=1\n";
+
+ config_line_t *lines = NULL;
+ or_state_t *state = tor_malloc_zero(sizeof(or_state_t));
+ int r = config_get_lines(STATE, &lines, 0);
+ char *msg = NULL;
+ smartlist_t *text = smartlist_new();
+ char *joined = NULL;
+
+ MOCK(entry_guard_is_listed, mock_entry_guard_is_listed);
+
+ dummy_state = state;
+ MOCK(get_or_state,
+ get_or_state_replacement);
+
+ tt_assert(r == 0);
+ tt_assert(lines);
+
+ state->Guard = lines;
+
+ /* Try it first without setting the result. */
+ r = entry_guards_parse_state(state, 0, &msg);
+ tt_assert(r == 0);
+ guard_selection_t *gs_br =
+ get_guard_selection_by_name("bridges", GS_TYPE_BRIDGE, 0);
+ tt_assert(!gs_br);
+
+ r = entry_guards_parse_state(state, 1, &msg);
+ tt_assert(r == 0);
+ gs_br = get_guard_selection_by_name("bridges", GS_TYPE_BRIDGE, 0);
+ guard_selection_t *gs_df =
+ get_guard_selection_by_name("default", GS_TYPE_NORMAL, 0);
+ guard_selection_t *gs_wb =
+ get_guard_selection_by_name("wobblesome", GS_TYPE_NORMAL, 0);
+
+ tt_assert(gs_br);
+ tt_assert(gs_df);
+ tt_assert(gs_wb);
+
+ tt_int_op(smartlist_len(gs_df->sampled_entry_guards), OP_EQ, 5);
+ tt_int_op(smartlist_len(gs_br->sampled_entry_guards), OP_EQ, 2);
+ tt_int_op(smartlist_len(gs_wb->sampled_entry_guards), OP_EQ, 1);
+
+ /* Try again; make sure it doesn't double-add the guards. */
+ r = entry_guards_parse_state(state, 1, &msg);
+ tt_assert(r == 0);
+ gs_br = get_guard_selection_by_name("bridges", GS_TYPE_BRIDGE, 0);
+ gs_df = get_guard_selection_by_name("default", GS_TYPE_NORMAL, 0);
+ tt_assert(gs_br);
+ tt_assert(gs_df);
+ tt_int_op(smartlist_len(gs_df->sampled_entry_guards), OP_EQ, 5);
+ tt_int_op(smartlist_len(gs_br->sampled_entry_guards), OP_EQ, 2);
+
+ /* Re-encode; it should be the same... almost. */
+ {
+ /* (Make a guard nonpersistent first) */
+ entry_guard_t *g = smartlist_get(gs_df->sampled_entry_guards, 0);
+ g->is_persistent = 0;
+ }
+ config_free_lines(lines);
+ lines = state->Guard = NULL; // to prevent double-free.
+ entry_guards_update_state(state);
+ tt_assert(state->Guard);
+ lines = state->Guard;
+
+ config_line_t *ln;
+ for (ln = lines; ln; ln = ln->next) {
+ smartlist_add_asprintf(text, "%s %s\n",ln->key, ln->value);
+ }
+ joined = smartlist_join_strings(text, "", 0, NULL);
+ tt_str_op(joined, OP_EQ,
+ "Guard in=default rsa_id=052900AB0EA3ED54BAB84AE8A99E74E8693CE2B2 "
+ "nickname=5OfNovember sampled_on=2016-11-20T04:32:05 "
+ "sampled_by=0.3.0.0-alpha-dev "
+ "listed=1 confirmed_on=2016-11-22T08:13:28 confirmed_idx=0 "
+ "pb_circ_attempts=4.000000 pb_circ_successes=2.000000 "
+ "pb_successful_circuits_closed=2.000000\n"
+ "Guard in=default rsa_id=7B700C0C207EBD0002E00F499BE265519AC3C25A "
+ "nickname=dc6jgk11 sampled_on=2016-11-28T11:50:13 "
+ "sampled_by=0.3.0.0-alpha-dev "
+ "listed=1 confirmed_on=2016-11-24T08:45:30 confirmed_idx=1 "
+ "pb_circ_attempts=5.000000 pb_circ_successes=5.000000 "
+ "pb_successful_circuits_closed=5.000000\n"
+ "Guard in=default rsa_id=E9025AD60D86875D5F11548D536CC6AF60F0EF5E "
+ "nickname=maibrunn sampled_on=2016-11-25T22:36:38 "
+ "sampled_by=0.3.0.0-alpha-dev listed=1\n"
+ "Guard in=default rsa_id=DCD30B90BA3A792DA75DC54A327EF353FB84C38E "
+ "nickname=Unnamed sampled_on=2016-11-25T14:34:00 "
+ "sampled_by=0.3.0.0-alpha-dev listed=1\n"
+ "Guard in=wobblesome rsa_id=7B700C0C207EBD0002E00F499BE265519AC3C25A "
+ "nickname=dc6jgk11 sampled_on=2016-11-28T11:50:13 "
+ "sampled_by=0.3.0.0-alpha-dev "
+ "listed=1\n"
+ "Guard in=bridges rsa_id=8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E "
+ "bridge_addr=24.1.1.1:443 sampled_on=2016-11-25T06:44:14 "
+ "sampled_by=0.3.0.0-alpha-dev listed=1 "
+ "confirmed_on=2016-11-29T10:36:06 confirmed_idx=0 "
+ "pb_circ_attempts=8.000000 pb_circ_successes=8.000000 "
+ "pb_successful_circuits_closed=13.000000\n"
+ "Guard in=bridges rsa_id=5800000000000000000000000000000000000000 "
+ "bridge_addr=37.218.246.143:28366 "
+ "sampled_on=2016-11-18T15:07:34 sampled_by=0.3.0.0-alpha-dev listed=1\n");
+
+ done:
+ config_free_lines(lines);
+ tor_free(state);
+ tor_free(msg);
+ UNMOCK(get_or_state);
+ UNMOCK(entry_guard_is_listed);
+ SMARTLIST_FOREACH(text, char *, cp, tor_free(cp));
+ smartlist_free(text);
+ tor_free(joined);
+}
+
+static void
+test_entry_guard_parse_from_state_broken(void *arg)
+{
+ (void)arg;
+ /* Here's a variation on the previous state. Every line but the first is
+ * busted somehow. */
+ const char STATE[] =
+ /* Okay. */
+ "Guard in=default rsa_id=214F44BD5B638E8C817D47FF7C97397790BF0345 "
+ "nickname=TotallyNinja sampled_on=2016-11-12T19:32:49 "
+ "sampled_by=0.3.0.0-alpha-dev "
+ "listed=1\n"
+ /* No selection listed. */
+ "Guard rsa_id=052900AB0EA3ED54BAB84AE8A99E74E8693CE2B2 "
+ "nickname=5OfNovember sampled_on=2016-11-20T04:32:05 "
+ "sampled_by=0.3.0.0-alpha-dev "
+ "listed=1 confirmed_on=2016-11-22T08:13:28 confirmed_idx=0 "
+ "pb_circ_attempts=4.000000 pb_circ_successes=2.000000 "
+ "pb_successful_circuits_closed=2.000000\n"
+ /* Selection is "legacy"!! */
+ "Guard in=legacy rsa_id=7B700C0C207EBD0002E00F499BE265519AC3C25A "
+ "nickname=dc6jgk11 sampled_on=2016-11-28T11:50:13 "
+ "sampled_by=0.3.0.0-alpha-dev "
+ "listed=1 confirmed_on=2016-11-24T08:45:30 confirmed_idx=4 "
+ "pb_circ_attempts=5.000000 pb_circ_successes=5.000000 "
+ "pb_successful_circuits_closed=5.000000\n";
+
+ config_line_t *lines = NULL;
+ or_state_t *state = tor_malloc_zero(sizeof(or_state_t));
+ int r = config_get_lines(STATE, &lines, 0);
+ char *msg = NULL;
+
+ dummy_state = state;
+ MOCK(get_or_state,
+ get_or_state_replacement);
+
+ tt_assert(r == 0);
+ tt_assert(lines);
+
+ state->Guard = lines;
+
+ /* First, no-set case. we should get an error. */
+ r = entry_guards_parse_state(state, 0, &msg);
+ tt_int_op(r, OP_LT, 0);
+ tt_ptr_op(msg, OP_NE, NULL);
+ /* And we shouldn't have made anything. */
+ guard_selection_t *gs_df =
+ get_guard_selection_by_name("default", GS_TYPE_NORMAL, 0);
+ tt_assert(gs_df == NULL);
+ tor_free(msg);
+
+ /* Now see about the set case (which shouldn't happen IRL) */
+ r = entry_guards_parse_state(state, 1, &msg);
+ tt_int_op(r, OP_LT, 0);
+ tt_ptr_op(msg, OP_NE, NULL);
+ gs_df = get_guard_selection_by_name("default", GS_TYPE_NORMAL, 0);
+ tt_assert(gs_df != NULL);
+ tt_int_op(smartlist_len(gs_df->sampled_entry_guards), OP_EQ, 1);
+ guard_selection_t *gs_legacy =
+ get_guard_selection_by_name("legacy", GS_TYPE_LEGACY, 0);
+ tt_assert(gs_legacy != NULL);
+ tt_int_op(smartlist_len(gs_legacy->chosen_entry_guards), OP_EQ, 0);
+
+ done:
+ config_free_lines(lines);
+ tor_free(state);
+ tor_free(msg);
+ UNMOCK(get_or_state);
+}
+
static void
test_entry_guard_get_guard_selection_by_name(void *arg)
{
@@ -3019,6 +3253,10 @@ struct testcase_t entrynodes_tests[] = {
test_entry_guard_parse_from_state_failure, 0, NULL, NULL },
{ "parse_from_state_partial_failure",
test_entry_guard_parse_from_state_partial_failure, 0, NULL, NULL },
+ { "parse_from_state_full",
+ test_entry_guard_parse_from_state_full, TT_FORK, NULL, NULL },
+ { "parse_from_state_broken",
+ test_entry_guard_parse_from_state_broken, TT_FORK, NULL, NULL },
{ "get_guard_selection_by_name",
test_entry_guard_get_guard_selection_by_name, TT_FORK, NULL, NULL },
BFN_TEST(add_single_guard),
[View Less]
1
0
commit 50783d0123c38c649851421f33c616e0bf75d827
Author: George Kadianakis <desnacked(a)riseup.net>
Date: Tue Dec 6 14:35:31 2016 -0500
Easy code fixes.
- Correctly maintain the previous guard selection in choose_guard_selection().
- Print bridge identifier instead of nothing in entry_guard_describe()._
---
src/or/entrynodes.c | 19 +++++++++++++------
src/or/entrynodes.h | 6 +++---
2 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/src/or/entrynodes.c b/…
[View More]src/or/entrynodes.c
index a28603d..bcf4182 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -341,7 +341,8 @@ entry_guard_describe(const entry_guard_t *guard)
static char buf[256];
tor_snprintf(buf, sizeof(buf),
"%s ($%s)",
- guard->nickname, hex_str(guard->identity, DIGEST_LEN));
+ guard->nickname ? guard->nickname : "[bridge]",
+ hex_str(guard->identity, DIGEST_LEN));
return buf;
}
@@ -527,7 +528,7 @@ get_extreme_restriction_threshold(void)
STATIC const char *
choose_guard_selection(const or_options_t *options,
const networkstatus_t *live_ns,
- const char *old_selection,
+ const guard_selection_t *old_selection,
guard_selection_type_t *type_out)
{
tor_assert(options);
@@ -607,7 +608,11 @@ choose_guard_selection(const or_options_t *options,
}
}
- /* Trickier case: we do have a previous selection */
+ /* Trickier case: we do have a previous guard selection context. */
+ tor_assert(old_selection);
+
+ /* Use high and low thresholds to decide guard selection, and if we fall in
+ the middle then keep the current guard selection context. */
if (n_passing_filter >= meaningful_threshold_high) {
*type_out = GS_TYPE_NORMAL;
return "default";
@@ -615,7 +620,9 @@ choose_guard_selection(const or_options_t *options,
*type_out = GS_TYPE_RESTRICTED;
return "restricted";
} else {
- return NULL;
+ /* we are in the middle: maintain previous guard selection */
+ *type_out = old_selection->type;
+ return old_selection->name;
}
}
@@ -634,16 +641,16 @@ update_guard_selection_choice(const or_options_t *options)
return 1;
}
- const char *cur_name = curr_guard_context->name;
guard_selection_type_t type = GS_TYPE_INFER;
const char *new_name = choose_guard_selection(
options,
networkstatus_get_live_consensus(approx_time()),
- cur_name,
+ curr_guard_context,
&type);
tor_assert(new_name);
tor_assert(type != GS_TYPE_INFER);
+ const char *cur_name = curr_guard_context->name;
if (! strcmp(cur_name, new_name)) {
log_debug(LD_GUARD,
"Staying with guard context \"%s\" (no change)", new_name);
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 116e5ab..1133525 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -519,9 +519,9 @@ STATIC void guard_selection_free(guard_selection_t *gs);
MOCK_DECL(STATIC int, entry_guard_is_listed,
(guard_selection_t *gs, const entry_guard_t *guard));
STATIC const char *choose_guard_selection(const or_options_t *options,
- const networkstatus_t *ns,
- const char *old_selection,
- guard_selection_type_t *type_out);
+ const networkstatus_t *ns,
+ const guard_selection_t *old_selection,
+ guard_selection_type_t *type_out);
STATIC entry_guard_t *get_sampled_guard_with_id(guard_selection_t *gs,
const uint8_t *rsa_id);
[View Less]
1
0

[tor/master] Update node-selection tests to consider restrictions
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit d9f010db8448fa2aa4de80f0c26c41fafb25a694
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Wed Nov 30 13:37:37 2016 -0500
Update node-selection tests to consider restrictions
---
src/test/test_entrynodes.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index 84fdf07..e443210 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -2464,6 +2464,19 @…
[View More]@ test_entry_guard_select_for_circuit_no_confirmed(void *arg)
tt_i64_op(guard->unreachable_since, OP_EQ, approx_time() - 30);
});
+ /* Let's try again and we should get the first primary guard again */
+ g = select_entry_guard_for_circuit(gs, NULL, &state);
+ tt_ptr_op(g, OP_EQ, smartlist_get(gs->primary_entry_guards, 0));
+ g2 = select_entry_guard_for_circuit(gs, NULL, &state);
+ tt_ptr_op(g2, OP_EQ, g);
+
+ /* But if we impose a restriction, we don't get the same guard */
+ entry_guard_restriction_t rst;
+ memset(&rst, 0, sizeof(rst));
+ memcpy(rst.exclude_id, g->identity, DIGEST_LEN);
+ g2 = select_entry_guard_for_circuit(gs, &rst, &state);
+ tt_ptr_op(g2, OP_NE, g);
+
done:
guard_selection_free(gs);
}
@@ -2527,10 +2540,22 @@ test_entry_guard_select_for_circuit_confirmed(void *arg)
tt_uint_op(state, OP_EQ, GUARD_CIRC_STATE_USABLE_IF_NO_BETTER_GUARD);
tt_i64_op(g2->last_tried_to_connect, OP_EQ, approx_time());
+ // If we say that the next confirmed guard in order is excluded, we get
+ // The one AFTER that.
+ g = smartlist_get(gs->confirmed_entry_guards,
+ smartlist_len(gs->primary_entry_guards)+2);
+ entry_guard_restriction_t rst;
+ memset(&rst, 0, sizeof(rst));
+ memcpy(rst.exclude_id, g->identity, DIGEST_LEN);
+ g2 = select_entry_guard_for_circuit(gs, &rst, &state);
+ tt_ptr_op(g2, OP_NE, g);
+ tt_int_op(g2->confirmed_idx, OP_EQ,
+ smartlist_len(gs->primary_entry_guards)+3);
+
// If we make every confirmed guard become pending then we start poking
// other guards.
const int n_remaining_confirmed =
- N_CONFIRMED - 2 - smartlist_len(gs->primary_entry_guards);
+ N_CONFIRMED - 3 - smartlist_len(gs->primary_entry_guards);
for (i = 0; i < n_remaining_confirmed; ++i) {
g = select_entry_guard_for_circuit(gs, NULL, &state);
tt_int_op(g->confirmed_idx, OP_GE, 0);
[View Less]
1
0

[tor/master] Wrap all of the legacy guard code, and its users, in #ifdefs
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit 68679504323b0a676a446b8fb34b976c9dc66b4f
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Wed Dec 7 12:36:13 2016 -0500
Wrap all of the legacy guard code, and its users, in #ifdefs
This will make it easier to see what we remove down the line.
---
src/or/bridges.c | 8 ++++
src/or/channel.c | 2 +
src/or/circpathbias.c | 6 +++
src/or/circuitbuild.c | 2 +
src/or/circuituse.c | 16 ++++----
src/or/config.c | …
[View More]9 +++++
src/or/connection_or.c | 4 ++
src/or/control.c | 5 +++
src/or/entrynodes.c | 91 ++++++++++++++++++++++++++++++++++++++++++++--
src/or/entrynodes.h | 26 +++++++++++++
src/or/routerlist.c | 6 +++
src/test/test_entrynodes.c | 20 ++++++++--
src/test/test_routerlist.c | 10 +++++
13 files changed, 188 insertions(+), 17 deletions(-)
diff --git a/src/or/bridges.c b/src/or/bridges.c
index c480e3f..4058979 100644
--- a/src/or/bridges.c
+++ b/src/or/bridges.c
@@ -743,7 +743,11 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
(int) bridge->port);
}
if (get_options()->UseDeprecatedGuardAlgorithm) {
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
add_bridge_as_entry_guard(get_guard_selection_info(), node);
+#else
+ tor_assert_nonfatal_unreached();
+#endif
} else {
entry_guard_learned_bridge_identity(&bridge->addrport_configured,
(const uint8_t*)ri->cache_info.identity_digest);
@@ -754,8 +758,12 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
/* set entry->made_contact so if it goes down we don't drop it from
* our entry node list */
if (get_options()->UseDeprecatedGuardAlgorithm) {
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
entry_guard_register_connect_status(ri->cache_info.identity_digest,
1, 0, now);
+#else
+ tor_assert_nonfatal_unreached();
+#endif
}
if (first) {
routerlist_retry_directory_downloads(now);
diff --git a/src/or/channel.c b/src/or/channel.c
index 1e3e99c..9898148 100644
--- a/src/or/channel.c
+++ b/src/or/channel.c
@@ -2538,6 +2538,7 @@ channel_do_open_actions(channel_t *chan)
if (started_here) {
circuit_build_times_network_is_live(get_circuit_build_times_mutable());
rep_hist_note_connect_succeeded(chan->identity_digest, now);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
// XXXX prop271 this call is no longer useful with the new algorithm.
if (entry_guard_register_connect_status(
chan->identity_digest, 1, 0, now) < 0) {
@@ -2549,6 +2550,7 @@ channel_do_open_actions(channel_t *chan)
"connection so we can retry the earlier entry guards.");
close_origin_circuits = 1;
}
+#endif
router_set_status(chan->identity_digest, 1);
} else {
/* only report it to the geoip module if it's not a known router */
diff --git a/src/or/circpathbias.c b/src/or/circpathbias.c
index be11465..d86d70f 100644
--- a/src/or/circpathbias.c
+++ b/src/or/circpathbias.c
@@ -1279,7 +1279,10 @@ pathbias_measure_use_rate(entry_guard_t *guard)
tor_lround(pb->timeouts),
tor_lround(get_circuit_build_close_time_ms()/1000));
pb->path_bias_disabled = 1;
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
+ // XXXX
entry_guard_mark_bad(guard);
+#endif
return;
}
} else if (!pb->path_bias_use_extreme) {
@@ -1385,7 +1388,10 @@ pathbias_measure_close_rate(entry_guard_t *guard)
tor_lround(pb->timeouts),
tor_lround(get_circuit_build_close_time_ms()/1000));
pb->path_bias_disabled = 1;
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
+ // XXXX
entry_guard_mark_bad(guard);
+#endif
return;
}
} else if (!pb->path_bias_extreme) {
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 0790309..bf52b90 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -2277,6 +2277,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state,
* family. */
nodelist_add_node_and_family(excluded, node);
}
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/* and exclude current entry guards and their families,
* unless we're in a test network, and excluding guards
* would exclude all nodes (i.e. we're in an incredibly small tor network,
@@ -2295,6 +2296,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state,
}
});
}
+#endif
if (state) {
if (state->need_uptime)
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 787c490..8e0fbd1 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -550,16 +550,14 @@ circuit_expire_building(void)
== CPATH_STATE_OPEN;
log_info(LD_CIRC,
"No circuits are opened. Relaxing timeout for circuit %d "
- "(a %s %d-hop circuit in state %s with channel state %s). "
- "%d guards are live.",
+ "(a %s %d-hop circuit in state %s with channel state %s).",
TO_ORIGIN_CIRCUIT(victim)->global_identifier,
circuit_purpose_to_string(victim->purpose),
TO_ORIGIN_CIRCUIT(victim)->build_state ?
TO_ORIGIN_CIRCUIT(victim)->build_state->desired_path_len :
-1,
circuit_state_to_string(victim->state),
- channel_state_to_string(victim->n_chan->state),
- num_live_entry_guards(0));
+ channel_state_to_string(victim->n_chan->state));
/* We count the timeout here for CBT, because technically this
* was a timeout, and the timeout value needs to reset if we
@@ -577,7 +575,7 @@ circuit_expire_building(void)
"No circuits are opened. Relaxed timeout for circuit %d "
"(a %s %d-hop circuit in state %s with channel state %s) to "
"%ldms. However, it appears the circuit has timed out "
- "anyway. %d guards are live.",
+ "anyway.",
TO_ORIGIN_CIRCUIT(victim)->global_identifier,
circuit_purpose_to_string(victim->purpose),
TO_ORIGIN_CIRCUIT(victim)->build_state ?
@@ -585,8 +583,7 @@ circuit_expire_building(void)
-1,
circuit_state_to_string(victim->state),
channel_state_to_string(victim->n_chan->state),
- (long)build_close_ms,
- num_live_entry_guards(0));
+ (long)build_close_ms);
}
}
@@ -1655,8 +1652,10 @@ circuit_build_failed(origin_circuit_t *circ)
/* New guard API: we failed. */
if (circ->guard_state)
entry_guard_failed(&circ->guard_state);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/* Old guard API: we failed. */
entry_guard_register_connect_status(n_chan_id, 0, 1, time(NULL));
+#endif
/* if there are any one-hop streams waiting on this circuit, fail
* them now so they can retry elsewhere. */
connection_ap_fail_onehop(n_chan_id, circ->build_state);
@@ -1966,7 +1965,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
int severity = LOG_NOTICE;
/* Retry some stuff that might help the connection work. */
if (entry_list_is_constrained(options) &&
- entries_known_but_down(options)) {
+ guards_retry_optimistic(options)) {
log_fn(severity, LD_APP|LD_DIR,
"Application request when we haven't %s. "
"Optimistically trying known %s again.",
@@ -1974,7 +1973,6 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
"used client functionality lately" :
"received a consensus with exits",
options->UseBridges ? "bridges" : "entrynodes");
- entries_retry_all(options);
} else if (!options->UseBridges || any_bridge_descriptors_known()) {
log_fn(severity, LD_APP|LD_DIR,
"Application request when we haven't %s. "
diff --git a/src/or/config.c b/src/or/config.c
index 22e5dfd..2ec96d3 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -2116,11 +2116,13 @@ options_act(const or_options_t *old_options)
rep_hist_desc_stats_term();
/* Check if we need to parse and add the EntryNodes config option. */
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
if (options->EntryNodes &&
(!old_options ||
!routerset_equal(old_options->EntryNodes,options->EntryNodes) ||
!routerset_equal(old_options->ExcludeNodes,options->ExcludeNodes)))
entry_nodes_should_be_added();
+#endif
/* Since our options changed, we might need to regenerate and upload our
* server descriptor.
@@ -3040,6 +3042,13 @@ options_validate(or_options_t *old_options, or_options_t *options,
warn_about_relative_paths(options);
+#ifndef ENABLE_LEGACY_GUARD_ALGORITHM
+ if (options->UseDeprecatedGuardAlgorithm) {
+ log_warn(LD_CONFIG, "DeprecatedGuardAlgorithm not supported.");
+ return -1;
+ }
+#endif
+
if (server_mode(options) &&
(!strcmpstart(uname, "Windows 95") ||
!strcmpstart(uname, "Windows 98") ||
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index 3b6f82c..6233fb7 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -737,9 +737,11 @@ connection_or_about_to_close(or_connection_t *or_conn)
rep_hist_note_connect_failed(or_conn->identity_digest, now);
/* Tell the new guard API about the channel failure */
entry_guard_chan_failed(TLS_CHAN_TO_BASE(or_conn->chan));
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/* Tell the old guard API about the channel failure */
entry_guard_register_connect_status(or_conn->identity_digest,0,
!options->HTTPSProxy, now);
+#endif
if (conn->state >= OR_CONN_STATE_TLS_HANDSHAKING) {
int reason = tls_error_to_orconn_end_reason(or_conn->tls_error);
control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
@@ -1678,9 +1680,11 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
conn->base_.address, conn->base_.port, expected, seen, extra_log);
/* Tell the new guard API about the channel failure */
entry_guard_chan_failed(TLS_CHAN_TO_BASE(conn->chan));
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/* Tell the old guard API about the channel failure */
entry_guard_register_connect_status(conn->identity_digest, 0, 1,
time(NULL));
+#endif
control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED,
END_OR_CONN_REASON_OR_IDENTITY);
if (!authdir_mode_tests_reachability(options))
diff --git a/src/or/control.c b/src/or/control.c
index 03742e8..9a8845a 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -4041,12 +4041,17 @@ handle_control_dropguards(control_connection_t *conn,
smartlist_split_string(args, body, " ",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
if (smartlist_len(args)) {
connection_printf_to_buf(conn, "512 Too many arguments to DROPGUARDS\r\n");
} else {
remove_all_entry_guards();
send_control_done(conn);
}
+#else
+ // XXXX
+ connection_printf_to_buf(conn, "512 not supported\r\n");
+#endif
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
smartlist_free(args);
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index ac62155..76070a3 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -149,11 +149,13 @@ static guard_selection_t *curr_guard_context = NULL;
* and those changes need to be flushed to disk. */
static int entry_guards_dirty = 0;
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
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);
+#endif
static void entry_guard_set_filtered_flags(const or_options_t *options,
guard_selection_t *gs,
entry_guard_t *guard);
@@ -228,7 +230,9 @@ guard_selection_new(const char *name,
gs = tor_malloc_zero(sizeof(*gs));
gs->name = tor_strdup(name);
gs->type = type;
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
gs->chosen_entry_guards = smartlist_new();
+#endif
gs->sampled_entry_guards = smartlist_new();
gs->confirmed_entry_guards = smartlist_new();
gs->primary_entry_guards = smartlist_new();
@@ -298,6 +302,7 @@ get_guard_selection_info(void)
return curr_guard_context;
}
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/** Return the list of entry guards for a guard_selection_t, creating it
* if necessary. */
const smartlist_t *
@@ -324,6 +329,7 @@ entry_guard_mark_bad(entry_guard_t *guard)
guard->bad_since = approx_time();
entry_guards_changed();
}
+#endif
/** Return a statically allocated human-readable description of <b>guard</b>
*/
@@ -2831,6 +2837,7 @@ entry_guards_load_guards_from_state(or_state_t *state, int set)
/* XXXXX prop271 ----- end of new-for-prop271 code ----- */
/* XXXXX ----------------------------------------------- */
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/**
* @name Constants for old (pre-prop271) guard selection algorithm.
*/
@@ -3109,6 +3116,7 @@ num_live_entry_guards(int for_directory)
return num_live_entry_guards_for_guard_selection(
get_guard_selection_info(), for_directory);
}
+#endif
/** If <b>digest</b> matches the identity of any node in the
* entry_guards list for the provided guard selection state,
@@ -3123,11 +3131,12 @@ entry_guard_get_by_id_digest_for_guard_selection(guard_selection_t *gs,
if (tor_memeq(digest, entry->identity, DIGEST_LEN))
return entry;
);
-
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
SMARTLIST_FOREACH(gs->chosen_entry_guards, entry_guard_t *, entry,
if (tor_memeq(digest, entry->identity, DIGEST_LEN))
return entry;
);
+#endif
return NULL;
}
@@ -3150,6 +3159,7 @@ entry_guard_get_by_id_digest(const char *digest)
get_guard_selection_info(), digest);
}
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/** Dump a description of our list of entry guards in the given guard
* selection context to the log at level <b>severity</b>. */
static void
@@ -3375,6 +3385,7 @@ pick_entry_guards(guard_selection_t *gs,
if (changed)
entry_guards_changed_for_guard_selection(gs);
}
+#endif
/** Release all storage held by <b>e</b>. */
STATIC void
@@ -3383,7 +3394,9 @@ entry_guard_free(entry_guard_t *e)
if (!e)
return;
entry_guard_handles_clear(e);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
tor_free(e->chosen_by_version);
+#endif
tor_free(e->sampled_by_version);
tor_free(e->extra_state_fields);
tor_free(e->selection_name);
@@ -3391,6 +3404,7 @@ entry_guard_free(entry_guard_t *e)
tor_free(e);
}
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/** 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
@@ -3869,6 +3883,7 @@ entry_guards_set_from_config(guard_selection_t *gs,
smartlist_free(old_entry_guards_not_on_list);
entry_guards_changed_for_guard_selection(gs);
}
+#endif
/** Return 0 if we're fine adding arbitrary routers out of the
* directory to our entry guard list, or return 1 if we have a
@@ -3877,6 +3892,7 @@ entry_guards_set_from_config(guard_selection_t *gs,
int
entry_list_is_constrained(const or_options_t *options)
{
+ // XXXX prop271 look at the current selection.
if (options->EntryNodes)
return 1;
if (options->UseBridges)
@@ -3884,6 +3900,7 @@ entry_list_is_constrained(const or_options_t *options)
return 0;
}
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/** Pick a live (up and listed) entry guard from entry_guards. If
* <b>state</b> is non-NULL, this is for a specific circuit --
* make sure not to pick this circuit's exit or any node in the
@@ -3910,6 +3927,7 @@ choose_random_dirguard(dirinfo_type_t type)
return choose_random_entry_impl(get_guard_selection_info(),
NULL, 1, type, NULL);
}
+#endif
/** Return the number of bridges that have descriptors that are marked with
* purpose 'bridge' and are running.
@@ -3920,10 +3938,13 @@ num_bridges_usable(void)
int n_options = 0;
if (get_options()->UseDeprecatedGuardAlgorithm) {
-
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
tor_assert(get_options()->UseBridges);
(void) choose_random_entry_impl(get_guard_selection_info(),
NULL, 0, 0, &n_options);
+#else
+ tor_assert_nonfatal_unreached();
+#endif
} else {
/* XXXX prop271 Is this quite right? */
tor_assert(get_options()->UseBridges);
@@ -3944,6 +3965,7 @@ num_bridges_usable(void)
return n_options;
}
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/** Filter <b>all_entry_guards</b> for usable entry guards and put them
* in <b>live_entry_guards</b>. We filter based on whether the node is
* currently alive, and on whether it satisfies the restrictions
@@ -4156,6 +4178,7 @@ choose_random_entry_impl(guard_selection_t *gs,
smartlist_free(live_entry_guards);
return node;
}
+#endif
static void
pathbias_check_use_success_count(entry_guard_t *node)
@@ -4199,6 +4222,7 @@ pathbias_check_close_success_count(entry_guard_t *node)
}
}
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/** Parse <b>state</b> and learn about the entry guards it describes.
* If <b>set</b> is true, and there are no errors, replace the guard
* list in the provided guard selection context with what we find.
@@ -4452,6 +4476,7 @@ entry_guards_parse_state_for_guard_selection(
digestmap_free(added_by, tor_free_);
return *msg ? -1 : 0;
}
+#endif
/** Parse <b>state</b> and learn about the entry guards it describes.
* If <b>set</b> is true, and there are no errors, replace the guard
@@ -4466,9 +4491,13 @@ entry_guards_parse_state(or_state_t *state, int set, char **msg)
int r1 = entry_guards_load_guards_from_state(state, set);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
int r2 = entry_guards_parse_state_for_guard_selection(
get_guard_selection_by_name("legacy", GS_TYPE_LEGACY, 1),
state, set, msg);
+#else
+ int r2 = 0;
+#endif
entry_guards_dirty = 0;
@@ -4530,8 +4559,6 @@ entry_guards_changed(void)
void
entry_guards_update_state(or_state_t *state)
{
- config_line_t **next, *line;
-
entry_guards_dirty = 0;
// Handles all non-legacy guard info.
@@ -4539,6 +4566,9 @@ entry_guards_update_state(or_state_t *state)
entry_guards_dirty = 0;
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
+ config_line_t **next, *line;
+
guard_selection_t *gs;
gs = get_guard_selection_by_name("legacy", GS_TYPE_LEGACY, 0);
if (!gs)
@@ -4612,6 +4642,7 @@ entry_guards_update_state(or_state_t *state)
}
} SMARTLIST_FOREACH_END(e);
+#endif
if (!get_options()->AvoidDiskWrites)
or_state_mark_dirty(get_or_state(), 0);
entry_guards_dirty = 0;
@@ -4634,11 +4665,18 @@ getinfo_helper_entry_guards(control_connection_t *conn,
guard_selection_t *gs = get_guard_selection_info();
tor_assert(gs != NULL);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
tor_assert(gs->chosen_entry_guards != NULL);
+#else
+ // XXXX
+ (void)question;
+ (void)answer;
+#endif
(void) conn;
(void) errmsg;
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
if (!strcmp(question,"entry-guards") ||
!strcmp(question,"helper-nodes")) {
smartlist_t *sl = smartlist_new();
@@ -4683,6 +4721,7 @@ getinfo_helper_entry_guards(control_connection_t *conn,
SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
smartlist_free(sl);
}
+#endif
return 0;
}
@@ -4721,6 +4760,7 @@ guard_get_guardfraction_bandwidth(guardfraction_bandwidth_t *guardfraction_bw,
guardfraction_bw->non_guard_bw = orig_bandwidth - (int) guard_bw;
}
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/** Returns true iff the node is used as a guard in the specified guard
* context */
int
@@ -4819,6 +4859,7 @@ entries_retry_all(const or_options_t *options)
tor_assert(entry_list_is_constrained(options));
entries_retry_helper(options, 1);
}
+#endif
/** Helper: Update the status of all entry guards, in whatever algorithm
* is used. Return true if we should stop using all previously generated
@@ -4833,7 +4874,11 @@ guards_update_all(void)
tor_assert(curr_guard_context);
if (curr_guard_context->type == GS_TYPE_LEGACY) {
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
entry_guards_compute_status(get_options(), approx_time());
+#else
+ tor_assert_nonfatal_unreached();
+#endif
} else {
if (entry_guards_update_all(curr_guard_context))
mark_circuits = 1;
@@ -4849,7 +4894,12 @@ guards_choose_guard(cpath_build_state_t *state,
circuit_guard_state_t **guard_state_out)
{
if (get_options()->UseDeprecatedGuardAlgorithm) {
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
return choose_random_entry(state);
+#else
+ tor_assert_nonfatal_unreached();
+ return NULL;
+#endif
} else {
const node_t *r = NULL;
const uint8_t *exit_id = NULL;
@@ -4877,7 +4927,13 @@ guards_choose_dirguard(dirinfo_type_t info,
circuit_guard_state_t **guard_state_out)
{
if (get_options()->UseDeprecatedGuardAlgorithm) {
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
return choose_random_dirguard(info);
+#else
+ (void)info;
+ tor_assert_nonfatal_unreached();
+ return NULL;
+#endif
} else {
/* XXXX prop271 We don't need to look at the dirinfo_type_t here,
* apparently. If you look at the old implementation, and you follow info
@@ -4897,6 +4953,31 @@ guards_choose_dirguard(dirinfo_type_t info,
}
}
+/**
+ * If we're running with a constrained guard set, then maybe mark our guards
+ * usable. Return 1 if we do; 0 if we don't.
+ */
+int
+guards_retry_optimistic(const or_options_t *options)
+{
+ if (! entry_list_is_constrained(options))
+ return 0;
+
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
+ if (options->UseDeprecatedGuardAlgorithm) {
+ if (entries_known_but_down(options)) {
+ entries_retry_all(options);
+ return 1;
+ }
+ }
+#endif
+
+ // XXXX prop271 -- is this correct?
+ mark_primary_guards_maybe_reachable(get_guard_selection_info());
+
+ return 1;
+}
+
/** Free one guard selection context */
STATIC void
guard_selection_free(guard_selection_t *gs)
@@ -4905,12 +4986,14 @@ guard_selection_free(guard_selection_t *gs)
tor_free(gs->name);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
if (gs->chosen_entry_guards) {
SMARTLIST_FOREACH(gs->chosen_entry_guards, entry_guard_t *, e,
entry_guard_free(e));
smartlist_free(gs->chosen_entry_guards);
gs->chosen_entry_guards = NULL;
}
+#endif
if (gs->sampled_entry_guards) {
SMARTLIST_FOREACH(gs->sampled_entry_guards, entry_guard_t *, e,
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index c05a3e3..3250be1 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -28,6 +28,11 @@ typedef struct circuit_guard_state_t circuit_guard_state_t;
private. */
typedef struct entry_guard_restriction_t entry_guard_restriction_t;
+/*
+ XXXX Prop271 undefine this in order to disable all legacy guard functions.
+*/
+#define ENABLE_LEGACY_GUARD_ALGORITHM
+
/* 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.
@@ -174,6 +179,7 @@ struct entry_guard_t {
guard_selection_t *in_selection;
/**@}*/
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/**
* @name legacy guard selection algorithm fields
*
@@ -202,6 +208,7 @@ struct entry_guard_t {
* at which we last failed to connect to it. */
/**}@*/
+#endif
/** Path bias information for this guard. */
guard_pathbias_t pb;
@@ -298,6 +305,7 @@ struct guard_selection_s {
* confirmed_entry_guards receive? */
int next_confirmed_idx;
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/**
* A list of our chosen entry guards, as entry_guard_t structures; this
* preserves the pre-Prop271 behavior.
@@ -310,6 +318,7 @@ struct guard_selection_s {
* preserves the pre-Prop271 behavior.
*/
int should_add_entry_nodes;
+#endif
};
struct entry_guard_handle_t;
@@ -369,9 +378,11 @@ entry_guard_t *entry_guard_get_by_id_digest(const char *digest);
void entry_guards_changed_for_guard_selection(guard_selection_t *gs);
void entry_guards_changed(void);
guard_selection_t * get_guard_selection_info(void);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
const smartlist_t *get_entry_guards_for_guard_selection(
guard_selection_t *gs);
const smartlist_t *get_entry_guards(void);
+#endif
int num_live_entry_guards_for_guard_selection(
guard_selection_t *gs,
int for_directory);
@@ -379,7 +390,9 @@ int num_live_entry_guards(int for_directory);
#endif
const node_t *entry_guard_find_node(const entry_guard_t *guard);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
void entry_guard_mark_bad(entry_guard_t *guard);
+#endif
const char *entry_guard_get_rsa_id_digest(const entry_guard_t *guard);
const char *entry_guard_describe(const entry_guard_t *guard);
guard_pathbias_t *entry_guard_get_pathbias_state(entry_guard_t *guard);
@@ -408,8 +421,10 @@ void entry_guards_note_internet_connectivity(guard_selection_t *gs);
int update_guard_selection_choice(const or_options_t *options);
/* Used by bridges.c only. */
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
void add_bridge_as_entry_guard(guard_selection_t *gs,
const node_t *chosen);
+#endif
int num_bridges_usable(void);
#ifdef ENTRYNODES_PRIVATE
@@ -568,6 +583,7 @@ STATIC unsigned entry_guards_note_guard_success(guard_selection_t *gs,
unsigned old_state);
STATIC int entry_guard_has_higher_priority(entry_guard_t *a, entry_guard_t *b);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
// ---------- XXXX this stuff is pre-prop271.
STATIC const node_t *add_an_entry_guard(guard_selection_t *gs,
@@ -599,16 +615,20 @@ STATIC const node_t *entry_is_live(const entry_guard_t *e,
const char **msg);
STATIC int entry_is_time_to_retry(const entry_guard_t *e, time_t now);
+#endif
#endif
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
void remove_all_entry_guards_for_guard_selection(guard_selection_t *gs);
void remove_all_entry_guards(void);
+#endif
struct bridge_info_t;
void entry_guard_learned_bridge_identity(const tor_addr_port_t *addrport,
const uint8_t *rsa_id_digest);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
void entry_guards_compute_status_for_guard_selection(
guard_selection_t *gs, const or_options_t *options, time_t now);
void entry_guards_compute_status(const or_options_t *options, time_t now);
@@ -619,9 +639,13 @@ int entry_guard_register_connect_status(const char *digest, int succeeded,
int mark_relay_status, time_t now);
void entry_nodes_should_be_added_for_guard_selection(guard_selection_t *gs);
void entry_nodes_should_be_added(void);
+#endif
int entry_list_is_constrained(const or_options_t *options);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
const node_t *choose_random_entry(cpath_build_state_t *state);
const node_t *choose_random_dirguard(dirinfo_type_t t);
+#endif
+int guards_retry_optimistic(const or_options_t *options);
int entry_guards_parse_state_for_guard_selection(
guard_selection_t *gs, or_state_t *state, int set, char **msg);
int entry_guards_parse_state(or_state_t *state, int set, char **msg);
@@ -629,9 +653,11 @@ void entry_guards_update_state(or_state_t *state);
int getinfo_helper_entry_guards(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
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));
+#endif
int entries_known_but_down(const or_options_t *options);
void entries_retry_all(const or_options_t *options);
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index d2f360a..cfa570c 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -2003,6 +2003,10 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags,
int try_excluding = 1, n_excluded = 0, n_busy = 0;
int try_ip_pref = 1;
+#ifndef ENABLE_LEGACY_GUARD_ALGORITHM
+ tor_assert_nonfatal(! for_guard);
+#endif
+
if (!consensus)
return NULL;
@@ -2038,10 +2042,12 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags,
if ((type & EXTRAINFO_DIRINFO) &&
!router_supports_extrainfo(node->identity, is_trusted_extrainfo))
continue;
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/* Don't make the same node a guard twice */
if (for_guard && is_node_used_as_guard(node)) {
continue;
}
+#endif
/* Ensure that a directory guard is actually a guard node. */
if (for_guard && !node->is_possible_guard) {
continue;
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index fbb3b13..594708a 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -45,6 +45,7 @@ get_or_state_replacement(void)
return dummy_state;
}
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/* Unittest cleanup function: Cleanup the fake network. */
static int
fake_network_cleanup(const struct testcase_t *testcase, void *ptr)
@@ -77,6 +78,7 @@ fake_network_setup(const struct testcase_t *testcase)
/* Return anything but NULL (it's interpreted as test fail) */
return dummy_state;
}
+#endif
static networkstatus_t *dummy_consensus = NULL;
@@ -200,6 +202,7 @@ mock_get_options(void)
return &mocked_options;
}
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
/** Test choose_random_entry() with none of our routers being guard nodes. */
static void
test_choose_random_entry_no_guards(void *arg)
@@ -888,6 +891,7 @@ test_entry_is_live(void *arg)
done:
; /* XXX */
}
+#endif
#define TEST_IPV4_ADDR "123.45.67.89"
#define TEST_IPV6_ADDR "[1234:5678:90ab:cdef::]"
@@ -1471,8 +1475,12 @@ test_entry_guard_parse_from_state_broken(void *arg)
tt_int_op(smartlist_len(gs_df->sampled_entry_guards), OP_EQ, 1);
guard_selection_t *gs_legacy =
get_guard_selection_by_name("legacy", GS_TYPE_LEGACY, 0);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
tt_assert(gs_legacy != NULL);
tt_int_op(smartlist_len(gs_legacy->chosen_entry_guards), OP_EQ, 0);
+#else
+ tt_assert(gs_legacy == NULL);
+#endif
done:
config_free_lines(lines);
@@ -2455,7 +2463,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg)
// if we mark that guard down, we should get a different primary guard.
// auto-retry it.
g->is_reachable = GUARD_REACHABLE_NO;
- g->unreachable_since = approx_time() - 10;
+ g->failing_since = approx_time() - 10;
g->last_tried_to_connect = approx_time() - 10;
state = 9999;
g2 = select_entry_guard_for_circuit(gs, NULL, &state);
@@ -2469,7 +2477,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg)
// If we say that the first primary guard was last tried a long time ago, we
// should get an automatic retry on it.
- g->unreachable_since = approx_time() - 72*60*60;
+ g->failing_since = approx_time() - 72*60*60;
g->last_tried_to_connect = approx_time() - 72*60*60;
state = 9999;
g2 = select_entry_guard_for_circuit(gs, NULL, &state);
@@ -2484,7 +2492,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg)
SMARTLIST_FOREACH(gs->primary_entry_guards, entry_guard_t *, guard, {
guard->is_reachable = GUARD_REACHABLE_NO;
guard->last_tried_to_connect = approx_time() - 5;
- guard->unreachable_since = approx_time() - 30;
+ guard->failing_since = approx_time() - 30;
});
state = 9999;
g2 = select_entry_guard_for_circuit(gs, NULL, &state);
@@ -2503,7 +2511,7 @@ test_entry_guard_select_for_circuit_no_confirmed(void *arg)
tt_assert(guard->is_usable_filtered_guard == 1);
// no change to these fields.
tt_i64_op(guard->last_tried_to_connect, OP_EQ, approx_time() - 5);
- tt_i64_op(guard->unreachable_since, OP_EQ, approx_time() - 30);
+ tt_i64_op(guard->failing_since, OP_EQ, approx_time() - 30);
});
/* Let's try again and we should get the first primary guard again */
@@ -3334,9 +3342,11 @@ test_enty_guard_should_expire_waiting(void *arg)
tor_free(fake_state);
}
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
static const struct testcase_setup_t fake_network = {
fake_network_setup, fake_network_cleanup
};
+#endif
static const struct testcase_setup_t big_fake_network = {
big_fake_network_setup, big_fake_network_cleanup
@@ -3354,6 +3364,7 @@ static const struct testcase_setup_t upgrade_circuits = {
(void*)(arg) }
struct testcase_t entrynodes_tests[] = {
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
{ "entry_is_time_to_retry", test_entry_is_time_to_retry,
TT_FORK, NULL, NULL },
{ "choose_random_entry_no_guards", test_choose_random_entry_no_guards,
@@ -3379,6 +3390,7 @@ struct testcase_t entrynodes_tests[] = {
{ "entry_is_live",
test_entry_is_live,
TT_FORK, &fake_network, NULL },
+#endif
{ "node_preferred_orport",
test_node_preferred_orport,
0, NULL, NULL },
diff --git a/src/test/test_routerlist.c b/src/test/test_routerlist.c
index af5c121..73e8d10 100644
--- a/src/test/test_routerlist.c
+++ b/src/test/test_routerlist.c
@@ -204,6 +204,7 @@ mock_usable_consensus_flavor(void)
return mock_usable_consensus_flavor_value;
}
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
static smartlist_t *mock_is_guard_list = NULL;
static int
@@ -250,6 +251,7 @@ clear_mock_guard_list(void)
mock_is_guard_list = NULL;
}
}
+#endif
static void
test_router_pick_directory_server_impl(void *arg)
@@ -271,7 +273,9 @@ test_router_pick_directory_server_impl(void *arg)
(void)arg;
MOCK(usable_consensus_flavor, mock_usable_consensus_flavor);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
MOCK(is_node_used_as_guard, mock_is_node_used_as_guard);
+#endif
/* With no consensus, we must be bootstrapping, regardless of time or flavor
*/
@@ -384,6 +388,7 @@ test_router_pick_directory_server_impl(void *arg)
node_router1->is_valid = 1;
node_router3->is_valid = 1;
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
flags |= PDS_FOR_GUARD;
mark_node_used_as_guard(node_router1);
mark_node_used_as_guard(node_router2);
@@ -397,8 +402,10 @@ test_router_pick_directory_server_impl(void *arg)
rs = NULL;
mark_node_unused_as_guard(node_router2);
mark_node_unused_as_guard(node_router3);
+#endif
/* One not valid, one guard. This should leave one remaining */
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
node_router1->is_valid = 0;
mark_node_used_as_guard(node_router2);
rs = router_pick_directory_server_impl(V3_DIRINFO, flags, NULL);
@@ -407,6 +414,7 @@ test_router_pick_directory_server_impl(void *arg)
rs = NULL;
node_router1->is_valid = 1;
mark_node_unused_as_guard(node_router2);
+#endif
/* Manipulate overloaded */
@@ -469,8 +477,10 @@ test_router_pick_directory_server_impl(void *arg)
done:
UNMOCK(usable_consensus_flavor);
+#ifdef ENABLE_LEGACY_GUARD_ALGORITHM
UNMOCK(is_node_used_as_guard);
clear_mock_guard_list();
+#endif
if (router1_id)
tor_free(router1_id);
[View Less]
1
0
commit 2b4bfe62ee74b927d65923f5d07fe04f51f8779a
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Wed Nov 30 14:25:16 2016 -0500
Fix a signed/unsigned warning on 32-bit
---
src/or/entrynodes.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 78257ca..ac62155 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -1665,7 +1665,7 @@ entry_guards_update_primary(guard_selection_t *gs)
* Return the …
[View More]number of seconds after the last attempt at which we should
* retry a guard that has been failing since <b>failing_since</b>.
*/
-static unsigned
+static int
get_retry_schedule(time_t failing_since, time_t now,
int is_primary)
{
@@ -1712,7 +1712,7 @@ entry_guard_consider_retry(entry_guard_t *guard)
return; /* No retry needed. */
const time_t now = approx_time();
- const unsigned delay =
+ const int delay =
get_retry_schedule(guard->failing_since, now, guard->is_primary);
const time_t last_attempt = guard->last_tried_to_connect;
[View Less]
1
0

[tor/master] Tests for restricted-circuit cases of upgrade_waiting_circuits()
by nickm@torproject.org 16 Dec '16
by nickm@torproject.org 16 Dec '16
16 Dec '16
commit 7361e1b499f3b2dc4a24192eed47d0adb668c25a
Author: Nick Mathewson <nickm(a)torproject.org>
Date: Wed Nov 30 13:28:44 2016 -0500
Tests for restricted-circuit cases of upgrade_waiting_circuits()
---
src/test/test_entrynodes.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 80 insertions(+)
diff --git a/src/test/test_entrynodes.c b/src/test/test_entrynodes.c
index 1fbb8f8..84fdf07 100644
--- a/src/test/test_entrynodes.c
+++ b/src/test/test_entrynodes.c
@@ -…
[View More]3079,6 +3079,45 @@ test_entry_guard_upgrade_blocked_by_better_circ_complete(void *arg)
}
static void
+test_entry_guard_upgrade_not_blocked_by_restricted_circ_complete(void *arg)
+{
+ upgrade_circuits_data_t *data = arg;
+
+ /* Once more, let circ1 become complete. But this time, we'll claim
+ * that circ2 was restricted to not use the same guard as circ1. */
+ data->guard2_state->restrictions =
+ tor_malloc_zero(sizeof(entry_guard_restriction_t));
+ memcpy(data->guard2_state->restrictions->exclude_id,
+ data->guard1->identity, DIGEST_LEN);
+
+ smartlist_t *result = smartlist_new();
+ int r;
+ r = entry_guards_upgrade_waiting_circuits(data->gs,
+ data->all_origin_circuits,
+ result);
+ tt_int_op(r, OP_EQ, 1);
+ tt_int_op(smartlist_len(result), OP_EQ, 1);
+ origin_circuit_t *oc = smartlist_get(result, 0);
+ tt_ptr_op(oc, OP_EQ, data->circ1);
+ tt_ptr_op(data->guard1_state, OP_NE, NULL);
+ tt_int_op(data->guard1_state->state, OP_EQ, GUARD_CIRC_STATE_COMPLETE);
+
+ /* Now, we try again. Since circ2 has a restriction that circ1 doesn't obey,
+ * circ2 _is_ eligible for upgrade. */
+ smartlist_clear(result);
+ r = entry_guards_upgrade_waiting_circuits(data->gs,
+ data->all_origin_circuits,
+ result);
+ tt_int_op(r, OP_EQ, 1);
+ tt_int_op(smartlist_len(result), OP_EQ, 1);
+ origin_circuit_t *oc2 = smartlist_get(result, 0);
+ tt_ptr_op(oc2, OP_EQ, data->circ2);
+
+ done:
+ smartlist_free(result);
+}
+
+static void
test_entry_guard_upgrade_not_blocked_by_worse_circ_complete(void *arg)
{
upgrade_circuits_data_t *data = arg;
@@ -3140,6 +3179,43 @@ test_entry_guard_upgrade_blocked_by_better_circ_pending(void *arg)
}
static void
+test_entry_guard_upgrade_not_blocked_by_restricted_circ_pending(void *arg)
+{
+ upgrade_circuits_data_t *data = arg;
+ /* circ2 is done, but circ1 is still pending. But when there is a
+ restriction on circ2 that circ1 can't satisfy, circ1 can't block
+ circ2. */
+
+ /* XXXX Prop271 -- this is a kludge. I'm making sure circ1 _is_ better,
+ * by messing with the guards' confirmed_idx */
+ make_guard_confirmed(data->gs, data->guard1);
+ {
+ int tmp;
+ tmp = data->guard1->confirmed_idx;
+ data->guard1->confirmed_idx = data->guard2->confirmed_idx;
+ data->guard2->confirmed_idx = tmp;
+ }
+
+ data->guard2_state->restrictions =
+ tor_malloc_zero(sizeof(entry_guard_restriction_t));
+ memcpy(data->guard2_state->restrictions->exclude_id,
+ data->guard1->identity, DIGEST_LEN);
+
+ smartlist_t *result = smartlist_new();
+ int r;
+ r = entry_guards_upgrade_waiting_circuits(data->gs,
+ data->all_origin_circuits,
+ result);
+ tt_int_op(r, OP_EQ, 1);
+ tt_int_op(smartlist_len(result), OP_EQ, 1);
+ origin_circuit_t *oc = smartlist_get(result, 0);
+ tt_ptr_op(oc, OP_EQ, data->circ2);
+
+ done:
+ smartlist_free(result);
+}
+
+static void
test_entry_guard_upgrade_not_blocked_by_worse_circ_pending(void *arg)
{
upgrade_circuits_data_t *data = arg;
@@ -3283,8 +3359,12 @@ struct testcase_t entrynodes_tests[] = {
UPGRADE_TEST(upgrade_blocked_by_live_primary_guards, "c1-done c2-done"),
UPGRADE_TEST(upgrade_blocked_by_lack_of_waiting_circuits, ""),
UPGRADE_TEST(upgrade_blocked_by_better_circ_complete, "c1-done c2-done"),
+ UPGRADE_TEST(upgrade_not_blocked_by_restricted_circ_complete,
+ "c1-done c2-done"),
UPGRADE_TEST(upgrade_not_blocked_by_worse_circ_complete, "c1-done c2-done"),
UPGRADE_TEST(upgrade_blocked_by_better_circ_pending, "c2-done"),
+ UPGRADE_TEST(upgrade_not_blocked_by_restricted_circ_pending,
+ "c2-done"),
UPGRADE_TEST(upgrade_not_blocked_by_worse_circ_pending, "c1-done"),
{ "should_expire_waiting", test_enty_guard_should_expire_waiting, TT_FORK,
NULL, NULL },
[View Less]
1
0
commit 7ab2678074e5d49628d948fadb80c5904950236c
Author: George Kadianakis <desnacked(a)riseup.net>
Date: Tue Dec 6 14:34:48 2016 -0500
Trivial documentation improvements.
---
src/or/circuitlist.c | 13 ++++++-------
src/or/entrynodes.c | 17 +++++++++++++----
src/or/entrynodes.h | 9 ++++++---
3 files changed, 25 insertions(+), 14 deletions(-)
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index b25f817..ab38b54 100644
--- a/src/or/circuitlist.c
+++ b/src/or/…
[View More]circuitlist.c
@@ -562,7 +562,6 @@ circuit_get_global_list,(void))
return global_circuitlist;
}
-/** */
/** Return a pointer to the global list of origin circuits. */
smartlist_t *
circuit_get_global_origin_circuit_list(void)
@@ -1758,17 +1757,17 @@ circuit_find_circuits_to_upgrade_from_guard_wait(void)
if (! circuits_pending_other_guards ||
smartlist_len(circuits_pending_other_guards)==0)
return NULL;
- /* Only if we have some origin circuiuts should we run the algorithm.
- */
+ /* Only if we have some origin circuits should we run the algorithm. */
if (!global_origin_circuit_list)
return NULL;
/* Okay; we can pass our circuit list to entrynodes.c.*/
smartlist_t *result = smartlist_new();
- int r = entry_guards_upgrade_waiting_circuits(get_guard_selection_info(),
- global_origin_circuit_list,
- result);
- if (r && smartlist_len(result)) {
+ int circuits_upgraded = entry_guards_upgrade_waiting_circuits(
+ get_guard_selection_info(),
+ global_origin_circuit_list,
+ result);
+ if (circuits_upgraded && smartlist_len(result)) {
return result;
} else {
smartlist_free(result);
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index 76070a3..a28603d 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -142,7 +142,9 @@
#include "transports.h"
#include "statefile.h"
+/** A list of existing guard selection contexts. */
static smartlist_t *guard_contexts = NULL;
+/** The currently enabled guard selection context. */
static guard_selection_t *curr_guard_context = NULL;
/** A value of 1 means that at least one context has changed,
@@ -593,7 +595,8 @@ choose_guard_selection(const or_options_t *options,
"rest of the world.", (int)(exclude_frac * 100));
}
- /* Easy case: no previous selection */
+ /* Easy case: no previous selection. Just check if we are in restricted or
+ normal guard selection. */
if (old_selection == NULL) {
if (n_passing_filter >= meaningful_threshold_mid) {
*type_out = GS_TYPE_NORMAL;
@@ -768,8 +771,9 @@ entry_guard_add_to_sample(guard_selection_t *gs,
/**
* Backend: adds a new sampled guard to <b>gs</b>, with given identity,
- * nickname, and ORPort. rsa_id_digest and bridge_addrport are
- * optional, but we need one of them. nickname is optional.
+ * nickname, and ORPort. rsa_id_digest and bridge_addrport are optional, but
+ * we need one of them. nickname is optional. The caller is responsible for
+ * maintaining the size limit of the SAMPLED_GUARDS set.
*/
static entry_guard_t *
entry_guard_add_to_sample_impl(guard_selection_t *gs,
@@ -2171,7 +2175,8 @@ entry_guards_all_primary_guards_are_down(guard_selection_t *gs)
}
/** Wrapper for entry_guard_has_higher_priority that compares the
- * guard-priorities of a pair of circuits.
+ * guard-priorities of a pair of circuits. Return 1 if <b>a</b> has higher
+ * priority than <b>b</b>.
*
* If a restriction is provided in <b>rst</b>, then do not consider
* <b>a</b> to have higher priority if it violates the restriction.
@@ -4180,6 +4185,8 @@ choose_random_entry_impl(guard_selection_t *gs,
}
#endif
+/** Check the pathbias use success count of <b>node</b> and disable it if it
+ * goes over our thresholds. */
static void
pathbias_check_use_success_count(entry_guard_t *node)
{
@@ -4201,6 +4208,8 @@ pathbias_check_use_success_count(entry_guard_t *node)
}
}
+/** Check the pathbias close count of <b>node</b> and disable it if it goes
+ * over our thresholds. */
static void
pathbias_check_close_success_count(entry_guard_t *node)
{
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 3250be1..116e5ab 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -402,11 +402,14 @@ int entry_guard_pick_for_circuit(guard_selection_t *gs,
entry_guard_restriction_t *rst,
const node_t **chosen_node_out,
circuit_guard_state_t **guard_state_out);
+
+/* We just connected to an entry guard. What should we do with the circuit? */
typedef enum {
- GUARD_USABLE_NEVER = -1,
- GUARD_MAYBE_USABLE_LATER = 0,
- GUARD_USABLE_NOW = 1,
+ GUARD_USABLE_NEVER = -1, /* Never use the circuit */
+ GUARD_MAYBE_USABLE_LATER = 0, /* Keep it. We might use it in the future */
+ GUARD_USABLE_NOW = 1, /* Use it right now */
} guard_usable_t;
+
guard_usable_t entry_guard_succeeded(circuit_guard_state_t **guard_state_p);
void entry_guard_failed(circuit_guard_state_t **guard_state_p);
void entry_guard_cancel(circuit_guard_state_t **guard_state_p);
[View Less]
1
0