test_relay.c (12475B)
1 /* Copyright (c) 2014-2021, The Tor Project, Inc. */ 2 /* See LICENSE for licensing information */ 3 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" 17 18 #include "core/or/cell_st.h" 19 #include "core/or/or_circuit_st.h" 20 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" 26 27 #define CONFIG_PRIVATE 28 #include "app/config/config.h" 29 #include "app/config/resolve_addr.h" 30 31 /* Test suite stuff */ 32 #include "test/test.h" 33 #include "test/fakechans.h" 34 #include "test/fakecircs.h" 35 36 static void test_relay_append_cell_to_circuit_queue(void *arg); 37 38 static int 39 mock_server_mode_true(const or_options_t *options) 40 { 41 (void) options; 42 return 1; 43 } 44 45 static void 46 assert_circuit_ok_mock(const circuit_t *c) 47 { 48 (void) c; 49 return; 50 } 51 52 static void 53 test_relay_close_circuit(void *arg) 54 { 55 channel_t *nchan = NULL, *pchan = NULL; 56 or_circuit_t *orcirc = NULL; 57 cell_t *cell = NULL; 58 int old_count, new_count; 59 60 (void)arg; 61 62 /* Make fake channels to be nchan and pchan for the circuit */ 63 nchan = new_fake_channel(); 64 tt_assert(nchan); 65 66 pchan = new_fake_channel(); 67 tt_assert(pchan); 68 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); 76 77 /* Make a cell */ 78 cell = tor_malloc_zero(sizeof(cell_t)); 79 make_fake_cell(cell); 80 81 MOCK(scheduler_channel_has_waiting_cells, 82 scheduler_channel_has_waiting_cells_mock); 83 MOCK(assert_circuit_ok, 84 assert_circuit_ok_mock); 85 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); 92 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); 99 100 /* Ensure our write totals are 0 */ 101 tt_u64_op(find_largest_max(write_array, 86400), OP_EQ, 0); 102 103 /* Mark the circuit for close */ 104 circuit_mark_for_close(TO_CIRCUIT(orcirc), 0); 105 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)); 113 114 UNMOCK(scheduler_channel_has_waiting_cells); 115 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); 121 122 /* Shut down channels */ 123 channel_free_all(); 124 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); 132 } 133 free_fake_orcirc(orcirc); 134 free_fake_channel(nchan); 135 free_fake_channel(pchan); 136 UNMOCK(assert_circuit_ok); 137 138 return; 139 } 140 141 static void 142 test_relay_append_cell_to_circuit_queue(void *arg) 143 { 144 channel_t *nchan = NULL, *pchan = NULL; 145 or_circuit_t *orcirc = NULL; 146 cell_t *cell = NULL; 147 int old_count, new_count; 148 149 (void)arg; 150 151 /* Make fake channels to be nchan and pchan for the circuit */ 152 nchan = new_fake_channel(); 153 tt_assert(nchan); 154 155 pchan = new_fake_channel(); 156 tt_assert(pchan); 157 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); 165 166 /* Make a cell */ 167 cell = tor_malloc_zero(sizeof(cell_t)); 168 make_fake_cell(cell); 169 170 MOCK(scheduler_channel_has_waiting_cells, 171 scheduler_channel_has_waiting_cells_mock); 172 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); 179 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); 186 187 UNMOCK(scheduler_channel_has_waiting_cells); 188 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); 194 195 /* Shut down channels */ 196 channel_free_all(); 197 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); 205 } 206 free_fake_orcirc(orcirc); 207 free_fake_channel(nchan); 208 free_fake_channel(pchan); 209 210 return; 211 } 212 213 static void 214 test_suggested_address(void *arg) 215 { 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 }; 222 223 (void) arg; 224 225 MOCK(server_mode, mock_server_mode_true); 226 227 /* Unstrusted relay source. */ 228 ret = tor_addr_parse(&untrusted_addr, "8.8.8.8"); 229 tt_int_op(ret, OP_EQ, AF_INET); 230 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); 235 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); 243 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); 250 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); 257 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)); 263 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)); 269 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)); 275 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)); 281 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)); 286 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)); 291 292 done: 293 dirlist_free_all(); 294 295 UNMOCK(server_mode); 296 } 297 298 static void 299 test_find_addr_to_publish(void *arg) 300 { 301 int family; 302 bool ret; 303 tor_addr_t ipv4_addr, ipv6_addr, cache_addr; 304 or_options_t *options; 305 306 (void) arg; 307 308 options = options_new(); 309 options_init(options); 310 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)); 317 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)); 323 324 /* Setup ORPort config. */ 325 { 326 int n, w, r; 327 char *msg = NULL; 328 329 config_line_append(&options->ORPort_lines, "ORPort", "9001"); 330 331 r = parse_ports(options, 0, &msg, &n, &w); 332 tt_int_op(r, OP_EQ, 0); 333 } 334 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)); 340 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); 347 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)); 356 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); 364 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); 372 373 done: 374 or_options_free(options); 375 } 376 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 }, 386 387 END_OF_TESTCASES 388 };