diff options
-rw-r--r-- | doc/TODO | 2 | ||||
-rw-r--r-- | src/or/circuituse.c | 35 | ||||
-rw-r--r-- | src/or/connection_edge.c | 1 | ||||
-rw-r--r-- | src/or/or.h | 2 | ||||
-rw-r--r-- | src/or/relay.c | 18 |
5 files changed, 48 insertions, 10 deletions
@@ -108,7 +108,7 @@ R - remember the last time we saw one of our entry guards labelled with - If the client's clock is too far in the past, it will drop (or just not try to get) descriptors, so it'll never build circuits. R - Failed rend desc fetches sometimes don't get retried. - - If we fail to connect via an exit enclave, (warn and) try again + o If we fail to connect via an exit enclave, (warn and) try again without demanding that exit node. R - non-v1 authorities should not accept rend descs. - We need a separate list of "hidserv authorities" if we want to diff --git a/src/or/circuituse.c b/src/or/circuituse.c index b6ceafd70..0c7198a7b 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -963,10 +963,16 @@ circuit_get_open_circ_or_launch(connection_t *conn, if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) { if (conn->chosen_exit_name) { routerinfo_t *r; + int opt = conn->chosen_exit_optional; if (!(r = router_get_by_nickname(conn->chosen_exit_name, 1))) { - log_notice(LD_APP, - "Requested exit point '%s' is not known. Closing.", - conn->chosen_exit_name); + log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP, + "Requested exit point '%s' is not known. %s.", + conn->chosen_exit_name, opt ? "Trying others" : "Closing"); + if (opt) { + conn->chosen_exit_optional = 0; + tor_free(conn->chosen_exit_name); + return 0; + } return -1; } extend_info = extend_info_from_router(r); @@ -1151,16 +1157,27 @@ connection_ap_handshake_attach_circuit(connection_t *conn) if (conn->chosen_exit_name) { routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1); + int opt = conn->chosen_exit_optional; if (!router) { - log_warn(LD_APP, - "Requested exit point '%s' is not known. Closing.", - conn->chosen_exit_name); + log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP, + "Requested exit point '%s' is not known. %s.", + conn->chosen_exit_name, opt ? "Trying others" : "Closing"); + if (opt) { + conn->chosen_exit_optional = 0; + tor_free(conn->chosen_exit_name); + return 0; + } return -1; } if (!connection_ap_can_use_exit(conn, router)) { - log_warn(LD_APP, - "Requested exit point '%s' would refuse request. Closing.", - conn->chosen_exit_name); + log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP, + "Requested exit point '%s' would refuse request. %s.", + conn->chosen_exit_name, opt ? "Trying others" : "Closing"); + if (opt) { + conn->chosen_exit_optional = 0; + tor_free(conn->chosen_exit_name); + return 0; + } return -1; } } diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 41948e055..45620e2a3 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1126,6 +1126,7 @@ connection_ap_handshake_rewrite_and_attach(connection_t *conn, routers with this nickname */ conn->chosen_exit_name = tor_strdup(hex_str(r->cache_info.identity_digest, DIGEST_LEN)); + conn->chosen_exit_optional = 1; } } diff --git a/src/or/or.h b/src/or/or.h index 5700221fa..ff3a26e65 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -656,6 +656,8 @@ struct connection_t { /** Nickname of planned exit node -- used with .exit support. */ char *chosen_exit_name; + /** If 1, and we fail to reach the chosen exit, stop requiring it. */ + unsigned int chosen_exit_optional:1; /* Used only by OR connections: */ tor_tls_t *tls; /**< TLS connection state (OR only.) */ diff --git a/src/or/relay.c b/src/or/relay.c index 95b999c72..7dc7d3b7b 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -696,11 +696,21 @@ connection_edge_process_end_not_open( /* rewrite it to an IP if we learned one. */ addressmap_rewrite(conn->socks_request->address, sizeof(conn->socks_request->address)); + if (conn->chosen_exit_optional) { /* stop wanting a specific exit */ + conn->chosen_exit_optional = 0; + tor_free(conn->chosen_exit_name); + } if (connection_ap_detach_retriable(conn, circ) >= 0) return 0; /* else, conn will get closed below */ break; + case END_STREAM_REASON_CONNECTREFUSED: + if (!conn->chosen_exit_optional) + break; /* break means it'll close, below */ + /* Else fall through: expire this circuit, clear the + * chosen_exit_name field, and try again. */ case END_STREAM_REASON_RESOLVEFAILED: + case END_STREAM_REASON_TIMEOUT: case END_STREAM_REASON_MISC: if (client_dns_incr_failures(conn->socks_request->address) < MAX_RESOLVE_FAILURES) { @@ -709,6 +719,10 @@ connection_edge_process_end_not_open( tor_assert(circ->timestamp_dirty); circ->timestamp_dirty -= get_options()->MaxCircuitDirtiness; + if (conn->chosen_exit_optional) { /* stop wanting a specific exit */ + conn->chosen_exit_optional = 0; + tor_free(conn->chosen_exit_name); + } if (connection_ap_detach_retriable(conn, circ) >= 0) return 0; /* else, conn will get closed below */ @@ -729,6 +743,10 @@ connection_edge_process_end_not_open( exitrouter->exit_policy = router_parse_addr_policy_from_string("reject *:*", -1); } + if (conn->chosen_exit_optional) { /* stop wanting a specific exit */ + conn->chosen_exit_optional = 0; + tor_free(conn->chosen_exit_name); + } if (connection_ap_detach_retriable(conn, circ) >= 0) return 0; /* else, will close below */ |