1 /* Copyright (c) 2015-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
5 #include "core/or/or.h"
10 #include "feature/relay/dns.h"
11 #include "core/mainloop/connection.h"
12 #include "core/or/connection_edge.h"
13 #include "feature/relay/router.h"
15 #include "core/or/edge_connection_st.h"
16 #include "core/or/or_circuit_st.h"
17 #include "app/config/or_options_st.h"
18 #include "app/config/config.h"
20 #include <event2/event.h>
21 #include <event2/dns.h>
23 #ifdef HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR
25 static or_options_t options
= {
29 static const or_options_t
*
30 mock_get_options(void)
36 test_dns_configure_ns_fallback(void *arg
)
39 tor_addr_t
*nameserver_addr
= NULL
;
41 MOCK(get_options
, mock_get_options
);
43 options
.ServerDNSResolvConfFile
= (char *)"no_such_file!!!";
45 dns_init(); // calls configure_nameservers()
47 tt_int_op(number_of_configured_nameservers(), OP_EQ
, 1);
49 nameserver_addr
= configured_nameserver_address(0);
51 tt_assert(tor_addr_family(nameserver_addr
) == AF_INET
);
52 tt_assert(tor_addr_eq_ipv4h(nameserver_addr
, 0x7f000001));
55 tor_free(nameserver_addr
);
57 options
.ServerDNSResolvConfFile
= (char *)"/dev/null";
61 tt_int_op(number_of_configured_nameservers(), OP_EQ
, 1);
63 nameserver_addr
= configured_nameserver_address(0);
65 tt_assert(tor_addr_family(nameserver_addr
) == AF_INET
);
66 tt_assert(tor_addr_eq_ipv4h(nameserver_addr
, 0x7f000001));
67 #endif /* !defined(_WIN32) */
72 tor_free(nameserver_addr
);
76 #endif /* defined(HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR) */
79 test_dns_clip_ttl(void *arg
)
83 uint32_t ttl_mid
= MIN_DNS_TTL
/ 2 + MAX_DNS_TTL
/ 2;
85 tt_int_op(clip_dns_ttl(MIN_DNS_TTL
- 1),OP_EQ
,MIN_DNS_TTL
);
86 tt_int_op(clip_dns_ttl(ttl_mid
),OP_EQ
,MAX_DNS_TTL
);
87 tt_int_op(clip_dns_ttl(MAX_DNS_TTL
+ 1),OP_EQ
,MAX_DNS_TTL
);
94 test_dns_clip_fuzzy_ttl(void *arg
)
98 /* Case 0: check that the fuzzy TTL constant is valid
100 tt_int_op(FUZZY_DNS_TTL
, OP_LE
, MIN_DNS_TTL
);
101 tt_int_op(FUZZY_DNS_TTL
, OP_LE
, MAX_DNS_TTL
);
105 for (int i
= 0; i
< 1024; i
++) {
106 int fuzzy_ttl
= clip_dns_fuzzy_ttl(MIN_DNS_TTL
- 1);
107 tt_int_op(fuzzy_ttl
, OP_GE
, MIN_DNS_TTL
-FUZZY_DNS_TTL
);
108 tt_int_op(fuzzy_ttl
, OP_LE
, MIN_DNS_TTL
+FUZZY_DNS_TTL
);
111 /* Case 2: high clips
113 for (int i
= 0; i
< 1024; i
++) {
114 int fuzzy_ttl
= clip_dns_fuzzy_ttl(MIN_DNS_TTL
);
115 tt_int_op(fuzzy_ttl
, OP_GE
, MAX_DNS_TTL
-FUZZY_DNS_TTL
);
116 tt_int_op(fuzzy_ttl
, OP_LE
, MAX_DNS_TTL
+FUZZY_DNS_TTL
);
123 static int resolve_retval
= 0;
124 static int resolve_made_conn_pending
= 0;
125 static char *resolved_name
= NULL
;
126 static cached_resolve_t
*cache_entry_mock
= NULL
;
128 static int n_fake_impl
= 0;
130 static int dns_resolve_dns_resolve_impl(edge_connection_t
*exitconn
,
131 int is_resolve
, or_circuit_t
*oncirc
,
132 char **hostname_out
, int *made_connection_pending_out
,
133 cached_resolve_t
**resolve_out
);
134 ATTR_UNUSED
static int dns_resolve_dns_resolve_impl_called
= 0;
136 /** This will be our configurable substitute for <b>dns_resolve_impl</b> in
137 * dns.c. It will return <b>resolve_retval</b>,
138 * and set <b>resolve_made_conn_pending</b> to
139 * <b>made_connection_pending_out</b>. It will set <b>hostname_out</b>
140 * to a duplicate of <b>resolved_name</b> and it will set <b>resolve_out</b>
141 * to <b>cache_entry</b>. Lastly, it will increment <b>n_fake_impl</b< by
145 dns_resolve_dns_resolve_impl(edge_connection_t
*exitconn
, int is_resolve
,
146 or_circuit_t
*oncirc
, char **hostname_out
,
147 int *made_connection_pending_out
,
148 cached_resolve_t
**resolve_out
)
154 if (made_connection_pending_out
)
155 *made_connection_pending_out
= resolve_made_conn_pending
;
157 if (hostname_out
&& resolved_name
)
158 *hostname_out
= tor_strdup(resolved_name
);
160 if (resolve_out
&& cache_entry_mock
)
161 *resolve_out
= cache_entry_mock
;
165 return resolve_retval
;
168 static edge_connection_t
*conn_for_resolved_cell
= NULL
;
170 static int n_send_resolved_cell_replacement
= 0;
171 static uint8_t last_answer_type
= 0;
172 static cached_resolve_t
*last_resolved
;
175 dns_resolve_send_resolved_cell(edge_connection_t
*conn
, uint8_t answer_type
,
176 const cached_resolve_t
*resolved
)
178 conn_for_resolved_cell
= conn
;
180 last_answer_type
= answer_type
;
181 last_resolved
= (cached_resolve_t
*)resolved
;
183 n_send_resolved_cell_replacement
++;
186 static int n_send_resolved_hostname_cell_replacement
= 0;
188 static char *last_resolved_hostname
= NULL
;
191 dns_resolve_send_resolved_hostname_cell(edge_connection_t
*conn
,
192 const char *hostname
)
194 conn_for_resolved_cell
= conn
;
196 tor_free(last_resolved_hostname
);
197 last_resolved_hostname
= tor_strdup(hostname
);
199 n_send_resolved_hostname_cell_replacement
++;
202 static int n_dns_cancel_pending_resolve_replacement
= 0;
205 dns_resolve_dns_cancel_pending_resolve(const char *address
)
208 n_dns_cancel_pending_resolve_replacement
++;
211 static int n_connection_free
= 0;
212 static connection_t
*last_freed_conn
= NULL
;
215 dns_resolve_connection_free_(connection_t
*conn
)
219 last_freed_conn
= conn
;
223 test_dns_resolve(void *arg
)
227 int prev_n_send_resolved_hostname_cell_replacement
;
228 int prev_n_send_resolved_cell_replacement
;
229 int prev_n_connection_free
;
230 cached_resolve_t
*fake_resolved
= tor_malloc(sizeof(cached_resolve_t
));
231 edge_connection_t
*exitconn
= tor_malloc(sizeof(edge_connection_t
));
232 edge_connection_t
*nextconn
= tor_malloc(sizeof(edge_connection_t
));
234 or_circuit_t
*on_circuit
= tor_malloc(sizeof(or_circuit_t
));
235 memset(on_circuit
,0,sizeof(or_circuit_t
));
236 on_circuit
->base_
.magic
= OR_CIRCUIT_MAGIC
;
238 memset(fake_resolved
,0,sizeof(cached_resolve_t
));
239 memset(exitconn
,0,sizeof(edge_connection_t
));
240 memset(nextconn
,0,sizeof(edge_connection_t
));
242 MOCK(dns_resolve_impl
,
243 dns_resolve_dns_resolve_impl
);
244 MOCK(send_resolved_cell
,
245 dns_resolve_send_resolved_cell
);
246 MOCK(send_resolved_hostname_cell
,
247 dns_resolve_send_resolved_hostname_cell
);
250 * CASE 1: dns_resolve_impl returns 1 and sets a hostname. purpose is
251 * EXIT_PURPOSE_RESOLVE.
253 * We want dns_resolve() to call send_resolved_hostname_cell() for a
254 * given exit connection (represented by edge_connection_t object)
255 * with a hostname it received from _impl.
258 prev_n_send_resolved_hostname_cell_replacement
=
259 n_send_resolved_hostname_cell_replacement
;
261 exitconn
->base_
.purpose
= EXIT_PURPOSE_RESOLVE
;
262 exitconn
->on_circuit
= &(on_circuit
->base_
);
265 resolved_name
= tor_strdup("www.torproject.org");
267 retval
= dns_resolve(exitconn
);
269 tt_int_op(retval
,OP_EQ
,1);
270 tt_str_op(resolved_name
,OP_EQ
,last_resolved_hostname
);
271 tt_assert(conn_for_resolved_cell
== exitconn
);
272 tt_int_op(n_send_resolved_hostname_cell_replacement
,OP_EQ
,
273 prev_n_send_resolved_hostname_cell_replacement
+ 1);
274 tt_assert(exitconn
->on_circuit
== NULL
);
276 tor_free(last_resolved_hostname
);
277 // implies last_resolved_hostname = NULL;
279 /* CASE 2: dns_resolve_impl returns 1, but does not set hostname.
280 * Instead, it yields cached_resolve_t object.
282 * We want dns_resolve to call send_resolved_cell on exitconn with
283 * RESOLVED_TYPE_AUTO and the cached_resolve_t object from _impl.
286 tor_free(resolved_name
);
287 resolved_name
= NULL
;
289 exitconn
->on_circuit
= &(on_circuit
->base_
);
291 cache_entry_mock
= fake_resolved
;
293 prev_n_send_resolved_cell_replacement
=
294 n_send_resolved_cell_replacement
;
296 retval
= dns_resolve(exitconn
);
298 tt_int_op(retval
,OP_EQ
,1);
299 tt_assert(conn_for_resolved_cell
== exitconn
);
300 tt_int_op(n_send_resolved_cell_replacement
,OP_EQ
,
301 prev_n_send_resolved_cell_replacement
+ 1);
302 tt_assert(last_resolved
== fake_resolved
);
303 tt_int_op(last_answer_type
,OP_EQ
,0xff);
304 tt_assert(exitconn
->on_circuit
== NULL
);
306 /* CASE 3: The purpose of exit connection is not EXIT_PURPOSE_RESOLVE
307 * and _impl returns 1.
309 * We want dns_resolve to prepend exitconn to n_streams linked list.
310 * We don't want it to send any cells about hostname being resolved.
313 exitconn
->base_
.purpose
= EXIT_PURPOSE_CONNECT
;
314 exitconn
->on_circuit
= &(on_circuit
->base_
);
316 on_circuit
->n_streams
= nextconn
;
318 prev_n_send_resolved_cell_replacement
=
319 n_send_resolved_cell_replacement
;
321 prev_n_send_resolved_hostname_cell_replacement
=
322 n_send_resolved_hostname_cell_replacement
;
324 retval
= dns_resolve(exitconn
);
326 tt_int_op(retval
,OP_EQ
,1);
327 tt_assert(on_circuit
->n_streams
== exitconn
);
328 tt_assert(exitconn
->next_stream
== nextconn
);
329 tt_int_op(prev_n_send_resolved_cell_replacement
,OP_EQ
,
330 n_send_resolved_cell_replacement
);
331 tt_int_op(prev_n_send_resolved_hostname_cell_replacement
,OP_EQ
,
332 n_send_resolved_hostname_cell_replacement
);
334 /* CASE 4: _impl returns 0.
336 * We want dns_resolve() to set exitconn state to
337 * EXIT_CONN_STATE_RESOLVING and prepend exitconn to resolving_streams
341 exitconn
->on_circuit
= &(on_circuit
->base_
);
345 exitconn
->next_stream
= NULL
;
346 on_circuit
->resolving_streams
= nextconn
;
348 retval
= dns_resolve(exitconn
);
350 tt_int_op(retval
,OP_EQ
,0);
351 tt_int_op(exitconn
->base_
.state
,OP_EQ
,EXIT_CONN_STATE_RESOLVING
);
352 tt_assert(on_circuit
->resolving_streams
== exitconn
);
353 tt_assert(exitconn
->next_stream
== nextconn
);
355 /* CASE 5: _impl returns -1 when purpose of exitconn is
356 * EXIT_PURPOSE_RESOLVE. We want dns_resolve to call send_resolved_cell
357 * on exitconn with type being RESOLVED_TYPE_ERROR.
360 MOCK(dns_cancel_pending_resolve
,
361 dns_resolve_dns_cancel_pending_resolve
);
362 MOCK(connection_free_
,
363 dns_resolve_connection_free_
);
365 exitconn
->on_circuit
= &(on_circuit
->base_
);
366 exitconn
->base_
.purpose
= EXIT_PURPOSE_RESOLVE
;
370 prev_n_send_resolved_cell_replacement
=
371 n_send_resolved_cell_replacement
;
373 prev_n_connection_free
= n_connection_free
;
375 retval
= dns_resolve(exitconn
);
377 tt_int_op(retval
,OP_EQ
,-1);
378 tt_int_op(n_send_resolved_cell_replacement
,OP_EQ
,
379 prev_n_send_resolved_cell_replacement
+ 1);
380 tt_int_op(last_answer_type
,OP_EQ
,RESOLVED_TYPE_ERROR
);
381 tt_int_op(n_dns_cancel_pending_resolve_replacement
,OP_EQ
,1);
382 tt_int_op(n_connection_free
,OP_EQ
,prev_n_connection_free
+ 1);
383 tt_assert(last_freed_conn
== TO_CONN(exitconn
));
386 UNMOCK(dns_resolve_impl
);
387 UNMOCK(send_resolved_cell
);
388 UNMOCK(send_resolved_hostname_cell
);
389 UNMOCK(dns_cancel_pending_resolve
);
390 UNMOCK(connection_free_
);
391 tor_free(on_circuit
);
394 tor_free(resolved_name
);
395 tor_free(fake_resolved
);
396 tor_free(last_resolved_hostname
);
400 /** Create an <b>edge_connection_t</b> instance that is considered a
401 * valid exit connection by asserts in dns_resolve_impl.
403 static edge_connection_t
*
404 create_valid_exitconn(void)
406 edge_connection_t
*exitconn
= tor_malloc_zero(sizeof(edge_connection_t
));
407 TO_CONN(exitconn
)->type
= CONN_TYPE_EXIT
;
408 TO_CONN(exitconn
)->magic
= EDGE_CONNECTION_MAGIC
;
409 TO_CONN(exitconn
)->purpose
= EXIT_PURPOSE_RESOLVE
;
410 TO_CONN(exitconn
)->state
= EXIT_CONN_STATE_RESOLVING
;
411 exitconn
->base_
.s
= TOR_INVALID_SOCKET
;
417 * Given that <b>exitconn->base_.address</b> is IP address string, we
418 * want dns_resolve_impl() to parse it and store in
419 * <b>exitconn->base_.addr</b>. We expect dns_resolve_impl to return 1.
420 * Lastly, we want it to set the TTL value to default one for DNS queries.
424 test_dns_impl_addr_is_ip(void *arg
)
428 const tor_addr_t
*resolved_addr
;
429 tor_addr_t addr_to_compare
;
433 tor_addr_parse(&addr_to_compare
, "8.8.8.8");
435 or_circuit_t
*on_circ
= tor_malloc_zero(sizeof(or_circuit_t
));
437 edge_connection_t
*exitconn
= create_valid_exitconn();
439 TO_CONN(exitconn
)->address
= tor_strdup("8.8.8.8");
441 retval
= dns_resolve_impl(exitconn
, 1, on_circ
, NULL
, &made_pending
,
444 resolved_addr
= &(exitconn
->base_
.addr
);
446 tt_int_op(retval
,OP_EQ
,1);
447 tt_assert(tor_addr_eq(resolved_addr
, (const tor_addr_t
*)&addr_to_compare
));
448 tt_int_op(exitconn
->address_ttl
,OP_EQ
,DEFAULT_DNS_TTL
);
452 tor_free(TO_CONN(exitconn
)->address
);
457 /** Given that Tor instance is not configured as an exit node, we want
458 * dns_resolve_impl() to fail with return value -1.
461 dns_impl_non_exit_router_my_exit_policy_is_reject_star(void)
467 test_dns_impl_non_exit(void *arg
)
472 edge_connection_t
*exitconn
= create_valid_exitconn();
473 or_circuit_t
*on_circ
= tor_malloc_zero(sizeof(or_circuit_t
));
477 TO_CONN(exitconn
)->address
= tor_strdup("torproject.org");
479 MOCK(router_my_exit_policy_is_reject_star
,
480 dns_impl_non_exit_router_my_exit_policy_is_reject_star
);
482 retval
= dns_resolve_impl(exitconn
, 1, on_circ
, NULL
, &made_pending
,
485 tt_int_op(retval
,OP_EQ
,-1);
488 tor_free(TO_CONN(exitconn
)->address
);
491 UNMOCK(router_my_exit_policy_is_reject_star
);
495 /** Given that address is not a valid destination (as judged by
496 * address_is_invalid_destination() function), we want dns_resolve_impl()
497 * function to fail with return value -1.
501 dns_impl_addr_is_invalid_dest_router_my_exit_policy_is_reject_star(void)
507 test_dns_impl_addr_is_invalid_dest(void *arg
)
512 edge_connection_t
*exitconn
= create_valid_exitconn();
513 or_circuit_t
*on_circ
= tor_malloc_zero(sizeof(or_circuit_t
));
517 MOCK(router_my_exit_policy_is_reject_star
,
518 dns_impl_addr_is_invalid_dest_router_my_exit_policy_is_reject_star
);
520 TO_CONN(exitconn
)->address
= tor_strdup("invalid#@!.org");
522 retval
= dns_resolve_impl(exitconn
, 1, on_circ
, NULL
, &made_pending
,
525 tt_int_op(retval
,OP_EQ
,-1);
528 UNMOCK(router_my_exit_policy_is_reject_star
);
529 tor_free(TO_CONN(exitconn
)->address
);
535 /** Given that address is a malformed PTR name, we want dns_resolve_impl to
540 dns_impl_malformed_ptr_router_my_exit_policy_is_reject_star(void)
546 test_dns_impl_malformed_ptr(void *arg
)
551 edge_connection_t
*exitconn
= create_valid_exitconn();
552 or_circuit_t
*on_circ
= tor_malloc_zero(sizeof(or_circuit_t
));
556 TO_CONN(exitconn
)->address
= tor_strdup("1.0.0.127.in-addr.arpa");
558 MOCK(router_my_exit_policy_is_reject_star
,
559 dns_impl_malformed_ptr_router_my_exit_policy_is_reject_star
);
561 retval
= dns_resolve_impl(exitconn
, 1, on_circ
, NULL
, &made_pending
,
564 tt_int_op(retval
,OP_EQ
,-1);
566 tor_free(TO_CONN(exitconn
)->address
);
568 TO_CONN(exitconn
)->address
=
569 tor_strdup("z01234567890123456789.in-addr.arpa");
571 retval
= dns_resolve_impl(exitconn
, 1, on_circ
, NULL
, &made_pending
,
574 tt_int_op(retval
,OP_EQ
,-1);
577 UNMOCK(router_my_exit_policy_is_reject_star
);
578 tor_free(TO_CONN(exitconn
)->address
);
584 /* Given that there is already a pending resolve for the given address,
585 * we want dns_resolve_impl to append our exit connection to list
586 * of pending connections for the pending DNS request and return 0.
590 dns_impl_cache_hit_pending_router_my_exit_policy_is_reject_star(void)
596 test_dns_impl_cache_hit_pending(void *arg
)
599 int made_pending
= 0;
601 pending_connection_t
*pending_conn
= NULL
;
603 edge_connection_t
*exitconn
= create_valid_exitconn();
604 or_circuit_t
*on_circ
= tor_malloc_zero(sizeof(or_circuit_t
));
606 cached_resolve_t
*cache_entry
= tor_malloc_zero(sizeof(cached_resolve_t
));
607 cache_entry
->magic
= CACHED_RESOLVE_MAGIC
;
608 cache_entry
->state
= CACHE_STATE_PENDING
;
609 cache_entry
->minheap_idx
= -1;
610 cache_entry
->expire
= time(NULL
) + 60 * 60;
614 TO_CONN(exitconn
)->address
= tor_strdup("torproject.org");
616 strlcpy(cache_entry
->address
, TO_CONN(exitconn
)->address
,
617 sizeof(cache_entry
->address
));
619 MOCK(router_my_exit_policy_is_reject_star
,
620 dns_impl_cache_hit_pending_router_my_exit_policy_is_reject_star
);
624 dns_insert_cache_entry(cache_entry
);
626 retval
= dns_resolve_impl(exitconn
, 1, on_circ
, NULL
, &made_pending
,
629 tt_int_op(retval
,OP_EQ
,0);
630 tt_int_op(made_pending
,OP_EQ
,1);
632 pending_conn
= cache_entry
->pending_connections
;
634 tt_assert(pending_conn
!= NULL
);
635 tt_assert(pending_conn
->conn
== exitconn
);
638 UNMOCK(router_my_exit_policy_is_reject_star
);
640 tor_free(TO_CONN(exitconn
)->address
);
641 tor_free(cache_entry
->pending_connections
);
642 tor_free(cache_entry
);
647 /* Given that a finished DNS resolve is available in our cache, we want
648 * dns_resolve_impl() return it to called via resolve_out and pass the
649 * handling to set_exitconn_info_from_resolve function.
652 dns_impl_cache_hit_cached_router_my_exit_policy_is_reject_star(void)
657 static edge_connection_t
*last_exitconn
= NULL
;
658 static cached_resolve_t
*last_resolve
= NULL
;
661 dns_impl_cache_hit_cached_set_exitconn_info_from_resolve(
662 edge_connection_t
*exitconn
,
663 const cached_resolve_t
*resolve
,
666 last_exitconn
= exitconn
;
667 last_resolve
= (cached_resolve_t
*)resolve
;
675 test_dns_impl_cache_hit_cached(void *arg
)
678 int made_pending
= 0;
680 edge_connection_t
*exitconn
= create_valid_exitconn();
681 or_circuit_t
*on_circ
= tor_malloc_zero(sizeof(or_circuit_t
));
683 cached_resolve_t
*resolve_out
= NULL
;
685 cached_resolve_t
*cache_entry
= tor_malloc_zero(sizeof(cached_resolve_t
));
686 cache_entry
->magic
= CACHED_RESOLVE_MAGIC
;
687 cache_entry
->state
= CACHE_STATE_CACHED
;
688 cache_entry
->minheap_idx
= -1;
689 cache_entry
->expire
= time(NULL
) + 60 * 60;
693 TO_CONN(exitconn
)->address
= tor_strdup("torproject.org");
695 strlcpy(cache_entry
->address
, TO_CONN(exitconn
)->address
,
696 sizeof(cache_entry
->address
));
698 MOCK(router_my_exit_policy_is_reject_star
,
699 dns_impl_cache_hit_cached_router_my_exit_policy_is_reject_star
);
700 MOCK(set_exitconn_info_from_resolve
,
701 dns_impl_cache_hit_cached_set_exitconn_info_from_resolve
);
705 dns_insert_cache_entry(cache_entry
);
707 retval
= dns_resolve_impl(exitconn
, 1, on_circ
, NULL
, &made_pending
,
710 tt_int_op(retval
,OP_EQ
,0);
711 tt_int_op(made_pending
,OP_EQ
,0);
712 tt_assert(resolve_out
== cache_entry
);
714 tt_assert(last_exitconn
== exitconn
);
715 tt_assert(last_resolve
== cache_entry
);
718 UNMOCK(router_my_exit_policy_is_reject_star
);
719 UNMOCK(set_exitconn_info_from_resolve
);
721 tor_free(TO_CONN(exitconn
)->address
);
722 tor_free(cache_entry
->pending_connections
);
723 tor_free(cache_entry
);
727 /* Given that there are neither pending nor pre-cached resolve for a given
728 * address, we want dns_resolve_impl() to create a new cached_resolve_t
729 * object, mark it as pending, insert it into the cache, attach the exit
730 * connection to list of pending connections and call launch_resolve()
731 * with the cached_resolve_t object it created.
734 dns_impl_cache_miss_router_my_exit_policy_is_reject_star(void)
739 static cached_resolve_t
*last_launched_resolve
= NULL
;
742 dns_impl_cache_miss_launch_resolve(cached_resolve_t
*resolve
)
744 last_launched_resolve
= resolve
;
750 test_dns_impl_cache_miss(void *arg
)
753 int made_pending
= 0;
755 pending_connection_t
*pending_conn
= NULL
;
757 edge_connection_t
*exitconn
= create_valid_exitconn();
758 or_circuit_t
*on_circ
= tor_malloc_zero(sizeof(or_circuit_t
));
760 cached_resolve_t
*cache_entry
= NULL
;
761 cached_resolve_t query
;
765 TO_CONN(exitconn
)->address
= tor_strdup("torproject.org");
767 strlcpy(query
.address
, TO_CONN(exitconn
)->address
, sizeof(query
.address
));
769 MOCK(router_my_exit_policy_is_reject_star
,
770 dns_impl_cache_miss_router_my_exit_policy_is_reject_star
);
772 dns_impl_cache_miss_launch_resolve
);
776 retval
= dns_resolve_impl(exitconn
, 1, on_circ
, NULL
, &made_pending
,
779 tt_int_op(retval
,OP_EQ
,0);
780 tt_int_op(made_pending
,OP_EQ
,1);
782 cache_entry
= dns_get_cache_entry(&query
);
784 tt_assert(cache_entry
);
786 pending_conn
= cache_entry
->pending_connections
;
788 tt_assert(pending_conn
!= NULL
);
789 tt_assert(pending_conn
->conn
== exitconn
);
791 tt_assert(last_launched_resolve
== cache_entry
);
792 tt_str_op(cache_entry
->address
,OP_EQ
,TO_CONN(exitconn
)->address
);
795 UNMOCK(router_my_exit_policy_is_reject_star
);
796 UNMOCK(launch_resolve
);
798 tor_free(TO_CONN(exitconn
)->address
);
800 tor_free(cache_entry
->pending_connections
);
801 tor_free(cache_entry
);
806 struct testcase_t dns_tests
[] = {
807 #ifdef HAVE_EVDNS_BASE_GET_NAMESERVER_ADDR
808 { "configure_ns_fallback", test_dns_configure_ns_fallback
,
809 TT_FORK
, NULL
, NULL
},
811 { "clip_ttl", test_dns_clip_ttl
, TT_FORK
, NULL
, NULL
},
812 { "clip_fuzzy_ttl", test_dns_clip_fuzzy_ttl
, TT_FORK
, NULL
, NULL
},
813 { "resolve", test_dns_resolve
, TT_FORK
, NULL
, NULL
},
814 { "impl_addr_is_ip", test_dns_impl_addr_is_ip
, TT_FORK
, NULL
, NULL
},
815 { "impl_non_exit", test_dns_impl_non_exit
, TT_FORK
, NULL
, NULL
},
816 { "impl_addr_is_invalid_dest", test_dns_impl_addr_is_invalid_dest
,
817 TT_FORK
, NULL
, NULL
},
818 { "impl_malformed_ptr", test_dns_impl_malformed_ptr
, TT_FORK
, NULL
, NULL
},
819 { "impl_cache_hit_pending", test_dns_impl_cache_hit_pending
,
820 TT_FORK
, NULL
, NULL
},
821 { "impl_cache_hit_cached", test_dns_impl_cache_hit_cached
,
822 TT_FORK
, NULL
, NULL
},
823 { "impl_cache_miss", test_dns_impl_cache_miss
, TT_FORK
, NULL
, NULL
},