Tor 0.4.9.8
Loading...
Searching...
No Matches
sendme.c
Go to the documentation of this file.
1/* Copyright (c) 2019-2021, The Tor Project, Inc. */
2/* See LICENSE for licensing information */
3
4/**
5 * \file sendme.c
6 * \brief Code that is related to SENDME cells both in terms of
7 * creating/parsing cells and handling the content.
8 */
9
10// For access to cpath pvt_crypto field.
11#define SENDME_PRIVATE
12#define CRYPT_PATH_PRIVATE
13
14#include "core/or/or.h"
15
16#include "app/config/config.h"
19#include "core/or/cell_st.h"
20#include "core/or/crypt_path.h"
21#include "core/or/circuitlist.h"
22#include "core/or/circuituse.h"
23#include "core/or/or_circuit_st.h"
24#include "core/or/relay.h"
25#include "core/or/sendme.h"
29#include "lib/ctime/di_ops.h"
30#include "trunnel/sendme_cell.h"
31
32/**
33 * Return true iff tag_len is some length we recognize.
34 */
35static inline bool
36tag_len_ok(size_t tag_len)
37{
38 return tag_len == SENDME_TAG_LEN_CGO || tag_len == SENDME_TAG_LEN_TOR1;
39}
40
41/* Return the minimum version given by the consensus (if any) that should be
42 * used when emitting a SENDME cell. */
43STATIC int
44get_emit_min_version(void)
45{
46 return networkstatus_get_param(NULL, "sendme_emit_min_version",
47 SENDME_EMIT_MIN_VERSION_DEFAULT,
48 SENDME_EMIT_MIN_VERSION_MIN,
49 SENDME_EMIT_MIN_VERSION_MAX);
50}
51
52/* Return the minimum version given by the consensus (if any) that should be
53 * accepted when receiving a SENDME cell. */
54STATIC int
55get_accept_min_version(void)
56{
57 return networkstatus_get_param(NULL, "sendme_accept_min_version",
58 SENDME_ACCEPT_MIN_VERSION_DEFAULT,
59 SENDME_ACCEPT_MIN_VERSION_MIN,
60 SENDME_ACCEPT_MIN_VERSION_MAX);
61}
62
63/* Pop the first cell digset on the given circuit from the SENDME last digests
64 * list. NULL is returned if the list is uninitialized or empty.
65 *
66 * The caller gets ownership of the returned digest thus is responsible for
67 * freeing the memory. */
68static uint8_t *
69pop_first_cell_digest(const circuit_t *circ)
70{
71 uint8_t *circ_digest;
72
73 tor_assert(circ);
74
75 if (circ->sendme_last_digests == NULL ||
76 smartlist_len(circ->sendme_last_digests) == 0) {
77 return NULL;
78 }
79
80 circ_digest = smartlist_get(circ->sendme_last_digests, 0);
82 return circ_digest;
83}
84
85/* Return true iff the given cell tag matches the first digest in the
86 * circuit sendme list. */
87static bool
88v1_tag_matches(const uint8_t *circ_digest,
89 const uint8_t *cell_tag, size_t tag_len)
90{
91 tor_assert(circ_digest);
92 tor_assert(cell_tag);
93
94 /* Compare the digest with the one in the SENDME. This cell is invalid
95 * without a perfect match. */
96 if (tor_memneq(circ_digest, cell_tag, tag_len)) {
97 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
98 "SENDME v1 cell digest do not match.");
99 return false;
100 }
101
102 /* Digests matches! */
103 return true;
104}
105
106/* Return true iff the given decoded SENDME version 1 cell is valid and
107 * matches the expected digest on the circuit.
108 *
109 * Validation is done by comparing the digest in the cell from the previous
110 * cell we saw which tells us that the other side has in fact seen that cell.
111 * See proposal 289 for more details. */
112static bool
113cell_v1_is_valid(const sendme_cell_t *cell, const uint8_t *circ_digest,
114 size_t circ_digest_len)
115{
116 tor_assert(cell);
117 tor_assert(circ_digest);
118
119 size_t tag_len = sendme_cell_get_data_len(cell);
120 if (! tag_len_ok(tag_len))
121 return false;
122 if (sendme_cell_getlen_data_v1_digest(cell) < tag_len)
123 return false;
124 if (tag_len != circ_digest_len)
125 return false;
126
127 const uint8_t *cell_digest = sendme_cell_getconstarray_data_v1_digest(cell);
128 return v1_tag_matches(circ_digest, cell_digest, tag_len);
129}
130
131/* Return true iff the given cell version can be handled or if the minimum
132 * accepted version from the consensus is known to us. */
133STATIC bool
134cell_version_can_be_handled(uint8_t cell_version)
135{
136 int accept_version = get_accept_min_version();
137
138 /* We will first check if the consensus minimum accepted version can be
139 * handled by us and if not, regardless of the cell version we got, we can't
140 * continue. */
141 if (accept_version > SENDME_MAX_SUPPORTED_VERSION) {
142 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
143 "Unable to accept SENDME version %u (from consensus). "
144 "We only support <= %u. Probably your tor is too old?",
145 accept_version, SENDME_MAX_SUPPORTED_VERSION);
146 goto invalid;
147 }
148
149 /* Then, is this version below the accepted version from the consensus? If
150 * yes, we must not handle it. */
151 if (cell_version < accept_version) {
152 log_info(LD_PROTOCOL, "Unacceptable SENDME version %u. Only "
153 "accepting %u (from consensus). Closing circuit.",
154 cell_version, accept_version);
155 goto invalid;
156 }
157
158 /* Is this cell version supported by us? */
159 if (cell_version > SENDME_MAX_SUPPORTED_VERSION) {
160 log_info(LD_PROTOCOL, "SENDME cell version %u is not supported by us. "
161 "We only support <= %u",
162 cell_version, SENDME_MAX_SUPPORTED_VERSION);
163 goto invalid;
164 }
165
166 return true;
167 invalid:
168 return false;
169}
170
171/* Return true iff the encoded SENDME cell in cell_payload of length
172 * cell_payload_len is valid. For each version:
173 *
174 * 0: No validation
175 * 1: Authenticated with last cell digest.
176 *
177 * This is the main critical function to make sure we can continue to
178 * send/recv cells on a circuit. If the SENDME is invalid, the circuit should
179 * be marked for close by the caller. */
180/*
181 * NOTE: This function uses `layer_hint` to determine
182 * what the sendme tag length will be, and nothing else.
183 * Notably, we _don't_ keep a separate queue
184 * of expected tags for each layer!
185 */
186STATIC bool
187sendme_is_valid(circuit_t *circ,
188 const crypt_path_t *layer_hint,
189 const uint8_t *cell_payload,
190 size_t cell_payload_len)
191{
192 uint8_t cell_version;
193 uint8_t *circ_digest = NULL;
194 sendme_cell_t *cell = NULL;
195
196 tor_assert(circ);
197 tor_assert(cell_payload);
198
199 /* An empty payload means version 0 so skip trunnel parsing. We won't be
200 * able to parse a 0 length buffer into a valid SENDME cell. */
201 if (cell_payload_len == 0) {
202 cell_version = 0;
203 } else {
204 /* First we'll decode the cell so we can get the version. */
205 if (sendme_cell_parse(&cell, cell_payload, cell_payload_len) < 0) {
206 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
207 "Unparseable SENDME cell received. Closing circuit.");
208 goto invalid;
209 }
210 cell_version = sendme_cell_get_version(cell);
211 }
212
213 /* Validate that we can handle this cell version. */
214 if (CIRCUIT_IS_ORCIRC(circ) &&
215 TO_OR_CIRCUIT(circ)->used_legacy_circuit_handshake &&
216 cell_version == 0) {
217 /* exception, allow v0 sendmes on circuits made with CREATE_FAST */
218 log_info(LD_CIRC, "Permitting sendme version 0 on legacy circuit.");
219 /* Record this choice on the circuit, so we can avoid counting
220 * directory fetches on this circuit toward our geoip stats. */
222 } else if (!cell_version_can_be_handled(cell_version)) {
223 goto invalid;
224 }
225
226 /* Determine the expected tag length for this sendme. */
227 size_t circ_expects_tag_len;
228 if (layer_hint) {
229 circ_expects_tag_len =
230 relay_crypto_sendme_tag_len(&layer_hint->pvt_crypto);
231 } else if (CIRCUIT_IS_ORCIRC(circ)) {
232 const or_circuit_t *or_circ = CONST_TO_OR_CIRCUIT(circ);
233 circ_expects_tag_len = relay_crypto_sendme_tag_len(&or_circ->crypto);
234 } else {
236 goto invalid;
237 }
238
239 /* Pop the first element that was added (FIFO). We do that regardless of the
240 * version so we don't accumulate on the circuit if v0 is used by the other
241 * end point. */
242 circ_digest = pop_first_cell_digest(circ);
243 if (circ_digest == NULL) {
244 /* We shouldn't have received a SENDME if we have no digests. Log at
245 * protocol warning because it can be tricked by sending many SENDMEs
246 * without prior data cell. */
247 log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
248 "We received a SENDME but we have no cell digests to match. "
249 "Closing circuit.");
250 goto invalid;
251 } /* Validate depending on the version now. */
252 switch (cell_version) {
253 case 0x01:
254 if (!cell_v1_is_valid(cell, circ_digest, circ_expects_tag_len)) {
255 goto invalid;
256 }
257 break;
258 case 0x00:
259 /* Version 0, there is no work to be done on the payload so it is
260 * necessarily valid if we pass the version validation. */
261 break;
262 default:
263 log_warn(LD_PROTOCOL, "Unknown SENDME cell version %d received.",
264 cell_version);
266 break;
267 }
268
269 /* Valid cell. */
270 sendme_cell_free(cell);
271 tor_free(circ_digest);
272 return true;
273 invalid:
274 sendme_cell_free(cell);
275 tor_free(circ_digest);
276 return false;
277}
278
279/* Build and encode a version 1 SENDME cell into payload, which must be at
280 * least of RELAY_PAYLOAD_SIZE_MAX bytes, using the digest for the cell data.
281 *
282 * Return the size in bytes of the encoded cell in payload. A negative value
283 * is returned on encoding failure. */
284STATIC ssize_t
285build_cell_payload_v1(const uint8_t *cell_tag, const size_t tag_len,
286 uint8_t *payload)
287{
288 ssize_t len = -1;
289 sendme_cell_t *cell = NULL;
290
291 tor_assert(cell_tag);
292 tor_assert(tag_len_ok(tag_len));
293 tor_assert(payload);
294
295 cell = sendme_cell_new();
296
297 /* Building a payload for version 1. */
298 sendme_cell_set_version(cell, 0x01);
299 /* Set the data length field for v1. */
300 sendme_cell_set_data_len(cell, tag_len);
301 sendme_cell_setlen_data_v1_digest(cell, tag_len);
302
303 /* Copy the digest into the data payload. */
304 memcpy(sendme_cell_getarray_data_v1_digest(cell), cell_tag, tag_len);
305
306 /* Finally, encode the cell into the payload. */
307 len = sendme_cell_encode(payload, RELAY_PAYLOAD_SIZE_MAX, cell);
308
309 sendme_cell_free(cell);
310 return len;
311}
312
313/* Send a circuit-level SENDME on the given circuit using the layer_hint if
314 * not NULL. The digest is only used for version 1.
315 *
316 * Return 0 on success else a negative value and the circuit will be closed
317 * because we failed to send the cell on it. */
318static int
319send_circuit_level_sendme(circuit_t *circ, crypt_path_t *layer_hint,
320 const uint8_t *cell_tag, size_t tag_len)
321{
322 uint8_t emit_version;
323 uint8_t payload[RELAY_PAYLOAD_SIZE_MAX];
324 ssize_t payload_len;
325
326 tor_assert(circ);
327 tor_assert(cell_tag);
328
329 emit_version = get_emit_min_version();
330 switch (emit_version) {
331 case 0x01:
332 payload_len = build_cell_payload_v1(cell_tag, tag_len, payload);
333 if (BUG(payload_len < 0)) {
334 /* Unable to encode the cell, abort. We can recover from this by closing
335 * the circuit but in theory it should never happen. */
336 return -1;
337 }
338 log_debug(LD_PROTOCOL, "Emitting SENDME version 1 cell.");
339 break;
340 case 0x00:
341 FALLTHROUGH;
342 default:
343 /* Unknown version, fallback to version 0 meaning no payload. */
344 payload_len = 0;
345 log_debug(LD_PROTOCOL, "Emitting SENDME version 0 cell. "
346 "Consensus emit version is %d", emit_version);
347 break;
348 }
349
350 if (relay_send_command_from_edge(0, circ, RELAY_COMMAND_SENDME,
351 (char *) payload, payload_len,
352 layer_hint) < 0) {
353 log_warn(LD_CIRC,
354 "SENDME relay_send_command_from_edge failed. Circuit's closed.");
355 return -1; /* the circuit's closed, don't continue */
356 }
357 return 0;
358}
359
360/* Record the sendme tag as expected in a future SENDME, */
361static void
362record_cell_digest_on_circ(circuit_t *circ,
363 const uint8_t *sendme_tag,
364 size_t tag_len)
365{
366 tor_assert(circ);
367 tor_assert(sendme_tag);
368
369 /* Add the digest to the last seen list in the circuit. */
370 if (circ->sendme_last_digests == NULL) {
372 }
373 // We always allocate the largest possible tag here to
374 // make sure we don't have heap overflow bugs.
375 uint8_t *tag;
376 if (tag_len == SENDME_TAG_LEN_CGO) {
377 tag = tor_malloc_zero(SENDME_TAG_LEN_TOR1);
378 memcpy(tag, sendme_tag, tag_len);
379 // (The final bytes were initialized to zero.)
380 } else if (tag_len == SENDME_TAG_LEN_TOR1) {
381 tag = tor_memdup(sendme_tag, SENDME_TAG_LEN_TOR1);
382 } else {
383 tor_assert_unreached();
384 }
385
387}
388
389/*
390 * Public API
391 */
392
393/** Called when we've just received a relay data cell, when we've just
394 * finished flushing all bytes to stream <b>conn</b>, or when we've flushed
395 * *some* bytes to the stream <b>conn</b>.
396 *
397 * If conn->outbuf is not too full, and our deliver window is low, send back a
398 * suitable number of stream-level sendme cells.
399 */
400void
402{
403 tor_assert(conn);
404
405 int log_domain = TO_CONN(conn)->type == CONN_TYPE_AP ? LD_APP : LD_EXIT;
406
407 /* If we use flow control, we do not send stream sendmes */
408 if (edge_uses_flow_control(conn))
409 goto end;
410
411 /* Don't send it if we still have data to deliver. */
413 goto end;
414 }
415
416 if (circuit_get_by_edge_conn(conn) == NULL) {
417 /* This can legitimately happen if the destroy has already arrived and
418 * torn down the circuit. */
419 log_info(log_domain, "No circuit associated with edge connection. "
420 "Skipping sending SENDME.");
421 goto end;
422 }
423
424 while (conn->deliver_window <=
426 log_debug(log_domain, "Outbuf %" TOR_PRIuSZ ", queuing stream SENDME.",
427 buf_datalen(TO_CONN(conn)->outbuf));
429 if (connection_edge_send_command(conn, RELAY_COMMAND_SENDME,
430 NULL, 0) < 0) {
431 log_debug(LD_CIRC, "connection_edge_send_command failed while sending "
432 "a SENDME. Circuit probably closed, skipping.");
433 goto end; /* The circuit's closed, don't continue */
434 }
435 }
436
437 end:
438 return;
439}
440
441/** Check if the deliver_window for circuit <b>circ</b> (at hop
442 * <b>layer_hint</b> if it's defined) is low enough that we should
443 * send a circuit-level sendme back down the circuit. If so, send
444 * enough sendmes that the window would be overfull if we sent any
445 * more.
446 */
447void
449{
450 bool sent_one_sendme = false;
451 const uint8_t *tag;
452 size_t tag_len = 0;
453 int sendme_inc = sendme_get_inc_count(circ, layer_hint);
454
455 while ((layer_hint ? layer_hint->deliver_window : circ->deliver_window) <=
456 CIRCWINDOW_START - sendme_inc) {
457 log_debug(LD_CIRC,"Queuing circuit sendme.");
458 if (layer_hint) {
459 layer_hint->deliver_window += sendme_inc;
460 tag = cpath_get_sendme_tag(layer_hint, &tag_len);
461 } else {
462 circ->deliver_window += sendme_inc;
463 tag = relay_crypto_get_sendme_tag(&TO_OR_CIRCUIT(circ)->crypto,
464 &tag_len);
465 }
466 if (send_circuit_level_sendme(circ, layer_hint, tag, tag_len) < 0) {
467 return; /* The circuit's closed, don't continue */
468 }
469 /* Current implementation is not suppose to send multiple SENDME at once
470 * because this means we would use the same relay crypto digest for each
471 * SENDME leading to a mismatch on the other side and the circuit to
472 * collapse. Scream loudly if it ever happens so we can address it. */
473 tor_assert_nonfatal(!sent_one_sendme);
474 sent_one_sendme = true;
475 }
476}
477
478/* Process a circuit-level SENDME cell that we just received. The layer_hint,
479 * if not NULL, is the Exit hop of the connection which means that we are a
480 * client. In that case, circ must be an origin circuit. The cell_body_len is
481 * the length of the SENDME cell payload (excluding the header). The
482 * cell_payload is the payload.
483 *
484 * This function validates the SENDME's digest, and then dispatches to
485 * the appropriate congestion control algorithm in use on the circuit.
486 *
487 * Return 0 on success (the SENDME is valid and the package window has
488 * been updated properly).
489 *
490 * On error, a negative value is returned, which indicates that the
491 * circuit must be closed using the value as the reason for it. */
492int
493sendme_process_circuit_level(crypt_path_t *layer_hint,
494 circuit_t *circ, const uint8_t *cell_payload,
495 uint16_t cell_payload_len)
496{
497 tor_assert(circ);
498 tor_assert(cell_payload);
500
501 /* Validate the SENDME cell. Depending on the version, different validation
502 * can be done. An invalid SENDME requires us to close the circuit. */
503 if (!sendme_is_valid(circ, layer_hint, cell_payload, cell_payload_len)) {
504 return -END_CIRC_REASON_TORPROTOCOL;
505 }
506
507 /* origin circuits need to count valid sendmes as valid protocol data */
508 if (CIRCUIT_IS_ORIGIN(circ)) {
509 circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), cell_payload_len);
510 }
511
512 // Get CC
513 if (layer_hint) {
514 cc = layer_hint->ccontrol;
515 } else {
516 cc = circ->ccontrol;
517 }
518
519 /* If there is no CC object, assume fixed alg */
520 if (!cc) {
521 return sendme_process_circuit_level_impl(layer_hint, circ);
522 }
523
524 return congestion_control_dispatch_cc_alg(cc, circ);
525}
526
527/**
528 * Process a SENDME for Tor's original fixed window circuit-level flow control.
529 * Updates the package_window and ensures that it does not exceed the max.
530 *
531 * Returns -END_CIRC_REASON_TORPROTOCOL if the max is exceeded, otherwise
532 * returns 0.
533 */
534int
536{
537 /* If we are the origin of the circuit, we are the Client so we use the
538 * layer hint (the Exit hop) for the package window tracking. */
539 if (CIRCUIT_IS_ORIGIN(circ)) {
540 /* If we are the origin of the circuit, it is impossible to not have a
541 * cpath. Just in case, bug on it and close the circuit. */
542 if (BUG(layer_hint == NULL)) {
543 return -END_CIRC_REASON_TORPROTOCOL;
544 }
545 if ((layer_hint->package_window + CIRCWINDOW_INCREMENT) >
546 CIRCWINDOW_START_MAX) {
547 static struct ratelim_t exit_warn_ratelim = RATELIM_INIT(600);
548 log_fn_ratelim(&exit_warn_ratelim, LOG_WARN, LD_PROTOCOL,
549 "Unexpected sendme cell from exit relay. "
550 "Closing circ.");
551 return -END_CIRC_REASON_TORPROTOCOL;
552 }
554 log_debug(LD_APP, "circ-level sendme at origin, packagewindow %d.",
555 layer_hint->package_window);
556 } else {
557 /* We aren't the origin of this circuit so we are the Exit and thus we
558 * track the package window with the circuit object. */
560 CIRCWINDOW_START_MAX) {
561 static struct ratelim_t client_warn_ratelim = RATELIM_INIT(600);
562 log_fn_ratelim(&client_warn_ratelim, LOG_PROTOCOL_WARN, LD_PROTOCOL,
563 "Unexpected sendme cell from client. "
564 "Closing circ (window %d).", circ->package_window);
565 return -END_CIRC_REASON_TORPROTOCOL;
566 }
568 log_debug(LD_EXIT, "circ-level sendme at non-origin, packagewindow %d.",
569 circ->package_window);
570 }
571
572 return 0;
573}
574
575/* Process a stream-level SENDME cell that we just received. The conn is the
576 * edge connection (stream) that the circuit circ is associated with. The
577 * cell_body_len is the length of the payload (excluding the header).
578 *
579 * Return 0 on success (the SENDME is valid and the package window has
580 * been updated properly).
581 *
582 * On error, a negative value is returned, which indicates that the
583 * circuit must be closed using the value as the reason for it. */
584int
585sendme_process_stream_level(edge_connection_t *conn, circuit_t *circ,
586 uint16_t cell_body_len)
587{
588 tor_assert(conn);
589 tor_assert(circ);
590
591 if (edge_uses_flow_control(conn)) {
592 log_fn(LOG_PROTOCOL_WARN, LD_EDGE,
593 "Congestion control got stream sendme");
594 return -END_CIRC_REASON_TORPROTOCOL;
595 }
596
597 /* Don't allow the other endpoint to request more than our maximum (i.e.
598 * initial) stream SENDME window worth of data. Well-behaved stock clients
599 * will not request more than this max (as per the check in the while loop
600 * of sendme_connection_edge_consider_sending()). */
602 STREAMWINDOW_START_MAX) {
603 static struct ratelim_t stream_warn_ratelim = RATELIM_INIT(600);
604 log_fn_ratelim(&stream_warn_ratelim, LOG_PROTOCOL_WARN, LD_PROTOCOL,
605 "Unexpected stream sendme cell. Closing circ (window %d).",
606 conn->package_window);
607 return -END_CIRC_REASON_TORPROTOCOL;
608 }
609 /* At this point, the stream sendme is valid */
611
612 /* We count circuit-level sendme's as valid delivered data because they are
613 * rate limited. */
614 if (CIRCUIT_IS_ORIGIN(circ)) {
615 circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), cell_body_len);
616 }
617
618 log_debug(CIRCUIT_IS_ORIGIN(circ) ? LD_APP : LD_EXIT,
619 "stream-level sendme, package_window now %d.",
620 conn->package_window);
621 return 0;
622}
623
624/* Called when a relay DATA cell is received on the given circuit. If
625 * layer_hint is NULL, this means we are the Exit end point else we are the
626 * Client. Update the deliver window and return its new value. */
627int
628sendme_circuit_data_received(circuit_t *circ, crypt_path_t *layer_hint)
629{
630 int deliver_window, domain;
631
632 if (CIRCUIT_IS_ORIGIN(circ)) {
633 tor_assert(layer_hint);
634 --layer_hint->deliver_window;
635 deliver_window = layer_hint->deliver_window;
636 domain = LD_APP;
637 } else {
638 tor_assert(!layer_hint);
639 --circ->deliver_window;
640 deliver_window = circ->deliver_window;
641 domain = LD_EXIT;
642 }
643
644 log_debug(domain, "Circuit deliver_window now %d.", deliver_window);
645 return deliver_window;
646}
647
648/* Called when a relay DATA cell is received for the given edge connection
649 * conn. Update the deliver window and return its new value. */
650int
651sendme_stream_data_received(edge_connection_t *conn)
652{
653 tor_assert(conn);
654
655 if (edge_uses_flow_control(conn)) {
656 return flow_control_decide_xoff(conn);
657 } else {
658 return --conn->deliver_window;
659 }
660}
661
662/* Called when a relay DATA cell is packaged on the given circuit. If
663 * layer_hint is NULL, this means we are the Exit end point else we are the
664 * Client. Update the package window and return its new value. */
665int
666sendme_note_circuit_data_packaged(circuit_t *circ, crypt_path_t *layer_hint)
667{
668 int package_window, domain;
670
671 tor_assert(circ);
672
673 if (layer_hint) {
674 cc = layer_hint->ccontrol;
675 domain = LD_APP;
676 } else {
677 cc = circ->ccontrol;
678 domain = LD_EXIT;
679 }
680
681 if (cc) {
682 congestion_control_note_cell_sent(cc, circ, layer_hint);
683 } else {
684 /* Fixed alg uses package_window and must update it */
685
686 if (CIRCUIT_IS_ORIGIN(circ)) {
687 /* Client side. */
688 tor_assert(layer_hint);
689 --layer_hint->package_window;
690 package_window = layer_hint->package_window;
691 } else {
692 /* Exit side. */
693 tor_assert(!layer_hint);
694 --circ->package_window;
695 package_window = circ->package_window;
696 }
697 log_debug(domain, "Circuit package_window now %d.", package_window);
698 }
699
700 /* Return appropriate number designating how many cells can still be sent */
701 return congestion_control_get_package_window(circ, layer_hint);
702}
703
704/* Called when a relay DATA cell is packaged for the given edge connection
705 * conn. Update the package window and return its new value. */
706int
707sendme_note_stream_data_packaged(edge_connection_t *conn, size_t len)
708{
709 tor_assert(conn);
710
711 if (edge_uses_flow_control(conn)) {
713 if (conn->xoff_received)
714 return -1;
715 else
716 return 1;
717 }
718
719 --conn->package_window;
720 log_debug(LD_APP, "Stream package_window now %d.", conn->package_window);
721 return conn->package_window;
722}
723
724/* Record the cell digest into the circuit sendme digest list depending on
725 * which edge we are. The digest is recorded only if we expect the next cell
726 * that we will receive is a SENDME so we can match the digest. */
727void
728sendme_record_cell_digest_on_circ(circuit_t *circ, crypt_path_t *cpath)
729{
730 const uint8_t *sendme_tag;
731 size_t tag_len = 0;
732
733 tor_assert(circ);
734
735 /* Is this the last cell before a SENDME? The idea is that if the
736 * package_window reaches a multiple of the increment, after this cell, we
737 * should expect a SENDME. */
738 if (!circuit_sent_cell_for_sendme(circ, cpath)) {
739 return;
740 }
741
742 /* Getting the digest is expensive so we only do it once we are certain to
743 * record it on the circuit. */
744 if (cpath) {
745 sendme_tag = cpath_get_sendme_tag(cpath, &tag_len);
746 } else {
747 sendme_tag =
748 relay_crypto_get_sendme_tag(&TO_OR_CIRCUIT(circ)->crypto, &tag_len);
749 }
750
751 record_cell_digest_on_circ(circ, sendme_tag, tag_len);
752}
size_t buf_datalen(const buf_t *buf)
Definition buffers.c:394
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_ORCIRC(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.
#define CONN_TYPE_AP
Definition connection.h:51
const uint8_t * cpath_get_sendme_tag(crypt_path_t *cpath, size_t *len_out)
Definition crypt_path.c:178
Header file for crypt_path.c.
Headers for di_ops.c.
#define tor_memneq(a, b, sz)
Definition di_ops.h:21
#define log_fn(severity, domain, args,...)
Definition log.h:283
#define log_fn_ratelim(ratelim, severity, domain, args,...)
Definition log.h:288
#define LD_EDGE
Definition log.h:94
#define LD_APP
Definition log.h:78
#define LD_PROTOCOL
Definition log.h:72
#define LD_CIRC
Definition log.h:82
#define LOG_WARN
Definition log.h:53
#define tor_free(p)
Definition malloc.h:56
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
Definition or.h:456
#define STREAMWINDOW_START
Definition or.h:453
#define SENDME_TAG_LEN_TOR1
Definition or.h:459
#define SENDME_TAG_LEN_CGO
Definition or.h:461
#define CIRCWINDOW_START
Definition or.h:446
#define TO_CONN(c)
Definition or.h:709
#define RELAY_PAYLOAD_SIZE_MAX
Definition or.h:576
#define CIRCWINDOW_INCREMENT
Definition or.h:450
int connection_edge_send_command(edge_connection_t *fromconn, uint8_t relay_command, const char *payload, size_t payload_len)
Definition relay.c:766
Header file for relay.c.
Header for relay_crypto.c.
void sendme_connection_edge_consider_sending(edge_connection_t *conn)
Definition sendme.c:401
void sendme_circuit_consider_sending(circuit_t *circ, crypt_path_t *layer_hint)
Definition sendme.c:448
static bool tag_len_ok(size_t tag_len)
Definition sendme.c:36
int sendme_process_circuit_level_impl(crypt_path_t *layer_hint, circuit_t *circ)
Definition sendme.c:535
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
Definition circuit_st.h:158
int deliver_window
Definition circuit_st.h:122
int package_window
Definition circuit_st.h:117
struct congestion_control_t * ccontrol
Definition circuit_st.h:260
struct congestion_control_t * ccontrol
bool used_obsolete_sendme
relay_crypto_t crypto
#define STATIC
Definition testsupport.h:32
#define tor_assert_nonfatal_unreached()
Definition util_bug.h:177
#define tor_assert(expr)
Definition util_bug.h:103