diff --git a/src/or/addressmap.c b/src/or/addressmap.c index 8145a14a99..a77e199e15 100644 --- a/src/or/addressmap.c +++ b/src/or/addressmap.c @@ -335,7 +335,9 @@ addressmap_match_superdomains(char *address) * was a .exit. */ int -addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out, +addressmap_rewrite(char *address, size_t maxlen, + unsigned flags, + time_t *expires_out, addressmap_entry_source_t *exit_source_out) { addressmap_entry_t *ent; @@ -368,6 +370,16 @@ addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out, goto done; } + if (ent && ent->source == ADDRMAPSRC_DNS) { + sa_family_t f; + tor_addr_t tmp; + f = tor_addr_parse(&tmp, ent->new_address); + if (f == AF_INET && !(flags & AMR_FLAG_USE_IPV4_DNS)) + goto done; + else if (f == AF_INET6 && !(flags & AMR_FLAG_USE_IPV6_DNS)) + goto done; + } + if (ent->dst_wildcard && !exact_match) { strlcat(address, ".", maxlen); strlcat(address, ent->new_address, maxlen); @@ -409,11 +421,22 @@ addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out, * *expires_out to the expiry time of the result, or to time_max * if the result does not expire. */ int -addressmap_rewrite_reverse(char *address, size_t maxlen, time_t *expires_out) +addressmap_rewrite_reverse(char *address, size_t maxlen, unsigned flags, + time_t *expires_out) { char *s, *cp; addressmap_entry_t *ent; int r = 0; + { + sa_family_t f; + tor_addr_t tmp; + f = tor_addr_parse(&tmp, address); + if (f == AF_INET && !(flags & AMR_FLAG_USE_IPV4_DNS)) + return 0; + else if (f == AF_INET6 && !(flags & AMR_FLAG_USE_IPV6_DNS)) + return 0; + } + tor_asprintf(&s, "REVERSE[%s]", address); ent = strmap_get(addressmap, s); if (ent) { diff --git a/src/or/addressmap.h b/src/or/addressmap.h index 9b07341479..54b3e0ae7c 100644 --- a/src/or/addressmap.h +++ b/src/or/addressmap.h @@ -14,9 +14,12 @@ void addressmap_clean(time_t now); void addressmap_clear_configured(void); void addressmap_clear_transient(void); void addressmap_free_all(void); -int addressmap_rewrite(char *address, size_t maxlen, time_t *expires_out, +#define AMR_FLAG_USE_IPV4_DNS (1u<<0) +#define AMR_FLAG_USE_IPV6_DNS (1u<<1) +int addressmap_rewrite(char *address, size_t maxlen, unsigned flags, + time_t *expires_out, addressmap_entry_source_t *exit_source_out); -int addressmap_rewrite_reverse(char *address, size_t maxlen, +int addressmap_rewrite_reverse(char *address, size_t maxlen, unsigned flags, time_t *expires_out); int addressmap_have_mapping(const char *address, int update_timeout); diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 95088c7c17..091c14570a 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -952,8 +952,14 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, } if (socks->command == SOCKS_COMMAND_RESOLVE_PTR) { + unsigned rewrite_flags = 0; + if (conn->use_cached_ipv4_answers) + rewrite_flags |= AMR_FLAG_USE_IPV4_DNS; + if (conn->use_cached_ipv6_answers) + rewrite_flags |= AMR_FLAG_USE_IPV6_DNS; + if (addressmap_rewrite_reverse(socks->address, sizeof(socks->address), - &map_expires)) { + rewrite_flags, &map_expires)) { char *result = tor_strdup(socks->address); /* remember _what_ is supposed to have been resolved. */ tor_snprintf(socks->address, sizeof(socks->address), "REVERSE[%s]", @@ -984,8 +990,13 @@ connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, } } else if (!automap) { /* For address map controls, remap the address. */ + unsigned rewrite_flags = 0; + if (conn->use_cached_ipv4_answers) + rewrite_flags |= AMR_FLAG_USE_IPV4_DNS; + if (conn->use_cached_ipv6_answers) + rewrite_flags |= AMR_FLAG_USE_IPV6_DNS; if (addressmap_rewrite(socks->address, sizeof(socks->address), - &map_expires, &exit_source)) { + rewrite_flags, &map_expires, &exit_source)) { control_event_stream_status(conn, STREAM_EVENT_REMAP, REMAP_STREAM_SOURCE_CACHE); } diff --git a/src/or/relay.c b/src/or/relay.c index 7f49299e2b..608b5fa60e 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -758,10 +758,17 @@ connection_ap_process_end_not_open( policies_set_node_exitpolicy_to_reject_all(exitrouter); } /* rewrite it to an IP if we learned one. */ - if (addressmap_rewrite(conn->socks_request->address, - sizeof(conn->socks_request->address), - NULL, NULL)) { - control_event_stream_status(conn, STREAM_EVENT_REMAP, 0); + { + unsigned rewrite_flags = 0; + if (conn->use_cached_ipv4_answers) + rewrite_flags |= AMR_FLAG_USE_IPV4_DNS; + if (conn->use_cached_ipv6_answers) + rewrite_flags |= AMR_FLAG_USE_IPV6_DNS; + if (addressmap_rewrite(conn->socks_request->address, + sizeof(conn->socks_request->address), + rewrite_flags, NULL, NULL)) { + control_event_stream_status(conn, STREAM_EVENT_REMAP, 0); + } } if (conn->chosen_exit_optional || conn->chosen_exit_retries) { diff --git a/src/test/test_config.c b/src/test/test_config.c index e04b9dfc2e..9f6b260fea 100644 --- a/src/test/test_config.c +++ b/src/test/test_config.c @@ -42,6 +42,11 @@ test_config_addressmap(void *arg) config_get_lines(buf, &(get_options_mutable()->AddressMap), 0); config_register_addressmaps(get_options()); +/* Use old interface for now, so we don't need to rewrite the unit tests */ +#define addressmap_rewrite(a,s,eo,ao) \ + addressmap_rewrite((a),(s),AMR_FLAG_USE_IPV4_DNS|AMR_FLAG_USE_IPV6_DNS, \ + (eo),(ao)) + /* MapAddress .invalidwildcard.com .torserver.exit - no match */ strlcpy(address, "www.invalidwildcard.com", sizeof(address)); test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); @@ -158,6 +163,8 @@ test_config_addressmap(void *arg) strlcpy(address, "www.torproject.org", sizeof(address)); test_assert(!addressmap_rewrite(address, sizeof(address), &expires, NULL)); +#undef addressmap_rewrite + done: ; }