Tor 0.4.9.3-alpha-dev
Loading...
Searching...
No Matches
conflux_pool.c
Go to the documentation of this file.
1/* Copyright (c) 2021, The Tor Project, Inc. */
2/* See LICENSE for licensing information */
3
4/**
5 * \file conflux_pool.c
6 * \brief Conflux circuit pool management
7 */
8
9#define TOR_CONFLUX_PRIVATE
10#define CONFLUX_CELL_PRIVATE
11
12#include "core/or/or.h"
13
14#include "app/config/config.h"
15
17#include "core/or/circuitlist.h"
19#include "core/or/circuituse.h"
21#include "core/or/conflux.h"
23#include "trunnel/conflux.h"
27#include "core/or/relay.h"
30
32#include "core/or/or_circuit_st.h"
35#include "core/or/conflux_st.h"
36
39#include "app/config/config.h"
40
43
44/* Indicate if we are shutting down. This is used so we avoid recovering a
45 * conflux set on total shutdown. */
46static bool shutting_down = false;
47
48/** The pool of client-side conflux_t that are built, linked, and ready
49 * to be used. Indexed by nonce. */
50static digest256map_t *client_linked_pool;
51
52/** The pool of origin unlinked_circuits_t indexed by nonce. */
53static digest256map_t *client_unlinked_pool;
54
55/** The pool of relay conflux_t indexed by nonce. We call these "server"
56 * because they could be onion-service side too (even though we likely will
57 * only implement onion service conflux in Arti). The code is littered with
58 * asserts to ensure there are no origin circuits in here for now, too. */
59static digest256map_t *server_linked_pool;
60
61/** The pool of relay unlinked_circuits_t indexed by nonce. */
62static digest256map_t *server_unlinked_pool;
63
64/* A leg is essentially a circuit for a conflux set. We use this object for the
65 * unlinked pool. */
66typedef struct leg_t {
67 /* The circuit of the leg. */
68 circuit_t *circ;
69
70 /* The LINK cell content which is used to put the information back in the
71 * conflux_t object once all legs have linked and validate the ack. */
73
74 /* Indicate if the leg has received the LINKED or the LINKED_ACK cell
75 * depending on its side of the circuit. When all legs are linked, we then
76 * finalize the conflux_t object and move it to the linked pool. */
77 bool linked;
78
79 /* What time did we send the LINK/LINKED (depending on which side) so we can
80 * calculate the RTT. */
81 uint64_t link_sent_usec;
82
83 /* The RTT value in usec takend from the LINK <--> LINKED round trip. */
84 uint64_t rtt_usec;
85} leg_t;
86
87/* Object used to track unlinked circuits which are kept in the unlinked pool
88 * until they are linked and moved to the linked pool and global circuit set.
89 */
90typedef struct unlinked_circuits_t {
91 /* If true, indicate that this unlinked set is client side as in the legs are
92 * origin circuits. Else, it is on the exit side and thus or circuits. */
93 bool is_client;
94
95 /* If true, indicate if the conflux_t is related to a linked set. */
96 bool is_for_linked_set;
97
98 /* Conflux object that will be set in each leg once all linked. */
99 conflux_t *cfx;
100
101 /* Legs. */
102 smartlist_t *legs;
104
105/** Error code used when linking circuits. Based on those, we decide to
106 * relaunch or not. */
107typedef enum link_circ_err_t {
108 /* Linking was successful. */
109 ERR_LINK_CIRC_OK = 0,
110 /* The RTT was not acceptable. */
111 ERR_LINK_CIRC_BAD_RTT = 1,
112 /* The leg can't be found. */
113 ERR_LINK_CIRC_MISSING_LEG = 2,
114 /* The set can't be found. */
115 ERR_LINK_CIRC_MISSING_SET = 3,
116 /* Invalid leg as in not pass validation. */
117 ERR_LINK_CIRC_INVALID_LEG = 4,
119
120#ifdef TOR_UNIT_TESTS
121digest256map_t *
122get_unlinked_pool(bool is_client)
123{
124 return is_client ? client_unlinked_pool : server_unlinked_pool;
125}
126
127digest256map_t *
128get_linked_pool(bool is_client)
129{
130 return is_client ? client_linked_pool : server_linked_pool;
131}
132#endif
133
134/* For unit tests only: please treat these exactly as the defines in the
135 * code. */
136STATIC uint8_t DEFAULT_CLIENT_UX = CONFLUX_UX_HIGH_THROUGHPUT;
137STATIC uint8_t DEFAULT_EXIT_UX = CONFLUX_UX_MIN_LATENCY;
138
139/** Helper: Format at 8 bytes the nonce for logging. */
140static inline const char *
141fmt_nonce(const uint8_t *nonce)
142{
143 return hex_str((char *) nonce, 8);
144}
145
146/**
147 * Return the conflux algorithm for a desired UX value.
148 */
149static uint8_t
150conflux_choose_algorithm(uint8_t desired_ux)
151{
152 switch (desired_ux) {
153 case CONFLUX_UX_NO_OPINION:
154 return CONFLUX_ALG_LOWRTT;
155 case CONFLUX_UX_MIN_LATENCY:
156 return CONFLUX_ALG_MINRTT;
157 case CONFLUX_UX_HIGH_THROUGHPUT:
158 return CONFLUX_ALG_LOWRTT;
159 /* For now, we have no low mem algs, so use minRTT since it should
160 * switch less and thus use less mem */
161 /* TODO-329-TUNING: Pick better algs here*/
162 case CONFLUX_UX_LOW_MEM_THROUGHPUT:
163 case CONFLUX_UX_LOW_MEM_LATENCY:
164 return CONFLUX_ALG_MINRTT;
165 default:
166 /* Trunnel should protect us from this */
168 return CONFLUX_ALG_LOWRTT;
169 }
170}
171
172/** Return a newly allocated conflux_t object. */
173static conflux_t *
175{
176 conflux_t *cfx = tor_malloc_zero(sizeof(*cfx));
177
178 cfx->ooo_q = smartlist_new();
179 cfx->legs = smartlist_new();
180
181 return cfx;
182}
183
184static void
185conflux_free_(conflux_t *cfx)
186{
187 if (!cfx) {
188 return;
189 }
190 tor_assert(cfx->legs);
191 tor_assert(cfx->ooo_q);
192
194 SMARTLIST_DEL_CURRENT(cfx->legs, leg);
195 tor_free(leg);
196 } SMARTLIST_FOREACH_END(leg);
197 smartlist_free(cfx->legs);
198
200 conflux_relay_msg_free(cell));
201 smartlist_free(cfx->ooo_q);
202
203 memwipe(cfx->nonce, 0, sizeof(cfx->nonce));
204 tor_free(cfx);
205}
206
207/** Wrapper for the free function, set the cfx pointer to NULL after free */
208#define conflux_free(cfx) \
209 FREE_AND_NULL(conflux_t, conflux_free_, cfx)
210
211/** Helper: Free function for the digest256map_free(). */
212static inline void
214{
215 conflux_t *cfx = (conflux_t *)ptr;
216 conflux_free(cfx);
217}
218
219/** Return a newly allocated leg object containing the given circuit and link
220 * pointer (no copy). */
221static leg_t *
223{
224 leg_t *leg = tor_malloc_zero(sizeof(*leg));
225 leg->circ = circ;
226 leg->link = link;
227 return leg;
228}
229
230/** Free the given leg object. Passing NULL is safe. */
231static void
233{
234 if (!leg) {
235 return;
236 }
237 if (leg->circ) {
239 leg->circ->conflux_pending_nonce = NULL;
240 }
241 tor_free(leg->link);
242 tor_free(leg);
243}
244
245/** Return a newly allocated unlinked set object for the given nonce. A new
246 * conflux object is also created. */
247static unlinked_circuits_t *
248unlinked_new(const uint8_t *nonce, bool is_client)
249{
250 unlinked_circuits_t *unlinked = tor_malloc_zero(sizeof(*unlinked));
251 unlinked->cfx = conflux_new();
252 unlinked->legs = smartlist_new();
253 unlinked->is_client = is_client;
254 memcpy(unlinked->cfx->nonce, nonce, sizeof(unlinked->cfx->nonce));
255
256 return unlinked;
257}
258
259/** Free the given unlinked object. */
260static void
262{
263 if (!unlinked) {
264 return;
265 }
266 tor_assert(unlinked->legs);
267
268 /* This cfx is pointing to a linked set. */
269 if (!unlinked->is_for_linked_set) {
270 conflux_free(unlinked->cfx);
271 }
272 SMARTLIST_FOREACH(unlinked->legs, leg_t *, leg, leg_free(leg));
273 smartlist_free(unlinked->legs);
274 tor_free(unlinked);
275}
276
277/** Add the given unlinked object to the unlinked pool. */
278static void
279unlinked_pool_add(unlinked_circuits_t *unlinked, bool is_client)
280{
281 tor_assert(unlinked);
282 if (is_client) {
283 digest256map_set(client_unlinked_pool, unlinked->cfx->nonce, unlinked);
284 } else {
285 digest256map_set(server_unlinked_pool, unlinked->cfx->nonce, unlinked);
286 }
287}
288
289/** Delete the given unlinked object from the unlinked pool. */
290static void
291unlinked_pool_del(unlinked_circuits_t *unlinked, bool is_client)
292{
293 tor_assert(unlinked);
294
295 if (is_client) {
296 digest256map_remove(client_unlinked_pool, unlinked->cfx->nonce);
297 } else {
298 digest256map_remove(server_unlinked_pool, unlinked->cfx->nonce);
299 }
300}
301
302/** Return an unlinked object for the given nonce else NULL. */
303static unlinked_circuits_t *
304unlinked_pool_get(const uint8_t *nonce, bool is_client)
305{
306 tor_assert(nonce);
307 if (is_client) {
308 return digest256map_get(client_unlinked_pool, nonce);
309 } else {
310 return digest256map_get(server_unlinked_pool, nonce);
311 }
312}
313
314/** Delete from the pool and free the given unlinked object. */
315static void
317{
318 tor_assert(unlinked);
319 unlinked_pool_del(unlinked, is_client);
320 unlinked_free(unlinked);
321}
322
323/** Add the given conflux object to the linked conflux set. */
324static void
325linked_pool_add(conflux_t *cfx, bool is_client)
326{
327 tor_assert(cfx);
328 if (is_client) {
329 digest256map_set(client_linked_pool, cfx->nonce, cfx);
330 } else {
331 digest256map_set(server_linked_pool, cfx->nonce, cfx);
332 }
333}
334
335/** Delete from the linked conflux set the given nonce. */
336static void
337linked_pool_del(const uint8_t *nonce, bool is_client)
338{
339 tor_assert(nonce);
340 if (is_client) {
341 digest256map_remove(client_linked_pool, nonce);
342 } else {
343 digest256map_remove(server_linked_pool, nonce);
344 }
345}
346
347/** Return a conflux_t object for the given nonce from the linked set. */
348static conflux_t *
349linked_pool_get(const uint8_t *nonce, bool is_client)
350{
351 tor_assert(nonce);
352 if (is_client) {
353 return digest256map_get(client_linked_pool, nonce);
354 } else {
355 return digest256map_get(server_linked_pool, nonce);
356 }
357}
358
359/** Add the given leg to the given unlinked object. */
360static inline void
362{
363 tor_assert(unlinked);
364 tor_assert(leg);
365
366 smartlist_add(unlinked->legs, leg);
367}
368
369/** Return an unlinked leg for the given unlinked object and for the given
370 * circuit. */
371static inline leg_t *
372leg_find(const unlinked_circuits_t *unlinked, const circuit_t *circ)
373{
374 SMARTLIST_FOREACH_BEGIN(unlinked->legs, leg_t *, leg) {
375 if (leg->circ == circ) {
376 return leg;
377 }
378 } SMARTLIST_FOREACH_END(leg);
379 return NULL;
380}
381
382/** Return the given circuit leg from its unlinked set (if any). */
383static leg_t *
384unlinked_leg_find(const circuit_t *circ, bool is_client)
385{
386 unlinked_circuits_t *unlinked =
388 if (!unlinked) {
389 return NULL;
390 }
391 return leg_find(unlinked, circ);
392}
393
394static void
395unlinked_leg_del_and_free(unlinked_circuits_t *unlinked,
396 const circuit_t *circ)
397{
398 tor_assert(circ);
399 tor_assert(unlinked);
400
401 SMARTLIST_FOREACH_BEGIN(unlinked->legs, leg_t *, leg) {
402 if (leg->circ == circ) {
403 SMARTLIST_DEL_CURRENT(unlinked->legs, leg);
404 leg_free(leg);
405 break;
406 }
407 } SMARTLIST_FOREACH_END(leg);
408}
409
410/**
411 * Ensure that the given circuit has no attached streams.
412 *
413 * This validation function is called at various stages for
414 * unlinked circuits, to make sure they have no streams.
415 */
416static void
418{
419 if (CIRCUIT_IS_ORIGIN(circ)) {
420 origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
421 if (BUG(ocirc->p_streams)) {
422 log_warn(LD_BUG,
423 "Unlinked Conflux circuit %u has attached streams.",
424 ocirc->global_identifier);
425 ocirc->p_streams = NULL;
426 }
427 if (BUG(ocirc->half_streams)) {
428 log_warn(LD_BUG,
429 "Unlinked conflux circ %u has half streams.",
430 ocirc->global_identifier);
431 ocirc->half_streams = NULL;
432 }
433 } else {
434 or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
435 if (BUG(orcirc->n_streams)) {
436 log_warn(LD_BUG,
437 "Unlinked conflux circuit has attached streams.");
438 orcirc->n_streams = NULL;
439 }
440 if (BUG(orcirc->resolving_streams)) {
441 log_warn(LD_BUG,
442 "Unlinked conflux circuit has resolving streams.");
443 orcirc->resolving_streams = NULL;
444 }
445 }
446}
447
448/** Return true iff the legs in the given unlinked set are valid and coherent
449 * to be a linked set. */
450static bool
452{
453 bool valid = true;
454 uint8_t version;
455 uint8_t *nonce = NULL;
456
457 tor_assert(unlinked);
458
459 SMARTLIST_FOREACH_BEGIN(unlinked->legs, const leg_t *, leg) {
460 if (!nonce) {
461 nonce = leg->link->nonce;
462 version = leg->link->version;
463 } else {
464 /* Version and nonce must match in all legs. */
465 valid &= (leg->link->version == version &&
466 tor_memeq(leg->link->nonce, nonce, sizeof(leg->link->nonce)));
467 }
468
469 // If the other ends last sent sequence number is higher than the
470 // last sequence number we delivered, we have data loss, and cannot link.
471 if (leg->link->last_seqno_sent > unlinked->cfx->last_seq_delivered) {
472 log_fn(unlinked->is_client ? LOG_NOTICE : LOG_PROTOCOL_WARN, LD_CIRC,
473 "Data loss detected while trying to add a conflux leg.");
474 valid = false;
475
476 // TODO-329-ARTI: Instead of closing the set here, we could
477 // immediately send a SWITCH cell and re-send the missing data.
478 // To do this, though, we would need to constantly buffer at least
479 // a cwnd worth of sent data to retransmit. We're not going to try
480 // this in C-Tor, but arti could consider it.
481 }
483 } SMARTLIST_FOREACH_END(leg);
484
485 /* Note that if no legs, it validates. */
486
487 return valid;
488}
489
490/** Add up a new leg to the given conflux object. */
491static void
493{
494 tor_assert(cfx);
495 tor_assert(leg);
496 tor_assert(leg->link);
497
498 /* Big trouble if we add a leg to the wrong set. */
499 tor_assert(tor_memeq(cfx->nonce, leg->link->nonce, sizeof(cfx->nonce)));
500
501 conflux_leg_t *cleg = tor_malloc_zero(sizeof(*cleg));
502 cleg->circ = leg->circ;
503 // TODO-329-ARTI: Blindly copying the values from the cell. Is this correct?
504 // I think no... When adding new legs, switching to this leg is
505 // likely to break, unless the sender tracks what link cell it sent..
506 // Is that the best option? Or should we use the max of our legs, here?
507 // (It seems the other side will have no idea what our current maxes
508 /// are, so this option seems better right now)
509 cleg->last_seq_recv = leg->link->last_seqno_sent;
510 cleg->last_seq_sent = leg->link->last_seqno_recv;
511 cleg->circ_rtts_usec = leg->rtt_usec;
512 cleg->linked_sent_usec = leg->link_sent_usec;
513
514 cfx->params.alg = conflux_choose_algorithm(leg->link->desired_ux);
515
516 /* Add leg to given conflux. */
517 smartlist_add(cfx->legs, cleg);
518
519 /* Ensure the new circuit has no streams. */
521
522 /* If this is not the first leg, get the first leg, and get
523 * the reference streams from it. */
524 if (CONFLUX_NUM_LEGS(cfx) > 0) {
525 conflux_leg_t *first_leg = smartlist_get(cfx->legs, 0);
526 if (CIRCUIT_IS_ORIGIN(first_leg->circ)) {
527 origin_circuit_t *old_circ = TO_ORIGIN_CIRCUIT(first_leg->circ);
528 origin_circuit_t *new_circ = TO_ORIGIN_CIRCUIT(leg->circ);
529
530 new_circ->p_streams = old_circ->p_streams;
531 new_circ->half_streams = old_circ->half_streams;
532 /* Sync all legs with the new stream(s). */
533 conflux_sync_circ_fields(cfx, old_circ);
534 } else {
535 or_circuit_t *old_circ = TO_OR_CIRCUIT(first_leg->circ);
536 or_circuit_t *new_circ = TO_OR_CIRCUIT(leg->circ);
537 new_circ->n_streams = old_circ->n_streams;
538 new_circ->resolving_streams = old_circ->resolving_streams;
539 }
540 }
541
542 if (CIRCUIT_IS_ORIGIN(cleg->circ)) {
543 tor_assert_nonfatal(cleg->circ->purpose ==
545 circuit_change_purpose(cleg->circ, CIRCUIT_PURPOSE_CONFLUX_LINKED);
546 }
548}
549
550/**
551 * Clean up a circuit from its conflux_t object.
552 *
553 * Return true if closing this circuit should tear down the entire set,
554 * false otherwise.
555 */
556static bool
558{
559 conflux_leg_t *leg;
560 bool full_teardown = false;
561
562 tor_assert(cfx);
563 tor_assert(circ);
564
565 leg = conflux_get_leg(cfx, circ);
566 if (!leg) {
567 goto end;
568 }
569
570 // If the circuit still has inflight data, teardown
571 const struct congestion_control_t *cc = circuit_ccontrol(circ);
572 tor_assert(cc);
574 if (cc->inflight >= cc->sendme_inc) {
575 full_teardown = true;
576 log_info(LD_CIRC, "Conflux current circuit has closed with "
577 "data in flight, tearing down entire set.");
578 }
579
580 /* Remove it from the cfx. */
581 smartlist_remove(cfx->legs, leg);
582
583 /* After removal, if this leg had the highest sent (or recv)
584 * sequence number, it was in active use by us (or the other side).
585 * We need to tear down the entire set. */
586 // TODO-329-ARTI: If we support resumption, we don't need this.
587 if (CONFLUX_NUM_LEGS(cfx) > 0) {
588 if (conflux_get_max_seq_sent(cfx) < leg->last_seq_sent ||
590 full_teardown = true;
591 log_info(LD_CIRC, "Conflux sequence number check failed, "
592 "tearing down entire set.");
593 }
594 }
595
596 /* Cleanup any reference to leg. */
597 if (cfx->curr_leg == leg) {
598 cfx->curr_leg = NULL;
599 full_teardown = true;
600 log_info(LD_CIRC, "Conflux current circuit has closed, "
601 "tearing down entire set.");
602 }
603 if (cfx->prev_leg == leg) {
604 cfx->prev_leg = NULL;
605 }
606
607 tor_free(leg);
608
609 end:
610 return full_teardown;
611}
612
613/** Close the circuit of each legs of the given unlinked object. */
614static void
616{
617 smartlist_t *circ_to_close = NULL;
618
619 tor_assert(unlinked);
620
621 /* Small optimization here, avoid this work if no legs. */
622 if (smartlist_len(unlinked->legs) == 0) {
623 return;
624 }
625
626 /* We will iterate over all legs and put the circuit in its own list and then
627 * mark them for close. The unlinked object gets freed opportunistically once
628 * there is no more legs attached to it and so we can't hold a reference
629 * while closing circuits. */
630 circ_to_close = smartlist_new();
631
632 SMARTLIST_FOREACH(unlinked->legs, leg_t *, leg,
633 smartlist_add(circ_to_close, leg->circ));
634 unlinked = NULL;
635
636 /* The leg gets cleaned up in the circuit close. */
637 SMARTLIST_FOREACH_BEGIN(circ_to_close, circuit_t *, circ) {
638 if (CIRCUIT_IS_ORIGIN(circ)) {
639 tor_assert_nonfatal(circ->purpose == CIRCUIT_PURPOSE_CONFLUX_UNLINKED);
640 }
641 if (!circ->marked_for_close) {
642 circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
643 }
644 } SMARTLIST_FOREACH_END(circ);
645
646 /* Drop the list and ignore its content, we don't have ownership. */
647 smartlist_free(circ_to_close);
648}
649
650/** Either closee all legs of the given unlinked set or delete it from the pool
651 * and free its memory.
652 *
653 * Important: The unlinked object is freed opportunistically when legs are
654 * removed until the point none remains. And so, it is only safe to free the
655 * object if no more legs exist.
656 */
657static void
659{
660 if (!unlinked) {
661 return;
662 }
663
664 /* If we have legs, the circuit close will trigger the unlinked object to be
665 * opportunistically freed. Else, we do it explicitly. */
666 if (smartlist_len(unlinked->legs) > 0) {
667 unlinked_close_all_legs(unlinked);
668 } else {
669 unlinked_pool_del_and_free(unlinked, unlinked->is_client);
670 }
671 /* Either the unlinked object has been freed or the last leg close will free
672 * it so from this point on, nullify for safety reasons. */
673 unlinked = NULL;
674}
675
676/** Upon an error condition or a close of an in-use circuit, we must close all
677 * linked and unlinked circuits associated with a set. When the last leg of
678 * each set is closed, the set is removed from the pool. */
679void
680conflux_mark_all_for_close(const uint8_t *nonce, bool is_client, int reason)
681{
682 /* It is possible that for a nonce we have both an unlinked set and a linked
683 * set. This happens if there is a recovery leg launched for an existing
684 * linked set. */
685
686 /* Close the unlinked set. */
687 unlinked_circuits_t *unlinked = unlinked_pool_get(nonce, is_client);
688 if (unlinked) {
689 unlinked_close_or_free(unlinked);
690 }
691 /* In case it gets freed, be safe here. */
692 unlinked = NULL;
693
694 /* Close the linked set. It will free itself upon the close of
695 * the last leg. */
696 conflux_t *linked = linked_pool_get(nonce, is_client);
697 if (linked) {
698 if (linked->in_full_teardown) {
699 return;
700 }
701 linked->in_full_teardown = true;
702
703 smartlist_t *circ_to_close = smartlist_new();
704
705 SMARTLIST_FOREACH(linked->legs, conflux_leg_t *, leg,
706 smartlist_add(circ_to_close, leg->circ));
707
708 SMARTLIST_FOREACH(circ_to_close, circuit_t *, circ,
709 circuit_mark_for_close(circ, reason));
710
711 /* Drop the list and ignore its content, we don't have ownership. */
712 smartlist_free(circ_to_close);
713 }
714}
715
716/** Helper: Free function taking a void pointer for the digest256map_free. */
717static inline void
719{
720 unlinked_circuits_t *unlinked = ptr;
721 unlinked_pool_del_and_free(unlinked, unlinked->is_client);
722}
723
724/** Attempt to finalize the unlinked set to become a linked set and be put in
725 * the linked pool.
726 *
727 * If this finalized successfully, the given unlinked object is freed. */
728static link_circ_err_t
730{
731 link_circ_err_t err = ERR_LINK_CIRC_OK;
732 bool is_client;
733
734 tor_assert(unlinked);
735 tor_assert(unlinked->legs);
736 tor_assert(unlinked->cfx);
737 tor_assert(unlinked->cfx->legs);
738
739 /* Without legs, this is not ready to become a linked set. */
740 if (BUG(smartlist_len(unlinked->legs) == 0)) {
741 err = ERR_LINK_CIRC_MISSING_LEG;
742 goto end;
743 }
744
745 /* If there are too many legs, we can't link. */
746 if (smartlist_len(unlinked->legs) +
747 smartlist_len(unlinked->cfx->legs) > conflux_params_get_max_legs_set()) {
748 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
749 "Conflux set has too many legs to link. "
750 "Rejecting this circuit.");
751 conflux_log_set(LOG_PROTOCOL_WARN, unlinked->cfx, unlinked->is_client);
752 err = ERR_LINK_CIRC_INVALID_LEG;
753 goto end;
754 }
755
756 /* Validate that all legs are coherent and parameters match. On failure, we
757 * teardown the whole unlinked set because this means we either have a code
758 * flow problem or the Exit is trying to trick us. */
759 if (!validate_unlinked_legs(unlinked)) {
760 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
761 "Conflux unlinked set legs are not validating. Tearing it down.");
762 conflux_mark_all_for_close(unlinked->cfx->nonce, unlinked->is_client,
763 END_CIRC_REASON_TORPROTOCOL);
764 err = ERR_LINK_CIRC_INVALID_LEG;
765 goto end;
766 }
767
768 /* Check all linked status. All need to be true in order to finalize the set
769 * and move it to the linked pool. */
770 SMARTLIST_FOREACH_BEGIN(unlinked->legs, const leg_t *, leg) {
771 /* We are still waiting on a leg. */
772 if (!leg->linked) {
773 log_info(LD_CIRC, "Can't finalize conflux set, still waiting on at "
774 "least one leg to link up.");
775
776 goto end;
777 }
778 } SMARTLIST_FOREACH_END(leg);
779
780 /* Finalize the cfx object by adding all legs into it. */
781 SMARTLIST_FOREACH_BEGIN(unlinked->legs, leg_t *, leg) {
782 /* Removing the leg from the list is important so we avoid ending up with a
783 * leg in the unlinked list that is set with LINKED purpose. */
784 SMARTLIST_DEL_CURRENT(unlinked->legs, leg);
785
786 /* We are ready to attach the leg to the cfx object now. */
787 cfx_add_leg(unlinked->cfx, leg);
788
789 /* Clean the pending nonce and set the conflux object in the circuit. */
790 leg->circ->conflux = unlinked->cfx;
791
792 /* We are done with this leg object. */
793 leg_free(leg);
794 } SMARTLIST_FOREACH_END(leg);
795
796 is_client = unlinked->is_client;
797
798 /* Add the conflux object to the linked pool. For an existing linked cfx
799 * object, we'll simply replace it with itself. */
800 linked_pool_add(unlinked->cfx, is_client);
801
802 /* Remove it from the unlinked pool. */
803 unlinked_pool_del(unlinked, is_client);
804
805 /* We don't recover a leg when it is linked but if we would like to support
806 * session ressumption, this would be very important in order to allow new
807 * legs to be created/recovered. */
808 unlinked->cfx->num_leg_launch = 0;
809
810 /* Nullify because we are about to free the unlinked object and the cfx has
811 * moved to all circuits. */
812 unlinked->cfx = NULL;
813 unlinked_free(unlinked);
814
815 log_info(LD_CIRC,
816 "Successfully linked a conflux %s set which is now usable.",
817 is_client ? "client" : "relay");
818
819 end:
820 return err;
821}
822
823/** Record the RTT for this client circuit.
824 *
825 * Return the RTT value. UINT64_MAX is returned if we couldn't find the initial
826 * measurement of when the cell was sent or if the leg is missing. */
827static uint64_t
829{
830 tor_assert(circ);
833
834 leg_t *leg = unlinked_leg_find(circ, true);
835
836 if (BUG(!leg || leg->link_sent_usec == 0)) {
837 log_warn(LD_BUG,
838 "Conflux: Trying to record client RTT without a timestamp");
839 goto err;
840 }
841
842 uint64_t now = monotime_absolute_usec();
843 tor_assert_nonfatal(now >= leg->link_sent_usec);
844 leg->rtt_usec = now - leg->link_sent_usec;
845 if (leg->rtt_usec == 0) {
846 log_warn(LD_CIRC, "Clock appears stalled for conflux.");
847 // TODO-329-TUNING: For now, let's accept this case. We need to do
848 // tuning and clean up the tests such that they use RTT in order to
849 // fail here.
850 //goto err;
851 }
852 return leg->rtt_usec;
853
854 err:
855 // Avoid using this leg until a timestamp comes in
856 if (leg)
857 leg->rtt_usec = UINT64_MAX;
858 return UINT64_MAX;
859}
860
861/** Record the RTT for this Exit circuit.
862 *
863 * Return the RTT value. UINT64_MAX is returned if we couldn't find the initial
864 * measurement of when the cell was sent or if the leg is missing. */
865
866static uint64_t
868{
869 tor_assert(circ);
870 tor_assert(circ->conflux);
872
873 conflux_leg_t *leg = conflux_get_leg(circ->conflux, circ);
874
875 if (BUG(!leg || leg->linked_sent_usec == 0)) {
876 log_warn(LD_BUG,
877 "Conflux: Trying to record exit RTT without a timestamp");
878 goto err;
879 }
880
881 uint64_t now = monotime_absolute_usec();
882 tor_assert_nonfatal(now >= leg->linked_sent_usec);
883 leg->circ_rtts_usec = now - leg->linked_sent_usec;
884
885 if (leg->circ_rtts_usec == 0) {
886 log_warn(LD_CIRC, "Clock appears stalled for conflux.");
887 goto err;
888 }
889 return leg->circ_rtts_usec;
890
891 err:
892 if (leg)
893 leg->circ_rtts_usec = UINT64_MAX;
894 return UINT64_MAX;
895}
896
897/** For the given circuit, record the RTT from when the LINK or LINKED cell was
898 * sent that is this function works for either client or Exit.
899 *
900 * Return false if the RTT is too high for our standard else true. */
901static bool
902record_rtt(const circuit_t *circ, bool is_client)
903{
904 uint64_t rtt_usec;
905
906 tor_assert(circ);
907
908 if (is_client) {
909 rtt_usec = record_rtt_client(circ);
910
911 if (rtt_usec == UINT64_MAX)
912 return false;
913
914 if (rtt_usec >= get_circuit_build_timeout_ms()*1000) {
915 log_info(LD_CIRC, "Conflux leg RTT is above circuit build time out "
916 "currently at %f msec. Relaunching.",
918 return false;
919 }
920 } else {
921 rtt_usec = record_rtt_exit(circ);
922 }
923
924 return true;
925}
926
927/** Link the given circuit within its unlinked set. This is called when either
928 * the LINKED or LINKED_ACK is received depending on which side of the circuit
929 * it is.
930 *
931 * It attempts to finalize the unlinked set as well which, if successful, puts
932 * it in the linked pool. */
933static link_circ_err_t
935{
936 link_circ_err_t err = ERR_LINK_CIRC_OK;
937 unlinked_circuits_t *unlinked = NULL;
938 bool is_client = false;
939
940 tor_assert(circ);
941 if (CIRCUIT_IS_ORIGIN(circ)) {
942 tor_assert_nonfatal(circ->purpose == CIRCUIT_PURPOSE_CONFLUX_UNLINKED);
943 is_client = true;
944 }
945
946 unlinked = unlinked_pool_get(circ->conflux_pending_nonce, is_client);
947 if (BUG(!unlinked)) {
948 log_warn(LD_BUG, "Failed to find the unlinked set %s when linking. "
949 "Closing circuit.",
951 err = ERR_LINK_CIRC_MISSING_SET;
952 goto end;
953 }
954
955 leg_t *leg = leg_find(unlinked, circ);
956 if (BUG(!leg)) {
957 /* Failure to find the leg when linking a circuit is an important problem
958 * so log loudly and error. */
959 log_warn(LD_BUG, "Failed to find leg for the unlinked set %s when "
960 "linking. Closing circuit.",
961 fmt_nonce(unlinked->cfx->nonce));
962 err = ERR_LINK_CIRC_MISSING_LEG;
963 goto end;
964 }
965
966 /* Successful link. Attempt to finalize the set in case this was the last
967 * LINKED or LINKED_ACK cell to receive. */
968 leg->linked = true;
969 err = try_finalize_set(unlinked);
970
971 end:
972 return err;
973}
974
975/** Launch a brand new set.
976 *
977 * Return true if all legs successfully launched or false if one failed. */
978STATIC bool
979launch_new_set(int num_legs)
980{
981 uint8_t nonce[DIGEST256_LEN];
982
983 /* Brand new nonce for this set. */
984 crypto_rand((char *) nonce, sizeof(nonce));
985
986 /* Launch all legs. */
987 for (int i = 0; i < num_legs; i++) {
988 if (!conflux_launch_leg(nonce)) {
989 /* This function cleans up entirely the unlinked set if a leg is unable
990 * to be launched. The recovery would be complex here. */
991 goto err;
992 }
993 }
994
995 return true;
996
997 err:
998 return false;
999}
1000
1001static unlinked_circuits_t *
1002unlinked_get_or_create(const uint8_t *nonce, bool is_client)
1003{
1004 unlinked_circuits_t *unlinked;
1005
1006 tor_assert(nonce);
1007
1008 unlinked = unlinked_pool_get(nonce, is_client);
1009 if (!unlinked) {
1010 unlinked = unlinked_new(nonce, is_client);
1011
1012 /* If this is a leg of an existing linked set, use that conflux object
1013 * instead so all legs point to the same. It is put in the leg's circuit
1014 * once the link is confirmed. */
1015 conflux_t *cfx = linked_pool_get(nonce, is_client);
1016 if (cfx) {
1017 conflux_free(unlinked->cfx);
1018 unlinked->cfx = cfx;
1019 unlinked->is_for_linked_set = true;
1020 }
1021 /* Add this set to the unlinked pool. */
1022 unlinked_pool_add(unlinked, is_client);
1023 }
1024
1025 return unlinked;
1026}
1027
1028/**
1029 * On the client side, we need to determine if there is already
1030 * an exit in use for this set, and if so, use that.
1031 *
1032 * Otherwise, we return NULL and the exit is decided by the
1033 * circuitbuild.c code.
1034 */
1035static extend_info_t *
1036get_exit_for_nonce(const uint8_t *nonce)
1037{
1038 extend_info_t *exit = NULL;
1039
1040 tor_assert(nonce);
1041
1042 // First, check the linked pool for the nonce
1043 const conflux_t *cfx = linked_pool_get(nonce, true);
1044 if (cfx) {
1045 tor_assert(cfx->legs);
1046 /* Get the exit from the first leg */
1047 conflux_leg_t *leg = smartlist_get(cfx->legs, 0);
1048 tor_assert(leg);
1049 tor_assert(leg->circ);
1052 tor_assert(exit);
1053 } else {
1054 unlinked_circuits_t *unlinked = NULL;
1055 unlinked = unlinked_pool_get(nonce, true);
1056
1057 if (unlinked) {
1058 tor_assert(unlinked->legs);
1059 if (smartlist_len(unlinked->legs) > 0) {
1060 /* Get the exit from the first leg */
1061 leg_t *leg = smartlist_get(unlinked->legs, 0);
1062 tor_assert(leg);
1063 tor_assert(leg->circ);
1064 tor_assert(TO_ORIGIN_CIRCUIT(leg->circ)->cpath);
1065 exit = TO_ORIGIN_CIRCUIT(leg->circ)->cpath->prev->extend_info;
1066 tor_assert(exit);
1067 }
1068 }
1069 }
1070
1071 return exit;
1072}
1073
1074/**
1075 * Return the currently configured client UX.
1076 */
1077static uint8_t
1079{
1080#ifdef TOR_UNIT_TESTS
1081 return DEFAULT_CLIENT_UX;
1082#else
1083 const or_options_t *opt = get_options();
1084 tor_assert(opt);
1085 (void)DEFAULT_CLIENT_UX;
1086
1087 /* Return the UX */
1088 return opt->ConfluxClientUX;
1089#endif
1090}
1091
1092/** Return true iff the given conflux object is allowed to launch a new leg. If
1093 * the cfx object is NULL, then it is always allowed to launch a new leg. */
1094static bool
1096{
1097 if (!cfx) {
1098 goto allowed;
1099 }
1100
1101 /* The maximum number of retry is the minimum number of legs we are allowed
1102 * per set plus the maximum amount of retries we are allowed to do. */
1103 unsigned int max_num_launch =
1104 conflux_params_get_num_legs_set() +
1105 conflux_params_get_max_unlinked_leg_retry();
1106
1107 /* Only log once per nonce if we've reached the maximum. */
1108 if (cfx->num_leg_launch == max_num_launch) {
1109 log_info(LD_CIRC, "Maximum number of leg launch reached for nonce %s",
1110 fmt_nonce(cfx->nonce));
1111 }
1112
1113 if (cfx->num_leg_launch >= max_num_launch) {
1114 return false;
1115 }
1116
1117 allowed:
1118 return true;
1119}
1120
1121/*
1122 * Public API.
1123 */
1124
1125/** Launch a new conflux leg for the given nonce.
1126 *
1127 * Return true on success else false which teardowns the entire unlinked set if
1128 * any. */
1129bool
1130conflux_launch_leg(const uint8_t *nonce)
1131{
1134 unlinked_circuits_t *unlinked = NULL;
1135 extend_info_t *exit = NULL;
1136
1137 tor_assert(nonce);
1138
1139 /* Get or create a new unlinked object for this leg. */
1140 unlinked = unlinked_get_or_create(nonce, true);
1141 tor_assert(unlinked);
1142
1143 /* If we have an existing linked set, validate the number of leg retries
1144 * before attempting the launch. */
1145 if (!launch_leg_is_allowed(unlinked->cfx)) {
1146 goto err;
1147 }
1148
1149 exit = get_exit_for_nonce(nonce);
1150
1151 if (exit) {
1152 log_info(LD_CIRC, "Launching conflux leg for nonce %s.", fmt_nonce(nonce));
1153 } else {
1154 log_info(LD_CIRC, "Launching new conflux set for nonce %s.",
1155 fmt_nonce(nonce));
1156 }
1157
1158 /* Increase the retry count for this conflux object as in this nonce.
1159 * We must do this now, because some of the maze's early failure paths
1160 * call right back into this function for relaunch. */
1161 unlinked->cfx->num_leg_launch++;
1162
1163 origin_circuit_t *circ =
1165 exit, flags);
1166
1167 /* The above call to establish a circuit can send us back a closed
1168 * circuit if the OOM handler closes this very circuit while in that
1169 * function. OOM handler runs everytime we queue a cell on a circuit which
1170 * the above function does with the CREATE cell.
1171 *
1172 * The BUG() checks after are in the same spirit which is that there are so
1173 * many things that can happen in that establish circuit function that we
1174 * ought to make sure we have a valid nonce and a valid conflux object. */
1175 if (!circ || TO_CIRCUIT(circ)->marked_for_close) {
1176 goto err;
1177 }
1178 /* We think this won't happen but it might. The maze is powerful. #41155 */
1179 if (BUG(!TO_CIRCUIT(circ)->conflux_pending_nonce || !unlinked->cfx)) {
1180 goto err;
1181 }
1182
1183 /* At this point, the unlinked object has either a new conflux_t or the one
1184 * used by a linked set so it is fine to use the cfx from the unlinked object
1185 * from now on. */
1186
1187 /* Get the max_seq_sent and recv from the linked pool, if it exists, and pass
1188 * to new link cell. */
1189 uint64_t last_seq_sent = conflux_get_max_seq_sent(unlinked->cfx);
1190 uint64_t last_seq_recv = unlinked->cfx->last_seq_delivered;
1191
1192 // TODO-329-ARTI: To support resumption/retransmit, the client should store
1193 // the last_seq_sent now, so that it can know how much data to retransmit to
1194 // the server after link. C-Tor will not be implementing this, but arti and
1195 // arti-relay could (if resumption seems worthwhile; it may not be worth the
1196 // memory storage there, either).
1197
1198 /* We have a circuit, create the new leg and attach it to the set. */
1199 leg_t *leg = leg_new(TO_CIRCUIT(circ),
1200 conflux_cell_new_link(nonce,
1201 last_seq_sent, last_seq_recv,
1202 get_client_ux()));
1203
1204 unlinked_leg_add(unlinked, leg);
1205 return true;
1206
1207 err:
1208 return false;
1209}
1210
1211/**
1212 * Add the identity digest of the guard nodes of all legs of the conflux
1213 * circuit.
1214 *
1215 * This function checks both pending and linked conflux circuits.
1216 */
1217void
1219 smartlist_t *excluded)
1220{
1221 tor_assert(orig_circ);
1222 tor_assert(excluded);
1223
1224 /* Ease our lives. */
1225 const circuit_t *circ = TO_CIRCUIT(orig_circ);
1226
1227 /* Ignore if this is not conflux related. */
1228 if (!CIRCUIT_IS_CONFLUX(circ)) {
1229 return;
1230 }
1231
1232 /* When building a circuit, we should not have a conflux object
1233 * ourselves (though one may exist elsewhere). */
1234 tor_assert(!circ->conflux);
1235
1236 /* Getting here without a nonce is a code flow issue. */
1237 if (BUG(!circ->conflux_pending_nonce)) {
1238 return;
1239 }
1240
1241 /* If there is only one bridge, then only issue a warn once that
1242 * at least two bridges are best for conflux. Exempt Snowflake
1243 * from this warn */
1244 if (get_options()->UseBridges && !conflux_can_exclude_used_bridges()) {
1245 /* Do not build any exclude lists; not enough bridges */
1246 return;
1247 }
1248
1249 /* A linked set exists, use it. */
1250 const conflux_t *cfx = linked_pool_get(circ->conflux_pending_nonce, true);
1251 if (cfx) {
1252 CONFLUX_FOR_EACH_LEG_BEGIN(cfx, leg) {
1253 const origin_circuit_t *ocirc = CONST_TO_ORIGIN_CIRCUIT(leg->circ);
1254 smartlist_add(excluded,
1255 tor_memdup(ocirc->cpath->extend_info->identity_digest,
1256 DIGEST_LEN));
1257 } CONFLUX_FOR_EACH_LEG_END(leg);
1258 }
1259
1260 /* An unlinked set might exist for this nonce, if so, add the second hop of
1261 * the existing legs to the exclusion list. */
1262 unlinked_circuits_t *unlinked =
1264 if (unlinked) {
1265 tor_assert(unlinked->is_client);
1266 SMARTLIST_FOREACH_BEGIN(unlinked->legs, leg_t *, leg) {
1267 /* Convert to origin circ and get cpath */
1268 const origin_circuit_t *ocirc = CONST_TO_ORIGIN_CIRCUIT(leg->circ);
1269 smartlist_add(excluded,
1270 tor_memdup(ocirc->cpath->extend_info->identity_digest,
1271 DIGEST_LEN));
1272 } SMARTLIST_FOREACH_END(leg);
1273 }
1274}
1275
1276/**
1277 * Add the identity digest of the middle nodes of all legs of the conflux
1278 * circuit.
1279 *
1280 * This function checks both pending and linked conflux circuits.
1281 *
1282 * XXX: The add guard and middle could be merged since it is the exact same
1283 * code except for the cpath position and the identity digest vs node_t in
1284 * the list. We could use an extra param indicating guard or middle. */
1285void
1287 smartlist_t *excluded)
1288{
1289 tor_assert(orig_circ);
1290 tor_assert(excluded);
1291
1292 /* Ease our lives. */
1293 const circuit_t *circ = TO_CIRCUIT(orig_circ);
1294
1295 /* Ignore if this is not conflux related. */
1296 if (!CIRCUIT_IS_CONFLUX(circ)) {
1297 return;
1298 }
1299
1300 /* When building a circuit, we should not have a conflux object
1301 * ourselves (though one may exist elsewhere). */
1302 tor_assert(!circ->conflux);
1303
1304 /* Getting here without a nonce is a code flow issue. */
1305 if (BUG(!circ->conflux_pending_nonce)) {
1306 return;
1307 }
1308
1309 /* A linked set exists, use it. */
1310 const conflux_t *cfx = linked_pool_get(circ->conflux_pending_nonce, true);
1311 if (cfx) {
1312 CONFLUX_FOR_EACH_LEG_BEGIN(cfx, leg) {
1313 const origin_circuit_t *ocirc = CONST_TO_ORIGIN_CIRCUIT(leg->circ);
1316 if (node) {
1317 smartlist_add(excluded, node);
1318 }
1319 } CONFLUX_FOR_EACH_LEG_END(leg);
1320 }
1321
1322 /* An unlinked set might exist for this nonce, if so, add the second hop of
1323 * the existing legs to the exclusion list. */
1324 unlinked_circuits_t *unlinked =
1326 if (unlinked) {
1327 tor_assert(unlinked->is_client);
1328 SMARTLIST_FOREACH_BEGIN(unlinked->legs, leg_t *, leg) {
1329 /* Convert to origin circ and get cpath */
1330 const origin_circuit_t *ocirc = CONST_TO_ORIGIN_CIRCUIT(leg->circ);
1333 if (node) {
1334 smartlist_add(excluded, node);
1335 }
1336 } SMARTLIST_FOREACH_END(leg);
1337 }
1338}
1339
1340/** Return the number of unused client linked set. */
1341static int
1343{
1344 int count = 0;
1345
1346 DIGEST256MAP_FOREACH(client_linked_pool, key, conflux_t *, cfx) {
1347 conflux_leg_t *leg = smartlist_get(cfx->legs, 0);
1348 if (BUG(!leg->circ)) {
1349 log_warn(LD_BUG, "Client conflux linked set leg without a circuit");
1350 continue;
1351 }
1352
1353 /* The maze marks circuits used several different ways. If any of
1354 * them are marked for this leg, launch a new one. */
1355 if (!CONST_TO_ORIGIN_CIRCUIT(leg->circ)->unusable_for_new_conns &&
1356 !CONST_TO_ORIGIN_CIRCUIT(leg->circ)->isolation_values_set &&
1357 !leg->circ->timestamp_dirty) {
1358 count++;
1359 }
1360 } DIGEST256MAP_FOREACH_END;
1361
1362 return count;
1363}
1364
1365/** Determine if we need to launch new conflux circuits for our preemptive
1366 * pool.
1367 *
1368 * This is called once a second from the mainloop from
1369 * circuit_predict_and_launch_new(). */
1370void
1372{
1373 (void) now;
1374
1375 /* If conflux is disabled, or we have insufficient consensus exits,
1376 * don't prebuild. */
1377 if (!conflux_is_enabled(NULL) ||
1378 router_have_consensus_path() != CONSENSUS_PATH_EXIT) {
1379 return;
1380 }
1381
1382 /* Don't attempt to build a new set if we are above our allowed maximum of
1383 * linked sets. */
1384 if (digest256map_size(client_linked_pool) >=
1385 conflux_params_get_max_linked_set()) {
1386 return;
1387 }
1388
1389 /* Count the linked and unlinked to get the total number of sets we have
1390 * (will have). */
1391 int num_linked = count_client_usable_sets();
1392 int num_unlinked = digest256map_size(client_unlinked_pool);
1393 int num_set = num_unlinked + num_linked;
1394 int max_prebuilt = conflux_params_get_max_prebuilt();
1395
1396 if (num_set >= max_prebuilt) {
1397 return;
1398 }
1399
1400 log_info(LD_CIRC, "Preemptively launching new conflux circuit set(s). "
1401 "We have %d linked and %d unlinked.",
1402 num_linked, num_unlinked);
1403
1404 for (int i = 0; i < (max_prebuilt - num_set); i++) {
1405 if (!launch_new_set(conflux_params_get_num_legs_set())) {
1406 /* Failing once likely means we'll fail next attempt so stop for now and
1407 * we'll try later. */
1408 break;
1409 }
1410 }
1411}
1412
1413/** Return the first circuit from the linked pool that will work with the conn.
1414 * If no such circuit exists, return NULL. */
1417{
1418 /* Use conn to check the exit policy of the first circuit
1419 * of each set in the linked pool. */
1420 tor_assert(conn);
1421
1422 DIGEST256MAP_FOREACH(client_linked_pool, key, conflux_t *, cfx) {
1423 /* Get the first circuit of the set. */
1424 conflux_leg_t *leg = smartlist_get(cfx->legs, 0);
1425 tor_assert(leg);
1426 tor_assert(leg->circ);
1427
1428 /* Bug on these but we can recover. */
1429 if (BUG(leg->circ->purpose != CIRCUIT_PURPOSE_CONFLUX_LINKED)) {
1430 continue;
1431 }
1432 if (BUG(!CIRCUIT_IS_ORIGIN(leg->circ))) {
1433 continue;
1434 }
1436
1437 /* Make sure the connection conforms with the exit policy and the isolation
1438 * flags also allows it. */
1439 if (!circuit_is_acceptable(ocirc, conn, 1 /* Must be open */,
1440 CIRCUIT_PURPOSE_CONFLUX_LINKED,
1441 1 /* Need uptime */,
1442 0 /* No need for internal */, now)) {
1443 continue;
1444 }
1445
1446 /* Found a circuit that works. */
1447 return ocirc;
1448 } DIGEST256MAP_FOREACH_END;
1449
1450 return NULL;
1451}
1452
1453/** The given circuit is conflux pending and has closed. This deletes the leg
1454 * from the set, attempt to finalize it and relaunch a new leg. If the set is
1455 * empty after removing this leg, it is deleted. */
1456static void
1458{
1459 uint8_t nonce[DIGEST256_LEN];
1460 unlinked_circuits_t *unlinked = NULL;
1461 bool is_client = false;
1462
1463 tor_assert(circ);
1465
1466 if (CIRCUIT_IS_ORIGIN(circ)) {
1467 tor_assert_nonfatal(circ->purpose == CIRCUIT_PURPOSE_CONFLUX_UNLINKED);
1468 is_client = true;
1469 }
1470
1471 unlinked = unlinked_pool_get(circ->conflux_pending_nonce, is_client);
1472
1473 /* This circuit is part of set that has already been removed previously freed
1474 * by another leg closing. */
1475 if (!unlinked) {
1476 return;
1477 }
1478
1479 /* We keep the nonce here because we will try to recover if we can and the
1480 * pending nonce will get nullified early. */
1481 memcpy(nonce, circ->conflux_pending_nonce, sizeof(nonce));
1482
1483 log_info(LD_CIRC, "Conflux unlinked circuit with nonce %s has closed",
1484 fmt_nonce(nonce));
1485
1486 /* Remove leg from set. */
1487 unlinked_leg_del_and_free(unlinked, circ);
1488 /* The circuit pending nonce has been nullified at this point. */
1489
1490 /* If no more legs, opportunistically free the unlinked set. */
1491 if (smartlist_len(unlinked->legs) == 0) {
1492 unlinked_pool_del_and_free(unlinked, is_client);
1493 } else if (!shutting_down && !have_been_under_memory_pressure()) {
1494 /* Launch a new leg for this set to recover if we are not shutting down or
1495 * if we are not under memory pressure. We must not launch legs under
1496 * memory pressure else it can just create a feedback loop of being closed
1497 * by the OOM handler and relaunching, rinse and repeat. */
1498 if (CIRCUIT_IS_ORIGIN(circ)) {
1499 conflux_launch_leg(nonce);
1500 }
1501 }
1502 /* After this, it might have been freed. */
1503 unlinked = NULL;
1504
1505 /* Unlinked circuits should not have attached streams, but check
1506 * anyway, because The Maze. */
1508}
1509
1510/** Update all stream pointers to point to this circuit.
1511 * This is used when a linked circuit is closed and we need to update the
1512 * streams to point to the remaining circuit
1513 */
1514static void
1516{
1517 tor_assert(circ);
1518 tor_assert_nonfatal(circ->conflux);
1519
1520 if (CIRCUIT_IS_ORIGIN(circ)) {
1521 origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
1522 tor_assert_nonfatal(circ->purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED);
1523 /* Iterate over stream list using next_stream pointer, until null */
1524 for (edge_connection_t *stream = ocirc->p_streams; stream;
1525 stream = stream->next_stream) {
1526 /* Update the circuit pointer of each stream */
1527 stream->on_circuit = circ;
1528 stream->cpath_layer = ocirc->cpath->prev;
1529 }
1530 } else {
1531 or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
1532 /* Iterate over stream list using next_stream pointer, until null */
1533 for (edge_connection_t *stream = orcirc->n_streams; stream;
1534 stream = stream->next_stream) {
1535 /* Update the circuit pointer of each stream */
1536 stream->on_circuit = circ;
1537 }
1538 /* Iterate over stream list using next_stream pointer, until null */
1539 for (edge_connection_t *stream = orcirc->resolving_streams; stream;
1540 stream = stream->next_stream) {
1541 /* Update the circuit pointer of each stream */
1542 stream->on_circuit = circ;
1543 }
1544 }
1545}
1546
1547/** Nullify all streams of the given circuit. */
1548static void
1550{
1551 tor_assert(circ);
1552
1553 if (CIRCUIT_IS_ORIGIN(circ)) {
1554 origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
1555 ocirc->p_streams = NULL;
1556 ocirc->half_streams = NULL;
1557 } else {
1558 or_circuit_t *orcirc = TO_OR_CIRCUIT(circ);
1559 orcirc->n_streams = NULL;
1560 orcirc->resolving_streams = NULL;
1561 }
1562}
1563
1564/** The given circuit is already linked to a set and has been closed. Remove it
1565 * from the set and free the pool if no more legs. */
1566static void
1568{
1569 bool is_client = false;
1570 bool full_teardown = false;
1571 uint8_t nonce[DIGEST256_LEN] = {0};
1572
1573 tor_assert(circ);
1574 tor_assert(circ->conflux);
1575
1576 if (CIRCUIT_IS_ORIGIN(circ)) {
1577 tor_assert_nonfatal(circ->purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED);
1578 is_client = true;
1579 }
1580
1581 /* Unlink circuit from its conflux object. */
1582 full_teardown = cfx_del_leg(circ->conflux, circ);
1583
1584 if (CONFLUX_NUM_LEGS(circ->conflux) == 0) {
1585 /* Last leg, remove conflux object from linked set. */
1586 linked_pool_del(circ->conflux->nonce, is_client);
1587 } else {
1588 /* If there are other circuits, update streams backpointers and
1589 * nullify the stream lists. We do not free those streams in circuit_free_.
1590 * (They only get freed when the last circuit is freed). */
1591 conflux_leg_t *leg = smartlist_get(circ->conflux->legs, 0);
1594 }
1595
1596 /* Keep the nonce so we can use it through out the rest of the function in
1597 * case we nullify the conflux object before. Reason is that in the case of a
1598 * full teardown, this function becomes basically recursive and so we must
1599 * nullify the conflux object of this circuit now before the recursiveness
1600 * starts leading to all legs being removed and thus not noticing if we are
1601 * the last or the first.
1602 *
1603 * Not the prettiest but that is the price to pay to live in the C-tor maze
1604 * and protected by ballrogs. */
1605 memcpy(nonce, circ->conflux->nonce, sizeof(nonce));
1606
1607 /* Nullify the conflux object from the circuit being closed iff we have more
1608 * legs. Reason being that the last leg needs to have the conflux object
1609 * attached to the circuit so it can be freed in conflux_circuit_free(). */
1610 if (CONFLUX_NUM_LEGS(circ->conflux) > 0) {
1611 circ->conflux = NULL;
1612 }
1613
1614 /* If this was a teardown condition, we need to mark other circuits,
1615 * including any potential unlinked circuits, for close.
1616 *
1617 * This call is recursive in the sense that linked_circuit_closed() will end
1618 * up being called for all legs and so by the time we come back here, the
1619 * linked is likely entirely gone. Thus why this is done last. */
1620 if (full_teardown) {
1621 conflux_mark_all_for_close(nonce, is_client, END_CIRC_REASON_FINISHED);
1622 }
1623}
1624
1625/** The given circuit is being freed and it is a linked leg. Clean up and free
1626 * anything that has to do with this circuit.
1627 *
1628 * After this call, the circuit should NOT be referenced anymore anywhere. */
1629static void
1630linked_circuit_free(circuit_t *circ, bool is_client)
1631{
1632 tor_assert(circ);
1633 tor_assert(circ->conflux);
1634 tor_assert(circ->conflux->legs);
1635 tor_assert(circ->conflux->ooo_q);
1636
1637 if (is_client) {
1638 tor_assert(circ->purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED);
1639 }
1640
1641 /* Circuit can be freed without being closed and so we try to delete this leg
1642 * so we can learn if this circuit is the last leg or not. */
1643 if (cfx_del_leg(circ->conflux, circ)) {
1644 /* Check for instances of bug #40870, which we suspect happen
1645 * during exit. If any happen outside of exit, BUG and warn. */
1646 if (!circ->conflux->in_full_teardown) {
1647 /* We should bug and warn if we're not in a shutdown process; that
1648 * means we got here somehow without a close. */
1649 if (BUG(!shutting_down)) {
1650 log_warn(LD_BUG,
1651 "Conflux circuit %p being freed without being marked for "
1652 "full teardown via close, with shutdown state %d. "
1653 "Please report this.", circ, shutting_down);
1654 conflux_log_set(LOG_WARN, circ->conflux, is_client);
1655 }
1656 circ->conflux->in_full_teardown = true;
1657 }
1658 }
1659
1660 if (CONFLUX_NUM_LEGS(circ->conflux) > 0) {
1661 /* The last leg will free the streams but until then, we nullify to avoid
1662 * use-after-free. */
1664 } else {
1665 /* We are the last leg. */
1666
1667 /* Remove from pool in case it is still lingering there else we'll end up
1668 * in a double free situation. */
1669 linked_pool_del(circ->conflux->nonce, is_client);
1670
1671 /* If there is an unlinked circuit that was also created for this set, we
1672 * need to look for it, and tell it is no longer part of a linked set
1673 * anymore, so it can be freed properly, or can complete the link if it is
1674 * able to. Effectively, the conflux_t object lifetime is longer than
1675 * either the linked or unlinked sets by themselves. This is a situation we
1676 * could cover with handles, but so far, it is not clear they are an
1677 * obvious benefit for other cases than this one. */
1678 unlinked_circuits_t *unlinked =
1679 unlinked_pool_get(circ->conflux->nonce, is_client);
1680 if (unlinked) {
1681 tor_assert(unlinked->is_for_linked_set);
1682 unlinked->is_for_linked_set = false;
1683 } else {
1684 /* We are the last one, clear the conflux object. If an unlinked object
1685 * has a reference to it, it won't get freed due to is_for_linked_set
1686 * flag. */
1687 conflux_free(circ->conflux);
1688 }
1689 }
1690}
1691
1692/** The given circuit is being freed and it is an unlinked leg. Clean up and
1693 * free anything that has to do with this circuit.
1694 *
1695 * After this call, the circuit should NOT be referenced anymore anywhere. */
1696static void
1697unlinked_circuit_free(circuit_t *circ, bool is_client)
1698{
1699 tor_assert(circ);
1701 if (is_client) {
1703 }
1704
1705 /* Cleanup circuit reference if a leg exists. This is possible if the circuit
1706 * was not marked for close before being freed. */
1707 leg_t *leg = unlinked_leg_find(circ, is_client);
1708 if (leg) {
1709 leg->circ = NULL;
1710 }
1711
1712 /* Null pointers are safe here. */
1714}
1715
1716/** Circuit has been marked for close. */
1717void
1719{
1720 /* The unlinked case. If an unlinked set exists, we delete the leg and then
1721 * attempt to finalize it. After that, we'll launch a new leg to recover. */
1722 if (circ->conflux_pending_nonce) {
1724 } else if (circ->conflux) {
1726 }
1727}
1728
1729/** Circuit with conflux purpose just opened. */
1730void
1732{
1733 circuit_t *circ = NULL;
1734 leg_t *leg = NULL;
1735
1736 tor_assert(orig_circ);
1737
1738 circ = TO_CIRCUIT(orig_circ);
1739
1740 /* Extra safety layer so we never let a circuit opens if conflux is not
1741 * enabled. */
1742 if (!conflux_is_enabled(circ)) {
1743 circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
1744 static ratelim_t conflux_ratelim = RATELIM_INIT(600);
1745 log_fn_ratelim(&conflux_ratelim, LOG_NOTICE, LD_CIRC,
1746 "Conflux circuit opened without negotiating "
1747 "congestion control");
1748 return;
1749 }
1750
1751 /* Unrelated to conflux. */
1752 if (circ->conflux_pending_nonce == NULL) {
1753 goto end;
1754 }
1755
1756 log_info(LD_CIRC, "Conflux circuit has opened with nonce %s",
1758
1759 leg = unlinked_leg_find(circ, true);
1760 if (BUG(!leg)) {
1761 log_warn(LD_CIRC, "Unable to find conflux leg in unlinked set.");
1762 goto end;
1763 }
1764
1765 /* On failure here, the circuit is closed and thus the leg and unlinked set
1766 * will be cleaned up. */
1767 if (!conflux_cell_send_link(leg->link, orig_circ)) {
1768 goto end;
1769 }
1770
1771 /* Mark the leg on when the LINK cell is sent. Used to timeout the circuit
1772 * for a minimum RTT when getting the LINKED. */
1773 leg->link_sent_usec = monotime_absolute_usec();
1774
1775 end:
1777 return;
1778}
1779
1780/** Process a CONFLUX_LINK cell which arrived on the given circuit. */
1781void
1783{
1784 unlinked_circuits_t *unlinked = NULL;
1785 conflux_cell_link_t *link = NULL;
1786
1787 tor_assert(circ);
1788 tor_assert(msg);
1789
1790 if (!conflux_is_enabled(circ)) {
1791 circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
1792 goto end;
1793 }
1794
1795 /* This cell can't be received on an origin circuit because only the endpoint
1796 * creating the circuit sends it. */
1797 if (CIRCUIT_IS_ORIGIN(circ)) {
1798 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
1799 "Got a CONFLUX_LINK cell on an origin circuit. Closing circuit.");
1800 circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
1801 goto end;
1802 }
1803
1804 if (!conflux_validate_source_hop(circ, NULL)) {
1805 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
1806 "Got a CONFLUX_LINK with further hops. Closing circuit.");
1807 circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
1808 goto end;
1809 }
1810
1811 if (circ->conflux_pending_nonce) {
1812 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
1813 "Got a CONFLUX_LINK on a circuit with a pending nonce. "
1814 "Closing circuit.");
1815 circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
1816 goto end;
1817 }
1818
1819 if (circ->conflux) {
1820 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
1821 "Got a CONFLUX_LINK on an already linked circuit "
1822 "Closing circuit.");
1823 circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
1824 goto end;
1825 }
1826
1827 /* On errors, logging is emitted in this parsing function. */
1828 link = conflux_cell_parse_link(msg);
1829 if (!link) {
1830 log_fn(LOG_PROTOCOL_WARN, LD_CIRC, "Unable to parse "
1831 "CONFLUX_LINK cell. Closing circuit.");
1832 circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
1833 goto end;
1834 }
1835
1836 log_info(LD_CIRC, "Processing a CONFLUX_LINK for set %s",
1837 fmt_nonce(link->nonce));
1838
1839 /* Consider this circuit a new leg. We'll now attempt to attach it to an
1840 * existing set or unlinked one. */
1841 leg_t *leg = leg_new(circ, link);
1842 unlinked = unlinked_get_or_create(link->nonce, false);
1843 tor_assert(unlinked);
1844
1845 /* Attach leg to the unlinked set. */
1846 unlinked_leg_add(unlinked, leg);
1847
1848 /* Set the circuit in a pending conflux state for the LINKED_ACK. */
1849 circ->conflux_pending_nonce = tor_memdup(leg->link->nonce,
1850 sizeof(leg->link->nonce));
1851
1852 /* Mark when we send the LINKED. */
1853 leg->link_sent_usec = monotime_absolute_usec();
1854
1855 /* Send LINKED. */
1856 uint64_t last_seq_sent = conflux_get_max_seq_sent(unlinked->cfx);
1857 uint64_t last_seq_recv = unlinked->cfx->last_seq_delivered;
1858
1859 // TODO-329-ARTI: To support resumption/retransmit, the server should
1860 // store the last_seq_sent now, so that it can know how much data
1861 // to retransmit to the server after link. C-Tor will not be implementing
1862 // this, but arti and arti-relay could (if resumption seems worthwhile;
1863 // it may not be worth the memory storage there, either).
1864
1865 uint8_t nonce[DIGEST256_LEN];
1866 memcpy(nonce, circ->conflux_pending_nonce, sizeof(nonce));
1867
1868 /* Link the circuit to the a conflux set immediately before the LINKED is
1869 * sent. Reason is that once the client sends the LINKED_ACK, there is a race
1870 * with the BEGIN cell that can be sent immediately after and arrive first.
1871 * And so, we need to sync the streams before that happens that is before we
1872 * receive the LINKED_ACK. */
1873 if (link_circuit(circ) != ERR_LINK_CIRC_OK) {
1874 circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
1875 goto end;
1876 }
1877
1878 /* Exits should always request min latency from clients */
1879 conflux_cell_link_t *linked = conflux_cell_new_link(nonce, last_seq_sent,
1880 last_seq_recv,
1881 DEFAULT_EXIT_UX);
1882
1883 conflux_cell_send_linked(linked, TO_OR_CIRCUIT(circ));
1884 tor_free(linked);
1885
1886 end:
1887 return;
1888}
1889
1890/** Process a CONFLUX_LINKED cell which arrived on the given circuit. */
1891void
1893 const relay_msg_t *msg)
1894{
1895 conflux_cell_link_t *link = NULL;
1896
1897 tor_assert(circ);
1898
1899 /*
1900 * There several ways a malicious exit could create problems when sending
1901 * back this LINKED cell.
1902 *
1903 * 1. Using a different nonce that it knows about from another set. Accepting
1904 * it would mean a confirmation attack of linking sets to the same client.
1905 * To address that, the cell nonce MUST be matched with the circuit nonce.
1906 *
1907 * 2. Re-Sending a LINKED cell on an already linked circuit could create side
1908 * channel attacks or unpredictable issues. Circuit is closed.
1909 *
1910 * 3. Receiving a LINKED cell on a circuit that was not expecting it. Again,
1911 * as (2), can create side channel(s). Circuit is closed.
1912 *
1913 * 4. Receiving a LINKED cell from the another hop other than the last one
1914 * (exit). Same as (2) and (3) in terms of issues. Circuit is closed.
1915 */
1916
1917 if (!conflux_is_enabled(circ)) {
1918 circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
1919 goto end;
1920 }
1921
1922 /* LINKED cell are in response to a LINK cell which are only sent on an
1923 * origin circuit and thus received on such.*/
1924 if (!CIRCUIT_IS_ORIGIN(circ)) {
1925 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
1926 "Received CONFLUX_LINKED cell on a non origin circuit.");
1927 goto close;
1928 }
1929
1930 if (!circ->conflux_pending_nonce) {
1931 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
1932 "Received a CONFLUX_LINKED cell without having sent a "
1933 "CONFLUX_LINK cell. Closing circuit.");
1934 goto close;
1935 }
1936
1937 if (circ->conflux) {
1938 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
1939 "Received a CONFLUX_LINKED cell on a circuit that is already "
1940 "linked. Closing circuit.");
1941 goto close;
1942 }
1943
1944 if (!conflux_validate_source_hop(circ, layer_hint)) {
1945 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
1946 "Got a CONFLUX_LINKED from wrong hop on circuit. Closing circuit.");
1947 goto close;
1948 }
1949
1950 tor_assert_nonfatal(circ->purpose == CIRCUIT_PURPOSE_CONFLUX_UNLINKED);
1951
1952 /* On errors, logging is emitted in this parsing function. */
1953 link = conflux_cell_parse_link(msg);
1954 if (!link) {
1955 goto close;
1956 }
1957
1958 log_info(LD_CIRC, "Processing a CONFLUX_LINKED for set %s",
1959 fmt_nonce(link->nonce));
1960
1961 /* Make sure the cell nonce matches the one on the circuit that was
1962 * previously set by the CONFLUX_LINK cell. */
1963 if (tor_memneq(link->nonce, circ->conflux_pending_nonce,
1964 sizeof(*link->nonce))) {
1965 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
1966 "Received CONFLUX_LINKED but circuit nonce doesn't match "
1967 "cell nonce. Closing circuit.");
1968 goto close;
1969 }
1970
1971 /* Find the leg from the associated unlinked set. */
1972 leg_t *leg = unlinked_leg_find(circ, true);
1973 if (BUG(!leg)) {
1974 log_warn(LD_CIRC, "Received CONFLUX_LINKED but can't find "
1975 "associated leg. Closing circuit.");
1976 goto close;
1977 }
1978
1979 log_info(LD_CIRC, "Successfully processed a CONFLUX_LINKED cell.");
1980
1981 /* Free the old link, and store the new one. We need to validate
1982 * the one we get during finalize, not the one we sent. */
1983 tor_free(leg->link);
1984 leg->link = link;
1985
1986 /* Record the RTT for this circuit. On failure, it means the RTT was too
1987 * high, we relaunch to recover. */
1988 if (!record_rtt(circ, true)) {
1989 goto close;
1990 }
1991
1992 /* The following will link the circuit with its set and attempt to finalize
1993 * the set if all expected legs have linked. On error, we close the circuit
1994 * because it means the unlinked set needs to be teardowned. */
1995 link_circ_err_t err = link_circuit(circ);
1996 switch (err) {
1997 case ERR_LINK_CIRC_OK:
1998 /* Successfully linked. */
1999 break;
2000 case ERR_LINK_CIRC_INVALID_LEG:
2001 case ERR_LINK_CIRC_MISSING_SET:
2002 /* No relaunch if the leg is invalid or the set is not found as in the
2003 * nonce is unknown. */
2004 break;
2005 case ERR_LINK_CIRC_BAD_RTT:
2006 case ERR_LINK_CIRC_MISSING_LEG:
2007 goto close;
2008 }
2009
2010 /* We can send the ack only if we finalize. This will not cause issues,
2011 * because LINKED_ACK is exempted from multiplexing in
2012 * conflux_should_multiplex(). */
2013 if (!conflux_cell_send_linked_ack(TO_ORIGIN_CIRCUIT(circ))) {
2014 /* On failure, the circuit is closed by the underlying function(s). */
2015 goto end;
2016 }
2017
2018 /* If this set is ready to use with a valid conflux set, try any pending
2019 * streams again. */
2020 if (circ->conflux) {
2022 }
2023
2024 /* This cell is now considered valid for clients. */
2025 circuit_read_valid_data(TO_ORIGIN_CIRCUIT(circ), msg->length);
2026
2027 goto end;
2028
2029 close:
2030 circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
2031
2032 end:
2033 return;
2034}
2035
2036/** Process a CONFLUX_LINKED_ACK cell which arrived on the given circuit. */
2037void
2039{
2040 tor_assert(circ);
2041
2042 if (!conflux_is_enabled(circ)) {
2043 goto close;
2044 }
2045
2046 if (CIRCUIT_IS_ORIGIN(circ)) {
2047 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
2048 "Received CONFLUX_LINKED_ACK cell on an origin circuit. Closing.");
2049 goto close;
2050 }
2051
2052 if (!conflux_validate_source_hop(circ, NULL)) {
2053 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
2054 "Got a CONFLUX_LINKED_ACK with further hops. Closing circuit.");
2055 goto close;
2056 }
2057
2058 if (BUG(!circ->conflux)) {
2059 log_fn(LOG_PROTOCOL_WARN, LD_CIRC,
2060 "Received a CONFLUX_LINKED_ACK cell on a circuit that is not"
2061 "linked. Closing circuit.");
2062 goto close;
2063 }
2064
2065 log_info(LD_CIRC, "Processing a CONFLUX_LINKED_ACK for set %s",
2066 fmt_nonce(circ->conflux->nonce));
2067
2068 /* Record the RTT for this circuit. This should not fail */
2069 if (BUG(!record_rtt(circ, false))) {
2070 goto close;
2071 }
2072
2073 return;
2074
2075 close:
2076 circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
2077}
2078
2079/** Called when a circuit is freed.
2080 *
2081 * It is possible a conflux circuit gets freed without being closed (for
2082 * instance SIGTERM) and so this callback is needed in order to finalize the
2083 * cleanup. */
2084void
2086{
2087 tor_assert(circ);
2088
2089 bool is_client = CIRCUIT_IS_ORIGIN(circ);
2090
2091 if (circ->conflux) {
2092 linked_circuit_free(circ, is_client);
2093 } else if (circ->conflux_pending_nonce) {
2094 unlinked_circuit_free(circ, is_client);
2095 }
2096
2097 /* Whatever happens, nullify all conflux related pointers. */
2098 circ->conflux = NULL;
2099 circ->conflux_pending_nonce = NULL;
2100}
2101
2102/** Initialize the conflux pool subsystem. This is called by the subsys
2103 * manager. */
2104void
2106{
2107 if (!client_linked_pool) {
2108 client_linked_pool = digest256map_new();
2109 }
2110 if (!client_unlinked_pool) {
2111 client_unlinked_pool = digest256map_new();
2112 }
2113 if (!server_linked_pool) {
2114 server_linked_pool = digest256map_new();
2115 }
2116 if (!server_unlinked_pool) {
2117 server_unlinked_pool = digest256map_new();
2118 }
2119}
2120
2121/**
2122 * Return a description of all linked and unlinked circuits associated
2123 * with a conflux set.
2124 *
2125 * For use in rare bug cases that are hard to diagnose.
2126 */
2127void
2128conflux_log_set(int loglevel, const conflux_t *cfx, bool is_client)
2129{
2130 /* This could be called on a closed circuit. */
2131 if (cfx == NULL) {
2132 return;
2133 }
2134
2135 log_fn(loglevel,
2136 LD_BUG,
2137 "Conflux %s: %d linked, %d launched. Delivered: %"PRIu64"; "
2138 "teardown: %d; Current: %p, Previous: %p",
2139 fmt_nonce(cfx->nonce), smartlist_len(cfx->legs),
2140 cfx->num_leg_launch,
2142 cfx->curr_leg, cfx->prev_leg);
2143
2144 // Log all linked legs
2145 int legs = 0;
2146 CONFLUX_FOR_EACH_LEG_BEGIN(cfx, leg) {
2147 const struct congestion_control_t *cc = circuit_ccontrol(leg->circ);
2148 log_fn(loglevel, LD_BUG,
2149 " - Linked Leg %d purpose=%d; RTT %"PRIu64", sent: %"PRIu64
2150 "; sent: %"PRIu64", recv: %"PRIu64", infl: %"PRIu64", "
2151 "ptr: %p, idx: %d, marked: %d",
2152 legs, leg->circ->purpose, leg->circ_rtts_usec,
2153 leg->linked_sent_usec, leg->last_seq_recv,
2154 leg->last_seq_sent, cc->inflight, leg->circ,
2155 leg->circ->global_circuitlist_idx,
2156 leg->circ->marked_for_close);
2157 legs++;
2158 } CONFLUX_FOR_EACH_LEG_END(leg);
2159
2160 // Look up the nonce to see if we have any unlinked circuits.
2161 unlinked_circuits_t *unlinked = unlinked_pool_get(cfx->nonce, is_client);
2162 if (unlinked) {
2163 // Log the number of legs and the is_for_linked_set status
2164 log_fn(loglevel, LD_BUG, " - Unlinked set: %d legs, for link: %d",
2165 smartlist_len(unlinked->legs), unlinked->is_for_linked_set);
2166 legs = 0;
2167 SMARTLIST_FOREACH_BEGIN(unlinked->legs, leg_t *, leg) {
2168 log_fn(loglevel, LD_BUG,
2169 " Unlinked Leg: %d purpose=%d; linked: %d, RTT %"PRIu64", "
2170 "sent: %"PRIu64" link ptr %p, circ ptr: %p, idx: %d, marked: %d",
2171 legs, leg->circ->purpose, leg->linked,
2172 leg->rtt_usec, leg->link_sent_usec,
2173 leg->link, leg->circ,
2174 leg->circ->global_circuitlist_idx,
2175 leg->circ->marked_for_close);
2176 legs++;
2177 } SMARTLIST_FOREACH_END(leg);
2178 }
2179}
2180
2181/**
2182 * Conflux needs a notification when tor_shutdown() begins, so that
2183 * when circuits are freed, new legs are not launched.
2184 *
2185 * This needs a separate notification from conflux_pool_free_all(),
2186 * because circuits must be freed before that function.
2187 */
2188void
2190{
2191 shutting_down = true;
2192}
2193
2194#ifdef TOR_UNIT_TESTS
2195/**
2196 * For unit tests: Clear the shutting down state so we resume building legs.
2197 */
2198void
2199conflux_clear_shutdown(void)
2200{
2201 shutting_down = false;
2202}
2203#endif
2204
2205/** Free and clean up the conflux pool subsystem. This is called by the subsys
2206 * manager AFTER all circuits have been freed which implies that all objects in
2207 * the pools aren't referenced anymore. */
2208void
2210{
2211 digest256map_free(client_linked_pool, free_conflux_void_);
2212 digest256map_free(server_linked_pool, free_conflux_void_);
2213 digest256map_free(client_unlinked_pool, free_unlinked_void_);
2214 digest256map_free(server_unlinked_pool, free_unlinked_void_);
2215}
const char * hex_str(const char *from, size_t fromlen)
Definition binascii.c:34
bool conflux_can_exclude_used_bridges(void)
Definition bridges.c:147
Header file for circuitbuild.c.
origin_circuit_t * circuit_establish_circuit_conflux(const uint8_t *conflux_nonce, uint8_t purpose, extend_info_t *exit_ei, int flags)
Header file for circuitbuild.c.
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)
#define CIRCUIT_PURPOSE_CONFLUX_UNLINKED
double get_circuit_build_timeout_ms(void)
Header file for circuitstats.c.
void circuit_read_valid_data(origin_circuit_t *circ, uint16_t relay_body_len)
void circuit_change_purpose(circuit_t *circ, uint8_t new_purpose)
int circuit_is_acceptable(const origin_circuit_t *origin_circ, const entry_connection_t *conn, int must_be_open, uint8_t purpose, int need_uptime, int need_internal, time_t now)
Definition circuituse.c:109
Header file for circuituse.c.
#define CIRCLAUNCH_NEED_CAPACITY
Definition circuituse.h:43
#define CIRCLAUNCH_NEED_UPTIME
Definition circuituse.h:41
#define CIRCLAUNCH_NEED_CONFLUX
Definition circuituse.h:53
uint64_t monotime_absolute_usec(void)
const or_options_t * get_options(void)
Definition config.c:948
Header file for config.c.
const congestion_control_t * circuit_ccontrol(const circuit_t *circ)
Definition conflux.c:729
uint64_t conflux_get_max_seq_recv(const conflux_t *cfx)
Definition conflux.c:156
uint64_t conflux_get_max_seq_sent(const conflux_t *cfx)
Definition conflux.c:139
conflux_leg_t * conflux_get_leg(conflux_t *cfx, const circuit_t *circ)
Definition conflux.c:118
Public APIs for conflux multipath support.
#define CONFLUX_FOR_EACH_LEG_BEGIN(cfx, var)
Definition conflux.h:20
#define CONFLUX_NUM_LEGS(cfx)
Definition conflux.h:26
Header file for conflux_cell.c.
Header file for conflux_params.c.
static void unlinked_pool_del(unlinked_circuits_t *unlinked, bool is_client)
static const char * fmt_nonce(const uint8_t *nonce)
static link_circ_err_t link_circuit(circuit_t *circ)
static unlinked_circuits_t * unlinked_pool_get(const uint8_t *nonce, bool is_client)
static leg_t * leg_find(const unlinked_circuits_t *unlinked, const circuit_t *circ)
static void linked_circuit_closed(circuit_t *circ)
void conflux_circuit_has_opened(origin_circuit_t *orig_circ)
void conflux_process_linked_ack(circuit_t *circ)
static void unlinked_close_all_legs(unlinked_circuits_t *unlinked)
static void leg_free(leg_t *leg)
#define conflux_free(cfx)
static bool cfx_del_leg(conflux_t *cfx, const circuit_t *circ)
void conflux_log_set(int loglevel, const conflux_t *cfx, bool is_client)
void conflux_circuit_has_closed(circuit_t *circ)
static void linked_circuit_free(circuit_t *circ, bool is_client)
static void free_conflux_void_(void *ptr)
static void cfx_add_leg(conflux_t *cfx, leg_t *leg)
static extend_info_t * get_exit_for_nonce(const uint8_t *nonce)
static uint64_t record_rtt_client(const circuit_t *circ)
STATIC bool launch_new_set(int num_legs)
static bool validate_unlinked_legs(unlinked_circuits_t *unlinked)
static bool record_rtt(const circuit_t *circ, bool is_client)
static leg_t * leg_new(circuit_t *circ, conflux_cell_link_t *link)
void conflux_predict_new(time_t now)
static void linked_nullify_streams(circuit_t *circ)
static bool launch_leg_is_allowed(const conflux_t *cfx)
static digest256map_t * server_unlinked_pool
void conflux_notify_shutdown(void)
static uint8_t conflux_choose_algorithm(uint8_t desired_ux)
static void linked_pool_del(const uint8_t *nonce, bool is_client)
static link_circ_err_t try_finalize_set(unlinked_circuits_t *unlinked)
static void unlinked_pool_add(unlinked_circuits_t *unlinked, bool is_client)
static digest256map_t * client_linked_pool
static void linked_update_stream_backpointers(circuit_t *circ)
static void unlinked_pool_del_and_free(unlinked_circuits_t *unlinked, bool is_client)
void conflux_pool_init(void)
static void unlinked_circuit_free(circuit_t *circ, bool is_client)
static conflux_t * linked_pool_get(const uint8_t *nonce, bool is_client)
void conflux_add_middles_to_exclude_list(const origin_circuit_t *orig_circ, smartlist_t *excluded)
static void unlinked_close_or_free(unlinked_circuits_t *unlinked)
void conflux_circuit_about_to_free(circuit_t *circ)
static unlinked_circuits_t * unlinked_new(const uint8_t *nonce, bool is_client)
static uint64_t record_rtt_exit(const circuit_t *circ)
static void free_unlinked_void_(void *ptr)
static digest256map_t * client_unlinked_pool
link_circ_err_t
static digest256map_t * server_linked_pool
static void linked_pool_add(conflux_t *cfx, bool is_client)
bool conflux_launch_leg(const uint8_t *nonce)
static void unlinked_leg_add(unlinked_circuits_t *unlinked, leg_t *leg)
static int count_client_usable_sets(void)
void conflux_mark_all_for_close(const uint8_t *nonce, bool is_client, int reason)
static void unlinked_free(unlinked_circuits_t *unlinked)
void conflux_pool_free_all(void)
void conflux_add_guards_to_exclude_list(const origin_circuit_t *orig_circ, smartlist_t *excluded)
origin_circuit_t * conflux_get_circ_for_conn(const entry_connection_t *conn, time_t now)
static conflux_t * conflux_new(void)
static void validate_circ_has_no_streams(circuit_t *circ)
static uint8_t get_client_ux(void)
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 relay_msg_t *msg)
static void unlinked_circuit_closed(circuit_t *circ)
static leg_t * unlinked_leg_find(const circuit_t *circ, bool is_client)
Header file for conflux_pool.c.
Structure definitions for conflux multipath.
void conflux_validate_stream_lists(const conflux_t *cfx)
bool conflux_validate_source_hop(circuit_t *in_circ, crypt_path_t *layer_hint)
void conflux_sync_circ_fields(conflux_t *cfx, origin_circuit_t *ref_circ)
Header file for conflux_util.c.
Structure definitions for congestion control.
void connection_ap_attach_pending(int retry)
Header file for connection_edge.c.
Path structures for origin circuits.
void crypto_rand(char *to, size_t n)
Common functions for using (pseudo-)random number generators.
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition crypto_util.c:55
Common functions for cryptographic routines.
int tor_memeq(const void *a, const void *b, size_t sz)
Definition di_ops.c:107
#define tor_memneq(a, b, sz)
Definition di_ops.h:21
#define DIGEST_LEN
#define DIGEST256_LEN
Edge-connection structure.
Extend-info structure.
#define log_fn(severity, domain, args,...)
Definition log.h:283
#define log_fn_ratelim(ratelim, severity, domain, args,...)
Definition log.h:288
#define LD_BUG
Definition log.h:86
#define LOG_NOTICE
Definition log.h:50
#define LD_CIRC
Definition log.h:82
#define LOG_WARN
Definition log.h:53
#define tor_free(p)
Definition malloc.h:56
consensus_path_type_t router_have_consensus_path(void)
Definition nodelist.c:2514
node_t * node_get_mutable_by_id(const char *identity_digest)
Definition nodelist.c:197
Header file for nodelist.c.
Master header file for Tor-specific functionality.
#define TO_CIRCUIT(x)
Definition or.h:951
Origin circuit structure.
bool have_been_under_memory_pressure(void)
Definition relay.c:2930
Header file for relay.c.
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
void smartlist_remove(smartlist_t *sl, const void *element)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
#define SMARTLIST_DEL_CURRENT(sl, var)
time_t timestamp_dirty
Definition circuit_st.h:198
uint16_t marked_for_close
Definition circuit_st.h:200
struct conflux_t * conflux
Definition circuit_st.h:273
uint8_t purpose
Definition circuit_st.h:112
uint8_t * conflux_pending_nonce
Definition circuit_st.h:281
uint64_t last_seq_sent
Definition conflux_st.h:66
uint64_t last_seq_recv
Definition conflux_st.h:47
uint64_t circ_rtts_usec
Definition conflux_st.h:75
uint64_t linked_sent_usec
Definition conflux_st.h:79
circuit_t * circ
Definition conflux_st.h:82
smartlist_t * ooo_q
Definition conflux_st.h:103
struct conflux_leg_t * curr_leg
Definition conflux_st.h:123
struct conflux_params_t params
Definition conflux_st.h:88
struct conflux_leg_t * prev_leg
Definition conflux_st.h:127
uint8_t nonce[DIGEST256_LEN]
Definition conflux_st.h:130
uint64_t last_seq_delivered
Definition conflux_st.h:114
smartlist_t * legs
Definition conflux_st.h:93
bool in_full_teardown
Definition conflux_st.h:135
unsigned int num_leg_launch
Definition conflux_st.h:139
struct crypt_path_t * prev
struct crypt_path_t * next
extend_info_t * extend_info
char identity_digest[DIGEST_LEN]
edge_connection_t * resolving_streams
edge_connection_t * n_streams
edge_connection_t * p_streams
unsigned int isolation_values_set
crypt_path_t * cpath
smartlist_t * half_streams
#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