diff options
author | Nick Mathewson <nickm@torproject.org> | 2006-10-01 18:13:16 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2006-10-01 18:13:16 +0000 |
commit | 335a36a50ef26f19ca876d000c325db5e5e80aac (patch) | |
tree | e275ef7bc1c5f1082d018e8bf556716747d30e06 | |
parent | 1912d1a67c9fe1403d5f300cfbd3009d0476edd9 (diff) | |
download | tor-335a36a50ef26f19ca876d000c325db5e5e80aac.tar.gz tor-335a36a50ef26f19ca876d000c325db5e5e80aac.zip |
Backport 8478: fix long-standing server-side DNS bug.
svn:r8562
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | src/or/connection_edge.c | 4 | ||||
-rw-r--r-- | src/or/dns.c | 32 | ||||
-rw-r--r-- | src/or/or.h | 2 |
4 files changed, 25 insertions, 16 deletions
@@ -8,6 +8,9 @@ Changes in version 0.1.1.24 - 2006-09-29 This should improve client CPU usage by 25-50%. - Don't crash if, after a server has been running for a while, it can't resolve its hostname. + - When a client asks us to resolve (not connect to) an address, + and we have a cached answer, give them the cached answer. + Previously, we would give them no answer at all. o Minor bugfixes: - Allow Tor to start when RunAsDaemon is set but no logs are set. diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 902e0c009b..fef46360b8 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1669,7 +1669,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) } /* send it off to the gethostbyname farm */ - switch (dns_resolve(n_stream)) { + switch (dns_resolve(n_stream, NULL)) { case 1: /* resolve worked */ /* add it into the linked list of n_streams on this circuit */ @@ -1723,7 +1723,7 @@ connection_exit_begin_resolve(cell_t *cell, circuit_t *circ) dummy_conn->purpose = EXIT_PURPOSE_RESOLVE; /* send it off to the gethostbyname farm */ - switch (dns_resolve(dummy_conn)) { + switch (dns_resolve(dummy_conn, circ)) { case -1: /* Impossible to resolve; a resolved cell was sent. */ /* Connection freed; don't touch it. */ return 0; diff --git a/src/or/dns.c b/src/or/dns.c index 5303ced78a..81881dd744 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -71,13 +71,14 @@ typedef struct cached_resolve_t { } cached_resolve_t; static void purge_expired_resolves(uint32_t now); -static int assign_to_dnsworker(connection_t *exitconn); +static int assign_to_dnsworker(connection_t *exitconn, circuit_t *oncirc); static void dns_purge_resolve(cached_resolve_t *resolve); static void dns_found_answer(char *address, uint32_t addr, char outcome); static int dnsworker_main(void *data); static int spawn_dnsworker(void); static int spawn_enough_dnsworkers(void); -static void send_resolved_cell(connection_t *conn, uint8_t answer_type); +static void send_resolved_cell(connection_t *conn, circuit_t *circ, + uint8_t answer_type); /** Hash table of cached_resolve objects. */ static HT_HEAD(cache_map, cached_resolve_t) cache_root; @@ -199,7 +200,7 @@ purge_expired_resolves(uint32_t now) /** Send a response to the RESOVLE request of a connection. answer_type must * be one of RESOLVED_TYPE_(IPV4|ERROR|ERROR_TRANSIENT) */ static void -send_resolved_cell(connection_t *conn, uint8_t answer_type) +send_resolved_cell(connection_t *conn, circuit_t *circ, uint8_t answer_type) { char buf[RELAY_PAYLOAD_SIZE]; size_t buflen; @@ -229,7 +230,12 @@ send_resolved_cell(connection_t *conn, uint8_t answer_type) default: tor_assert(0); } - connection_edge_send_command(conn, circuit_get_by_edge_conn(conn), + + if (circ == NULL) { + circ = circuit_get_by_edge_conn(conn); + } + + connection_edge_send_command(conn, circ, RELAY_COMMAND_RESOLVED, buf, buflen, conn->cpath_layer); } @@ -261,7 +267,7 @@ insert_resolve(cached_resolve_t *r) * dns farm, and return 0. */ int -dns_resolve(connection_t *exitconn) +dns_resolve(connection_t *exitconn, circuit_t *oncirc) { cached_resolve_t *resolve; cached_resolve_t search; @@ -277,7 +283,7 @@ dns_resolve(connection_t *exitconn) if (tor_inet_aton(exitconn->address, &in) != 0) { exitconn->addr = ntohl(in.s_addr); if (exitconn->purpose == EXIT_PURPOSE_RESOLVE) - send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4); + send_resolved_cell(exitconn, oncirc, RESOLVED_TYPE_IPV4); return 1; } @@ -310,13 +316,13 @@ dns_resolve(connection_t *exitconn) log_debug(LD_EXIT,"Connection (fd %d) found cached answer for %s", exitconn->s, escaped_safe_str(exitconn->address)); if (exitconn->purpose == EXIT_PURPOSE_RESOLVE) - send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4); + send_resolved_cell(exitconn, oncirc, RESOLVED_TYPE_IPV4); return 1; case CACHE_STATE_FAILED: log_debug(LD_EXIT,"Connection (fd %d) found cached error for %s", exitconn->s, escaped_safe_str(exitconn->address)); if (exitconn->purpose == EXIT_PURPOSE_RESOLVE) - send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR); + send_resolved_cell(exitconn, oncirc, RESOLVED_TYPE_ERROR); circ = circuit_get_by_edge_conn(exitconn); if (circ) circuit_detach_stream(circ, exitconn); @@ -339,14 +345,14 @@ dns_resolve(connection_t *exitconn) exitconn->state = EXIT_CONN_STATE_RESOLVING; insert_resolve(resolve); - return assign_to_dnsworker(exitconn); + return assign_to_dnsworker(exitconn, oncirc); } /** Find or spawn a dns worker process to handle resolving * <b>exitconn</b>-\>address; tell that dns worker to begin resolving. */ static int -assign_to_dnsworker(connection_t *exitconn) +assign_to_dnsworker(connection_t *exitconn, circuit_t *oncirc) { connection_t *dnsconn; unsigned char len; @@ -365,7 +371,7 @@ assign_to_dnsworker(connection_t *exitconn) if (!dnsconn) { log_warn(LD_EXIT,"no idle dns workers. Failing."); if (exitconn->purpose == EXIT_PURPOSE_RESOLVE) - send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR_TRANSIENT); + send_resolved_cell(exitconn, oncirc, RESOLVED_TYPE_ERROR_TRANSIENT); goto err; } @@ -631,7 +637,7 @@ dns_found_answer(char *address, uint32_t addr, char outcome) /* This detach must happen after we send the end cell. */ circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn); } else { - send_resolved_cell(pendconn, RESOLVED_TYPE_ERROR); + send_resolved_cell(pendconn, NULL, RESOLVED_TYPE_ERROR); /* This detach must happen after we send the resolved cell. */ circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn); } @@ -655,7 +661,7 @@ dns_found_answer(char *address, uint32_t addr, char outcome) /* prevent double-remove. This isn't really an accurate state, * but it does the right thing. */ pendconn->state = EXIT_CONN_STATE_RESOLVEFAILED; - send_resolved_cell(pendconn, RESOLVED_TYPE_IPV4); + send_resolved_cell(pendconn, NULL, RESOLVED_TYPE_IPV4); circ = circuit_get_by_edge_conn(pendconn); tor_assert(circ); circuit_detach_stream(circ, pendconn); diff --git a/src/or/or.h b/src/or/or.h index 9b6849eb6b..18c85bc407 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1961,7 +1961,7 @@ void connection_dns_remove(connection_t *conn); void assert_connection_edge_not_dns_pending(connection_t *conn); void assert_all_pending_dns_resolves_ok(void); void dns_cancel_pending_resolve(char *question); -int dns_resolve(connection_t *exitconn); +int dns_resolve(connection_t *exitconn, circuit_t *oncirc); /********************************* hibernate.c **********************/ |