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