commit 023a70da841182fbbbe11389929c8fbbc7490365 Author: David Goulet dgoulet@torproject.org Date: Wed Jan 9 12:22:35 2019 -0500
prop289: Support sending SENDME version 1
This code will obey the consensus parameter "sendme_emit_min_version" to know which SENDME version it should send. For now, the default is 0 and the parameter is not yet used in the consensus.
This commit adds the support to send version 1 SENDMEs but aren't sent on the wire at this commit.
Closes #26840
Signed-off-by: David Goulet dgoulet@torproject.org --- src/core/or/relay.c | 2 +- src/core/or/sendme.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/core/or/sendme.h | 3 +- 3 files changed, 103 insertions(+), 8 deletions(-)
diff --git a/src/core/or/relay.c b/src/core/or/relay.c index 6ff053d8a..6f69ed999 100644 --- a/src/core/or/relay.c +++ b/src/core/or/relay.c @@ -1560,7 +1560,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, }
/* Consider sending a circuit-level SENDME cell. */ - sendme_circuit_consider_sending(circ, layer_hint); + sendme_circuit_consider_sending(circ, layer_hint, NULL);
if (rh.stream_id == 0) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Relay data cell with zero " diff --git a/src/core/or/sendme.c b/src/core/or/sendme.c index bba760ae9..f22e7027d 100644 --- a/src/core/or/sendme.c +++ b/src/core/or/sendme.c @@ -16,6 +16,7 @@ #include "core/or/relay.h" #include "core/or/sendme.h" #include "feature/nodelist/networkstatus.h" +#include "trunnel/sendme.h"
/* The cell version constants for when emitting a cell. */ #define SENDME_EMIT_MIN_VERSION_DEFAULT 0 @@ -38,6 +39,7 @@ get_emit_min_version(void) SENDME_EMIT_MIN_VERSION_MAX); }
+#if 0 /* Return the minimum version given by the consensus (if any) that should be * accepted when receiving a SENDME cell. */ static int @@ -48,6 +50,98 @@ get_accept_min_version(void) SENDME_ACCEPT_MIN_VERSION_MIN, SENDME_ACCEPT_MIN_VERSION_MAX); } +#endif + +/* Build and encode a version 1 SENDME cell into payload, which must be at + * least of RELAY_PAYLOAD_SIZE bytes, using the digest for the cell data. + * + * Return the size in bytes of the encoded cell in payload. A negative value + * is returned on encoding failure. */ +static ssize_t +build_cell_payload_v1(crypto_digest_t *cell_digest, uint8_t *payload) +{ + ssize_t len = -1; + sendme_cell_t *cell = NULL; + sendme_data_v1_t *data = NULL; + + tor_assert(cell_digest); + tor_assert(payload); + + cell = sendme_cell_new(); + data = sendme_data_v1_new(); + + /* Building a payload for version 1. */ + sendme_cell_set_version(cell, 0x01); + + /* Copy the digest into the data payload. */ + crypto_digest_get_digest(cell_digest, + (char *) sendme_data_v1_getarray_digest(data), + sendme_data_v1_getlen_digest(data)); + + /* Set the length of the data in the cell payload. It is the encoded length + * of the v1 data object. */ + sendme_cell_setlen_data(cell, sendme_data_v1_encoded_len(data)); + /* Encode into the cell's data field using its current length just set. */ + if (sendme_data_v1_encode(sendme_cell_getarray_data(cell), + sendme_cell_getlen_data(cell), data) < 0) { + goto end; + } + /* Set the DATA_LEN field to what we've just encoded. */ + sendme_cell_set_data_len(cell, sendme_cell_getlen_data(cell)); + + /* Finally, encode the cell into the payload. */ + len = sendme_cell_encode(payload, RELAY_PAYLOAD_SIZE, cell); + + end: + sendme_cell_free(cell); + sendme_data_v1_free(data); + return len; +} + +/* Send a circuit-level SENDME on the given circuit using the layer_hint if + * not NULL. The digest is only used for version 1. + * + * Return 0 on success else a negative value and the circuit will be closed + * because we failed to send the cell on it. */ +static int +send_circuit_level_sendme(circuit_t *circ, crypt_path_t *layer_hint, + crypto_digest_t *cell_digest) +{ + uint8_t emit_version; + uint8_t payload[RELAY_PAYLOAD_SIZE]; + ssize_t payload_len; + + tor_assert(circ); + tor_assert(cell_digest); + + emit_version = get_emit_min_version(); + switch (emit_version) { + case 0x01: + payload_len = build_cell_payload_v1(cell_digest, payload); + if (BUG(payload_len < 0)) { + /* Unable to encode the cell, abort. We can recover from this by closing + * the circuit but in theory it should never happen. */ + return -1; + } + log_debug(LD_PROTOCOL, "Emitting SENDME version 1 cell."); + break; + case 0x00: + /* Fallthrough because default is to use v0. */ + default: + /* Unknown version, fallback to version 0 meaning no payload. */ + payload_len = 0; + break; + } + + if (relay_send_command_from_edge(0, circ, RELAY_COMMAND_SENDME, + (char *) payload, payload_len, + layer_hint) < 0) { + log_warn(LD_CIRC, + "SENDME relay_send_command_from_edge failed. Circuit's closed."); + return -1; /* the circuit's closed, don't continue */ + } + return 0; +}
/** Called when we've just received a relay data cell, when we've just * finished flushing all bytes to stream <b>conn</b>, or when we've flushed @@ -100,8 +194,11 @@ sendme_connection_edge_consider_sending(edge_connection_t *conn) * more. */ void -sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint) +sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint, + crypto_digest_t *digest) { + tor_assert(digest); + while ((layer_hint ? layer_hint->deliver_window : circ->deliver_window) <= CIRCWINDOW_START - CIRCWINDOW_INCREMENT) { log_debug(LD_CIRC,"Queuing circuit sendme."); @@ -109,11 +206,8 @@ sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint) layer_hint->deliver_window += CIRCWINDOW_INCREMENT; else circ->deliver_window += CIRCWINDOW_INCREMENT; - if (relay_send_command_from_edge(0, circ, RELAY_COMMAND_SENDME, - NULL, 0, layer_hint) < 0) { - log_warn(LD_CIRC, - "relay_send_command_from_edge failed. Circuit's closed."); - return; /* the circuit's closed, don't continue */ + if (send_circuit_level_sendme(circ, layer_hint, digest) < 0) { + return; /* The circuit's closed, don't continue */ } } } diff --git a/src/core/or/sendme.h b/src/core/or/sendme.h index f50ccfbfe..ba01ecfaf 100644 --- a/src/core/or/sendme.h +++ b/src/core/or/sendme.h @@ -16,7 +16,8 @@ /* Sending SENDME cell. */ void sendme_connection_edge_consider_sending(edge_connection_t *edge_conn); void sendme_circuit_consider_sending(circuit_t *circ, - crypt_path_t *layer_hint); + crypt_path_t *layer_hint, + crypto_digest_t *digest);
/* Processing SENDME cell. */ int sendme_process_circuit_level(crypt_path_t *layer_hint,