diff options
-rw-r--r-- | doc/TODO | 6 | ||||
-rw-r--r-- | src/or/eventdns.c | 287 | ||||
-rw-r--r-- | src/or/eventdns.h | 197 | ||||
-rw-r--r-- | src/or/eventdns_tor.h | 6 |
4 files changed, 256 insertions, 240 deletions
@@ -134,6 +134,12 @@ d - Special-case localhost? - address_is_invalid_destination() is the right thing to call here (and feel free to make that function smarter) +d - Eventdns improvements + - Have a way to query for AAAA and A records simultaneously. + - Improve request API: At the very least, add the ability to construct + a more-or-less arbitrary request and get a response. + - (Can we suppress cnames? Should we?) + - Performance improvements x - Better estimates in the directory of whether servers have good uptime diff --git a/src/or/eventdns.c b/src/or/eventdns.c index eafcb2a17..5a0214ed7 100644 --- a/src/or/eventdns.c +++ b/src/or/eventdns.c @@ -7,16 +7,13 @@ * reformat the whitespace, add Tor dependencies, or so on. * * TODO: - * - Have a way to query for AAAA and A records simultaneously. - * - Improve request API: At the very least, add the ability to construct - * a more-or-less arbitrary request and get a response. - * - (Can we suppress cnames? Should we?) * - Replace all externally visible magic numbers with #defined constants. * - Write documentation for APIs of all external functions. */ /* Async DNS Library * Adam Langley <agl@imperialviolet.org> + * http://www.imperialviolet.org/eventdns.html * Public Domain code * * This software is Public Domain. To view a copy of the public domain dedication, @@ -34,195 +31,9 @@ * the source verbatim in their source distributions) * * Version: 0.1b - * - * - * Welcome, gentle reader - * - * Async DNS lookups are really a whole lot harder than they should be, - * mostly stemming from the fact that the libc resolver has never been - * very good at them. Before you use this library you should see if libc - * can do the job for you with the modern async call getaddrinfo_a - * (see http://www.imperialviolet.org/page25.html#e498). Otherwise, - * please continue. - * - * This code is based on libevent and you must call event_init before - * any of the APIs in this file. You must also seed the OpenSSL random - * source if you are using OpenSSL for ids (see below). - * - * This library is designed to be included and shipped with your source - * code. You statically link with it. You should also test for the - * existence of strtok_r and define HAVE_STRTOK_R if you have it. - * - * The DNS protocol requires a good source of id numbers and these - * numbers should be unpredictable for spoofing reasons. There are - * three methods for generating them here and you must define exactly - * one of them. In increasing order of preference: - * - * DNS_USE_GETTIMEOFDAY_FOR_ID: - * Using the bottom 16 bits of the usec result from gettimeofday. This - * is a pretty poor solution but should work anywhere. - * DNS_USE_CPU_CLOCK_FOR_ID: - * Using the bottom 16 bits of the nsec result from the CPU's time - * counter. This is better, but may not work everywhere. Requires - * POSIX realtime support and you'll need to link against -lrt on - * glibc systems at least. - * DNS_USE_OPENSSL_FOR_ID: - * Uses the OpenSSL RAND_bytes call to generate the data. You must - * have seeded the pool before making any calls to this library. - * - * The library keeps track of the state of nameservers and will avoid - * them when they go down. Otherwise it will round robin between them. - * - * Quick start guide: - * #include "eventdns.h" - * void callback(int result, char type, int count, int ttl, - * void *addresses, void *arg); - * evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf"); - * evdns_resolve("www.hostname.com", 0, callback, NULL); - * - * When the lookup is complete the callback function is called. The - * first argument will be one of the DNS_ERR_* defines in eventdns.h. - * Hopefully it will be DNS_ERR_NONE, in which case type will be - * DNS_IPv4_A, count will be the number of IP addresses, ttl is the time - * which the data can be cached for (in seconds), addresses will point - * to an array of uint32_t's and arg will be whatever you passed to - * evdns_resolve. - * - * Searching: - * - * In order for this library to be a good replacement for glibc's resolver it - * supports searching. This involves setting a list of default domains, in - * which names will be queried for. The number of dots in the query name - * determines the order in which this list is used. - * - * Searching appears to be a single lookup from the point of view of the API, - * although many DNS queries may be generated from a single call to - * evdns_resolve. Searching can also drastically slow down the resolution - * of names. - * - * To disable searching: - * 1. Never set it up. If you never call evdns_resolv_conf_parse or - * evdns_search_add then no searching will occur. - * - * 2. If you do call evdns_resolv_conf_parse then don't pass - * DNS_OPTION_SEARCH (or DNS_OPTIONS_ALL, which implies it). - * - * 3. When calling evdns_resolve, pass the DNS_QUERY_NO_SEARCH flag. - * - * The order of searches depends on the number of dots in the name. If the - * number is greater than the ndots setting then the names is first tried - * globally. Otherwise each search domain is appended in turn. - * - * The ndots setting can either be set from a resolv.conf, or by calling - * evdns_search_ndots_set. - * - * For example, with ndots set to 1 (the default) and a search domain list of - * ["myhome.net"]: - * Query: www - * Order: www.myhome.net, www. - * - * Query: www.abc - * Order: www.abc., www.abc.myhome.net - * - * API reference: - * - * int evdns_nameserver_add(unsigned long int address) - * Add a nameserver. The address should be an IP address in - * network byte order. The type of address is chosen so that - * it matches in_addr.s_addr. - * Returns non-zero on error. - * - * int evdns_nameserver_ip_add(const char *ip_as_string) - * This wraps the above function by parsing a string as an IP - * address and adds it as a nameserver. - * Returns non-zero on error - * - * int evdns_resolve(const char *name, int flags, - * evdns_callback_type callback, - * void *ptr) - * Resolve a name. The name parameter should be a DNS name. - * The flags parameter should be 0, or DNS_QUERY_NO_SEARCH - * which disables searching for this query. (see defn of - * searching above). - * - * The callback argument is a function which is called when - * this query completes and ptr is an argument which is passed - * to that callback function. - * - * Returns non-zero on error - * - * void evdns_search_clear() - * Clears the list of search domains - * - * void evdns_search_add(const char *domain) - * Add a domain to the list of search domains - * - * void evdns_search_ndots_set(int ndots) - * Set the number of dots which, when found in a name, causes - * the first query to be without any search domain. - * - * int evdns_count_nameservers(void) - * Return the number of configured nameservers (not necessarily the - * number of running nameservers). This is useful for double-checking - * whether our calls to the various nameserver configuration functions - * have been successful. - * - * int evdns_clear_nameservers_and_suspend(void) - * Remove all currently configured nameservers, and suspend all pending - * resolves. Resolves will not necessarily be re-attempted until - * evdns_resume() is called. - * - * int evdns_resume(void) - * Re-attempt resolves left in limbo after an earlier call to - * evdns_clear_nameservers_and_suspend(). - * - * int evdns_config_windows_nameservers(void) - * Attempt to configure a set of nameservers based on platform settings on - * a win32 host. Preferentially tries to use GetNetworkParams; if that fails, - * looks in the registry. Returns 0 on success, nonzero on failure. - * - * int evdns_resolv_conf_parse(int flags, const char *filename) - * Parse a resolv.conf like file from the given filename. - * - * See the man page for resolv.conf for the format of this file. - * The flags argument determines what information is parsed from - * this file: - * DNS_OPTION_SEARCH - domain, search and ndots options - * DNS_OPTION_NAMESERVERS - nameserver lines - * DNS_OPTION_MISC - timeout and attempts options - * DNS_OPTIONS_ALL - all of the above - * The following directives are not parsed from the file: - * sortlist, rotate, no-check-names, inet6, debug - * - * Returns non-zero on error: - * 0 no errors - * 1 failed to open file - * 2 failed to stat file - * 3 file too large - * 4 out of memory - * 5 short read from file - * - * Internals: - * - * Requests are kept in two queues. The first is the inflight queue. In - * this queue requests have an allocated transaction id and nameserver. - * They will soon be transmitted if they haven't already been. - * - * The second is the waiting queue. The size of the inflight ring is - * limited and all other requests wait in waiting queue for space. This - * bounds the number of concurrent requests so that we don't flood the - * nameserver. Several algorithms require a full walk of the inflight - * queue and so bounding its size keeps thing going nicely under huge - * (many thousands of requests) loads. - * - * If a nameserver loses too many requests it is considered down and we - * try not to use it. After a while we send a probe to that nameserver - * (a lookup for google.com) and, if it replies, we consider it working - * again. If the nameserver fails a probe we wait longer to try again - * with the next probe. */ -#include "eventdns.h" +#include <sys/types.h> #include "eventdns_tor.h" //#define NDEBUG #include "../common/torint.h" @@ -259,10 +70,11 @@ #define _FORTIFY_SOURCE 3 #include <string.h> -#include <sys/types.h> #include <fcntl.h> #include <sys/time.h> -// #include <stdint.h> +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif #include <stdlib.h> #include <string.h> #include <errno.h> @@ -274,6 +86,7 @@ #include <stdio.h> #include <stdarg.h> +#include "eventdns.h" #ifdef WIN32 #include <windows.h> #include <winsock2.h> @@ -312,8 +125,6 @@ typedef unsigned int uint; #define u16 uint16_t #define u8 uint8_t -#include "eventdns.h" - #define MAX_ADDRS 4 // maximum number of addresses from a single packet // which we bother recording @@ -502,7 +313,7 @@ static void server_request_free_answers(struct server_request *req); static void server_port_free(struct evdns_server_port *port); static void server_port_ready_callback(int fd, short events, void *arg); -#if defined(MS_WINDOWS) || defined(WIN32) +#ifdef WIN32 static int last_error(int sock) { @@ -585,7 +396,7 @@ _evdns_log(int warn, const char *fmt, ...) if (!evdns_log_fn) return; va_start(args,fmt); -#if defined(MS_WINDOWS) || defined(WIN32) +#ifdef WIN32 _vsnprintf(buf, sizeof(buf), fmt, args); #else vsnprintf(buf, sizeof(buf), fmt, args); @@ -912,9 +723,9 @@ static inline int name_parse(u8 *packet, int length, int *idx, char *name_out, int name_out_len) { int name_end = -1; int j = *idx; -#define GET32(x) do { if (j + 4 > length) return -1; memcpy(&_t32, packet + j, 4); j += 4; x = ntohl(_t32); } while(0); -#define GET16(x) do { if (j + 2 > length) return -1; memcpy(&_t, packet + j, 2); j += 2; x = ntohs(_t); } while(0); -#define GET8(x) do { if (j >= length) return -1; x = packet[j++]; } while(0); +#define GET32(x) do { if (j + 4 > length) goto err; memcpy(&_t32, packet + j, 4); j += 4; x = ntohl(_t32); } while(0); +#define GET16(x) do { if (j + 2 > length) goto err; memcpy(&_t, packet + j, 2); j += 2; x = ntohs(_t); } while(0); +#define GET8(x) do { if (j >= length) goto err; x = packet[j++]; } while(0); char *cp = name_out; const char *const end = name_out + name_out_len; @@ -955,6 +766,8 @@ name_parse(u8 *packet, int length, int *idx, char *name_out, int name_out_len) { else *idx = name_end; return 0; + err: + return -1; } // parses a raw request from a nameserver. @@ -968,7 +781,7 @@ reply_parse(u8 *packet, int length) { u16 trans_id, flags, questions, answers, authority, additional, datalength; u32 ttl, ttl_r = 0xffffffff; struct reply reply; - struct request *req = NULL; + struct request *req; unsigned int i; GET16(trans_id); @@ -977,15 +790,8 @@ reply_parse(u8 *packet, int length) { GET16(answers); GET16(authority); GET16(additional); - (void) authority; - (void) additional; - - // This macro skips a name in the DNS reply. -#define SKIP_NAME \ - do { tmp_name[0] = '\0'; \ - if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0) \ - return -1; \ - } while(0); + (void) authority; /* suppress "unused variable" warnings. */ + (void) additional; /* suppress "unused variable" warnings. */ req = request_find_from_trans_id(trans_id); if (!req) return -1; @@ -1001,6 +807,13 @@ reply_parse(u8 *packet, int length) { } // if (!answers) return; // must have an answer of some form + // This macro skips a name in the DNS reply. +#define SKIP_NAME \ + do { tmp_name[0] = '\0'; \ + if (name_parse(packet, length, &j, tmp_name, sizeof(tmp_name))<0) \ + goto err; \ + } while(0); + reply.type = req->request_type; // skip over each question in the reply @@ -1079,11 +892,9 @@ reply_parse(u8 *packet, int length) { reply_handle(req, flags, ttl_r, &reply); return 0; + err: + return -1; } -#undef SKIP_NAME -#undef GET32 -#undef GET16 -#undef GET8 // Parse a raw request (packet,length) sent to a nameserver port (port) from // a DNS client (addr,addrlen), and if it's well-formed, call the corresponding @@ -1095,9 +906,6 @@ request_parse(u8 *packet, int length, struct evdns_server_port *port, struct soc u16 _t; // used by the macros char tmp_name[256]; // used by the macros -#define GET16(x) do { if (j + 2 > length) goto err; memcpy(&_t, packet + j, 2); j += 2; x = ntohs(_t); } while(0); -#define GET8(x) do { if (j >= length) goto err; x = packet[j++]; } while(0); - int i; u16 trans_id, flags, questions, answers, authority, additional; struct server_request *server_req = NULL; @@ -1163,9 +971,12 @@ err: free(server_req); } return -1; -} + +#undef SKIP_NAME +#undef GET32 #undef GET16 #undef GET8 +} // Try to choose a strong transaction id which isn't already in flight static u16 @@ -1463,6 +1274,13 @@ dnsname_to_labels(u8 *const buf, size_t buf_len, off_t j, memcpy(buf + j, &_t, 2); \ j += 2; \ } while (0) +#define APPEND32(x) do { \ + if (j + 4 > (off_t)buf_len) \ + goto overflow; \ + _t32 = htonl(x); \ + memcpy(buf + j, &_t32, 4); \ + j += 4; \ + } while (0) if (name_len > 255) return -2; @@ -1522,20 +1340,12 @@ evdns_request_len(const int name_len) { // // Returns the amount of space used. Negative on error. static int -evdns_request_data_build(const char *const name, const int name_len, const u16 trans_id, - const u16 type, const u16 class, +evdns_request_data_build(const char *const name, const int name_len, + const u16 trans_id, const u16 type, const u16 class, u8 *const buf, size_t buf_len) { off_t j = 0; // current offset into buf u16 _t; // used by the macros -#define APPEND32(x) do { \ - if (j + 4 > (off_t)buf_len) \ - goto overflow; \ - _t32 = htonl(x); \ - memcpy(buf + j, &_t32, 4); \ - j += 4; \ - } while (0) - APPEND16(trans_id); APPEND16(0x0100); // standard query, recusion needed APPEND16(1); // one question @@ -2031,8 +1841,8 @@ evdns_request_transmit(struct request *req) { evtimer_set(&req->timeout_event, evdns_request_timeout_callback, req); if (evtimer_add(&req->timeout_event, &global_timeout) < 0) { log(EVDNS_LOG_WARN, - "Error from libevent when adding timer for " - "request %lx", (unsigned long) req); + "Error from libevent when adding timer for request %lx", + (unsigned long) req); // ???? Do more? } req->tx_count++; @@ -2159,6 +1969,7 @@ evdns_clear_nameservers_and_suspend(void) return 0; } + // exported function int evdns_resume(void) @@ -2190,7 +2001,7 @@ evdns_nameserver_add(unsigned long int address) { ns->socket = socket(PF_INET, SOCK_DGRAM, 0); if (ns->socket < 0) { err = 1; goto out1; } -#if defined(MS_WINDOWS) || defined(WIN32) +#ifdef WIN32 { u_long nonblocking = 1; ioctlsocket(ns->socket, FIONBIO, &nonblocking); @@ -2342,7 +2153,7 @@ int evdns_resolve_ipv4(const char *name, int flags, request_submit(req); return (0); } else { - return search_request_new(TYPE_A, name, flags, callback, ptr); + return (search_request_new(TYPE_A, name, flags, callback, ptr)); } } @@ -2358,7 +2169,7 @@ int evdns_resolve_ipv6(const char *name, int flags, request_submit(req); return (0); } else { - return search_request_new(TYPE_AAAA, name, flags, callback, ptr); + return (search_request_new(TYPE_AAAA, name, flags, callback, ptr)); } } @@ -2386,7 +2197,6 @@ int evdns_resolve_reverse_ipv6(struct in6_addr *in, int flags, evdns_callback_ty struct request *req; int i; assert(in); - cp = buf; for (i=0; i < 16; ++i) { u8 byte = in->s6_addr[i]; @@ -2404,6 +2214,7 @@ int evdns_resolve_reverse_ipv6(struct in6_addr *in, int flags, evdns_callback_ty return 0; } + ///////////////////////////////////////////////////////////////////// // Search support // @@ -2556,7 +2367,7 @@ search_make_new(const struct search_state *const state, int n, const char *const // we ran off the end of the list and still didn't find the requested string abort(); - return NULL; /* unreachable. */ + return NULL; /* unreachable; stops warnings in some compilers. */ } static int @@ -2806,7 +2617,7 @@ out1: return err; } -#if defined(MS_WINDOWS) || defined(WIN32) +#ifdef WIN32 // Add multiple nameservers from a space-or-comma-separated list. static int evdns_nameserver_ip_add_line(const char *ips) { @@ -2861,7 +2672,6 @@ load_nameservers_with_getnetworkparams(void) buf = malloc(size); if (!buf) { status = 4; goto done; } - } fixed = buf; r = fn(fixed, &size); if (r != ERROR_SUCCESS && r != ERROR_BUFFER_OVERFLOW) { @@ -2900,7 +2710,6 @@ load_nameservers_with_getnetworkparams(void) } if (!added_any) { - //should we ever get here? - mikec log(EVDNS_LOG_DEBUG, "No nameservers added."); status = -1; } @@ -3006,7 +2815,7 @@ int evdns_init(void) { int res = 0; -#if defined(MS_WINDOWS) || defined(WIN32) +#ifdef WIN32 evdns_config_windows_nameservers(); #else res = evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf"); diff --git a/src/or/eventdns.h b/src/or/eventdns.h index e3d43cee5..4d97e22ed 100644 --- a/src/or/eventdns.h +++ b/src/or/eventdns.h @@ -1,4 +1,12 @@ -/* This software is Public Domain. To view a copy of the public domain dedication, + +/* + * The original DNS code is due to Adam Langley with heavy + * modifications by Nick Mathewson. Adam put his DNS software in the + * public domain. You can find his original copyright below. Please, + * aware that the code as part of libevent is governed by the 3-clause + * BSD license above. + * + * This software is Public Domain. To view a copy of the public domain dedication, * visit http://creativecommons.org/licenses/publicdomain/ or send a letter to * Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA. * @@ -13,6 +21,193 @@ * the source verbatim in their source distributions) */ +/* + * Welcome, gentle reader + * + * Async DNS lookups are really a whole lot harder than they should be, + * mostly stemming from the fact that the libc resolver has never been + * very good at them. Before you use this library you should see if libc + * can do the job for you with the modern async call getaddrinfo_a + * (see http://www.imperialviolet.org/page25.html#e498). Otherwise, + * please continue. + * + * This code is based on libevent and you must call event_init before + * any of the APIs in this file. You must also seed the OpenSSL random + * source if you are using OpenSSL for ids (see below). + * + * This library is designed to be included and shipped with your source + * code. You statically link with it. You should also test for the + * existence of strtok_r and define HAVE_STRTOK_R if you have it. + * + * The DNS protocol requires a good source of id numbers and these + * numbers should be unpredictable for spoofing reasons. There are + * three methods for generating them here and you must define exactly + * one of them. In increasing order of preference: + * + * DNS_USE_GETTIMEOFDAY_FOR_ID: + * Using the bottom 16 bits of the usec result from gettimeofday. This + * is a pretty poor solution but should work anywhere. + * DNS_USE_CPU_CLOCK_FOR_ID: + * Using the bottom 16 bits of the nsec result from the CPU's time + * counter. This is better, but may not work everywhere. Requires + * POSIX realtime support and you'll need to link against -lrt on + * glibc systems at least. + * DNS_USE_OPENSSL_FOR_ID: + * Uses the OpenSSL RAND_bytes call to generate the data. You must + * have seeded the pool before making any calls to this library. + * + * The library keeps track of the state of nameservers and will avoid + * them when they go down. Otherwise it will round robin between them. + * + * Quick start guide: + * #include "evdns.h" + * void callback(int result, char type, int count, int ttl, + * void *addresses, void *arg); + * evdns_resolv_conf_parse(DNS_OPTIONS_ALL, "/etc/resolv.conf"); + * evdns_resolve("www.hostname.com", 0, callback, NULL); + * + * When the lookup is complete the callback function is called. The + * first argument will be one of the DNS_ERR_* defines in evdns.h. + * Hopefully it will be DNS_ERR_NONE, in which case type will be + * DNS_IPv4_A, count will be the number of IP addresses, ttl is the time + * which the data can be cached for (in seconds), addresses will point + * to an array of uint32_t's and arg will be whatever you passed to + * evdns_resolve. + * + * Searching: + * + * In order for this library to be a good replacement for glibc's resolver it + * supports searching. This involves setting a list of default domains, in + * which names will be queried for. The number of dots in the query name + * determines the order in which this list is used. + * + * Searching appears to be a single lookup from the point of view of the API, + * although many DNS queries may be generated from a single call to + * evdns_resolve. Searching can also drastically slow down the resolution + * of names. + * + * To disable searching: + * 1. Never set it up. If you never call evdns_resolv_conf_parse or + * evdns_search_add then no searching will occur. + * + * 2. If you do call evdns_resolv_conf_parse then don't pass + * DNS_OPTION_SEARCH (or DNS_OPTIONS_ALL, which implies it). + * + * 3. When calling evdns_resolve, pass the DNS_QUERY_NO_SEARCH flag. + * + * The order of searches depends on the number of dots in the name. If the + * number is greater than the ndots setting then the names is first tried + * globally. Otherwise each search domain is appended in turn. + * + * The ndots setting can either be set from a resolv.conf, or by calling + * evdns_search_ndots_set. + * + * For example, with ndots set to 1 (the default) and a search domain list of + * ["myhome.net"]: + * Query: www + * Order: www.myhome.net, www. + * + * Query: www.abc + * Order: www.abc., www.abc.myhome.net + * + * API reference: + * + * int evdns_nameserver_add(unsigned long int address) + * Add a nameserver. The address should be an IP address in + * network byte order. The type of address is chosen so that + * it matches in_addr.s_addr. + * Returns non-zero on error. + * + * int evdns_nameserver_ip_add(const char *ip_as_string) + * This wraps the above function by parsing a string as an IP + * address and adds it as a nameserver. + * Returns non-zero on error + * + * int evdns_resolve(const char *name, int flags, + * evdns_callback_type callback, + * void *ptr) + * Resolve a name. The name parameter should be a DNS name. + * The flags parameter should be 0, or DNS_QUERY_NO_SEARCH + * which disables searching for this query. (see defn of + * searching above). + * + * The callback argument is a function which is called when + * this query completes and ptr is an argument which is passed + * to that callback function. + * + * Returns non-zero on error + * + * void evdns_search_clear() + * Clears the list of search domains + * + * void evdns_search_add(const char *domain) + * Add a domain to the list of search domains + * + * void evdns_search_ndots_set(int ndots) + * Set the number of dots which, when found in a name, causes + * the first query to be without any search domain. + * + * int evdns_count_nameservers(void) + * Return the number of configured nameservers (not necessarily the + * number of running nameservers). This is useful for double-checking + * whether our calls to the various nameserver configuration functions + * have been successful. + * + * int evdns_clear_nameservers_and_suspend(void) + * Remove all currently configured nameservers, and suspend all pending + * resolves. Resolves will not necessarily be re-attempted until + * evdns_resume() is called. + * + * int evdns_resume(void) + * Re-attempt resolves left in limbo after an earlier call to + * evdns_clear_nameservers_and_suspend(). + * + * int evdns_config_windows_nameservers(void) + * Attempt to configure a set of nameservers based on platform settings on + * a win32 host. Preferentially tries to use GetNetworkParams; if that fails, + * looks in the registry. Returns 0 on success, nonzero on failure. + * + * int evdns_resolv_conf_parse(int flags, const char *filename) + * Parse a resolv.conf like file from the given filename. + * + * See the man page for resolv.conf for the format of this file. + * The flags argument determines what information is parsed from + * this file: + * DNS_OPTION_SEARCH - domain, search and ndots options + * DNS_OPTION_NAMESERVERS - nameserver lines + * DNS_OPTION_MISC - timeout and attempts options + * DNS_OPTIONS_ALL - all of the above + * The following directives are not parsed from the file: + * sortlist, rotate, no-check-names, inet6, debug + * + * Returns non-zero on error: + * 0 no errors + * 1 failed to open file + * 2 failed to stat file + * 3 file too large + * 4 out of memory + * 5 short read from file + * + * Internals: + * + * Requests are kept in two queues. The first is the inflight queue. In + * this queue requests have an allocated transaction id and nameserver. + * They will soon be transmitted if they haven't already been. + * + * The second is the waiting queue. The size of the inflight ring is + * limited and all other requests wait in waiting queue for space. This + * bounds the number of concurrent requests so that we don't flood the + * nameserver. Several algorithms require a full walk of the inflight + * queue and so bounding its size keeps thing going nicely under huge + * (many thousands of requests) loads. + * + * If a nameserver loses too many requests it is considered down and we + * try not to use it. After a while we send a probe to that nameserver + * (a lookup for google.com) and, if it replies, we consider it working + * again. If the nameserver fails a probe we wait longer to try again + * with the next probe. + */ + #ifndef EVENTDNS_H #define EVENTDNS_H diff --git a/src/or/eventdns_tor.h b/src/or/eventdns_tor.h index a10b3726b..d1acfe275 100644 --- a/src/or/eventdns_tor.h +++ b/src/or/eventdns_tor.h @@ -10,4 +10,10 @@ typedef unsigned char u_char; #ifdef MS_WINDOWS #define inline __inline #endif +#include "../common/torint.h" + +#if defined(MS_WINDOWS) && !defined(WIN32) +/* How did _this_ happen? */ +#define WIN32 +#endif |