mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Make dns.c use eventdns.c -- but only when you pass the --enable-eventdns argument to configure.in. This will *so* not work on Windows yet.
svn:r6525
This commit is contained in:
parent
7cb3232ade
commit
85a25c8a29
282
src/or/dns.c
282
src/or/dns.c
@ -21,6 +21,9 @@ const char dns_c_id[] =
|
|||||||
|
|
||||||
#include "or.h"
|
#include "or.h"
|
||||||
#include "../common/ht.h"
|
#include "../common/ht.h"
|
||||||
|
#ifdef USE_EVENTDNS
|
||||||
|
#include "eventdns.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Longest hostname we're willing to resolve. */
|
/** Longest hostname we're willing to resolve. */
|
||||||
#define MAX_ADDRESSLEN 256
|
#define MAX_ADDRESSLEN 256
|
||||||
@ -39,12 +42,14 @@ const char dns_c_id[] =
|
|||||||
#define DNS_RESOLVE_FAILED_PERMANENT 2
|
#define DNS_RESOLVE_FAILED_PERMANENT 2
|
||||||
#define DNS_RESOLVE_SUCCEEDED 3
|
#define DNS_RESOLVE_SUCCEEDED 3
|
||||||
|
|
||||||
|
#ifndef USE_EVENTDNS
|
||||||
/** How many dnsworkers we have running right now. */
|
/** How many dnsworkers we have running right now. */
|
||||||
static int num_dnsworkers=0;
|
static int num_dnsworkers=0;
|
||||||
/** How many of the running dnsworkers have an assigned task right now. */
|
/** How many of the running dnsworkers have an assigned task right now. */
|
||||||
static int num_dnsworkers_busy=0;
|
static int num_dnsworkers_busy=0;
|
||||||
/** When did we last rotate the dnsworkers? */
|
/** When did we last rotate the dnsworkers? */
|
||||||
static time_t last_rotation_time=0;
|
static time_t last_rotation_time=0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Linked list of connections waiting for a DNS answer. */
|
/** Linked list of connections waiting for a DNS answer. */
|
||||||
typedef struct pending_connection_t {
|
typedef struct pending_connection_t {
|
||||||
@ -71,13 +76,17 @@ typedef struct cached_resolve_t {
|
|||||||
} cached_resolve_t;
|
} cached_resolve_t;
|
||||||
|
|
||||||
static void purge_expired_resolves(uint32_t now);
|
static void purge_expired_resolves(uint32_t now);
|
||||||
static int assign_to_dnsworker(connection_t *exitconn);
|
|
||||||
static void dns_purge_resolve(cached_resolve_t *resolve);
|
static void dns_purge_resolve(cached_resolve_t *resolve);
|
||||||
static void dns_found_answer(char *address, uint32_t addr, char outcome);
|
static void dns_found_answer(char *address, uint32_t addr, char outcome,
|
||||||
|
uint32_t ttl);
|
||||||
|
static void send_resolved_cell(connection_t *conn, uint8_t answer_type,
|
||||||
|
uint32_t ttl);
|
||||||
|
static int assign_to_dnsworker(connection_t *exitconn);
|
||||||
|
#ifndef USE_EVENTDNS
|
||||||
static int dnsworker_main(void *data);
|
static int dnsworker_main(void *data);
|
||||||
static int spawn_dnsworker(void);
|
static int spawn_dnsworker(void);
|
||||||
static int spawn_enough_dnsworkers(void);
|
static int spawn_enough_dnsworkers(void);
|
||||||
static void send_resolved_cell(connection_t *conn, uint8_t answer_type);
|
#endif
|
||||||
|
|
||||||
/** Hash table of cached_resolve objects. */
|
/** Hash table of cached_resolve objects. */
|
||||||
static HT_HEAD(cache_map, cached_resolve_t) cache_root;
|
static HT_HEAD(cache_map, cached_resolve_t) cache_root;
|
||||||
@ -115,6 +124,10 @@ dns_init(void)
|
|||||||
{
|
{
|
||||||
init_cache_map();
|
init_cache_map();
|
||||||
dnsworkers_rotate();
|
dnsworkers_rotate();
|
||||||
|
#ifdef USE_EVENTDNS
|
||||||
|
eventdns_resolv_conf_parse(DNS_OPTION_NAMESERVERS|DNS_OPTION_MISC,
|
||||||
|
"/etc/resolv.conf");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Helper: free storage held by an entry in the DNS cache. */
|
/** Helper: free storage held by an entry in the DNS cache. */
|
||||||
@ -199,7 +212,7 @@ purge_expired_resolves(uint32_t now)
|
|||||||
/** Send a response to the RESOVLE request of a connection. answer_type must
|
/** Send a response to the RESOVLE request of a connection. answer_type must
|
||||||
* be one of RESOLVED_TYPE_(IPV4|ERROR|ERROR_TRANSIENT) */
|
* be one of RESOLVED_TYPE_(IPV4|ERROR|ERROR_TRANSIENT) */
|
||||||
static void
|
static void
|
||||||
send_resolved_cell(connection_t *conn, uint8_t answer_type)
|
send_resolved_cell(connection_t *conn, uint8_t answer_type, uint32_t ttl)
|
||||||
{
|
{
|
||||||
char buf[RELAY_PAYLOAD_SIZE];
|
char buf[RELAY_PAYLOAD_SIZE];
|
||||||
size_t buflen;
|
size_t buflen;
|
||||||
@ -211,7 +224,7 @@ send_resolved_cell(connection_t *conn, uint8_t answer_type)
|
|||||||
case RESOLVED_TYPE_IPV4:
|
case RESOLVED_TYPE_IPV4:
|
||||||
buf[1] = 4;
|
buf[1] = 4;
|
||||||
set_uint32(buf+2, htonl(conn->addr));
|
set_uint32(buf+2, htonl(conn->addr));
|
||||||
set_uint32(buf+6, htonl(MAX_DNS_ENTRY_AGE)); /*XXXX send a real TTL*/
|
set_uint32(buf+6, htonl(ttl));
|
||||||
buflen = 10;
|
buflen = 10;
|
||||||
break;
|
break;
|
||||||
case RESOLVED_TYPE_ERROR_TRANSIENT:
|
case RESOLVED_TYPE_ERROR_TRANSIENT:
|
||||||
@ -219,10 +232,10 @@ send_resolved_cell(connection_t *conn, uint8_t answer_type)
|
|||||||
{
|
{
|
||||||
const char *errmsg = "Error resolving hostname";
|
const char *errmsg = "Error resolving hostname";
|
||||||
int msglen = strlen(errmsg);
|
int msglen = strlen(errmsg);
|
||||||
int ttl = (answer_type == RESOLVED_TYPE_ERROR ? MAX_DNS_ENTRY_AGE : 0);
|
|
||||||
buf[1] = msglen;
|
buf[1] = msglen;
|
||||||
strlcpy(buf+2, errmsg, sizeof(buf)-2);
|
strlcpy(buf+2, errmsg, sizeof(buf)-2);
|
||||||
set_uint32(buf+2+msglen, htonl((uint32_t)ttl));
|
set_uint32(buf+2+msglen, htonl(ttl));
|
||||||
buflen = 6+msglen;
|
buflen = 6+msglen;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -277,7 +290,7 @@ dns_resolve(connection_t *exitconn)
|
|||||||
if (tor_inet_aton(exitconn->address, &in) != 0) {
|
if (tor_inet_aton(exitconn->address, &in) != 0) {
|
||||||
exitconn->addr = ntohl(in.s_addr);
|
exitconn->addr = ntohl(in.s_addr);
|
||||||
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
|
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
|
||||||
send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
|
send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4, MAX_DNS_ENTRY_AGE);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -291,7 +304,10 @@ dns_resolve(connection_t *exitconn)
|
|||||||
/* 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->address, sizeof(search.address));
|
strlcpy(search.address, exitconn->address, sizeof(search.address));
|
||||||
resolve = HT_FIND(cache_map, &cache_root, &search);
|
resolve = HT_FIND(cache_map, &cache_root, &search);
|
||||||
if (resolve) { /* already there */
|
if (resolve && resolve->expire > now) { /* already there */
|
||||||
|
// XXXX Security problem: this leaks a time at which somebody asked for
|
||||||
|
// XXXX the address. That's a problem.
|
||||||
|
unsigned int ttl = (unsigned int) resolve->expire - now;
|
||||||
switch (resolve->state) {
|
switch (resolve->state) {
|
||||||
case CACHE_STATE_PENDING:
|
case CACHE_STATE_PENDING:
|
||||||
/* add us to the pending list */
|
/* add us to the pending list */
|
||||||
@ -310,13 +326,13 @@ dns_resolve(connection_t *exitconn)
|
|||||||
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->s, escaped_safe_str(exitconn->address));
|
exitconn->s, escaped_safe_str(exitconn->address));
|
||||||
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
|
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
|
||||||
send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
|
send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4, ttl);
|
||||||
return 1;
|
return 1;
|
||||||
case CACHE_STATE_FAILED:
|
case CACHE_STATE_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->s, escaped_safe_str(exitconn->address));
|
exitconn->s, escaped_safe_str(exitconn->address));
|
||||||
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
|
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
|
||||||
send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR);
|
send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR, ttl);
|
||||||
circ = circuit_get_by_edge_conn(exitconn);
|
circ = circuit_get_by_edge_conn(exitconn);
|
||||||
if (circ)
|
if (circ)
|
||||||
circuit_detach_stream(circ, exitconn);
|
circuit_detach_stream(circ, exitconn);
|
||||||
@ -344,51 +360,40 @@ dns_resolve(connection_t *exitconn)
|
|||||||
return assign_to_dnsworker(exitconn);
|
return assign_to_dnsworker(exitconn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Find or spawn a dns worker process to handle resolving
|
/** Log an error and abort if conn is waiting for a DNS resolve.
|
||||||
* <b>exitconn</b>-\>address; tell that dns worker to begin resolving.
|
|
||||||
*/
|
*/
|
||||||
static int
|
void
|
||||||
assign_to_dnsworker(connection_t *exitconn)
|
assert_connection_edge_not_dns_pending(connection_t *conn)
|
||||||
{
|
{
|
||||||
connection_t *dnsconn;
|
pending_connection_t *pend;
|
||||||
unsigned char len;
|
cached_resolve_t **resolve;
|
||||||
|
|
||||||
tor_assert(exitconn->state == EXIT_CONN_STATE_RESOLVING);
|
HT_FOREACH(resolve, cache_map, &cache_root) {
|
||||||
tor_assert(exitconn->s == -1);
|
for (pend = (*resolve)->pending_connections;
|
||||||
|
pend;
|
||||||
/* respawn here, to be sure there are enough */
|
pend = pend->next) {
|
||||||
if (spawn_enough_dnsworkers() < 0) {
|
tor_assert(pend->conn != conn);
|
||||||
goto err;
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dnsconn = connection_get_by_type_state(CONN_TYPE_DNSWORKER,
|
/** Log an error and abort if any connection waiting for a DNS resolve is
|
||||||
DNSWORKER_STATE_IDLE);
|
* corrupted. */
|
||||||
|
void
|
||||||
|
assert_all_pending_dns_resolves_ok(void)
|
||||||
|
{
|
||||||
|
pending_connection_t *pend;
|
||||||
|
cached_resolve_t **resolve;
|
||||||
|
|
||||||
if (!dnsconn) {
|
HT_FOREACH(resolve, cache_map, &cache_root) {
|
||||||
log_warn(LD_EXIT,"no idle dns workers. Failing.");
|
for (pend = (*resolve)->pending_connections;
|
||||||
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
|
pend;
|
||||||
send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR_TRANSIENT);
|
pend = pend->next) {
|
||||||
goto err;
|
assert_connection_ok(pend->conn, 0);
|
||||||
|
tor_assert(pend->conn->s == -1);
|
||||||
|
tor_assert(!connection_in_array(pend->conn));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debug(LD_EXIT,
|
|
||||||
"Connection (fd %d) needs to resolve %s; assigning "
|
|
||||||
"to DNSWorker (fd %d)", exitconn->s,
|
|
||||||
escaped_safe_str(exitconn->address), dnsconn->s);
|
|
||||||
|
|
||||||
tor_free(dnsconn->address);
|
|
||||||
dnsconn->address = tor_strdup(exitconn->address);
|
|
||||||
dnsconn->state = DNSWORKER_STATE_BUSY;
|
|
||||||
num_dnsworkers_busy++;
|
|
||||||
|
|
||||||
len = strlen(dnsconn->address);
|
|
||||||
connection_write_to_buf((char*)&len, 1, dnsconn);
|
|
||||||
connection_write_to_buf(dnsconn->address, len, dnsconn);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
err:
|
|
||||||
dns_cancel_pending_resolve(exitconn->address); /* also sends end and frees */
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Remove <b>conn</b> from the list of connections waiting for conn-\>address.
|
/** Remove <b>conn</b> from the list of connections waiting for conn-\>address.
|
||||||
@ -440,42 +445,6 @@ connection_dns_remove(connection_t *conn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Log an error and abort if conn is waiting for a DNS resolve.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
assert_connection_edge_not_dns_pending(connection_t *conn)
|
|
||||||
{
|
|
||||||
pending_connection_t *pend;
|
|
||||||
cached_resolve_t **resolve;
|
|
||||||
|
|
||||||
HT_FOREACH(resolve, cache_map, &cache_root) {
|
|
||||||
for (pend = (*resolve)->pending_connections;
|
|
||||||
pend;
|
|
||||||
pend = pend->next) {
|
|
||||||
tor_assert(pend->conn != conn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Log an error and abort if any connection waiting for a DNS resolve is
|
|
||||||
* corrupted. */
|
|
||||||
void
|
|
||||||
assert_all_pending_dns_resolves_ok(void)
|
|
||||||
{
|
|
||||||
pending_connection_t *pend;
|
|
||||||
cached_resolve_t **resolve;
|
|
||||||
|
|
||||||
HT_FOREACH(resolve, cache_map, &cache_root) {
|
|
||||||
for (pend = (*resolve)->pending_connections;
|
|
||||||
pend;
|
|
||||||
pend = pend->next) {
|
|
||||||
assert_connection_ok(pend->conn, 0);
|
|
||||||
tor_assert(pend->conn->s == -1);
|
|
||||||
tor_assert(!connection_in_array(pend->conn));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Mark all connections waiting for <b>address</b> for close. Then cancel
|
/** Mark all connections waiting for <b>address</b> for close. Then cancel
|
||||||
* the resolve for <b>address</b> itself, and remove any cached results for
|
* the resolve for <b>address</b> itself, and remove any cached results for
|
||||||
* <b>address</b> from the cache.
|
* <b>address</b> from the cache.
|
||||||
@ -570,7 +539,7 @@ dns_purge_resolve(cached_resolve_t *resolve)
|
|||||||
* DNS_RESOLVE_{FAILED_TRANSIENT|FAILED_PERMANENT|SUCCEEDED}.
|
* DNS_RESOLVE_{FAILED_TRANSIENT|FAILED_PERMANENT|SUCCEEDED}.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
dns_found_answer(char *address, uint32_t addr, char outcome)
|
dns_found_answer(char *address, uint32_t addr, char outcome, uint32_t ttl)
|
||||||
{
|
{
|
||||||
pending_connection_t *pend;
|
pending_connection_t *pend;
|
||||||
cached_resolve_t search;
|
cached_resolve_t search;
|
||||||
@ -588,7 +557,7 @@ dns_found_answer(char *address, uint32_t addr, char outcome)
|
|||||||
resolve->state = (outcome == DNS_RESOLVE_SUCCEEDED) ?
|
resolve->state = (outcome == DNS_RESOLVE_SUCCEEDED) ?
|
||||||
CACHE_STATE_VALID : CACHE_STATE_FAILED;
|
CACHE_STATE_VALID : CACHE_STATE_FAILED;
|
||||||
resolve->addr = addr;
|
resolve->addr = addr;
|
||||||
resolve->expire = time(NULL) + MAX_DNS_ENTRY_AGE;
|
resolve->expire = time(NULL) + ttl;
|
||||||
insert_resolve(resolve);
|
insert_resolve(resolve);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -608,6 +577,7 @@ dns_found_answer(char *address, uint32_t addr, char outcome)
|
|||||||
/* tor_assert(resolve->state == CACHE_STATE_PENDING); */
|
/* tor_assert(resolve->state == CACHE_STATE_PENDING); */
|
||||||
|
|
||||||
resolve->addr = addr;
|
resolve->addr = addr;
|
||||||
|
resolve->expire = time(NULL) + ttl;
|
||||||
if (outcome == DNS_RESOLVE_SUCCEEDED)
|
if (outcome == DNS_RESOLVE_SUCCEEDED)
|
||||||
resolve->state = CACHE_STATE_VALID;
|
resolve->state = CACHE_STATE_VALID;
|
||||||
else
|
else
|
||||||
@ -629,7 +599,7 @@ dns_found_answer(char *address, uint32_t addr, char outcome)
|
|||||||
/* This detach must happen after we send the end cell. */
|
/* This detach must happen after we send the end cell. */
|
||||||
circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn);
|
circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn);
|
||||||
} else {
|
} else {
|
||||||
send_resolved_cell(pendconn, RESOLVED_TYPE_ERROR);
|
send_resolved_cell(pendconn, RESOLVED_TYPE_ERROR, ttl);
|
||||||
/* This detach must happen after we send the resolved cell. */
|
/* This detach must happen after we send the resolved cell. */
|
||||||
circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn);
|
circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn);
|
||||||
}
|
}
|
||||||
@ -653,7 +623,7 @@ dns_found_answer(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->state = EXIT_CONN_STATE_RESOLVEFAILED;
|
pendconn->state = EXIT_CONN_STATE_RESOLVEFAILED;
|
||||||
send_resolved_cell(pendconn, RESOLVED_TYPE_IPV4);
|
send_resolved_cell(pendconn, RESOLVED_TYPE_IPV4, ttl);
|
||||||
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);
|
||||||
@ -669,6 +639,54 @@ dns_found_answer(char *address, uint32_t addr, char outcome)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef USE_EVENTDNS
|
||||||
|
/** 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)
|
||||||
|
{
|
||||||
|
connection_t *dnsconn;
|
||||||
|
unsigned char len;
|
||||||
|
|
||||||
|
tor_assert(exitconn->state == EXIT_CONN_STATE_RESOLVING);
|
||||||
|
tor_assert(exitconn->s == -1);
|
||||||
|
|
||||||
|
/* respawn here, to be sure there are enough */
|
||||||
|
if (spawn_enough_dnsworkers() < 0) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
dnsconn = connection_get_by_type_state(CONN_TYPE_DNSWORKER,
|
||||||
|
DNSWORKER_STATE_IDLE);
|
||||||
|
|
||||||
|
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, 0);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug(LD_EXIT,
|
||||||
|
"Connection (fd %d) needs to resolve %s; assigning "
|
||||||
|
"to DNSWorker (fd %d)", exitconn->s,
|
||||||
|
escaped_safe_str(exitconn->address), dnsconn->s);
|
||||||
|
|
||||||
|
tor_free(dnsconn->address);
|
||||||
|
dnsconn->address = tor_strdup(exitconn->address);
|
||||||
|
dnsconn->state = DNSWORKER_STATE_BUSY;
|
||||||
|
num_dnsworkers_busy++;
|
||||||
|
|
||||||
|
len = strlen(dnsconn->address);
|
||||||
|
connection_write_to_buf((char*)&len, 1, dnsconn);
|
||||||
|
connection_write_to_buf(dnsconn->address, len, dnsconn);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
err:
|
||||||
|
dns_cancel_pending_resolve(exitconn->address); /* also sends end and frees */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************/
|
/******************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -709,6 +727,7 @@ connection_dns_process_inbuf(connection_t *conn)
|
|||||||
{
|
{
|
||||||
char success;
|
char success;
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
|
int ttl;
|
||||||
|
|
||||||
tor_assert(conn);
|
tor_assert(conn);
|
||||||
tor_assert(conn->type == CONN_TYPE_DNSWORKER);
|
tor_assert(conn->type == CONN_TYPE_DNSWORKER);
|
||||||
@ -744,7 +763,9 @@ connection_dns_process_inbuf(connection_t *conn)
|
|||||||
|
|
||||||
tor_assert(success >= DNS_RESOLVE_FAILED_TRANSIENT);
|
tor_assert(success >= DNS_RESOLVE_FAILED_TRANSIENT);
|
||||||
tor_assert(success <= DNS_RESOLVE_SUCCEEDED);
|
tor_assert(success <= DNS_RESOLVE_SUCCEEDED);
|
||||||
dns_found_answer(conn->address, ntohl(addr), success);
|
|
||||||
|
ttl = (success == DNS_RESOLVE_FAILED_TRANSIENT) ? 0 : MAX_DNS_ENTRY_AGE;
|
||||||
|
dns_found_answer(conn->address, ntohl(addr), success, ttl);
|
||||||
|
|
||||||
tor_free(conn->address);
|
tor_free(conn->address);
|
||||||
conn->address = tor_strdup("<idle>");
|
conn->address = tor_strdup("<idle>");
|
||||||
@ -989,4 +1010,85 @@ spawn_enough_dnsworkers(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#else /* !USE_EVENTDNS */
|
||||||
|
static int
|
||||||
|
eventdns_err_is_transient(int err)
|
||||||
|
{
|
||||||
|
switch (err)
|
||||||
|
{
|
||||||
|
case DNS_ERR_SERVERFAILED:
|
||||||
|
case DNS_ERR_TRUNCATED:
|
||||||
|
case DNS_ERR_TIMEOUT:
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void
|
||||||
|
dnsworkers_rotate(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
int
|
||||||
|
connection_dns_finished_flushing(connection_t *conn)
|
||||||
|
{
|
||||||
|
tor_assert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int
|
||||||
|
connection_dns_process_inbuf(connection_t *conn)
|
||||||
|
{
|
||||||
|
tor_assert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int
|
||||||
|
connection_dns_reached_eof(connection_t *conn)
|
||||||
|
{
|
||||||
|
tor_assert(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
eventdns_callback(int result, char type, int count, int ttl, void *addresses,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
char *string_address = arg;
|
||||||
|
if (result == DNS_ERR_NONE) {
|
||||||
|
if (type == DNS_IPv4_A && count) {
|
||||||
|
uint32_t *addrs = addresses;
|
||||||
|
dns_found_answer(string_address, addrs[0], DNS_RESOLVE_SUCCEEDED, ttl);
|
||||||
|
} else if (count) {
|
||||||
|
log_warn(LD_EXIT, "eventdns returned only non-IPv4 answers for %s.",
|
||||||
|
escaped_safe_str(string_address));
|
||||||
|
dns_found_answer(string_address, 0, DNS_RESOLVE_FAILED_PERMANENT, ttl);
|
||||||
|
} else {
|
||||||
|
log_warn(LD_BUG, "eventdns returned no addresses or error for %s!",
|
||||||
|
escaped_safe_str(string_address));
|
||||||
|
dns_found_answer(string_address, 0, DNS_RESOLVE_FAILED_PERMANENT, ttl);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int err = eventdns_err_is_transient(result)
|
||||||
|
? DNS_RESOLVE_FAILED_TRANSIENT : DNS_RESOLVE_FAILED_PERMANENT;
|
||||||
|
dns_found_answer(string_address, 0, err, ttl);
|
||||||
|
}
|
||||||
|
tor_free(string_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int assign_to_dnsworker(connection_t *exitconn)
|
||||||
|
{
|
||||||
|
char *addr = tor_strdup(exitconn->address);
|
||||||
|
int r = eventdns_resolve(exitconn->address, DNS_QUERY_NO_SEARCH,
|
||||||
|
eventdns_callback, addr);
|
||||||
|
if (r) {
|
||||||
|
log_warn(LD_EXIT, "eventdns rejected address %s: error %d.",
|
||||||
|
escaped_safe_str(addr), r);
|
||||||
|
if (exitconn->purpose == EXIT_PURPOSE_RESOLVE) {
|
||||||
|
if (eventdns_err_is_transient(r))
|
||||||
|
send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR_TRANSIENT, 0);
|
||||||
|
else
|
||||||
|
send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR, MAX_DNS_ENTRY_AGE);
|
||||||
|
}
|
||||||
|
dns_cancel_pending_resolve(addr);/* also sends end and frees */
|
||||||
|
tor_free(addr);
|
||||||
|
}
|
||||||
|
return r ? -1 : 0;
|
||||||
|
}
|
||||||
|
#endif /* USE_EVENTDNS */
|
||||||
|
Loading…
Reference in New Issue
Block a user