diff options
Diffstat (limited to 'src/feature')
-rw-r--r-- | src/feature/control/control_getinfo.c | 17 | ||||
-rw-r--r-- | src/feature/nodelist/node_select.c | 152 | ||||
-rw-r--r-- | src/feature/nodelist/node_select.h | 28 | ||||
-rw-r--r-- | src/feature/nodelist/node_st.h | 5 | ||||
-rw-r--r-- | src/feature/nodelist/nodelist.c | 76 | ||||
-rw-r--r-- | src/feature/nodelist/nodelist.h | 16 | ||||
-rw-r--r-- | src/feature/nodelist/routerinfo.c | 35 | ||||
-rw-r--r-- | src/feature/nodelist/routerinfo.h | 5 | ||||
-rw-r--r-- | src/feature/nodelist/routerlist.c | 150 | ||||
-rw-r--r-- | src/feature/nodelist/routerlist.h | 14 | ||||
-rw-r--r-- | src/feature/relay/relay_periodic.c | 4 | ||||
-rw-r--r-- | src/feature/relay/router.c | 21 | ||||
-rw-r--r-- | src/feature/relay/selftest.c | 231 | ||||
-rw-r--r-- | src/feature/relay/selftest.h | 10 | ||||
-rw-r--r-- | src/feature/stats/predict_ports.c | 4 |
15 files changed, 524 insertions, 244 deletions
diff --git a/src/feature/control/control_getinfo.c b/src/feature/control/control_getinfo.c index 0823acbe07..c2557e164c 100644 --- a/src/feature/control/control_getinfo.c +++ b/src/feature/control/control_getinfo.c @@ -1278,15 +1278,18 @@ getinfo_helper_events(control_connection_t *control_conn, *answer = tor_strdup(directories_have_accepted_server_descriptor() ? "1" : "0"); } else if (!strcmp(question, "status/reachability-succeeded/or")) { - *answer = tor_strdup(check_whether_orport_reachable(options) ? - "1" : "0"); + *answer = tor_strdup( + router_should_skip_orport_reachability_check(options) ? + "1" : "0"); } else if (!strcmp(question, "status/reachability-succeeded/dir")) { - *answer = tor_strdup(check_whether_dirport_reachable(options) ? - "1" : "0"); + *answer = tor_strdup( + router_should_skip_dirport_reachability_check(options) ? + "1" : "0"); } else if (!strcmp(question, "status/reachability-succeeded")) { - tor_asprintf(answer, "OR=%d DIR=%d", - check_whether_orport_reachable(options) ? 1 : 0, - check_whether_dirport_reachable(options) ? 1 : 0); + tor_asprintf( + answer, "OR=%d DIR=%d", + router_should_skip_orport_reachability_check(options) ? 1 : 0, + router_should_skip_dirport_reachability_check(options) ? 1 : 0); } else if (!strcmp(question, "status/bootstrap-phase")) { *answer = control_event_boot_last_msg(); } else if (!strcmpstart(question, "status/version/")) { diff --git a/src/feature/nodelist/node_select.c b/src/feature/nodelist/node_select.c index e831248413..25904d4c63 100644 --- a/src/feature/nodelist/node_select.c +++ b/src/feature/nodelist/node_select.c @@ -321,8 +321,12 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags, overloaded_direct = smartlist_new(); overloaded_tunnel = smartlist_new(); - const int skip_or_fw = router_skip_or_reachability(options, try_ip_pref); - const int skip_dir_fw = router_skip_dir_reachability(options, try_ip_pref); + const int skip_or_fw = router_or_conn_should_skip_reachable_address_check( + options, + try_ip_pref); + const int skip_dir_fw = router_dir_conn_should_skip_reachable_address_check( + options, + try_ip_pref); const int must_have_or = dirclient_must_use_begindir(options); /* Find all the running dirservers we know about. */ @@ -926,64 +930,67 @@ nodelist_subtract(smartlist_t *sl, const smartlist_t *excluded) bitarray_free(excluded_idx); } -/** Return a random running node from the nodelist. Never - * pick a node that is in - * <b>excludedsmartlist</b>, or which matches <b>excludedset</b>, - * even if they are the only nodes available. - * If <b>CRN_NEED_UPTIME</b> is set in flags and any router has more than - * a minimum uptime, return one of those. - * If <b>CRN_NEED_CAPACITY</b> is set in flags, weight your choice by the - * advertised capacity of each router. - * If <b>CRN_NEED_GUARD</b> is set in flags, consider only Guard routers. - * If <b>CRN_WEIGHT_AS_EXIT</b> is set in flags, we weight bandwidths as if - * picking an exit node, otherwise we weight bandwidths for picking a relay - * node (that is, possibly discounting exit nodes). - * If <b>CRN_NEED_DESC</b> is set in flags, we only consider nodes that - * have a routerinfo or microdescriptor -- that is, enough info to be - * used to build a circuit. - * If <b>CRN_PREF_ADDR</b> is set in flags, we only consider nodes that - * have an address that is preferred by the ClientPreferIPv6ORPort setting - * (regardless of this flag, we exclude nodes that aren't allowed by the - * firewall, including ClientUseIPv4 0 and fascist_firewall_use_ipv6() == 0). +/* Node selection helper for router_choose_random_node(). + * + * Populates a node list based on <b>flags</b>, ignoring nodes in + * <b>excludednodes</b> and <b>excludedset</b>. Chooses the node based on + * <b>rule</b>. */ +static const node_t * +router_choose_random_node_helper(smartlist_t *excludednodes, + routerset_t *excludedset, + router_crn_flags_t flags, + bandwidth_weight_rule_t rule) +{ + smartlist_t *sl=smartlist_new(); + const node_t *choice = NULL; + + router_add_running_nodes_to_smartlist(sl, flags); + log_debug(LD_CIRC, + "We found %d running nodes.", + smartlist_len(sl)); + + nodelist_subtract(sl, excludednodes); + + if (excludedset) { + routerset_subtract_nodes(sl,excludedset); + log_debug(LD_CIRC, + "We removed excludedset, leaving %d nodes.", + smartlist_len(sl)); + } + + // Always weight by bandwidth + choice = node_sl_choose_by_bandwidth(sl, rule); + + smartlist_free(sl); + + return choice; +} + +/** Return a random running node from the nodelist. Never pick a node that is + * in <b>excludedsmartlist</b>, or which matches <b>excludedset</b>, even if + * they are the only nodes available. + * + * <b>flags</b> is a set of CRN_* flags, see + * router_add_running_nodes_to_smartlist() for details. */ const node_t * router_choose_random_node(smartlist_t *excludedsmartlist, routerset_t *excludedset, router_crn_flags_t flags) -{ /* XXXX MOVE */ - const int need_uptime = (flags & CRN_NEED_UPTIME) != 0; - const int need_capacity = (flags & CRN_NEED_CAPACITY) != 0; - const int need_guard = (flags & CRN_NEED_GUARD) != 0; - const int weight_for_exit = (flags & CRN_WEIGHT_AS_EXIT) != 0; - const int need_desc = (flags & CRN_NEED_DESC) != 0; - const int pref_addr = (flags & CRN_PREF_ADDR) != 0; - const int direct_conn = (flags & CRN_DIRECT_CONN) != 0; - const int rendezvous_v3 = (flags & CRN_RENDEZVOUS_V3) != 0; - - const smartlist_t *node_list = nodelist_get_list(); - smartlist_t *sl=smartlist_new(), - *excludednodes=smartlist_new(); +{ + /* A limited set of flags, used for fallback node selection. + */ + const bool need_uptime = (flags & CRN_NEED_UPTIME) != 0; + const bool need_capacity = (flags & CRN_NEED_CAPACITY) != 0; + const bool need_guard = (flags & CRN_NEED_GUARD) != 0; + const bool pref_addr = (flags & CRN_PREF_ADDR) != 0; + + smartlist_t *excludednodes=smartlist_new(); const node_t *choice = NULL; const routerinfo_t *r; bandwidth_weight_rule_t rule; - tor_assert(!(weight_for_exit && need_guard)); - rule = weight_for_exit ? WEIGHT_FOR_EXIT : - (need_guard ? WEIGHT_FOR_GUARD : WEIGHT_FOR_MID); - - SMARTLIST_FOREACH_BEGIN(node_list, const node_t *, node) { - if (node_allows_single_hop_exits(node)) { - /* Exclude relays that allow single hop exit circuits. This is an - * obsolete option since 0.2.9.2-alpha and done by default in - * 0.3.1.0-alpha. */ - smartlist_add(excludednodes, (node_t*)node); - } else if (rendezvous_v3 && - !node_supports_v3_rendezvous_point(node)) { - /* Exclude relays that do not support to rendezvous for a hidden service - * version 3. */ - smartlist_add(excludednodes, (node_t*)node); - } - } SMARTLIST_FOREACH_END(node); + rule = (need_guard ? WEIGHT_FOR_GUARD : WEIGHT_FOR_MID); /* If the node_t is not found we won't be to exclude ourself but we * won't be able to pick ourself in router_choose_random_node() so @@ -991,41 +998,30 @@ router_choose_random_node(smartlist_t *excludedsmartlist, if ((r = router_get_my_routerinfo())) routerlist_add_node_and_family(excludednodes, r); - router_add_running_nodes_to_smartlist(sl, need_uptime, need_capacity, - need_guard, need_desc, pref_addr, - direct_conn); - log_debug(LD_CIRC, - "We found %d running nodes.", - smartlist_len(sl)); - if (excludedsmartlist) { smartlist_add_all(excludednodes, excludedsmartlist); } - nodelist_subtract(sl, excludednodes); - if (excludedset) { - routerset_subtract_nodes(sl,excludedset); - log_debug(LD_CIRC, - "We removed excludedset, leaving %d nodes.", - smartlist_len(sl)); - } + choice = router_choose_random_node_helper(excludednodes, + excludedset, + flags, + rule); - // Always weight by bandwidth - choice = node_sl_choose_by_bandwidth(sl, rule); - - smartlist_free(sl); if (!choice && (need_uptime || need_capacity || need_guard || pref_addr)) { - /* try once more -- recurse but with fewer restrictions. */ + /* try once more, with fewer restrictions. */ log_info(LD_CIRC, - "We couldn't find any live%s%s%s routers; falling back " + "We couldn't find any live%s%s%s%s routers; falling back " "to list of all routers.", need_capacity?", fast":"", need_uptime?", stable":"", - need_guard?", guard":""); + need_guard?", guard":"", + pref_addr?", preferred address":""); flags &= ~ (CRN_NEED_UPTIME|CRN_NEED_CAPACITY|CRN_NEED_GUARD| CRN_PREF_ADDR); - choice = router_choose_random_node( - excludedsmartlist, excludedset, flags); + choice = router_choose_random_node_helper(excludednodes, + excludedset, + flags, + rule); } smartlist_free(excludednodes); if (!choice) { @@ -1120,8 +1116,12 @@ router_pick_trusteddirserver_impl(const smartlist_t *sourcelist, overloaded_direct = smartlist_new(); overloaded_tunnel = smartlist_new(); - const int skip_or_fw = router_skip_or_reachability(options, try_ip_pref); - const int skip_dir_fw = router_skip_dir_reachability(options, try_ip_pref); + const int skip_or_fw = router_or_conn_should_skip_reachable_address_check( + options, + try_ip_pref); + const int skip_dir_fw = router_dir_conn_should_skip_reachable_address_check( + options, + try_ip_pref); const int must_have_or = dirclient_must_use_begindir(options); SMARTLIST_FOREACH_BEGIN(sourcelist, const dir_server_t *, d) diff --git a/src/feature/nodelist/node_select.h b/src/feature/nodelist/node_select.h index 2e67f990f6..1776d8ea1a 100644 --- a/src/feature/nodelist/node_select.h +++ b/src/feature/nodelist/node_select.h @@ -14,20 +14,26 @@ /** Flags to be passed to control router_choose_random_node() to indicate what * kind of nodes to pick according to what algorithm. */ typedef enum router_crn_flags_t { + /* Try to choose stable nodes. */ CRN_NEED_UPTIME = 1<<0, + /* Try to choose nodes with a reasonable amount of bandwidth. */ CRN_NEED_CAPACITY = 1<<1, - CRN_NEED_GUARD = 1<<2, - /* XXXX not used, apparently. */ - CRN_WEIGHT_AS_EXIT = 1<<5, - CRN_NEED_DESC = 1<<6, - /* On clients, only provide nodes that satisfy ClientPreferIPv6OR */ - CRN_PREF_ADDR = 1<<7, + /* Only choose nodes if we have downloaded their descriptor or + * microdescriptor. */ + CRN_NEED_DESC = 1<<2, + /* Choose nodes that can be used as Guard relays. */ + CRN_NEED_GUARD = 1<<3, /* On clients, only provide nodes that we can connect to directly, based on - * our firewall rules */ - CRN_DIRECT_CONN = 1<<8, - /* On clients, only provide nodes with HSRend >= 2 protocol version which - * is required for hidden service version >= 3. */ - CRN_RENDEZVOUS_V3 = 1<<9, + * our firewall rules. */ + CRN_DIRECT_CONN = 1<<4, + /* On clients, if choosing a node for a direct connection, only provide + * nodes that satisfy ClientPreferIPv6OR. */ + CRN_PREF_ADDR = 1<<5, + /* On clients, only provide nodes with HSRend=2 protocol version which + * is required for hidden service version 3. */ + CRN_RENDEZVOUS_V3 = 1<<6, + /* On clients, only provide nodes that can initiate IPv6 extends. */ + CRN_INITIATE_IPV6_EXTEND = 1<<7, } router_crn_flags_t; /** Possible ways to weight routers when choosing one randomly. See diff --git a/src/feature/nodelist/node_st.h b/src/feature/nodelist/node_st.h index b1ec4db202..3769f9dc84 100644 --- a/src/feature/nodelist/node_st.h +++ b/src/feature/nodelist/node_st.h @@ -84,12 +84,11 @@ struct node_t { /* Local info: derived. */ - /** True if the IPv6 OR port is preferred over the IPv4 OR port. - * XX/teor - can this become out of date if the torrc changes? */ + /** True if the IPv6 OR port is preferred over the IPv4 OR port. */ unsigned int ipv6_preferred:1; /** According to the geoip db what country is this router in? */ - /* XXXprop186 what is this suppose to mean with multiple OR ports? */ + /* IPv6: what is this supposed to mean with multiple OR ports? */ country_t country; /* The below items are used only by authdirservers for diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c index 7454f342f9..6b2c0d2016 100644 --- a/src/feature/nodelist/nodelist.c +++ b/src/feature/nodelist/nodelist.c @@ -1133,7 +1133,7 @@ node_ed25519_id_matches(const node_t *node, const ed25519_public_key_t *id) /** Dummy object that should be unreturnable. Used to ensure that * node_get_protover_summary_flags() always returns non-NULL. */ static const protover_summary_flags_t zero_protover_flags = { - 0,0,0,0,0,0,0,0,0 + 0,0,0,0,0,0,0,0,0,0,0,0 }; /** Return the protover_summary_flags for a given node. */ @@ -1158,9 +1158,9 @@ node_get_protover_summary_flags(const node_t *node) * by ed25519 ID during the link handshake. If <b>compatible_with_us</b>, * it needs to be using a link authentication method that we understand. * If not, any plausible link authentication method will do. */ -MOCK_IMPL(int, +MOCK_IMPL(bool, node_supports_ed25519_link_authentication,(const node_t *node, - int compatible_with_us)) + bool compatible_with_us)) { if (! node_get_ed25519_id(node)) return 0; @@ -1175,7 +1175,7 @@ node_supports_ed25519_link_authentication,(const node_t *node, /** Return true iff <b>node</b> supports the hidden service directory version * 3 protocol (proposal 224). */ -int +bool node_supports_v3_hsdir(const node_t *node) { tor_assert(node); @@ -1185,7 +1185,7 @@ node_supports_v3_hsdir(const node_t *node) /** Return true iff <b>node</b> supports ed25519 authentication as an hidden * service introduction point.*/ -int +bool node_supports_ed25519_hs_intro(const node_t *node) { tor_assert(node); @@ -1193,9 +1193,24 @@ node_supports_ed25519_hs_intro(const node_t *node) return node_get_protover_summary_flags(node)->supports_ed25519_hs_intro; } +/** Return true iff <b>node</b> can be a rendezvous point for hidden + * service version 3 (HSRend=2). */ +bool +node_supports_v3_rendezvous_point(const node_t *node) +{ + tor_assert(node); + + /* We can't use a v3 rendezvous point without the curve25519 onion pk. */ + if (!node_get_curve25519_onion_key(node)) { + return 0; + } + + return node_get_protover_summary_flags(node)->supports_v3_rendezvous_point; +} + /** Return true iff <b>node</b> supports the DoS ESTABLISH_INTRO cell * extenstion. */ -int +bool node_supports_establish_intro_dos_extension(const node_t *node) { tor_assert(node); @@ -1204,19 +1219,54 @@ node_supports_establish_intro_dos_extension(const node_t *node) supports_establish_intro_dos_extension; } -/** Return true iff <b>node</b> supports to be a rendezvous point for hidden - * service version 3 (HSRend=2). */ -int -node_supports_v3_rendezvous_point(const node_t *node) +/** Return true iff <b>node</b> can initiate IPv6 extends (Relay=3). + * + * This check should only be performed by client path selection code. + * + * Extending relays should check their own IPv6 support using + * router_can_extend_over_ipv6(). Like other extends, they should not verify + * the link specifiers in the extend cell against the consensus, because it + * may be out of date. */ +bool +node_supports_initiating_ipv6_extends(const node_t *node) { tor_assert(node); - /* We can't use a v3 rendezvous point without the curve25519 onion pk. */ - if (!node_get_curve25519_onion_key(node)) { + /* Relays can't initiate an IPv6 extend, unless they have an IPv6 ORPort. */ + if (!node_has_ipv6_orport(node)) { return 0; } - return node_get_protover_summary_flags(node)->supports_v3_rendezvous_point; + /* Initiating relays also need to support the relevant protocol version. */ + return + node_get_protover_summary_flags(node)->supports_initiating_ipv6_extends; +} + +/** Return true iff <b>node</b> can accept IPv6 extends (Relay=2 or Relay=3) + * from other relays. If <b>need_canonical_ipv6_conn</b> is true, also check + * if the relay supports canonical IPv6 connections (Relay=3 only). + * + * This check should only be performed by client path selection code. + */ +bool +node_supports_accepting_ipv6_extends(const node_t *node, + bool need_canonical_ipv6_conn) +{ + tor_assert(node); + + /* Relays can't accept an IPv6 extend, unless they have an IPv6 ORPort. */ + if (!node_has_ipv6_orport(node)) { + return 0; + } + + /* Accepting relays also need to support the relevant protocol version. */ + if (need_canonical_ipv6_conn) { + return + node_get_protover_summary_flags(node)->supports_canonical_ipv6_conns; + } else { + return + node_get_protover_summary_flags(node)->supports_accepting_ipv6_extends; + } } /** Return the RSA ID key's SHA1 digest for the provided node. */ diff --git a/src/feature/nodelist/nodelist.h b/src/feature/nodelist/nodelist.h index 57ab2d5913..4ba699d69d 100644 --- a/src/feature/nodelist/nodelist.h +++ b/src/feature/nodelist/nodelist.h @@ -74,13 +74,17 @@ MOCK_DECL(const struct ed25519_public_key_t *,node_get_ed25519_id, (const node_t *node)); int node_ed25519_id_matches(const node_t *node, const struct ed25519_public_key_t *id); -MOCK_DECL(int,node_supports_ed25519_link_authentication, +MOCK_DECL(bool,node_supports_ed25519_link_authentication, (const node_t *node, - int compatible_with_us)); -int node_supports_v3_hsdir(const node_t *node); -int node_supports_ed25519_hs_intro(const node_t *node); -int node_supports_v3_rendezvous_point(const node_t *node); -int node_supports_establish_intro_dos_extension(const node_t *node); + bool compatible_with_us)); +bool node_supports_v3_hsdir(const node_t *node); +bool node_supports_ed25519_hs_intro(const node_t *node); +bool node_supports_v3_rendezvous_point(const node_t *node); +bool node_supports_establish_intro_dos_extension(const node_t *node); +bool node_supports_initiating_ipv6_extends(const node_t *node); +bool node_supports_accepting_ipv6_extends(const node_t *node, + bool need_canonical_ipv6_conn); + const uint8_t *node_get_rsa_id_digest(const node_t *node); MOCK_DECL(smartlist_t *,node_get_link_specifier_smartlist,(const node_t *node, bool direct_conn)); diff --git a/src/feature/nodelist/routerinfo.c b/src/feature/nodelist/routerinfo.c index 0bf2a977f5..55f21dfe67 100644 --- a/src/feature/nodelist/routerinfo.c +++ b/src/feature/nodelist/routerinfo.c @@ -17,14 +17,37 @@ #include "feature/nodelist/node_st.h" #include "feature/nodelist/routerinfo_st.h" -/** Copy the primary (IPv4) OR port (IP address and TCP port) for - * <b>router</b> into *<b>ap_out</b>. */ -void -router_get_prim_orport(const routerinfo_t *router, tor_addr_port_t *ap_out) +/** Copy the OR port (IP address and TCP port) for <b>router</b> and + * <b>family</b> into *<b>ap_out</b>. + * + * If the requested ORPort does not exist, sets *<b>ap_out</b> to the null + * address and port, and returns -1. Otherwise, returns 0. */ +int +router_get_orport(const routerinfo_t *router, + tor_addr_port_t *ap_out, + int family) { tor_assert(ap_out != NULL); - tor_addr_from_ipv4h(&ap_out->addr, router->addr); - ap_out->port = router->or_port; + if (family == AF_INET) { + tor_addr_from_ipv4h(&ap_out->addr, router->addr); + ap_out->port = router->or_port; + return 0; + } else if (family == AF_INET6) { + /* IPv6 addresses are optional, so check if it is valid. */ + if (tor_addr_port_is_valid(&router->ipv6_addr, router->ipv6_orport, 0)) { + tor_addr_copy(&ap_out->addr, &router->ipv6_addr); + ap_out->port = router->ipv6_orport; + return 0; + } else { + tor_addr_port_make_null_ap(ap_out, AF_INET6); + return -1; + } + } else { + /* Unsupported address family */ + tor_assert_nonfatal_unreached(); + tor_addr_port_make_null_ap(ap_out, AF_UNSPEC); + return -1; + } } int diff --git a/src/feature/nodelist/routerinfo.h b/src/feature/nodelist/routerinfo.h index 604e478999..2e12cbeba3 100644 --- a/src/feature/nodelist/routerinfo.h +++ b/src/feature/nodelist/routerinfo.h @@ -12,8 +12,9 @@ #ifndef TOR_ROUTERINFO_H #define TOR_ROUTERINFO_H -void router_get_prim_orport(const routerinfo_t *router, - tor_addr_port_t *addr_port_out); +int router_get_orport(const routerinfo_t *router, + tor_addr_port_t *addr_port_out, + int family); int router_has_orport(const routerinfo_t *router, const tor_addr_port_t *orport); diff --git a/src/feature/nodelist/routerlist.c b/src/feature/nodelist/routerlist.c index 80c1aa6893..ece3379fa5 100644 --- a/src/feature/nodelist/routerlist.c +++ b/src/feature/nodelist/routerlist.c @@ -465,11 +465,20 @@ router_reload_router_list(void) return 0; } -/* When iterating through the routerlist, can OR address/port preference - * and reachability checks be skipped? +/* When selecting a router for a direct connection, can OR address/port + * preference and reachability checks be skipped? + * + * Servers never check ReachableAddresses or ClientPreferIPv6. Returns + * true for servers. + * + * Otherwise, if <b>try_ip_pref</b> is true, returns false. Used to make + * clients check ClientPreferIPv6, even if ReachableAddresses is not set. + * Finally, return true if ReachableAddresses is set. */ int -router_skip_or_reachability(const or_options_t *options, int try_ip_pref) +router_or_conn_should_skip_reachable_address_check( + const or_options_t *options, + int try_ip_pref) { /* Servers always have and prefer IPv4. * And if clients are checking against the firewall for reachability only, @@ -477,11 +486,15 @@ router_skip_or_reachability(const or_options_t *options, int try_ip_pref) return server_mode(options) || (!try_ip_pref && !firewall_is_fascist_or()); } -/* When iterating through the routerlist, can Dir address/port preference +/* When selecting a router for a direct connection, can Dir address/port * and reachability checks be skipped? + * + * This function is obsolete, because clients only use ORPorts. */ int -router_skip_dir_reachability(const or_options_t *options, int try_ip_pref) +router_dir_conn_should_skip_reachable_address_check( + const or_options_t *options, + int try_ip_pref) { /* Servers always have and prefer IPv4. * And if clients are checking against the firewall for reachability only, @@ -498,40 +511,109 @@ routers_have_same_or_addrs(const routerinfo_t *r1, const routerinfo_t *r2) r1->ipv6_orport == r2->ipv6_orport; } +/* Returns true if <b>node</b> can be chosen based on <b>flags</b>. + * + * The following conditions are applied to all nodes: + * - is running; + * - is valid; + * - supports EXTEND2 cells; + * - has an ntor circuit crypto key; and + * - does not allow single-hop exits. + * + * If the node has a routerinfo, we're checking for a direct connection, and + * we're using bridges, the following condition is applied: + * - has a bridge-purpose routerinfo; + * and for all other nodes: + * - has a general-purpose routerinfo (or no routerinfo). + * + * Nodes that don't have a routerinfo must be general-purpose nodes, because + * routerstatuses and microdescriptors only come via consensuses. + * + * The <b>flags</b> chech that <b>node</b>: + * - <b>CRN_NEED_UPTIME</b>: has more than a minimum uptime; + * - <b>CRN_NEED_CAPACITY</b>: has more than a minimum capacity; + * - <b>CRN_NEED_GUARD</b>: is a Guard; + * - <b>CRN_NEED_DESC</b>: has a routerinfo or microdescriptor -- that is, + * enough info to be used to build a circuit; + * - <b>CRN_DIRECT_CONN</b>: is suitable for direct connections. Checks + * for the relevant descriptors. Checks the address + * against ReachableAddresses, ClientUseIPv4 0, and + * fascist_firewall_use_ipv6() == 0); + * - <b>CRN_PREF_ADDR</b>: if we are connecting directly to the node, it has + * an address that is preferred by the + * ClientPreferIPv6ORPort setting; + * - <b>CRN_RENDEZVOUS_V3</b>: can become a v3 onion service rendezvous point; + * - <b>CRN_INITIATE_IPV6_EXTEND</b>: can initiate IPv6 extends. + */ +bool +router_can_choose_node(const node_t *node, int flags) +{ + /* The full set of flags used for node selection. */ + const bool need_uptime = (flags & CRN_NEED_UPTIME) != 0; + const bool need_capacity = (flags & CRN_NEED_CAPACITY) != 0; + const bool need_guard = (flags & CRN_NEED_GUARD) != 0; + const bool need_desc = (flags & CRN_NEED_DESC) != 0; + const bool pref_addr = (flags & CRN_PREF_ADDR) != 0; + const bool direct_conn = (flags & CRN_DIRECT_CONN) != 0; + const bool rendezvous_v3 = (flags & CRN_RENDEZVOUS_V3) != 0; + const bool initiate_ipv6_extend = (flags & CRN_INITIATE_IPV6_EXTEND) != 0; + + const or_options_t *options = get_options(); + const bool check_reach = + !router_or_conn_should_skip_reachable_address_check(options, pref_addr); + const bool direct_bridge = direct_conn && options->UseBridges; + + if (!node->is_running || !node->is_valid) + return false; + if (need_desc && !node_has_preferred_descriptor(node, direct_conn)) + return false; + if (node->ri) { + if (direct_bridge && node->ri->purpose != ROUTER_PURPOSE_BRIDGE) + return false; + else if (node->ri->purpose != ROUTER_PURPOSE_GENERAL) + return false; + } + if (node_is_unreliable(node, need_uptime, need_capacity, need_guard)) + return false; + /* Don't choose nodes if we are certain they can't do EXTEND2 cells */ + if (node->rs && !routerstatus_version_supports_extend2_cells(node->rs, 1)) + return false; + /* Don't choose nodes if we are certain they can't do ntor. */ + if ((node->ri || node->md) && !node_has_curve25519_onion_key(node)) + return false; + /* Exclude relays that allow single hop exit circuits. This is an + * obsolete option since 0.2.9.2-alpha and done by default in + * 0.3.1.0-alpha. */ + if (node_allows_single_hop_exits(node)) + return false; + /* Exclude relays that can not become a rendezvous for a hidden service + * version 3. */ + if (rendezvous_v3 && + !node_supports_v3_rendezvous_point(node)) + return false; + /* Choose a node with an OR address that matches the firewall rules */ + if (direct_conn && check_reach && + !fascist_firewall_allows_node(node, + FIREWALL_OR_CONNECTION, + pref_addr)) + return false; + if (initiate_ipv6_extend && !node_supports_initiating_ipv6_extends(node)) + return false; + + return true; +} + /** Add every suitable node from our nodelist to <b>sl</b>, so that - * we can pick a node for a circuit. + * we can pick a node for a circuit based on <b>flags</b>. + * + * See router_can_choose_node() for details of <b>flags</b>. */ void -router_add_running_nodes_to_smartlist(smartlist_t *sl, int need_uptime, - int need_capacity, int need_guard, - int need_desc, int pref_addr, - int direct_conn) -{ - const int check_reach = !router_skip_or_reachability(get_options(), - pref_addr); - /* XXXX MOVE */ +router_add_running_nodes_to_smartlist(smartlist_t *sl, int flags) +{ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) { - if (!node->is_running || !node->is_valid) - continue; - if (need_desc && !node_has_preferred_descriptor(node, direct_conn)) - continue; - if (node->ri && node->ri->purpose != ROUTER_PURPOSE_GENERAL) + if (!router_can_choose_node(node, flags)) continue; - if (node_is_unreliable(node, need_uptime, need_capacity, need_guard)) - continue; - /* Don't choose nodes if we are certain they can't do EXTEND2 cells */ - if (node->rs && !routerstatus_version_supports_extend2_cells(node->rs, 1)) - continue; - /* Don't choose nodes if we are certain they can't do ntor. */ - if ((node->ri || node->md) && !node_has_curve25519_onion_key(node)) - continue; - /* Choose a node with an OR address that matches the firewall rules */ - if (direct_conn && check_reach && - !fascist_firewall_allows_node(node, - FIREWALL_OR_CONNECTION, - pref_addr)) - continue; - smartlist_add(sl, (void *)node); } SMARTLIST_FOREACH_END(node); } diff --git a/src/feature/nodelist/routerlist.h b/src/feature/nodelist/routerlist.h index 81a2343540..98472b2771 100644 --- a/src/feature/nodelist/routerlist.h +++ b/src/feature/nodelist/routerlist.h @@ -50,14 +50,16 @@ typedef enum was_router_added_t { int router_reload_router_list(void); -int router_skip_or_reachability(const or_options_t *options, int try_ip_pref); -int router_skip_dir_reachability(const or_options_t *options, int try_ip_pref); +int router_or_conn_should_skip_reachable_address_check( + const or_options_t *options, + int try_ip_pref); +int router_dir_conn_should_skip_reachable_address_check( + const or_options_t *options, + int try_ip_pref); void router_reset_status_download_failures(void); int routers_have_same_or_addrs(const routerinfo_t *r1, const routerinfo_t *r2); -void router_add_running_nodes_to_smartlist(smartlist_t *sl, int need_uptime, - int need_capacity, int need_guard, - int need_desc, int pref_addr, - int direct_conn); +bool router_can_choose_node(const node_t *node, int flags); +void router_add_running_nodes_to_smartlist(smartlist_t *sl, int flags); const routerinfo_t *routerlist_find_my_routerinfo(void); uint32_t router_get_advertised_bandwidth(const routerinfo_t *router); diff --git a/src/feature/relay/relay_periodic.c b/src/feature/relay/relay_periodic.c index 08ad110cf6..6a92f49d2e 100644 --- a/src/feature/relay/relay_periodic.c +++ b/src/feature/relay/relay_periodic.c @@ -201,7 +201,7 @@ reachability_warnings_callback(time_t now, const or_options_t *options) have_completed_a_circuit()) { /* every 20 minutes, check and complain if necessary */ const routerinfo_t *me = router_get_my_routerinfo(); - if (me && !check_whether_orport_reachable(options)) { + if (me && !router_should_skip_orport_reachability_check(options)) { char *address = tor_dup_ip(me->addr); if (address) { log_warn(LD_CONFIG, @@ -217,7 +217,7 @@ reachability_warnings_callback(time_t now, const or_options_t *options) } } - if (me && !check_whether_dirport_reachable(options)) { + if (me && !router_should_skip_dirport_reachability_check(options)) { char *address = tor_dup_ip(me->addr); if (address) { log_warn(LD_CONFIG, diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c index 34d8163c36..6914946729 100644 --- a/src/feature/relay/router.c +++ b/src/feature/relay/router.c @@ -1363,14 +1363,14 @@ decide_if_publishable_server(void) return 1; if (!router_get_advertised_or_port(options)) return 0; - if (!check_whether_orport_reachable(options)) + if (!router_should_skip_orport_reachability_check(options)) return 0; if (router_have_consensus_path() == CONSENSUS_PATH_INTERNAL) { /* All set: there are no exits in the consensus (maybe this is a tiny * test network), so we can't check our DirPort reachability. */ return 1; } else { - return check_whether_dirport_reachable(options); + return router_should_skip_dirport_reachability_check(options); } } @@ -1501,7 +1501,22 @@ router_has_advertised_ipv6_orport(const or_options_t *options) return tor_addr_port_is_valid_ap(&ipv6_ap, 0); } -/** Returns true if this router has an advertised IPv6 ORPort. */ +/** Returns true if this router can extend over IPv6. + * + * This check should only be performed by relay extend code. + * + * Clients should check if relays can initiate and accept IPv6 extends using + * node_supports_initiating_ipv6_extends() and + * node_supports_accepting_ipv6_extends(). + * + * As with other extends, relays should assume the client has already + * performed the relevant checks for the next hop. (Otherwise, relays that + * have just added IPv6 ORPorts won't be able to self-test those ORPorts.) + * + * Accepting relays don't need to perform any IPv6-specific checks before + * accepting a connection, because having an IPv6 ORPort implies support for + * the relevant protocol version. + */ MOCK_IMPL(bool, router_can_extend_over_ipv6,(const or_options_t *options)) { diff --git a/src/feature/relay/selftest.c b/src/feature/relay/selftest.c index 18fe25b989..2b0fc951b7 100644 --- a/src/feature/relay/selftest.c +++ b/src/feature/relay/selftest.c @@ -15,24 +15,31 @@ #include "core/or/or.h" #include "app/config/config.h" + #include "core/mainloop/connection.h" #include "core/mainloop/mainloop.h" #include "core/mainloop/netstatus.h" + #include "core/or/circuitbuild.h" #include "core/or/circuitlist.h" #include "core/or/circuituse.h" #include "core/or/crypt_path_st.h" +#include "core/or/extend_info_st.h" #include "core/or/origin_circuit_st.h" #include "core/or/relay.h" + #include "feature/control/control_events.h" + #include "feature/dirclient/dirclient.h" #include "feature/dircommon/directory.h" + #include "feature/nodelist/authority_cert_st.h" #include "feature/nodelist/routerinfo.h" #include "feature/nodelist/routerinfo_st.h" #include "feature/nodelist/routerlist.h" // but... #include "feature/nodelist/routerset.h" #include "feature/nodelist/torcert.h" + #include "feature/relay/relay_periodic.h" #include "feature/relay/router.h" #include "feature/relay/selftest.h" @@ -70,7 +77,7 @@ router_reachability_checks_disabled(const or_options_t *options) * - the network is disabled. */ int -check_whether_orport_reachable(const or_options_t *options) +router_should_skip_orport_reachability_check(const or_options_t *options) { int reach_checks_disabled = router_reachability_checks_disabled(options); return reach_checks_disabled || @@ -87,7 +94,7 @@ check_whether_orport_reachable(const or_options_t *options) * - the network is disabled. */ int -check_whether_dirport_reachable(const or_options_t *options) +router_should_skip_dirport_reachability_check(const or_options_t *options) { int reach_checks_disabled = router_reachability_checks_disabled(options) || !options->DirPort_set; @@ -107,6 +114,7 @@ router_should_check_reachability(int test_or, int test_dir) if (!me) return 0; + /* Doesn't check our IPv6 address, see #34065. */ if (routerset_contains_router(options->ExcludeNodes, me, -1) && options->StrictNodes) { /* If we've excluded ourself, and StrictNodes is set, we can't test @@ -126,18 +134,28 @@ router_should_check_reachability(int test_or, int test_dir) } /** Allocate and return a new extend_info_t that can be used to build - * a circuit to or through the router <b>r</b>. Uses the primary - * address of the router, so should only be called on a server. */ + * a circuit to or through the router <b>r</b>, using an address from + * <b>family</b> (if available). + * + * Clients don't have routerinfos, so this function should only be called on a + * server. + * + * If the requested address is not available, returns NULL. */ static extend_info_t * -extend_info_from_router(const routerinfo_t *r) +extend_info_from_router(const routerinfo_t *r, int family) { crypto_pk_t *rsa_pubkey; extend_info_t *info; tor_addr_port_t ap; - tor_assert(r); - /* Make sure we don't need to check address reachability */ - tor_assert_nonfatal(router_skip_or_reachability(get_options(), 0)); + if (BUG(!r)) { + return NULL; + } + + /* Relays always assume that the first hop is reachable. They ignore + * ReachableAddresses. */ + tor_assert_nonfatal(router_or_conn_should_skip_reachable_address_check( + get_options(), 0)); const ed25519_public_key_t *ed_id_key; if (r->cache_info.signing_key_cert) @@ -145,7 +163,10 @@ extend_info_from_router(const routerinfo_t *r) else ed_id_key = NULL; - router_get_prim_orport(r, &ap); + if (router_get_orport(r, &ap, family) < 0) { + /* We don't have an ORPort for the requested family. */ + return NULL; + } rsa_pubkey = router_get_rsa_onion_pkey(r->onion_pkey, r->onion_pkey_len); info = extend_info_new(r->nickname, r->cache_info.identity_digest, ed_id_key, @@ -155,6 +176,69 @@ extend_info_from_router(const routerinfo_t *r) return info; } +/** Launch a self-testing circuit to one of our ORPorts, using an address from + * <b>family</b> (if available). The circuit can be used to test reachability + * or bandwidth. <b>me</b> is our own routerinfo. + * + * Logs an info-level status message. If <b>orport_reachable</b> is false, + * call it a reachability circuit. Otherwise, call it a bandwidth circuit. + * + * See router_do_reachability_checks() for details. */ +static void +router_do_orport_reachability_checks(const routerinfo_t *me, + int family, + int orport_reachable) +{ + extend_info_t *ei = extend_info_from_router(me, family); + int ipv6_flags = (family == AF_INET6 ? CIRCLAUNCH_IS_IPV6_SELFTEST : 0); + + /* If we're trying to test IPv6, but we don't have an IPv6 ORPort, ei will + * be NULL. */ + if (ei) { + const char *family_name = fmt_af_family(family); + log_info(LD_CIRC, "Testing %s of my %s ORPort: %s.", + !orport_reachable ? "reachability" : "bandwidth", + family_name, fmt_addrport(&ei->addr, ei->port)); + circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei, + CIRCLAUNCH_NEED_CAPACITY| + CIRCLAUNCH_IS_INTERNAL| + ipv6_flags); + extend_info_free(ei); + } +} + +/** Launch a self-testing circuit, and ask an exit to connect to our DirPort. + * <b>me</b> is our own routerinfo. + * + * Relays don't advertise IPv6 DirPorts, so this function only supports IPv4. + * + * See router_do_reachability_checks() for details. */ +static void +router_do_dirport_reachability_checks(const routerinfo_t *me) +{ + tor_addr_port_t my_dirport; + tor_addr_from_ipv4h(&my_dirport.addr, me->addr); + my_dirport.port = me->dir_port; + + /* If there is already a pending connection, don't open another one. */ + if (!connection_get_by_type_addr_port_purpose( + CONN_TYPE_DIR, + &my_dirport.addr, my_dirport.port, + DIR_PURPOSE_FETCH_SERVERDESC)) { + /* ask myself, via tor, for my server descriptor. */ + directory_request_t *req = + directory_request_new(DIR_PURPOSE_FETCH_SERVERDESC); + directory_request_set_dir_addr_port(req, &my_dirport); + directory_request_set_directory_id_digest(req, + me->cache_info.identity_digest); + /* ask via an anon circuit, connecting to our dirport. */ + directory_request_set_indirection(req, DIRIND_ANON_DIRPORT); + directory_request_set_resource(req, "authority.z"); + directory_initiate_request(req); + directory_request_free(req); + } +} + /** Some time has passed, or we just got new directory information. * See if we currently believe our ORPort or DirPort to be * unreachable. If so, launch a new test for it. @@ -171,83 +255,89 @@ router_do_reachability_checks(int test_or, int test_dir) { const routerinfo_t *me = router_get_my_routerinfo(); const or_options_t *options = get_options(); - int orport_reachable = check_whether_orport_reachable(options); - tor_addr_t addr; + int orport_reachable = router_should_skip_orport_reachability_check(options); if (router_should_check_reachability(test_or, test_dir)) { if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) { - extend_info_t *ei = extend_info_from_router(me); - /* XXX IPv6 self testing */ - log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.", - !orport_reachable ? "reachability" : "bandwidth", - fmt_addr32(me->addr), me->or_port); - circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei, - CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL); - extend_info_free(ei); + /* At the moment, tor relays believe that they are reachable when they + * receive any create cell on an inbound connection. We'll do separate + * IPv4 and IPv6 reachability checks in #34067, and make them more + * precise. */ + router_do_orport_reachability_checks(me, AF_INET, orport_reachable); + router_do_orport_reachability_checks(me, AF_INET6, orport_reachable); } - /* XXX IPv6 self testing */ - tor_addr_from_ipv4h(&addr, me->addr); - if (test_dir && !check_whether_dirport_reachable(options) && - !connection_get_by_type_addr_port_purpose( - CONN_TYPE_DIR, &addr, me->dir_port, - DIR_PURPOSE_FETCH_SERVERDESC)) { - tor_addr_port_t my_orport, my_dirport; - memcpy(&my_orport.addr, &addr, sizeof(addr)); - memcpy(&my_dirport.addr, &addr, sizeof(addr)); - my_orport.port = me->or_port; - my_dirport.port = me->dir_port; - /* ask myself, via tor, for my server descriptor. */ - directory_request_t *req = - directory_request_new(DIR_PURPOSE_FETCH_SERVERDESC); - directory_request_set_or_addr_port(req, &my_orport); - directory_request_set_dir_addr_port(req, &my_dirport); - directory_request_set_directory_id_digest(req, - me->cache_info.identity_digest); - // ask via an anon circuit, connecting to our dirport. - directory_request_set_indirection(req, DIRIND_ANON_DIRPORT); - directory_request_set_resource(req, "authority.z"); - directory_initiate_request(req); - directory_request_free(req); + if (test_dir && !router_should_skip_dirport_reachability_check(options)) { + router_do_dirport_reachability_checks(me); } } } -/** We've decided to start our reachability testing. If all - * is set, log this to the user. Return 1 if we did, or 0 if - * we chose not to log anything. */ +/** If reachability testing is in progress, let the user know that it's + * happening. + * + * If all is set, log a notice-level message. Return 1 if we did, or 0 if + * we chose not to log anything, because we were unable to test reachability. + */ int inform_testing_reachability(void) { - char dirbuf[128]; - char *address; + char ipv4_or_buf[TOR_ADDRPORT_BUF_LEN]; + char ipv6_or_buf[TOR_ADDRPORT_BUF_LEN]; + char ipv4_dir_buf[TOR_ADDRPORT_BUF_LEN]; + + /* There's a race condition here, between: + * - tor launching reachability tests, + * - any circuits actually completing, + * - routerinfo updates, and + * - these log messages. + * In rare cases, we might log the wrong ports, log when we didn't actually + * start reachability tests, or fail to log after we actually started + * reachability tests. + * + * After we separate the IPv4 and IPv6 reachability flags in #34067, tor + * will test any IPv6 address that it discovers after launching reachability + * checks. We'll deal with late disabled IPv6 ORPorts and IPv4 DirPorts, and + * extra or skipped log messages in #34137. + */ const routerinfo_t *me = router_get_my_routerinfo(); if (!me) return 0; - address = tor_dup_ip(me->addr); - if (!address) - return 0; - + /* IPv4 ORPort */ + strlcpy(ipv4_or_buf, fmt_addr32_port(me->addr, me->or_port), + sizeof(ipv4_or_buf)); control_event_server_status(LOG_NOTICE, - "CHECKING_REACHABILITY ORADDRESS=%s:%d", - address, me->or_port); + "CHECKING_REACHABILITY ORADDRESS=%s", + ipv4_or_buf); + /* IPv6 ORPort */ + const bool has_ipv6 = tor_addr_port_is_valid(&me->ipv6_addr, + me->ipv6_orport, 0); + if (has_ipv6) { + strlcpy(ipv6_or_buf, fmt_addrport(&me->ipv6_addr, me->ipv6_orport), + sizeof(ipv6_or_buf)); + /* We'll add an IPv6 control event in #34068. */ + } + /* IPv4 DirPort (there are no advertised IPv6 DirPorts) */ if (me->dir_port) { - tor_snprintf(dirbuf, sizeof(dirbuf), " and DirPort %s:%d", - address, me->dir_port); + strlcpy(ipv4_dir_buf, fmt_addr32_port(me->addr, me->dir_port), + sizeof(ipv4_dir_buf)); control_event_server_status(LOG_NOTICE, - "CHECKING_REACHABILITY DIRADDRESS=%s:%d", - address, me->dir_port); + "CHECKING_REACHABILITY DIRADDRESS=%s", + ipv4_dir_buf); } - log_notice(LD_OR, "Now checking whether ORPort %s:%d%s %s reachable... " - "(this may take up to %d minutes -- look for log " - "messages indicating success)", - address, me->or_port, - me->dir_port ? dirbuf : "", - me->dir_port ? "are" : "is", - TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT/60); - - tor_free(address); + log_notice(LD_OR, "Now checking whether ORPort%s %s%s%s%s%s %s reachable... " + "(this may take up to %d minutes -- look for log " + "messages indicating success)", + has_ipv6 ? "s" : "", + ipv4_or_buf, + has_ipv6 ? " and " : "", + has_ipv6 ? ipv6_or_buf : "", + me->dir_port ? " and DirPort " : "", + me->dir_port ? ipv4_dir_buf : "", + has_ipv6 || me->dir_port ? "are" : "is", + TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT/60); + return 1; } @@ -266,7 +356,7 @@ router_orport_found_reachable(void) log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from " "the outside. Excellent.%s", options->PublishServerDescriptor_ != NO_DIRINFO - && check_whether_dirport_reachable(options) ? + && router_should_skip_dirport_reachability_check(options) ? " Publishing server descriptor." : ""); can_reach_or_port = 1; mark_my_descriptor_dirty("ORPort found reachable"); @@ -275,6 +365,7 @@ router_orport_found_reachable(void) if (options->TestingTorNetwork == 1) { reschedule_descriptor_update_check(); } + /* We'll add an IPv6 event in #34068. */ control_event_server_status(LOG_NOTICE, "REACHABILITY_SUCCEEDED ORADDRESS=%s:%d", address, me->or_port); @@ -297,7 +388,7 @@ router_dirport_found_reachable(void) log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable " "from the outside. Excellent.%s", options->PublishServerDescriptor_ != NO_DIRINFO - && check_whether_orport_reachable(options) ? + && router_should_skip_orport_reachability_check(options) ? " Publishing server descriptor." : ""); can_reach_dir_port = 1; if (router_should_advertise_dirport(options, me->dir_port)) { @@ -316,7 +407,9 @@ router_dirport_found_reachable(void) } /** We have enough testing circuits open. Send a bunch of "drop" - * cells down each of them, to exercise our bandwidth. */ + * cells down each of them, to exercise our bandwidth. + * + * May use IPv4 and IPv6 testing circuits (if available). */ void router_perform_bandwidth_test(int num_circs, time_t now) { diff --git a/src/feature/relay/selftest.h b/src/feature/relay/selftest.h index f5babc95da..5799a6ca33 100644 --- a/src/feature/relay/selftest.h +++ b/src/feature/relay/selftest.h @@ -15,8 +15,10 @@ #ifdef HAVE_MODULE_RELAY struct or_options_t; -int check_whether_orport_reachable(const struct or_options_t *options); -int check_whether_dirport_reachable(const struct or_options_t *options); +int router_should_skip_orport_reachability_check( + const struct or_options_t *options); +int router_should_skip_dirport_reachability_check( + const struct or_options_t *options); void router_do_reachability_checks(int test_or, int test_dir); void router_perform_bandwidth_test(int num_circs, time_t now); @@ -29,9 +31,9 @@ void router_reset_reachability(void); #else /* !defined(HAVE_MODULE_RELAY) */ -#define check_whether_orport_reachable(opts) \ +#define router_should_skip_orport_reachability_check(opts) \ ((void)(opts), 0) -#define check_whether_dirport_reachable(opts) \ +#define router_should_skip_dirport_reachability_check(opts) \ ((void)(opts), 0) static inline void diff --git a/src/feature/stats/predict_ports.c b/src/feature/stats/predict_ports.c index d728f106a2..440cea6725 100644 --- a/src/feature/stats/predict_ports.c +++ b/src/feature/stats/predict_ports.c @@ -270,10 +270,10 @@ rep_hist_circbuilding_dormant(time_t now) /* see if we'll still need to build testing circuits */ if (server_mode(options) && - (!check_whether_orport_reachable(options) || + (!router_should_skip_orport_reachability_check(options) || !circuit_enough_testing_circs())) return 0; - if (!check_whether_dirport_reachable(options)) + if (!router_should_skip_dirport_reachability_check(options)) return 0; return 1; |