commit 0f2d45328dfcb16acb4a517711413a6f0386487a Merge: 31eaa81f59 adb248b6d6 Author: Nick Mathewson <ni...@torproject.org> Date: Thu Jun 10 08:52:39 2021 -0400
Merge branch 'maint-0.3.5' into maint-0.4.4 Conflicts resolved: src/core/or/relay.c changes/ticket40389 | 3 +++ src/core/or/relay.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --cc src/core/or/relay.c index 75d2d479e7,00353f47a9..78fda99a45 --- a/src/core/or/relay.c +++ b/src/core/or/relay.c @@@ -1503,108 -1428,104 +1503,127 @@@ connection_edge_process_relay_cell_not_ // return -1; } + /** + * Return true iff our decryption layer_hint is from the last hop + * in a circuit. + */ + static bool + relay_crypt_from_last_hop(origin_circuit_t *circ, crypt_path_t *layer_hint) + { + tor_assert(circ); + tor_assert(layer_hint); + tor_assert(circ->cpath); + + if (layer_hint != circ->cpath->prev) { + log_fn(LOG_PROTOCOL_WARN, LD_CIRC, + "Got unexpected relay data from intermediate hop"); + return false; + } + return true; + } + -/** An incoming relay cell has arrived on circuit <b>circ</b>. If - * <b>conn</b> is NULL this is a control cell, else <b>cell</b> is - * destined for <b>conn</b>. +/** Process a SENDME cell that arrived on <b>circ</b>. If it is a stream level + * cell, it is destined for the given <b>conn</b>. If it is a circuit level + * cell, it is destined for the <b>layer_hint</b>. The <b>domain</b> is the + * logging domain that should be used. * - * If <b>layer_hint</b> is defined, then we're the origin of the - * circuit, and it specifies the hop that packaged <b>cell</b>. - * - * 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, - edge_connection_t *conn, - crypt_path_t *layer_hint) + * 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) { - static int num_seen=0; - relay_header_t rh; - unsigned domain = layer_hint?LD_APP:LD_EXIT; - int reason; - 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. */ + int ret; - tor_assert(cell); - 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); + tor_assert(rh); - 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; + if (!rh->stream_id) { + /* Circuit level SENDME cell. */ + ret = sendme_process_circuit_level(layer_hint, circ, + cell->payload + RELAY_HEADER_SIZE, + rh->length); + if (ret < 0) { + return ret; + } + /* Resume reading on any streams now that we've processed a valid + * SENDME cell that updated our package window. */ + circuit_resume_edge_reading(circ, layer_hint); + /* We are done, the rest of the code is for the stream level. */ + return 0; } - if (rh.stream_id == 0) { - switch (rh.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); - return 0; - default: - ; + /* No connection, might be half edge state. We are done if so. */ + if (!conn) { + 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); + log_info(domain, "Sendme cell on circ %u valid on half-closed " + "stream id %d", + ocirc->global_identifier, rh->stream_id); + } } + + log_info(domain, "SENDME cell dropped, unknown stream (streamid %d).", + rh->stream_id); + return 0; } - /* either conn is NULL, in which case we've got a control cell, or else - * conn points to the recognized stream. */ + /* Stream level SENDME cell. */ + ret = sendme_process_stream_level(conn, circ, rh->length); + if (ret < 0) { + /* Means we need to close the circuit with reason ret. */ + return ret; + } - if (conn && !connection_state_is_open(TO_CONN(conn))) { - 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) { - /* 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) { - 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); - } + /* We've now processed properly a SENDME cell, all windows have been + * properly updated, we'll read on the edge connection to see if we can + * get data out towards the end point (Exit or client) since we are now + * allowed to deliver more cells. */ + + if (circuit_queue_streams_are_blocked(circ)) { + /* Still waiting for queue to flush; don't touch conn */ + return 0; } + connection_start_reading(TO_CONN(conn)); + /* handle whatever might still be on the inbuf */ + if (connection_edge_package_raw_inbuf(conn, 1, NULL) < 0) { + /* (We already sent an end cell if possible) */ + connection_mark_for_close(TO_CONN(conn)); + return 0; + } + return 0; +} - switch (rh.command) { - case RELAY_COMMAND_DROP: - rep_hist_padding_count_read(PADDING_TYPE_DROP); -// log_info(domain,"Got a relay-level padding cell. Dropping."); - return 0; +/** A helper for connection_edge_process_relay_cell(): Actually handles the + * cell that we received on the connection. + * + * The arguments are the same as in the parent function + * connection_edge_process_relay_cell(), plus the relay header <b>rh</b> as + * unpacked by the parent function, and <b>optimistic_data</b> as set by the + * 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) +{ + unsigned domain = layer_hint?LD_APP:LD_EXIT; + int reason; + + tor_assert(rh); + + /* 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) { + log_debug(domain, "Cell handled as circuit padding"); + return 0; + } + + /* Now handle all the other commands */ + switch (rh->command) { case RELAY_COMMAND_BEGIN: case RELAY_COMMAND_BEGIN_DIR: if (layer_hint && @@@ -1716,10 -1635,11 +1735,19 @@@ if (!conn) { if (CIRCUIT_IS_ORIGIN(circ)) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); ++<<<<<<< HEAD + if (connection_half_edge_is_valid_end(ocirc->half_streams, + rh->stream_id)) { ++||||||| d71bf986b4faf7 ++ if (connection_half_edge_is_valid_end(ocirc->half_streams, ++ rh.stream_id)) { ++======= + if (relay_crypt_from_last_hop(ocirc, layer_hint) && + connection_half_edge_is_valid_end(ocirc->half_streams, + rh.stream_id)) { ++>>>>>>> maint-0.3.5 - circuit_read_valid_data(ocirc, rh.length); + circuit_read_valid_data(ocirc, rh->length); log_info(domain, "end cell (%s) on circ %u valid on half-closed " "stream id %d", @@@ -1926,12 -1938,13 +1954,23 @@@ if (CIRCUIT_IS_ORIGIN(circ)) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); ++<<<<<<< HEAD + if (connection_half_edge_is_valid_resolved(ocirc->half_streams, + rh->stream_id)) { + circuit_read_valid_data(ocirc, rh->length); ++||||||| d71bf986b4faf7 ++ if (connection_half_edge_is_valid_resolved(ocirc->half_streams, ++ rh.stream_id)) { ++ circuit_read_valid_data(ocirc, rh.length); ++======= + 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); ++>>>>>>> maint-0.3.5 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, rh->stream_id); return 0; } } _______________________________________________ tor-commits mailing list tor-commits@lists.torproject.org https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits