GitLab is used only for code review, issue tracking and project management. Canonical locations for source code are still https://gitweb.torproject.org/ https://git.torproject.org/ and git-rw.torproject.org.

Commit 354f085e authored by Nick Mathewson's avatar Nick Mathewson 🔬

Merge remote-tracking branch 'tor-github/pr/1888/head'

parents eaae5625 1df451ab
o Minor bugfixes (rust, protocol versions):
- Declare support for the onion service introduction point denial of
service extensions, when building tor with Rust.
Fixes bug 34248; bugfix on 0.4.2.1-alpha.
o Minor bugfixes (rust, protocol versions):
- Make Rust protocol version support checks consistent with the
undocumented error behaviour of the corresponding C code.
Fixes bug 34251; bugfix on 0.3.3.5-rc.
o Major features (IPv6, relay):
- Launch IPv4 and IPv6 ORPort self-test circuits on relays and bridges.
Closes ticket 33222.
o Minor features (IPv6, relay):
- Allow relays to send IPv6-only extend cells. Closes ticket 33222.
- Declare support for the Relay=3 subprotocol version. Closes ticket 33226.
- When launching IPv6 ORPort self-test circuits, make sure that the
second-last hop can initiate an IPv6 extend. Closes ticket 33222.
o Code simplification and refactoring:
- Refactor some common node selection code into a single function.
Closes ticket 34200.
......@@ -2038,12 +2038,12 @@ different from other Tor clients:
A list of identity fingerprints and country codes of nodes
to use for "middle" hops in your normal circuits.
Normal circuits include all circuits except for direct connections
to directory servers. Middle hops are all hops other than exit and entry. +
to directory servers. Middle hops are all hops other than exit and entry.
+
This is an **experimental** feature that is meant to be used by researchers
and developers to test new features in the Tor network safely. Using it
without care will strongly influence your anonymity. This feature might get
removed in the future.
without care will strongly influence your anonymity. Other tor features may
not work with MiddleNodes. This feature might get removed in the future.
+
The HSLayer2Node and HSLayer3Node options override this option for onion
service circuits, if they are set. The vanguards addon will read this
......
......@@ -96,7 +96,7 @@ problem function-size /src/core/or/channeltls.c:channel_tls_process_authenticate
problem dependency-violation /src/core/or/channeltls.c 11
problem include-count /src/core/or/circuitbuild.c 53
problem function-size /src/core/or/circuitbuild.c:get_unique_circ_id_by_chan() 128
problem function-size /src/core/or/circuitbuild.c:choose_good_exit_server_general() 206
problem function-size /src/core/or/circuitbuild.c:choose_good_exit_server_general() 196
problem dependency-violation /src/core/or/circuitbuild.c 25
problem include-count /src/core/or/circuitlist.c 55
problem function-size /src/core/or/circuitlist.c:HT_PROTOTYPE() 109
......@@ -117,7 +117,7 @@ problem function-size /src/core/or/circuitpadding_machines.c:circpad_machine_cli
problem dependency-violation /src/core/or/circuitpadding_machines.c 1
problem function-size /src/core/or/circuitstats.c:circuit_build_times_parse_state() 123
problem dependency-violation /src/core/or/circuitstats.c 11
problem file-size /src/core/or/circuituse.c 3195
problem file-size /src/core/or/circuituse.c 3250
problem function-size /src/core/or/circuituse.c:circuit_is_acceptable() 128
problem function-size /src/core/or/circuituse.c:circuit_expire_building() 389
problem function-size /src/core/or/circuituse.c:circuit_log_ancient_one_hop_circuits() 126
......@@ -146,7 +146,7 @@ problem function-size /src/core/or/connection_or.c:connection_or_client_learned_
problem dependency-violation /src/core/or/connection_or.c 21
problem dependency-violation /src/core/or/dos.c 6
problem dependency-violation /src/core/or/onion.c 2
problem file-size /src/core/or/or.h 1105
problem file-size /src/core/or/or.h 1150
problem include-count /src/core/or/or.h 48
problem dependency-violation /src/core/or/or.h 1
problem dependency-violation /src/core/or/or_periodic.c 1
......@@ -198,7 +198,7 @@ problem function-size /src/feature/control/control_events.c:control_event_stream
problem include-count /src/feature/control/control_getinfo.c 56
problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_misc() 108
problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_dir() 297
problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_events() 234
problem function-size /src/feature/control/control_getinfo.c:getinfo_helper_events() 237
problem function-size /src/feature/dirauth/bwauth.c:dirserv_read_measured_bandwidths() 121
problem file-size /src/feature/dirauth/dirvote.c 4734
problem include-count /src/feature/dirauth/dirvote.c 55
......@@ -255,11 +255,11 @@ problem function-size /src/feature/nodelist/microdesc.c:microdesc_cache_rebuild(
problem include-count /src/feature/nodelist/networkstatus.c 65
problem function-size /src/feature/nodelist/networkstatus.c:networkstatus_check_consensus_signature() 175
problem function-size /src/feature/nodelist/networkstatus.c:networkstatus_set_current_consensus() 289
problem function-size /src/feature/nodelist/node_select.c:router_pick_directory_server_impl() 122
problem function-size /src/feature/nodelist/node_select.c:router_pick_directory_server_impl() 126
problem function-size /src/feature/nodelist/node_select.c:compute_weighted_bandwidths() 204
problem function-size /src/feature/nodelist/node_select.c:router_pick_trusteddirserver_impl() 112
problem function-size /src/feature/nodelist/node_select.c:router_pick_trusteddirserver_impl() 116
problem function-size /src/feature/nodelist/nodelist.c:compute_frac_paths_available() 190
problem file-size /src/feature/nodelist/routerlist.c 3247
problem file-size /src/feature/nodelist/routerlist.c 3350
problem function-size /src/feature/nodelist/routerlist.c:router_rebuild_store() 148
problem function-size /src/feature/nodelist/routerlist.c:router_add_to_routerlist() 168
problem function-size /src/feature/nodelist/routerlist.c:routerlist_remove_old_routers() 121
......
......@@ -439,7 +439,8 @@ onion_populate_cpath(origin_circuit_t *circ)
/** Create and return a new origin circuit. Initialize its purpose and
* build-state based on our arguments. The <b>flags</b> argument is a
* bitfield of CIRCLAUNCH_* flags. */
* bitfield of CIRCLAUNCH_* flags, see circuit_launch_by_extend_info() for
* more details. */
origin_circuit_t *
origin_circuit_init(uint8_t purpose, int flags)
{
......@@ -455,13 +456,16 @@ origin_circuit_init(uint8_t purpose, int flags)
((flags & CIRCLAUNCH_NEED_CAPACITY) ? 1 : 0);
circ->build_state->is_internal =
((flags & CIRCLAUNCH_IS_INTERNAL) ? 1 : 0);
circ->build_state->is_ipv6_selftest =
((flags & CIRCLAUNCH_IS_IPV6_SELFTEST) ? 1 : 0);
circ->base_.purpose = purpose;
return circ;
}
/** Build a new circuit for <b>purpose</b>. If <b>exit</b>
* is defined, then use that as your exit router, else choose a suitable
* exit node.
/** Build a new circuit for <b>purpose</b>. If <b>exit</b> is defined, then use
* that as your exit router, else choose a suitable exit node. The <b>flags</b>
* argument is a bitfield of CIRCLAUNCH_* flags, see
* circuit_launch_by_extend_info() for more details.
*
* Also launch a connection to the first OR in the chosen path, if
* it's not open already.
......@@ -1050,7 +1054,8 @@ circuit_build_no_more_hops(origin_circuit_t *circ)
control_event_bootstrap(BOOTSTRAP_STATUS_DONE, 0);
control_event_client_status(LOG_NOTICE, "CIRCUIT_ESTABLISHED");
clear_broken_connection_map(1);
if (server_mode(options) && !check_whether_orport_reachable(options)) {
if (server_mode(options) &&
!router_should_skip_orport_reachability_check(options)) {
inform_testing_reachability();
router_do_reachability_checks(1, 1);
}
......@@ -1074,14 +1079,25 @@ circuit_send_intermediate_onion_skin(origin_circuit_t *circ,
crypt_path_t *hop)
{
int len;
int family = tor_addr_family(&hop->extend_info->addr);
extend_cell_t ec;
memset(&ec, 0, sizeof(ec));
log_debug(LD_CIRC,"starting to send subsequent skin.");
if (tor_addr_family(&hop->extend_info->addr) != AF_INET) {
log_warn(LD_BUG, "Trying to extend to a non-IPv4 address.");
return - END_CIRC_REASON_INTERNAL;
/* Relays and bridges can send IPv6 extends. But for clients, it's an
* obvious version distinguisher. */
if (server_mode(get_options())) {
if (family != AF_INET && family != AF_INET6) {
log_warn(LD_BUG, "Server trying to extend to an invalid address "
"family.");
return - END_CIRC_REASON_INTERNAL;
}
} else {
if (family != AF_INET) {
log_warn(LD_BUG, "Client trying to extend to a non-IPv4 address.");
return - END_CIRC_REASON_INTERNAL;
}
}
circuit_pick_extend_handshake(&ec.cell_type,
......@@ -1089,9 +1105,17 @@ circuit_send_intermediate_onion_skin(origin_circuit_t *circ,
&ec.create_cell.handshake_type,
hop->extend_info);
tor_addr_copy(&ec.orport_ipv4.addr, &hop->extend_info->addr);
ec.orport_ipv4.port = hop->extend_info->port;
tor_addr_make_unspec(&ec.orport_ipv6.addr);
/* At the moment, extend_info only has one ORPort address. We'll add a
* second address in #34069, to support dual-stack extend cells. */
if (family == AF_INET) {
tor_addr_copy(&ec.orport_ipv4.addr, &hop->extend_info->addr);
ec.orport_ipv4.port = hop->extend_info->port;
tor_addr_make_unspec(&ec.orport_ipv6.addr);
} else {
tor_addr_copy(&ec.orport_ipv6.addr, &hop->extend_info->addr);
ec.orport_ipv6.port = hop->extend_info->port;
tor_addr_make_unspec(&ec.orport_ipv4.addr);
}
memcpy(ec.node_id, hop->extend_info->identity_digest, DIGEST_LEN);
/* Set the ED25519 identity too -- it will only get included
* in the extend2 cell if we're configured to use it, though. */
......@@ -1539,7 +1563,23 @@ choose_good_exit_server_general(router_crn_flags_t flags)
const node_t *selected_node=NULL;
const int need_uptime = (flags & CRN_NEED_UPTIME) != 0;
const int need_capacity = (flags & CRN_NEED_CAPACITY) != 0;
const int direct_conn = (flags & CRN_DIRECT_CONN) != 0;
/* We should not require guard flags on exits. */
IF_BUG_ONCE(flags & CRN_NEED_GUARD)
return NULL;
/* We reject single-hop exits for all node positions. */
IF_BUG_ONCE(flags & CRN_DIRECT_CONN)
return NULL;
/* This isn't the function for picking rendezvous nodes. */
IF_BUG_ONCE(flags & CRN_RENDEZVOUS_V3)
return NULL;
/* We only want exits to extend if we cannibalize the circuit.
* But we don't require IPv6 extends yet. */
IF_BUG_ONCE(flags & CRN_INITIATE_IPV6_EXTEND)
return NULL;
connections = get_connection_array();
......@@ -1572,19 +1612,14 @@ choose_good_exit_server_general(router_crn_flags_t flags)
*/
continue;
}
if (!node_has_preferred_descriptor(node, direct_conn)) {
if (!router_can_choose_node(node, flags)) {
n_supported[i] = -1;
continue;
}
if (!node->is_running || node->is_bad_exit) {
if (node->is_bad_exit) {
n_supported[i] = -1;
continue; /* skip routers that are known to be down or bad exits */
}
if (node_get_purpose(node) != ROUTER_PURPOSE_GENERAL) {
/* never pick a non-general node as a random exit. */
n_supported[i] = -1;
continue;
}
if (routerset_contains_node(options->ExcludeExitNodesUnion_, node)) {
n_supported[i] = -1;
continue; /* user asked us not to use it, no matter what */
......@@ -1594,27 +1629,6 @@ choose_good_exit_server_general(router_crn_flags_t flags)
n_supported[i] = -1;
continue; /* not one of our chosen exit nodes */
}
if (node_is_unreliable(node, need_uptime, need_capacity, 0)) {
n_supported[i] = -1;
continue; /* skip routers that are not suitable. Don't worry if
* this makes us reject all the possible routers: if so,
* we'll retry later in this function with need_update and
* need_capacity set to 0. */
}
if (!(node->is_valid)) {
/* if it's invalid and we don't want it */
n_supported[i] = -1;
// log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- invalid router.",
// router->nickname, i);
continue; /* skip invalid routers */
}
/* We do not allow relays that allow single hop exits by default. Option
* was deprecated in 0.2.9.2-alpha and removed in 0.3.1.0-alpha. */
if (node_allows_single_hop_exits(node)) {
n_supported[i] = -1;
continue;
}
if (node_exit_policy_rejects_all(node)) {
n_supported[i] = -1;
// log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- it rejects all.",
......@@ -1771,13 +1785,7 @@ pick_restricted_middle_node(router_crn_flags_t flags,
tor_assert(pick_from);
/* Add all running nodes to all_live_nodes */
router_add_running_nodes_to_smartlist(all_live_nodes,
(flags & CRN_NEED_UPTIME) != 0,
(flags & CRN_NEED_CAPACITY) != 0,
(flags & CRN_NEED_GUARD) != 0,
(flags & CRN_NEED_DESC) != 0,
(flags & CRN_PREF_ADDR) != 0,
(flags & CRN_DIRECT_CONN) != 0);
router_add_running_nodes_to_smartlist(all_live_nodes, flags);
/* Filter all_live_nodes to only add live *and* whitelisted middles
* to the list whitelisted_live_middles. */
......@@ -1957,6 +1965,43 @@ warn_if_last_router_excluded(origin_circuit_t *circ,
return;
}
/* Return a set of generic CRN_* flags based on <b>state</b>.
*
* Called for every position in the circuit. */
STATIC int
cpath_build_state_to_crn_flags(const cpath_build_state_t *state)
{
router_crn_flags_t flags = 0;
/* These flags apply to entry, middle, and exit nodes.
* If a flag only applies to a specific position, it should be checked in
* that function. */
if (state->need_uptime)
flags |= CRN_NEED_UPTIME;
if (state->need_capacity)
flags |= CRN_NEED_CAPACITY;
return flags;
}
/* Return the CRN_INITIATE_IPV6_EXTEND flag, based on <b>state</b> and
* <b>cur_len</b>.
*
* Only called for middle nodes (for now). Must not be called on single-hop
* circuits. */
STATIC int
cpath_build_state_to_crn_ipv6_extend_flag(const cpath_build_state_t *state,
int cur_len)
{
IF_BUG_ONCE(state->desired_path_len < 2)
return 0;
/* The last node is the relay doing the self-test. So we want to extend over
* IPv6 from the second-last node. */
if (state->is_ipv6_selftest && cur_len == state->desired_path_len - 2)
return CRN_INITIATE_IPV6_EXTEND;
else
return 0;
}
/** Decide a suitable length for circ's cpath, and pick an exit
* router (or use <b>exit</b> if provided). Store these in the
* cpath.
......@@ -1990,14 +2035,13 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit_ei,
exit_ei = extend_info_dup(exit_ei);
} else { /* we have to decide one */
router_crn_flags_t flags = CRN_NEED_DESC;
if (state->need_uptime)
flags |= CRN_NEED_UPTIME;
if (state->need_capacity)
flags |= CRN_NEED_CAPACITY;
if (is_hs_v3_rp_circuit)
flags |= CRN_RENDEZVOUS_V3;
flags |= cpath_build_state_to_crn_flags(state);
/* Some internal exits are one hop, for example directory connections.
* (Guards are always direct, middles are never direct.) */
if (state->onehop_tunnel)
flags |= CRN_DIRECT_CONN;
if (is_hs_v3_rp_circuit)
flags |= CRN_RENDEZVOUS_V3;
const node_t *node =
choose_good_exit_server(circ, flags, state->is_internal);
if (!node) {
......@@ -2059,32 +2103,27 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit_ei)
return 0;
}
/** Return the number of routers in <b>routers</b> that are currently up
* and available for building circuits through.
/** Return the number of routers in <b>nodes</b> that are currently up and
* available for building circuits through.
*
* (Note that this function may overcount or undercount, if we have
* descriptors that are not the type we would prefer to use for some
* particular router. See bug #25885.)
* If <b>direct</b> is true, only count nodes that are suitable for direct
* connections. Counts nodes regardless of whether their addresses are
* preferred.
*/
MOCK_IMPL(STATIC int,
count_acceptable_nodes, (const smartlist_t *nodes, int direct))
{
int num=0;
int flags = CRN_NEED_DESC;
if (direct)
flags |= CRN_DIRECT_CONN;
SMARTLIST_FOREACH_BEGIN(nodes, const node_t *, node) {
// log_debug(LD_CIRC,
// "Contemplating whether router %d (%s) is a new option.",
// i, r->nickname);
if (! node->is_running)
// 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))
// "Contemplating whether router %d (%s) is a new option.",
// i, r->nickname);
if (!router_can_choose_node(node, flags))
continue;
++num;
} SMARTLIST_FOREACH_END(node);
......@@ -2278,10 +2317,8 @@ choose_good_middle_server(uint8_t purpose,
excluded = build_middle_exclude_list(purpose, state, head, cur_len);
if (state->need_uptime)
flags |= CRN_NEED_UPTIME;
if (state->need_capacity)
flags |= CRN_NEED_CAPACITY;
flags |= cpath_build_state_to_crn_flags(state);
flags |= cpath_build_state_to_crn_ipv6_extend_flag(state, cur_len);
/** If a hidden service circuit wants a specific middle node, pin it. */
if (middle_node_must_be_vanguard(options, purpose, cur_len)) {
......@@ -2357,10 +2394,7 @@ choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state,
}
if (state) {
if (state->need_uptime)
flags |= CRN_NEED_UPTIME;
if (state->need_capacity)
flags |= CRN_NEED_CAPACITY;
flags |= cpath_build_state_to_crn_flags(state);
}
choice = router_choose_random_node(excluded, options->ExcludeNodes, flags);
......
......@@ -97,6 +97,10 @@ STATIC int onion_extend_cpath(origin_circuit_t *circ);
STATIC int
onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit_ei,
int is_hs_v3_rp_circuit);
STATIC int cpath_build_state_to_crn_flags(const cpath_build_state_t *state);
STATIC int cpath_build_state_to_crn_ipv6_extend_flag(
const cpath_build_state_t *state,
int cur_len);
#endif /* defined(CIRCUITBUILD_PRIVATE) */
......
......@@ -1944,7 +1944,7 @@ circuit_find_to_cannibalize(uint8_t purpose_to_produce, extend_info_t *info,
/* Ignore any circuits for which we can't use the Guard. It is possible
* that the Guard was removed from the sampled set after the circuit
* was created so avoid using it. */
* was created, so avoid using it. */
if (!entry_guard_could_succeed(circ->guard_state)) {
goto next;
}
......
......@@ -1642,7 +1642,7 @@ static void
circuit_testing_opened(origin_circuit_t *circ)
{
if (have_performed_bandwidth_test ||
!check_whether_orport_reachable(get_options())) {
!router_should_skip_orport_reachability_check(get_options())) {
/* either we've already done everything we want with testing circuits,
* or this testing circuit became open due to a fluke, e.g. we picked
* a last hop where we already had the connection open due to an
......@@ -1660,7 +1660,8 @@ static void
circuit_testing_failed(origin_circuit_t *circ, int at_last_hop)
{
const or_options_t *options = get_options();
if (server_mode(options) && check_whether_orport_reachable(options))
if (server_mode(options) &&
router_should_skip_orport_reachability_check(options))
return;
log_info(LD_GENERAL,
......@@ -2092,11 +2093,18 @@ circuit_should_cannibalize_to_build(uint8_t purpose_to_build,
}
/** Launch a new circuit with purpose <b>purpose</b> and exit node
* <b>extend_info</b> (or NULL to select a random exit node). If flags
* contains CIRCLAUNCH_NEED_UPTIME, choose among routers with high uptime. If
* CIRCLAUNCH_NEED_CAPACITY is set, choose among routers with high bandwidth.
* If CIRCLAUNCH_IS_INTERNAL is true, the last hop need not be an exit node.
* If CIRCLAUNCH_ONEHOP_TUNNEL is set, the circuit will have only one hop.
* <b>extend_info</b> (or NULL to select a random exit node).
*
* If flags contains:
* - CIRCLAUNCH_ONEHOP_TUNNEL: the circuit will have only one hop;
* - CIRCLAUNCH_NEED_UPTIME: choose routers with high uptime;
* - CIRCLAUNCH_NEED_CAPACITY: choose routers with high bandwidth;
* - CIRCLAUNCH_IS_IPV6_SELFTEST: the second-last hop must support IPv6
* extends;
* - CIRCLAUNCH_IS_INTERNAL: the last hop need not be an exit node;
* - CIRCLAUNCH_IS_V3_RP: the last hop must support v3 onion service
* rendezvous.
*
* Return the newly allocated circuit on success, or NULL on failure. */
origin_circuit_t *
circuit_launch_by_extend_info(uint8_t purpose,
......
......@@ -36,17 +36,23 @@ void circuit_try_attaching_streams(origin_circuit_t *circ);
void circuit_build_failed(origin_circuit_t *circ);
/** Flag to set when a circuit should have only a single hop. */
#define CIRCLAUNCH_ONEHOP_TUNNEL (1<<0)
#define CIRCLAUNCH_ONEHOP_TUNNEL (1<<0)
/** Flag to set when a circuit needs to be built of high-uptime nodes */
#define CIRCLAUNCH_NEED_UPTIME (1<<1)
#define CIRCLAUNCH_NEED_UPTIME (1<<1)
/** Flag to set when a circuit needs to be built of high-capacity nodes */
#define CIRCLAUNCH_NEED_CAPACITY (1<<2)
#define CIRCLAUNCH_NEED_CAPACITY (1<<2)
/** Flag to set when the last hop of a circuit doesn't need to be an
* exit node. */
#define CIRCLAUNCH_IS_INTERNAL (1<<3)
#define CIRCLAUNCH_IS_INTERNAL (1<<3)
/** Flag to set when we are trying to launch a v3 rendezvous circuit. We need
* to apply some additional filters on the node picked. */
#define CIRCLAUNCH_IS_V3_RP (1<<4)
#define CIRCLAUNCH_IS_V3_RP (1<<4)
/** Flag to set when we are trying to launch a self-testing circuit to our
* IPv6 ORPort. We need to apply some additional filters on the second-last
* node in the circuit. (We are both the client and the last node in the
* circuit.) */
#define CIRCLAUNCH_IS_IPV6_SELFTEST (1<<5)
origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
extend_info_t *info,
int flags);
......
......@@ -24,6 +24,8 @@ struct cpath_build_state_t {
unsigned int need_capacity : 1;
/** Whether the last hop was picked with exiting in mind. */
unsigned int is_internal : 1;
/** Is this an IPv6 ORPort self-testing circuit? */
unsigned int is_ipv6_selftest : 1;
/** Did we pick this as a one-hop tunnel (not safe for other streams)?
* These are for encrypted dir conns that exit to this router, not
* for arbitrary exits from the circuit. */
......
......@@ -815,6 +815,18 @@ typedef struct protover_summary_flags_t {
* accept EXTEND2 cells. This requires Relay=2. */
unsigned int supports_extend2_cells:1;
/** True iff this router has a version or protocol list that allows it to
* accept IPv6 connections. This requires Relay=2 or Relay=3. */
unsigned int supports_accepting_ipv6_extends:1;
/** True iff this router has a version or protocol list that allows it to
* initiate IPv6 connections. This requires Relay=3. */
unsigned int supports_initiating_ipv6_extends:1;
/** True iff this router has a version or protocol list that allows it to
* consider IPv6 connections canonical. This requires Relay=3. */
unsigned int supports_canonical_ipv6_conns:1;
/** True iff this router has a protocol list that allows it to negotiate
* ed25519 identity keys on a link handshake with us. This
* requires LinkAuth=3. */
......@@ -830,6 +842,10 @@ typedef struct protover_summary_flags_t {
* the v3 protocol detailed in proposal 224. This requires HSIntro=4. */
unsigned int supports_ed25519_hs_intro : 1;
/** True iff this router has a protocol list that allows it to support the
* ESTABLISH_INTRO DoS cell extension. Requires HSIntro=5. */
unsigned int supports_establish_intro_dos_extension : 1;
/** True iff this router has a protocol list that allows it to be an hidden
* service directory supporting version 3 as seen in proposal 224. This
* requires HSDir=2. */
......@@ -841,12 +857,9 @@ typedef struct protover_summary_flags_t {
unsigned int supports_v3_rendezvous_point: 1;
/** True iff this router has a protocol list that allows clients to
* negotiate hs circuit setup padding. Requires Padding>=2. */
* negotiate hs circuit setup padding. Requires Padding=2. */
unsigned int supports_hs_setup_padding : 1;
/** True iff this router has a protocol list that allows it to support the
* ESTABLISH_INTRO DoS cell extension. Requires HSIntro>=5. */
unsigned int supports_establish_intro_dos_extension : 1;
} protover_summary_flags_t;
typedef struct routerinfo_t routerinfo_t;
......
......@@ -326,6 +326,9 @@ protover_is_supported_here(protocol_type_t pr, uint32_t ver)
/**
* Return true iff "list" encodes a protocol list that includes support for
* the indicated protocol and version.
*
* If the protocol list is unparseable, treat it as if it defines no
* protocols, and return 0.
*/
int
protocol_list_supports_protocol(const char *list, protocol_type_t tp,
......@@ -348,6 +351,9 @@ protocol_list_supports_protocol(const char *list, protocol_type_t tp,
/**
* Return true iff "list" encodes a protocol list that includes support for
* the indicated protocol and version, or some later version.
*
* If the protocol list is unparseable, treat it as if it defines no
* protocols, and return 0.
*/
int
protocol_list_supports_protocol_or_later(const char *list,
......@@ -403,7 +409,7 @@ protover_get_supported_protocols(void)
#endif
"Microdesc=1-2 "
"Padding=2 "
"Relay=1-2";
"Relay=1-3";
}
/** The protocols from protover_get_supported_protocols(), as parsed into a
......@@ -740,6 +746,9 @@ protover_compute_vote(const smartlist_t *list_of_proto_strings,
* one that we support, and false otherwise. If <b>missing_out</b> is
* provided, set it to the list of protocols we do not support.
*
* If the protocol version string is unparseable, treat it as if it defines no
* protocols, and return 1.
*
* NOTE: This is quadratic, but we don't do it much: only a few times per
* consensus. Checking signatures should be way more expensive than this
* ever would be.
......
......@@ -22,12 +22,32 @@ struct smartlist_t;
/// `FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS`
#define FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS "0.2.9.3-alpha"
/** The protover version number that signifies HSDir support for HSv3 */
#define PROTOVER_HSDIR_V3 2
/** The protover version number that signifies ed25519 link handshake support
*/
#define PROTOVER_LINKAUTH_ED25519_HANDSHAKE 3
/** The protover version number that signifies extend2 cell support */
#define PROTOVER_RELAY_EXTEND2 2
/** The protover version number where relays can accept IPv6 connections */
#define PROTOVER_RELAY_ACCEPT_IPV6 2
/** The protover version number where relays can initiate IPv6 extends */
#define PROTOVER_RELAY_EXTEND_IPV6 3
/** The protover version number where relays can consider IPv6 connections
* canonical */
#define PROTOVER_RELAY_CANONICAL_IPV6 3
/** The protover version number that signifies HSv3 intro point support */
#define PROTOVER_HS_INTRO_V3 4
/** The protover version number where intro points support denial of service
* resistance */
#define PROTOVER_HS_INTRO_DOS 5
/** The protover version number that signifies HSv3 rendezvous point support */
#define PROTOVER_HS_RENDEZVOUS_POINT_V3 2