circuitbuild: Do node checks when counting nodes

Use the node check function to check that there are enough nodes to
select a circuit path.

Adds these checks, which are implied by other code:
* supports EXTEND2 cells,
* does not allow single-hop exits,

Adds these extra checks:
* has a general-purpose routerinfo,
* if it is a direct connection, check reachable addresses.
These checks reduce the node count, but they will never under-count
nodes.

Bridge nodes aren't handled correctly, we'll fix that in the next
commit.

Part of 34200.
This commit is contained in:
teor 2020-05-13 13:23:39 +10:00
parent 766fc86df4
commit e46c3d95f4

View file

@ -2103,32 +2103,27 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit_ei)
return 0; return 0;
} }
/** Return the number of routers in <b>routers</b> that are currently up /** Return the number of routers in <b>nodes</b> that are currently up and
* and available for building circuits through. * available for building circuits through.
* *
* (Note that this function may overcount or undercount, if we have * If <b>direct</b> is true, only count nodes that are suitable for direct
* descriptors that are not the type we would prefer to use for some * connections. Counts nodes regardless of whether their addresses are
* particular router. See bug #25885.) * preferred.
*/ */
MOCK_IMPL(STATIC int, MOCK_IMPL(STATIC int,
count_acceptable_nodes, (const smartlist_t *nodes, int direct)) count_acceptable_nodes, (const smartlist_t *nodes, int direct))
{ {
int num=0; int num=0;
int flags = CRN_NEED_DESC;
if (direct)
flags |= CRN_DIRECT_CONN;
SMARTLIST_FOREACH_BEGIN(nodes, const node_t *, node) { SMARTLIST_FOREACH_BEGIN(nodes, const node_t *, node) {
// log_debug(LD_CIRC, // log_debug(LD_CIRC,
// "Contemplating whether router %d (%s) is a new option.", // "Contemplating whether router %d (%s) is a new option.",
// i, r->nickname); // i, r->nickname);
if (! node->is_running) if (!router_can_choose_node(node, flags))
// log_debug(LD_CIRC,"Nope, the directory says %d is not running.",i);
continue;
if (! node->is_valid)
// log_debug(LD_CIRC,"Nope, the directory says %d is not valid.",i);
continue;
if (! node_has_preferred_descriptor(node, direct))
continue;
/* The node has a descriptor, so we can just check the ntor key directly */
if (!node_has_curve25519_onion_key(node))
continue; continue;
++num; ++num;
} SMARTLIST_FOREACH_END(node); } SMARTLIST_FOREACH_END(node);