diff options
author | Nick Mathewson <nickm@torproject.org> | 2006-12-26 22:41:43 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2006-12-26 22:41:43 +0000 |
commit | 1df04d70f7151f5ff230b3bc65fee7f820808aaa (patch) | |
tree | 0447fafe413bc3bb67519e583253331712049d11 /src | |
parent | 92e2d687fa7fe13d36b478dcf2acbfe63a0e9c33 (diff) | |
download | tor-1df04d70f7151f5ff230b3bc65fee7f820808aaa.tar.gz tor-1df04d70f7151f5ff230b3bc65fee7f820808aaa.zip |
r11718@Kushana: nickm | 2006-12-26 16:57:44 -0500
Add client-side caching for reverse DNS.
svn:r9194
Diffstat (limited to 'src')
-rw-r--r-- | src/or/connection_edge.c | 123 |
1 files changed, 101 insertions, 22 deletions
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 2c6f3205fb..29e3858734 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -664,6 +664,7 @@ addressmap_rewrite(char *address, size_t maxlen) { addressmap_entry_t *ent; int rewrites; + char *cp; for (rewrites = 0; rewrites < 16; rewrites++) { ent = strmap_get(addressmap, address); @@ -671,8 +672,10 @@ addressmap_rewrite(char *address, size_t maxlen) if (!ent || !ent->new_address) return; /* done, no rewrite needed */ + cp = tor_strdup(escaped_safe_str(ent->new_address)); log_info(LD_APP, "Addressmap: rewriting '%s' to '%s'", - safe_str(address), safe_str(ent->new_address)); + escaped_safe_str(address), cp); + tor_free(cp); strlcpy(address, ent->new_address, maxlen); } log_warn(LD_CONFIG, @@ -681,6 +684,28 @@ addressmap_rewrite(char *address, size_t maxlen) /* it's fine to rewrite a rewrite, but don't loop forever */ } +/* DOCDOC */ +static int +addressmap_rewrite_reverse(char *address, size_t maxlen) +{ + size_t len = maxlen + 16; + char *s = tor_malloc(len), *cp; + addressmap_entry_t *ent; + int r = 0; + tor_snprintf(s, len, "REVERSE[%s]", address); + ent = strmap_get(addressmap, s); + if (ent) { + cp = tor_strdup(escaped_safe_str(ent->new_address)); + log_info(LD_APP, "Rewrote reverse lookup '%s' -> '%s'", + escaped_safe_str(s), cp); + tor_free(cp); + strlcpy(address, ent->new_address, maxlen); + r = 1; + } + tor_free(s); + return r; +} + /** Return 1 if <b>address</b> is already registered, else return 0 */ int addressmap_have_mapping(const char *address) @@ -775,7 +800,7 @@ client_dns_clear_failures(const char *address) ent->num_resolve_failures = 0; } -/** Record the fact that <b>address</b> resolved to <b>val</b>. +/** Record the fact that <b>address</b> resolved to <b>name</b>. * We can now use this in subsequent streams via addressmap_rewrite() * so we can more correctly choose an exit that will allow <b>address</b>. * @@ -785,30 +810,24 @@ client_dns_clear_failures(const char *address) * If <b>ttl</b> is nonnegative, the mapping will be valid for * <b>ttl</b>seconds; otherwise, we use the default. */ -void -client_dns_set_addressmap(const char *address, uint32_t val, - const char *exitname, - int ttl) +static void +client_dns_set_addressmap_impl(const char *address, const char *name, + const char *exitname, + int ttl) { - struct in_addr in; /* <address>.<hex or nickname>.exit\0 or just <address>\0 */ char extendedaddress[MAX_SOCKS_ADDR_LEN+MAX_VERBOSE_NICKNAME_LEN+10]; /* 123.123.123.123.<hex or nickname>.exit\0 or just 123.123.123.123\0 */ char extendedval[INET_NTOA_BUF_LEN+MAX_VERBOSE_NICKNAME_LEN+10]; - char valbuf[INET_NTOA_BUF_LEN]; tor_assert(address); - tor_assert(val); + tor_assert(name); if (ttl<0) ttl = DEFAULT_DNS_TTL; else ttl = dns_clip_ttl(ttl); - if (tor_inet_aton(address, &in)) - return; /* If address was an IP address already, don't add a mapping. */ - in.s_addr = htonl(val); - tor_inet_ntoa(&in,valbuf,sizeof(valbuf)); if (exitname) { /* XXXX fails to ever get attempts to get an exit address of * google.com.digest[=~]nickname.exit; we need a syntax for this that @@ -816,17 +835,58 @@ client_dns_set_addressmap(const char *address, uint32_t val, tor_snprintf(extendedaddress, sizeof(extendedaddress), "%s.%s.exit", address, exitname); tor_snprintf(extendedval, sizeof(extendedval), - "%s.%s.exit", valbuf, exitname); + "%s.%s.exit", name, exitname); } else { tor_snprintf(extendedaddress, sizeof(extendedaddress), "%s", address); tor_snprintf(extendedval, sizeof(extendedval), - "%s", valbuf); + "%s", name); } addressmap_register(extendedaddress, tor_strdup(extendedval), time(NULL) + ttl); } +/** Record the fact that <b>address</b> resolved to <b>val</b>. + * We can now use this in subsequent streams via addressmap_rewrite() + * so we can more correctly choose an exit that will allow <b>address</b>. + * + * If <b>exitname</b> is defined, then append the addresses with + * ".exitname.exit" before registering the mapping. + * + * If <b>ttl</b> is nonnegative, the mapping will be valid for + * <b>ttl</b>seconds; otherwise, we use the default. + */ +void +client_dns_set_addressmap(const char *address, uint32_t val, + const char *exitname, + int ttl) +{ + struct in_addr in; + char valbuf[INET_NTOA_BUF_LEN]; + + tor_assert(address); + + if (tor_inet_aton(address, &in)) + return; /* If address was an IP address already, don't add a mapping. */ + in.s_addr = htonl(val); + tor_inet_ntoa(&in,valbuf,sizeof(valbuf)); + + client_dns_set_addressmap_impl(address, valbuf, exitname, ttl); +} + +/** DOCDOC */ +static void +client_dns_set_reverse_addressmap(const char *address, const char *v, + const char *exitname, + int ttl) +{ + size_t len = strlen(address) + 16; + char *s = tor_malloc(len); + tor_snprintf(s, len, "REVERSE[%s]", address); + client_dns_set_addressmap_impl(s, v, exitname, ttl); + tor_free(s); +} + /* By default, we hand out 127.192.0.1 through 127.254.254.254. * These addresses should map to localhost, so even if the * application accidentally tried to connect to them directly (not @@ -1103,8 +1163,19 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, safe_str(socks->address), socks->port); - /* For address map controls, remap the address */ - addressmap_rewrite(socks->address, sizeof(socks->address)); + if (socks->command == SOCKS_COMMAND_RESOLVE_PTR) { + if (addressmap_rewrite_reverse(socks->address, sizeof(socks->address))) { + connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_HOSTNAME, + strlen(socks->address), + socks->address, -1); + connection_mark_unattached_ap(conn, + END_STREAM_REASON_ALREADY_SOCKS_REPLIED); + return 0; + } + } else { + /* For address map controls, remap the address */ + addressmap_rewrite(socks->address, sizeof(socks->address)); + } if (address_is_in_virtual_range(socks->address)) { /* This address was probably handed out by client_dns_get_unmapped_address, @@ -1826,11 +1897,19 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn, char buf[384]; size_t replylen; - if (answer_type == RESOLVED_TYPE_IPV4) { - uint32_t a = ntohl(get_uint32(answer)); - if (a) - client_dns_set_addressmap(conn->socks_request->address, a, - conn->chosen_exit_name, ttl); + if (ttl >= 0) { + if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) { + uint32_t a = ntohl(get_uint32(answer)); + if (a) + client_dns_set_addressmap(conn->socks_request->address, a, + conn->chosen_exit_name, ttl); + } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) { + char *cp = tor_strndup(answer, answer_len); + client_dns_set_reverse_addressmap(conn->socks_request->address, + cp, + conn->chosen_exit_name, ttl); + tor_free(cp); + } } if (conn->socks_request->socks_version == 4) { |