|  | @@ -127,10 +127,16 @@ typedef struct pending_connection_t {
 | 
	
		
			
				|  |  |   * connections, and should appear in the hash table. */
 | 
	
		
			
				|  |  |  #define CACHE_STATE_CACHED 2
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/* DOCDOC */
 | 
	
		
			
				|  |  | +/** @name status values for a single DNS request.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * @{ */
 | 
	
		
			
				|  |  | +/** The DNS request is in progress. */
 | 
	
		
			
				|  |  |  #define RES_STATUS_INFLIGHT 1
 | 
	
		
			
				|  |  | +/** The DNS request finished and gave an answer */
 | 
	
		
			
				|  |  |  #define RES_STATUS_DONE_OK 2
 | 
	
		
			
				|  |  | +/** The DNS request finished and gave an error */
 | 
	
		
			
				|  |  |  #define RES_STATUS_DONE_ERR 3
 | 
	
		
			
				|  |  | +/**@}*/
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** A DNS request: possibly completed, possibly pending; cached_resolve
 | 
	
		
			
				|  |  |   * structs are stored at the OR side in a hash table, and as a linked
 | 
	
	
		
			
				|  | @@ -138,27 +144,34 @@ typedef struct pending_connection_t {
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  typedef struct cached_resolve_t {
 | 
	
		
			
				|  |  |    HT_ENTRY(cached_resolve_t) node;
 | 
	
		
			
				|  |  | -  uint32_t magic;
 | 
	
		
			
				|  |  | +  uint32_t magic;  /**< Must be CACHED_RESOLVE_MAGIC */
 | 
	
		
			
				|  |  |    char address[MAX_ADDRESSLEN]; /**< The hostname to be resolved. */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    union {
 | 
	
		
			
				|  |  | -    uint32_t addr_ipv4; /**< IPv4 addr for <b>address</b>. */
 | 
	
		
			
				|  |  | -    int err_ipv4;
 | 
	
		
			
				|  |  | -  } result_ipv4;
 | 
	
		
			
				|  |  | +    uint32_t addr_ipv4; /**< IPv4 addr for <b>address</b>, if successful */
 | 
	
		
			
				|  |  | +    int err_ipv4; /**< One of DNS_ERR_*, if IPv4 lookup failed. */
 | 
	
		
			
				|  |  | +  } result_ipv4; /**< Outcome of IPv4 lookup */
 | 
	
		
			
				|  |  |    union {
 | 
	
		
			
				|  |  | -    struct in6_addr addr_ipv6;
 | 
	
		
			
				|  |  | -    int err_ipv6;
 | 
	
		
			
				|  |  | -  } result_ipv6;
 | 
	
		
			
				|  |  | +    struct in6_addr addr_ipv6; /**< IPv6 addr for <b>address</b>, if
 | 
	
		
			
				|  |  | +                                * successful */
 | 
	
		
			
				|  |  | +    int err_ipv6; /**< One of DNS_ERR_*, if IPv6 lookup failed. */
 | 
	
		
			
				|  |  | +  } result_ipv6; /**< Outcome of IPv6 lookup, if any */
 | 
	
		
			
				|  |  |    union {
 | 
	
		
			
				|  |  | -    char *hostname;
 | 
	
		
			
				|  |  | -    int err_hostname;
 | 
	
		
			
				|  |  | +    char *hostname; /** A hostname, if PTR lookup happened successfully*/
 | 
	
		
			
				|  |  | +    int err_hostname; /** One of DNS_ERR_*, if PTR lookup failed. */
 | 
	
		
			
				|  |  |    } result_ptr;
 | 
	
		
			
				|  |  | +  /** @name Status fields
 | 
	
		
			
				|  |  | +   *
 | 
	
		
			
				|  |  | +   * These take one of the RES_STATUS_* values, depending on the state
 | 
	
		
			
				|  |  | +   * of the corresponding lookup.
 | 
	
		
			
				|  |  | +   *
 | 
	
		
			
				|  |  | +   * @{ */
 | 
	
		
			
				|  |  |    unsigned int res_status_ipv4 : 2;
 | 
	
		
			
				|  |  |    unsigned int res_status_ipv6 : 2;
 | 
	
		
			
				|  |  |    unsigned int res_status_hostname : 2;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +  /**@}*/
 | 
	
		
			
				|  |  |    uint8_t state; /**< Is this cached entry pending/done/informative? */
 | 
	
		
			
				|  |  | -  //uint8_t is_reverse; /**< Is this a reverse (addr-to-hostname) lookup? */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    time_t expire; /**< Remove items from cache after this time. */
 | 
	
		
			
				|  |  |    uint32_t ttl_ipv4; /**< What TTL did the nameserver tell us? */
 | 
	
		
			
				|  |  |    uint32_t ttl_ipv6; /**< What TTL did the nameserver tell us? */
 | 
	
	
		
			
				|  | @@ -201,9 +214,11 @@ static void assert_resolve_ok(cached_resolve_t *resolve);
 | 
	
		
			
				|  |  |  /** Hash table of cached_resolve objects. */
 | 
	
		
			
				|  |  |  static HT_HEAD(cache_map, cached_resolve_t) cache_root;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*DOCDOC*/
 | 
	
		
			
				|  |  | +/** Global: how many IPv6 requests have we made in all? */
 | 
	
		
			
				|  |  |  static uint64_t n_ipv6_requests_made = 0;
 | 
	
		
			
				|  |  | +/** Global: how many IPv6 requests have timed out? */
 | 
	
		
			
				|  |  |  static uint64_t n_ipv6_timeouts = 0;
 | 
	
		
			
				|  |  | +/** Global: Do we think that IPv6 DNS is broken? */
 | 
	
		
			
				|  |  |  static int dns_is_broken_for_ipv6 = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** Function to compare hashed resolves on their addresses; used to
 | 
	
	
		
			
				|  | @@ -445,7 +460,7 @@ cached_resolve_add_answer(cached_resolve_t *resolve,
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*DOCDOC*/
 | 
	
		
			
				|  |  | +/** Return true iff there are no in-flight requests for <b>resolve</b>. */
 | 
	
		
			
				|  |  |  static int
 | 
	
		
			
				|  |  |  cached_resolve_have_all_answers(const cached_resolve_t *resolve)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -911,7 +926,16 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve,
 | 
	
		
			
				|  |  |    return launch_resolve(resolve);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/* DOCDOC must set address_ttl, addr, etc.*/
 | 
	
		
			
				|  |  | +/** Given an exit connection <b>exitconn</b>, and a cached_resolve_t
 | 
	
		
			
				|  |  | + * <b>resolve</b> whose DNS lookups have all succeeded or failed, update the
 | 
	
		
			
				|  |  | + * appropriate fields (address_ttl and addr) of <b>exitconn</b>.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * If this is a reverse lookup, set *<b>hostname_out</b> to a newly allocated
 | 
	
		
			
				|  |  | + * copy of the name resulting hostname.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Return -2 on a transient error, -1 on a permenent error, and 1 on
 | 
	
		
			
				|  |  | + * a successful lookup.
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  |  static int
 | 
	
		
			
				|  |  |  set_exitconn_info_from_resolve(edge_connection_t *exitconn,
 | 
	
		
			
				|  |  |                                 const cached_resolve_t *resolve,
 | 
	
	
		
			
				|  | @@ -1178,11 +1202,14 @@ is_test_address(const char *address)
 | 
	
		
			
				|  |  |      smartlist_string_isin_case(options->ServerDNSTestAddresses, address);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/** Called on the OR side when a DNS worker or the eventdns library tells us
 | 
	
		
			
				|  |  | - * the outcome of a DNS resolve: tell all pending connections about the result
 | 
	
		
			
				|  |  | - * of the lookup, and cache the value.  (<b>address</b> is a NUL-terminated
 | 
	
		
			
				|  |  | - * string containing the address to look up; <b>addr</b> is an IPv4 address in
 | 
	
		
			
				|  |  | - * host order; DOCDOC
 | 
	
		
			
				|  |  | +/** Called on the OR side when the eventdns library tells us the outcome of a
 | 
	
		
			
				|  |  | + * single DNS resolve: remember the answer, and tell all pending connections
 | 
	
		
			
				|  |  | + * about the result of the lookup if the lookup is now done.  (<b>address</b>
 | 
	
		
			
				|  |  | + * is a NUL-terminated string containing the address to look up;
 | 
	
		
			
				|  |  | + * <b>query_type</b> is one of DNS_{IPv4_A,IPv6_AAAA,PTR}; <b>dns_answer</b>
 | 
	
		
			
				|  |  | + * is DNS_OK or one of DNS_ERR_*, <b>addr</b> is an IPv4 or IPv6 address if we
 | 
	
		
			
				|  |  | + * got one; <b>hostname</b> is a hostname fora PTR request if we got one, and
 | 
	
		
			
				|  |  | + * <b>ttl</b> is the time-to-live of this answer, in seconds.)
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  static void
 | 
	
		
			
				|  |  |  dns_found_answer(const char *address, uint8_t query_type,
 | 
	
	
		
			
				|  | @@ -1229,7 +1256,9 @@ dns_found_answer(const char *address, uint8_t query_type,
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*DOCDOC*/
 | 
	
		
			
				|  |  | +/** Given a pending cached_resolve_t that we just finished resolving,
 | 
	
		
			
				|  |  | + * inform every connection that was waiting for the outcome of that
 | 
	
		
			
				|  |  | + * resolution. */
 | 
	
		
			
				|  |  |  static void
 | 
	
		
			
				|  |  |  inform_pending_connections(cached_resolve_t *resolve)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -1306,7 +1335,12 @@ inform_pending_connections(cached_resolve_t *resolve)
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/*DOCDOC*/
 | 
	
		
			
				|  |  | +/** Remove a pending cached_resolve_t from the hashtable, and add a
 | 
	
		
			
				|  |  | + * corresponding cached cached_resolve_t.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * This function is only necessary because of the perversity of our
 | 
	
		
			
				|  |  | + * cache timeout code; see inline comment for ideas on eliminating it.
 | 
	
		
			
				|  |  | + **/
 | 
	
		
			
				|  |  |  static void
 | 
	
		
			
				|  |  |  make_pending_resolve_cached(cached_resolve_t *resolve)
 | 
	
		
			
				|  |  |  {
 | 
	
	
		
			
				|  | @@ -1627,7 +1661,9 @@ evdns_callback(int result, char type, int count, int ttl, void *addresses,
 | 
	
		
			
				|  |  |    tor_free(arg_);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/**DOCDOC*/
 | 
	
		
			
				|  |  | +/** Start a single DNS resolve for <b>address</b> (if <b>query_type</b> is
 | 
	
		
			
				|  |  | + * DNS_IPv4_A or DNS_IPv6_AAAA) <b>ptr_address</b> (if <b>query_type</b> is
 | 
	
		
			
				|  |  | + * DNS_PTR). Return 0 if we launched the request, -1 otherwise. */
 | 
	
		
			
				|  |  |  static int
 | 
	
		
			
				|  |  |  launch_one_resolve(const char *address, uint8_t query_type,
 | 
	
		
			
				|  |  |                     const tor_addr_t *ptr_address)
 | 
	
	
		
			
				|  | @@ -2011,7 +2047,7 @@ dns_seems_to_be_broken(void)
 | 
	
		
			
				|  |  |    return dns_is_completely_invalid;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/** DOCDOC */
 | 
	
		
			
				|  |  | +/** Return true iff we think that IPv6 hostname lookup is broken */
 | 
	
		
			
				|  |  |  int
 | 
	
		
			
				|  |  |  dns_seems_to_be_broken_for_ipv6(void)
 | 
	
		
			
				|  |  |  {
 |