7 #include "connection.h"
10 test_dns_clip_ttl(void *arg
)
14 uint32_t ttl_mid
= MIN_DNS_TTL
/ 2 + MAX_DNS_TTL
/ 2;
16 tt_int_op(dns_clip_ttl(MIN_DNS_TTL
- 1),==,MIN_DNS_TTL
);
17 tt_int_op(dns_clip_ttl(ttl_mid
),==,ttl_mid
);
18 tt_int_op(dns_clip_ttl(MAX_DNS_TTL
+ 1),==,MAX_DNS_TTL
);
25 test_dns_expiry_ttl(void *arg
)
29 uint32_t ttl_mid
= MIN_DNS_TTL
/ 2 + MAX_DNS_ENTRY_AGE
/ 2;
31 tt_int_op(dns_get_expiry_ttl(MIN_DNS_TTL
- 1),==,MIN_DNS_TTL
);
32 tt_int_op(dns_get_expiry_ttl(ttl_mid
),==,ttl_mid
);
33 tt_int_op(dns_get_expiry_ttl(MAX_DNS_ENTRY_AGE
+ 1),==,MAX_DNS_ENTRY_AGE
);
39 static int resolve_retval
= 0;
40 static int resolve_made_conn_pending
= 0;
41 static char *resolved_name
= NULL
;
42 static cached_resolve_t
*cache_entry
= NULL
;
44 static int n_fake_impl
= 0;
46 /** This will be our configurable substitute for <b>dns_resolve_impl</b> in
47 * dns.c. It will return <b>resolve_retval</b>,
48 * and set <b>resolve_made_conn_pending</b> to
49 * <b>made_connection_pending_out</b>. It will set <b>hostname_out</b>
50 * to a duplicate of <b>resolved_name</b> and it will set <b>resolve_out</b>
51 * to <b>cache_entry</b>. Lastly, it will increment <b>n_fake_impl</b< by
55 dns_resolve_fake_impl(edge_connection_t
*exitconn
, int is_resolve
,
56 or_circuit_t
*oncirc
, char **hostname_out
,
57 int *made_connection_pending_out
,
58 cached_resolve_t
**resolve_out
)
64 if (made_connection_pending_out
)
65 *made_connection_pending_out
= resolve_made_conn_pending
;
67 if (hostname_out
&& resolved_name
)
68 *hostname_out
= tor_strdup(resolved_name
);
70 if (resolve_out
&& cache_entry
)
71 *resolve_out
= cache_entry
;
75 return resolve_retval
;
78 static edge_connection_t
*conn_for_resolved_cell
= NULL
;
80 static int n_send_resolved_cell_replacement
= 0;
81 static uint8_t last_answer_type
= 0;
82 static cached_resolve_t
*last_resolved
;
85 send_resolved_cell_replacement(edge_connection_t
*conn
, uint8_t answer_type
,
86 const cached_resolve_t
*resolved
)
88 conn_for_resolved_cell
= conn
;
90 last_answer_type
= answer_type
;
91 last_resolved
= (cached_resolve_t
*)resolved
;
93 n_send_resolved_cell_replacement
++;
96 static int n_send_resolved_hostname_cell_replacement
= 0;
98 static char *last_resolved_hostname
= NULL
;
101 send_resolved_hostname_cell_replacement(edge_connection_t
*conn
,
102 const char *hostname
)
104 conn_for_resolved_cell
= conn
;
106 tor_free(last_resolved_hostname
);
107 last_resolved_hostname
= tor_strdup(hostname
);
109 n_send_resolved_hostname_cell_replacement
++;
112 static int n_dns_cancel_pending_resolve_replacement
= 0;
115 dns_cancel_pending_resolve_replacement(const char *address
)
118 n_dns_cancel_pending_resolve_replacement
++;
121 static int n_connection_free
= 0;
122 static connection_t
*last_freed_conn
= NULL
;
125 connection_free_replacement(connection_t
*conn
)
129 last_freed_conn
= conn
;
133 test_dns_resolve_outer(void *arg
)
137 int prev_n_send_resolved_hostname_cell_replacement
;
138 int prev_n_send_resolved_cell_replacement
;
139 int prev_n_connection_free
;
140 cached_resolve_t
*fake_resolved
= tor_malloc(sizeof(cached_resolve_t
));
141 edge_connection_t
*exitconn
= tor_malloc(sizeof(edge_connection_t
));
142 edge_connection_t
*nextconn
= tor_malloc(sizeof(edge_connection_t
));
144 or_circuit_t
*on_circuit
= tor_malloc(sizeof(or_circuit_t
));
145 memset(on_circuit
,0,sizeof(or_circuit_t
));
146 on_circuit
->base_
.magic
= OR_CIRCUIT_MAGIC
;
148 memset(fake_resolved
,0,sizeof(cached_resolve_t
));
149 memset(exitconn
,0,sizeof(edge_connection_t
));
150 memset(nextconn
,0,sizeof(edge_connection_t
));
152 MOCK(dns_resolve_impl
,dns_resolve_fake_impl
);
153 MOCK(send_resolved_cell
,send_resolved_cell_replacement
);
154 MOCK(send_resolved_hostname_cell
,send_resolved_hostname_cell_replacement
);
157 * CASE 1: dns_resolve_impl returns 1 and sets a hostname. purpose is
158 * EXIT_PURPOSE_RESOLVE.
160 * We want dns_resolve() to call send_resolved_hostname_cell() for a
161 * given exit connection (represented by edge_connection_t object)
162 * with a hostname it received from _impl.
165 prev_n_send_resolved_hostname_cell_replacement
=
166 n_send_resolved_hostname_cell_replacement
;
168 exitconn
->base_
.purpose
= EXIT_PURPOSE_RESOLVE
;
169 exitconn
->on_circuit
= &(on_circuit
->base_
);
172 resolved_name
= tor_strdup("www.torproject.org");
174 retval
= dns_resolve(exitconn
);
176 tt_int_op(retval
,==,1);
177 tt_str_op(resolved_name
,==,last_resolved_hostname
);
178 tt_assert(conn_for_resolved_cell
== exitconn
);
179 tt_int_op(n_send_resolved_hostname_cell_replacement
,==,
180 prev_n_send_resolved_hostname_cell_replacement
+ 1);
181 tt_assert(exitconn
->on_circuit
== NULL
);
183 tor_free(last_resolved_hostname
);
184 // implies last_resolved_hostname = NULL;
186 /* CASE 2: dns_resolve_impl returns 1, but does not set hostname.
187 * Instead, it yields cached_resolve_t object.
189 * We want dns_resolve to call send_resolved_cell on exitconn with
190 * RESOLVED_TYPE_AUTO and the cached_resolve_t object from _impl.
193 tor_free(resolved_name
);
194 resolved_name
= NULL
;
196 exitconn
->on_circuit
= &(on_circuit
->base_
);
198 cache_entry
= fake_resolved
;
200 prev_n_send_resolved_cell_replacement
=
201 n_send_resolved_cell_replacement
;
203 retval
= dns_resolve(exitconn
);
205 tt_int_op(retval
,==,1);
206 tt_assert(conn_for_resolved_cell
== exitconn
);
207 tt_int_op(n_send_resolved_cell_replacement
,==,
208 prev_n_send_resolved_cell_replacement
+ 1);
209 tt_assert(last_resolved
== fake_resolved
);
210 tt_int_op(last_answer_type
,==,0xff);
211 tt_assert(exitconn
->on_circuit
== NULL
);
213 /* CASE 3: The purpose of exit connection is not EXIT_PURPOSE_RESOLVE
214 * and _impl returns 1.
216 * We want dns_resolve to prepend exitconn to n_streams linked list.
217 * We don't want it to send any cells about hostname being resolved.
220 exitconn
->base_
.purpose
= EXIT_PURPOSE_CONNECT
;
221 exitconn
->on_circuit
= &(on_circuit
->base_
);
223 on_circuit
->n_streams
= nextconn
;
225 prev_n_send_resolved_cell_replacement
=
226 n_send_resolved_cell_replacement
;
228 prev_n_send_resolved_hostname_cell_replacement
=
229 n_send_resolved_hostname_cell_replacement
;
231 retval
= dns_resolve(exitconn
);
233 tt_int_op(retval
,==,1);
234 tt_assert(on_circuit
->n_streams
== exitconn
);
235 tt_assert(exitconn
->next_stream
== nextconn
);
236 tt_int_op(prev_n_send_resolved_cell_replacement
,==,
237 n_send_resolved_cell_replacement
);
238 tt_int_op(prev_n_send_resolved_hostname_cell_replacement
,==,
239 n_send_resolved_hostname_cell_replacement
);
241 /* CASE 4: _impl returns 0.
243 * We want dns_resolve() to set exitconn state to
244 * EXIT_CONN_STATE_RESOLVING and prepend exitconn to resolving_streams
248 exitconn
->on_circuit
= &(on_circuit
->base_
);
252 exitconn
->next_stream
= NULL
;
253 on_circuit
->resolving_streams
= nextconn
;
255 retval
= dns_resolve(exitconn
);
257 tt_int_op(retval
,==,0);
258 tt_int_op(exitconn
->base_
.state
,==,EXIT_CONN_STATE_RESOLVING
);
259 tt_assert(on_circuit
->resolving_streams
== exitconn
);
260 tt_assert(exitconn
->next_stream
== nextconn
);
262 /* CASE 5: _impl returns -1 when purpose of exitconn is
263 * EXIT_PURPOSE_RESOLVE. We want dns_resolve to call send_resolved_cell
264 * on exitconn with type being RESOLVED_TYPE_ERROR.
267 MOCK(dns_cancel_pending_resolve
,dns_cancel_pending_resolve_replacement
);
268 MOCK(connection_free
,connection_free_replacement
);
270 exitconn
->on_circuit
= &(on_circuit
->base_
);
271 exitconn
->base_
.purpose
= EXIT_PURPOSE_RESOLVE
;
275 prev_n_send_resolved_cell_replacement
=
276 n_send_resolved_cell_replacement
;
278 prev_n_connection_free
= n_connection_free
;
280 retval
= dns_resolve(exitconn
);
282 tt_int_op(retval
,==,-1);
283 tt_int_op(n_send_resolved_cell_replacement
,==,
284 prev_n_send_resolved_cell_replacement
+ 1);
285 tt_int_op(last_answer_type
,==,RESOLVED_TYPE_ERROR
);
286 tt_int_op(n_dns_cancel_pending_resolve_replacement
,==,1);
287 tt_int_op(n_connection_free
,==,prev_n_connection_free
+ 1);
288 tt_assert(last_freed_conn
== TO_CONN(exitconn
));
291 UNMOCK(dns_resolve_impl
);
292 UNMOCK(send_resolved_cell
);
293 UNMOCK(send_resolved_hostname_cell
);
294 UNMOCK(dns_cancel_pending_resolve
);
295 UNMOCK(connection_free
);
296 tor_free(on_circuit
);
299 tor_free(resolved_name
);
300 tor_free(fake_resolved
);
301 tor_free(last_resolved_hostname
);
305 struct testcase_t dns_tests
[] = {
306 { "clip_ttl", test_dns_clip_ttl
, 0, NULL
, NULL
},
307 { "expiry_ttl", test_dns_expiry_ttl
, 0, NULL
, NULL
},
308 { "resolve_outer", test_dns_resolve_outer
, TT_FORK
, NULL
, NULL
},