mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Record intro point timeouts in rend_intro_point_t
This commit is contained in:
parent
6803c1c371
commit
eaed37d14c
@ -1119,9 +1119,8 @@ circuit_expire_all_dirty_circs(void)
|
||||
* - If circ isn't open yet: call circuit_build_failed() if we're
|
||||
* the origin, and in either case call circuit_rep_hist_note_result()
|
||||
* to note stats.
|
||||
* - If purpose is C_INTRODUCE_ACK_WAIT, remove the intro point we
|
||||
* just tried from our list of intro points for that service
|
||||
* descriptor.
|
||||
* - If purpose is C_INTRODUCE_ACK_WAIT, report the intro point
|
||||
* failure we just had to the hidden service client module.
|
||||
* - Send appropriate destroys and edge_destroys for conns and
|
||||
* streams attached to circ.
|
||||
* - If circ->rend_splice is set (we are the midpoint of a joined
|
||||
@ -1190,16 +1189,20 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
|
||||
}
|
||||
if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
|
||||
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
|
||||
int timed_out = (reason == END_STREAM_REASON_TIMEOUT);
|
||||
tor_assert(circ->state == CIRCUIT_STATE_OPEN);
|
||||
tor_assert(ocirc->build_state->chosen_exit);
|
||||
tor_assert(ocirc->rend_data);
|
||||
/* treat this like getting a nack from it */
|
||||
log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). "
|
||||
"Removing from descriptor.",
|
||||
log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). %s",
|
||||
safe_str_client(ocirc->rend_data->onion_address),
|
||||
safe_str_client(build_state_get_exit_nickname(ocirc->build_state)));
|
||||
rend_client_remove_intro_point(ocirc->build_state->chosen_exit,
|
||||
ocirc->rend_data);
|
||||
safe_str_client(build_state_get_exit_nickname(ocirc->build_state)),
|
||||
timed_out ? "Recording timeout." : "Removing from descriptor.");
|
||||
rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
|
||||
ocirc->rend_data,
|
||||
timed_out ?
|
||||
INTRO_POINT_FAILURE_TIMEOUT :
|
||||
INTRO_POINT_FAILURE_GENERIC);
|
||||
}
|
||||
if (circ->n_conn) {
|
||||
circuit_clear_cell_queue(circ, circ->n_conn);
|
||||
|
@ -3463,6 +3463,13 @@ typedef struct rend_intro_point_t {
|
||||
extend_info_t *extend_info; /**< Extend info of this introduction point. */
|
||||
crypto_pk_env_t *intro_key; /**< Introduction key that replaces the service
|
||||
* key, if this descriptor is V2. */
|
||||
|
||||
/** (Client side only) Flag indicating that a timeout has occurred
|
||||
* after sending an INTRODUCE cell to this intro point. After a
|
||||
* timeout, an intro point should not be tried again during the same
|
||||
* hidden service connection attempt, but it may be tried again
|
||||
* during a future connection attempt. */
|
||||
unsigned int timed_out : 1;
|
||||
} rend_intro_point_t;
|
||||
|
||||
/** Information used to connect to a hidden service. Used on both the
|
||||
|
@ -366,8 +366,9 @@ rend_client_introduction_acked(origin_circuit_t *circ,
|
||||
log_info(LD_REND, "Got nack for %s from %s...",
|
||||
safe_str_client(circ->rend_data->onion_address),
|
||||
safe_str_client(extend_info_describe(circ->build_state->chosen_exit)));
|
||||
if (rend_client_remove_intro_point(circ->build_state->chosen_exit,
|
||||
circ->rend_data) > 0) {
|
||||
if (rend_client_report_intro_point_failure(circ->build_state->chosen_exit,
|
||||
circ->rend_data,
|
||||
INTRO_POINT_FAILURE_GENERIC)>0){
|
||||
/* There are introduction points left. Re-extend the circuit to
|
||||
* another intro point and try again. */
|
||||
int result = rend_client_reextend_intro_circuit(circ);
|
||||
@ -648,16 +649,26 @@ rend_client_cancel_descriptor_fetches(void)
|
||||
} SMARTLIST_FOREACH_END(conn);
|
||||
}
|
||||
|
||||
/** Remove failed_intro from ent. If ent now has no intro points, or
|
||||
* service is unrecognized, then launch a new renddesc fetch.
|
||||
|
||||
/** Mark <b>failed_intro</b> as a failed introduction point for the
|
||||
* hidden service specified by <b>rend_query</b>. If the HS now has no
|
||||
* usable intro points, or we do not have an HS descriptor for it,
|
||||
* then launch a new renddesc fetch.
|
||||
*
|
||||
* Return -1 if error, 0 if no intro points remain or service
|
||||
* If <b>failure_type</b> is INTRO_POINT_FAILURE_GENERIC, remove the
|
||||
* intro point from (our parsed copy of) the HS descriptor.
|
||||
*
|
||||
* If <b>failure_type</b> is INTRO_POINT_FAILURE_TIMEOUT, mark the
|
||||
* intro point as 'timed out'; it will not be retried until the
|
||||
* current hidden service connection attempt has ended or it has
|
||||
* appeared in a newly fetched rendezvous descriptor.
|
||||
*
|
||||
* Return -1 if error, 0 if no usable intro points remain or service
|
||||
* unrecognized, 1 if recognized and some intro points remain.
|
||||
*/
|
||||
int
|
||||
rend_client_remove_intro_point(extend_info_t *failed_intro,
|
||||
const rend_data_t *rend_query)
|
||||
rend_client_report_intro_point_failure(extend_info_t *failed_intro,
|
||||
const rend_data_t *rend_query,
|
||||
unsigned int failure_type)
|
||||
{
|
||||
int i, r;
|
||||
rend_cache_entry_t *ent;
|
||||
@ -680,9 +691,21 @@ rend_client_remove_intro_point(extend_info_t *failed_intro,
|
||||
rend_intro_point_t *intro = smartlist_get(ent->parsed->intro_nodes, i);
|
||||
if (tor_memeq(failed_intro->identity_digest,
|
||||
intro->extend_info->identity_digest, DIGEST_LEN)) {
|
||||
switch (failure_type) {
|
||||
default:
|
||||
log_warn(LD_BUG, "Unknown failure type %u. Removing intro point.",
|
||||
failure_type);
|
||||
tor_fragile_assert();
|
||||
/* fall through */
|
||||
case INTRO_POINT_FAILURE_GENERIC:
|
||||
rend_intro_point_free(intro);
|
||||
smartlist_del(ent->parsed->intro_nodes, i);
|
||||
break;
|
||||
case INTRO_POINT_FAILURE_TIMEOUT:
|
||||
intro->timed_out = 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -911,6 +934,13 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry,
|
||||
usable_nodes = smartlist_create();
|
||||
smartlist_add_all(usable_nodes, entry->parsed->intro_nodes);
|
||||
|
||||
/* Remove the intro points that have timed out during this HS
|
||||
* connection attempt from our list of usable nodes. */
|
||||
SMARTLIST_FOREACH(usable_nodes, rend_intro_point_t *, ip,
|
||||
if (ip->timed_out) {
|
||||
SMARTLIST_DEL_CURRENT(usable_nodes, ip);
|
||||
});
|
||||
|
||||
again:
|
||||
if (smartlist_len(usable_nodes) == 0) {
|
||||
if (n_excluded && get_options()->StrictNodes && warnings) {
|
||||
|
@ -22,8 +22,14 @@ int rend_client_introduction_acked(origin_circuit_t *circ,
|
||||
void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query);
|
||||
void rend_client_cancel_descriptor_fetches(void);
|
||||
void rend_client_purge_last_hid_serv_requests(void);
|
||||
int rend_client_remove_intro_point(extend_info_t *failed_intro,
|
||||
const rend_data_t *rend_query);
|
||||
|
||||
#define INTRO_POINT_FAILURE_GENERIC 0
|
||||
#define INTRO_POINT_FAILURE_TIMEOUT 1
|
||||
|
||||
int rend_client_report_intro_point_failure(extend_info_t *failed_intro,
|
||||
const rend_data_t *rend_query,
|
||||
unsigned int failure_type);
|
||||
|
||||
int rend_client_rendezvous_acked(origin_circuit_t *circ,
|
||||
const uint8_t *request,
|
||||
size_t request_len);
|
||||
|
Loading…
Reference in New Issue
Block a user