Merge branch 'maint-0.4.8'
[tor.git] / src / test / test_relay.c
blobdbedc021e4feee54c43bb36d78befe4d8c863efe
1 /* Copyright (c) 2014-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 #define CIRCUITBUILD_PRIVATE
5 #define RELAY_PRIVATE
6 #define BWHIST_PRIVATE
7 #include "core/or/or.h"
8 #include "core/or/circuitbuild.h"
9 #include "core/or/circuitlist.h"
10 #include "core/or/channeltls.h"
11 #include "feature/stats/bwhist.h"
12 #include "core/or/relay.h"
13 #include "lib/container/order.h"
14 #include "lib/encoding/confline.h"
15 /* For init/free stuff */
16 #include "core/or/scheduler.h"
18 #include "core/or/cell_st.h"
19 #include "core/or/or_circuit_st.h"
21 #define RESOLVE_ADDR_PRIVATE
22 #include "feature/nodelist/dirlist.h"
23 #include "feature/relay/relay_find_addr.h"
24 #include "feature/relay/routermode.h"
25 #include "feature/dirclient/dir_server_st.h"
27 #define CONFIG_PRIVATE
28 #include "app/config/config.h"
29 #include "app/config/resolve_addr.h"
31 /* Test suite stuff */
32 #include "test/test.h"
33 #include "test/fakechans.h"
34 #include "test/fakecircs.h"
36 static void test_relay_append_cell_to_circuit_queue(void *arg);
38 static int
39 mock_server_mode_true(const or_options_t *options)
41 (void) options;
42 return 1;
45 static void
46 assert_circuit_ok_mock(const circuit_t *c)
48 (void) c;
49 return;
52 static void
53 test_relay_close_circuit(void *arg)
55 channel_t *nchan = NULL, *pchan = NULL;
56 or_circuit_t *orcirc = NULL;
57 cell_t *cell = NULL;
58 int old_count, new_count;
60 (void)arg;
62 /* Make fake channels to be nchan and pchan for the circuit */
63 nchan = new_fake_channel();
64 tt_assert(nchan);
66 pchan = new_fake_channel();
67 tt_assert(pchan);
69 /* Make a fake orcirc */
70 orcirc = new_fake_orcirc(nchan, pchan);
71 tt_assert(orcirc);
72 circuitmux_attach_circuit(nchan->cmux, TO_CIRCUIT(orcirc),
73 CELL_DIRECTION_OUT);
74 circuitmux_attach_circuit(pchan->cmux, TO_CIRCUIT(orcirc),
75 CELL_DIRECTION_IN);
77 /* Make a cell */
78 cell = tor_malloc_zero(sizeof(cell_t));
79 make_fake_cell(cell);
81 MOCK(scheduler_channel_has_waiting_cells,
82 scheduler_channel_has_waiting_cells_mock);
83 MOCK(assert_circuit_ok,
84 assert_circuit_ok_mock);
86 /* Append it */
87 old_count = get_mock_scheduler_has_waiting_cells_count();
88 append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), nchan, cell,
89 CELL_DIRECTION_OUT, 0);
90 new_count = get_mock_scheduler_has_waiting_cells_count();
91 tt_int_op(new_count, OP_EQ, old_count + 1);
93 /* Now try the reverse direction */
94 old_count = get_mock_scheduler_has_waiting_cells_count();
95 append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), pchan, cell,
96 CELL_DIRECTION_IN, 0);
97 new_count = get_mock_scheduler_has_waiting_cells_count();
98 tt_int_op(new_count, OP_EQ, old_count + 1);
100 /* Ensure our write totals are 0 */
101 tt_u64_op(find_largest_max(write_array, 86400), OP_EQ, 0);
103 /* Mark the circuit for close */
104 circuit_mark_for_close(TO_CIRCUIT(orcirc), 0);
106 /* Check our write totals. */
107 advance_obs(write_array);
108 commit_max(write_array);
109 /* Check for two cells plus overhead */
110 tt_u64_op(find_largest_max(write_array, 86400), OP_EQ,
111 2*(get_cell_network_size(nchan->wide_circ_ids)
112 +TLS_PER_CELL_OVERHEAD));
114 UNMOCK(scheduler_channel_has_waiting_cells);
116 /* Get rid of the fake channels */
117 MOCK(scheduler_release_channel, scheduler_release_channel_mock);
118 channel_mark_for_close(nchan);
119 channel_mark_for_close(pchan);
120 UNMOCK(scheduler_release_channel);
122 /* Shut down channels */
123 channel_free_all();
125 done:
126 tor_free(cell);
127 if (orcirc) {
128 circuitmux_detach_circuit(nchan->cmux, TO_CIRCUIT(orcirc));
129 circuitmux_detach_circuit(pchan->cmux, TO_CIRCUIT(orcirc));
130 cell_queue_clear(&orcirc->base_.n_chan_cells);
131 cell_queue_clear(&orcirc->p_chan_cells);
133 free_fake_orcirc(orcirc);
134 free_fake_channel(nchan);
135 free_fake_channel(pchan);
136 UNMOCK(assert_circuit_ok);
138 return;
141 static void
142 test_relay_append_cell_to_circuit_queue(void *arg)
144 channel_t *nchan = NULL, *pchan = NULL;
145 or_circuit_t *orcirc = NULL;
146 cell_t *cell = NULL;
147 int old_count, new_count;
149 (void)arg;
151 /* Make fake channels to be nchan and pchan for the circuit */
152 nchan = new_fake_channel();
153 tt_assert(nchan);
155 pchan = new_fake_channel();
156 tt_assert(pchan);
158 /* Make a fake orcirc */
159 orcirc = new_fake_orcirc(nchan, pchan);
160 tt_assert(orcirc);
161 circuitmux_attach_circuit(nchan->cmux, TO_CIRCUIT(orcirc),
162 CELL_DIRECTION_OUT);
163 circuitmux_attach_circuit(pchan->cmux, TO_CIRCUIT(orcirc),
164 CELL_DIRECTION_IN);
166 /* Make a cell */
167 cell = tor_malloc_zero(sizeof(cell_t));
168 make_fake_cell(cell);
170 MOCK(scheduler_channel_has_waiting_cells,
171 scheduler_channel_has_waiting_cells_mock);
173 /* Append it */
174 old_count = get_mock_scheduler_has_waiting_cells_count();
175 append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), nchan, cell,
176 CELL_DIRECTION_OUT, 0);
177 new_count = get_mock_scheduler_has_waiting_cells_count();
178 tt_int_op(new_count, OP_EQ, old_count + 1);
180 /* Now try the reverse direction */
181 old_count = get_mock_scheduler_has_waiting_cells_count();
182 append_cell_to_circuit_queue(TO_CIRCUIT(orcirc), pchan, cell,
183 CELL_DIRECTION_IN, 0);
184 new_count = get_mock_scheduler_has_waiting_cells_count();
185 tt_int_op(new_count, OP_EQ, old_count + 1);
187 UNMOCK(scheduler_channel_has_waiting_cells);
189 /* Get rid of the fake channels */
190 MOCK(scheduler_release_channel, scheduler_release_channel_mock);
191 channel_mark_for_close(nchan);
192 channel_mark_for_close(pchan);
193 UNMOCK(scheduler_release_channel);
195 /* Shut down channels */
196 channel_free_all();
198 done:
199 tor_free(cell);
200 if (orcirc) {
201 circuitmux_detach_circuit(nchan->cmux, TO_CIRCUIT(orcirc));
202 circuitmux_detach_circuit(pchan->cmux, TO_CIRCUIT(orcirc));
203 cell_queue_clear(&orcirc->base_.n_chan_cells);
204 cell_queue_clear(&orcirc->p_chan_cells);
206 free_fake_orcirc(orcirc);
207 free_fake_channel(nchan);
208 free_fake_channel(pchan);
210 return;
213 static void
214 test_suggested_address(void *arg)
216 int ret;
217 const char *untrusted_id = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
218 dir_server_t *ds = NULL;
219 tor_addr_t ipv4_addr, ipv6_addr, cache_addr;
220 tor_addr_t trusted_addr, untrusted_addr;
221 tor_addr_port_t trusted_ap_v6 = { .port = 443 };
223 (void) arg;
225 MOCK(server_mode, mock_server_mode_true);
227 /* Unstrusted relay source. */
228 ret = tor_addr_parse(&untrusted_addr, "8.8.8.8");
229 tt_int_op(ret, OP_EQ, AF_INET);
231 /* Add gabelmoo as a trusted directory authority. */
232 ret = tor_addr_parse(&trusted_addr, "[2001:638:a000:4140::ffff:189]");
233 tt_int_op(ret, OP_EQ, AF_INET6);
234 tor_addr_copy(&trusted_ap_v6.addr, &trusted_addr);
236 ds = trusted_dir_server_new("gabelmoo", "131.188.40.189", 80, 443,
237 &trusted_ap_v6,
238 "F2044413DAC2E02E3D6BCF4735A19BCA1DE97281",
239 "ED03BB616EB2F60BEC80151114BB25CEF515B226",
240 V3_DIRINFO, 1.0);
241 tt_assert(ds);
242 dir_server_add(ds);
244 /* 1. Valid IPv4 from a trusted authority (gabelmoo). */
245 ret = tor_addr_parse(&ipv4_addr, "1.2.3.4");
246 relay_address_new_suggestion(&ipv4_addr, &ds->ipv4_addr, ds->digest);
247 resolved_addr_get_suggested(AF_INET, &cache_addr);
248 tt_assert(tor_addr_eq(&cache_addr, &ipv4_addr));
249 resolve_addr_reset_suggested(AF_INET);
251 /* 2. Valid IPv6 from a trusted authority (gabelmoo). */
252 ret = tor_addr_parse(&ipv6_addr, "[4242::4242]");
253 relay_address_new_suggestion(&ipv6_addr, &ds->ipv6_addr, ds->digest);
254 resolved_addr_get_suggested(AF_INET6, &cache_addr);
255 tt_assert(tor_addr_eq(&cache_addr, &ipv6_addr));
256 resolve_addr_reset_suggested(AF_INET6);
258 /* 3. Valid IPv4 but untrusted source. */
259 ret = tor_addr_parse(&ipv4_addr, "1.2.3.4");
260 relay_address_new_suggestion(&ipv4_addr, &untrusted_addr, untrusted_id);
261 resolved_addr_get_suggested(AF_INET, &cache_addr);
262 tt_assert(tor_addr_is_unspec(&cache_addr));
264 /* 4. Valid IPv6 but untrusted source. */
265 ret = tor_addr_parse(&ipv6_addr, "[4242::4242]");
266 relay_address_new_suggestion(&ipv6_addr, &untrusted_addr, untrusted_id);
267 resolved_addr_get_suggested(AF_INET6, &cache_addr);
268 tt_assert(tor_addr_is_unspec(&cache_addr));
270 /* 5. Internal IPv4 from a trusted authority (gabelmoo). */
271 ret = tor_addr_parse(&ipv4_addr, "127.0.0.1");
272 relay_address_new_suggestion(&ipv4_addr, &ds->ipv4_addr, ds->digest);
273 resolved_addr_get_suggested(AF_INET, &cache_addr);
274 tt_assert(tor_addr_is_unspec(&cache_addr));
276 /* 6. Internal IPv6 from a trusted authority (gabelmoo). */
277 ret = tor_addr_parse(&ipv6_addr, "[::1]");
278 relay_address_new_suggestion(&ipv6_addr, &ds->ipv6_addr, ds->digest);
279 resolved_addr_get_suggested(AF_INET6, &cache_addr);
280 tt_assert(tor_addr_is_unspec(&cache_addr));
282 /* 7. IPv4 from a trusted authority (gabelmoo). */
283 relay_address_new_suggestion(&ds->ipv4_addr, &ds->ipv4_addr, ds->digest);
284 resolved_addr_get_suggested(AF_INET, &cache_addr);
285 tt_assert(tor_addr_is_unspec(&cache_addr));
287 /* 8. IPv6 from a trusted authority (gabelmoo). */
288 relay_address_new_suggestion(&ds->ipv6_addr, &ds->ipv6_addr, ds->digest);
289 resolved_addr_get_suggested(AF_INET6, &cache_addr);
290 tt_assert(tor_addr_is_unspec(&cache_addr));
292 done:
293 dirlist_free_all();
295 UNMOCK(server_mode);
298 static void
299 test_find_addr_to_publish(void *arg)
301 int family;
302 bool ret;
303 tor_addr_t ipv4_addr, ipv6_addr, cache_addr;
304 or_options_t *options;
306 (void) arg;
308 options = options_new();
309 options_init(options);
311 /* Populate our resolved cache with a valid IPv4 and IPv6. */
312 family = tor_addr_parse(&ipv4_addr, "1.2.3.4");
313 tt_int_op(family, OP_EQ, AF_INET);
314 resolved_addr_set_last(&ipv4_addr, RESOLVED_ADDR_CONFIGURED, NULL);
315 resolved_addr_get_last(AF_INET, &cache_addr);
316 tt_assert(tor_addr_eq(&ipv4_addr, &cache_addr));
318 family = tor_addr_parse(&ipv6_addr, "[4242::4242]");
319 tt_int_op(family, OP_EQ, AF_INET6);
320 resolved_addr_set_last(&ipv6_addr, RESOLVED_ADDR_CONFIGURED, NULL);
321 resolved_addr_get_last(AF_INET6, &cache_addr);
322 tt_assert(tor_addr_eq(&ipv6_addr, &cache_addr));
324 /* Setup ORPort config. */
326 int n, w, r;
327 char *msg = NULL;
329 config_line_append(&options->ORPort_lines, "ORPort", "9001");
331 r = parse_ports(options, 0, &msg, &n, &w);
332 tt_int_op(r, OP_EQ, 0);
335 /* 1. Address located in the resolved cache. */
336 ret = relay_find_addr_to_publish(options, AF_INET,
337 RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
338 tt_assert(ret);
339 tt_assert(tor_addr_eq(&ipv4_addr, &cache_addr));
341 ret = relay_find_addr_to_publish(options, AF_INET6,
342 RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
343 tt_assert(ret);
344 tt_assert(tor_addr_eq(&ipv6_addr, &cache_addr));
345 resolved_addr_reset_last(AF_INET);
346 resolved_addr_reset_last(AF_INET6);
348 /* 2. No IP in the resolve cache, go to the suggested cache. We will ignore
349 * the find_my_address() code path because that is extensively tested in
350 * another unit tests. */
351 resolved_addr_set_suggested(&ipv4_addr);
352 ret = relay_find_addr_to_publish(options, AF_INET,
353 RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
354 tt_assert(ret);
355 tt_assert(tor_addr_eq(&ipv4_addr, &cache_addr));
357 resolved_addr_set_suggested(&ipv6_addr);
358 ret = relay_find_addr_to_publish(options, AF_INET6,
359 RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
360 tt_assert(ret);
361 tt_assert(tor_addr_eq(&ipv6_addr, &cache_addr));
362 resolve_addr_reset_suggested(AF_INET);
363 resolve_addr_reset_suggested(AF_INET6);
365 /* 3. No IP anywhere. */
366 ret = relay_find_addr_to_publish(options, AF_INET,
367 RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
368 tt_assert(!ret);
369 ret = relay_find_addr_to_publish(options, AF_INET6,
370 RELAY_FIND_ADDR_CACHE_ONLY, &cache_addr);
371 tt_assert(!ret);
373 done:
374 or_options_free(options);
377 struct testcase_t relay_tests[] = {
378 { "append_cell_to_circuit_queue", test_relay_append_cell_to_circuit_queue,
379 TT_FORK, NULL, NULL },
380 { "close_circ_rephist", test_relay_close_circuit,
381 TT_FORK, NULL, NULL },
382 { "suggested_address", test_suggested_address,
383 TT_FORK, NULL, NULL },
384 { "find_addr_to_publish", test_find_addr_to_publish,
385 TT_FORK, NULL, NULL },
387 END_OF_TESTCASES