diff options
author | Roger Dingledine <arma@torproject.org> | 2008-02-21 09:00:54 +0000 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2008-02-21 09:00:54 +0000 |
commit | a60f7caa5490a38bd67d01ae65fb08c51250cd87 (patch) | |
tree | 2960a01b5d359b1a7ba823e3628d0cee536fdc09 | |
parent | 18a209ffe6580115124ba08e125ff77c9478dcfb (diff) | |
download | tor-a60f7caa5490a38bd67d01ae65fb08c51250cd87.tar.gz tor-a60f7caa5490a38bd67d01ae65fb08c51250cd87.zip |
start allowing clients to give up on trackhostexits targets if
five circuit attempts fail for a given stream. part of the fix
for bug 437. still an XXX020rc remaining.
svn:r13648
-rw-r--r-- | src/or/connection.c | 2 | ||||
-rw-r--r-- | src/or/connection_edge.c | 29 | ||||
-rw-r--r-- | src/or/or.h | 7 | ||||
-rw-r--r-- | src/or/relay.c | 11 |
4 files changed, 43 insertions, 6 deletions
diff --git a/src/or/connection.c b/src/or/connection.c index 408fbec17b..2c3cbab134 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -2876,7 +2876,7 @@ assert_connection_ok(connection_t *conn, time_t now) assert_buf_ok(conn->outbuf); } - if (conn->chosen_exit_optional) { + if (conn->chosen_exit_optional || conn->chosen_exit_retries) { tor_assert(conn->type == CONN_TYPE_AP); tor_assert((TO_EDGE_CONN(conn))->chosen_exit_name); } diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index a36e7cbe66..b4f79a8c72 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -472,13 +472,16 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info) if (conn->marked_for_close || conn->type != CONN_TYPE_AP || conn->state != AP_CONN_STATE_CIRCUIT_WAIT || - !conn->chosen_exit_optional) + (!conn->chosen_exit_optional && + !conn->chosen_exit_retries)) continue; edge_conn = TO_EDGE_CONN(conn); r1 = router_get_by_nickname(edge_conn->chosen_exit_name, 0); r2 = router_get_by_nickname(info->nickname, 0); - if (r1 && r2 && r1==r2) { - tor_assert(edge_conn->socks_request); + if (!r1 || !r2 || r1 != r2) + continue; + tor_assert(edge_conn->socks_request); + if (conn->chosen_exit_optional) { log_info(LD_APP, "Giving up on enclave exit '%s' for destination %s.", safe_str(edge_conn->chosen_exit_name), escaped_safe_str(edge_conn->socks_request->address)); @@ -488,6 +491,16 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info) * think it'll be using an enclave. */ consider_plaintext_ports(edge_conn, edge_conn->socks_request->port); } + if (conn->chosen_exit_retries) { + if (--conn->chosen_exit_retries == 0) { /* give up! */ + /* XXX020rc unregister maps from foo to + * foo.chosen_exit_name.exit \forall foo. -RD */ + tor_free(edge_conn->chosen_exit_name); /* clears it */ + /* if this port is dangerous, warn or reject it now that we don't + * think it'll be using an enclave. */ + consider_plaintext_ports(edge_conn, edge_conn->socks_request->port); + } + } }); } @@ -1244,6 +1257,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, int automap = 0; char orig_address[MAX_SOCKS_ADDR_LEN]; time_t map_expires = TIME_MAX; + int remapped_to_exit = 0; time_t now = time(NULL); tor_strlower(socks->address); /* normalize it */ @@ -1299,11 +1313,16 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, } } } else if (!automap) { + int started_without_chosen_exit = strcasecmpend(socks->address, ".exit"); /* For address map controls, remap the address. */ if (addressmap_rewrite(socks->address, sizeof(socks->address), &map_expires)) { control_event_stream_status(conn, STREAM_EVENT_REMAP, REMAP_STREAM_SOURCE_CACHE); + if (started_without_chosen_exit && + !strcasecmpend(socks->address, ".exit") && + map_expires < TIME_MAX) + remapped_to_exit = 1; } } @@ -1340,6 +1359,10 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, if (s) { if (s[1] != '\0') { conn->chosen_exit_name = tor_strdup(s+1); +/* DOCDOC */ +#define TRACKHOSTEXITS_RETRIES 5 + if (remapped_to_exit) /* 5 tries before it expires the addressmap */ + TO_CONN(conn)->chosen_exit_retries = TRACKHOSTEXITS_RETRIES; *s = 0; } else { log_warn(LD_APP,"Malformed exit address '%s.exit'. Refusing.", diff --git a/src/or/or.h b/src/or/or.h index 33ae67a4e8..1c5a16f598 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -811,6 +811,11 @@ typedef struct connection_t { /** For AP connections only. If 1, and we fail to reach the chosen exit, * stop requiring it. */ unsigned int chosen_exit_optional:1; + /** For AP connections only. If non-zero, this exit node was picked as + * a result of the TrackHostExit, and the value decrements every time + * we fail to complete a circuit to our chosen exit -- if it reaches + * zero, abandon the associated mapaddress. */ + unsigned int chosen_exit_retries:3; /** Set to 1 when we're inside connection_flushed_some to keep us from * calling connection_handle_write() recursively. */ unsigned int in_flushed_some:1; @@ -861,7 +866,7 @@ typedef struct connection_t { * we marked for close? */ char *address; /**< FQDN (or IP) of the guy on the other end. * strdup into this, because free_connection frees it. */ - /** Annother connection that's connected to this one in lieu of a socket. */ + /** Another connection that's connected to this one in lieu of a socket. */ struct connection_t *linked_conn; /* XXXX021 move this into a subtype. */ diff --git a/src/or/relay.c b/src/or/relay.c index 0dc79e4488..9b3052b392 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -771,9 +771,18 @@ connection_edge_process_end_not_open( NULL)) { control_event_stream_status(conn, STREAM_EVENT_REMAP, 0); } - if (conn->_base.chosen_exit_optional) { + if (conn->_base.chosen_exit_optional || + conn->_base.chosen_exit_retries) { /* stop wanting a specific exit */ conn->_base.chosen_exit_optional = 0; + /* A non-zero chosen_exit_retries can happen if we set a + * TrackHostExits for this address under a port that the exit + * relay allows, but then try the same address with a different + * port that it doesn't allow to exit. We shouldn't unregister + * the mapping, since it is probably still wanted on the + * original port. But now we give away to the exit relay that + * we probably have a TrackHostExits on it. So be it. */ + conn->_base.chosen_exit_retries = 0; tor_free(conn->chosen_exit_name); /* clears it */ } if (connection_ap_detach_retriable(conn, circ, control_reason) >= 0) |