diff options
Diffstat (limited to 'src/or/circuitbuild.c')
-rw-r--r-- | src/or/circuitbuild.c | 205 |
1 files changed, 142 insertions, 63 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index d02ea1678..4ec45bc08 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -263,7 +263,7 @@ circuit_build_times_test_frequency(void) } /** - * Retrieve and bounds-check the cbtmintimeout consensus paramter. + * Retrieve and bounds-check the cbtmintimeout consensus parameter. * * Effect: This is the minimum allowed timeout value in milliseconds. * The minimum is to prevent rounding to 0 (we only check once @@ -679,7 +679,15 @@ circuit_build_times_shuffle_and_store_array(circuit_build_times_t *cbt, log_notice(LD_CIRC, "The number of circuit times that this Tor version " "uses to calculate build times is less than the number stored " "in your state file. Decreasing the circuit time history from " - "%d to %d.", num_times, CBT_NCIRCUITS_TO_OBSERVE); + "%lu to %d.", (unsigned long)num_times, + CBT_NCIRCUITS_TO_OBSERVE); + } + + if (n > INT_MAX-1) { + log_warn(LD_CIRC, "For some insane reasons, you had %lu circuit build " + "observations in your state file. That's far too many; probably " + "there's a bug here.", (unsigned long)n); + n = INT_MAX-1; } /* This code can only be run on a compact array */ @@ -1494,7 +1502,7 @@ get_unique_circ_id_by_conn(or_connection_t *conn) } /** If <b>verbose</b> is false, allocate and return a comma-separated list of - * the currently built elements of circuit_t. If <b>verbose</b> is true, also + * the currently built elements of <b>circ</b>. If <b>verbose</b> is true, also * list information about link status in a more verbose format using spaces. * If <b>verbose_names</b> is false, give nicknames for Named routers and hex * digests for others; if <b>verbose_names</b> is true, use $DIGEST=Name style @@ -1580,7 +1588,7 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names) } /** If <b>verbose</b> is false, allocate and return a comma-separated - * list of the currently built elements of circuit_t. If + * list of the currently built elements of <b>circ</b>. If * <b>verbose</b> is true, also list information about link status in * a more verbose format using spaces. */ @@ -1591,7 +1599,7 @@ circuit_list_path(origin_circuit_t *circ, int verbose) } /** Allocate and return a comma-separated list of the currently built elements - * of circuit_t, giving each as a verbose nickname. + * of <b>circ</b>, giving each as a verbose nickname. */ char * circuit_list_path_for_controller(origin_circuit_t *circ) @@ -1600,7 +1608,7 @@ circuit_list_path_for_controller(origin_circuit_t *circ) } /** Log, at severity <b>severity</b>, the nicknames of each router in - * circ's cpath. Also log the length of the cpath, and the intended + * <b>circ</b>'s cpath. Also log the length of the cpath, and the intended * exit point. */ void @@ -1612,7 +1620,7 @@ circuit_log_path(int severity, unsigned int domain, origin_circuit_t *circ) } /** Tell the rep(utation)hist(ory) module about the status of the links - * in circ. Hops that have become OPEN are marked as successfully + * in <b>circ</b>. Hops that have become OPEN are marked as successfully * extended; the _first_ hop that isn't open (if any) is marked as * unable to extend. */ @@ -1748,10 +1756,9 @@ circuit_handle_first_hop(origin_circuit_t *circ) if (!n_conn) { /* not currently connected in a useful way. */ - const char *name = strlen(firsthop->extend_info->nickname) ? - firsthop->extend_info->nickname : fmt_addr(&firsthop->extend_info->addr); - log_info(LD_CIRC, "Next router is %s: %s ", - safe_str_client(name), msg?msg:"???"); + log_info(LD_CIRC, "Next router is %s: %s", + safe_str_client(extend_info_describe(firsthop->extend_info)), + msg?msg:"???"); circ->_base.n_hop = extend_info_dup(firsthop->extend_info); if (should_launch) { @@ -1818,7 +1825,7 @@ circuit_n_conn_done(or_connection_t *or_conn, int status) continue; } else { /* We expected a key. See if it's the right one. */ - if (memcmp(or_conn->identity_digest, + if (tor_memneq(or_conn->identity_digest, circ->n_hop->identity_digest, DIGEST_LEN)) continue; } @@ -1941,7 +1948,7 @@ inform_testing_reachability(void) static INLINE int should_use_create_fast_for_circuit(origin_circuit_t *circ) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); tor_assert(circ->cpath); tor_assert(circ->cpath->extend_info); @@ -2034,7 +2041,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING); log_info(LD_CIRC,"First hop: finished sending %s cell to '%s'", fast ? "CREATE_FAST" : "CREATE", - node ? node_get_nickname(node) : "<unnamed>"); + node ? node_describe(node) : "<unnamed>"); } else { tor_assert(circ->cpath->state == CPATH_STATE_OPEN); tor_assert(circ->_base.state == CIRCUIT_STATE_BUILDING); @@ -2076,7 +2083,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) if (circ->build_state->onehop_tunnel) control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_STATUS, 0); if (!can_complete_circuit && !circ->build_state->onehop_tunnel) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); can_complete_circuit=1; /* FFFF Log a count of known routers here */ log_notice(LD_GENERAL, @@ -2226,7 +2233,7 @@ circuit_extend(cell_t *cell, circuit_t *circ) /* Next, check if we're being asked to connect to the hop that the * extend cell came from. There isn't any reason for that, and it can * assist circular-path attacks. */ - if (!memcmp(id_digest, TO_OR_CIRCUIT(circ)->p_conn->identity_digest, + if (tor_memeq(id_digest, TO_OR_CIRCUIT(circ)->p_conn->identity_digest, DIGEST_LEN)) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Client asked me to extend back to the previous hop."); @@ -2643,7 +2650,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) smartlist_t *connections; int best_support = -1; int n_best_support=0; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); const smartlist_t *the_nodes; const node_t *node=NULL; @@ -2818,7 +2825,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) tor_free(n_supported); if (node) { - log_info(LD_CIRC, "Chose exit server '%s'", node_get_nickname(node)); + log_info(LD_CIRC, "Chose exit server '%s'", node_describe(node)); return node; } if (options->ExitNodes) { @@ -2844,7 +2851,7 @@ static const node_t * choose_good_exit_server(uint8_t purpose, int need_uptime, int need_capacity, int is_internal) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); router_crn_flags_t flags = CRN_NEED_DESC; if (need_uptime) flags |= CRN_NEED_UPTIME; @@ -2874,7 +2881,7 @@ choose_good_exit_server(uint8_t purpose, static void warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); routerset_t *rs = options->ExcludeNodes; const char *description; uint8_t purpose = circ->_base.purpose; @@ -2925,7 +2932,7 @@ warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit) log_warn(LD_BUG, "Using %s '%s' which is listed in ExcludeNodes%s, " "even though StrictNodes is set. Please report. " "(Circuit purpose: %s)", - description, exit->nickname, + description, extend_info_describe(exit), rs==options->ExcludeNodes?"":" or ExcludeExitNodes", circuit_purpose_to_string(purpose)); } else { @@ -2934,7 +2941,7 @@ warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit) "prevent this (and possibly break your Tor functionality), " "set the StrictNodes configuration option. " "(Circuit purpose: %s)", - description, exit->nickname, + description, extend_info_describe(exit), rs==options->ExcludeNodes?"":" or ExcludeExitNodes", circuit_purpose_to_string(purpose)); } @@ -2964,7 +2971,8 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit) if (exit) { /* the circuit-builder pre-requested one */ warn_if_last_router_excluded(circ, exit); - log_info(LD_CIRC,"Using requested exit node '%s'", exit->nickname); + log_info(LD_CIRC,"Using requested exit node '%s'", + extend_info_describe(exit)); exit = extend_info_dup(exit); } else { /* we have to decide one */ const node_t *node = @@ -3014,8 +3022,8 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit) circuit_append_new_exit(circ, exit); circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING); if ((err_reason = circuit_send_next_onion_skin(circ))<0) { - log_warn(LD_CIRC, "Couldn't extend circuit to new point '%s'.", - exit->nickname); + log_warn(LD_CIRC, "Couldn't extend circuit to new point %s.", + extend_info_describe(exit)); circuit_mark_for_close(TO_CIRCUIT(circ), -err_reason); return -1; } @@ -3087,7 +3095,7 @@ choose_good_middle_server(uint8_t purpose, const node_t *r, *choice; crypt_path_t *cpath; smartlist_t *excluded; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); router_crn_flags_t flags = CRN_NEED_DESC; tor_assert(_CIRCUIT_PURPOSE_MIN <= purpose && purpose <= _CIRCUIT_PURPOSE_MAX); @@ -3129,7 +3137,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state) { const node_t *choice; smartlist_t *excluded; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); router_crn_flags_t flags = CRN_NEED_GUARD|CRN_NEED_DESC; const node_t *node; @@ -3239,7 +3247,8 @@ onion_extend_cpath(origin_circuit_t *circ) } log_debug(LD_CIRC,"Chose router %s for hop %d (exit is %s)", - info->nickname, cur_len+1, build_state_get_exit_nickname(state)); + extend_info_describe(info), + cur_len+1, build_state_get_exit_nickname(state)); onion_append_hop(&circ->cpath, info); extend_info_free(info); @@ -3379,7 +3388,8 @@ build_state_get_exit_nickname(cpath_build_state_t *state) */ static int entry_guard_set_status(entry_guard_t *e, const node_t *node, - time_t now, or_options_t *options, const char **reason) + time_t now, const or_options_t *options, + const char **reason) { char buf[HEX_DIGEST_LEN+1]; int changed = 0; @@ -3394,6 +3404,8 @@ entry_guard_set_status(entry_guard_t *e, const node_t *node, else if (options->UseBridges && (!node->ri || node->ri->purpose != ROUTER_PURPOSE_BRIDGE)) *reason = "not a bridge"; + else if (options->UseBridges && !node_is_a_configured_bridge(node)) + *reason = "not a configured bridge"; else if (!options->UseBridges && !node->is_possible_guard && !routerset_contains_node(options->EntryNodes,node)) *reason = "not recommended as a guard"; @@ -3460,7 +3472,7 @@ entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity, int assume_reachable, const char **msg) { const node_t *node; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); tor_assert(msg); if (e->bad_since) { @@ -3483,6 +3495,10 @@ entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity, *msg = "not a bridge"; return NULL; } + if (!node_is_a_configured_bridge(node)) { + *msg = "not a configured bridge"; + return NULL; + } } else { /* !get_options()->UseBridges */ if (node_get_purpose(node) != ROUTER_PURPOSE_GENERAL) { *msg = "not general-purpose"; @@ -3527,7 +3543,7 @@ static INLINE entry_guard_t * is_an_entry_guard(const char *digest) { SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry, - if (!memcmp(digest, entry->identity, DIGEST_LEN)) + if (tor_memeq(digest, entry->identity, DIGEST_LEN)) return entry; ); return NULL; @@ -3541,20 +3557,24 @@ log_entry_guards(int severity) smartlist_t *elements = smartlist_create(); char *s; - SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { const char *msg = NULL; char *cp; if (entry_is_live(e, 0, 1, 0, &msg)) - tor_asprintf(&cp, "%s (up %s)", + tor_asprintf(&cp, "%s [%s] (up %s)", e->nickname, + hex_str(e->identity, DIGEST_LEN), e->made_contact ? "made-contact" : "never-contacted"); else - tor_asprintf(&cp, "%s (%s, %s)", - e->nickname, msg, + tor_asprintf(&cp, "%s [%s] (%s, %s)", + e->nickname, + hex_str(e->identity, DIGEST_LEN), + msg, e->made_contact ? "made-contact" : "never-contacted"); smartlist_add(elements, cp); - }); + } + SMARTLIST_FOREACH_END(e); s = smartlist_join_strings(elements, ",", 0, NULL); SMARTLIST_FOREACH(elements, char*, cp, tor_free(cp)); @@ -3578,7 +3598,7 @@ control_event_guard_deferred(void) #if 0 int n = 0; const char *msg; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); if (!entry_guards) return; SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry, @@ -3622,8 +3642,8 @@ add_an_entry_guard(const node_t *chosen, int reset_status) return NULL; } entry = tor_malloc_zero(sizeof(entry_guard_t)); - log_info(LD_CIRC, "Chose '%s' as new entry guard.", - node_get_nickname(node)); + log_info(LD_CIRC, "Chose %s as new entry guard.", + node_describe(node)); strlcpy(entry->nickname, node_get_nickname(node), sizeof(entry->nickname)); memcpy(entry->identity, node->identity, DIGEST_LEN); /* Choose expiry time smudged over the past month. The goal here @@ -3646,7 +3666,7 @@ add_an_entry_guard(const node_t *chosen, int reset_status) /** If the use of entry guards is configured, choose more entry guards * until we have enough in the list. */ static void -pick_entry_guards(or_options_t *options) +pick_entry_guards(const or_options_t *options) { int changed = 0; @@ -3779,10 +3799,9 @@ remove_dead_entry_guards(time_t now) * think that things are unlisted. */ void -entry_guards_compute_status(or_options_t *options, time_t now) +entry_guards_compute_status(const or_options_t *options, time_t now) { int changed = 0; - int severity = LOG_DEBUG; digestmap_t *reasons; if (! entry_guards) @@ -3809,15 +3828,14 @@ entry_guards_compute_status(or_options_t *options, time_t now) if (remove_dead_entry_guards(now)) changed = 1; - severity = changed ? LOG_DEBUG : LOG_INFO; - if (changed) { SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { const char *reason = digestmap_get(reasons, entry->identity); const char *live_msg = ""; const node_t *r = entry_is_live(entry, 0, 1, 0, &live_msg); - log_info(LD_CIRC, "Summary: Entry '%s' is %s, %s%s%s, and %s%s.", + log_info(LD_CIRC, "Summary: Entry %s [%s] is %s, %s%s%s, and %s%s.", entry->nickname, + hex_str(entry->identity, DIGEST_LEN), entry->unreachable_since ? "unreachable" : "reachable", entry->bad_since ? "unusable" : "usable", reason ? ", ": "", @@ -3860,7 +3878,7 @@ entry_guard_register_connect_status(const char *digest, int succeeded, SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, { - if (!memcmp(e->identity, digest, DIGEST_LEN)) { + if (tor_memeq(e->identity, digest, DIGEST_LEN)) { entry = e; idx = e_sl_idx; break; @@ -3971,7 +3989,7 @@ entry_nodes_should_be_added(void) /** Add all nodes in EntryNodes that aren't currently guard nodes to the list * of guard nodes, at the front. */ static void -entry_guards_prepend_from_config(or_options_t *options) +entry_guards_prepend_from_config(const or_options_t *options) { smartlist_t *entry_nodes, *entry_fps; smartlist_t *old_entry_guards_on_list, *old_entry_guards_not_on_list; @@ -4050,7 +4068,7 @@ entry_guards_prepend_from_config(or_options_t *options) * list already and we must stick to it. */ int -entry_list_is_constrained(or_options_t *options) +entry_list_is_constrained(const or_options_t *options) { if (options->EntryNodes) return 1; @@ -4067,7 +4085,7 @@ entry_list_is_constrained(or_options_t *options) const node_t * choose_random_entry(cpath_build_state_t *state) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); smartlist_t *live_entry_guards = smartlist_create(); smartlist_t *exit_family = smartlist_create(); const node_t *chosen_exit = @@ -4488,6 +4506,9 @@ typedef struct { 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]; @@ -4496,11 +4517,39 @@ typedef struct { } bridge_info_t; /** A list of configured bridges. Whenever we actually get a descriptor - * for one, we add it as an entry guard. */ + * 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; -/** Initialize the bridge list to empty, creating it if needed. */ +/** 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_create(); + 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_create(); + SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) { + if (b->marked_for_removal) { + SMARTLIST_DEL_CURRENT(bridge_list, b); + tor_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) @@ -4513,7 +4562,8 @@ clear_bridge_list(void) * (either by comparing keys if possible, else by comparing addr/port). * Else return NULL. */ static bridge_info_t * -get_configured_bridge_by_addr_port_digest(tor_addr_t *addr, uint16_t port, +get_configured_bridge_by_addr_port_digest(const tor_addr_t *addr, + uint16_t port, const char *digest) { if (!bridge_list) @@ -4524,7 +4574,7 @@ get_configured_bridge_by_addr_port_digest(tor_addr_t *addr, uint16_t port, !tor_addr_compare(&bridge->addr, addr, CMP_EXACT) && bridge->port == port) return bridge; - if (!memcmp(bridge->identity, digest, DIGEST_LEN)) + if (digest && tor_memeq(bridge->identity, digest, DIGEST_LEN)) return bridge; } SMARTLIST_FOREACH_END(bridge); @@ -4549,12 +4599,31 @@ 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) +{ + tor_addr_t addr; + uint16_t orport; + if (!node) + return 0; + if (node_get_addr(node, &addr) < 0) + return 0; + orport = node_get_orport(node); + if (orport == 0) + return 0; + + return get_configured_bridge_by_addr_port_digest( + &addr, orport, node->identity) != NULL; +} + /** 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(tor_addr_t *addr, uint16_t port, const char *digest) +learned_router_identity(const tor_addr_t *addr, uint16_t port, + const char *digest) { bridge_info_t *bridge = get_configured_bridge_by_addr_port_digest(addr, port, digest); @@ -4566,11 +4635,20 @@ learned_router_identity(tor_addr_t *addr, uint16_t port, const char *digest) } /** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b> - * is set, it tells us the identity key too. */ + * is set, it tells us the identity key too. If we already had the + * bridge in our list, unmark it, and don't actually add anything new. */ void -bridge_add_from_config(const tor_addr_t *addr, uint16_t port, char *digest) +bridge_add_from_config(const tor_addr_t *addr, uint16_t port, + const char *digest) { - bridge_info_t *b = tor_malloc_zero(sizeof(bridge_info_t)); + bridge_info_t *b; + + if ((b = get_configured_bridge_by_addr_port_digest(addr, port, digest))) { + b->marked_for_removal = 0; + return; + } + + b = tor_malloc_zero(sizeof(bridge_info_t)); tor_addr_copy(&b->addr, addr); b->port = port; if (digest) @@ -4578,6 +4656,7 @@ bridge_add_from_config(const tor_addr_t *addr, uint16_t port, char *digest) b->fetch_status.schedule = DL_SCHED_BRIDGE; if (!bridge_list) bridge_list = smartlist_create(); + smartlist_add(bridge_list, b); } @@ -4605,7 +4684,7 @@ find_bridge_by_digest(const char *digest) { SMARTLIST_FOREACH(bridge_list, bridge_info_t *, bridge, { - if (!memcmp(bridge->identity, digest, DIGEST_LEN)) + if (tor_memeq(bridge->identity, digest, DIGEST_LEN)) return bridge; }); return NULL; @@ -4616,7 +4695,7 @@ static void launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge) { char *address; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); if (connection_get_by_type_addr_port_purpose( CONN_TYPE_DIR, &bridge->addr, bridge->port, @@ -4657,7 +4736,7 @@ retry_bridge_descriptor_fetch_directly(const char *digest) * descriptor, fetch a new copy of its descriptor -- either directly * from the bridge or via a bridge authority. */ void -fetch_bridge_descriptors(or_options_t *options, time_t now) +fetch_bridge_descriptors(const or_options_t *options, time_t now) { int num_bridge_auths = get_n_authorities(BRIDGE_DIRINFO); int ask_bridge_directly; @@ -4851,7 +4930,7 @@ any_pending_bridge_descriptor_fetches(void) * down. Else return 0. If <b>act</b> is 1, then mark the down guards * up; else just observe and report. */ static int -entries_retry_helper(or_options_t *options, int act) +entries_retry_helper(const or_options_t *options, int act) { const node_t *node; int any_known = 0; @@ -4890,7 +4969,7 @@ entries_retry_helper(or_options_t *options, int act) /** Do we know any descriptors for our bridges / entrynodes, and are * all the ones we have descriptors for down? */ int -entries_known_but_down(or_options_t *options) +entries_known_but_down(const or_options_t *options) { tor_assert(entry_list_is_constrained(options)); return entries_retry_helper(options, 0); @@ -4898,7 +4977,7 @@ entries_known_but_down(or_options_t *options) /** Mark all down known bridges / entrynodes up. */ void -entries_retry_all(or_options_t *options) +entries_retry_all(const or_options_t *options) { tor_assert(entry_list_is_constrained(options)); entries_retry_helper(options, 1); |