Commit a9424416 authored by Nick Mathewson's avatar Nick Mathewson 🥄
Browse files

r8872@Kushana: nickm | 2006-09-21 14:00:20 -0400

 Implement server-side reverse DNS using eventdns.  Add an option to routerdescs so we can tell which servers have eventdns enabled.


svn:r8437
parent b2cc52fa
Changes in version 0.1.2.2-alpha - 2006-??-?? Changes in version 0.1.2.2-alpha - 2006-??-??
o Major features:
- Add server-side support for "reverse" DNS lookups (using PTR
records so clients can determine the canonical hostname for a given
IPv4 address). This has been specified for a long time, but was
previously never implemented. This is only supported by eventdns;
servers now announce in their descriptors whether they support
eventdns.
o Security Fixes, minor o Security Fixes, minor
- If a client asked for a server by name, and we didn't have a - If a client asked for a server by name, and we didn't have a
......
...@@ -100,13 +100,15 @@ d - Autodetect whether DNS is broken in this way. ...@@ -100,13 +100,15 @@ d - Autodetect whether DNS is broken in this way.
d - Add option to use /etc/hosts? d - Add option to use /etc/hosts?
d - Special-case localhost? d - Special-case localhost?
- Verify that it works on windows - Verify that it works on windows
N - Make reverse DNS work. . Make reverse DNS work.
- Specify o Specify
X Implement with dnsworkers X Implement with dnsworkers
(There's no point doing this, since we will throw away dnsworkers once (There's no point doing this, since we will throw away dnsworkers once
eventdns is confirmed to work everywhere.) eventdns is confirmed to work everywhere.)
o Implement in eventdns o Implement in eventdns
- Connect to resolve cells, server-side. o Connect to resolve cells, server-side.
o Add element to routerinfo to note routers that aren't using eventdns,
so we can avoid sending them reverse DNS etc.
- Add client-side interface - Add client-side interface
- Performance improvements - Performance improvements
......
...@@ -254,7 +254,22 @@ $Id$ ...@@ -254,7 +254,22 @@ $Id$
[We didn't start parsing these lines until Tor 0.1.0.6-rc; they should [We didn't start parsing these lines until Tor 0.1.0.6-rc; they should
be marked with "opt" until earlier versions of Tor are obsolete.] be marked with "opt" until earlier versions of Tor are obsolete.]
2.1. Nonterminals in routerdescriptors "eventdns" bool NL
Declare whether this version of Tor is using the newer enhanced
dns logic. Versions of Tor without eventdns SHOULD not be used for
reverse hostname lookups.
[All versions of Tor before 0.1.2.2-alpha should be assumed to have
this option set to 0 if it is not present. All Tor versions at
0.1.2.2-alpha or later should be assumed to have this option set to
1 if it is not present. Until 0.1.2.1-alpha-dev, this option was
not generated, even when eventdns was in use. Versions of Tor
before 0.1.2.1-alpha-dev did not parse this option, so it should be
marked "opt". With some future version, the old 'dnsworker' logic
will be removed, rendering this option of historical interest only.]
2.1. Nonterminals in router descriptors
nickname ::= between 1 and 19 alphanumeric characters, case-insensitive. nickname ::= between 1 and 19 alphanumeric characters, case-insensitive.
...@@ -270,6 +285,8 @@ $Id$ ...@@ -270,6 +285,8 @@ $Id$
ip6 ::= an IPv6 address, surrounded by square brackets. ip6 ::= an IPv6 address, surrounded by square brackets.
num_ip6_bits ::= an integer between 0 and 128 num_ip6_bits ::= an integer between 0 and 128
bool ::= "0" | "1"
Ports are required; if they are not included in the router Ports are required; if they are not included in the router
line, they must appear in the "ports" lines. line, they must appear in the "ports" lines.
......
...@@ -97,8 +97,12 @@ typedef struct cached_resolve_t { ...@@ -97,8 +97,12 @@ typedef struct cached_resolve_t {
HT_ENTRY(cached_resolve_t) node; HT_ENTRY(cached_resolve_t) node;
uint32_t magic; uint32_t magic;
char address[MAX_ADDRESSLEN]; /**< The hostname to be resolved. */ char address[MAX_ADDRESSLEN]; /**< The hostname to be resolved. */
uint32_t addr; /**< IPv4 addr for <b>address</b>. */ union {
uint32_t addr; /**< IPv4 addr for <b>address</b>. */
char *hostname; /**< Hostname for <b>address</b> (if a reverse lookup) */
} result;
uint8_t state; /**< Is this cached entry pending/done/valid/failed? */ uint8_t state; /**< Is this cached entry pending/done/valid/failed? */
uint8_t is_reverse; /**< Is this a reverse (addr-to-hostname) lookup? */
time_t expire; /**< Remove items from cache after this time. */ time_t expire; /**< Remove items from cache after this time. */
uint32_t ttl; /**< What TTL did the nameserver tell us? */ uint32_t ttl; /**< What TTL did the nameserver tell us? */
/** Connections that want to know when we get an answer for this resolve. */ /** Connections that want to know when we get an answer for this resolve. */
...@@ -106,7 +110,8 @@ typedef struct cached_resolve_t { ...@@ -106,7 +110,8 @@ typedef struct cached_resolve_t {
} cached_resolve_t; } cached_resolve_t;
static void purge_expired_resolves(time_t now); static void purge_expired_resolves(time_t now);
static void dns_found_answer(const char *address, uint32_t addr, char outcome, static void dns_found_answer(const char *address, int is_reverse,
uint32_t addr, const char *hostname, char outcome,
uint32_t ttl); uint32_t ttl);
static void send_resolved_cell(edge_connection_t *conn, uint8_t answer_type); static void send_resolved_cell(edge_connection_t *conn, uint8_t answer_type);
static int launch_resolve(edge_connection_t *exitconn); static int launch_resolve(edge_connection_t *exitconn);
...@@ -245,6 +250,8 @@ _free_cached_resolve(cached_resolve_t *r) ...@@ -245,6 +250,8 @@ _free_cached_resolve(cached_resolve_t *r)
r->pending_connections = victim->next; r->pending_connections = victim->next;
tor_free(victim); tor_free(victim);
} }
if (r->is_reverse)
tor_free(r->result.hostname);
r->magic = 0xFF00FF00; r->magic = 0xFF00FF00;
tor_free(r); tor_free(r);
} }
...@@ -362,6 +369,8 @@ purge_expired_resolves(time_t now) ...@@ -362,6 +369,8 @@ purge_expired_resolves(time_t now)
removed ? removed->address : "NULL", (void*)remove); removed ? removed->address : "NULL", (void*)remove);
} }
tor_assert(removed == resolve); tor_assert(removed == resolve);
if (resolve->is_reverse)
tor_free(resolve->result.hostname);
resolve->magic = 0xF0BBF0BB; resolve->magic = 0xF0BBF0BB;
tor_free(resolve); tor_free(resolve);
} else { } else {
...@@ -415,6 +424,74 @@ send_resolved_cell(edge_connection_t *conn, uint8_t answer_type) ...@@ -415,6 +424,74 @@ send_resolved_cell(edge_connection_t *conn, uint8_t answer_type)
conn->cpath_layer); conn->cpath_layer);
} }
/** Send a response to the RESOLVE request of a connection for an in-addr.arpa
* address on connection <b>conn</b> which yielded the result <b>hostname</b>.
* The answer type will be RESOLVED_HOSTNAME.
*/
static void
send_resolved_hostname_cell(edge_connection_t *conn, const char *hostname)
{
char buf[RELAY_PAYLOAD_SIZE];
size_t buflen;
uint32_t ttl;
size_t namelen = strlen(hostname);
tor_assert(namelen < 256);
ttl = dns_clip_ttl(conn->address_ttl);
buf[0] = RESOLVED_TYPE_HOSTNAME;
buf[1] = (uint8_t)namelen;
memcpy(buf+2, hostname, namelen);
set_uint32(buf+2+namelen, htonl(ttl));
buflen = 2+namelen+4;
connection_edge_send_command(conn, circuit_get_by_edge_conn(conn),
RELAY_COMMAND_RESOLVED, buf, buflen,
conn->cpath_layer);
}
/** Given a lower-case <b>address</b>, check to see whether it's a
* 1.2.3.4.in-addr.arpa address used for reverse lookups. If so,
* parse it and place the address in <b>in</b> if present. Return 1 on success;
* 0 if the address is not in in-addr.arpa format, and -1 if the address is
* malformed. */
static int
parse_inaddr_arpa_address(const char *address, struct in_addr *in)
{
char buf[INET_NTOA_BUF_LEN];
char *cp;
size_t len;
struct in_addr inaddr;
cp = strstr(address, ".in-addr.arpa");
if (!cp || *(cp+strlen(".in-addr.arpa")))
return 0; /* not an .in-addr.arpa address */
len = cp - address;
if (len >= INET_NTOA_BUF_LEN)
return -1; /* Too long. */
memcpy(buf, cp, len);
buf[len] = '\0';
if (tor_inet_aton(buf, &inaddr) == 0)
return -1; /* malformed. */
if (in) {
uint32_t a;
/* reverse the bytes */
a = ( ((inaddr.s_addr & 0x000000fful) << 24)
|((inaddr.s_addr & 0x0000ff00ul) << 8)
|((inaddr.s_addr & 0x00ff0000ul) >> 8)
|((inaddr.s_addr & 0xff000000ul) >> 24));
inaddr.s_addr = a;
memcpy(in, &inaddr, sizeof(inaddr));
}
return 1;
}
/** See if we have a cache entry for <b>exitconn</b>-\>address. if so, /** See if we have a cache entry for <b>exitconn</b>-\>address. if so,
* if resolve valid, put it into <b>exitconn</b>-\>addr and return 1. * if resolve valid, put it into <b>exitconn</b>-\>addr and return 1.
* If resolve failed, unlink exitconn if needed, free it, and return -1. * If resolve failed, unlink exitconn if needed, free it, and return -1.
...@@ -431,20 +508,23 @@ dns_resolve(edge_connection_t *exitconn) ...@@ -431,20 +508,23 @@ dns_resolve(edge_connection_t *exitconn)
cached_resolve_t *resolve; cached_resolve_t *resolve;
cached_resolve_t search; cached_resolve_t search;
pending_connection_t *pending_connection; pending_connection_t *pending_connection;
struct in_addr in;
circuit_t *circ; circuit_t *circ;
struct in_addr in;
time_t now = time(NULL); time_t now = time(NULL);
int is_reverse = 0, is_resolve, r;
assert_connection_ok(TO_CONN(exitconn), 0); assert_connection_ok(TO_CONN(exitconn), 0);
tor_assert(exitconn->_base.s == -1); tor_assert(exitconn->_base.s == -1);
assert_cache_ok(); assert_cache_ok();
is_resolve = exitconn->_base.purpose = EXIT_PURPOSE_RESOLVE;
/* first check if exitconn->_base.address is an IP. If so, we already /* first check if exitconn->_base.address is an IP. If so, we already
* know the answer. */ * know the answer. */
if (tor_inet_aton(exitconn->_base.address, &in) != 0) { if (tor_inet_aton(exitconn->_base.address, &in) != 0) {
exitconn->_base.addr = ntohl(in.s_addr); exitconn->_base.addr = ntohl(in.s_addr);
exitconn->address_ttl = DEFAULT_DNS_TTL; exitconn->address_ttl = DEFAULT_DNS_TTL;
if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE) if (is_resolve)
send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4); send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
return 1; return 1;
} }
...@@ -456,6 +536,42 @@ dns_resolve(edge_connection_t *exitconn) ...@@ -456,6 +536,42 @@ dns_resolve(edge_connection_t *exitconn)
/* lower-case exitconn->_base.address, so it's in canonical form */ /* lower-case exitconn->_base.address, so it's in canonical form */
tor_strlower(exitconn->_base.address); tor_strlower(exitconn->_base.address);
/* Check whether this is a reverse lookup. If it's malformed, or it's a
* .in-addr.arpa address but this isn't a resolve request, kill the
* connecction.
*/
if ((r = parse_inaddr_arpa_address(exitconn->_base.address, NULL)) != 0) {
if (r == 1)
is_reverse = 1;
#ifdef USE_EVENTDNS
if (!is_reverse || !is_resolve) {
if (!is_reverse)
log_info(LD_EXIT, "Bad .in-addr.arpa address \"%s\"; sending error.",
escaped_safe_str(exitconn->_base.address));
else if (!is_resolve)
log_info(LD_EXIT,
"Attempt to connect to a .in-addr.arpa address \"%s\"; "
"sending error.",
escaped_safe_str(exitconn->_base.address));
#else
if (1) {
log_info(LD_PROTOCOL, "Dnsworker code does not support in-addr.arpa "
"domain, but received a request for \"%s\"; sending error.",
escaped_safe_str(exitconn->_base.address));
#endif
if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE)
send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR);
circ = circuit_get_by_edge_conn(exitconn);
if (circ)
circuit_detach_stream(circ, exitconn);
if (!exitconn->_base.marked_for_close)
connection_free(TO_CONN(exitconn));
return -1;
}
}
/* now check the hash table to see if 'address' is already there. */ /* now check the hash table to see if 'address' is already there. */
strlcpy(search.address, exitconn->_base.address, sizeof(search.address)); strlcpy(search.address, exitconn->_base.address, sizeof(search.address));
resolve = HT_FIND(cache_map, &cache_root, &search); resolve = HT_FIND(cache_map, &cache_root, &search);
...@@ -474,19 +590,24 @@ dns_resolve(edge_connection_t *exitconn) ...@@ -474,19 +590,24 @@ dns_resolve(edge_connection_t *exitconn)
exitconn->_base.state = EXIT_CONN_STATE_RESOLVING; exitconn->_base.state = EXIT_CONN_STATE_RESOLVING;
return 0; return 0;
case CACHE_STATE_CACHED_VALID: case CACHE_STATE_CACHED_VALID:
exitconn->_base.addr = resolve->addr;
exitconn->address_ttl = resolve->ttl;
log_debug(LD_EXIT,"Connection (fd %d) found cached answer for %s", log_debug(LD_EXIT,"Connection (fd %d) found cached answer for %s",
exitconn->_base.s, exitconn->_base.s,
escaped_safe_str(exitconn->_base.address)); escaped_safe_str(resolve->address));
if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE) exitconn->address_ttl = resolve->ttl;
send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4); if (resolve->is_reverse) {
tor_assert(is_resolve);
send_resolved_hostname_cell(exitconn, resolve->result.hostname);
} else {
exitconn->_base.addr = resolve->result.addr;
if (is_resolve)
send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
}
return 1; return 1;
case CACHE_STATE_CACHED_FAILED: case CACHE_STATE_CACHED_FAILED:
log_debug(LD_EXIT,"Connection (fd %d) found cached error for %s", log_debug(LD_EXIT,"Connection (fd %d) found cached error for %s",
exitconn->_base.s, exitconn->_base.s,
escaped_safe_str(exitconn->_base.address)); escaped_safe_str(exitconn->_base.address));
if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE) if (is_resolve)
send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR); send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR);
circ = circuit_get_by_edge_conn(exitconn); circ = circuit_get_by_edge_conn(exitconn);
if (circ) if (circ)
...@@ -504,6 +625,7 @@ dns_resolve(edge_connection_t *exitconn) ...@@ -504,6 +625,7 @@ dns_resolve(edge_connection_t *exitconn)
resolve = tor_malloc_zero(sizeof(cached_resolve_t)); resolve = tor_malloc_zero(sizeof(cached_resolve_t));
resolve->magic = CACHED_RESOLVE_MAGIC; resolve->magic = CACHED_RESOLVE_MAGIC;
resolve->state = CACHE_STATE_PENDING; resolve->state = CACHE_STATE_PENDING;
resolve->is_reverse = is_reverse;
strlcpy(resolve->address, exitconn->_base.address, sizeof(resolve->address)); strlcpy(resolve->address, exitconn->_base.address, sizeof(resolve->address));
/* add this connection to the pending list */ /* add this connection to the pending list */
...@@ -612,7 +734,7 @@ connection_dns_remove(edge_connection_t *conn) ...@@ -612,7 +734,7 @@ connection_dns_remove(edge_connection_t *conn)
* <b>address</b> from the cache. * <b>address</b> from the cache.
*/ */
void void
dns_cancel_pending_resolve(char *address) dns_cancel_pending_resolve(const char *address)
{ {
pending_connection_t *pend; pending_connection_t *pend;
cached_resolve_t search; cached_resolve_t search;
...@@ -675,10 +797,13 @@ dns_cancel_pending_resolve(char *address) ...@@ -675,10 +797,13 @@ dns_cancel_pending_resolve(char *address)
/** Helper: adds an entry to the DNS cache mapping <b>address</b> to the ipv4 /** Helper: adds an entry to the DNS cache mapping <b>address</b> to the ipv4
* address <b>addr</b>. <b>ttl</b> is a cache ttl; <b>outcome</b> is one of * address <b>addr</b>. <b>ttl</b> is a cache ttl; <b>outcome</b> is one of
* DNS_RESOLVE_{FAILED_TRANSIENT|FAILED_PERMANENT|SUCCEEDED}. */ * DNS_RESOLVE_{FAILED_TRANSIENT|FAILED_PERMANENT|SUCCEEDED}.
*
* DOCDOC args
**/
static void static void
add_answer_to_cache(const char *address, uint32_t addr, char outcome, add_answer_to_cache(const char *address, int is_reverse, uint32_t addr,
uint32_t ttl) const char *hostname, char outcome, uint32_t ttl)
{ {
cached_resolve_t *resolve; cached_resolve_t *resolve;
if (outcome == DNS_RESOLVE_FAILED_TRANSIENT) if (outcome == DNS_RESOLVE_FAILED_TRANSIENT)
...@@ -689,7 +814,13 @@ add_answer_to_cache(const char *address, uint32_t addr, char outcome, ...@@ -689,7 +814,13 @@ add_answer_to_cache(const char *address, uint32_t addr, char outcome,
resolve->state = (outcome == DNS_RESOLVE_SUCCEEDED) ? resolve->state = (outcome == DNS_RESOLVE_SUCCEEDED) ?
CACHE_STATE_CACHED_VALID : CACHE_STATE_CACHED_FAILED; CACHE_STATE_CACHED_VALID : CACHE_STATE_CACHED_FAILED;
strlcpy(resolve->address, address, sizeof(resolve->address)); strlcpy(resolve->address, address, sizeof(resolve->address));
resolve->addr = addr; if (is_reverse) {
tor_assert(hostname);
resolve->result.hostname = tor_strdup(hostname);
} else {
tor_assert(!hostname);
resolve->result.addr = addr;
}
resolve->ttl = ttl; resolve->ttl = ttl;
assert_resolve_ok(resolve); assert_resolve_ok(resolve);
HT_INSERT(cache_map, &cache_root, resolve); HT_INSERT(cache_map, &cache_root, resolve);
...@@ -704,8 +835,8 @@ add_answer_to_cache(const char *address, uint32_t addr, char outcome, ...@@ -704,8 +835,8 @@ add_answer_to_cache(const char *address, uint32_t addr, char outcome,
* DNS_RESOLVE_{FAILED_TRANSIENT|FAILED_PERMANENT|SUCCEEDED}. * DNS_RESOLVE_{FAILED_TRANSIENT|FAILED_PERMANENT|SUCCEEDED}.
*/ */
static void static void
dns_found_answer(const char *address, uint32_t addr, char outcome, dns_found_answer(const char *address, int is_reverse, uint32_t addr,
uint32_t ttl) const char *hostname, char outcome, uint32_t ttl)
{ {
pending_connection_t *pend; pending_connection_t *pend;
cached_resolve_t search; cached_resolve_t search;
...@@ -721,7 +852,7 @@ dns_found_answer(const char *address, uint32_t addr, char outcome, ...@@ -721,7 +852,7 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
if (!resolve) { if (!resolve) {
log_info(LD_EXIT,"Resolved unasked address %s; caching anyway.", log_info(LD_EXIT,"Resolved unasked address %s; caching anyway.",
escaped_safe_str(address)); escaped_safe_str(address));
add_answer_to_cache(address, addr, outcome, ttl); add_answer_to_cache(address, is_reverse, addr, hostname, outcome, ttl);
return; return;
} }
assert_resolve_ok(resolve); assert_resolve_ok(resolve);
...@@ -764,6 +895,7 @@ dns_found_answer(const char *address, uint32_t addr, char outcome, ...@@ -764,6 +895,7 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
connection_free(TO_CONN(pendconn)); connection_free(TO_CONN(pendconn));
} else { } else {
if (pendconn->_base.purpose == EXIT_PURPOSE_CONNECT) { if (pendconn->_base.purpose == EXIT_PURPOSE_CONNECT) {
tor_assert(!is_reverse);
/* prevent double-remove. */ /* prevent double-remove. */
pend->conn->_base.state = EXIT_CONN_STATE_CONNECTING; pend->conn->_base.state = EXIT_CONN_STATE_CONNECTING;
...@@ -782,7 +914,10 @@ dns_found_answer(const char *address, uint32_t addr, char outcome, ...@@ -782,7 +914,10 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
/* prevent double-remove. This isn't really an accurate state, /* prevent double-remove. This isn't really an accurate state,
* but it does the right thing. */ * but it does the right thing. */
pendconn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED; pendconn->_base.state = EXIT_CONN_STATE_RESOLVEFAILED;
send_resolved_cell(pendconn, RESOLVED_TYPE_IPV4); if (is_reverse)
send_resolved_hostname_cell(pendconn, hostname);
else
send_resolved_cell(pendconn, RESOLVED_TYPE_IPV4);
circ = circuit_get_by_edge_conn(pendconn); circ = circuit_get_by_edge_conn(pendconn);
tor_assert(circ); tor_assert(circ);
circuit_detach_stream(circ, pendconn); circuit_detach_stream(circ, pendconn);
...@@ -804,7 +939,7 @@ dns_found_answer(const char *address, uint32_t addr, char outcome, ...@@ -804,7 +939,7 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
assert_resolve_ok(resolve); assert_resolve_ok(resolve);
assert_cache_ok(); assert_cache_ok();
add_answer_to_cache(address, addr, outcome, ttl); add_answer_to_cache(address, is_reverse, addr, hostname, outcome, ttl);
assert_cache_ok(); assert_cache_ok();
} }
...@@ -942,7 +1077,7 @@ connection_dns_process_inbuf(connection_t *conn) ...@@ -942,7 +1077,7 @@ connection_dns_process_inbuf(connection_t *conn)
tor_assert(success <= DNS_RESOLVE_SUCCEEDED); tor_assert(success <= DNS_RESOLVE_SUCCEEDED);
ttl = (success == DNS_RESOLVE_FAILED_TRANSIENT) ? 0 : MAX_DNS_ENTRY_AGE; ttl = (success == DNS_RESOLVE_FAILED_TRANSIENT) ? 0 : MAX_DNS_ENTRY_AGE;
dns_found_answer(conn->address, ntohl(addr), success, ttl); dns_found_answer(conn->address, 0, ntohl(addr), NULL, success, ttl);
tor_free(conn->address); tor_free(conn->address);
conn->address = tor_strdup("<idle>"); conn->address = tor_strdup("<idle>");
...@@ -1320,8 +1455,11 @@ eventdns_callback(int result, char type, int count, int ttl, void *addresses, ...@@ -1320,8 +1455,11 @@ eventdns_callback(int result, char type, int count, int ttl, void *addresses,
void *arg) void *arg)
{ {
char *string_address = arg; char *string_address = arg;
int is_reverse = 0;
int status = DNS_RESOLVE_FAILED_PERMANENT; int status = DNS_RESOLVE_FAILED_PERMANENT;
uint32_t addr = 0; uint32_t addr = 0;
const char *hostname = NULL;
if (result == DNS_ERR_NONE) { if (result == DNS_ERR_NONE) {
if (type == DNS_IPv4_A && count) { if (type == DNS_IPv4_A && count) {
char answer_buf[INET_NTOA_BUF_LEN+1]; char answer_buf[INET_NTOA_BUF_LEN+1];
...@@ -1333,7 +1471,13 @@ eventdns_callback(int result, char type, int count, int ttl, void *addresses, ...@@ -1333,7 +1471,13 @@ eventdns_callback(int result, char type, int count, int ttl, void *addresses,
tor_inet_ntoa(&in, answer_buf, sizeof(answer_buf)); tor_inet_ntoa(&in, answer_buf, sizeof(answer_buf));
log_debug(LD_EXIT, "eventdns said that %s resolves to %s", log_debug(LD_EXIT, "eventdns said that %s resolves to %s",
escaped_safe_str(string_address), escaped_safe_str(string_address),
escaped_safe_str(answer_buf)); escaped_safe_str(answer_buf)); // XXXX not ok.
} else if (type == DNS_PTR && count) {
is_reverse = 1;
hostname = ((char**)addresses)[0];
log_debug(LD_EXIT, "eventdns said that %s resolves to %s",
escaped_safe_str(string_address),
escaped_safe_str(hostname)); // XXXX not ok.
} else if (count) { } else if (count) {
log_warn(LD_EXIT, "eventdns returned only non-IPv4 answers for %s.", log_warn(LD_EXIT, "eventdns returned only non-IPv4 answers for %s.",
escaped_safe_str(string_address)); escaped_safe_str(string_address));
...@@ -1345,7 +1489,7 @@ eventdns_callback(int result, char type, int count, int ttl, void *addresses, ...@@ -1345,7 +1489,7 @@ eventdns_callback(int result, char type, int count, int ttl, void *addresses,
if (eventdns_err_is_transient(result)) if (eventdns_err_is_transient(result))
status = DNS_RESOLVE_FAILED_TRANSIENT; status = DNS_RESOLVE_FAILED_TRANSIENT;
} }
dns_found_answer(string_address, addr, status, ttl); dns_found_answer(string_address, is_reverse, addr, hostname, status, ttl);
tor_free(string_address); tor_free(string_address);
} }
...@@ -1355,6 +1499,7 @@ static int ...@@ -1355,6 +1499,7 @@ static int
launch_resolve(edge_connection_t *exitconn) launch_resolve(edge_connection_t *exitconn)
{ {
char *addr = tor_strdup(exitconn->_base.address); char *addr = tor_strdup(exitconn->_base.address);
struct in_addr in;
int r; int r;
int options = get_options()->SearchDomains ? 0 : DNS_QUERY_NO_SEARCH; int options = get_options()->SearchDomains ? 0 : DNS_QUERY_NO_SEARCH;
/* What? Nameservers not configured? Sounds like a bug. */ /* What? Nameservers not configured? Sounds like a bug. */
...@@ -1364,10 +1509,22 @@ launch_resolve(edge_connection_t *exitconn) ...@@ -1364,10 +1509,22 @@ launch_resolve(edge_connection_t *exitconn)
if (configure_nameservers(1) < 0) if (configure_nameservers(1) < 0)
return -1; return -1;
} }
log_info(LD_EXIT, "Launching eventdns request for %s",
escaped_safe_str(exitconn->_base.address)); r = parse_inaddr_arpa_address(exitconn->_base.address, &in);
r = eventdns_resolve_ipv4(exitconn->_base.address, options, if (r == 0) {
eventdns_callback, addr); log_info(LD_EXIT, "Launching eventdns request for %s",
escaped_safe_str(exitconn->_base.address));
r = eventdns_resolve_ipv4(exitconn->_base.address, options,
eventdns_callback, addr);
} else if (r == 1) {
log_info(LD_EXIT, "Launching eventdns reverse request for %s",
escaped_safe_str(exitconn->_base.address));
r = eventdns_resolve_reverse(&in, DNS_QUERY_NO_SEARCH,
eventdns_callback, addr);
} else if (r == -1) {
log_warn(LD_BUG, "Somehow a malformed in-addr.arpa address reached here.");
}
if (r) { if (r) {
log_warn(LD_EXIT, "eventdns rejected address %s: error %d.", log_warn(LD_EXIT, "eventdns rejected address %s: error %d.",
escaped_safe_str(addr), r); escaped_safe_str(addr), r);
...@@ -1400,7 +1557,10 @@ assert_resolve_ok(cached_resolve_t *resolve) ...@@ -1400,7 +1557,10 @@ assert_resolve_ok(cached_resolve_t *resolve)
if (resolve->state == CACHE_STATE_PENDING || if (resolve->state == CACHE_STATE_PENDING ||
resolve->state == CACHE_STATE_DONE) { resolve->state == CACHE_STATE_DONE) {
tor_assert(!resolve->ttl); tor_assert(!resolve->ttl);
tor_assert(!resolve->addr); if (resolve->is_reverse)
tor_assert(!resolve->result.hostname);
else
tor_assert(!resolve->result.addr);
} }
} }
......
...@@ -900,6 +900,8 @@ typedef struct { ...@@ -900,6 +900,8 @@ typedef struct {
char *contact_info; /**< Declared contact info for this router. */ char *contact_info; /**< Declared contact info for this router. */
unsigned int is_hibernating:1; /**< Whether the router claims to be unsigned int is_hibernating:1; /**< Whether the router claims to be
* hibernating */ * hibernating */
unsigned int has_old_dnsworkers:1; /**< Whether the router is using
* dnsworker code. */
/* local info */ /* local info */
unsigned int is_running:1; /**< As far as we know, is this OR currently unsigned int is_running:1; /**< As far as we know, is this OR currently
...@@ -2154,7 +2156,7 @@ void dns_reset(void); ...@@ -2154,7 +2156,7 @@ void dns_reset(void);
void connection_dns_remove(edge_connection_t *conn); void connection_dns_remove(edge_connection_t *conn);