Make DNS callback pass IPv6 answers to dns_answer_found

Also, count ipv6 timeouts vs others.  If we have too many ipv6
requests time out, then we could be degrading performance because of a
broken DNS server that ignores AAAA requests.  Other cases in which
we never learn an AAAA address aren't so bad, since they don't slow
A (ipv4) answers down very much.
This commit is contained in:
Nick Mathewson 2012-10-27 16:34:49 -04:00
parent 00633b9446
commit b7843ca554
2 changed files with 68 additions and 7 deletions

View File

@ -1342,6 +1342,10 @@ configure_nameservers(int force)
return -1;
}
static uint64_t n_ipv6_requests_made = 0;
static uint64_t n_ipv6_timeouts = 0;
static int dns_is_broken_for_ipv6 = 0;
/** For eventdns: Called when we get an answer for a request we launched.
* See eventdns.h for arguments; 'arg' holds the address we tried to resolve.
*/
@ -1352,20 +1356,39 @@ evdns_callback(int result, char type, int count, int ttl, void *addresses,
char *string_address = arg;
uint8_t is_reverse = 0;
int status = DNS_RESOLVE_FAILED_PERMANENT;
uint32_t addr = 0;
tor_addr_t addr;
const char *hostname = NULL;
int was_wildcarded = 0;
tor_addr_make_unspec(&addr); /*WRONG WRONG WRONG XXXX XXXXX IPV6 prop208*/
/* Keep track of whether IPv6 is working */
if (type == DNS_IPv6_AAAA) {
if (result == DNS_ERR_TIMEOUT) {
++n_ipv6_timeouts;
}
if (n_ipv6_timeouts > 10 &&
n_ipv6_timeouts > n_ipv6_requests_made / 2) {
if (! dns_is_broken_for_ipv6) {
log_notice(LD_EXIT, "More than half of our IPv6 requests seem to "
"have timed out. I'm going to assume I can't get AAAA "
"responses.");
dns_is_broken_for_ipv6 = 1;
}
}
}
if (result == DNS_ERR_NONE) {
if (type == DNS_IPv4_A && count) {
char answer_buf[INET_NTOA_BUF_LEN+1];
struct in_addr in;
char *escaped_address;
uint32_t *addrs = addresses;
in.s_addr = addrs[0];
addr = ntohl(addrs[0]);
tor_addr_from_ipv4n(&addr, addrs[0]);
status = DNS_RESOLVE_SUCCEEDED;
tor_inet_ntoa(&in, answer_buf, sizeof(answer_buf));
tor_addr_to_str(answer_buf, &addr, sizeof(answer_buf), 0);
escaped_address = esc_for_log(string_address);
if (answer_is_wildcarded(answer_buf)) {
@ -1382,6 +1405,29 @@ evdns_callback(int result, char type, int count, int ttl, void *addresses,
escaped_safe_str(answer_buf));
}
tor_free(escaped_address);
} else if (type == DNS_IPv6_AAAA && count) {
char answer_buf[TOR_ADDR_BUF_LEN];
char *escaped_address;
struct in6_addr *addrs = addresses;
tor_addr_from_in6(&addr, &addrs[0]);
status = DNS_RESOLVE_SUCCEEDED;
tor_inet_ntop(AF_INET6, &addrs[0], answer_buf, sizeof(answer_buf));
escaped_address = esc_for_log(string_address);
if (answer_is_wildcarded(answer_buf)) {
log_debug(LD_EXIT, "eventdns said that %s resolves to ISP-hijacked "
"address %s; treating as a failure.",
safe_str(escaped_address),
escaped_safe_str(answer_buf));
was_wildcarded = 1;
tor_addr_make_unspec(&addr); /* WRONG WRONG ETC XXXXXXXX */
status = DNS_RESOLVE_FAILED_PERMANENT;
} else {
log_debug(LD_EXIT, "eventdns said that %s resolves to %s",
safe_str(escaped_address),
escaped_safe_str(answer_buf));
}
tor_free(escaped_address);
} else if (type == DNS_PTR && count) {
char *escaped_address;
is_reverse = 1;
@ -1666,8 +1712,8 @@ launch_test_addresses(int fd, short event, void *args)
/* This situation is worse than the failure-hijacking situation. When this
* happens, we're no good for DNS requests at all, and we shouldn't really
* be an exit server.*/
if (!options->ServerDNSTestAddresses)
return;
if (options->ServerDNSTestAddresses) {
tor_assert(the_evdns_base);
SMARTLIST_FOREACH_BEGIN(options->ServerDNSTestAddresses,
const char *, address) {
@ -1683,12 +1729,16 @@ launch_test_addresses(int fd, short event, void *args)
a = tor_strdup(address);
req = evdns_base_resolve_ipv6(the_evdns_base,
address, DNS_QUERY_NO_SEARCH, evdns_callback, a);
++n_ipv6_requests_made;
if (!req) {
log_info(LD_EXIT, "eventdns rejected test address %s",
escaped_safe_str(address));
tor_free(a);
}
} SMARTLIST_FOREACH_END(address);
} /*XXXX REINDENT */
}
#define N_WILDCARD_CHECKS 2
@ -1756,6 +1806,13 @@ dns_seems_to_be_broken(void)
return dns_is_completely_invalid;
}
/** DOCDOC */
int
dns_seems_to_be_broken_for_ipv6(void)
{
return dns_is_broken_for_ipv6;
}
/** Forget what we've previously learned about our DNS servers' correctness. */
void
dns_reset_correctness_checks(void)
@ -1765,6 +1822,8 @@ dns_reset_correctness_checks(void)
n_wildcard_requests = 0;
n_ipv6_requests_made = n_ipv6_timeouts = 0;
if (dns_wildcard_list) {
SMARTLIST_FOREACH(dns_wildcard_list, char *, cp, tor_free(cp));
smartlist_clear(dns_wildcard_list);
@ -1775,7 +1834,8 @@ dns_reset_correctness_checks(void)
smartlist_clear(dns_wildcarded_test_address_list);
}
dns_wildcard_one_notice_given = dns_wildcard_notice_given =
dns_wildcarded_test_address_notice_given = dns_is_completely_invalid = 0;
dns_wildcarded_test_address_notice_given = dns_is_completely_invalid =
dns_is_broken_for_ipv6 = 0;
}
/** Return true iff we have noticed that the dotted-quad <b>ip</b> has been

View File

@ -24,6 +24,7 @@ void dns_cancel_pending_resolve(const char *question);
int dns_resolve(edge_connection_t *exitconn);
void dns_launch_correctness_checks(void);
int dns_seems_to_be_broken(void);
int dns_seems_to_be_broken_for_ipv6(void);
void dns_reset_correctness_checks(void);
void dump_dns_mem_usage(int severity);