diff --git a/src/common/address.c b/src/common/address.c index 7a2ce6eef8..e94f147ce7 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -181,7 +181,9 @@ tor_addr_make_unspec(tor_addr_t *a) a->family = AF_UNSPEC; } -/** DOCDOC */ +/** Set address a to the null address in address family family. + * The null address for AF_INET is 0.0.0.0. The null address for AF_INET6 is + * [::]. AF_UNSPEC is all null. */ void tor_addr_make_null(tor_addr_t *a, sa_family_t family) { diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index fbba172b3d..dc58a0e709 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -392,10 +392,17 @@ connection_edge_finished_flushing(edge_connection_t *conn) return 0; } -/** DOCDOC */ +/** Longest size for the relay payload of a RELAY_CONNECTED cell that we're + * able to generate. */ +/* 4 zero bytes; 1 type byte; 16 byte IPv6 address; 4 byte TTL. */ #define MAX_CONNECTED_CELL_PAYLOAD_LEN 25 -/** DOCDOC */ +/** Set the buffer at payload_out -- which must have at least + * MAX_CONNECTED_CELL_PAYLOAD_LEN bytes available -- to the body of a + * RELAY_CONNECTED cell indicating that we have connected to addr, and + * that the name resolution that led us to addr will be valid for + * ttl seconds. Return -1 on error, or the number of bytes used on + * success. */ /* private */int connected_cell_format_payload(uint8_t *payload_out, const tor_addr_t *addr, @@ -404,6 +411,9 @@ connected_cell_format_payload(uint8_t *payload_out, const sa_family_t family = tor_addr_family(addr); int connected_payload_len; + /* should be needless */ + memset(payload_out, 0, MAX_CONNECTED_CELL_PAYLOAD_LEN); + if (family == AF_INET) { set_uint32(payload_out, tor_addr_to_ipv4n(addr)); connected_payload_len = 4; @@ -1672,7 +1682,8 @@ connection_ap_supports_optimistic_data(const entry_connection_t *conn) return conn->may_use_optimistic_data; } -/** DOCDOC */ +/** Return a bitmask of BEGIN_FLAG_* flags that we should transmit in the + * RELAY_BEGIN cell for ap_conn. */ static uint32_t connection_ap_get_begincell_flags(entry_connection_t *ap_conn) { @@ -1680,12 +1691,16 @@ connection_ap_get_begincell_flags(entry_connection_t *ap_conn) const node_t *exitnode = NULL; const crypt_path_t *cpath_layer = edge_conn->cpath_layer; uint32_t flags = 0; + + /* No flags for begindir */ if (ap_conn->use_begindir) return 0; + /* No flags for hidden services. */ if (edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL) return 0; + /* If only IPv4 is supported, no flags */ if (ap_conn->ipv4_traffic_ok && !ap_conn->ipv6_traffic_ok) return 0; @@ -1704,6 +1719,8 @@ connection_ap_get_begincell_flags(entry_connection_t *ap_conn) if (compare_tor_addr_to_node_policy(&a, ap_conn->socks_request->port, exitnode) != ADDR_POLICY_REJECTED) { + /* Only say "IPv6 OK" if the exit node supports IPv6. Otherwise there's + * no point. */ flags |= BEGIN_FLAG_IPV6_OK; } } @@ -2184,7 +2201,10 @@ connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply, return; } -/* DOCDOC */ +/** Read a RELAY_BEGIN or RELAY_BEGINDIR cell from cell, decode it, and + * place the result in bcell. On success return 0; on failure return + * <0 and set *end_reason_out to the end reason we should send back to + * the client. */ /* static */ int begin_cell_parse(const cell_t *cell, begin_cell_t *bcell, uint8_t *end_reason_out) diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h index 95bc29cba7..9f38951f40 100644 --- a/src/or/connection_edge.h +++ b/src/or/connection_edge.h @@ -91,19 +91,41 @@ int connection_edge_update_circuit_isolation(const entry_connection_t *conn, int dry_run); void circuit_clear_isolation(origin_circuit_t *circ); -/* DOCDOC*/ +/** @name Begin-cell flags + * + * These flags are used in RELAY_BEGIN cells to change the default behavior + * of the cell. + * + * @{ + **/ +/** When this flag is set, the client is willing to get connected to IPv6 + * addresses */ #define BEGIN_FLAG_IPV6_OK (1u<<0) +/** When this flag is set, the client DOES NOT support connecting to IPv4 + * addresses. (The sense of this flag is inverted from IPV6_OK, so that the + * old default behavior of Tor is equivalent to having all flags set to 0.) + **/ #define BEGIN_FLAG_IPV4_NOT_OK (1u<<1) +/** When this flag is set, if we find both an IPv4 and an IPv6 address, + * we use the IPv6 address. Otherwise we use the IPv4 address. */ #define BEGIN_FLAG_IPV6_PREFERRED (1u<<2) +/**@}*/ #ifdef CONNECTION_EDGE_PRIVATE -/*DOCDOC*/ +/** A parsed BEGIN or BEGIN_DIR cell */ typedef struct begin_cell_t { + /** The address the client has asked us to connect to, or NULL if this is + * a BEGIN_DIR cell*/ char *address; + /** The flags specified in the BEGIN cell's body. One or more of + * BEGIN_FLAG_*. */ uint32_t flags; + /** The client's requested port. */ uint16_t port; + /** The client's requested Stream ID */ uint16_t stream_id; + /** True iff this is a BEGIN_DIR cell. */ unsigned is_begindir : 1; } begin_cell_t; diff --git a/src/or/dns.c b/src/or/dns.c index b7b5e0e64a..6090c459fd 100644 --- a/src/or/dns.c +++ b/src/or/dns.c @@ -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 address. */ - int err_ipv4; - } result_ipv4; + uint32_t addr_ipv4; /**< IPv4 addr for address, 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 address, 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 resolve. */ 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 exitconn, and a cached_resolve_t + * resolve whose DNS lookups have all succeeded or failed, update the + * appropriate fields (address_ttl and addr) of exitconn. + * + * If this is a reverse lookup, set *hostname_out 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. (address is a NUL-terminated - * string containing the address to look up; addr 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. (address + * is a NUL-terminated string containing the address to look up; + * query_type is one of DNS_{IPv4_A,IPv6_AAAA,PTR}; dns_answer + * is DNS_OK or one of DNS_ERR_*, addr is an IPv4 or IPv6 address if we + * got one; hostname is a hostname fora PTR request if we got one, and + * ttl 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 address (if query_type is + * DNS_IPv4_A or DNS_IPv6_AAAA) ptr_address (if query_type 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) { diff --git a/src/or/or.h b/src/or/or.h index 4566f9152a..a8645f854e 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1237,7 +1237,6 @@ typedef struct listener_connection_t { * addresses? */ unsigned int socks_prefer_ipv6 : 1; - } listener_connection_t; /** Minimum length of the random part of an AUTH_CHALLENGE cell. */ @@ -1444,7 +1443,7 @@ typedef struct edge_connection_t { /** True iff this connection is for a DNS request only. */ unsigned int is_dns_request:1; - /* DOCDOC exit only */ + /** True iff this connection is for a PTR DNS request. (exit only) */ unsigned int is_reverse_dns_lookup:1; unsigned int edge_has_sent_end:1; /**< For debugging; only used on edge @@ -3772,7 +3771,7 @@ typedef struct { int PathBiasScaleFactor; /** @} */ - int IPv6Exit; /**< DOCDOC*/ + int IPv6Exit; /**< Do we support exiting to IPv6 addresses? */ } or_options_t;