From: David Goulet Date: Thu, 5 Oct 2023 16:29:54 +0000 (-0400) Subject: prop340: Use relay messages accross the code X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=70ca7d2bec695753957acf38cb0dcddb3e32903f;p=thirdparty%2Ftor.git prop340: Use relay messages accross the code Author: David Goulet (This won't yet compile; for now I am _only_ taking the parts as dgoulet wrote them, minus a codec-only piece.) Modified by nickm: Encode and decode relay messages using our new functions. In David's original branch, this was done using codec objects, but since we aren't doing prop340, this is simpler. --- diff --git a/src/core/or/circuitpadding.c b/src/core/or/circuitpadding.c index 590a2d60c9..018d14b28f 100644 --- a/src/core/or/circuitpadding.c +++ b/src/core/or/circuitpadding.c @@ -1846,22 +1846,21 @@ circpad_cell_event_nonpadding_sent(circuit_t *on_circ) * not need any other consideration, otherwise return 1. */ int -circpad_check_received_cell(cell_t *cell, circuit_t *circ, - crypt_path_t *layer_hint, - const relay_header_t *rh) +circpad_check_received_cell(const relay_msg_t *msg, circuit_t *circ, + crypt_path_t *layer_hint) { /* First handle the padding commands, since we want to ignore any other * commands if this circuit is padding-specific. */ - switch (rh->command) { + switch (msg->command) { case RELAY_COMMAND_DROP: /* Already examined in circpad_deliver_recognized_relay_cell_events */ return 0; case RELAY_COMMAND_PADDING_NEGOTIATE: - circpad_handle_padding_negotiate(circ, cell); + circpad_handle_padding_negotiate(circ, msg); return 0; case RELAY_COMMAND_PADDING_NEGOTIATED: - if (circpad_handle_padding_negotiated(circ, cell, layer_hint) == 0) - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh->length); + if (circpad_handle_padding_negotiated(circ, msg, layer_hint) == 0) + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); return 0; } @@ -1888,7 +1887,7 @@ circpad_check_received_cell(cell_t *cell, circuit_t *circ, if (circ->purpose == CIRCUIT_PURPOSE_C_CIRCUIT_PADDING) { log_fn(LOG_PROTOCOL_WARN, LD_CIRC, "Ignored cell (%d) that arrived in padding circuit " - " %u.", rh->command, CIRCUIT_IS_ORIGIN(circ) ? + " %u.", msg->command, CIRCUIT_IS_ORIGIN(circ) ? TO_ORIGIN_CIRCUIT(circ)->global_identifier : 0); return 0; } @@ -2969,7 +2968,7 @@ circpad_padding_negotiated(circuit_t *circ, * Returns -1 on error, 0 on success. */ signed_error_t -circpad_handle_padding_negotiate(circuit_t *circ, cell_t *cell) +circpad_handle_padding_negotiate(circuit_t *circ, const relay_msg_t *msg) { int retval = 0; /* Should we send back a STOP cell? */ @@ -2983,8 +2982,7 @@ circpad_handle_padding_negotiate(circuit_t *circ, cell_t *cell) return -1; } - if (circpad_negotiate_parse(&negotiate, cell->payload+RELAY_HEADER_SIZE, - CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE) < 0) { + if (circpad_negotiate_parse(&negotiate, msg->body, msg->length) < 0) { log_fn(LOG_PROTOCOL_WARN, LD_CIRC, "Received malformed PADDING_NEGOTIATE cell; dropping."); return -1; @@ -3057,7 +3055,7 @@ circpad_handle_padding_negotiate(circuit_t *circ, cell_t *cell) * Returns -1 on error, 0 on success. */ signed_error_t -circpad_handle_padding_negotiated(circuit_t *circ, cell_t *cell, +circpad_handle_padding_negotiated(circuit_t *circ, const relay_msg_t *msg, crypt_path_t *layer_hint) { circpad_negotiated_t *negotiated; @@ -3076,8 +3074,7 @@ circpad_handle_padding_negotiated(circuit_t *circ, cell_t *cell, return -1; } - if (circpad_negotiated_parse(&negotiated, cell->payload+RELAY_HEADER_SIZE, - CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE) < 0) { + if (circpad_negotiated_parse(&negotiated, msg->body, msg->length) < 0) { log_fn(LOG_PROTOCOL_WARN, LD_CIRC, "Received malformed PADDING_NEGOTIATED cell on circuit %u; " "dropping.", TO_ORIGIN_CIRCUIT(circ)->global_identifier); diff --git a/src/core/or/circuitpadding.h b/src/core/or/circuitpadding.h index 306d178684..419701a686 100644 --- a/src/core/or/circuitpadding.h +++ b/src/core/or/circuitpadding.h @@ -12,6 +12,7 @@ #include "trunnel/circpad_negotiation.h" #include "lib/evloop/timers.h" +#include "core/or/relay_msg_st.h" struct circuit_t; struct origin_circuit_t; @@ -736,9 +737,9 @@ const circpad_machine_spec_t *circpad_string_to_machine(const char *str); /* Padding negotiation between client and middle */ signed_error_t circpad_handle_padding_negotiate(struct circuit_t *circ, - struct cell_t *cell); + const relay_msg_t *msg); signed_error_t circpad_handle_padding_negotiated(struct circuit_t *circ, - struct cell_t *cell, + const relay_msg_t *msg, crypt_path_t *layer_hint); signed_error_t circpad_negotiate_padding(struct origin_circuit_t *circ, circpad_machine_num_t machine, @@ -753,9 +754,8 @@ bool circpad_padding_negotiated(struct circuit_t *circ, circpad_purpose_mask_t circpad_circ_purpose_to_mask(uint8_t circ_purpose); -int circpad_check_received_cell(cell_t *cell, circuit_t *circ, - crypt_path_t *layer_hint, - const relay_header_t *rh); +int circpad_check_received_cell(const relay_msg_t *msg, circuit_t *circ, + crypt_path_t *layer_hint); MOCK_DECL(circpad_decision_t, circpad_machine_schedule_padding,(circpad_machine_runtime_t *)); diff --git a/src/core/or/conflux.c b/src/core/or/conflux.c index 9025dcffaf..b657eb00ef 100644 --- a/src/core/or/conflux.c +++ b/src/core/or/conflux.c @@ -6,6 +6,7 @@ * \brief Conflux multipath core algorithms */ +#include "core/or/relay_msg.h" #define TOR_CONFLUX_PRIVATE #include "core/or/or.h" @@ -169,7 +170,7 @@ uint64_t conflux_get_circ_bytes_allocation(const circuit_t *circ) { if (circ->conflux) { - return smartlist_len(circ->conflux->ooo_q) * sizeof(conflux_cell_t); + return smartlist_len(circ->conflux->ooo_q) * sizeof(conflux_msg_t); } return 0; } @@ -680,8 +681,8 @@ conflux_queue_cmp(const void *a, const void *b) { // Compare a and b as conflux_cell_t using the seq field, and return a // comparison result such that the lowest seq is at the head of the pqueue. - const conflux_cell_t *cell_a = a; - const conflux_cell_t *cell_b = b; + const conflux_msg_t *cell_a = a; + const conflux_msg_t *cell_b = b; tor_assert(cell_a); tor_assert(cell_b); @@ -732,12 +733,11 @@ circuit_ccontrol(const circuit_t *circ) */ int conflux_process_switch_command(circuit_t *in_circ, - crypt_path_t *layer_hint, cell_t *cell, - relay_header_t *rh) + crypt_path_t *layer_hint, + const relay_msg_t *msg) { tor_assert(in_circ); - tor_assert(cell); - tor_assert(rh); + tor_assert(msg); conflux_t *cfx = in_circ->conflux; uint32_t relative_seq; @@ -781,7 +781,7 @@ conflux_process_switch_command(circuit_t *in_circ, return -1; } - relative_seq = conflux_cell_parse_switch(cell, rh->length); + relative_seq = conflux_cell_parse_switch(msg); /* * We have to make sure that the switch command is truely @@ -816,7 +816,7 @@ conflux_process_switch_command(circuit_t *in_circ, /* Mark this data as validated for controlport and vanguards * dropped cell handling */ if (CIRCUIT_IS_ORIGIN(in_circ)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(in_circ), rh->length); + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(in_circ), msg->length); } return 0; @@ -830,8 +830,8 @@ conflux_process_switch_command(circuit_t *in_circ, * to streams, false otherwise. */ bool -conflux_process_cell(conflux_t *cfx, circuit_t *in_circ, - crypt_path_t *layer_hint, cell_t *cell) +conflux_process_relay_msg(conflux_t *cfx, circuit_t *in_circ, + crypt_path_t *layer_hint, const relay_msg_t *msg) { // TODO-329-TUNING: Temporarily validate legs here. We can remove // this after tuning is complete. @@ -867,14 +867,19 @@ conflux_process_cell(conflux_t *cfx, circuit_t *in_circ, circuit_mark_for_close(in_circ, END_CIRC_REASON_INTERNAL); return false; } else { - conflux_cell_t *c_cell = tor_malloc_zero(sizeof(conflux_cell_t)); - c_cell->seq = leg->last_seq_recv; - - memcpy(&c_cell->cell, cell, sizeof(cell_t)); + conflux_msg_t *c_msg = tor_malloc_zero(sizeof(conflux_msg_t)); + c_msg->seq = leg->last_seq_recv; + /* Notice the copy here. Reason is that we don't have ownership of the + * message. If we wanted to pull that off, we would need to change the + * whole calling stack and unit tests on either not touching it after this + * function indicates that it has taken it or never allocate it from the + * stack. This is simpler and less error prone but might show up in our + * profile (maybe?). The Maze is serious. It needs to be respected. */ + c_msg->msg = relay_msg_copy(msg); smartlist_pqueue_add(cfx->ooo_q, conflux_queue_cmp, - offsetof(conflux_cell_t, heap_idx), c_cell); - total_ooo_q_bytes += sizeof(cell_t); + offsetof(conflux_msg_t, heap_idx), c_msg); + total_ooo_q_bytes += sizeof(msg->length); /* This cell should not be processed yet, and the queue is not ready * to process because the next absolute seqnum has not yet arrived */ @@ -888,10 +893,10 @@ conflux_process_cell(conflux_t *cfx, circuit_t *in_circ, * Returns the cell as a conflux_cell_t, or NULL if the queue is empty * or has a hole. */ -conflux_cell_t * -conflux_dequeue_cell(conflux_t *cfx) +conflux_msg_t * +conflux_dequeue_relay_msg(conflux_t *cfx) { - conflux_cell_t *top = NULL; + conflux_msg_t *top = NULL; if (smartlist_len(cfx->ooo_q) == 0) return NULL; @@ -901,11 +906,21 @@ conflux_dequeue_cell(conflux_t *cfx) * pop and return it. */ if (top->seq == cfx->last_seq_delivered+1) { smartlist_pqueue_pop(cfx->ooo_q, conflux_queue_cmp, - offsetof(conflux_cell_t, heap_idx)); - total_ooo_q_bytes -= sizeof(cell_t); + offsetof(conflux_msg_t, heap_idx)); + total_ooo_q_bytes -= sizeof(top->msg->length); cfx->last_seq_delivered++; return top; } else { return NULL; } } + +/** Free a given conflux msg object. */ +void +conflux_relay_msg_free(conflux_msg_t *msg) +{ + if (msg) { + relay_msg_free(msg->msg); + tor_free(msg); + } +} diff --git a/src/core/or/conflux.h b/src/core/or/conflux.h index e01b323317..1594039e26 100644 --- a/src/core/or/conflux.h +++ b/src/core/or/conflux.h @@ -11,6 +11,7 @@ #include "core/or/circuit_st.h" #include "core/or/conflux_st.h" +#include "core/or/relay_msg_st.h" typedef struct conflux_t conflux_t; typedef struct conflux_leg_t conflux_leg_t; @@ -24,8 +25,7 @@ typedef struct conflux_leg_t conflux_leg_t; /** Helper: Return the number of legs a conflux object has. */ #define CONFLUX_NUM_LEGS(cfx) (smartlist_len(cfx->legs)) -/** A cell for the out-of-order queue. - * XXX: Consider trying to use packed_cell_t instead here? */ +/** A relay message for the out-of-order queue. */ typedef struct { /** * Absolute sequence number of this cell, computed from the @@ -37,10 +37,10 @@ typedef struct { */ int heap_idx; - /** The cell here is always guaranteed to have removed its + /** The relay message here is always guaranteed to have removed its * extra conflux sequence number, for ease of processing */ - cell_t cell; -} conflux_cell_t; + relay_msg_t *msg; +} conflux_msg_t; size_t conflux_handle_oom(size_t bytes_to_remove); uint64_t conflux_get_total_bytes_allocation(void); @@ -54,15 +54,16 @@ circuit_t *conflux_decide_circ_for_send(conflux_t *cfx, circuit_t *conflux_decide_next_circ(conflux_t *cfx); int conflux_process_switch_command(circuit_t *in_circ, - crypt_path_t *layer_hint, cell_t *cell, - relay_header_t *rh); + crypt_path_t *layer_hint, + const relay_msg_t *msg); bool conflux_should_multiplex(int relay_command); -bool conflux_process_cell(conflux_t *cfx, circuit_t *in_circ, - crypt_path_t *layer_hint, - cell_t *cell); -conflux_cell_t *conflux_dequeue_cell(conflux_t *cfx); +bool conflux_process_relay_msg(conflux_t *cfx, circuit_t *in_circ, + crypt_path_t *layer_hint, + const relay_msg_t *msg); +conflux_msg_t *conflux_dequeue_relay_msg(conflux_t *cfx); void conflux_note_cell_sent(conflux_t *cfx, circuit_t *circ, uint8_t relay_command); +void conflux_relay_msg_free(conflux_msg_t *msg); /* Private section starts. */ #ifdef TOR_CONFLUX_PRIVATE diff --git a/src/core/or/conflux_cell.c b/src/core/or/conflux_cell.c index a59fa735f1..24b85e3005 100644 --- a/src/core/or/conflux_cell.c +++ b/src/core/or/conflux_cell.c @@ -226,16 +226,14 @@ conflux_cell_parse_link_v1(const trn_cell_conflux_link_t *trn_link) } conflux_cell_link_t * -conflux_cell_parse_link(const cell_t *cell, const uint16_t cell_len) +conflux_cell_parse_link(const relay_msg_t *msg) { conflux_cell_link_t *link = NULL; trn_cell_conflux_link_t *trn_cell = NULL; - tor_assert(cell); + tor_assert(msg); - if (trn_cell_conflux_link_parse(&trn_cell, - cell->payload + RELAY_HEADER_SIZE, - cell_len) < 0) { + if (trn_cell_conflux_link_parse(&trn_cell, msg->body, msg->length) < 0) { log_fn(LOG_PROTOCOL_WARN, LD_CIRC, "Unable to parse CONFLUX_LINK cell."); goto end; @@ -258,10 +256,10 @@ conflux_cell_parse_link(const cell_t *cell, const uint16_t cell_len) } conflux_cell_link_t * -conflux_cell_parse_linked(const cell_t *cell, const uint16_t cell_len) +conflux_cell_parse_linked(const relay_msg_t *msg) { /* At the moment, same exact payload so avoid code duplication. */ - return conflux_cell_parse_link(cell, cell_len); + return conflux_cell_parse_link(msg); } conflux_cell_link_t * @@ -284,15 +282,15 @@ conflux_cell_new_link(const uint8_t *nonce, uint64_t last_seqno_sent, * Extracts the sequence number from a switch cell. */ uint32_t -conflux_cell_parse_switch(const cell_t *cell, uint16_t rh_len) +conflux_cell_parse_switch(const relay_msg_t *msg) { uint32_t seq = 0; trn_cell_conflux_switch_t *switch_cell = NULL; - tor_assert(cell); + + tor_assert(msg); if (trn_cell_conflux_switch_parse(&switch_cell, - cell->payload + RELAY_HEADER_SIZE, - rh_len) < 0) { + msg->body, msg->length) < 0) { log_warn(LD_BUG, "Failed to parse switch cell"); // Zero counts as a failure to the validation, since legs should // not switch after 0 cells. diff --git a/src/core/or/conflux_cell.h b/src/core/or/conflux_cell.h index 60fff42241..74c9596e75 100644 --- a/src/core/or/conflux_cell.h +++ b/src/core/or/conflux_cell.h @@ -10,6 +10,7 @@ #define TOR_CONFLUX_CELL_H #include "core/or/or.h" +#include "core/or/relay_msg_st.h" typedef struct conflux_cell_link_t { uint8_t version; @@ -25,12 +26,9 @@ conflux_cell_link_t *conflux_cell_new_link(const uint8_t *nonce, uint64_t last_recv, uint8_t ux); -conflux_cell_link_t *conflux_cell_parse_link(const cell_t *cell, - const uint16_t cell_len); -conflux_cell_link_t *conflux_cell_parse_linked(const cell_t *cell, - const uint16_t cell_le); -uint32_t conflux_cell_parse_switch(const cell_t *cell, - const uint16_t rh_len); +conflux_cell_link_t *conflux_cell_parse_link(const relay_msg_t *msg); +conflux_cell_link_t *conflux_cell_parse_linked(const relay_msg_t *msg); +uint32_t conflux_cell_parse_switch(const relay_msg_t *msg); bool conflux_cell_send_link(const conflux_cell_link_t *link, origin_circuit_t *circ); diff --git a/src/core/or/conflux_pool.c b/src/core/or/conflux_pool.c index 82043d607f..9bfaf22b57 100644 --- a/src/core/or/conflux_pool.c +++ b/src/core/or/conflux_pool.c @@ -196,7 +196,7 @@ conflux_free_(conflux_t *cfx) } SMARTLIST_FOREACH_END(leg); smartlist_free(cfx->legs); - SMARTLIST_FOREACH(cfx->ooo_q, conflux_cell_t *, cell, tor_free(cell)); + SMARTLIST_FOREACH(cfx->ooo_q, conflux_msg_t *, cell, tor_free(cell)); smartlist_free(cfx->ooo_q); memwipe(cfx->nonce, 0, sizeof(cfx->nonce)); @@ -1763,14 +1763,13 @@ conflux_circuit_has_opened(origin_circuit_t *orig_circ) /** Process a CONFLUX_LINK cell which arrived on the given circuit. */ void -conflux_process_link(circuit_t *circ, const cell_t *cell, - const uint16_t cell_len) +conflux_process_link(circuit_t *circ, const relay_msg_t *msg) { unlinked_circuits_t *unlinked = NULL; conflux_cell_link_t *link = NULL; tor_assert(circ); - tor_assert(cell); + tor_assert(msg); if (!conflux_is_enabled(circ)) { circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL); @@ -1810,7 +1809,7 @@ conflux_process_link(circuit_t *circ, const cell_t *cell, } /* On errors, logging is emitted in this parsing function. */ - link = conflux_cell_parse_link(cell, cell_len); + link = conflux_cell_parse_link(msg); if (!link) { log_fn(LOG_PROTOCOL_WARN, LD_CIRC, "Unable to parse " "CONFLUX_LINK cell. Closing circuit."); @@ -1875,8 +1874,7 @@ conflux_process_link(circuit_t *circ, const cell_t *cell, /** Process a CONFLUX_LINKED cell which arrived on the given circuit. */ void conflux_process_linked(circuit_t *circ, crypt_path_t *layer_hint, - const cell_t *cell, - const uint16_t cell_len) + const relay_msg_t *msg) { conflux_cell_link_t *link = NULL; @@ -1936,7 +1934,7 @@ conflux_process_linked(circuit_t *circ, crypt_path_t *layer_hint, tor_assert_nonfatal(circ->purpose == CIRCUIT_PURPOSE_CONFLUX_UNLINKED); /* On errors, logging is emitted in this parsing function. */ - link = conflux_cell_parse_link(cell, cell_len); + link = conflux_cell_parse_link(msg); if (!link) { goto close; } @@ -2008,7 +2006,7 @@ conflux_process_linked(circuit_t *circ, crypt_path_t *layer_hint, } /* This cell is now considered valid for clients. */ - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), cell_len); + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); goto end; diff --git a/src/core/or/conflux_pool.h b/src/core/or/conflux_pool.h index eba726b03a..7c97f49502 100644 --- a/src/core/or/conflux_pool.h +++ b/src/core/or/conflux_pool.h @@ -10,6 +10,7 @@ #define TOR_CONFLUX_POOL_H #include "core/or/or.h" +#include "core/or/relay_msg_st.h" void conflux_pool_init(void); void conflux_notify_shutdown(void); @@ -31,10 +32,9 @@ void conflux_circuit_has_closed(circuit_t *circ); void conflux_circuit_has_opened(origin_circuit_t *orig_circ); void conflux_circuit_about_to_free(circuit_t *circ); -void conflux_process_link(circuit_t *circ, const cell_t *cell, - const uint16_t cell_len); +void conflux_process_link(circuit_t *circ, const relay_msg_t *msg); void conflux_process_linked(circuit_t *circ, crypt_path_t *layer_hint, - const cell_t *cell, const uint16_t cell_len); + const relay_msg_t *msg); void conflux_process_linked_ack(circuit_t *circ); typedef struct conflux_t conflux_t; diff --git a/src/core/or/congestion_control_flow.c b/src/core/or/congestion_control_flow.c index fa9455a8a1..4e1c545870 100644 --- a/src/core/or/congestion_control_flow.c +++ b/src/core/or/congestion_control_flow.c @@ -232,10 +232,8 @@ circuit_send_stream_xon(edge_connection_t *stream) */ bool circuit_process_stream_xoff(edge_connection_t *conn, - const crypt_path_t *layer_hint, - const cell_t *cell) + const crypt_path_t *layer_hint) { - (void)cell; bool retval = true; if (BUG(!conn)) { @@ -327,7 +325,7 @@ circuit_process_stream_xoff(edge_connection_t *conn, bool circuit_process_stream_xon(edge_connection_t *conn, const crypt_path_t *layer_hint, - const cell_t *cell) + const relay_msg_t *msg) { xon_cell_t *xon; bool retval = true; @@ -351,8 +349,7 @@ circuit_process_stream_xon(edge_connection_t *conn, return false; } - if (xon_cell_parse(&xon, cell->payload+RELAY_HEADER_SIZE, - CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE) < 0) { + if (xon_cell_parse(&xon, msg->body, msg->length) < 0) { log_fn(LOG_PROTOCOL_WARN, LD_EDGE, "Received malformed XON cell."); return false; diff --git a/src/core/or/congestion_control_flow.h b/src/core/or/congestion_control_flow.h index 05e25c44d0..74545ef882 100644 --- a/src/core/or/congestion_control_flow.h +++ b/src/core/or/congestion_control_flow.h @@ -13,14 +13,15 @@ #include "core/or/circuit_st.h" #include "core/or/edge_connection_st.h" +struct relay_msg_t; + void flow_control_new_consensus_params(const struct networkstatus_t *); bool circuit_process_stream_xoff(edge_connection_t *conn, - const crypt_path_t *layer_hint, - const cell_t *cell); + const crypt_path_t *layer_hint); bool circuit_process_stream_xon(edge_connection_t *conn, const crypt_path_t *layer_hint, - const cell_t *cell); + const struct relay_msg_t *msg); int flow_control_decide_xoff(edge_connection_t *stream); void flow_control_decide_xon(edge_connection_t *stream, size_t n_written); diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c index b36d0d9013..14a45a7b53 100644 --- a/src/core/or/connection_edge.c +++ b/src/core/or/connection_edge.c @@ -3816,33 +3816,27 @@ connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply, * we don't. **/ STATIC int -begin_cell_parse(const cell_t *cell, begin_cell_t *bcell, +begin_cell_parse(const relay_msg_t *msg, begin_cell_t *bcell, uint8_t *end_reason_out) { - relay_header_t rh; const uint8_t *body, *nul; memset(bcell, 0, sizeof(*bcell)); *end_reason_out = END_STREAM_REASON_MISC; - relay_header_unpack(&rh, cell->payload); - if (rh.length > RELAY_PAYLOAD_SIZE) { - return -2; /*XXXX why not TORPROTOCOL? */ - } - - bcell->stream_id = rh.stream_id; + bcell->stream_id = msg->stream_id; - if (rh.command == RELAY_COMMAND_BEGIN_DIR) { + if (msg->command == RELAY_COMMAND_BEGIN_DIR) { bcell->is_begindir = 1; return 0; - } else if (rh.command != RELAY_COMMAND_BEGIN) { - log_warn(LD_BUG, "Got an unexpected command %d", (int)rh.command); + } else if (msg->command != RELAY_COMMAND_BEGIN) { + log_warn(LD_BUG, "Got an unexpected command %u", msg->command); *end_reason_out = END_STREAM_REASON_INTERNAL; return -1; } - body = cell->payload + RELAY_HEADER_SIZE; - nul = memchr(body, 0, rh.length); + body = msg->body; + nul = memchr(body, 0, msg->length); if (! nul) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Relay begin cell has no \\0. Closing."); @@ -3865,7 +3859,7 @@ begin_cell_parse(const cell_t *cell, begin_cell_t *bcell, *end_reason_out = END_STREAM_REASON_TORPROTOCOL; return -1; } - if (body + rh.length >= nul + 4) + if (body + msg->length >= nul + 4) bcell->flags = ntohl(get_uint32(nul+1)); return 0; @@ -3978,10 +3972,9 @@ handle_hs_exit_conn(circuit_t *circ, edge_connection_t *conn) * Else return 0. */ int -connection_exit_begin_conn(cell_t *cell, circuit_t *circ) +connection_exit_begin_conn(const relay_msg_t *msg, circuit_t *circ) { edge_connection_t *n_stream; - relay_header_t rh; char *address = NULL; uint16_t port = 0; or_circuit_t *or_circ = NULL; @@ -4002,25 +3995,22 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) layer_hint = origin_circ->cpath->prev; } - relay_header_unpack(&rh, cell->payload); - if (rh.length > RELAY_PAYLOAD_SIZE) - return -END_CIRC_REASON_TORPROTOCOL; - if (!server_mode(options) && circ->purpose != CIRCUIT_PURPOSE_S_REND_JOINED) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Relay begin cell at non-server. Closing."); - relay_send_end_cell_from_edge(rh.stream_id, circ, + relay_send_end_cell_from_edge(msg->stream_id, circ, END_STREAM_REASON_EXITPOLICY, NULL); return 0; } - rv = begin_cell_parse(cell, &bcell, &end_reason); + rv = begin_cell_parse(msg, &bcell, &end_reason); if (rv < -1) { return -END_CIRC_REASON_TORPROTOCOL; } else if (rv == -1) { tor_free(bcell.address); - relay_send_end_cell_from_edge(rh.stream_id, circ, end_reason, layer_hint); + relay_send_end_cell_from_edge(msg->stream_id, circ, end_reason, + layer_hint); return 0; } @@ -4044,7 +4034,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) safe_str(channel_describe_peer(or_circ->p_chan)), client_chan ? "on first hop of circuit" : "from unknown relay"); - relay_send_end_cell_from_edge(rh.stream_id, circ, + relay_send_end_cell_from_edge(msg->stream_id, circ, client_chan ? END_STREAM_REASON_TORPROTOCOL : END_STREAM_REASON_MISC, @@ -4053,11 +4043,12 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) return 0; } } - } else if (rh.command == RELAY_COMMAND_BEGIN_DIR) { + } else if (msg->command == RELAY_COMMAND_BEGIN_DIR) { if (!directory_permits_begindir_requests(options) || circ->purpose != CIRCUIT_PURPOSE_OR) { - relay_send_end_cell_from_edge(rh.stream_id, circ, - END_STREAM_REASON_NOTDIRECTORY, layer_hint); + relay_send_end_cell_from_edge(msg->stream_id, circ, + END_STREAM_REASON_NOTDIRECTORY, + layer_hint); return 0; } /* Make sure to get the 'real' address of the previous hop: the @@ -4075,8 +4066,8 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) * isn't "really" a connection here. But we * need to set it to something nonzero. */ } else { - log_warn(LD_BUG, "Got an unexpected command %d", (int)rh.command); - relay_send_end_cell_from_edge(rh.stream_id, circ, + log_warn(LD_BUG, "Got an unexpected command %u", msg->command); + relay_send_end_cell_from_edge(msg->stream_id, circ, END_STREAM_REASON_INTERNAL, layer_hint); return 0; } @@ -4087,7 +4078,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) /* If you don't want IPv4, I can't help. */ if (bcell.flags & BEGIN_FLAG_IPV4_NOT_OK) { tor_free(address); - relay_send_end_cell_from_edge(rh.stream_id, circ, + relay_send_end_cell_from_edge(msg->stream_id, circ, END_STREAM_REASON_EXITPOLICY, layer_hint); return 0; } @@ -4104,7 +4095,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) n_stream->base_.purpose = EXIT_PURPOSE_CONNECT; n_stream->begincell_flags = bcell.flags; - n_stream->stream_id = rh.stream_id; + n_stream->stream_id = msg->stream_id; n_stream->base_.port = port; /* leave n_stream->s at -1, because it's not yet valid */ n_stream->package_window = STREAMWINDOW_START; @@ -4119,7 +4110,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) if (ret == 0) { /* This was a valid cell. Count it as delivered + overhead. */ - circuit_read_valid_data(origin_circ, rh.length); + circuit_read_valid_data(origin_circ, msg->length); } return ret; } @@ -4130,7 +4121,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) /* If we're hibernating or shutting down, we refuse to open new streams. */ if (we_are_hibernating()) { - relay_send_end_cell_from_edge(rh.stream_id, circ, + relay_send_end_cell_from_edge(msg->stream_id, circ, END_STREAM_REASON_HIBERNATING, NULL); connection_free_(TO_CONN(n_stream)); return 0; @@ -4138,7 +4129,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) n_stream->on_circuit = circ; - if (rh.command == RELAY_COMMAND_BEGIN_DIR) { + if (msg->command == RELAY_COMMAND_BEGIN_DIR) { tor_addr_t tmp_addr; tor_assert(or_circ); if (or_circ->p_chan && @@ -4159,8 +4150,8 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) case DOS_STREAM_DEFENSE_REFUSE_STREAM: // we don't use END_STREAM_REASON_RESOURCELIMIT because it would make a // client mark us as non-functional until they get a new consensus. - relay_send_end_cell_from_edge(rh.stream_id, circ, END_STREAM_REASON_MISC, - layer_hint); + relay_send_end_cell_from_edge(msg->stream_id, circ, + END_STREAM_REASON_MISC, layer_hint); connection_free_(TO_CONN(n_stream)); return 0; case DOS_STREAM_DEFENSE_CLOSE_CIRCUIT: @@ -4176,7 +4167,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) connection_exit_connect(n_stream); return 0; case -1: /* resolve failed */ - relay_send_end_cell_from_edge(rh.stream_id, circ, + relay_send_end_cell_from_edge(msg->stream_id, circ, END_STREAM_REASON_RESOLVEFAILED, NULL); /* n_stream got freed. don't touch it. */ break; @@ -4196,16 +4187,12 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) * Else return 0. */ int -connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ) +connection_exit_begin_resolve(const relay_msg_t *msg, or_circuit_t *circ) { edge_connection_t *dummy_conn; - relay_header_t rh; dos_stream_defense_type_t dos_defense_type; assert_circuit_ok(TO_CIRCUIT(circ)); - relay_header_unpack(&rh, cell->payload); - if (rh.length > RELAY_PAYLOAD_SIZE) - return 0; /* Note the RESOLVE stream as seen. */ rep_hist_note_exit_stream(RELAY_COMMAND_RESOLVE); @@ -4218,10 +4205,8 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ) * the housekeeping in dns.c would get way more complicated.) */ dummy_conn = edge_connection_new(CONN_TYPE_EXIT, AF_INET); - dummy_conn->stream_id = rh.stream_id; - dummy_conn->base_.address = tor_strndup( - (char*)cell->payload+RELAY_HEADER_SIZE, - rh.length); + dummy_conn->stream_id = msg->stream_id; + dummy_conn->base_.address = tor_strndup((char *) msg->body, msg->length); dummy_conn->base_.port = 0; dummy_conn->base_.state = EXIT_CONN_STATE_RESOLVEFAILED; dummy_conn->base_.purpose = EXIT_PURPOSE_RESOLVE; diff --git a/src/core/or/connection_edge.h b/src/core/or/connection_edge.h index 1bb0e6d368..6045bffc80 100644 --- a/src/core/or/connection_edge.h +++ b/src/core/or/connection_edge.h @@ -12,6 +12,8 @@ #ifndef TOR_CONNECTION_EDGE_H #define TOR_CONNECTION_EDGE_H +#include "core/or/relay_msg_st.h" + #include "lib/testsupport/testsupport.h" #include "lib/encoding/confline.h" @@ -129,8 +131,8 @@ void connection_ap_handshake_socks_resolved_addr(entry_connection_t *conn, int ttl, time_t expires); -int connection_exit_begin_conn(cell_t *cell, circuit_t *circ); -int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ); +int connection_exit_begin_conn(const relay_msg_t *msg, circuit_t *circ); +int connection_exit_begin_resolve(const relay_msg_t *msg, or_circuit_t *circ); void connection_exit_connect(edge_connection_t *conn); int connection_edge_is_rendezvous_stream(const edge_connection_t *conn); int connection_ap_can_use_exit(const entry_connection_t *conn, @@ -268,8 +270,8 @@ typedef struct begin_cell_t { unsigned is_begindir : 1; } begin_cell_t; -STATIC int begin_cell_parse(const cell_t *cell, begin_cell_t *bcell, - uint8_t *end_reason_out); +STATIC int begin_cell_parse(const relay_msg_t *msg, begin_cell_t *bcell, + uint8_t *end_reason_out); STATIC int connected_cell_format_payload(uint8_t *payload_out, const tor_addr_t *addr, uint32_t ttl); diff --git a/src/core/or/relay.c b/src/core/or/relay.c index b78f8f4e00..8aa74fafbb 100644 --- a/src/core/or/relay.c +++ b/src/core/or/relay.c @@ -45,7 +45,7 @@ * types of relay cells, launching requests or transmitting data as needed. **/ -#include "core/or/relay_cell.h" +#include "lib/log/log.h" #define RELAY_PRIVATE #include "core/or/or.h" #include "feature/client/addressmap.h" @@ -85,6 +85,8 @@ #include "core/or/scheduler.h" #include "feature/hs/hs_metrics.h" #include "feature/stats/rephist.h" +#include "core/or/relay_cell.h" +#include "core/or/relay_msg.h" #include "core/or/cell_st.h" #include "core/or/cell_queue_st.h" @@ -103,8 +105,10 @@ #include "core/or/conflux.h" #include "core/or/conflux_util.h" #include "core/or/conflux_pool.h" +#include "core/or/relay_msg_st.h" -static edge_connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell, +static edge_connection_t *relay_lookup_conn(circuit_t *circ, + const relay_msg_t *msg, cell_direction_t cell_direction, crypt_path_t *layer_hint); @@ -120,11 +124,10 @@ static void adjust_exit_policy_from_exitpolicy_failure(origin_circuit_t *circ, entry_connection_t *conn, node_t *node, const tor_addr_t *addr); -static int connection_edge_process_ordered_relay_cell(cell_t *cell, +static int connection_edge_process_ordered_relay_cell(const relay_msg_t *msg, circuit_t *circ, edge_connection_t *conn, - crypt_path_t *layer_hint, - relay_header_t *rh); + crypt_path_t *layer_hint); static void set_block_state_for_streams(circuit_t *circ, edge_connection_t *stream_list, int block, streamid_t stream_id); @@ -257,37 +260,50 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, if (recognized) { edge_connection_t *conn = NULL; + relay_cell_fmt_t format = relay_msg_get_format(circ, layer_hint); /* Recognized cell, the cell digest has been updated, we'll record it for * the SENDME if need be. */ sendme_record_received_cell_digest(circ, layer_hint); + cell->relay_cell_proto = format; // ????? TODO #41051. + // TODO #41051: This also doesn't need to copy! + relay_msg_t *msg = relay_msg_decode_cell(format, cell); + + if (msg == NULL) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Received undecodable relay cell"); + return -END_CIRC_REASON_TORPROTOCOL; + } + if (circ->purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) { - if (pathbias_check_probe_response(circ, cell) == -1) { - pathbias_count_valid_cells(circ, cell); + if (pathbias_check_probe_response(circ, msg) == -1) { + pathbias_count_valid_cells(circ, msg); } /* We need to drop this cell no matter what to avoid code that expects * a certain purpose (such as the hidserv code). */ + relay_msg_free(msg); return 0; } - conn = relay_lookup_conn(circ, cell, cell_direction, layer_hint); + conn = relay_lookup_conn(circ, msg, cell_direction, layer_hint); if (cell_direction == CELL_DIRECTION_OUT) { ++stats_n_relay_cells_delivered; log_debug(LD_OR,"Sending away from origin."); - reason = connection_edge_process_relay_cell(cell, circ, conn, NULL); + reason = connection_edge_process_relay_cell(msg, circ, conn, NULL); if (reason < 0) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "connection_edge_process_relay_cell (away from origin) " "failed."); + relay_msg_free(msg); return reason; } } if (cell_direction == CELL_DIRECTION_IN) { ++stats_n_relay_cells_delivered; log_debug(LD_OR,"Sending to origin."); - reason = connection_edge_process_relay_cell(cell, circ, conn, + reason = connection_edge_process_relay_cell(msg, circ, conn, layer_hint); if (reason < 0) { /* If a client is trying to connect to unknown hidden service port, @@ -297,9 +313,11 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, log_warn(LD_OR, "connection_edge_process_relay_cell (at origin) failed."); } + relay_msg_free(msg); return reason; } } + relay_msg_free(msg); return 0; } @@ -444,15 +462,12 @@ circuit_package_relay_cell, (cell_t *cell, circuit_t *circ, * attached to circ, return that conn, else return NULL. */ static edge_connection_t * -relay_lookup_conn(circuit_t *circ, cell_t *cell, +relay_lookup_conn(circuit_t *circ, const relay_msg_t *msg, cell_direction_t cell_direction, crypt_path_t *layer_hint) { edge_connection_t *tmpconn; - relay_header_t rh; - relay_header_unpack(&rh, cell->payload); - - if (!rh.stream_id) + if (!msg->stream_id) return NULL; /* IN or OUT cells could have come from either direction, now @@ -461,19 +476,19 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, if (CIRCUIT_IS_ORIGIN(circ)) { for (tmpconn = TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn; tmpconn=tmpconn->next_stream) { - if (rh.stream_id == tmpconn->stream_id && + if (msg->stream_id == tmpconn->stream_id && !tmpconn->base_.marked_for_close && edge_uses_cpath(tmpconn, layer_hint)) { - log_debug(LD_APP,"found conn for stream %d.", rh.stream_id); + log_debug(LD_APP,"found conn for stream %d.", msg->stream_id); return tmpconn; } } } else { for (tmpconn = TO_OR_CIRCUIT(circ)->n_streams; tmpconn; tmpconn=tmpconn->next_stream) { - if (rh.stream_id == tmpconn->stream_id && + if (msg->stream_id == tmpconn->stream_id && !tmpconn->base_.marked_for_close) { - log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id); + log_debug(LD_EXIT,"found conn for stream %d.", msg->stream_id); if (cell_direction == CELL_DIRECTION_OUT || connection_edge_is_rendezvous_stream(tmpconn)) return tmpconn; @@ -481,9 +496,9 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, } for (tmpconn = TO_OR_CIRCUIT(circ)->resolving_streams; tmpconn; tmpconn=tmpconn->next_stream) { - if (rh.stream_id == tmpconn->stream_id && + if (msg->stream_id == tmpconn->stream_id && !tmpconn->base_.marked_for_close) { - log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id); + log_debug(LD_EXIT,"found conn for stream %d.", msg->stream_id); return tmpconn; } } @@ -562,10 +577,6 @@ relay_command_to_string(uint8_t command) } } -/** When padding a cell with randomness, leave this many zeros after the - * payload. */ -#define CELL_PADDING_GAP 4 - /** Make a relay cell out of relay_command and payload, and send * it onto the open circuit circ. stream_id is the ID on * circ for the stream that's sending the relay cell, or 0 if it's a @@ -607,9 +618,28 @@ relay_send_command_from_edge_,(streamid_t stream_id, circuit_t *orig_circ, /* XXXX NM Split this function into a separate versions per circuit type? */ tor_assert(circ); - tor_assert(payload_len <= RELAY_PAYLOAD_SIZE); - memset(&cell, 0, sizeof(cell_t)); + { + relay_cell_fmt_t cell_format = relay_msg_get_format(circ, cpath_layer); + relay_msg_t msg; + tor_assert(payload_len <= + relay_cell_max_payload_size(cell_format, relay_command)); + + msg.relay_cell_proto = cell_format; + msg.command = relay_command; + msg.stream_id = stream_id; + msg.length = payload_len; + // This cast is mildly naughty, but ultimately harmless: + // There is no need to copy the payload here, so long as we don't + // free it. + msg.body = (uint8_t *) payload; + + if (relay_msg_encode_cell(cell_format, &msg, &cell) < 0) { + // This already gave a BUG warning, so no need to log. + return -1; + } + } + cell.command = CELL_RELAY; if (CIRCUIT_IS_ORIGIN(circ)) { tor_assert(cpath_layer); @@ -621,18 +651,6 @@ relay_send_command_from_edge_,(streamid_t stream_id, circuit_t *orig_circ, cell_direction = CELL_DIRECTION_IN; } - memset(&rh, 0, sizeof(rh)); - rh.command = relay_command; - rh.stream_id = stream_id; - rh.length = payload_len; - relay_header_pack(cell.payload, &rh); - - if (payload_len) - memcpy(cell.payload+RELAY_HEADER_SIZE, payload, payload_len); - - /* Add random padding to the cell if we can. */ - relay_cell_pad_payload(&cell, payload_len); - log_debug(LD_OR,"delivering %d cell %s.", relay_command, cell_direction == CELL_DIRECTION_OUT ? "forward" : "backward"); @@ -822,16 +840,16 @@ edge_reason_is_retriable(int reason) */ static int connection_ap_process_end_not_open( - relay_header_t *rh, cell_t *cell, origin_circuit_t *circ, + const relay_msg_t *msg, origin_circuit_t *circ, entry_connection_t *conn, crypt_path_t *layer_hint) { node_t *exitrouter; - int reason = *(cell->payload+RELAY_HEADER_SIZE); + int reason = get_uint8(msg->body); int control_reason; edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn); (void) layer_hint; /* unused */ - if (rh->length > 0) { + if (msg->length > 0) { if (reason == END_STREAM_REASON_TORPROTOCOL || reason == END_STREAM_REASON_DESTROY) { /* Both of these reasons could mean a failed tag @@ -854,9 +872,9 @@ connection_ap_process_end_not_open( } /* This end cell is now valid. */ - circuit_read_valid_data(circ, rh->length); + circuit_read_valid_data(circ, msg->length); - if (rh->length == 0) { + if (msg->length == 0) { reason = END_STREAM_REASON_MISC; } @@ -875,19 +893,17 @@ connection_ap_process_end_not_open( case END_STREAM_REASON_EXITPOLICY: { tor_addr_t addr; tor_addr_make_unspec(&addr); - if (rh->length >= 5) { + if (msg->length >= 5) { int ttl = -1; tor_addr_make_unspec(&addr); - if (rh->length == 5 || rh->length == 9) { - tor_addr_from_ipv4n(&addr, - get_uint32(cell->payload+RELAY_HEADER_SIZE+1)); - if (rh->length == 9) - ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+5)); - } else if (rh->length == 17 || rh->length == 21) { - tor_addr_from_ipv6_bytes(&addr, - (cell->payload+RELAY_HEADER_SIZE+1)); - if (rh->length == 21) - ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+17)); + if (msg->length == 5 || msg->length == 9) { + tor_addr_from_ipv4n(&addr, get_uint32(msg->body + 1)); + if (msg->length == 9) + ttl = (int)ntohl(get_uint32(msg->body + 5)); + } else if (msg->length == 17 || msg->length == 21) { + tor_addr_from_ipv6_bytes(&addr, msg->body + 1); + if (msg->length == 21) + ttl = (int)ntohl(get_uint32(msg->body + 17)); } if (tor_addr_is_null(&addr)) { log_info(LD_APP,"Address '%s' resolved to 0.0.0.0. Closing,", @@ -1009,7 +1025,7 @@ connection_ap_process_end_not_open( log_info(LD_APP, "Edge got end (%s) before we're connected. Marking for close.", - stream_end_reason_to_string(rh->length > 0 ? reason : -1)); + stream_end_reason_to_string(msg->length > 0 ? reason : -1)); circuit_log_path(LOG_INFO,LD_APP,circ); /* need to test because of detach_retriable */ if (!ENTRY_TO_CONN(conn)->marked_for_close) @@ -1082,17 +1098,17 @@ remap_event_helper(entry_connection_t *conn, const tor_addr_t *new_addr) * connection), and that the ttl can be absent (in which case ttl_out * is set to -1). */ STATIC int -connected_cell_parse(const relay_header_t *rh, const cell_t *cell, - tor_addr_t *addr_out, int *ttl_out) +connected_cell_parse(const relay_msg_t *msg, tor_addr_t *addr_out, + int *ttl_out) { uint32_t bytes; - const uint8_t *payload = cell->payload + RELAY_HEADER_SIZE; + const uint8_t *payload = msg->body; tor_addr_make_unspec(addr_out); *ttl_out = -1; - if (rh->length == 0) + if (msg->length == 0) return 0; - if (rh->length < 4) + if (msg->length < 4) return -1; bytes = ntohl(get_uint32(payload)); @@ -1100,13 +1116,13 @@ connected_cell_parse(const relay_header_t *rh, const cell_t *cell, if (bytes != 0) { /* v4 address */ tor_addr_from_ipv4h(addr_out, bytes); - if (rh->length >= 8) { + if (msg->length >= 8) { bytes = ntohl(get_uint32(payload + 4)); if (bytes <= INT32_MAX) *ttl_out = bytes; } } else { - if (rh->length < 25) /* 4 bytes of 0s, 1 addr, 16 ipv4, 4 ttl. */ + if (msg->length < 25) /* 4 bytes of 0s, 1 addr, 16 ipv4, 4 ttl. */ return -1; if (get_uint8(payload + 4) != 6) return -1; @@ -1134,8 +1150,8 @@ address_ttl_free_(address_ttl_t *addr) * one of 0, RESOLVED_TYPE_ERROR, or RESOLVED_TYPE_ERROR_TRANSIENT, and * return 0. */ STATIC int -resolved_cell_parse(const cell_t *cell, const relay_header_t *rh, - smartlist_t *addresses_out, int *errcode_out) +resolved_cell_parse(const relay_msg_t *msg, smartlist_t *addresses_out, + int *errcode_out) { const uint8_t *cp; uint8_t answer_type; @@ -1145,21 +1161,20 @@ resolved_cell_parse(const cell_t *cell, const relay_header_t *rh, int errcode = 0; smartlist_t *addrs; - tor_assert(cell); - tor_assert(rh); + tor_assert(msg); tor_assert(addresses_out); tor_assert(errcode_out); *errcode_out = 0; - if (rh->length > RELAY_PAYLOAD_SIZE) + if (msg->length > RELAY_PAYLOAD_SIZE) return -1; addrs = smartlist_new(); - cp = cell->payload + RELAY_HEADER_SIZE; + cp = msg->body; - remaining = rh->length; + remaining = msg->length; while (remaining) { const uint8_t *cp_orig = cp; if (remaining < 2) @@ -1306,8 +1321,7 @@ connection_ap_handshake_socks_got_resolved_cell(entry_connection_t *conn, * stream. */ STATIC int connection_edge_process_resolved_cell(edge_connection_t *conn, - const cell_t *cell, - const relay_header_t *rh) + const relay_msg_t *msg) { entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn); smartlist_t *resolved_addresses = NULL; @@ -1321,7 +1335,7 @@ connection_edge_process_resolved_cell(edge_connection_t *conn, tor_assert(SOCKS_COMMAND_IS_RESOLVE(entry_conn->socks_request->command)); resolved_addresses = smartlist_new(); - if (resolved_cell_parse(cell, rh, resolved_addresses, &errcode)) { + if (resolved_cell_parse(msg, resolved_addresses, &errcode)) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Dropping malformed 'resolved' cell"); connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TORPROTOCOL); @@ -1354,7 +1368,7 @@ connection_edge_process_resolved_cell(edge_connection_t *conn, /* This is valid data at this point. Count it */ if (conn->on_circuit && CIRCUIT_IS_ORIGIN(conn->on_circuit)) { circuit_read_valid_data(TO_ORIGIN_CIRCUIT(conn->on_circuit), - rh->length); + msg->length); } connection_ap_handshake_socks_got_resolved_cell(entry_conn, @@ -1381,27 +1395,26 @@ connection_edge_process_resolved_cell(edge_connection_t *conn, */ static int connection_edge_process_relay_cell_not_open( - relay_header_t *rh, cell_t *cell, circuit_t *circ, + const relay_msg_t *msg, circuit_t *circ, edge_connection_t *conn, crypt_path_t *layer_hint) { - if (rh->command == RELAY_COMMAND_END) { + if (msg->command == RELAY_COMMAND_END) { if (CIRCUIT_IS_ORIGIN(circ) && conn->base_.type == CONN_TYPE_AP) { - return connection_ap_process_end_not_open(rh, cell, + return connection_ap_process_end_not_open(msg, TO_ORIGIN_CIRCUIT(circ), EDGE_TO_ENTRY_CONN(conn), layer_hint); } else { /* we just got an 'end', don't need to send one */ conn->edge_has_sent_end = 1; - conn->end_reason = *(cell->payload+RELAY_HEADER_SIZE) | - END_STREAM_REASON_FLAG_REMOTE; + conn->end_reason = get_uint8(msg->body) | END_STREAM_REASON_FLAG_REMOTE; connection_mark_for_close(TO_CONN(conn)); return 0; } } if (conn->base_.type == CONN_TYPE_AP && - rh->command == RELAY_COMMAND_CONNECTED) { + msg->command == RELAY_COMMAND_CONNECTED) { tor_addr_t addr; int ttl; entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn); @@ -1416,9 +1429,9 @@ connection_edge_process_relay_cell_not_open( log_info(LD_APP,"'connected' received for circid %u streamid %d " "after %d seconds.", (unsigned)circ->n_circ_id, - rh->stream_id, + msg->stream_id, (int)(time(NULL) - conn->base_.timestamp_last_read_allowed)); - if (connected_cell_parse(rh, cell, &addr, &ttl) < 0) { + if (connected_cell_parse(msg, &addr, &ttl) < 0) { log_fn(LOG_PROTOCOL_WARN, LD_APP, "Got a badly formatted connected cell. Closing."); connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL); @@ -1496,7 +1509,7 @@ connection_edge_process_relay_cell_not_open( } /* This is valid data at this point. Count it */ - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh->length); + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); /* handle anything that might have queued */ if (connection_edge_package_raw_inbuf(conn, 1, NULL) < 0) { @@ -1507,13 +1520,13 @@ connection_edge_process_relay_cell_not_open( return 0; } if (conn->base_.type == CONN_TYPE_AP && - rh->command == RELAY_COMMAND_RESOLVED) { - return connection_edge_process_resolved_cell(conn, cell, rh); + msg->command == RELAY_COMMAND_RESOLVED) { + return connection_edge_process_resolved_cell(conn, msg); } log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Got an unexpected relay command %d, in state %d (%s). Dropping.", - rh->command, conn->base_.state, + msg->command, conn->base_.state, conn_state_to_string(conn->base_.type, conn->base_.state)); return 0; /* for forward compatibility, don't kill the circuit */ // connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL); @@ -1529,19 +1542,18 @@ connection_edge_process_relay_cell_not_open( * Return 0 if everything went well or a negative value representing a circuit * end reason on error for which the caller is responsible for closing it. */ static int -process_sendme_cell(const relay_header_t *rh, const cell_t *cell, - circuit_t *circ, edge_connection_t *conn, - crypt_path_t *layer_hint, int domain) +process_sendme_cell(const relay_msg_t *msg, circuit_t *circ, + edge_connection_t *conn, crypt_path_t *layer_hint, + int domain) { int ret; - tor_assert(rh); + tor_assert(msg); - if (!rh->stream_id) { + if (!msg->stream_id) { /* Circuit level SENDME cell. */ - ret = sendme_process_circuit_level(layer_hint, circ, - cell->payload + RELAY_HEADER_SIZE, - rh->length); + ret = sendme_process_circuit_level(layer_hint, circ, msg->body, + msg->length); if (ret < 0) { return ret; } @@ -1557,22 +1569,22 @@ process_sendme_cell(const relay_header_t *rh, const cell_t *cell, if (CIRCUIT_IS_ORIGIN(circ)) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); if (connection_half_edge_is_valid_sendme(ocirc->half_streams, - rh->stream_id)) { - circuit_read_valid_data(ocirc, rh->length); + msg->stream_id)) { + circuit_read_valid_data(ocirc, msg->length); log_info(domain, "Sendme cell on circ %u valid on half-closed " "stream id %d", - ocirc->global_identifier, rh->stream_id); + ocirc->global_identifier, msg->stream_id); } } log_info(domain, "SENDME cell dropped, unknown stream (streamid %d).", - rh->stream_id); + msg->stream_id); return 0; } /* Stream level SENDME cell. */ // TODO: Turn this off for cc_alg=1,2,3; use XON/XOFF instead - ret = sendme_process_stream_level(conn, circ, rh->length); + ret = sendme_process_stream_level(conn, circ, msg->length); if (ret < 0) { /* Means we need to close the circuit with reason ret. */ return ret; @@ -1606,35 +1618,35 @@ process_sendme_cell(const relay_header_t *rh, const cell_t *cell, * parent function. */ STATIC int -handle_relay_cell_command(cell_t *cell, circuit_t *circ, - edge_connection_t *conn, crypt_path_t *layer_hint, - relay_header_t *rh, int optimistic_data) +handle_relay_msg(const relay_msg_t *msg, circuit_t *circ, + edge_connection_t *conn, crypt_path_t *layer_hint, + int optimistic_data) { unsigned domain = layer_hint?LD_APP:LD_EXIT; int reason; - tor_assert(rh); + tor_assert(msg); /* First pass the cell to the circuit padding subsystem, in case it's a * padding cell or circuit that should be handled there. */ - if (circpad_check_received_cell(cell, circ, layer_hint, rh) == 0) { + if (circpad_check_received_cell(msg, circ, layer_hint) == 0) { log_debug(domain, "Cell handled as circuit padding"); return 0; } /* Now handle all the other commands */ - switch (rh->command) { + switch (msg->command) { case RELAY_COMMAND_CONFLUX_LINK: - conflux_process_link(circ, cell, rh->length); + conflux_process_link(circ, msg); return 0; case RELAY_COMMAND_CONFLUX_LINKED: - conflux_process_linked(circ, layer_hint, cell, rh->length); + conflux_process_linked(circ, layer_hint, msg); return 0; case RELAY_COMMAND_CONFLUX_LINKED_ACK: conflux_process_linked_ack(circ); return 0; case RELAY_COMMAND_CONFLUX_SWITCH: - return conflux_process_switch_command(circ, layer_hint, cell, rh); + return conflux_process_switch_command(circ, layer_hint, msg); case RELAY_COMMAND_BEGIN: case RELAY_COMMAND_BEGIN_DIR: if (layer_hint && @@ -1655,7 +1667,7 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, "Begin cell for known stream. Dropping."); return 0; } - if (rh->command == RELAY_COMMAND_BEGIN_DIR && + if (msg->command == RELAY_COMMAND_BEGIN_DIR && circ->purpose != CIRCUIT_PURPOSE_S_REND_JOINED) { /* Assign this circuit and its app-ward OR connection a unique ID, * so that we can measure download times. The local edge and dir @@ -1665,11 +1677,11 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, circ->dirreq_id = ++next_id; TO_OR_CIRCUIT(circ)->p_chan->dirreq_id = circ->dirreq_id; } - return connection_exit_begin_conn(cell, circ); + return connection_exit_begin_conn(msg, circ); case RELAY_COMMAND_DATA: ++stats_n_data_cells_received; - if (rh->stream_id == 0) { + if (msg->stream_id == 0) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Relay data cell with zero " "stream_id. Dropping."); return 0; @@ -1677,16 +1689,16 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, if (CIRCUIT_IS_ORIGIN(circ)) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); if (connection_half_edge_is_valid_data(ocirc->half_streams, - rh->stream_id)) { - circuit_read_valid_data(ocirc, rh->length); + msg->stream_id)) { + circuit_read_valid_data(ocirc, msg->length); log_info(domain, "data cell on circ %u valid on half-closed " - "stream id %d", ocirc->global_identifier, rh->stream_id); + "stream id %d", ocirc->global_identifier, msg->stream_id); } } log_info(domain,"data cell dropped, unknown stream (streamid %d).", - rh->stream_id); + msg->stream_id); return 0; } @@ -1700,20 +1712,19 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, return -END_CIRC_REASON_TORPROTOCOL; } /* Total all valid application bytes delivered */ - if (CIRCUIT_IS_ORIGIN(circ) && rh->length > 0) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh->length); + if (CIRCUIT_IS_ORIGIN(circ) && msg->length > 0) { + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } /* For onion service connection, update the metrics. */ if (conn->hs_ident) { hs_metrics_app_write_bytes(&conn->hs_ident->identity_pk, conn->hs_ident->orig_virtual_port, - rh->length); + msg->length); } - stats_n_data_bytes_received += rh->length; - connection_buf_add((char*)(cell->payload + RELAY_HEADER_SIZE), - rh->length, TO_CONN(conn)); + stats_n_data_bytes_received += msg->length; + connection_buf_add((char*) msg->body, msg->length, TO_CONN(conn)); #ifdef MEASUREMENTS_21206 /* Count number of RELAY_DATA cells received on a linked directory @@ -1739,16 +1750,16 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); if (relay_crypt_from_last_hop(ocirc, layer_hint) && connection_half_edge_is_valid_data(ocirc->half_streams, - rh->stream_id)) { - circuit_read_valid_data(ocirc, rh->length); + msg->stream_id)) { + circuit_read_valid_data(ocirc, msg->length); } } return 0; } - if (circuit_process_stream_xoff(conn, layer_hint, cell)) { + if (circuit_process_stream_xoff(conn, layer_hint)) { if (CIRCUIT_IS_ORIGIN(circ)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh->length); + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } } return 0; @@ -1758,35 +1769,34 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); if (relay_crypt_from_last_hop(ocirc, layer_hint) && connection_half_edge_is_valid_data(ocirc->half_streams, - rh->stream_id)) { - circuit_read_valid_data(ocirc, rh->length); + msg->stream_id)) { + circuit_read_valid_data(ocirc, msg->length); } } return 0; } - if (circuit_process_stream_xon(conn, layer_hint, cell)) { + if (circuit_process_stream_xon(conn, layer_hint, msg)) { if (CIRCUIT_IS_ORIGIN(circ)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh->length); + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } } return 0; case RELAY_COMMAND_END: - reason = rh->length > 0 ? - get_uint8(cell->payload+RELAY_HEADER_SIZE) : END_STREAM_REASON_MISC; + reason = msg->length > 0 ? get_uint8(msg->body) : END_STREAM_REASON_MISC; if (!conn) { if (CIRCUIT_IS_ORIGIN(circ)) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); if (relay_crypt_from_last_hop(ocirc, layer_hint) && connection_half_edge_is_valid_end(ocirc->half_streams, - rh->stream_id)) { + msg->stream_id)) { - circuit_read_valid_data(ocirc, rh->length); + circuit_read_valid_data(ocirc, msg->length); log_info(domain, "end cell (%s) on circ %u valid on half-closed " "stream id %d", stream_end_reason_to_string(reason), - ocirc->global_identifier, rh->stream_id); + ocirc->global_identifier, msg->stream_id); return 0; } } @@ -1818,7 +1828,7 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, /* Total all valid application bytes delivered */ if (CIRCUIT_IS_ORIGIN(circ)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh->length); + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } } return 0; @@ -1826,18 +1836,18 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, case RELAY_COMMAND_EXTEND2: { static uint64_t total_n_extend=0, total_nonearly=0; total_n_extend++; - if (rh->stream_id) { + if (msg->stream_id) { log_fn(LOG_PROTOCOL_WARN, domain, "'extend' cell received for non-zero stream. Dropping."); return 0; } - if (cell->command != CELL_RELAY_EARLY && + if (!msg->is_relay_early && !networkstatus_get_param(NULL,"AllowNonearlyExtend",0,0,1)) { #define EARLY_WARNING_INTERVAL 3600 static ratelim_t early_warning_limit = RATELIM_INIT(EARLY_WARNING_INTERVAL); char *m; - if (cell->command == CELL_RELAY) { + if (!msg->is_relay_early) { ++total_nonearly; if ((m = rate_limit_log(&early_warning_limit, approx_time()))) { double percentage = ((double)total_nonearly)/total_n_extend; @@ -1851,11 +1861,11 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, } else { log_fn(LOG_WARN, domain, "EXTEND cell received, in a cell with type %d! Dropping.", - cell->command); + msg->command); } return 0; } - return circuit_extend(cell, circ); + return circuit_extend(msg, circ); } case RELAY_COMMAND_EXTENDED: case RELAY_COMMAND_EXTENDED2: @@ -1867,9 +1877,8 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, log_debug(domain,"Got an extended cell! Yay."); { extended_cell_t extended_cell; - if (extended_cell_parse(&extended_cell, rh->command, - (const uint8_t*)cell->payload+RELAY_HEADER_SIZE, - rh->length)<0) { + if (extended_cell_parse(&extended_cell, msg->command, + msg->body, msg->length) < 0) { log_warn(LD_PROTOCOL, "Can't parse EXTENDED cell; killing circuit."); return -END_CIRC_REASON_TORPROTOCOL; @@ -1887,7 +1896,7 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, } /* Total all valid bytes delivered. */ if (CIRCUIT_IS_ORIGIN(circ)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh->length); + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } return 0; case RELAY_COMMAND_TRUNCATE: @@ -1905,7 +1914,7 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, circuit_set_state(circ, CIRCUIT_STATE_OPEN); } if (circ->n_chan) { - uint8_t trunc_reason = get_uint8(cell->payload + RELAY_HEADER_SIZE); + uint8_t trunc_reason = get_uint8(msg->body); circuit_synchronize_written_or_bandwidth(circ, CIRCUIT_N_CHAN); circuit_clear_cell_queue(circ, circ->n_chan); channel_send_destroy(circ->n_circ_id, circ->n_chan, @@ -1930,11 +1939,9 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, /* Count the truncated as valid, for completeness. The * circuit is being torn down anyway, though. */ if (CIRCUIT_IS_ORIGIN(circ)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), - rh->length); + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } - circuit_truncated(TO_ORIGIN_CIRCUIT(circ), - get_uint8(cell->payload + RELAY_HEADER_SIZE)); + circuit_truncated(TO_ORIGIN_CIRCUIT(circ), get_uint8(msg->body)); return 0; case RELAY_COMMAND_CONNECTED: if (conn) { @@ -1946,11 +1953,11 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, if (CIRCUIT_IS_ORIGIN(circ)) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); if (connection_half_edge_is_valid_connected(ocirc->half_streams, - rh->stream_id)) { - circuit_read_valid_data(ocirc, rh->length); + msg->stream_id)) { + circuit_read_valid_data(ocirc, msg->length); log_info(domain, "connected cell on circ %u valid on half-closed " - "stream id %d", ocirc->global_identifier, rh->stream_id); + "stream id %d", ocirc->global_identifier, msg->stream_id); return 0; } } @@ -1958,10 +1965,10 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, log_info(domain, "'connected' received on circid %u for streamid %d, " "no conn attached anymore. Ignoring.", - (unsigned)circ->n_circ_id, rh->stream_id); + (unsigned)circ->n_circ_id, msg->stream_id); return 0; case RELAY_COMMAND_SENDME: - return process_sendme_cell(rh, cell, circ, conn, layer_hint, domain); + return process_sendme_cell(msg, circ, conn, layer_hint, domain); case RELAY_COMMAND_RESOLVE: if (layer_hint) { log_fn(LOG_PROTOCOL_WARN, LD_APP, @@ -1977,7 +1984,7 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, circ->purpose); return 0; } - return connection_exit_begin_resolve(cell, TO_OR_CIRCUIT(circ)); + return connection_exit_begin_resolve(msg, TO_OR_CIRCUIT(circ)); case RELAY_COMMAND_RESOLVED: if (conn) { log_fn(LOG_PROTOCOL_WARN, domain, @@ -1989,11 +1996,11 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); if (relay_crypt_from_last_hop(ocirc, layer_hint) && connection_half_edge_is_valid_resolved(ocirc->half_streams, - rh->stream_id)) { - circuit_read_valid_data(ocirc, rh->length); + msg->stream_id)) { + circuit_read_valid_data(ocirc, msg->length); log_info(domain, "resolved cell on circ %u valid on half-closed " - "stream id %d", ocirc->global_identifier, rh->stream_id); + "stream id %d", ocirc->global_identifier, msg->stream_id); return 0; } } @@ -2011,14 +2018,13 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, case RELAY_COMMAND_INTRO_ESTABLISHED: case RELAY_COMMAND_RENDEZVOUS_ESTABLISHED: rend_process_relay_cell(circ, layer_hint, - rh->command, rh->length, - cell->payload+RELAY_HEADER_SIZE); + msg->command, msg->length, msg->body); return 0; } log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Received unknown relay command %d. Perhaps the other side is using " "a newer version of Tor? Dropping.", - rh->command); + msg->command); return 0; /* for forward compatibility, don't kill the circuit */ } @@ -2032,39 +2038,31 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, * Return -reason if you want to warn and tear down the circuit, else 0. */ STATIC int -connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, +connection_edge_process_relay_cell(const relay_msg_t *msg, circuit_t *circ, edge_connection_t *conn, crypt_path_t *layer_hint) { static int num_seen=0; - relay_header_t rh; unsigned domain = layer_hint?LD_APP:LD_EXIT; - tor_assert(cell); + tor_assert(msg); tor_assert(circ); - relay_header_unpack(&rh, cell->payload); // log_fn(LOG_DEBUG,"command %d stream %d", rh.command, rh.stream_id); num_seen++; log_debug(domain, "Now seen %d relay cells here (command %d, stream %d).", - num_seen, rh.command, rh.stream_id); - - if (rh.length > RELAY_PAYLOAD_SIZE) { - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Relay cell length field too long. Closing circuit."); - return - END_CIRC_REASON_TORPROTOCOL; - } + num_seen, msg->command, msg->stream_id); - if (rh.stream_id == 0) { - switch (rh.command) { + if (msg->stream_id == 0) { + switch (msg->command) { case RELAY_COMMAND_BEGIN: case RELAY_COMMAND_CONNECTED: case RELAY_COMMAND_END: case RELAY_COMMAND_RESOLVE: case RELAY_COMMAND_RESOLVED: case RELAY_COMMAND_BEGIN_DIR: - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Relay command %d with zero " - "stream_id. Dropping.", (int)rh.command); + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Relay command %u with zero " + "stream_id. Dropping.", msg->command); return 0; default: ; @@ -2074,7 +2072,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, /* Regardless of conflux or not, we always decide to send a SENDME * for RELAY_DATA immediately */ - if (rh.command == RELAY_COMMAND_DATA) { + if (msg->command == RELAY_COMMAND_DATA) { /* Update our circuit-level deliver window that we received a DATA cell. * If the deliver window goes below 0, we end the circuit and stream due * to a protocol failure. */ @@ -2098,37 +2096,39 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, * queues, and if doing so results in ordered cells to deliver, we * dequeue and process those in-order until there are no more. */ - if (!circ->conflux || !conflux_should_multiplex(rh.command)) { - return connection_edge_process_ordered_relay_cell(cell, circ, conn, - layer_hint, &rh); + if (!circ->conflux || !conflux_should_multiplex(msg->command)) { + return connection_edge_process_ordered_relay_cell(msg, circ, conn, + layer_hint); } else { // If conflux says this cell is in-order, then begin processing // cells from queue until there are none. Otherwise, we do nothing // until further cells arrive. - if (conflux_process_cell(circ->conflux, circ, layer_hint, cell)) { - conflux_cell_t *c_cell = NULL; + if (conflux_process_relay_msg(circ->conflux, circ, layer_hint, + (relay_msg_t *) msg)) { + conflux_msg_t *c_msg = NULL; int ret = 0; /* First, process this cell */ - if ((ret = connection_edge_process_ordered_relay_cell(cell, circ, conn, - layer_hint, &rh)) < 0) { + if ((ret = connection_edge_process_ordered_relay_cell(msg, circ, + conn, + layer_hint) < 0)) { return ret; } /* Now, check queue for more */ - while ((c_cell = conflux_dequeue_cell(circ->conflux))) { - relay_header_unpack(&rh, c_cell->cell.payload); - conn = relay_lookup_conn(circ, &c_cell->cell, CELL_DIRECTION_OUT, + while ((c_msg = conflux_dequeue_relay_msg(circ->conflux))) { + conn = relay_lookup_conn(circ, c_msg->msg, CELL_DIRECTION_OUT, layer_hint); - if ((ret = connection_edge_process_ordered_relay_cell(&c_cell->cell, - circ, conn, layer_hint, - &rh)) < 0) { + if ((ret = + connection_edge_process_ordered_relay_cell(c_msg->msg, circ, + conn, + layer_hint)) < 0) { /* Negative return value is a fatal error. Return early and tear down * circuit */ - tor_free(c_cell); + conflux_relay_msg_free(c_msg); return ret; } - tor_free(c_cell); + conflux_relay_msg_free(c_msg); } } } @@ -2140,17 +2140,17 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, * Helper function to process a relay cell that is in the proper order * for processing right now. */ static int -connection_edge_process_ordered_relay_cell(cell_t *cell, circuit_t *circ, +connection_edge_process_ordered_relay_cell(const relay_msg_t *msg, + circuit_t *circ, edge_connection_t *conn, - crypt_path_t *layer_hint, - relay_header_t *rh) + crypt_path_t *layer_hint) { int optimistic_data = 0; /* Set to 1 if we receive data on a stream * that's in the EXIT_CONN_STATE_RESOLVING * or EXIT_CONN_STATE_CONNECTING states. */ /* Tell circpad that we've received a recognized cell */ - circpad_deliver_recognized_relay_cell_events(circ, rh->command, layer_hint); + circpad_deliver_recognized_relay_cell_events(circ, msg->command, layer_hint); /* either conn is NULL, in which case we've got a control cell, or else * conn points to the recognized stream. */ @@ -2158,22 +2158,21 @@ connection_edge_process_ordered_relay_cell(cell_t *cell, circuit_t *circ, if (conn->base_.type == CONN_TYPE_EXIT && (conn->base_.state == EXIT_CONN_STATE_CONNECTING || conn->base_.state == EXIT_CONN_STATE_RESOLVING) && - rh->command == RELAY_COMMAND_DATA) { + msg->command == RELAY_COMMAND_DATA) { /* Allow DATA cells to be delivered to an exit node in state * EXIT_CONN_STATE_CONNECTING or EXIT_CONN_STATE_RESOLVING. * This speeds up HTTP, for example. */ optimistic_data = 1; - } else if (rh->stream_id == 0 && rh->command == RELAY_COMMAND_DATA) { + } else if (msg->stream_id == 0 && msg->command == RELAY_COMMAND_DATA) { log_warn(LD_BUG, "Somehow I had a connection that matched a " "data cell with stream ID 0."); } else { return connection_edge_process_relay_cell_not_open( - rh, cell, circ, conn, layer_hint); + msg, circ, conn, layer_hint); } } - return handle_relay_cell_command(cell, circ, conn, layer_hint, - rh, optimistic_data); + return handle_relay_msg(msg, circ, conn, layer_hint, optimistic_data); } /** How many relay_data cells have we built, ever? */ @@ -2203,13 +2202,6 @@ circuit_reset_sendme_randomness(circuit_t *circ) crypto_fast_rng_get_uint(get_thread_fast_rng(), CIRCWINDOW_INCREMENT / 2); } -/** - * Any relay data payload containing fewer than this many real bytes is - * considered to have enough randomness to. - **/ -#define RELAY_PAYLOAD_LENGTH_FOR_RANDOM_SENDMES \ - (RELAY_PAYLOAD_SIZE - CELL_PADDING_GAP - 16) - /** * Helper. Return the number of bytes that should be put into a cell from a * given edge connection on which n_available bytes are available. @@ -2217,7 +2209,8 @@ circuit_reset_sendme_randomness(circuit_t *circ) STATIC size_t connection_edge_get_inbuf_bytes_to_package(size_t n_available, int package_partial, - circuit_t *on_circuit) + circuit_t *on_circuit, + crypt_path_t *cpath) { if (!n_available) return 0; @@ -2227,12 +2220,18 @@ connection_edge_get_inbuf_bytes_to_package(size_t n_available, (on_circuit->send_randomness_after_n_cells == 0) && (! on_circuit->have_sent_sufficiently_random_cell); - /* At most how much would we like to send in this cell? */ - size_t target_length; + relay_cell_fmt_t cell_format = relay_msg_get_format(on_circuit, cpath); + size_t target_length = + relay_cell_max_payload_size(cell_format, RELAY_COMMAND_DATA); + +#define RELAY_CELL_PADDING_GAP 4 + + /* Any relay data payload containing fewer than this many real bytes is + * considered to have enough randomness to. */ + size_t target_length_with_random = target_length - + RELAY_CELL_PADDING_GAP - 16; if (force_random_bytes) { - target_length = RELAY_PAYLOAD_LENGTH_FOR_RANDOM_SENDMES; - } else { - target_length = RELAY_PAYLOAD_SIZE; + target_length = target_length_with_random; } /* Decide how many bytes we will actually put into this cell. */ @@ -2249,7 +2248,7 @@ connection_edge_get_inbuf_bytes_to_package(size_t n_available, /* If we reach this point, we will be definitely sending the cell. */ tor_assert_nonfatal(package_length > 0); - if (package_length <= RELAY_PAYLOAD_LENGTH_FOR_RANDOM_SENDMES) { + if (package_length <= target_length_with_random) { /* This cell will have enough randomness in the padding to make a future * sendme cell unpredictable. */ on_circuit->have_sent_sufficiently_random_cell = 1; @@ -2341,7 +2340,8 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial, } length = connection_edge_get_inbuf_bytes_to_package(bytes_to_process, - package_partial, circ); + package_partial, circ, + cpath_layer); if (!length) return 0; diff --git a/src/core/or/relay.h b/src/core/or/relay.h index 492fee9c37..a63a465bf2 100644 --- a/src/core/or/relay.h +++ b/src/core/or/relay.h @@ -12,6 +12,8 @@ #ifndef TOR_RELAY_H #define TOR_RELAY_H +#include "core/or/relay_msg_st.h" + extern uint64_t stats_n_relay_cells_relayed; extern uint64_t stats_n_relay_cells_delivered; extern uint64_t stats_n_circ_max_cell_reached; @@ -110,12 +112,12 @@ uint8_t packed_cell_get_command(const packed_cell_t *cell, int wide_circ_ids); #ifdef RELAY_PRIVATE STATIC int -handle_relay_cell_command(cell_t *cell, circuit_t *circ, - edge_connection_t *conn, crypt_path_t *layer_hint, - relay_header_t *rh, int optimistic_data); +handle_relay_msg(const relay_msg_t *msg, circuit_t *circ, + edge_connection_t *conn, crypt_path_t *layer_hint, + int optimistic_data); -STATIC int connected_cell_parse(const relay_header_t *rh, const cell_t *cell, - tor_addr_t *addr_out, int *ttl_out); +STATIC int connected_cell_parse(const relay_msg_t *msg, tor_addr_t *addr_out, + int *ttl_out); /** An address-and-ttl tuple as yielded by resolved_cell_parse */ typedef struct address_ttl_t { tor_addr_t addr; @@ -125,21 +127,22 @@ typedef struct address_ttl_t { STATIC void address_ttl_free_(address_ttl_t *addr); #define address_ttl_free(addr) \ FREE_AND_NULL(address_ttl_t, address_ttl_free_, (addr)) -STATIC int resolved_cell_parse(const cell_t *cell, const relay_header_t *rh, +STATIC int resolved_cell_parse(const relay_msg_t *msg, smartlist_t *addresses_out, int *errcode_out); STATIC int connection_edge_process_resolved_cell(edge_connection_t *conn, - const cell_t *cell, - const relay_header_t *rh); + const relay_msg_t *msg); STATIC packed_cell_t *packed_cell_new(void); STATIC packed_cell_t *cell_queue_pop(cell_queue_t *queue); STATIC destroy_cell_t *destroy_cell_queue_pop(destroy_cell_queue_t *queue); STATIC int cell_queues_check_size(void); -STATIC int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, - edge_connection_t *conn, - crypt_path_t *layer_hint); +STATIC int connection_edge_process_relay_cell(const relay_msg_t *msg, + circuit_t *circ, + edge_connection_t *conn, + crypt_path_t *layer_hint); STATIC size_t connection_edge_get_inbuf_bytes_to_package(size_t n_available, int package_partial, - circuit_t *on_circuit); + circuit_t *on_circuit, + crypt_path_t *cpath); #endif /* defined(RELAY_PRIVATE) */ diff --git a/src/core/or/relay_msg.h b/src/core/or/relay_msg.h index b52123ab68..cec56d6b28 100644 --- a/src/core/or/relay_msg.h +++ b/src/core/or/relay_msg.h @@ -35,6 +35,9 @@ relay_msg_t *relay_msg_decode_cell( relay_cell_fmt_t relay_msg_get_format(const circuit_t *circ, const crypt_path_t *cpath); +/* Helpers. */ +void relay_msg_free_messages(smartlist_t *messages); + #ifdef RELAY_MSG_PRIVATE #endif /* RELAY_MSG_PRIVATE */ diff --git a/src/feature/client/circpathbias.c b/src/feature/client/circpathbias.c index 144a53c972..c7b42ecfae 100644 --- a/src/feature/client/circpathbias.c +++ b/src/feature/client/circpathbias.c @@ -34,10 +34,11 @@ #include "feature/client/entrynodes.h" #include "feature/nodelist/networkstatus.h" #include "core/or/relay.h" +#include "core/or/relay_cell.h" +#include "core/or/relay_msg.h" #include "lib/math/fp.h" #include "lib/math/laplace.h" -#include "core/or/cell_st.h" #include "core/or/cpath_build_state_st.h" #include "core/or/crypt_path_st.h" #include "core/or/extend_info_st.h" @@ -903,41 +904,37 @@ pathbias_send_usable_probe(circuit_t *circ) * If the response is valid, return 0. Otherwise return < 0. */ int -pathbias_check_probe_response(circuit_t *circ, const cell_t *cell) +pathbias_check_probe_response(circuit_t *circ, const relay_msg_t *msg) { /* Based on connection_edge_process_relay_cell() */ - relay_header_t rh; int reason; uint32_t ipv4_host; origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); - tor_assert(cell); + tor_assert(msg); tor_assert(ocirc); tor_assert(circ->purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING); - relay_header_unpack(&rh, cell->payload); + reason = msg->length > 0 ? get_uint8(msg->body) : END_STREAM_REASON_MISC; - reason = rh.length > 0 ? - get_uint8(cell->payload+RELAY_HEADER_SIZE) : END_STREAM_REASON_MISC; - - if (rh.command == RELAY_COMMAND_END && + if (msg->command == RELAY_COMMAND_END && reason == END_STREAM_REASON_EXITPOLICY && - ocirc->pathbias_probe_id == rh.stream_id) { + ocirc->pathbias_probe_id == msg->stream_id) { /* Check length+extract host: It is in network order after the reason code. * See connection_edge_end(). */ - if (rh.length < 9) { /* reason+ipv4+dns_ttl */ + if (msg->length < 9) { /* reason+ipv4+dns_ttl */ log_notice(LD_PROTOCOL, - "Short path bias probe response length field (%d).", rh.length); + "Short path bias probe response length field (%d).", msg->length); return - END_CIRC_REASON_TORPROTOCOL; } - ipv4_host = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+1)); + ipv4_host = ntohl(get_uint32(msg->body + 1)); /* Check nonce */ if (ipv4_host == ocirc->pathbias_probe_nonce) { pathbias_mark_use_success(ocirc); - circuit_read_valid_data(ocirc, rh.length); + circuit_read_valid_data(ocirc, msg->length); circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); log_info(LD_CIRC, "Got valid path bias probe back for circ %d, stream %d.", @@ -954,7 +951,7 @@ pathbias_check_probe_response(circuit_t *circ, const cell_t *cell) log_info(LD_CIRC, "Got another cell back back on pathbias probe circuit %d: " "Command: %d, Reason: %d, Stream-id: %d", - ocirc->global_identifier, rh.command, reason, rh.stream_id); + ocirc->global_identifier, msg->command, reason, msg->stream_id); return -1; } @@ -963,58 +960,54 @@ pathbias_check_probe_response(circuit_t *circ, const cell_t *cell) * and if so, count it as valid. */ void -pathbias_count_valid_cells(circuit_t *circ, const cell_t *cell) +pathbias_count_valid_cells(circuit_t *circ, const relay_msg_t *msg) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); - relay_header_t rh; - - relay_header_unpack(&rh, cell->payload); /* Check to see if this is a cell from a previous connection, * or is a request to close the circuit. */ - switch (rh.command) { + switch (msg->command) { case RELAY_COMMAND_TRUNCATED: /* Truncated cells can arrive on path bias circs. When they do, * just process them. This closes the circ, but it was junk anyway. * No reason to wait for the probe. */ - circuit_read_valid_data(ocirc, rh.length); - circuit_truncated(TO_ORIGIN_CIRCUIT(circ), - get_uint8(cell->payload + RELAY_HEADER_SIZE)); + circuit_read_valid_data(ocirc, msg->length); + circuit_truncated(TO_ORIGIN_CIRCUIT(circ), get_uint8(msg->body)); break; case RELAY_COMMAND_END: if (connection_half_edge_is_valid_end(ocirc->half_streams, - rh.stream_id)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh.length); + msg->stream_id)) { + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } break; case RELAY_COMMAND_DATA: if (connection_half_edge_is_valid_data(ocirc->half_streams, - rh.stream_id)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh.length); + msg->stream_id)) { + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } break; case RELAY_COMMAND_SENDME: if (connection_half_edge_is_valid_sendme(ocirc->half_streams, - rh.stream_id)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh.length); + msg->stream_id)) { + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } break; case RELAY_COMMAND_CONNECTED: if (connection_half_edge_is_valid_connected(ocirc->half_streams, - rh.stream_id)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh.length); + msg->stream_id)) { + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } break; case RELAY_COMMAND_RESOLVED: if (connection_half_edge_is_valid_resolved(ocirc->half_streams, - rh.stream_id)) { - circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), rh.length); + msg->stream_id)) { + circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length); } break; } diff --git a/src/feature/client/circpathbias.h b/src/feature/client/circpathbias.h index e92756ae78..59750c7521 100644 --- a/src/feature/client/circpathbias.h +++ b/src/feature/client/circpathbias.h @@ -12,6 +12,8 @@ #ifndef TOR_CIRCPATHBIAS_H #define TOR_CIRCPATHBIAS_H +#include "core/or/relay_msg_st.h" + double pathbias_get_extreme_rate(const or_options_t *options); double pathbias_get_extreme_use_rate(const or_options_t *options); int pathbias_get_dropguards(const or_options_t *options); @@ -19,8 +21,8 @@ void pathbias_count_timeout(origin_circuit_t *circ); void pathbias_count_build_success(origin_circuit_t *circ); int pathbias_count_build_attempt(origin_circuit_t *circ); int pathbias_check_close(origin_circuit_t *circ, int reason); -int pathbias_check_probe_response(circuit_t *circ, const cell_t *cell); -void pathbias_count_valid_cells(circuit_t *circ, const cell_t *cell); +int pathbias_check_probe_response(circuit_t *circ, const relay_msg_t *msg); +void pathbias_count_valid_cells(circuit_t *circ, const relay_msg_t *msg); void pathbias_count_use_attempt(origin_circuit_t *circ); void pathbias_mark_use_success(origin_circuit_t *circ); void pathbias_mark_use_rollback(origin_circuit_t *circ); diff --git a/src/feature/relay/circuitbuild_relay.c b/src/feature/relay/circuitbuild_relay.c index 5ece5b4adc..4a2b3814be 100644 --- a/src/feature/relay/circuitbuild_relay.c +++ b/src/feature/relay/circuitbuild_relay.c @@ -421,15 +421,14 @@ circuit_open_connection_for_extend(const struct extend_cell_t *ec, * Return -1 if we want to warn and tear down the circuit, else return 0. */ int -circuit_extend(struct cell_t *cell, struct circuit_t *circ) +circuit_extend(const relay_msg_t *rmsg, struct circuit_t *circ) { channel_t *n_chan; - relay_header_t rh; extend_cell_t ec; const char *msg = NULL; int should_launch = 0; - IF_BUG_ONCE(!cell) { + IF_BUG_ONCE(!rmsg) { return -1; } @@ -440,17 +439,13 @@ circuit_extend(struct cell_t *cell, struct circuit_t *circ) if (circuit_extend_state_valid_helper(circ) < 0) return -1; - relay_header_unpack(&rh, cell->payload); - /* We no longer accept EXTEND messages; only EXTEND2. */ - if (rh.command == RELAY_COMMAND_EXTEND) { + if (rmsg->command == RELAY_COMMAND_EXTEND) { /* TODO: Should we log this? */ return -1; } - if (extend_cell_parse(&ec, rh.command, - cell->payload+RELAY_HEADER_SIZE, - rh.length) < 0) { + if (extend_cell_parse(&ec, rmsg->command, rmsg->body, rmsg->length) < 0) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Can't parse extend cell. Closing circuit."); return -1; diff --git a/src/feature/relay/circuitbuild_relay.h b/src/feature/relay/circuitbuild_relay.h index 307825bb5c..0148aa5581 100644 --- a/src/feature/relay/circuitbuild_relay.h +++ b/src/feature/relay/circuitbuild_relay.h @@ -14,6 +14,7 @@ #include "lib/cc/torint.h" #include "lib/log/log.h" +#include "core/or/relay_msg_st.h" #include "app/config/config.h" @@ -34,7 +35,7 @@ circuitbuild_warn_client_extend(void) #ifdef HAVE_MODULE_RELAY -int circuit_extend(struct cell_t *cell, struct circuit_t *circ); +int circuit_extend(const relay_msg_t *msg, struct circuit_t *circ); int onionskin_answer(struct or_circuit_t *circ, const struct created_cell_t *created_cell, @@ -44,9 +45,9 @@ int onionskin_answer(struct or_circuit_t *circ, #else /* !defined(HAVE_MODULE_RELAY) */ static inline int -circuit_extend(struct cell_t *cell, struct circuit_t *circ) +circuit_extend(const relay_msg_t *msg, struct circuit_t *circ) { - (void)cell; + (void)msg; (void)circ; circuitbuild_warn_client_extend(); return -1; diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c index d3ad68f89a..178aec2ab2 100644 --- a/src/test/test_cell_formats.c +++ b/src/test/test_cell_formats.c @@ -54,35 +54,28 @@ test_cfmt_relay_header(void *arg) } static void -make_relay_cell(cell_t *out, uint8_t command, - const void *body, size_t bodylen) +make_relay_msg(relay_msg_t *out, uint8_t command, + const void *body, size_t bodylen) { - relay_header_t rh; - - memset(&rh, 0, sizeof(rh)); - rh.stream_id = 5; - rh.command = command; - rh.length = bodylen; - - out->command = CELL_RELAY; - out->circ_id = 10; - relay_header_pack(out->payload, &rh); - - memcpy(out->payload + RELAY_HEADER_SIZE, body, bodylen); + memset(out, 0, sizeof(*out)); + out->command = command; + out->body = (uint8_t *)body; + out->length = bodylen; + out->stream_id = 5; } static void test_cfmt_begin_cells(void *arg) { - cell_t cell; + relay_msg_t msg; begin_cell_t bcell; uint8_t end_reason; (void)arg; /* Try begindir. */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN_DIR, "", 0); - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN_DIR, "", 0); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); tt_ptr_op(NULL, OP_EQ, bcell.address); tt_int_op(0, OP_EQ, bcell.flags); tt_int_op(0, OP_EQ, bcell.port); @@ -91,8 +84,8 @@ test_cfmt_begin_cells(void *arg) /* A Begindir with extra stuff. */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN_DIR, "12345", 5); - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN_DIR, "12345", 5); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); tt_ptr_op(NULL, OP_EQ, bcell.address); tt_int_op(0, OP_EQ, bcell.flags); tt_int_op(0, OP_EQ, bcell.port); @@ -101,8 +94,8 @@ test_cfmt_begin_cells(void *arg) /* A short but valid begin cell */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:9", 6); - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "a.b:9", 6); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); tt_str_op("a.b", OP_EQ, bcell.address); tt_int_op(0, OP_EQ, bcell.flags); tt_int_op(9, OP_EQ, bcell.port); @@ -113,21 +106,21 @@ test_cfmt_begin_cells(void *arg) /* A significantly loner begin cell */ memset(&bcell, 0x7f, sizeof(bcell)); { - const char c[] = "here-is-a-nice-long.hostname.com:65535"; - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, strlen(c)+1); - } - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + const char c[] = "here-is-a-nice-long.hostname.com:65535"; + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, c, strlen(c)+1); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); tt_str_op("here-is-a-nice-long.hostname.com", OP_EQ, bcell.address); tt_int_op(0, OP_EQ, bcell.flags); tt_int_op(65535, OP_EQ, bcell.port); tt_int_op(5, OP_EQ, bcell.stream_id); tt_int_op(0, OP_EQ, bcell.is_begindir); tor_free(bcell.address); + } /* An IPv4 begin cell. */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "18.9.22.169:80", 15); - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "18.9.22.169:80", 15); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); tt_str_op("18.9.22.169", OP_EQ, bcell.address); tt_int_op(0, OP_EQ, bcell.flags); tt_int_op(80, OP_EQ, bcell.port); @@ -137,9 +130,9 @@ test_cfmt_begin_cells(void *arg) /* An IPv6 begin cell. Let's make sure we handle colons*/ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "[2620::6b0:b:1a1a:0:26e5:480e]:80", 34); - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); tt_str_op("[2620::6b0:b:1a1a:0:26e5:480e]", OP_EQ, bcell.address); tt_int_op(0, OP_EQ, bcell.flags); tt_int_op(80, OP_EQ, bcell.port); @@ -151,88 +144,85 @@ test_cfmt_begin_cells(void *arg) memset(&bcell, 0x7f, sizeof(bcell)); { const char c[] = "another.example.com:80\x00\x01\x02"; - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, sizeof(c)-1); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, c, sizeof(c)-1); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); + tt_str_op("another.example.com", OP_EQ, bcell.address); + tt_int_op(0, OP_EQ, bcell.flags); + tt_int_op(80, OP_EQ, bcell.port); + tt_int_op(5, OP_EQ, bcell.stream_id); + tt_int_op(0, OP_EQ, bcell.is_begindir); + tor_free(bcell.address); } - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); - tt_str_op("another.example.com", OP_EQ, bcell.address); - tt_int_op(0, OP_EQ, bcell.flags); - tt_int_op(80, OP_EQ, bcell.port); - tt_int_op(5, OP_EQ, bcell.stream_id); - tt_int_op(0, OP_EQ, bcell.is_begindir); - tor_free(bcell.address); /* a begin cell with flags. */ memset(&bcell, 0x7f, sizeof(bcell)); { const char c[] = "another.example.com:443\x00\x01\x02\x03\x04"; - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, sizeof(c)-1); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, c, sizeof(c)-1); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); + tt_str_op("another.example.com", OP_EQ, bcell.address); + tt_int_op(0x1020304, OP_EQ, bcell.flags); + tt_int_op(443, OP_EQ, bcell.port); + tt_int_op(5, OP_EQ, bcell.stream_id); + tt_int_op(0, OP_EQ, bcell.is_begindir); + tor_free(bcell.address); } - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); - tt_str_op("another.example.com", OP_EQ, bcell.address); - tt_int_op(0x1020304, OP_EQ, bcell.flags); - tt_int_op(443, OP_EQ, bcell.port); - tt_int_op(5, OP_EQ, bcell.stream_id); - tt_int_op(0, OP_EQ, bcell.is_begindir); - tor_free(bcell.address); /* a begin cell with flags and even more cruft after that. */ memset(&bcell, 0x7f, sizeof(bcell)); { const char c[] = "a-further.example.com:22\x00\xee\xaa\x00\xffHi mom"; - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, c, sizeof(c)-1); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, c, sizeof(c)-1); + tt_int_op(0, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); + tt_str_op("a-further.example.com", OP_EQ, bcell.address); + tt_int_op(0xeeaa00ff, OP_EQ, bcell.flags); + tt_int_op(22, OP_EQ, bcell.port); + tt_int_op(5, OP_EQ, bcell.stream_id); + tt_int_op(0, OP_EQ, bcell.is_begindir); + tor_free(bcell.address); } - tt_int_op(0, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); - tt_str_op("a-further.example.com", OP_EQ, bcell.address); - tt_int_op(0xeeaa00ff, OP_EQ, bcell.flags); - tt_int_op(22, OP_EQ, bcell.port); - tt_int_op(5, OP_EQ, bcell.stream_id); - tt_int_op(0, OP_EQ, bcell.is_begindir); - tor_free(bcell.address); +#if 0 + // Note: This is now checked at when we decode the relay message. /* bad begin cell: impossible length. */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:80", 7); - cell.payload[9] = 0x01; /* Set length to 510 */ - cell.payload[10] = 0xfe; - { - relay_header_t rh; - relay_header_unpack(&rh, cell.payload); - tt_int_op(rh.length, OP_EQ, 510); - } - tt_int_op(-2, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "a.b:80", 7); + msg.length = 510; + tt_int_op(-2, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); +#endif /* Bad begin cell: no body. */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "", 0); - tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "", 0); + tt_int_op(-1, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); /* bad begin cell: no body. */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "", 0); - tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "", 0); + tt_int_op(-1, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); /* bad begin cell: no colon */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b", 4); - tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "a.b", 4); + tt_int_op(-1, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); /* bad begin cell: no ports */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:", 5); - tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "a.b:", 5); + tt_int_op(-1, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); /* bad begin cell: bad port */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:xyz", 8); - tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "a.b:xyz", 8); + tt_int_op(-1, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:100000", 11); - tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "a.b:100000", 11); + tt_int_op(-1, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); /* bad begin cell: no nul */ memset(&bcell, 0x7f, sizeof(bcell)); - make_relay_cell(&cell, RELAY_COMMAND_BEGIN, "a.b:80", 6); - tt_int_op(-1, OP_EQ, begin_cell_parse(&cell, &bcell, &end_reason)); + make_relay_msg(&msg, RELAY_COMMAND_BEGIN, "a.b:80", 6); + tt_int_op(-1, OP_EQ, begin_cell_parse(&msg, &bcell, &end_reason)); done: tor_free(bcell.address); @@ -241,144 +231,129 @@ test_cfmt_begin_cells(void *arg) static void test_cfmt_connected_cells(void *arg) { - relay_header_t rh; - cell_t cell; tor_addr_t addr; int ttl, r; char *mem_op_hex_tmp = NULL; + relay_msg_t msg; + uint8_t buf[512]; (void)arg; /* Let's try an oldschool one with nothing in it. */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, "", 0); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "", 0); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_UNSPEC); tt_int_op(ttl, OP_EQ, -1); /* A slightly less oldschool one: only an IPv4 address */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, "\x20\x30\x40\x50", 4); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x20\x30\x40\x50", 4); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET); tt_str_op(fmt_addr(&addr), OP_EQ, "32.48.64.80"); tt_int_op(ttl, OP_EQ, -1); /* Bogus but understandable: truncated TTL */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, "\x11\x12\x13\x14\x15", 5); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x11\x12\x13\x14\x15", 5); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET); tt_str_op(fmt_addr(&addr), OP_EQ, "17.18.19.20"); tt_int_op(ttl, OP_EQ, -1); /* Regular IPv4 one: address and TTL */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x02\x03\x04\x05\x00\x00\x0e\x10", 8); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET); tt_str_op(fmt_addr(&addr), OP_EQ, "2.3.4.5"); tt_int_op(ttl, OP_EQ, 3600); /* IPv4 with too-big TTL */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x02\x03\x04\x05\xf0\x00\x00\x00", 8); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET); tt_str_op(fmt_addr(&addr), OP_EQ, "2.3.4.5"); tt_int_op(ttl, OP_EQ, -1); /* IPv6 (ttl is mandatory) */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x00\x00\x00\x00\x06" "\x26\x07\xf8\xb0\x40\x0c\x0c\x02" "\x00\x00\x00\x00\x00\x00\x00\x68" "\x00\x00\x02\x58", 25); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET6); tt_str_op(fmt_addr(&addr), OP_EQ, "2607:f8b0:400c:c02::68"); tt_int_op(ttl, OP_EQ, 600); /* IPv6 (ttl too big) */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x00\x00\x00\x00\x06" "\x26\x07\xf8\xb0\x40\x0c\x0c\x02" "\x00\x00\x00\x00\x00\x00\x00\x68" "\x90\x00\x02\x58", 25); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET6); tt_str_op(fmt_addr(&addr), OP_EQ, "2607:f8b0:400c:c02::68"); tt_int_op(ttl, OP_EQ, -1); /* Bogus size: 3. */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x00\x01\x02", 3); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, -1); /* Bogus family: 7. */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x00\x00\x00\x00\x07" "\x26\x07\xf8\xb0\x40\x0c\x0c\x02" "\x00\x00\x00\x00\x00\x00\x00\x68" "\x90\x00\x02\x58", 25); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, -1); /* Truncated IPv6. */ - make_relay_cell(&cell, RELAY_COMMAND_CONNECTED, + make_relay_msg(&msg, RELAY_COMMAND_CONNECTED, "\x00\x00\x00\x00\x06" "\x26\x07\xf8\xb0\x40\x0c\x0c\x02" "\x00\x00\x00\x00\x00\x00\x00\x68" "\x00\x00\x02", 24); - relay_header_unpack(&rh, cell.payload); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, -1); /* Now make sure we can generate connected cells correctly. */ /* Try an IPv4 address */ - memset(&rh, 0, sizeof(rh)); - memset(&cell, 0, sizeof(cell)); tor_addr_parse(&addr, "30.40.50.60"); - rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE, - &addr, 1024); - tt_int_op(rh.length, OP_EQ, 8); - test_memeq_hex(cell.payload+RELAY_HEADER_SIZE, "1e28323c" "00000400"); + msg.body = buf; + msg.length = connected_cell_format_payload(buf, &addr, 1024); + tt_int_op(msg.length, OP_EQ, 8); + test_memeq_hex(msg.body, "1e28323c" "00000400"); /* Try parsing it. */ tor_addr_make_unspec(&addr); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET); tt_str_op(fmt_addr(&addr), OP_EQ, "30.40.50.60"); tt_int_op(ttl, OP_EQ, 1024); /* Try an IPv6 address */ - memset(&rh, 0, sizeof(rh)); - memset(&cell, 0, sizeof(cell)); tor_addr_parse(&addr, "2620::6b0:b:1a1a:0:26e5:480e"); - rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE, - &addr, 3600); - tt_int_op(rh.length, OP_EQ, 25); - test_memeq_hex(cell.payload + RELAY_HEADER_SIZE, + msg.length = connected_cell_format_payload(buf, &addr, 3600); + tt_int_op(msg.length, OP_EQ, 25); + test_memeq_hex(msg.body, "00000000" "06" "2620000006b0000b1a1a000026e5480e" "00000e10"); /* Try parsing it. */ tor_addr_make_unspec(&addr); - r = connected_cell_parse(&rh, &cell, &addr, &ttl); + r = connected_cell_parse(&msg, &addr, &ttl); tt_int_op(r, OP_EQ, 0); tt_int_op(tor_addr_family(&addr), OP_EQ, AF_INET6); tt_str_op(fmt_addr(&addr), OP_EQ, "2620:0:6b0:b:1a1a:0:26e5:480e"); @@ -825,15 +800,15 @@ static void test_cfmt_resolved_cells(void *arg) { smartlist_t *addrs = smartlist_new(); - relay_header_t rh; - cell_t cell; int r, errcode; address_ttl_t *a; + relay_msg_t msg; + uint8_t buf[500]; (void)arg; #define CLEAR_CELL() do { \ - memset(&cell, 0, sizeof(cell)); \ - memset(&rh, 0, sizeof(rh)); \ + memset(&msg, 0, sizeof(msg)); \ + memset(&buf, 0, sizeof(buf)); \ } while (0) #define CLEAR_ADDRS() do { \ SMARTLIST_FOREACH(addrs, address_ttl_t *, aa_, \ @@ -842,9 +817,10 @@ test_cfmt_resolved_cells(void *arg) } while (0) #define SET_CELL(s) do { \ CLEAR_CELL(); \ - memcpy(cell.payload + RELAY_HEADER_SIZE, (s), sizeof((s))-1); \ - rh.length = sizeof((s))-1; \ - rh.command = RELAY_COMMAND_RESOLVED; \ + memcpy(buf, (s), sizeof((s))-1); \ + msg.length = sizeof((s))-1; \ + msg.body = buf; \ + msg.command = RELAY_COMMAND_RESOLVED; \ errcode = -1; \ } while (0) @@ -857,7 +833,7 @@ test_cfmt_resolved_cells(void *arg) /* Let's try an empty cell */ SET_CELL(""); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 0); @@ -865,8 +841,8 @@ test_cfmt_resolved_cells(void *arg) /* Cell with one ipv4 addr */ SET_CELL("\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00"); - tt_int_op(rh.length, OP_EQ, 10); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, 10); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 1); @@ -881,8 +857,8 @@ test_cfmt_resolved_cells(void *arg) "\x20\x02\x90\x90\x00\x00\x00\x00" "\x00\x00\x00\x00\xf0\xf0\xab\xcd" "\x02\00\x00\x01"); - tt_int_op(rh.length, OP_EQ, 22); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, 22); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 1); @@ -896,8 +872,8 @@ test_cfmt_resolved_cells(void *arg) SET_CELL("\x00\x11" "motherbrain.zebes" "\x00\00\x00\x00"); - tt_int_op(rh.length, OP_EQ, 23); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, 23); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 1); @@ -917,8 +893,8 @@ test_cfmt_resolved_cells(void *arg) SET_CELL("\x00\xff" LONG_NAME "\x00\01\x00\x00"); - tt_int_op(rh.length, OP_EQ, 261); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, 261); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 1); @@ -932,8 +908,8 @@ test_cfmt_resolved_cells(void *arg) SET_CELL("\xf0\x2b" "I'm sorry, Dave. I'm afraid I can't do that" "\x00\x11\x22\x33"); - tt_int_op(rh.length, OP_EQ, 49); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, 49); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, RESOLVED_TYPE_ERROR_TRANSIENT); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 0); @@ -942,8 +918,8 @@ test_cfmt_resolved_cells(void *arg) SET_CELL("\xf1\x40" "This hostname is too important for me to allow you to resolve it" "\x00\x00\x00\x00"); - tt_int_op(rh.length, OP_EQ, 70); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, 70); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, RESOLVED_TYPE_ERROR); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 0); @@ -953,8 +929,8 @@ test_cfmt_resolved_cells(void *arg) SET_CELL("\xee\x16" "fault in the AE35 unit" "\x09\x09\x01\x01"); - tt_int_op(rh.length, OP_EQ, 28); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, 28); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 0); @@ -981,7 +957,7 @@ test_cfmt_resolved_cells(void *arg) "motherbrain.zebes" "\x00\00\x00\x00" ); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); /* no error reported; we got answers */ tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 3); @@ -1013,7 +989,7 @@ test_cfmt_resolved_cells(void *arg) "\x20\x02\x90\x01\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\xfa\xca\xde" "\x00\00\x00\x03"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 5); @@ -1053,8 +1029,8 @@ test_cfmt_resolved_cells(void *arg) "\x00\xe7" LONG_NAME2 "\x00\01\x00\x00"); - tt_int_op(rh.length, OP_EQ, RELAY_PAYLOAD_SIZE); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + tt_int_op(msg.length, OP_EQ, RELAY_PAYLOAD_SIZE); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, 0); tt_int_op(smartlist_len(addrs), OP_EQ, 2); @@ -1068,68 +1044,71 @@ test_cfmt_resolved_cells(void *arg) /* Invalid length on an IPv4 */ SET_CELL("\x04\x03zzz1234"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); SET_CELL("\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00" "\x04\x05zzzzz1234"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); /* Invalid length on an IPv6 */ SET_CELL("\x06\x03zzz1234"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); SET_CELL("\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00" "\x06\x17wwwwwwwwwwwwwwwww1234"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); SET_CELL("\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00" "\x06\x10xxxx"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); /* Empty hostname */ SET_CELL("\x00\x00xxxx"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); +#if 0 + //No longer possible with relay message encoding. /* rh.length out of range */ CLEAR_CELL(); rh.length = 499; - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(errcode, OP_EQ, 0); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); +#endif /* Item length extends beyond rh.length */ CLEAR_CELL(); SET_CELL("\x00\xff" LONG_NAME "\x00\01\x00\x00"); - rh.length -= 1; - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + msg.length -= 1; + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); - rh.length -= 5; - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + msg.length -= 5; + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); SET_CELL("\x04\x04" "\x7f\x00\x02\x0a" "\x00\00\x01\x00"); - rh.length -= 1; - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + msg.length -= 1; + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); @@ -1137,19 +1116,19 @@ test_cfmt_resolved_cells(void *arg) "\x20\x02\x90\x01\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\xfa\xca\xde" "\x00\00\x00\x03"); - rh.length -= 1; - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + msg.length -= 1; + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); /* Truncated item after first character */ SET_CELL("\x04"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); SET_CELL("\xee"); - r = resolved_cell_parse(&cell, &rh, addrs, &errcode); + r = resolved_cell_parse(&msg, addrs, &errcode); tt_int_op(r, OP_EQ, -1); tt_int_op(smartlist_len(addrs), OP_EQ, 0); diff --git a/src/test/test_circuitbuild.c b/src/test/test_circuitbuild.c index 0a5c3530bd..9bebcc2873 100644 --- a/src/test/test_circuitbuild.c +++ b/src/test/test_circuitbuild.c @@ -21,6 +21,7 @@ #include "core/or/circuitlist.h" #include "core/or/circuituse.h" #include "core/or/onion.h" +#include "core/or/relay_msg.h" #include "core/or/cell_st.h" #include "core/or/cpath_build_state_st.h" @@ -1278,7 +1279,7 @@ static void test_circuit_extend(void *arg) { (void)arg; - cell_t *cell = tor_malloc_zero(sizeof(cell_t)); + relay_msg_t *msg = tor_malloc_zero(sizeof(relay_msg_t)); channel_t *p_chan = tor_malloc_zero(sizeof(channel_t)); or_circuit_t *or_circ = tor_malloc_zero(sizeof(or_circuit_t)); circuit_t *circ = TO_CIRCUIT(or_circ); @@ -1293,10 +1294,13 @@ test_circuit_extend(void *arg) setup_full_capture_of_logs(LOG_INFO); + msg->command = RELAY_COMMAND_EXTEND2; + msg->body = tor_memdup("xyz", 3); + #ifndef ALL_BUGS_ARE_FATAL /* Circuit must be non-NULL */ tor_capture_bugs_(1); - tt_int_op(circuit_extend(cell, NULL), OP_EQ, -1); + tt_int_op(circuit_extend(msg, NULL), OP_EQ, -1); tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1); tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ, "!(ASSERT_PREDICT_UNLIKELY_(!circ))"); @@ -1308,7 +1312,7 @@ test_circuit_extend(void *arg) tt_int_op(circuit_extend(NULL, circ), OP_EQ, -1); tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1); tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ, - "!(ASSERT_PREDICT_UNLIKELY_(!cell))"); + "!(ASSERT_PREDICT_UNLIKELY_(!rmsg))"); tor_end_capture_bugs_(); mock_clean_saved_logs(); @@ -1324,13 +1328,13 @@ test_circuit_extend(void *arg) /* Clients can't extend */ server = 0; - tt_int_op(circuit_extend(cell, circ), OP_EQ, -1); + tt_int_op(circuit_extend(msg, circ), OP_EQ, -1); expect_log_msg("Got an extend cell, but running as a client. Closing.\n"); mock_clean_saved_logs(); /* But servers can. Unpack the cell, but fail parsing. */ server = 1; - tt_int_op(circuit_extend(cell, circ), OP_EQ, -1); + tt_int_op(circuit_extend(msg, circ), OP_EQ, -1); expect_log_msg("Can't parse extend cell. Closing circuit.\n"); mock_clean_saved_logs(); @@ -1343,7 +1347,7 @@ test_circuit_extend(void *arg) mock_extend_cell_parse_result = 0; mock_extend_cell_parse_calls = 0; - tt_int_op(circuit_extend(cell, circ), OP_EQ, -1); + tt_int_op(circuit_extend(msg, circ), OP_EQ, -1); tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1); expect_log_msg( "Client asked me to extend without specifying an id_digest.\n"); @@ -1354,7 +1358,7 @@ test_circuit_extend(void *arg) memset(&mock_extend_cell_parse_cell_out.node_id, 0xAA, sizeof(mock_extend_cell_parse_cell_out.node_id)); - tt_int_op(circuit_extend(cell, circ), OP_EQ, -1); + tt_int_op(circuit_extend(msg, circ), OP_EQ, -1); tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1); expect_log_msg("Client asked me to extend to a zero destination port " "or unspecified address '[scrubbed]'.\n"); @@ -1368,7 +1372,7 @@ test_circuit_extend(void *arg) #ifndef ALL_BUGS_ARE_FATAL tor_capture_bugs_(1); - tt_int_op(circuit_extend(cell, circ), OP_EQ, -1); + tt_int_op(circuit_extend(msg, circ), OP_EQ, -1); tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1); tt_int_op(smartlist_len(tor_get_captured_bug_log_()), OP_EQ, 1); tt_str_op(smartlist_get(tor_get_captured_bug_log_(), 0), OP_EQ, @@ -1389,7 +1393,7 @@ test_circuit_extend(void *arg) /* Test circuit not established, but don't launch another one */ mock_channel_get_for_extend_launch_out = 0; mock_channel_get_for_extend_nchan = NULL; - tt_int_op(circuit_extend(cell, circ), OP_EQ, 0); + tt_int_op(circuit_extend(msg, circ), OP_EQ, 0); tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1); tt_int_op(mock_channel_get_for_extend_calls, OP_EQ, 1); @@ -1409,7 +1413,7 @@ test_circuit_extend(void *arg) mock_channel_get_for_extend_launch_out = 1; mock_channel_get_for_extend_nchan = NULL; mock_channel_connect_nchan = fake_n_chan; - tt_int_op(circuit_extend(cell, circ), OP_EQ, 0); + tt_int_op(circuit_extend(msg, circ), OP_EQ, 0); tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1); tt_int_op(mock_channel_get_for_extend_calls, OP_EQ, 1); tt_int_op(mock_channel_connect_calls, OP_EQ, 1); @@ -1433,7 +1437,7 @@ test_circuit_extend(void *arg) mock_channel_get_for_extend_nchan = fake_n_chan; mock_channel_connect_nchan = NULL; mock_circuit_deliver_create_cell_result = 0; - tt_int_op(circuit_extend(cell, circ), OP_EQ, 0); + tt_int_op(circuit_extend(msg, circ), OP_EQ, 0); tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1); tt_int_op(mock_channel_get_for_extend_calls, OP_EQ, 1); tt_int_op(mock_channel_connect_calls, OP_EQ, 0); @@ -1456,7 +1460,7 @@ test_circuit_extend(void *arg) mock_channel_get_for_extend_nchan = fake_n_chan; mock_channel_connect_nchan = NULL; mock_circuit_deliver_create_cell_result = -1; - tt_int_op(circuit_extend(cell, circ), OP_EQ, -1); + tt_int_op(circuit_extend(msg, circ), OP_EQ, -1); tt_int_op(mock_extend_cell_parse_calls, OP_EQ, 1); tt_int_op(mock_channel_get_for_extend_calls, OP_EQ, 1); tt_int_op(mock_channel_connect_calls, OP_EQ, 0); @@ -1502,7 +1506,7 @@ test_circuit_extend(void *arg) mock_circuit_deliver_create_cell_calls = 0; mock_circuit_deliver_create_cell_result = 0; - tor_free(cell); + relay_msg_free(msg); /* circ and or_circ are the same object */ tor_free(circ->n_hop); tor_free(circ->n_chan_create_cell); diff --git a/src/test/test_circuitpadding.c b/src/test/test_circuitpadding.c index 95401465c1..a16a169cdf 100644 --- a/src/test/test_circuitpadding.c +++ b/src/test/test_circuitpadding.c @@ -24,6 +24,7 @@ #include "core/or/circuitpadding.h" #include "core/or/circuitpadding_machines.h" #include "core/or/extendinfo.h" +#include "core/or/relay_msg.h" #include "core/mainloop/netstatus.h" #include "core/crypto/relay_crypto.h" #include "core/or/protover.h" @@ -172,11 +173,16 @@ circuit_package_relay_cell_mock(cell_t *cell, circuit_t *circ, const char *filename, int lineno) { (void)cell; (void)on_stream; (void)filename; (void)lineno; + relay_msg_t *msg = NULL; + + msg = relay_msg_decode_cell(RELAY_CELL_FORMAT_V0, cell); + if (! msg) + goto done; if (circ == client_side) { if (cell->payload[0] == RELAY_COMMAND_PADDING_NEGOTIATE) { // Deliver to relay - circpad_handle_padding_negotiate(relay_side, cell); + circpad_handle_padding_negotiate(relay_side, msg); } else { int is_target_hop = circpad_padding_is_from_expected_hop(circ, @@ -190,7 +196,7 @@ circuit_package_relay_cell_mock(cell_t *cell, circuit_t *circ, // Receive padding cell at middle circpad_deliver_recognized_relay_cell_events(relay_side, - cell->payload[0], NULL); + msg->command, NULL); } n_client_cells++; } else if (circ == relay_side) { @@ -199,11 +205,11 @@ circuit_package_relay_cell_mock(cell_t *cell, circuit_t *circ, if (cell->payload[0] == RELAY_COMMAND_PADDING_NEGOTIATED) { // XXX: blah need right layer_hint.. if (deliver_negotiated) - circpad_handle_padding_negotiated(client_side, cell, + circpad_handle_padding_negotiated(client_side, msg, TO_ORIGIN_CIRCUIT(client_side) ->cpath->next); } else if (cell->payload[0] == RELAY_COMMAND_PADDING_NEGOTIATE) { - circpad_handle_padding_negotiate(client_side, cell); + circpad_handle_padding_negotiate(client_side, msg); } else { // No need to pretend a padding cell was sent: This event is // now emitted internally when the circuitpadding code sends them. @@ -211,7 +217,7 @@ circuit_package_relay_cell_mock(cell_t *cell, circuit_t *circ, // Receive padding cell at client circpad_deliver_recognized_relay_cell_events(client_side, - cell->payload[0], + msg->command, TO_ORIGIN_CIRCUIT(client_side)->cpath->next); } @@ -219,6 +225,7 @@ circuit_package_relay_cell_mock(cell_t *cell, circuit_t *circ, } done: + relay_msg_free(msg); timers_advance_and_run(1); return 0; } @@ -1251,7 +1258,7 @@ test_circuitpadding_wronghop(void *arg) */ (void)arg; uint32_t read_bw = 0, overhead_bw = 0; - cell_t cell; + relay_msg_t msg; signed_error_t ret; origin_circuit_t *orig_client; int64_t actual_mocked_monotime_start; @@ -1331,17 +1338,20 @@ test_circuitpadding_wronghop(void *arg) orig_client->n_overhead_read_circ_bw); /* 2. Test padding negotiated not handled from hops 1,3 */ - ret = circpad_handle_padding_negotiated(client_side, &cell, + memset(&msg, 0, sizeof(msg)); + ret = circpad_handle_padding_negotiated(client_side, &msg, TO_ORIGIN_CIRCUIT(client_side)->cpath); tt_int_op(ret, OP_EQ, -1); - ret = circpad_handle_padding_negotiated(client_side, &cell, + ret = circpad_handle_padding_negotiated(client_side, &msg, TO_ORIGIN_CIRCUIT(client_side)->cpath->next->next); tt_int_op(ret, OP_EQ, -1); /* 3. Garbled negotiated cell */ - memset(&cell, 255, sizeof(cell)); - ret = circpad_handle_padding_negotiated(client_side, &cell, + memset(&msg, 0, sizeof(msg)); + msg.body = tor_malloc_zero(99); + memset(msg.body, 0xff, 99); + ret = circpad_handle_padding_negotiated(client_side, &msg, TO_ORIGIN_CIRCUIT(client_side)->cpath->next); tt_int_op(ret, OP_EQ, -1); @@ -1350,7 +1360,7 @@ test_circuitpadding_wronghop(void *arg) overhead_bw = orig_client->n_overhead_read_circ_bw; relay_send_command_from_edge(0, relay_side, RELAY_COMMAND_PADDING_NEGOTIATE, - (void*)cell.payload, + "xyz", (size_t)3, NULL); tt_int_op(read_bw, OP_EQ, orig_client->n_delivered_read_circ_bw); @@ -1371,12 +1381,12 @@ test_circuitpadding_wronghop(void *arg) tt_int_op(n_client_cells, OP_EQ, 2); /* 6. Sending negotiated command to relay does nothing */ - ret = circpad_handle_padding_negotiated(relay_side, &cell, NULL); + ret = circpad_handle_padding_negotiated(relay_side, &msg, NULL); tt_int_op(ret, OP_EQ, -1); /* 7. Test garbled negotiated cell (bad command 255) */ - memset(&cell, 0, sizeof(cell)); - ret = circpad_handle_padding_negotiate(relay_side, &cell); + relay_msg_clear(&msg); + ret = circpad_handle_padding_negotiate(relay_side, &msg); tt_int_op(ret, OP_EQ, -1); tt_int_op(n_client_cells, OP_EQ, 2); @@ -1434,6 +1444,7 @@ test_circuitpadding_wronghop(void *arg) UNMOCK(circuitmux_attach_circuit); nodes_free(); testing_disable_reproducible_rng(); + relay_msg_clear(&msg); } void @@ -3100,17 +3111,18 @@ static void test_circuitpadding_ignore_non_padding_cells(void *arg) { int retval; - relay_header_t rh; (void) arg; client_side = (circuit_t *)origin_circuit_new(); client_side->purpose = CIRCUIT_PURPOSE_C_CIRCUIT_PADDING; - rh.command = RELAY_COMMAND_BEGIN; + relay_msg_t msg; + memset(&msg, 0, sizeof(msg)); + msg.command = RELAY_COMMAND_BEGIN; setup_full_capture_of_logs(LOG_INFO); - retval = handle_relay_cell_command(NULL, client_side, NULL, NULL, &rh, 0); + retval = handle_relay_msg(&msg, client_side, NULL, NULL, 0); tt_int_op(retval, OP_EQ, 0); expect_log_msg_containing("Ignored cell"); diff --git a/src/test/test_conflux_cell.c b/src/test/test_conflux_cell.c index bb440d0d0a..7e02f54764 100644 --- a/src/test/test_conflux_cell.c +++ b/src/test/test_conflux_cell.c @@ -13,15 +13,17 @@ #include "core/or/conflux_cell.h" #include "core/or/conflux_st.h" #include "trunnel/conflux.h" +#include "core/or/relay_msg.h" +#include "core/or/relay_msg_st.h" #include "lib/crypt_ops/crypto_rand.h" static void test_link(void *arg) { - cell_t cell; conflux_cell_link_t link; conflux_cell_link_t *decoded_link = NULL; + relay_msg_t msg; (void) arg; @@ -34,10 +36,12 @@ test_link(void *arg) crypto_rand((char *) link.nonce, sizeof(link.nonce)); - ssize_t cell_len = build_link_cell(&link, cell.payload+RELAY_HEADER_SIZE); + msg.body = tor_malloc(500); + ssize_t cell_len = build_link_cell(&link, msg.body); tt_int_op(cell_len, OP_GT, 0); + msg.length = cell_len; - decoded_link = conflux_cell_parse_link(&cell, cell_len); + decoded_link = conflux_cell_parse_link(&msg); tt_assert(decoded_link); uint8_t buf[RELAY_PAYLOAD_SIZE]; @@ -49,6 +53,7 @@ test_link(void *arg) tor_free(decoded_link); done: + relay_msg_clear(&msg); tor_free(decoded_link); } @@ -57,4 +62,3 @@ struct testcase_t conflux_cell_tests[] = { END_OF_TESTCASES }; - diff --git a/src/test/test_conflux_pool.c b/src/test/test_conflux_pool.c index 6fe3c8b65b..1294a8256b 100644 --- a/src/test/test_conflux_pool.c +++ b/src/test/test_conflux_pool.c @@ -29,6 +29,7 @@ #include "core/or/congestion_control_st.h" #include "core/or/congestion_control_common.h" #include "core/or/extendinfo.h" +#include "core/or/relay_msg.h" #include "core/mainloop/netstatus.h" #include "core/crypto/relay_crypto.h" #include "core/or/protover.h" @@ -223,6 +224,7 @@ static void process_mock_cell_delivery(void) { relay_header_t rh; + relay_msg_t *msg = NULL; cell_delivery_t *delivery = smartlist_pop_last(mock_cell_delivery); tor_assert(delivery); @@ -232,16 +234,20 @@ process_mock_cell_delivery(void) timers_advance_and_run(1); - switch (cell->payload[0]) { + msg = relay_msg_decode_cell(RELAY_CELL_FORMAT_V0, cell); + + tor_assert(msg); + + switch (msg->command) { case RELAY_COMMAND_CONFLUX_LINK: tor_assert(!CIRCUIT_IS_ORIGIN(dest_circ)); - conflux_process_link(dest_circ, cell, rh.length); + conflux_process_link(dest_circ, msg); break; case RELAY_COMMAND_CONFLUX_LINKED: tor_assert(CIRCUIT_IS_ORIGIN(dest_circ)); conflux_process_linked(dest_circ, TO_ORIGIN_CIRCUIT(dest_circ)->cpath->prev, - cell, rh.length); + msg); break; case RELAY_COMMAND_CONFLUX_LINKED_ACK: tor_assert(!CIRCUIT_IS_ORIGIN(dest_circ)); @@ -253,12 +259,13 @@ process_mock_cell_delivery(void) // the case where the switch is initiated by the exit, we will need to // get the cpath layer hint for the client. tor_assert(!CIRCUIT_IS_ORIGIN(dest_circ)); - conflux_process_switch_command(dest_circ, NULL, cell, &rh); + conflux_process_switch_command(dest_circ, NULL, msg); break; } tor_free(delivery); tor_free(cell); + relay_msg_free(msg); return; } diff --git a/src/test/test_relaycell.c b/src/test/test_relaycell.c index 6edc1030f9..ed5732b1f3 100644 --- a/src/test/test_relaycell.c +++ b/src/test/test_relaycell.c @@ -19,6 +19,7 @@ #include "core/or/connection_edge.h" #include "core/or/sendme.h" #include "core/or/relay.h" +#include "core/or/relay_msg.h" #include "test/test.h" #include "test/log_test_helpers.h" @@ -173,18 +174,19 @@ fake_entry_conn(origin_circuit_t *oncirc, streamid_t id) } #define PACK_CELL(id, cmd, body_s) do { \ - memset(&cell, 0, sizeof(cell)); \ - memset(&rh, 0, sizeof(rh)); \ - memcpy(cell.payload+RELAY_HEADER_SIZE, (body_s), sizeof((body_s))-1); \ - rh.length = sizeof((body_s))-1; \ - rh.command = (cmd); \ - rh.stream_id = (id); \ - relay_header_pack((uint8_t*)&cell.payload, &rh); \ + len_tmp = sizeof(body_s)-1; \ + relay_msg_free(msg); \ + msg = tor_malloc_zero(sizeof(relay_msg_t)); \ + msg->command = (cmd); \ + msg->stream_id = (id); \ + msg->body = tor_malloc(len_tmp); \ + msg->length = len_tmp; \ + memcpy(msg->body, (body_s), len_tmp); \ } while (0) #define ASSERT_COUNTED_BW() do { \ - tt_int_op(circ->n_delivered_read_circ_bw, OP_EQ, delivered+rh.length); \ + tt_int_op(circ->n_delivered_read_circ_bw, OP_EQ, delivered+msg->length); \ tt_int_op(circ->n_overhead_read_circ_bw, OP_EQ, \ - overhead+RELAY_PAYLOAD_SIZE-rh.length); \ + overhead+RELAY_PAYLOAD_SIZE-msg->length); \ delivered = circ->n_delivered_read_circ_bw; \ overhead = circ->n_overhead_read_circ_bw; \ } while (0) @@ -196,8 +198,8 @@ fake_entry_conn(origin_circuit_t *oncirc, streamid_t id) static int subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) { - cell_t cell; - relay_header_t rh; + relay_msg_t *msg = NULL; + size_t len_tmp; edge_connection_t *edgeconn; entry_connection_t *entryconn2=NULL; entry_connection_t *entryconn3=NULL; @@ -225,36 +227,36 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) /* Data cell not in the half-opened list */ PACK_CELL(4000, RELAY_COMMAND_DATA, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Sendme cell not in the half-opened list */ PACK_CELL(4000, RELAY_COMMAND_SENDME, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Connected cell not in the half-opened list */ PACK_CELL(4000, RELAY_COMMAND_CONNECTED, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Resolved cell not in the half-opened list */ PACK_CELL(4000, RELAY_COMMAND_RESOLVED, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -262,9 +264,9 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) edgeconn = ENTRY_TO_EDGE_CONN(entryconn2); PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -273,9 +275,9 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_COUNTED_BW(); data_cells--; @@ -283,9 +285,9 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -294,9 +296,9 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_COUNTED_BW(); sendme_cells--; @@ -304,9 +306,9 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -314,18 +316,18 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_COUNTED_BW(); ENTRY_TO_CONN(entryconn2)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -335,7 +337,7 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) /* sendme cell on open entryconn with full window */ PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); int ret = - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); tt_int_op(ret, OP_EQ, -END_CIRC_REASON_TORPROTOCOL); ASSERT_UNCOUNTED_BW(); @@ -346,18 +348,18 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) connection_edge_reached_eof(edgeconn); PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_COUNTED_BW(); ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_CONNECTED, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -365,16 +367,16 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_COUNTED_BW(); ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_SENDME, "Data1234"); ret = - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); tt_int_op(ret, OP_NE, -END_CIRC_REASON_TORPROTOCOL); ASSERT_UNCOUNTED_BW(); @@ -382,9 +384,9 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) ENTRY_TO_CONN(entryconn3)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -400,16 +402,16 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED, "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_COUNTED_BW(); ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_RESOLVED, "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -417,9 +419,9 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_DATA, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -427,17 +429,19 @@ subtest_circbw_halfclosed(origin_circuit_t *circ, streamid_t init_id) ENTRY_TO_CONN(entryconn4)->marked_for_close = 0; PACK_CELL(edgeconn->stream_id, RELAY_COMMAND_END, "Data1234"); if (circ->base_.purpose == CIRCUIT_PURPOSE_PATH_BIAS_TESTING) - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); else - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); + relay_msg_free(msg); connection_free_minimal(ENTRY_TO_CONN(entryconn2)); connection_free_minimal(ENTRY_TO_CONN(entryconn3)); connection_free_minimal(ENTRY_TO_CONN(entryconn4)); return 1; done: + relay_msg_free(msg); connection_free_minimal(ENTRY_TO_CONN(entryconn2)); connection_free_minimal(ENTRY_TO_CONN(entryconn3)); connection_free_minimal(ENTRY_TO_CONN(entryconn4)); @@ -666,8 +670,8 @@ test_halfstream_wrap(void *arg) static void test_circbw_relay(void *arg) { - cell_t cell; - relay_header_t rh; + relay_msg_t *msg = NULL; + size_t len_tmp; tor_addr_t addr; edge_connection_t *edgeconn; entry_connection_t *entryconn1=NULL; @@ -692,23 +696,24 @@ test_circbw_relay(void *arg) /* Stream id 0: Not counted */ PACK_CELL(0, RELAY_COMMAND_END, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Stream id 1: Counted */ PACK_CELL(1, RELAY_COMMAND_END, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); /* Properly formatted connect cell: counted */ PACK_CELL(1, RELAY_COMMAND_CONNECTED, "Data1234"); + tor_free(msg->body); + msg->body = tor_malloc(500); tor_addr_parse(&addr, "30.40.50.60"); - rh.length = connected_cell_format_payload(cell.payload+RELAY_HEADER_SIZE, - &addr, 1024); - relay_header_pack((uint8_t*)&cell.payload, &rh); \ - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + msg->length = connected_cell_format_payload(msg->body, + &addr, 1024); + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); @@ -718,7 +723,7 @@ test_circbw_relay(void *arg) edgeconn->on_circuit = TO_CIRCUIT(circ); PACK_CELL(1, RELAY_COMMAND_RESOLVED, "\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); @@ -727,65 +732,65 @@ test_circbw_relay(void *arg) /* Connected cell after open: not counted */ PACK_CELL(1, RELAY_COMMAND_CONNECTED, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Resolved cell after open: not counted */ PACK_CELL(1, RELAY_COMMAND_RESOLVED, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Drop cell: not counted */ PACK_CELL(1, RELAY_COMMAND_DROP, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Data cell on stream 0: not counted */ PACK_CELL(0, RELAY_COMMAND_DATA, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Data cell on open connection: counted */ ENTRY_TO_CONN(entryconn1)->marked_for_close = 0; PACK_CELL(1, RELAY_COMMAND_DATA, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); /* Empty Data cell on open connection: not counted */ ENTRY_TO_CONN(entryconn1)->marked_for_close = 0; PACK_CELL(1, RELAY_COMMAND_DATA, ""); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Sendme on valid stream: counted */ edgeconn->package_window -= STREAMWINDOW_INCREMENT; PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); /* Sendme on valid stream with full window: not counted */ PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234"); edgeconn->package_window = STREAMWINDOW_START; - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Sendme on unknown stream: not counted */ PACK_CELL(1, RELAY_COMMAND_SENDME, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Sendme on circuit with full window: not counted */ PACK_CELL(0, RELAY_COMMAND_SENDME, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -796,44 +801,44 @@ test_circbw_relay(void *arg) circ->cpath->package_window = 901; sendme_record_cell_digest_on_circ(TO_CIRCUIT(circ), circ->cpath); circ->cpath->package_window = 900; - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); /* Invalid extended cell: not counted */ PACK_CELL(1, RELAY_COMMAND_EXTENDED2, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Invalid extended cell: not counted */ PACK_CELL(1, RELAY_COMMAND_EXTENDED, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); /* Invalid HS cell: not counted */ PACK_CELL(1, RELAY_COMMAND_ESTABLISH_INTRO, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); /* "Valid" HS cell in expected state: counted */ TO_CIRCUIT(circ)->purpose = CIRCUIT_PURPOSE_C_ESTABLISH_REND; PACK_CELL(1, RELAY_COMMAND_RENDEZVOUS_ESTABLISHED, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_COUNTED_BW(); /* End cell on non-closed connection: counted */ PACK_CELL(1, RELAY_COMMAND_END, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), edgeconn, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), edgeconn, circ->cpath); ASSERT_COUNTED_BW(); /* End cell on connection that already got one: not counted */ PACK_CELL(1, RELAY_COMMAND_END, "Data1234"); - connection_edge_process_relay_cell(&cell, TO_CIRCUIT(circ), NULL, + connection_edge_process_relay_cell(msg, TO_CIRCUIT(circ), NULL, circ->cpath); ASSERT_UNCOUNTED_BW(); @@ -848,10 +853,11 @@ test_circbw_relay(void *arg) /* Path bias: truncated */ tt_int_op(circ->base_.marked_for_close, OP_EQ, 0); PACK_CELL(0, RELAY_COMMAND_TRUNCATED, "Data1234"); - pathbias_count_valid_cells(TO_CIRCUIT(circ), &cell); + pathbias_count_valid_cells(TO_CIRCUIT(circ), msg); tt_int_op(circ->base_.marked_for_close, OP_EQ, 1); done: + relay_msg_free(msg); UNMOCK(connection_start_reading); UNMOCK(connection_mark_unattached_ap_); UNMOCK(connection_mark_for_close_internal_); @@ -872,17 +878,18 @@ test_relaycell_resolved(void *arg) { entry_connection_t *entryconn; edge_connection_t *edgeconn; - cell_t cell; - relay_header_t rh; + relay_msg_t *msg = NULL; int r; or_options_t *options = get_options_mutable(); + size_t len_tmp; #define SET_CELL(s) do { \ - memset(&cell, 0, sizeof(cell)); \ - memset(&rh, 0, sizeof(rh)); \ - memcpy(cell.payload + RELAY_HEADER_SIZE, (s), sizeof((s))-1); \ - rh.length = sizeof((s))-1; \ - rh.command = RELAY_COMMAND_RESOLVED; \ + relay_msg_free(msg); \ + msg = tor_malloc_zero(sizeof(relay_msg_t)); \ + len_tmp = sizeof(s) - 1; \ + msg->body = tor_malloc_zero(len_tmp); \ + msg->length = len_tmp; \ + memcpy(msg->body, s, len_tmp); \ } while (0) #define MOCK_RESET() do { \ srm_ncalls = mum_ncalls = 0; \ @@ -892,20 +899,20 @@ test_relaycell_resolved(void *arg) tt_ptr_op(mum_conn, OP_EQ, entryconn); \ tt_int_op(mum_endreason, OP_EQ, (reason)); \ } while (0) -#define ASSERT_RESOLVED_CALLED(atype, answer, ttl, expires) do { \ - tt_int_op(srm_ncalls, OP_EQ, 1); \ - tt_ptr_op(srm_conn, OP_EQ, entryconn); \ - tt_int_op(srm_atype, OP_EQ, (atype)); \ - if ((answer) != NULL) { \ - tt_int_op(srm_alen, OP_EQ, sizeof(answer)-1); \ - tt_int_op(srm_alen, OP_LT, 512); \ - tt_int_op(srm_answer_is_set, OP_EQ, 1); \ - tt_mem_op(srm_answer, OP_EQ, answer, sizeof(answer)-1); \ - } else { \ - tt_int_op(srm_answer_is_set, OP_EQ, 0); \ - } \ - tt_int_op(srm_ttl, OP_EQ, ttl); \ - tt_i64_op(srm_expires, OP_EQ, expires); \ +#define ASSERT_RESOLVED_CALLED(atype, answer, ttl, expires) do { \ + tt_int_op(srm_ncalls, OP_EQ, 1); \ + tt_ptr_op(srm_conn, OP_EQ, entryconn); \ + tt_int_op(srm_atype, OP_EQ, (atype)); \ + if ((answer) != NULL) { \ + tt_int_op(srm_alen, OP_EQ, sizeof(answer)-1); \ + tt_int_op(srm_alen, OP_LT, 512); \ + tt_int_op(srm_answer_is_set, OP_EQ, 1); \ + tt_mem_op(srm_answer, OP_EQ, answer, sizeof(answer)-1); \ + } else { \ + tt_int_op(srm_answer_is_set, OP_EQ, 0); \ + } \ + tt_int_op(srm_ttl, OP_EQ, ttl); \ + tt_i64_op(srm_expires, OP_EQ, expires); \ } while (0) (void)arg; @@ -930,7 +937,7 @@ test_relaycell_resolved(void *arg) /* Try with connection in non-RESOLVE_WAIT state: cell gets ignored */ MOCK_RESET(); - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); tt_int_op(srm_ncalls, OP_EQ, 0); tt_int_op(mum_ncalls, OP_EQ, 0); @@ -944,7 +951,7 @@ test_relaycell_resolved(void *arg) /* We prefer ipv4, so we should get the first ipv4 answer */ MOCK_RESET(); - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -953,7 +960,7 @@ test_relaycell_resolved(void *arg) /* But we may be discarding private answers. */ MOCK_RESET(); options->ClientDNSRejectInternalAddresses = 1; - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -962,7 +969,7 @@ test_relaycell_resolved(void *arg) /* now prefer ipv6, and get the first ipv6 answer */ entryconn->entry_cfg.prefer_ipv6 = 1; MOCK_RESET(); - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -974,7 +981,7 @@ test_relaycell_resolved(void *arg) /* With a cell that only has IPv4, we report IPv4 even if we prefer IPv6 */ MOCK_RESET(); SET_CELL("\x04\x04\x12\x00\x00\x01\x00\x00\x02\x00"); - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -984,7 +991,7 @@ test_relaycell_resolved(void *arg) * ipv4 */ MOCK_RESET(); entryconn->entry_cfg.ipv4_traffic = 0; - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -994,7 +1001,7 @@ test_relaycell_resolved(void *arg) MOCK_RESET(); entryconn->entry_cfg.ipv4_traffic = 1; entryconn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -1003,7 +1010,7 @@ test_relaycell_resolved(void *arg) /* A hostname cell is fine though. */ MOCK_RESET(); SET_CELL("\x00\x0fwww.example.com\x00\x01\x00\x00"); - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); @@ -1013,7 +1020,7 @@ test_relaycell_resolved(void *arg) MOCK_RESET(); entryconn->socks_request->command = SOCKS_COMMAND_RESOLVE; SET_CELL("\x04\x04\x01\x02\x03\x04"); /* no ttl */ - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_TORPROTOCOL); tt_int_op(srm_ncalls, OP_EQ, 0); @@ -1024,7 +1031,7 @@ test_relaycell_resolved(void *arg) "\x04\x04\x7f\x00\x01\x02\x00\x00\x01\x00" /* IPv4: 192.168.1.1, ttl 256 */ "\x04\x04\xc0\xa8\x01\x01\x00\x00\x01\x00"); - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_TORPROTOCOL); ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR_TRANSIENT, NULL, 0, TIME_MAX); @@ -1032,13 +1039,14 @@ test_relaycell_resolved(void *arg) /* Legit error code */ MOCK_RESET(); SET_CELL("\xf0\x15" "quiet and meaningless" "\x00\x00\x0f\xff"); - r = connection_edge_process_resolved_cell(edgeconn, &cell, &rh); + r = connection_edge_process_resolved_cell(edgeconn, msg); tt_int_op(r, OP_EQ, 0); ASSERT_MARK_CALLED(END_STREAM_REASON_DONE| END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); ASSERT_RESOLVED_CALLED(RESOLVED_TYPE_ERROR_TRANSIENT, NULL, -1, -1); done: + relay_msg_free(msg); UNMOCK(connection_mark_unattached_ap_); UNMOCK(connection_ap_handshake_socks_resolved); } diff --git a/src/test/test_sendme.c b/src/test/test_sendme.c index 6dd1842501..7ece88c2cc 100644 --- a/src/test/test_sendme.c +++ b/src/test/test_sendme.c @@ -235,9 +235,11 @@ static void test_package_payload_len(void *arg) { (void)arg; - /* this is not a real circuit: it only has the fields needed for this - * test. */ - circuit_t *c = tor_malloc_zero(sizeof(circuit_t)); + or_circuit_t *or_circ = or_circuit_new(0, NULL); + crypt_path_t *cpath = NULL; + circuit_t *c = TO_CIRCUIT(or_circ); + + or_circ->relay_cell_format = RELAY_CELL_FORMAT_V0; /* check initial conditions. */ circuit_reset_sendme_randomness(c); @@ -248,15 +250,16 @@ test_package_payload_len(void *arg) /* We have a bunch of cells before we need to send randomness, so the first * few can be packaged full. */ int initial = c->send_randomness_after_n_cells; - size_t n = connection_edge_get_inbuf_bytes_to_package(10000, 0, c); + size_t n = connection_edge_get_inbuf_bytes_to_package(10000, 0, c, cpath); tt_uint_op(RELAY_PAYLOAD_SIZE, OP_EQ, n); - n = connection_edge_get_inbuf_bytes_to_package(95000, 1, c); + n = connection_edge_get_inbuf_bytes_to_package(95000, 1, c, cpath); tt_uint_op(RELAY_PAYLOAD_SIZE, OP_EQ, n); tt_int_op(c->send_randomness_after_n_cells, OP_EQ, initial - 2); /* If package_partial isn't set, we won't package a partially full cell at * all. */ - n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-1, 0, c); + n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-1, 0, + c, cpath); tt_int_op(n, OP_EQ, 0); /* no change in our state, since nothing was sent. */ tt_assert(! c->have_sent_sufficiently_random_cell); @@ -265,13 +268,15 @@ test_package_payload_len(void *arg) /* If package_partial is set and the partial cell is not going to have * _enough_ randomness, we package it, but we don't consider ourselves to * have sent a sufficiently random cell. */ - n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-1, 1, c); + n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-1, 1, + c, cpath); tt_int_op(n, OP_EQ, RELAY_PAYLOAD_SIZE-1); tt_assert(! c->have_sent_sufficiently_random_cell); tt_int_op(c->send_randomness_after_n_cells, OP_EQ, initial - 3); /* Make sure we set have_set_sufficiently_random_cell as appropriate. */ - n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-64, 1, c); + n = connection_edge_get_inbuf_bytes_to_package(RELAY_PAYLOAD_SIZE-64, 1, + c, cpath); tt_int_op(n, OP_EQ, RELAY_PAYLOAD_SIZE-64); tt_assert(c->have_sent_sufficiently_random_cell); tt_int_op(c->send_randomness_after_n_cells, OP_EQ, initial - 4); @@ -280,7 +285,7 @@ test_package_payload_len(void *arg) * sent a sufficiently random cell, we will not force this one to have a gap. */ c->send_randomness_after_n_cells = 0; - n = connection_edge_get_inbuf_bytes_to_package(10000, 1, c); + n = connection_edge_get_inbuf_bytes_to_package(10000, 1, c, cpath); tt_int_op(n, OP_EQ, RELAY_PAYLOAD_SIZE); /* Now these will be reset. */ tt_assert(! c->have_sent_sufficiently_random_cell); @@ -289,7 +294,7 @@ test_package_payload_len(void *arg) /* What would happen if we hadn't sent a sufficiently random cell? */ c->send_randomness_after_n_cells = 0; - n = connection_edge_get_inbuf_bytes_to_package(10000, 1, c); + n = connection_edge_get_inbuf_bytes_to_package(10000, 1, c, cpath); const size_t reduced_payload_size = RELAY_PAYLOAD_SIZE - 4 - 16; tt_int_op(n, OP_EQ, reduced_payload_size); /* Now these will be reset. */ @@ -301,11 +306,12 @@ test_package_payload_len(void *arg) * package_partial==0 should mean we accept that many bytes. */ c->send_randomness_after_n_cells = 0; - n = connection_edge_get_inbuf_bytes_to_package(reduced_payload_size, 0, c); + n = connection_edge_get_inbuf_bytes_to_package(reduced_payload_size, 0, + c, cpath); tt_int_op(n, OP_EQ, reduced_payload_size); done: - tor_free(c); + circuit_free(c); } /* Check that circuit_sendme_is_next works with a window of 1000,