1 /* Copyright (c) 2014-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
4 /* Unit tests for handling different kinds of relay cell */
7 #define CIRCUITLIST_PRIVATE
8 #define CONNECTION_EDGE_PRIVATE
9 #define CONNECTION_PRIVATE
11 #include "core/or/or.h"
12 #include "core/mainloop/mainloop.h"
13 #include "app/config/config.h"
14 #include "core/mainloop/connection.h"
15 #include "lib/crypt_ops/crypto_cipher.h"
16 #include "lib/crypt_ops/crypto_rand.h"
17 #include "core/or/circuitbuild.h"
18 #include "core/or/circuitlist.h"
19 #include "core/or/connection_edge.h"
20 #include "core/or/sendme.h"
21 #include "core/or/relay.h"
22 #include "test/test.h"
23 #include "test/log_test_helpers.h"
25 #include "core/or/cell_st.h"
26 #include "core/or/crypt_path_st.h"
27 #include "core/or/entry_connection_st.h"
28 #include "core/or/origin_circuit_st.h"
29 #include "core/or/socks_request_st.h"
30 #include "core/or/half_edge_st.h"
32 #include "feature/client/circpathbias.h"
34 static int srm_ncalls
;
35 static entry_connection_t
*srm_conn
;
37 static size_t srm_alen
;
38 static int srm_answer_is_set
;
39 static uint8_t srm_answer
[512];
41 static time_t srm_expires
;
43 /* Mock replacement for connection_ap_hannshake_socks_resolved() */
45 socks_resolved_mock(entry_connection_t
*conn
,
48 const uint8_t *answer
,
54 srm_atype
= answer_type
;
55 srm_alen
= answer_len
;
57 memset(srm_answer
, 0, sizeof(srm_answer
));
58 memcpy(srm_answer
, answer
, answer_len
< 512 ? answer_len
: 512);
59 srm_answer_is_set
= 1;
61 srm_answer_is_set
= 0;
64 srm_expires
= expires
;
67 static int mum_ncalls
;
68 static entry_connection_t
*mum_conn
;
69 static int mum_endreason
;
71 /* Mock replacement for connection_mark_unattached_ap_() */
73 mark_unattached_mock(entry_connection_t
*conn
, int endreason
,
74 int line
, const char *file
)
78 mum_endreason
= endreason
;
83 /* Helper: Return a newly allocated and initialized origin circuit with
84 * purpose and flags. A default HS identifier is set to an ed25519
85 * authentication key for introduction point. */
86 static origin_circuit_t
*
87 helper_create_origin_circuit(int purpose
, int flags
)
89 origin_circuit_t
*circ
= NULL
;
91 circ
= origin_circuit_init(purpose
, flags
);
93 circ
->cpath
= tor_malloc_zero(sizeof(crypt_path_t
));
94 circ
->cpath
->magic
= CRYPT_PATH_MAGIC
;
95 circ
->cpath
->state
= CPATH_STATE_OPEN
;
96 circ
->cpath
->package_window
= circuit_initial_package_window();
97 circ
->cpath
->deliver_window
= CIRCWINDOW_START
;
98 circ
->cpath
->prev
= circ
->cpath
;
99 /* Create a default HS identifier. */
100 circ
->hs_ident
= tor_malloc_zero(sizeof(hs_ident_circuit_t
));
106 mock_connection_mark_unattached_ap_(entry_connection_t
*conn
, int endreason
,
107 int line
, const char *file
)
111 conn
->edge_
.end_reason
= endreason
;
115 mock_mark_circ_for_close(circuit_t
*circ
, int reason
, int line
,
118 (void)reason
; (void)line
; (void)file
;
120 circ
->marked_for_close
= 1;
125 mock_mark_for_close(connection_t
*conn
,
126 int line
, const char *file
)
131 conn
->marked_for_close
= 1;
136 mock_start_reading(connection_t
*conn
)
143 mock_send_command(streamid_t stream_id
, circuit_t
*circ
,
144 uint8_t relay_command
, const char *payload
,
145 size_t payload_len
, crypt_path_t
*cpath_layer
,
146 const char *filename
, int lineno
)
148 (void)stream_id
; (void)circ
;
149 (void)relay_command
; (void)payload
;
150 (void)payload_len
; (void)cpath_layer
;
151 (void)filename
; (void)lineno
;
156 static entry_connection_t
*
157 fake_entry_conn(origin_circuit_t
*oncirc
, streamid_t id
)
159 edge_connection_t
*edgeconn
;
160 entry_connection_t
*entryconn
;
162 entryconn
= entry_connection_new(CONN_TYPE_AP
, AF_INET
);
163 edgeconn
= ENTRY_TO_EDGE_CONN(entryconn
);
164 edgeconn
->base_
.state
= AP_CONN_STATE_CONNECT_WAIT
;
165 edgeconn
->deliver_window
= STREAMWINDOW_START
;
166 edgeconn
->package_window
= STREAMWINDOW_START
;
168 edgeconn
->stream_id
= id
;
169 edgeconn
->on_circuit
= TO_CIRCUIT(oncirc
);
170 edgeconn
->cpath_layer
= oncirc
->cpath
;
175 #define PACK_CELL(id, cmd, body_s) do { \
176 memset(&cell, 0, sizeof(cell)); \
177 memset(&rh, 0, sizeof(rh)); \
178 memcpy(cell.payload+RELAY_HEADER_SIZE, (body_s), sizeof((body_s))-1); \
179 rh.length = sizeof((body_s))-1; \
180 rh.command = (cmd); \
181 rh.stream_id = (id); \
182 relay_header_pack((uint8_t*)&cell.payload, &rh); \
184 #define ASSERT_COUNTED_BW() do { \
185 tt_int_op(circ->n_delivered_read_circ_bw, OP_EQ, delivered+rh.length); \
186 tt_int_op(circ->n_overhead_read_circ_bw, OP_EQ, \
187 overhead+RELAY_PAYLOAD_SIZE-rh.length); \
188 delivered = circ->n_delivered_read_circ_bw; \
189 overhead = circ->n_overhead_read_circ_bw; \
191 #define ASSERT_UNCOUNTED_BW() do { \
192 tt_int_op(circ->n_delivered_read_circ_bw, OP_EQ, delivered); \
193 tt_int_op(circ->n_overhead_read_circ_bw, OP_EQ, overhead); \
197 subtest_circbw_halfclosed(origin_circuit_t
*circ
, streamid_t init_id
)
201 edge_connection_t
*edgeconn
;
202 entry_connection_t
*entryconn2
=NULL
;
203 entry_connection_t
*entryconn3
=NULL
;
204 entry_connection_t
*entryconn4
=NULL
;
205 int delivered
= circ
->n_delivered_read_circ_bw
;
206 int overhead
= circ
->n_overhead_read_circ_bw
;
208 /* Make new entryconns */
209 entryconn2
= fake_entry_conn(circ
, init_id
);
210 entryconn2
->socks_request
->has_finished
= 1;
211 entryconn3
= fake_entry_conn(circ
, init_id
+1);
212 entryconn3
->socks_request
->has_finished
= 1;
213 entryconn4
= fake_entry_conn(circ
, init_id
+2);
214 entryconn4
->socks_request
->has_finished
= 1;
215 edgeconn
= ENTRY_TO_EDGE_CONN(entryconn2
);
216 edgeconn
->package_window
= 23;
217 edgeconn
->base_
.state
= AP_CONN_STATE_OPEN
;
219 int data_cells
= edgeconn
->deliver_window
;
220 int sendme_cells
= (STREAMWINDOW_START
-edgeconn
->package_window
)
221 /STREAMWINDOW_INCREMENT
;
222 ENTRY_TO_CONN(entryconn2
)->marked_for_close
= 0;
223 connection_edge_reached_eof(edgeconn
);
225 /* Data cell not in the half-opened list */
226 PACK_CELL(4000, RELAY_COMMAND_DATA
, "Data1234");
227 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
228 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
230 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
232 ASSERT_UNCOUNTED_BW();
234 /* Sendme cell not in the half-opened list */
235 PACK_CELL(4000, RELAY_COMMAND_SENDME
, "Data1234");
236 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
237 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
239 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
241 ASSERT_UNCOUNTED_BW();
243 /* Connected cell not in the half-opened list */
244 PACK_CELL(4000, RELAY_COMMAND_CONNECTED
, "Data1234");
245 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
246 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
248 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
250 ASSERT_UNCOUNTED_BW();
252 /* Resolved cell not in the half-opened list */
253 PACK_CELL(4000, RELAY_COMMAND_RESOLVED
, "Data1234");
254 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
255 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
257 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
259 ASSERT_UNCOUNTED_BW();
261 /* Connected cell: not counted -- we were open */
262 edgeconn
= ENTRY_TO_EDGE_CONN(entryconn2
);
263 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_CONNECTED
, "Data1234");
264 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
265 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
267 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
269 ASSERT_UNCOUNTED_BW();
271 /* DATA cells up to limit */
272 while (data_cells
> 0) {
273 ENTRY_TO_CONN(entryconn2
)->marked_for_close
= 0;
274 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_DATA
, "Data1234");
275 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
276 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
278 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
283 ENTRY_TO_CONN(entryconn2
)->marked_for_close
= 0;
284 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_DATA
, "Data1234");
285 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
286 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
288 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
290 ASSERT_UNCOUNTED_BW();
292 /* SENDME cells up to limit */
293 while (sendme_cells
> 0) {
294 ENTRY_TO_CONN(entryconn2
)->marked_for_close
= 0;
295 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_SENDME
, "Data1234");
296 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
297 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
299 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
304 ENTRY_TO_CONN(entryconn2
)->marked_for_close
= 0;
305 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_SENDME
, "Data1234");
306 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
307 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
309 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
311 ASSERT_UNCOUNTED_BW();
313 /* Only one END cell */
314 ENTRY_TO_CONN(entryconn2
)->marked_for_close
= 0;
315 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_END
, "Data1234");
316 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
317 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
319 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
323 ENTRY_TO_CONN(entryconn2
)->marked_for_close
= 0;
324 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_END
, "Data1234");
325 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
326 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
328 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
330 ASSERT_UNCOUNTED_BW();
332 edgeconn
= ENTRY_TO_EDGE_CONN(entryconn3
);
333 edgeconn
->base_
.state
= AP_CONN_STATE_OPEN
;
334 ENTRY_TO_CONN(entryconn3
)->marked_for_close
= 0;
335 /* sendme cell on open entryconn with full window */
336 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_SENDME
, "Data1234");
338 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
340 tt_int_op(ret
, OP_EQ
, -END_CIRC_REASON_TORPROTOCOL
);
341 ASSERT_UNCOUNTED_BW();
343 /* connected cell on a after EOF */
344 ENTRY_TO_CONN(entryconn3
)->marked_for_close
= 0;
345 edgeconn
->base_
.state
= AP_CONN_STATE_CONNECT_WAIT
;
346 connection_edge_reached_eof(edgeconn
);
347 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_CONNECTED
, "Data1234");
348 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
349 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
351 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
355 ENTRY_TO_CONN(entryconn3
)->marked_for_close
= 0;
356 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_CONNECTED
, "Data1234");
357 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
358 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
360 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
362 ASSERT_UNCOUNTED_BW();
364 /* DATA and SENDME after END cell */
365 ENTRY_TO_CONN(entryconn3
)->marked_for_close
= 0;
366 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_END
, "Data1234");
367 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
368 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
370 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
374 ENTRY_TO_CONN(entryconn3
)->marked_for_close
= 0;
375 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_SENDME
, "Data1234");
377 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
379 tt_int_op(ret
, OP_NE
, -END_CIRC_REASON_TORPROTOCOL
);
380 ASSERT_UNCOUNTED_BW();
382 ENTRY_TO_CONN(entryconn3
)->marked_for_close
= 0;
383 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_DATA
, "Data1234");
384 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
385 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
387 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
389 ASSERT_UNCOUNTED_BW();
391 /* Resolved: 1 counted, more not */
392 edgeconn
= ENTRY_TO_EDGE_CONN(entryconn4
);
393 entryconn4
->socks_request
->command
= SOCKS_COMMAND_RESOLVE
;
394 edgeconn
->base_
.state
= AP_CONN_STATE_RESOLVE_WAIT
;
395 edgeconn
->on_circuit
= TO_CIRCUIT(circ
);
396 ENTRY_TO_CONN(entryconn4
)->marked_for_close
= 0;
397 connection_edge_reached_eof(edgeconn
);
399 ENTRY_TO_CONN(entryconn4
)->marked_for_close
= 0;
400 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_RESOLVED
,
401 "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
402 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
403 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
405 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
409 ENTRY_TO_CONN(entryconn4
)->marked_for_close
= 0;
410 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_RESOLVED
,
411 "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
412 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
414 ASSERT_UNCOUNTED_BW();
416 /* Data not counted after resolved */
417 ENTRY_TO_CONN(entryconn4
)->marked_for_close
= 0;
418 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_DATA
, "Data1234");
419 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
420 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
422 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
424 ASSERT_UNCOUNTED_BW();
426 /* End not counted after resolved */
427 ENTRY_TO_CONN(entryconn4
)->marked_for_close
= 0;
428 PACK_CELL(edgeconn
->stream_id
, RELAY_COMMAND_END
, "Data1234");
429 if (circ
->base_
.purpose
== CIRCUIT_PURPOSE_PATH_BIAS_TESTING
)
430 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
432 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
434 ASSERT_UNCOUNTED_BW();
436 connection_free_minimal(ENTRY_TO_CONN(entryconn2
));
437 connection_free_minimal(ENTRY_TO_CONN(entryconn3
));
438 connection_free_minimal(ENTRY_TO_CONN(entryconn4
));
441 connection_free_minimal(ENTRY_TO_CONN(entryconn2
));
442 connection_free_minimal(ENTRY_TO_CONN(entryconn3
));
443 connection_free_minimal(ENTRY_TO_CONN(entryconn4
));
448 halfstream_insert(origin_circuit_t
*circ
, edge_connection_t
*edgeconn
,
449 streamid_t
*streams
, int num
, int random
)
453 /* Insert num random elements */
454 while (inserted
< num
) {
458 id
= (streamid_t
)crypto_rand_int(65535)+1;
460 id
= get_unique_stream_id_by_circ(circ
);
462 edgeconn
->stream_id
= id
;
464 /* Ensure it isn't there */
465 if (connection_half_edge_find_stream_id(circ
->half_streams
, id
)) {
469 connection_half_edge_add(edgeconn
, circ
);
471 streams
[inserted
] = id
;
479 subtest_halfstream_insertremove(int num
)
481 origin_circuit_t
*circ
=
482 helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL
, 0);
483 edge_connection_t
*edgeconn
;
484 entry_connection_t
*entryconn
;
485 streamid_t
*streams
= tor_malloc_zero(num
*sizeof(streamid_t
));
488 circ
->cpath
->state
= CPATH_STATE_AWAITING_KEYS
;
489 circ
->cpath
->deliver_window
= CIRCWINDOW_START
;
491 entryconn
= fake_entry_conn(circ
, 23);
492 edgeconn
= ENTRY_TO_EDGE_CONN(entryconn
);
494 /* Explicitly test all operations on an absent stream list */
495 tt_int_op(connection_half_edge_is_valid_data(circ
->half_streams
,
497 tt_int_op(connection_half_edge_is_valid_connected(circ
->half_streams
,
499 tt_int_op(connection_half_edge_is_valid_sendme(circ
->half_streams
,
501 tt_int_op(connection_half_edge_is_valid_resolved(circ
->half_streams
,
503 tt_int_op(connection_half_edge_is_valid_end(circ
->half_streams
,
506 /* Insert a duplicate element; verify that other elements absent;
507 * ensure removing it once works */
508 edgeconn
->stream_id
= 23;
509 connection_half_edge_add(edgeconn
, circ
);
510 connection_half_edge_add(edgeconn
, circ
);
511 connection_half_edge_add(edgeconn
, circ
);
513 /* Verify that other elements absent */
514 tt_int_op(connection_half_edge_is_valid_data(circ
->half_streams
,
516 tt_int_op(connection_half_edge_is_valid_connected(circ
->half_streams
,
518 tt_int_op(connection_half_edge_is_valid_sendme(circ
->half_streams
,
520 tt_int_op(connection_half_edge_is_valid_resolved(circ
->half_streams
,
522 tt_int_op(connection_half_edge_is_valid_end(circ
->half_streams
,
525 tt_int_op(connection_half_edge_is_valid_data(circ
->half_streams
,
527 tt_int_op(connection_half_edge_is_valid_connected(circ
->half_streams
,
529 tt_int_op(connection_half_edge_is_valid_sendme(circ
->half_streams
,
531 tt_int_op(connection_half_edge_is_valid_resolved(circ
->half_streams
,
533 tt_int_op(connection_half_edge_is_valid_end(circ
->half_streams
,
536 /* Verify we only remove it once */
537 tt_int_op(connection_half_edge_is_valid_end(circ
->half_streams
,
539 tt_int_op(connection_half_edge_is_valid_end(circ
->half_streams
,
542 halfstream_insert(circ
, edgeconn
, streams
, num
, 1);
544 /* Remove half of them */
545 for (i
= 0; i
< num
/2; i
++) {
546 tt_int_op(connection_half_edge_is_valid_end(circ
->half_streams
,
551 /* Verify first half of list is gone */
552 for (i
= 0; i
< num
/2; i
++) {
553 tt_ptr_op(connection_half_edge_find_stream_id(circ
->half_streams
,
558 /* Verify second half of list is present */
559 for (; i
< num
; i
++) {
560 tt_ptr_op(connection_half_edge_find_stream_id(circ
->half_streams
,
565 /* Remove other half. Verify list is empty. */
566 for (i
= num
/2; i
< num
; i
++) {
567 tt_int_op(connection_half_edge_is_valid_end(circ
->half_streams
,
571 tt_int_op(smartlist_len(circ
->half_streams
), OP_EQ
, 0);
573 /* Explicitly test all operations on an empty stream list */
574 tt_int_op(connection_half_edge_is_valid_data(circ
->half_streams
,
576 tt_int_op(connection_half_edge_is_valid_connected(circ
->half_streams
,
578 tt_int_op(connection_half_edge_is_valid_sendme(circ
->half_streams
,
580 tt_int_op(connection_half_edge_is_valid_resolved(circ
->half_streams
,
582 tt_int_op(connection_half_edge_is_valid_end(circ
->half_streams
,
585 /* For valgrind, leave some around then free the circ */
586 halfstream_insert(circ
, edgeconn
, NULL
, 10, 0);
590 circuit_free_(TO_CIRCUIT(circ
));
591 connection_free_minimal(ENTRY_TO_CONN(entryconn
));
595 test_halfstream_insertremove(void *arg
)
599 /* Suppress the WARN message we generate in this test */
600 setup_full_capture_of_logs(LOG_WARN
);
602 /* Test insertion and removal with a few different sizes */
603 subtest_halfstream_insertremove(10);
604 subtest_halfstream_insertremove(100);
605 subtest_halfstream_insertremove(1000);
609 test_halfstream_wrap(void *arg
)
611 origin_circuit_t
*circ
=
612 helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL
, 0);
613 edge_connection_t
*edgeconn
;
614 entry_connection_t
*entryconn
;
616 circ
->cpath
->state
= CPATH_STATE_AWAITING_KEYS
;
617 circ
->cpath
->deliver_window
= CIRCWINDOW_START
;
619 entryconn
= fake_entry_conn(circ
, 23);
620 edgeconn
= ENTRY_TO_EDGE_CONN(entryconn
);
624 /* Suppress the WARN message we generate in this test */
625 setup_full_capture_of_logs(LOG_WARN
);
626 MOCK(connection_mark_for_close_internal_
, mock_mark_for_close
);
628 /* Verify that get_unique_stream_id_by_circ() can wrap uint16_t */
629 circ
->next_stream_id
= 65530;
630 halfstream_insert(circ
, edgeconn
, NULL
, 7, 0);
631 tt_int_op(circ
->next_stream_id
, OP_EQ
, 2);
632 tt_int_op(smartlist_len(circ
->half_streams
), OP_EQ
, 7);
635 halfstream_insert(circ
, edgeconn
, NULL
,
636 65534-smartlist_len(circ
->half_streams
), 0);
637 tt_int_op(smartlist_len(circ
->half_streams
), OP_EQ
, 65534);
639 /* Verify that we can get_unique_stream_id_by_circ() successfully */
640 edgeconn
->stream_id
= get_unique_stream_id_by_circ(circ
);
641 tt_int_op(edgeconn
->stream_id
, OP_NE
, 0); /* 0 is failure */
643 /* Insert an opened stream on the circ with that id */
644 ENTRY_TO_CONN(entryconn
)->marked_for_close
= 0;
645 edgeconn
->base_
.state
= AP_CONN_STATE_CONNECT_WAIT
;
646 circ
->p_streams
= edgeconn
;
648 /* Verify that get_unique_stream_id_by_circ() fails */
649 tt_int_op(get_unique_stream_id_by_circ(circ
), OP_EQ
, 0); /* 0 is failure */
651 /* eof the one opened stream. Verify it is now in half-closed */
652 tt_int_op(smartlist_len(circ
->half_streams
), OP_EQ
, 65534);
653 connection_edge_reached_eof(edgeconn
);
654 tt_int_op(smartlist_len(circ
->half_streams
), OP_EQ
, 65535);
656 /* Verify get_unique_stream_id_by_circ() fails due to full half-closed */
657 circ
->p_streams
= NULL
;
658 tt_int_op(get_unique_stream_id_by_circ(circ
), OP_EQ
, 0); /* 0 is failure */
661 circuit_free_(TO_CIRCUIT(circ
));
662 connection_free_minimal(ENTRY_TO_CONN(entryconn
));
663 UNMOCK(connection_mark_for_close_internal_
);
667 test_circbw_relay(void *arg
)
672 edge_connection_t
*edgeconn
;
673 entry_connection_t
*entryconn1
=NULL
;
674 origin_circuit_t
*circ
;
680 MOCK(connection_mark_unattached_ap_
, mock_connection_mark_unattached_ap_
);
681 MOCK(connection_start_reading
, mock_start_reading
);
682 MOCK(connection_mark_for_close_internal_
, mock_mark_for_close
);
683 MOCK(relay_send_command_from_edge_
, mock_send_command
);
684 MOCK(circuit_mark_for_close_
, mock_mark_circ_for_close
);
686 circ
= helper_create_origin_circuit(CIRCUIT_PURPOSE_C_GENERAL
, 0);
687 circ
->cpath
->state
= CPATH_STATE_AWAITING_KEYS
;
688 circ
->cpath
->deliver_window
= CIRCWINDOW_START
;
690 entryconn1
= fake_entry_conn(circ
, 1);
691 edgeconn
= ENTRY_TO_EDGE_CONN(entryconn1
);
693 /* Stream id 0: Not counted */
694 PACK_CELL(0, RELAY_COMMAND_END
, "Data1234");
695 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
697 ASSERT_UNCOUNTED_BW();
699 /* Stream id 1: Counted */
700 PACK_CELL(1, RELAY_COMMAND_END
, "Data1234");
701 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
705 /* Properly formatted connect cell: counted */
706 PACK_CELL(1, RELAY_COMMAND_CONNECTED
, "Data1234");
707 tor_addr_parse(&addr
, "30.40.50.60");
708 rh
.length
= connected_cell_format_payload(cell
.payload
+RELAY_HEADER_SIZE
,
710 relay_header_pack((uint8_t*)&cell
.payload
, &rh
); \
711 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
715 /* Properly formatted resolved cell in correct state: counted */
716 edgeconn
->base_
.state
= AP_CONN_STATE_RESOLVE_WAIT
;
717 entryconn1
->socks_request
->command
= SOCKS_COMMAND_RESOLVE
;
718 edgeconn
->on_circuit
= TO_CIRCUIT(circ
);
719 PACK_CELL(1, RELAY_COMMAND_RESOLVED
,
720 "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
721 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
725 edgeconn
->base_
.state
= AP_CONN_STATE_OPEN
;
726 entryconn1
->socks_request
->has_finished
= 1;
728 /* Connected cell after open: not counted */
729 PACK_CELL(1, RELAY_COMMAND_CONNECTED
, "Data1234");
730 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
732 ASSERT_UNCOUNTED_BW();
734 /* Resolved cell after open: not counted */
735 PACK_CELL(1, RELAY_COMMAND_RESOLVED
, "Data1234");
736 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
738 ASSERT_UNCOUNTED_BW();
740 /* Drop cell: not counted */
741 PACK_CELL(1, RELAY_COMMAND_DROP
, "Data1234");
742 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
744 ASSERT_UNCOUNTED_BW();
746 /* Data cell on stream 0: not counted */
747 PACK_CELL(0, RELAY_COMMAND_DATA
, "Data1234");
748 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
750 ASSERT_UNCOUNTED_BW();
752 /* Data cell on open connection: counted */
753 ENTRY_TO_CONN(entryconn1
)->marked_for_close
= 0;
754 PACK_CELL(1, RELAY_COMMAND_DATA
, "Data1234");
755 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
759 /* Empty Data cell on open connection: not counted */
760 ENTRY_TO_CONN(entryconn1
)->marked_for_close
= 0;
761 PACK_CELL(1, RELAY_COMMAND_DATA
, "");
762 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
764 ASSERT_UNCOUNTED_BW();
766 /* Sendme on valid stream: counted */
767 edgeconn
->package_window
-= STREAMWINDOW_INCREMENT
;
768 PACK_CELL(1, RELAY_COMMAND_SENDME
, "Data1234");
769 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
773 /* Sendme on valid stream with full window: not counted */
774 PACK_CELL(1, RELAY_COMMAND_SENDME
, "Data1234");
775 edgeconn
->package_window
= STREAMWINDOW_START
;
776 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
778 ASSERT_UNCOUNTED_BW();
780 /* Sendme on unknown stream: not counted */
781 PACK_CELL(1, RELAY_COMMAND_SENDME
, "Data1234");
782 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
784 ASSERT_UNCOUNTED_BW();
786 /* Sendme on circuit with full window: not counted */
787 PACK_CELL(0, RELAY_COMMAND_SENDME
, "Data1234");
788 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
790 ASSERT_UNCOUNTED_BW();
792 /* Sendme on circuit with non-full window: counted */
793 PACK_CELL(0, RELAY_COMMAND_SENDME
, "");
794 /* Recording a cell, the window is updated after decryption so off by one in
795 * order to record and then we process it with the proper window. */
796 circ
->cpath
->package_window
= 901;
797 sendme_record_cell_digest_on_circ(TO_CIRCUIT(circ
), circ
->cpath
);
798 circ
->cpath
->package_window
= 900;
799 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
803 /* Invalid extended cell: not counted */
804 PACK_CELL(1, RELAY_COMMAND_EXTENDED2
, "Data1234");
805 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
807 ASSERT_UNCOUNTED_BW();
809 /* Invalid extended cell: not counted */
810 PACK_CELL(1, RELAY_COMMAND_EXTENDED
, "Data1234");
811 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
813 ASSERT_UNCOUNTED_BW();
815 /* Invalid HS cell: not counted */
816 PACK_CELL(1, RELAY_COMMAND_ESTABLISH_INTRO
, "Data1234");
817 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
819 ASSERT_UNCOUNTED_BW();
821 /* "Valid" HS cell in expected state: counted */
822 TO_CIRCUIT(circ
)->purpose
= CIRCUIT_PURPOSE_C_ESTABLISH_REND
;
823 PACK_CELL(1, RELAY_COMMAND_RENDEZVOUS_ESTABLISHED
, "Data1234");
824 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
828 /* End cell on non-closed connection: counted */
829 PACK_CELL(1, RELAY_COMMAND_END
, "Data1234");
830 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), edgeconn
,
834 /* End cell on connection that already got one: not counted */
835 PACK_CELL(1, RELAY_COMMAND_END
, "Data1234");
836 connection_edge_process_relay_cell(&cell
, TO_CIRCUIT(circ
), NULL
,
838 ASSERT_UNCOUNTED_BW();
840 /* Simulate closed stream on entryconn, then test: */
841 if (!subtest_circbw_halfclosed(circ
, 2))
844 circ
->base_
.purpose
= CIRCUIT_PURPOSE_PATH_BIAS_TESTING
;
845 if (!subtest_circbw_halfclosed(circ
, 6))
848 /* Path bias: truncated */
849 tt_int_op(circ
->base_
.marked_for_close
, OP_EQ
, 0);
850 PACK_CELL(0, RELAY_COMMAND_TRUNCATED
, "Data1234");
851 pathbias_count_valid_cells(TO_CIRCUIT(circ
), &cell
);
852 tt_int_op(circ
->base_
.marked_for_close
, OP_EQ
, 1);
855 UNMOCK(connection_start_reading
);
856 UNMOCK(connection_mark_unattached_ap_
);
857 UNMOCK(connection_mark_for_close_internal_
);
858 UNMOCK(relay_send_command_from_edge_
);
859 UNMOCK(circuit_mark_for_close_
);
860 circuit_free_(TO_CIRCUIT(circ
));
861 connection_free_minimal(ENTRY_TO_CONN(entryconn1
));
864 /* Tests for connection_edge_process_resolved_cell().
866 The point of ..process_resolved_cell() is to handle an incoming cell
867 on an entry connection, and call connection_mark_unattached_ap() and/or
868 connection_ap_handshake_socks_resolved().
871 test_relaycell_resolved(void *arg
)
873 entry_connection_t
*entryconn
;
874 edge_connection_t
*edgeconn
;
878 or_options_t
*options
= get_options_mutable();
880 #define SET_CELL(s) do { \
881 memset(&cell, 0, sizeof(cell)); \
882 memset(&rh, 0, sizeof(rh)); \
883 memcpy(cell.payload + RELAY_HEADER_SIZE, (s), sizeof((s))-1); \
884 rh.length = sizeof((s))-1; \
885 rh.command = RELAY_COMMAND_RESOLVED; \
887 #define MOCK_RESET() do { \
888 srm_ncalls = mum_ncalls = 0; \
890 #define ASSERT_MARK_CALLED(reason) do { \
891 tt_int_op(mum_ncalls, OP_EQ, 1); \
892 tt_ptr_op(mum_conn, OP_EQ, entryconn); \
893 tt_int_op(mum_endreason, OP_EQ, (reason)); \
895 #define ASSERT_RESOLVED_CALLED(atype, answer, ttl, expires) do { \
896 tt_int_op(srm_ncalls, OP_EQ, 1); \
897 tt_ptr_op(srm_conn, OP_EQ, entryconn); \
898 tt_int_op(srm_atype, OP_EQ, (atype)); \
899 if ((answer) != NULL) { \
900 tt_int_op(srm_alen, OP_EQ, sizeof(answer)-1); \
901 tt_int_op(srm_alen, OP_LT, 512); \
902 tt_int_op(srm_answer_is_set, OP_EQ, 1); \
903 tt_mem_op(srm_answer, OP_EQ, answer, sizeof(answer)-1); \
905 tt_int_op(srm_answer_is_set, OP_EQ, 0); \
907 tt_int_op(srm_ttl, OP_EQ, ttl); \
908 tt_i64_op(srm_expires, OP_EQ, expires); \
913 MOCK(connection_mark_unattached_ap_
, mark_unattached_mock
);
914 MOCK(connection_ap_handshake_socks_resolved
, socks_resolved_mock
);
916 options
->ClientDNSRejectInternalAddresses
= 0;
918 SET_CELL(/* IPv4: 127.0.1.2, ttl 256 */
919 "\x04\x04\x7f\x00\x01\x02\x00\x00\x01\x00"
920 /* IPv4: 18.0.0.1, ttl 512 */
921 "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"
922 /* IPv6: 2003::3, ttl 1024 */
924 "\x20\x02\x00\x00\x00\x00\x00\x00"
925 "\x00\x00\x00\x00\x00\x00\x00\x03"
928 entryconn
= entry_connection_new(CONN_TYPE_AP
, AF_INET
);
929 edgeconn
= ENTRY_TO_EDGE_CONN(entryconn
);
931 /* Try with connection in non-RESOLVE_WAIT state: cell gets ignored */
933 r
= connection_edge_process_resolved_cell(edgeconn
, &cell
, &rh
);
934 tt_int_op(r
, OP_EQ
, 0);
935 tt_int_op(srm_ncalls
, OP_EQ
, 0);
936 tt_int_op(mum_ncalls
, OP_EQ
, 0);
938 /* Now put it in the right state. */
939 ENTRY_TO_CONN(entryconn
)->state
= AP_CONN_STATE_RESOLVE_WAIT
;
940 entryconn
->socks_request
->command
= SOCKS_COMMAND_RESOLVE
;
941 entryconn
->entry_cfg
.ipv4_traffic
= 1;
942 entryconn
->entry_cfg
.ipv6_traffic
= 1;
943 entryconn
->entry_cfg
.prefer_ipv6
= 0;
945 /* We prefer ipv4, so we should get the first ipv4 answer */
947 r
= connection_edge_process_resolved_cell(edgeconn
, &cell
, &rh
);
948 tt_int_op(r
, OP_EQ
, 0);
949 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE
|
950 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED
);
951 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_IPV4
, "\x7f\x00\x01\x02", 256, -1);
953 /* But we may be discarding private answers. */
955 options
->ClientDNSRejectInternalAddresses
= 1;
956 r
= connection_edge_process_resolved_cell(edgeconn
, &cell
, &rh
);
957 tt_int_op(r
, OP_EQ
, 0);
958 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE
|
959 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED
);
960 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_IPV4
, "\x12\x00\x00\x01", 512, -1);
962 /* now prefer ipv6, and get the first ipv6 answer */
963 entryconn
->entry_cfg
.prefer_ipv6
= 1;
965 r
= connection_edge_process_resolved_cell(edgeconn
, &cell
, &rh
);
966 tt_int_op(r
, OP_EQ
, 0);
967 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE
|
968 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED
);
969 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_IPV6
,
970 "\x20\x02\x00\x00\x00\x00\x00\x00"
971 "\x00\x00\x00\x00\x00\x00\x00\x03",
974 /* With a cell that only has IPv4, we report IPv4 even if we prefer IPv6 */
976 SET_CELL("\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00");
977 r
= connection_edge_process_resolved_cell(edgeconn
, &cell
, &rh
);
978 tt_int_op(r
, OP_EQ
, 0);
979 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE
|
980 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED
);
981 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_IPV4
, "\x12\x00\x00\x01", 512, -1);
983 /* But if we don't allow IPv4, we report nothing if the cell contains only
986 entryconn
->entry_cfg
.ipv4_traffic
= 0;
987 r
= connection_edge_process_resolved_cell(edgeconn
, &cell
, &rh
);
988 tt_int_op(r
, OP_EQ
, 0);
989 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE
|
990 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED
);
991 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR
, NULL
, -1, -1);
993 /* If we wanted hostnames, we report nothing, since we only had IPs. */
995 entryconn
->entry_cfg
.ipv4_traffic
= 1;
996 entryconn
->socks_request
->command
= SOCKS_COMMAND_RESOLVE_PTR
;
997 r
= connection_edge_process_resolved_cell(edgeconn
, &cell
, &rh
);
998 tt_int_op(r
, OP_EQ
, 0);
999 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE
|
1000 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED
);
1001 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR
, NULL
, -1, -1);
1003 /* A hostname cell is fine though. */
1005 SET_CELL("\x00\x0fwww.example.com\x00\x01\x00\x00");
1006 r
= connection_edge_process_resolved_cell(edgeconn
, &cell
, &rh
);
1007 tt_int_op(r
, OP_EQ
, 0);
1008 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE
|
1009 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED
);
1010 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_HOSTNAME
, "www.example.com", 65536, -1);
1012 /* error on malformed cell */
1014 entryconn
->socks_request
->command
= SOCKS_COMMAND_RESOLVE
;
1015 SET_CELL("\x04\x04\x01\x02\x03\x04"); /* no ttl */
1016 r
= connection_edge_process_resolved_cell(edgeconn
, &cell
, &rh
);
1017 tt_int_op(r
, OP_EQ
, 0);
1018 ASSERT_MARK_CALLED(END_STREAM_REASON_TORPROTOCOL
);
1019 tt_int_op(srm_ncalls
, OP_EQ
, 0);
1021 /* error on all addresses private */
1023 SET_CELL(/* IPv4: 127.0.1.2, ttl 256 */
1024 "\x04\x04\x7f\x00\x01\x02\x00\x00\x01\x00"
1025 /* IPv4: 192.168.1.1, ttl 256 */
1026 "\x04\x04\xc0\xa8\x01\x01\x00\x00\x01\x00");
1027 r
= connection_edge_process_resolved_cell(edgeconn
, &cell
, &rh
);
1028 tt_int_op(r
, OP_EQ
, 0);
1029 ASSERT_MARK_CALLED(END_STREAM_REASON_TORPROTOCOL
);
1030 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR_TRANSIENT
, NULL
, 0, TIME_MAX
);
1032 /* Legit error code */
1034 SET_CELL("\xf0\x15" "quiet and meaningless" "\x00\x00\x0f\xff");
1035 r
= connection_edge_process_resolved_cell(edgeconn
, &cell
, &rh
);
1036 tt_int_op(r
, OP_EQ
, 0);
1037 ASSERT_MARK_CALLED(END_STREAM_REASON_DONE
|
1038 END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED
);
1039 ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR_TRANSIENT
, NULL
, -1, -1);
1042 UNMOCK(connection_mark_unattached_ap_
);
1043 UNMOCK(connection_ap_handshake_socks_resolved
);
1046 struct testcase_t relaycell_tests
[] = {
1047 { "resolved", test_relaycell_resolved
, TT_FORK
, NULL
, NULL
},
1048 { "circbw", test_circbw_relay
, TT_FORK
, NULL
, NULL
},
1049 { "halfstream", test_halfstream_insertremove
, TT_FORK
, NULL
, NULL
},
1050 { "streamwrap", test_halfstream_wrap
, TT_FORK
, NULL
, NULL
},