21#include "core/or/or_circuit_st.h"
28#include "trunnel/sendme_cell.h"
33get_emit_min_version(
void)
36 SENDME_EMIT_MIN_VERSION_DEFAULT,
37 SENDME_EMIT_MIN_VERSION_MIN,
38 SENDME_EMIT_MIN_VERSION_MAX);
44get_accept_min_version(
void)
47 SENDME_ACCEPT_MIN_VERSION_DEFAULT,
48 SENDME_ACCEPT_MIN_VERSION_MIN,
49 SENDME_ACCEPT_MIN_VERSION_MAX);
58pop_first_cell_digest(
const circuit_t *circ)
77v1_digest_matches(
const uint8_t *circ_digest,
const uint8_t *cell_digest)
84 if (
tor_memneq(circ_digest, cell_digest, TRUNNEL_SENDME_V1_DIGEST_LEN)) {
86 "SENDME v1 cell digest do not match.");
101cell_v1_is_valid(
const sendme_cell_t *cell,
const uint8_t *circ_digest)
106 const uint8_t *cell_digest = sendme_cell_getconstarray_data_v1_digest(cell);
107 return v1_digest_matches(circ_digest, cell_digest);
113cell_version_can_be_handled(uint8_t cell_version)
115 int accept_version = get_accept_min_version();
120 if (accept_version > SENDME_MAX_SUPPORTED_VERSION) {
122 "Unable to accept SENDME version %u (from consensus). "
123 "We only support <= %u. Probably your tor is too old?",
124 accept_version, SENDME_MAX_SUPPORTED_VERSION);
130 if (cell_version < accept_version) {
131 log_info(
LD_PROTOCOL,
"Unacceptable SENDME version %u. Only "
132 "accepting %u (from consensus). Closing circuit.",
133 cell_version, accept_version);
138 if (cell_version > SENDME_MAX_SUPPORTED_VERSION) {
139 log_info(
LD_PROTOCOL,
"SENDME cell version %u is not supported by us. "
140 "We only support <= %u",
141 cell_version, SENDME_MAX_SUPPORTED_VERSION);
160sendme_is_valid(
const circuit_t *circ,
const uint8_t *cell_payload,
161 size_t cell_payload_len)
163 uint8_t cell_version;
164 uint8_t *circ_digest = NULL;
165 sendme_cell_t *cell = NULL;
172 if (cell_payload_len == 0) {
176 if (sendme_cell_parse(&cell, cell_payload, cell_payload_len) < 0) {
178 "Unparseable SENDME cell received. Closing circuit.");
181 cell_version = sendme_cell_get_version(cell);
185 if (!cell_version_can_be_handled(cell_version)) {
192 circ_digest = pop_first_cell_digest(circ);
193 if (circ_digest == NULL) {
198 "We received a SENDME but we have no cell digests to match. "
204 switch (cell_version) {
206 if (!cell_v1_is_valid(cell, circ_digest)) {
215 log_warn(
LD_PROTOCOL,
"Unknown SENDME cell version %d received.",
222 sendme_cell_free(cell);
226 sendme_cell_free(cell);
237build_cell_payload_v1(
const uint8_t *cell_digest, uint8_t *payload)
240 sendme_cell_t *cell = NULL;
245 cell = sendme_cell_new();
248 sendme_cell_set_version(cell, 0x01);
250 sendme_cell_set_data_len(cell, TRUNNEL_SENDME_V1_DIGEST_LEN);
253 memcpy(sendme_cell_getarray_data_v1_digest(cell), cell_digest,
254 sendme_cell_get_data_len(cell));
259 sendme_cell_free(cell);
270 const uint8_t *cell_digest)
272 uint8_t emit_version;
279 emit_version = get_emit_min_version();
280 switch (emit_version) {
282 payload_len = build_cell_payload_v1(cell_digest, payload);
283 if (BUG(payload_len < 0)) {
288 log_debug(
LD_PROTOCOL,
"Emitting SENDME version 1 cell.");
295 log_debug(
LD_PROTOCOL,
"Emitting SENDME version 0 cell. "
296 "Consensus emit version is %d", emit_version);
300 if (relay_send_command_from_edge(0, circ, RELAY_COMMAND_SENDME,
301 (
char *) payload, payload_len,
304 "SENDME relay_send_command_from_edge failed. Circuit's closed.");
312record_cell_digest_on_circ(
circuit_t *circ,
const uint8_t *sendme_digest)
391 log_info(log_domain,
"No circuit associated with edge connection. "
392 "Skipping sending SENDME.");
398 log_debug(log_domain,
"Outbuf %" TOR_PRIuSZ
", queuing stream SENDME.",
403 log_debug(
LD_CIRC,
"connection_edge_send_command failed while sending "
404 "a SENDME. Circuit probably closed, skipping.");
422 bool sent_one_sendme =
false;
423 const uint8_t *digest;
428 log_debug(
LD_CIRC,
"Queuing circuit sendme.");
436 if (send_circuit_level_sendme(circ, layer_hint, digest) < 0) {
443 tor_assert_nonfatal(!sent_one_sendme);
444 sent_one_sendme =
true;
464 circuit_t *circ,
const uint8_t *cell_payload,
465 uint16_t cell_payload_len)
473 if (!sendme_is_valid(circ, cell_payload, cell_payload_len)) {
474 return -END_CIRC_REASON_TORPROTOCOL;
512 if (BUG(layer_hint == NULL)) {
513 return -END_CIRC_REASON_TORPROTOCOL;
516 CIRCWINDOW_START_MAX) {
517 static struct ratelim_t exit_warn_ratelim = RATELIM_INIT(600);
519 "Unexpected sendme cell from exit relay. "
521 return -END_CIRC_REASON_TORPROTOCOL;
524 log_debug(
LD_APP,
"circ-level sendme at origin, packagewindow %d.",
530 CIRCWINDOW_START_MAX) {
531 static struct ratelim_t client_warn_ratelim = RATELIM_INIT(600);
533 "Unexpected sendme cell from client. "
535 return -END_CIRC_REASON_TORPROTOCOL;
538 log_debug(LD_EXIT,
"circ-level sendme at non-origin, packagewindow %d.",
556 uint16_t cell_body_len)
563 "Congestion control got stream sendme");
564 return -END_CIRC_REASON_TORPROTOCOL;
572 STREAMWINDOW_START_MAX) {
573 static struct ratelim_t stream_warn_ratelim = RATELIM_INIT(600);
575 "Unexpected stream sendme cell. Closing circ (window %d).",
577 return -END_CIRC_REASON_TORPROTOCOL;
589 "stream-level sendme, package_window now %d.",
600 int deliver_window, domain;
614 log_debug(domain,
"Circuit deliver_window now %d.", deliver_window);
615 return deliver_window;
638 int package_window, domain;
667 log_debug(domain,
"Circuit package_window now %d.", package_window);
700 uint8_t *sendme_digest;
720 record_cell_digest_on_circ(circ, sendme_digest);
size_t buf_datalen(const buf_t *buf)
Fixed-size cell structure.
circuit_t * circuit_get_by_edge_conn(edge_connection_t *conn)
origin_circuit_t * TO_ORIGIN_CIRCUIT(circuit_t *x)
or_circuit_t * TO_OR_CIRCUIT(circuit_t *x)
Header file for circuitlist.c.
#define CIRCUIT_IS_ORIGIN(c)
void circuit_read_valid_data(origin_circuit_t *circ, uint16_t relay_body_len)
Header file for circuituse.c.
Header file for config.c.
int sendme_get_inc_count(const circuit_t *circ, const crypt_path_t *layer_hint)
bool circuit_sent_cell_for_sendme(const circuit_t *circ, const crypt_path_t *layer_hint)
void congestion_control_note_cell_sent(congestion_control_t *cc, const circuit_t *circ, const crypt_path_t *cpath)
int congestion_control_dispatch_cc_alg(congestion_control_t *cc, circuit_t *circ)
int congestion_control_get_package_window(const circuit_t *circ, const crypt_path_t *cpath)
Public APIs for congestion control.
int flow_control_decide_xoff(edge_connection_t *stream)
void flow_control_note_sent_data(edge_connection_t *stream, size_t len)
bool edge_uses_flow_control(const edge_connection_t *stream)
APIs for stream flow control on congestion controlled circuits.
int connection_outbuf_too_full(connection_t *conn)
Header file for connection.c.
void cpath_sendme_record_cell_digest(crypt_path_t *cpath, bool is_foward_digest)
uint8_t * cpath_get_sendme_digest(crypt_path_t *cpath)
Header file for crypt_path.c.
#define tor_memneq(a, b, sz)
#define log_fn(severity, domain, args,...)
#define log_fn_ratelim(ratelim, severity, domain, args,...)
int32_t networkstatus_get_param(const networkstatus_t *ns, const char *param_name, int32_t default_val, int32_t min_val, int32_t max_val)
Header file for networkstatus.c.
Master header file for Tor-specific functionality.
#define STREAMWINDOW_INCREMENT
#define STREAMWINDOW_START
#define RELAY_PAYLOAD_SIZE
#define CIRCWINDOW_INCREMENT
int connection_edge_send_command(edge_connection_t *fromconn, uint8_t relay_command, const char *payload, size_t payload_len)
Header for relay_crypto.c.
uint8_t * relay_crypto_get_sendme_digest(relay_crypto_t *crypto)
void relay_crypto_record_sendme_digest(relay_crypto_t *crypto, bool is_foward_digest)
void sendme_connection_edge_consider_sending(edge_connection_t *conn)
void sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint)
STATIC bool circuit_sendme_cell_is_next(int deliver_window, int sendme_inc)
int sendme_process_circuit_level_impl(crypt_path_t *layer_hint, circuit_t *circ)
Header file for sendme.c.
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
void smartlist_del_keeporder(smartlist_t *sl, int idx)
smartlist_t * sendme_last_digests
struct congestion_control_t * ccontrol
struct congestion_control_t * ccontrol
#define tor_assert_nonfatal_unreached()