1 /* Copyright (c) 2017-2019, The Tor Project, Inc. */
2 /* Copyright (c) 2017, isis agora lovecruft */
3 /* See LICENSE for licensing information */
7 * \brief Unittests for code in router.c
10 #define CONFIG_PRIVATE
11 #define CONNECTION_PRIVATE
12 #include "core/or/or.h"
13 #include "app/config/config.h"
14 #include "core/mainloop/mainloop.h"
15 #include "core/mainloop/connection.h"
16 #include "feature/hibernate/hibernate.h"
17 #include "feature/nodelist/routerinfo_st.h"
18 #include "feature/nodelist/routerlist.h"
19 #include "feature/relay/router.h"
20 #include "feature/stats/rephist.h"
21 #include "lib/crypt_ops/crypto_curve25519.h"
22 #include "lib/crypt_ops/crypto_ed25519.h"
23 #include "lib/encoding/confline.h"
25 #include "core/or/listener_connection_st.h"
27 /* Test suite stuff */
28 #include "test/test.h"
29 #include "test/log_test_helpers.h"
31 NS_DECL(const routerinfo_t
*, router_get_my_routerinfo
, (void));
33 static routerinfo_t
* mock_routerinfo
;
35 static const routerinfo_t
*
36 NS(router_get_my_routerinfo
)(void)
38 crypto_pk_t
* ident_key
;
42 if (!mock_routerinfo
) {
43 /* Mock the published timestamp, otherwise router_dump_router_to_string()
44 * will poop its pants. */
47 /* We'll need keys, or router_dump_router_to_string() would return NULL. */
48 ident_key
= pk_generate(0);
49 tap_key
= pk_generate(0);
51 tor_assert(ident_key
!= NULL
);
52 tor_assert(tap_key
!= NULL
);
54 mock_routerinfo
= tor_malloc_zero(sizeof(routerinfo_t
));
55 mock_routerinfo
->nickname
= tor_strdup("ConlonNancarrow");
56 mock_routerinfo
->addr
= 123456789;
57 mock_routerinfo
->or_port
= 443;
58 mock_routerinfo
->platform
= tor_strdup("unittest");
59 mock_routerinfo
->cache_info
.published_on
= now
;
60 mock_routerinfo
->identity_pkey
= crypto_pk_dup_key(ident_key
);
61 router_set_rsa_onion_pkey(tap_key
, &mock_routerinfo
->onion_pkey
,
62 &mock_routerinfo
->onion_pkey_len
);
63 mock_routerinfo
->bandwidthrate
= 9001;
64 mock_routerinfo
->bandwidthburst
= 9002;
65 crypto_pk_free(ident_key
);
66 crypto_pk_free(tap_key
);
69 return mock_routerinfo
;
72 /* If no distribution option was set, then check_bridge_distribution_setting()
73 * should have set it to "any". */
75 test_router_dump_router_to_string_no_bridge_distribution_method(void *arg
)
77 const char* needle
= "bridge-distribution-request any";
78 or_options_t
* options
= get_options_mutable();
79 routerinfo_t
* router
= NULL
;
80 curve25519_keypair_t ntor_keypair
;
81 ed25519_keypair_t signing_keypair
;
86 NS_MOCK(router_get_my_routerinfo
);
88 options
->ORPort_set
= 1;
89 options
->BridgeRelay
= 1;
91 /* Generate keys which router_dump_router_to_string() expects to exist. */
92 tt_int_op(0, ==, curve25519_keypair_generate(&ntor_keypair
, 0));
93 tt_int_op(0, ==, ed25519_keypair_generate(&signing_keypair
, 0));
95 /* Set up part of our routerinfo_t so that we don't trigger any other
96 * assertions in router_dump_router_to_string(). */
97 router
= (routerinfo_t
*)router_get_my_routerinfo();
98 tt_ptr_op(router
, !=, NULL
);
100 router
->onion_curve25519_pkey
= &ntor_keypair
.pubkey
;
102 /* Generate our server descriptor and ensure that the substring
103 * "bridge-distribution-request any" occurs somewhere within it. */
104 crypto_pk_t
*onion_pkey
= router_get_rsa_onion_pkey(router
->onion_pkey
,
105 router
->onion_pkey_len
);
106 desc
= router_dump_router_to_string(router
,
107 router
->identity_pkey
,
111 crypto_pk_free(onion_pkey
);
112 tt_ptr_op(desc
, !=, NULL
);
113 found
= strstr(desc
, needle
);
114 tt_ptr_op(found
, !=, NULL
);
117 NS_UNMOCK(router_get_my_routerinfo
);
122 static routerinfo_t
*mock_router_get_my_routerinfo_result
= NULL
;
124 static const routerinfo_t
*
125 mock_router_get_my_routerinfo(void)
127 return mock_router_get_my_routerinfo_result
;
131 mock_get_uptime_3h(void)
137 mock_get_uptime_1d(void)
143 mock_rep_hist_bandwidth_assess(void)
149 mock_we_are_not_hibernating(void)
155 mock_we_are_hibernating(void)
161 test_router_check_descriptor_bandwidth_changed(void *arg
)
164 routerinfo_t routerinfo
;
165 memset(&routerinfo
, 0, sizeof(routerinfo
));
166 mock_router_get_my_routerinfo_result
= NULL
;
168 MOCK(we_are_hibernating
, mock_we_are_not_hibernating
);
169 MOCK(router_get_my_routerinfo
, mock_router_get_my_routerinfo
);
170 mock_router_get_my_routerinfo_result
= &routerinfo
;
172 /* When uptime is less than 24h, no previous bandwidth, no last_changed
173 * Uptime: 10800, last_changed: 0, Previous bw: 0, Current bw: 0 */
174 routerinfo
.bandwidthcapacity
= 0;
175 MOCK(get_uptime
, mock_get_uptime_3h
);
176 setup_full_capture_of_logs(LOG_INFO
);
177 check_descriptor_bandwidth_changed(time(NULL
));
178 expect_log_msg_not_containing(
179 "Measured bandwidth has changed; rebuilding descriptor.");
180 teardown_capture_of_logs();
182 /* When uptime is less than 24h, previous bandwidth,
183 * last_changed more than 3h ago
184 * Uptime: 10800, last_changed: 0, Previous bw: 10000, Current bw: 0 */
185 routerinfo
.bandwidthcapacity
= 10000;
186 setup_full_capture_of_logs(LOG_INFO
);
187 check_descriptor_bandwidth_changed(time(NULL
));
188 expect_log_msg_containing(
189 "Measured bandwidth has changed; rebuilding descriptor.");
190 teardown_capture_of_logs();
192 /* When uptime is less than 24h, previous bandwidth,
193 * last_changed more than 3h ago, and hibernating
194 * Uptime: 10800, last_changed: 0, Previous bw: 10000, Current bw: 0 */
196 UNMOCK(we_are_hibernating
);
197 MOCK(we_are_hibernating
, mock_we_are_hibernating
);
198 routerinfo
.bandwidthcapacity
= 10000;
199 setup_full_capture_of_logs(LOG_INFO
);
200 check_descriptor_bandwidth_changed(time(NULL
));
201 expect_log_msg_not_containing(
202 "Measured bandwidth has changed; rebuilding descriptor.");
203 teardown_capture_of_logs();
204 UNMOCK(we_are_hibernating
);
205 MOCK(we_are_hibernating
, mock_we_are_not_hibernating
);
207 /* When uptime is less than 24h, last_changed is not more than 3h ago
208 * Uptime: 10800, last_changed: x, Previous bw: 10000, Current bw: 0 */
209 setup_full_capture_of_logs(LOG_INFO
);
210 check_descriptor_bandwidth_changed(time(NULL
));
211 expect_log_msg_not_containing(
212 "Measured bandwidth has changed; rebuilding descriptor.");
213 teardown_capture_of_logs();
215 /* When uptime is less than 24h and bandwidthcapacity does not change
216 * Uptime: 10800, last_changed: x, Previous bw: 10000, Current bw: 20001 */
217 MOCK(rep_hist_bandwidth_assess
, mock_rep_hist_bandwidth_assess
);
218 setup_full_capture_of_logs(LOG_INFO
);
219 check_descriptor_bandwidth_changed(time(NULL
) + 6*60*60 + 1);
220 expect_log_msg_containing(
221 "Measured bandwidth has changed; rebuilding descriptor.");
223 UNMOCK(rep_hist_bandwidth_assess
);
224 teardown_capture_of_logs();
226 /* When uptime is more than 24h */
227 MOCK(get_uptime
, mock_get_uptime_1d
);
228 setup_full_capture_of_logs(LOG_INFO
);
229 check_descriptor_bandwidth_changed(time(NULL
));
230 expect_log_msg_not_containing(
231 "Measured bandwidth has changed; rebuilding descriptor.");
232 teardown_capture_of_logs();
236 UNMOCK(router_get_my_routerinfo
);
237 UNMOCK(we_are_hibernating
);
240 static smartlist_t
*fake_connection_array
= NULL
;
242 mock_get_connection_array(void)
244 return fake_connection_array
;
248 test_router_get_advertised_or_port(void *arg
)
253 or_options_t
*opts
= options_new();
254 listener_connection_t
*listener
= NULL
;
255 tor_addr_port_t ipv6
;
257 // Test one failing case of router_get_advertised_ipv6_or_ap().
258 router_get_advertised_ipv6_or_ap(opts
, &ipv6
);
259 tt_str_op(fmt_addrport(&ipv6
.addr
, ipv6
.port
), OP_EQ
, "[::]:0");
261 // And one failing case of router_get_advertised_or_port().
262 tt_int_op(0, OP_EQ
, router_get_advertised_or_port_by_af(opts
, AF_INET
));
263 tt_int_op(0, OP_EQ
, router_get_advertised_or_port(opts
));
265 // Set up a couple of configured ports.
266 config_line_append(&opts
->ORPort_lines
, "ORPort", "[1234::5678]:auto");
267 config_line_append(&opts
->ORPort_lines
, "ORPort", "5.6.7.8:9999");
268 r
= parse_ports(opts
, 0, &msg
, &n
, &w
);
271 // There are no listeners, so the "auto" case will turn up no results.
272 tt_int_op(0, OP_EQ
, router_get_advertised_or_port_by_af(opts
, AF_INET6
));
273 router_get_advertised_ipv6_or_ap(opts
, &ipv6
);
274 tt_str_op(fmt_addrport(&ipv6
.addr
, ipv6
.port
), OP_EQ
, "[::]:0");
276 // This will return the matching value from the configured port.
277 tt_int_op(9999, OP_EQ
, router_get_advertised_or_port_by_af(opts
, AF_INET
));
278 tt_int_op(9999, OP_EQ
, router_get_advertised_or_port(opts
));
280 // Now set up a dummy listener.
281 MOCK(get_connection_array
, mock_get_connection_array
);
282 fake_connection_array
= smartlist_new();
283 listener
= listener_connection_new(CONN_TYPE_OR_LISTENER
, AF_INET6
);
284 TO_CONN(listener
)->port
= 54321;
285 smartlist_add(fake_connection_array
, TO_CONN(listener
));
287 // We should get a port this time.
288 tt_int_op(54321, OP_EQ
, router_get_advertised_or_port_by_af(opts
, AF_INET6
));
290 // Test one succeeding case of router_get_advertised_ipv6_or_ap().
291 router_get_advertised_ipv6_or_ap(opts
, &ipv6
);
292 tt_str_op(fmt_addrport(&ipv6
.addr
, ipv6
.port
), OP_EQ
,
293 "[1234::5678]:54321");
295 // This will return the matching value from the configured port.
296 tt_int_op(9999, OP_EQ
, router_get_advertised_or_port_by_af(opts
, AF_INET
));
297 tt_int_op(9999, OP_EQ
, router_get_advertised_or_port(opts
));
300 or_options_free(opts
);
302 smartlist_free(fake_connection_array
);
303 connection_free_minimal(TO_CONN(listener
));
304 UNMOCK(get_connection_array
);
308 test_router_get_advertised_or_port_localhost(void *arg
)
313 or_options_t
*opts
= options_new();
314 tor_addr_port_t ipv6
;
316 // Set up a couple of configured ports on localhost.
317 config_line_append(&opts
->ORPort_lines
, "ORPort", "[::1]:9999");
318 config_line_append(&opts
->ORPort_lines
, "ORPort", "127.0.0.1:8888");
319 r
= parse_ports(opts
, 0, &msg
, &n
, &w
);
322 // We should refuse to advertise them, since we have default dirauths.
323 router_get_advertised_ipv6_or_ap(opts
, &ipv6
);
324 tt_str_op(fmt_addrport(&ipv6
.addr
, ipv6
.port
), OP_EQ
, "[::]:0");
325 // But the lower-level function should still report the correct value
326 tt_int_op(9999, OP_EQ
, router_get_advertised_or_port_by_af(opts
, AF_INET6
));
328 // The IPv4 checks are done in resolve_my_address(), which doesn't use
329 // ORPorts so we can't test them here. (See #33681.) Both these lower-level
330 // functions should still report the correct value.
331 tt_int_op(8888, OP_EQ
, router_get_advertised_or_port_by_af(opts
, AF_INET
));
332 tt_int_op(8888, OP_EQ
, router_get_advertised_or_port(opts
));
334 // Now try with a fake authority set up.
335 config_line_append(&opts
->DirAuthorities
, "DirAuthority",
337 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
339 tt_int_op(9999, OP_EQ
, router_get_advertised_or_port_by_af(opts
, AF_INET6
));
340 router_get_advertised_ipv6_or_ap(opts
, &ipv6
);
341 tt_str_op(fmt_addrport(&ipv6
.addr
, ipv6
.port
), OP_EQ
, "[::1]:9999");
343 tt_int_op(8888, OP_EQ
, router_get_advertised_or_port_by_af(opts
, AF_INET
));
344 tt_int_op(8888, OP_EQ
, router_get_advertised_or_port(opts
));
347 or_options_free(opts
);
351 #define ROUTER_TEST(name, flags) \
352 { #name, test_router_ ## name, flags, NULL, NULL }
354 struct testcase_t router_tests
[] = {
355 ROUTER_TEST(check_descriptor_bandwidth_changed
, TT_FORK
),
356 ROUTER_TEST(dump_router_to_string_no_bridge_distribution_method
, TT_FORK
),
357 ROUTER_TEST(get_advertised_or_port
, TT_FORK
),
358 ROUTER_TEST(get_advertised_or_port_localhost
, TT_FORK
),