123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817 |
- /* Copyright (c) 2015-2019, The Tor Project, Inc. */
- /* See LICENSE for licensing information */
- #include "orconfig.h"
- #include "core/or/or.h"
- #include "test/test.h"
- #define DNS_PRIVATE
- #include "feature/relay/dns.h"
- #include "core/mainloop/connection.h"
- #include "core/or/connection_edge.h"
- #include "feature/relay/router.h"
- #include "core/or/edge_connection_st.h"
- #include "core/or/or_circuit_st.h"
- #include "app/config/or_options_st.h"
- #include "app/config/config.h"
- #include <event2/event.h>
- #include <event2/dns.h>
- #define NS_MODULE dns
- #ifdef HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR
- #define NS_SUBMODULE configure_nameservers_fallback
- static or_options_t options = {
- .ORPort_set = 1,
- };
- static const or_options_t *
- mock_get_options(void)
- {
- return &options;
- }
- static void
- NS(test_main)(void *arg)
- {
- (void)arg;
- tor_addr_t *nameserver_addr = NULL;
- MOCK(get_options, mock_get_options);
- options.ServerDNSResolvConfFile = (char *)"no_such_file!!!";
- dns_init(); // calls configure_nameservers()
- tt_int_op(number_of_configured_nameservers(), OP_EQ, 1);
- nameserver_addr = configured_nameserver_address(0);
- tt_assert(tor_addr_family(nameserver_addr) == AF_INET);
- tt_assert(tor_addr_eq_ipv4h(nameserver_addr, 0x7f000001));
- #ifndef _WIN32
- tor_free(nameserver_addr);
- options.ServerDNSResolvConfFile = (char *)"/dev/null";
- dns_init();
- tt_int_op(number_of_configured_nameservers(), OP_EQ, 1);
- nameserver_addr = configured_nameserver_address(0);
- tt_assert(tor_addr_family(nameserver_addr) == AF_INET);
- tt_assert(tor_addr_eq_ipv4h(nameserver_addr, 0x7f000001));
- #endif /* !defined(_WIN32) */
- UNMOCK(get_options);
- done:
- tor_free(nameserver_addr);
- return;
- }
- #undef NS_SUBMODULE
- #endif /* defined(HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR) */
- #define NS_SUBMODULE clip_ttl
- static void
- NS(test_main)(void *arg)
- {
- (void)arg;
- uint32_t ttl_mid = MIN_DNS_TTL_AT_EXIT / 2 + MAX_DNS_TTL_AT_EXIT / 2;
- tt_int_op(dns_clip_ttl(MIN_DNS_TTL_AT_EXIT - 1),OP_EQ,MIN_DNS_TTL_AT_EXIT);
- tt_int_op(dns_clip_ttl(ttl_mid),OP_EQ,MAX_DNS_TTL_AT_EXIT);
- tt_int_op(dns_clip_ttl(MAX_DNS_TTL_AT_EXIT + 1),OP_EQ,MAX_DNS_TTL_AT_EXIT);
- done:
- return;
- }
- #undef NS_SUBMODULE
- #define NS_SUBMODULE resolve
- static int resolve_retval = 0;
- static int resolve_made_conn_pending = 0;
- static char *resolved_name = NULL;
- static cached_resolve_t *cache_entry_mock = NULL;
- static int n_fake_impl = 0;
- NS_DECL(int, dns_resolve_impl, (edge_connection_t *exitconn, int is_resolve,
- or_circuit_t *oncirc, char **hostname_out,
- int *made_connection_pending_out,
- cached_resolve_t **resolve_out));
- /** This will be our configurable substitute for <b>dns_resolve_impl</b> in
- * dns.c. It will return <b>resolve_retval</b>,
- * and set <b>resolve_made_conn_pending</b> to
- * <b>made_connection_pending_out</b>. It will set <b>hostname_out</b>
- * to a duplicate of <b>resolved_name</b> and it will set <b>resolve_out</b>
- * to <b>cache_entry</b>. Lastly, it will increment <b>n_fake_impl</b< by
- * 1.
- */
- static int
- NS(dns_resolve_impl)(edge_connection_t *exitconn, int is_resolve,
- or_circuit_t *oncirc, char **hostname_out,
- int *made_connection_pending_out,
- cached_resolve_t **resolve_out)
- {
- (void)oncirc;
- (void)exitconn;
- (void)is_resolve;
- if (made_connection_pending_out)
- *made_connection_pending_out = resolve_made_conn_pending;
- if (hostname_out && resolved_name)
- *hostname_out = tor_strdup(resolved_name);
- if (resolve_out && cache_entry_mock)
- *resolve_out = cache_entry_mock;
- n_fake_impl++;
- return resolve_retval;
- }
- static edge_connection_t *conn_for_resolved_cell = NULL;
- static int n_send_resolved_cell_replacement = 0;
- static uint8_t last_answer_type = 0;
- static cached_resolve_t *last_resolved;
- static void
- NS(send_resolved_cell)(edge_connection_t *conn, uint8_t answer_type,
- const cached_resolve_t *resolved)
- {
- conn_for_resolved_cell = conn;
- last_answer_type = answer_type;
- last_resolved = (cached_resolve_t *)resolved;
- n_send_resolved_cell_replacement++;
- }
- static int n_send_resolved_hostname_cell_replacement = 0;
- static char *last_resolved_hostname = NULL;
- static void
- NS(send_resolved_hostname_cell)(edge_connection_t *conn,
- const char *hostname)
- {
- conn_for_resolved_cell = conn;
- tor_free(last_resolved_hostname);
- last_resolved_hostname = tor_strdup(hostname);
- n_send_resolved_hostname_cell_replacement++;
- }
- static int n_dns_cancel_pending_resolve_replacement = 0;
- static void
- NS(dns_cancel_pending_resolve)(const char *address)
- {
- (void) address;
- n_dns_cancel_pending_resolve_replacement++;
- }
- static int n_connection_free = 0;
- static connection_t *last_freed_conn = NULL;
- static void
- NS(connection_free_)(connection_t *conn)
- {
- n_connection_free++;
- last_freed_conn = conn;
- }
- static void
- NS(test_main)(void *arg)
- {
- (void) arg;
- int retval;
- int prev_n_send_resolved_hostname_cell_replacement;
- int prev_n_send_resolved_cell_replacement;
- int prev_n_connection_free;
- cached_resolve_t *fake_resolved = tor_malloc(sizeof(cached_resolve_t));
- edge_connection_t *exitconn = tor_malloc(sizeof(edge_connection_t));
- edge_connection_t *nextconn = tor_malloc(sizeof(edge_connection_t));
- or_circuit_t *on_circuit = tor_malloc(sizeof(or_circuit_t));
- memset(on_circuit,0,sizeof(or_circuit_t));
- on_circuit->base_.magic = OR_CIRCUIT_MAGIC;
- memset(fake_resolved,0,sizeof(cached_resolve_t));
- memset(exitconn,0,sizeof(edge_connection_t));
- memset(nextconn,0,sizeof(edge_connection_t));
- NS_MOCK(dns_resolve_impl);
- NS_MOCK(send_resolved_cell);
- NS_MOCK(send_resolved_hostname_cell);
- /*
- * CASE 1: dns_resolve_impl returns 1 and sets a hostname. purpose is
- * EXIT_PURPOSE_RESOLVE.
- *
- * We want dns_resolve() to call send_resolved_hostname_cell() for a
- * given exit connection (represented by edge_connection_t object)
- * with a hostname it received from _impl.
- */
- prev_n_send_resolved_hostname_cell_replacement =
- n_send_resolved_hostname_cell_replacement;
- exitconn->base_.purpose = EXIT_PURPOSE_RESOLVE;
- exitconn->on_circuit = &(on_circuit->base_);
- resolve_retval = 1;
- resolved_name = tor_strdup("www.torproject.org");
- retval = dns_resolve(exitconn);
- tt_int_op(retval,OP_EQ,1);
- tt_str_op(resolved_name,OP_EQ,last_resolved_hostname);
- tt_assert(conn_for_resolved_cell == exitconn);
- tt_int_op(n_send_resolved_hostname_cell_replacement,OP_EQ,
- prev_n_send_resolved_hostname_cell_replacement + 1);
- tt_assert(exitconn->on_circuit == NULL);
- tor_free(last_resolved_hostname);
- // implies last_resolved_hostname = NULL;
- /* CASE 2: dns_resolve_impl returns 1, but does not set hostname.
- * Instead, it yields cached_resolve_t object.
- *
- * We want dns_resolve to call send_resolved_cell on exitconn with
- * RESOLVED_TYPE_AUTO and the cached_resolve_t object from _impl.
- */
- tor_free(resolved_name);
- resolved_name = NULL;
- exitconn->on_circuit = &(on_circuit->base_);
- cache_entry_mock = fake_resolved;
- prev_n_send_resolved_cell_replacement =
- n_send_resolved_cell_replacement;
- retval = dns_resolve(exitconn);
- tt_int_op(retval,OP_EQ,1);
- tt_assert(conn_for_resolved_cell == exitconn);
- tt_int_op(n_send_resolved_cell_replacement,OP_EQ,
- prev_n_send_resolved_cell_replacement + 1);
- tt_assert(last_resolved == fake_resolved);
- tt_int_op(last_answer_type,OP_EQ,0xff);
- tt_assert(exitconn->on_circuit == NULL);
- /* CASE 3: The purpose of exit connection is not EXIT_PURPOSE_RESOLVE
- * and _impl returns 1.
- *
- * We want dns_resolve to prepend exitconn to n_streams linked list.
- * We don't want it to send any cells about hostname being resolved.
- */
- exitconn->base_.purpose = EXIT_PURPOSE_CONNECT;
- exitconn->on_circuit = &(on_circuit->base_);
- on_circuit->n_streams = nextconn;
- prev_n_send_resolved_cell_replacement =
- n_send_resolved_cell_replacement;
- prev_n_send_resolved_hostname_cell_replacement =
- n_send_resolved_hostname_cell_replacement;
- retval = dns_resolve(exitconn);
- tt_int_op(retval,OP_EQ,1);
- tt_assert(on_circuit->n_streams == exitconn);
- tt_assert(exitconn->next_stream == nextconn);
- tt_int_op(prev_n_send_resolved_cell_replacement,OP_EQ,
- n_send_resolved_cell_replacement);
- tt_int_op(prev_n_send_resolved_hostname_cell_replacement,OP_EQ,
- n_send_resolved_hostname_cell_replacement);
- /* CASE 4: _impl returns 0.
- *
- * We want dns_resolve() to set exitconn state to
- * EXIT_CONN_STATE_RESOLVING and prepend exitconn to resolving_streams
- * linked list.
- */
- exitconn->on_circuit = &(on_circuit->base_);
- resolve_retval = 0;
- exitconn->next_stream = NULL;
- on_circuit->resolving_streams = nextconn;
- retval = dns_resolve(exitconn);
- tt_int_op(retval,OP_EQ,0);
- tt_int_op(exitconn->base_.state,OP_EQ,EXIT_CONN_STATE_RESOLVING);
- tt_assert(on_circuit->resolving_streams == exitconn);
- tt_assert(exitconn->next_stream == nextconn);
- /* CASE 5: _impl returns -1 when purpose of exitconn is
- * EXIT_PURPOSE_RESOLVE. We want dns_resolve to call send_resolved_cell
- * on exitconn with type being RESOLVED_TYPE_ERROR.
- */
- NS_MOCK(dns_cancel_pending_resolve);
- NS_MOCK(connection_free_);
- exitconn->on_circuit = &(on_circuit->base_);
- exitconn->base_.purpose = EXIT_PURPOSE_RESOLVE;
- resolve_retval = -1;
- prev_n_send_resolved_cell_replacement =
- n_send_resolved_cell_replacement;
- prev_n_connection_free = n_connection_free;
- retval = dns_resolve(exitconn);
- tt_int_op(retval,OP_EQ,-1);
- tt_int_op(n_send_resolved_cell_replacement,OP_EQ,
- prev_n_send_resolved_cell_replacement + 1);
- tt_int_op(last_answer_type,OP_EQ,RESOLVED_TYPE_ERROR);
- tt_int_op(n_dns_cancel_pending_resolve_replacement,OP_EQ,1);
- tt_int_op(n_connection_free,OP_EQ,prev_n_connection_free + 1);
- tt_assert(last_freed_conn == TO_CONN(exitconn));
- done:
- NS_UNMOCK(dns_resolve_impl);
- NS_UNMOCK(send_resolved_cell);
- NS_UNMOCK(send_resolved_hostname_cell);
- NS_UNMOCK(dns_cancel_pending_resolve);
- NS_UNMOCK(connection_free_);
- tor_free(on_circuit);
- tor_free(exitconn);
- tor_free(nextconn);
- tor_free(resolved_name);
- tor_free(fake_resolved);
- tor_free(last_resolved_hostname);
- return;
- }
- #undef NS_SUBMODULE
- /** Create an <b>edge_connection_t</b> instance that is considered a
- * valid exit connection by asserts in dns_resolve_impl.
- */
- static edge_connection_t *
- create_valid_exitconn(void)
- {
- edge_connection_t *exitconn = tor_malloc_zero(sizeof(edge_connection_t));
- TO_CONN(exitconn)->type = CONN_TYPE_EXIT;
- TO_CONN(exitconn)->magic = EDGE_CONNECTION_MAGIC;
- TO_CONN(exitconn)->purpose = EXIT_PURPOSE_RESOLVE;
- TO_CONN(exitconn)->state = EXIT_CONN_STATE_RESOLVING;
- exitconn->base_.s = TOR_INVALID_SOCKET;
- return exitconn;
- }
- #define NS_SUBMODULE ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve)
- /*
- * Given that <b>exitconn->base_.address</b> is IP address string, we
- * want dns_resolve_impl() to parse it and store in
- * <b>exitconn->base_.addr</b>. We expect dns_resolve_impl to return 1.
- * Lastly, we want it to set the TTL value to default one for DNS queries.
- */
- static void
- NS(test_main)(void *arg)
- {
- int retval;
- int made_pending;
- const tor_addr_t *resolved_addr;
- tor_addr_t addr_to_compare;
- (void)arg;
- tor_addr_parse(&addr_to_compare, "8.8.8.8");
- or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
- edge_connection_t *exitconn = create_valid_exitconn();
- TO_CONN(exitconn)->address = tor_strdup("8.8.8.8");
- retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
- NULL);
- resolved_addr = &(exitconn->base_.addr);
- tt_int_op(retval,OP_EQ,1);
- tt_assert(tor_addr_eq(resolved_addr, (const tor_addr_t *)&addr_to_compare));
- tt_int_op(exitconn->address_ttl,OP_EQ,DEFAULT_DNS_TTL);
- done:
- tor_free(on_circ);
- tor_free(TO_CONN(exitconn)->address);
- tor_free(exitconn);
- return;
- }
- #undef NS_SUBMODULE
- #define NS_SUBMODULE ASPECT(resolve_impl, non_exit)
- /** Given that Tor instance is not configured as an exit node, we want
- * dns_resolve_impl() to fail with return value -1.
- */
- static int
- NS(router_my_exit_policy_is_reject_star)(void)
- {
- return 1;
- }
- static void
- NS(test_main)(void *arg)
- {
- int retval;
- int made_pending;
- edge_connection_t *exitconn = create_valid_exitconn();
- or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
- (void)arg;
- TO_CONN(exitconn)->address = tor_strdup("torproject.org");
- NS_MOCK(router_my_exit_policy_is_reject_star);
- retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
- NULL);
- tt_int_op(retval,OP_EQ,-1);
- done:
- tor_free(TO_CONN(exitconn)->address);
- tor_free(exitconn);
- tor_free(on_circ);
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
- return;
- }
- #undef NS_SUBMODULE
- #define NS_SUBMODULE ASPECT(resolve_impl, addr_is_invalid_dest)
- /** Given that address is not a valid destination (as judged by
- * address_is_invalid_destination() function), we want dns_resolve_impl()
- * function to fail with return value -1.
- */
- static int
- NS(router_my_exit_policy_is_reject_star)(void)
- {
- return 0;
- }
- static void
- NS(test_main)(void *arg)
- {
- int retval;
- int made_pending;
- edge_connection_t *exitconn = create_valid_exitconn();
- or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
- (void)arg;
- NS_MOCK(router_my_exit_policy_is_reject_star);
- TO_CONN(exitconn)->address = tor_strdup("invalid#@!.org");
- retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
- NULL);
- tt_int_op(retval,OP_EQ,-1);
- done:
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
- tor_free(TO_CONN(exitconn)->address);
- tor_free(exitconn);
- tor_free(on_circ);
- return;
- }
- #undef NS_SUBMODULE
- #define NS_SUBMODULE ASPECT(resolve_impl, malformed_ptr)
- /** Given that address is a malformed PTR name, we want dns_resolve_impl to
- * fail.
- */
- static int
- NS(router_my_exit_policy_is_reject_star)(void)
- {
- return 0;
- }
- static void
- NS(test_main)(void *arg)
- {
- int retval;
- int made_pending;
- edge_connection_t *exitconn = create_valid_exitconn();
- or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
- (void)arg;
- TO_CONN(exitconn)->address = tor_strdup("1.0.0.127.in-addr.arpa");
- NS_MOCK(router_my_exit_policy_is_reject_star);
- retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
- NULL);
- tt_int_op(retval,OP_EQ,-1);
- tor_free(TO_CONN(exitconn)->address);
- TO_CONN(exitconn)->address =
- tor_strdup("z01234567890123456789.in-addr.arpa");
- retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
- NULL);
- tt_int_op(retval,OP_EQ,-1);
- done:
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
- tor_free(TO_CONN(exitconn)->address);
- tor_free(exitconn);
- tor_free(on_circ);
- return;
- }
- #undef NS_SUBMODULE
- #define NS_SUBMODULE ASPECT(resolve_impl, cache_hit_pending)
- /* Given that there is already a pending resolve for the given address,
- * we want dns_resolve_impl to append our exit connection to list
- * of pending connections for the pending DNS request and return 0.
- */
- static int
- NS(router_my_exit_policy_is_reject_star)(void)
- {
- return 0;
- }
- static void
- NS(test_main)(void *arg)
- {
- int retval;
- int made_pending = 0;
- pending_connection_t *pending_conn = NULL;
- edge_connection_t *exitconn = create_valid_exitconn();
- or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
- cached_resolve_t *cache_entry = tor_malloc_zero(sizeof(cached_resolve_t));
- cache_entry->magic = CACHED_RESOLVE_MAGIC;
- cache_entry->state = CACHE_STATE_PENDING;
- cache_entry->minheap_idx = -1;
- cache_entry->expire = time(NULL) + 60 * 60;
- (void)arg;
- TO_CONN(exitconn)->address = tor_strdup("torproject.org");
- strlcpy(cache_entry->address, TO_CONN(exitconn)->address,
- sizeof(cache_entry->address));
- NS_MOCK(router_my_exit_policy_is_reject_star);
- dns_init();
- dns_insert_cache_entry(cache_entry);
- retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
- NULL);
- tt_int_op(retval,OP_EQ,0);
- tt_int_op(made_pending,OP_EQ,1);
- pending_conn = cache_entry->pending_connections;
- tt_assert(pending_conn != NULL);
- tt_assert(pending_conn->conn == exitconn);
- done:
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
- tor_free(on_circ);
- tor_free(TO_CONN(exitconn)->address);
- tor_free(cache_entry->pending_connections);
- tor_free(cache_entry);
- tor_free(exitconn);
- return;
- }
- #undef NS_SUBMODULE
- #define NS_SUBMODULE ASPECT(resolve_impl, cache_hit_cached)
- /* Given that a finished DNS resolve is available in our cache, we want
- * dns_resolve_impl() return it to called via resolve_out and pass the
- * handling to set_exitconn_info_from_resolve function.
- */
- static int
- NS(router_my_exit_policy_is_reject_star)(void)
- {
- return 0;
- }
- static edge_connection_t *last_exitconn = NULL;
- static cached_resolve_t *last_resolve = NULL;
- static int
- NS(set_exitconn_info_from_resolve)(edge_connection_t *exitconn,
- const cached_resolve_t *resolve,
- char **hostname_out)
- {
- last_exitconn = exitconn;
- last_resolve = (cached_resolve_t *)resolve;
- (void)hostname_out;
- return 0;
- }
- static void
- NS(test_main)(void *arg)
- {
- int retval;
- int made_pending = 0;
- edge_connection_t *exitconn = create_valid_exitconn();
- or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
- cached_resolve_t *resolve_out = NULL;
- cached_resolve_t *cache_entry = tor_malloc_zero(sizeof(cached_resolve_t));
- cache_entry->magic = CACHED_RESOLVE_MAGIC;
- cache_entry->state = CACHE_STATE_CACHED;
- cache_entry->minheap_idx = -1;
- cache_entry->expire = time(NULL) + 60 * 60;
- (void)arg;
- TO_CONN(exitconn)->address = tor_strdup("torproject.org");
- strlcpy(cache_entry->address, TO_CONN(exitconn)->address,
- sizeof(cache_entry->address));
- NS_MOCK(router_my_exit_policy_is_reject_star);
- NS_MOCK(set_exitconn_info_from_resolve);
- dns_init();
- dns_insert_cache_entry(cache_entry);
- retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
- &resolve_out);
- tt_int_op(retval,OP_EQ,0);
- tt_int_op(made_pending,OP_EQ,0);
- tt_assert(resolve_out == cache_entry);
- tt_assert(last_exitconn == exitconn);
- tt_assert(last_resolve == cache_entry);
- done:
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
- NS_UNMOCK(set_exitconn_info_from_resolve);
- tor_free(on_circ);
- tor_free(TO_CONN(exitconn)->address);
- tor_free(cache_entry->pending_connections);
- tor_free(cache_entry);
- return;
- }
- #undef NS_SUBMODULE
- #define NS_SUBMODULE ASPECT(resolve_impl, cache_miss)
- /* Given that there are neither pending nor pre-cached resolve for a given
- * address, we want dns_resolve_impl() to create a new cached_resolve_t
- * object, mark it as pending, insert it into the cache, attach the exit
- * connection to list of pending connections and call launch_resolve()
- * with the cached_resolve_t object it created.
- */
- static int
- NS(router_my_exit_policy_is_reject_star)(void)
- {
- return 0;
- }
- static cached_resolve_t *last_launched_resolve = NULL;
- static int
- NS(launch_resolve)(cached_resolve_t *resolve)
- {
- last_launched_resolve = resolve;
- return 0;
- }
- static void
- NS(test_main)(void *arg)
- {
- int retval;
- int made_pending = 0;
- pending_connection_t *pending_conn = NULL;
- edge_connection_t *exitconn = create_valid_exitconn();
- or_circuit_t *on_circ = tor_malloc_zero(sizeof(or_circuit_t));
- cached_resolve_t *cache_entry = NULL;
- cached_resolve_t query;
- (void)arg;
- TO_CONN(exitconn)->address = tor_strdup("torproject.org");
- strlcpy(query.address, TO_CONN(exitconn)->address, sizeof(query.address));
- NS_MOCK(router_my_exit_policy_is_reject_star);
- NS_MOCK(launch_resolve);
- dns_init();
- retval = dns_resolve_impl(exitconn, 1, on_circ, NULL, &made_pending,
- NULL);
- tt_int_op(retval,OP_EQ,0);
- tt_int_op(made_pending,OP_EQ,1);
- cache_entry = dns_get_cache_entry(&query);
- tt_assert(cache_entry);
- pending_conn = cache_entry->pending_connections;
- tt_assert(pending_conn != NULL);
- tt_assert(pending_conn->conn == exitconn);
- tt_assert(last_launched_resolve == cache_entry);
- tt_str_op(cache_entry->address,OP_EQ,TO_CONN(exitconn)->address);
- done:
- NS_UNMOCK(router_my_exit_policy_is_reject_star);
- NS_UNMOCK(launch_resolve);
- tor_free(on_circ);
- tor_free(TO_CONN(exitconn)->address);
- if (cache_entry)
- tor_free(cache_entry->pending_connections);
- tor_free(cache_entry);
- tor_free(exitconn);
- return;
- }
- #undef NS_SUBMODULE
- struct testcase_t dns_tests[] = {
- #ifdef HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR
- TEST_CASE(configure_nameservers_fallback),
- #endif
- TEST_CASE(clip_ttl),
- TEST_CASE(resolve),
- TEST_CASE_ASPECT(resolve_impl, addr_is_ip_no_need_to_resolve),
- TEST_CASE_ASPECT(resolve_impl, non_exit),
- TEST_CASE_ASPECT(resolve_impl, addr_is_invalid_dest),
- TEST_CASE_ASPECT(resolve_impl, malformed_ptr),
- TEST_CASE_ASPECT(resolve_impl, cache_hit_pending),
- TEST_CASE_ASPECT(resolve_impl, cache_hit_cached),
- TEST_CASE_ASPECT(resolve_impl, cache_miss),
- END_OF_TESTCASES
- };
- #undef NS_MODULE
|