Tor  0.4.7.0-alpha-dev
Data Structures | Macros | Functions | Variables
circuitlist.c File Reference

Manage global structures that list and index circuits, and look up circuits within them. More...

#include "lib/cc/torint.h"
#include "core/or/or.h"
#include "core/or/channel.h"
#include "core/or/channeltls.h"
#include "feature/client/circpathbias.h"
#include "core/or/circuitbuild.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
#include "core/or/circuitstats.h"
#include "core/or/circuitpadding.h"
#include "core/or/crypt_path.h"
#include "core/or/extendinfo.h"
#include "core/or/trace_probes_circuit.h"
#include "core/mainloop/connection.h"
#include "app/config/config.h"
#include "core/or/connection_edge.h"
#include "core/or/connection_or.h"
#include "feature/control/control_events.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_util.h"
#include "lib/crypt_ops/crypto_dh.h"
#include "feature/dircommon/directory.h"
#include "feature/client/entrynodes.h"
#include "core/mainloop/mainloop.h"
#include "feature/hs/hs_cache.h"
#include "feature/hs/hs_circuit.h"
#include "feature/hs/hs_circuitmap.h"
#include "feature/hs/hs_ident.h"
#include "feature/nodelist/networkstatus.h"
#include "feature/nodelist/nodelist.h"
#include "feature/relay/onion_queue.h"
#include "core/crypto/onion_crypto.h"
#include "core/crypto/onion_fast.h"
#include "core/or/policies.h"
#include "core/or/relay.h"
#include "core/crypto/relay_crypto.h"
#include "feature/rend/rendcommon.h"
#include "feature/stats/predict_ports.h"
#include "feature/stats/bwhist.h"
#include "feature/stats/rephist.h"
#include "feature/nodelist/routerlist.h"
#include "feature/nodelist/routerset.h"
#include "core/or/channelpadding.h"
#include "lib/compress/compress.h"
#include "lib/compress/compress_lzma.h"
#include "lib/compress/compress_zlib.h"
#include "lib/compress/compress_zstd.h"
#include "lib/buf/buffers.h"
#include "core/or/ocirc_event.h"
#include "ht.h"
#include "core/or/cpath_build_state_st.h"
#include "core/or/crypt_path_reference_st.h"
#include "feature/dircommon/dir_connection_st.h"
#include "core/or/edge_connection_st.h"
#include "core/or/half_edge_st.h"
#include "core/or/extend_info_st.h"
#include "core/or/or_circuit_st.h"
#include "core/or/origin_circuit_st.h"

Go to the source code of this file.

Data Structures

struct  chan_circid_circuit_map_t
 

Macros

#define CIRCUITLIST_PRIVATE
 
#define OCIRC_EVENT_PRIVATE
 
#define DFLT_IDLE_TIMEOUT_WHILE_LEARNING   (3*60)
 
#define MIN_IDLE_TIMEOUT_WHILE_LEARNING   (10)
 
#define MAX_IDLE_TIMEOUT_WHILE_LEARNING   (1000*60)
 
#define FRACTION_OF_DATA_TO_RETAIN_ON_OOM   0.90
 

Functions

static void circuit_about_to_free_atexit (circuit_t *circ)
 
static void circuit_about_to_free (circuit_t *circ)
 
or_circuit_tTO_OR_CIRCUIT (circuit_t *x)
 
const or_circuit_tCONST_TO_OR_CIRCUIT (const circuit_t *x)
 
origin_circuit_tTO_ORIGIN_CIRCUIT (circuit_t *x)
 
const origin_circuit_tCONST_TO_ORIGIN_CIRCUIT (const circuit_t *x)
 
static int chan_circid_entries_eq_ (chan_circid_circuit_map_t *a, chan_circid_circuit_map_t *b)
 
static unsigned int chan_circid_entry_hash_ (chan_circid_circuit_map_t *a)
 
static HT_HEAD (HT_PROTOTYPE(chan_circid_map, HT_PROTOTYPE(chan_circid_circuit_map_t)
 
void channel_mark_circid_unusable (channel_t *chan, circid_t id)
 
void channel_mark_circid_usable (channel_t *chan, circid_t id)
 
void channel_note_destroy_pending (channel_t *chan, circid_t id)
 
void channel_note_destroy_not_pending (channel_t *chan, circid_t id)
 
void circuit_set_p_circid_chan (or_circuit_t *or_circ, circid_t id, channel_t *chan)
 
void circuit_set_n_circid_chan (circuit_t *circ, circid_t id, channel_t *chan)
 
int circuit_event_status (origin_circuit_t *circ, circuit_status_event_t tp, int reason_code)
 
static void circuit_state_publish (const circuit_t *circ)
 
void circuit_set_state (circuit_t *circ, uint8_t state)
 
void circuit_get_all_pending_on_channel (smartlist_t *out, channel_t *chan)
 
int circuit_count_pending_on_channel (channel_t *chan)
 
static void circuit_remove_from_origin_circuit_list (origin_circuit_t *origin_circ)
 
static void circuit_add_to_origin_circuit_list (origin_circuit_t *origin_circ)
 
void circuit_close_all_marked (void)
 
smartlist_tcircuit_get_global_list (void)
 
smartlist_tcircuit_get_global_origin_circuit_list (void)
 
int circuit_any_opened_circuits (void)
 
void circuit_cache_opened_circuit_state (int circuits_are_opened)
 
int circuit_any_opened_circuits_cached (void)
 
const char * circuit_state_to_string (int state)
 
const char * circuit_purpose_to_controller_string (uint8_t purpose)
 
const char * circuit_purpose_to_controller_hs_state_string (uint8_t purpose)
 
const char * circuit_purpose_to_string (uint8_t purpose)
 
int32_t circuit_initial_package_window (void)
 
static void init_circuit_base (circuit_t *circ)
 
origin_circuit_torigin_circuit_new (void)
 
or_circuit_tor_circuit_new (circid_t p_circ_id, channel_t *p_chan)
 
void circuit_clear_testing_cell_stats (circuit_t *circ)
 
STATIC void circuit_free_ (circuit_t *circ)
 
void circuit_clear_cpath (origin_circuit_t *circ)
 
void circuit_free_all (void)
 
static void circuit_dump_conn_details (int severity, circuit_t *circ, int conn_array_index, const char *type, circid_t this_circid, circid_t other_circid)
 
void circuit_dump_by_conn (connection_t *conn, int severity)
 
origin_circuit_tcircuit_get_by_global_id (uint32_t id)
 
static circuit_tcircuit_get_by_circid_channel_impl (circid_t circ_id, channel_t *chan, int *found_entry_out)
 
circuit_tcircuit_get_by_circid_channel (circid_t circ_id, channel_t *chan)
 
circuit_tcircuit_get_by_circid_channel_even_if_marked (circid_t circ_id, channel_t *chan)
 
int circuit_id_in_use_on_channel (circid_t circ_id, channel_t *chan)
 
time_t circuit_id_when_marked_unusable_on_channel (circid_t circ_id, channel_t *chan)
 
circuit_tcircuit_get_by_edge_conn (edge_connection_t *conn)
 
void circuit_unlink_all_from_channel (channel_t *chan, int reason)
 
origin_circuit_tcircuit_get_next_intro_circ (const origin_circuit_t *start, bool want_client_circ)
 
origin_circuit_tcircuit_get_next_service_rp_circ (origin_circuit_t *start)
 
origin_circuit_tcircuit_get_next_by_purpose (origin_circuit_t *start, uint8_t purpose)
 
static int circuit_can_be_cannibalized_for_v3_rp (const origin_circuit_t *circ)
 
static uint8_t get_circuit_purpose_needed_to_cannibalize (uint8_t purpose)
 
origin_circuit_tcircuit_find_to_cannibalize (uint8_t purpose_to_produce, extend_info_t *info, int flags)
 
smartlist_tcircuit_find_circuits_to_upgrade_from_guard_wait (void)
 
int circuit_get_cpath_len (origin_circuit_t *circ)
 
int circuit_get_cpath_opened_len (const origin_circuit_t *circ)
 
crypt_path_tcircuit_get_cpath_hop (origin_circuit_t *circ, int hopnum)
 
void circuit_mark_all_unused_circs (void)
 
void circuit_mark_all_dirty_circs_as_unusable (void)
 
void circuit_synchronize_written_or_bandwidth (const circuit_t *c, circuit_channel_direction_t dir)
 
void circuit_mark_for_close_ (circuit_t *circ, int reason, int line, const char *file)
 
static void marked_circuit_free_cells (circuit_t *circ)
 
static size_t single_conn_free_bytes (connection_t *conn)
 
static size_t marked_circuit_streams_free_bytes (edge_connection_t *stream)
 
static size_t marked_circuit_free_stream_bytes (circuit_t *c)
 
STATIC size_t n_cells_in_circ_queues (const circuit_t *c)
 
static size_t circuit_alloc_in_half_streams (const circuit_t *c)
 
STATIC uint32_t circuit_max_queued_cell_age (const circuit_t *c, uint32_t now)
 
static uint32_t conn_get_buffer_age (const connection_t *conn, uint32_t now_ts)
 
static uint32_t circuit_get_streams_max_data_age (const edge_connection_t *stream, uint32_t now)
 
STATIC uint32_t circuit_max_queued_data_age (const circuit_t *c, uint32_t now)
 
STATIC uint32_t circuit_max_queued_item_age (const circuit_t *c, uint32_t now)
 
static int circuits_compare_by_oldest_queued_item_ (const void **a_, const void **b_)
 
static int conns_compare_by_buffer_age_ (const void **a_, const void **b_)
 
size_t circuits_handle_oom (size_t current_allocation)
 
void assert_circuit_ok (const circuit_t *c)
 

Variables

static smartlist_tglobal_circuitlist = NULL
 
static smartlist_tglobal_origin_circuit_list = NULL
 
static smartlist_tcircuits_pending_chans = NULL
 
static smartlist_tcircuits_pending_other_guards = NULL
 
static smartlist_tcircuits_pending_close = NULL
 
static int any_opened_circs_cached_val = 0
 
static uint32_t now_ts_for_buf_cmp
 

Detailed Description

Manage global structures that list and index circuits, and look up circuits within them.

One of the most frequent operations in Tor occurs every time that a relay cell arrives on a channel. When that happens, we need to find which circuit it is associated with, based on the channel and the circuit ID in the relay cell.

To handle that, we maintain a global list of circuits, and a hashtable mapping [channel,circID] pairs to circuits. Circuits are added to and removed from this mapping using circuit_set_p_circid_chan() and circuit_set_n_circid_chan(). To look up a circuit from this map, most callers should use circuit_get_by_circid_channel(), though circuit_get_by_circid_channel_even_if_marked() is appropriate under some circumstances.

We also need to allow for the possibility that we have blocked use of a circuit ID (because we are waiting to send a DESTROY cell), but the circuit is not there any more. For that case, we allow placeholder entries in the table, using channel_mark_circid_unusable().

To efficiently handle a channel that has just opened, we also maintain a list of the circuits waiting for channels, so we can attach them as needed without iterating through the whole list of circuits, using circuit_get_all_pending_on_channel().

In this module, we also handle the list of circuits that have been marked for close elsewhere, and close them as needed. (We use this "mark now, close later" pattern here and elsewhere to avoid unpredictable recursion if we closed every circuit immediately upon realizing it needed to close.) See circuit_mark_for_close() for the mark function, and circuit_close_all_marked() for the close function.

For hidden services, we need to be able to look up introduction point circuits and rendezvous circuits by cookie, key, etc. These are currently handled with linear searches in circuit_get_next_by_pk_and_purpose(), and with hash lookups in circuit_get_rendezvous() and circuit_get_intro_point().

This module is also the entry point for our out-of-memory handler logic, which was originally circuit-focused.

Definition in file circuitlist.c.

Macro Definition Documentation

◆ DFLT_IDLE_TIMEOUT_WHILE_LEARNING

#define DFLT_IDLE_TIMEOUT_WHILE_LEARNING   (3*60)

If we haven't yet decided on a good timeout value for circuit building, we close idle circuits aggressively so we can get more data points. These are the default, min, and max consensus values

Definition at line 1010 of file circuitlist.c.

Function Documentation

◆ assert_circuit_ok()

void assert_circuit_ok ( const circuit_t c)

Verify that circuit c has all of its invariants correct. Trigger an assert if anything is invalid.

Definition at line 2716 of file circuitlist.c.

Referenced by circuit_mark_for_close_(), connection_exit_begin_conn(), connection_exit_begin_resolve(), and handle_hs_exit_conn().

◆ chan_circid_entries_eq_()

static int chan_circid_entries_eq_ ( chan_circid_circuit_map_t a,
chan_circid_circuit_map_t b 
)
inlinestatic

Helper for hash tables: compare the channel and circuit ID for a and b, and return less than, equal to, or greater than zero appropriately.

Definition at line 193 of file circuitlist.c.

◆ chan_circid_entry_hash_()

static unsigned int chan_circid_entry_hash_ ( chan_circid_circuit_map_t a)
inlinestatic

Helper: return a hash based on circuit ID and the pointer value of chan in a.

Definition at line 202 of file circuitlist.c.

◆ channel_mark_circid_unusable()

void channel_mark_circid_unusable ( channel_t chan,
circid_t  id 
)

Mark that circuit id id shouldn't be used on channel chan, even if there is no circuit on the channel. We use this to keep the circuit id from getting re-used while we have queued but not yet sent a destroy cell.

Definition at line 353 of file circuitlist.c.

Referenced by channel_note_destroy_pending(), circuit_set_n_circid_chan(), and circuit_set_p_circid_chan().

◆ channel_mark_circid_usable()

void channel_mark_circid_usable ( channel_t chan,
circid_t  id 
)

Mark that a circuit id id can be used again on chan. We use this to re-enable the circuit ID after we've sent a destroy cell.

Definition at line 386 of file circuitlist.c.

Referenced by channel_note_destroy_not_pending(), and circuitmux_mark_destroyed_circids_usable().

◆ channel_note_destroy_not_pending()

void channel_note_destroy_not_pending ( channel_t chan,
circid_t  id 
)

Called to indicate that a DESTROY is no longer pending on chan with circuit ID id – typically, because it has been sent.

Definition at line 429 of file circuitlist.c.

◆ channel_note_destroy_pending()

void channel_note_destroy_pending ( channel_t chan,
circid_t  id 
)

Called to indicate that a DESTROY is pending on chan with circuit ID id, but hasn't been sent yet.

Definition at line 409 of file circuitlist.c.

◆ circuit_about_to_free()

static void circuit_about_to_free ( circuit_t circ)
static

Called immediately before freeing a marked circuit circ. Disconnects the circuit from other data structures, launches events as appropriate, and performs other housekeeping.

Definition at line 2270 of file circuitlist.c.

◆ circuit_about_to_free_atexit()

static void circuit_about_to_free_atexit ( circuit_t circ)
static

Called immediately before freeing a marked circuit circ from circuit_free_all() while shutting down Tor; this is a safe-at-shutdown version of circuit_about_to_free(). It's important that it at least do circuitmux_detach_circuit() when appropriate.

Definition at line 2245 of file circuitlist.c.

Referenced by circuit_free_all().

◆ circuit_add_to_origin_circuit_list()

static void circuit_add_to_origin_circuit_list ( origin_circuit_t origin_circ)
static

Add origin_circ to the global list of origin circuits. Called when creating the circuit.

Definition at line 650 of file circuitlist.c.

◆ circuit_alloc_in_half_streams()

static size_t circuit_alloc_in_half_streams ( const circuit_t c)
static

Return the number of bytes allocated for c's half-open streams.

Definition at line 2436 of file circuitlist.c.

◆ circuit_any_opened_circuits()

int circuit_any_opened_circuits ( void  )

Return true if we have any opened general-purpose 3 hop origin circuits.

The result from this function is cached for use by circuit_any_opened_circuits_cached().

Definition at line 718 of file circuitlist.c.

Referenced by circuit_expire_building().

◆ circuit_any_opened_circuits_cached()

int circuit_any_opened_circuits_cached ( void  )

Return true if there were any opened circuits since the last call to circuit_any_opened_circuits(), or since circuit_expire_building() last ran (it runs roughly once per second).

Definition at line 755 of file circuitlist.c.

Referenced by circuit_build_times_handle_completed_hop().

◆ circuit_cache_opened_circuit_state()

void circuit_cache_opened_circuit_state ( int  circuits_are_opened)

Cache the "any circuits opened" state, as specified in param circuits_are_opened. This is a helper function to update the circuit opened status whenever we happen to look at the circuit list.

Definition at line 744 of file circuitlist.c.

Referenced by circuit_any_opened_circuits().

◆ circuit_can_be_cannibalized_for_v3_rp()

static int circuit_can_be_cannibalized_for_v3_rp ( const origin_circuit_t circ)
static

We might cannibalize this circuit: Return true if its last hop can be used as a v3 rendezvous point.

Definition at line 1799 of file circuitlist.c.

◆ circuit_clear_cpath()

void circuit_clear_cpath ( origin_circuit_t circ)

Deallocate the linked list circ->cpath, and remove the cpath from circ.

Definition at line 1278 of file circuitlist.c.

◆ circuit_clear_testing_cell_stats()

void circuit_clear_testing_cell_stats ( circuit_t circ)

Free all storage held in circ->testing_cell_stats

Definition at line 1113 of file circuitlist.c.

Referenced by circuit_free_().

◆ circuit_close_all_marked()

void circuit_close_all_marked ( void  )

Detach from the global circuit list, and deallocate, all circuits that have been marked for close.

Definition at line 662 of file circuitlist.c.

Referenced by postloop_cleanup_cb().

◆ circuit_count_pending_on_channel()

int circuit_count_pending_on_channel ( channel_t chan)

Return the number of circuits in state CHAN_WAIT, waiting for the given channel.

Definition at line 609 of file circuitlist.c.

◆ circuit_dump_by_conn()

void circuit_dump_by_conn ( connection_t conn,
int  severity 
)

Log, at severity severity, information about each circuit that is connected to conn.

Definition at line 1377 of file circuitlist.c.

◆ circuit_dump_conn_details()

static void circuit_dump_conn_details ( int  severity,
circuit_t circ,
int  conn_array_index,
const char *  type,
circid_t  this_circid,
circid_t  other_circid 
)
static

A helper function for circuit_dump_by_conn() below. Log a bunch of information about circuit circ.

Definition at line 1356 of file circuitlist.c.

Referenced by circuit_dump_by_conn().

◆ circuit_event_status()

int circuit_event_status ( origin_circuit_t circ,
circuit_status_event_t  tp,
int  reason_code 
)

Helper function to publish a message about events on an origin circuit

Publishes a message to subscribers of origin circuit events, and sends the control event.

Definition at line 499 of file circuitlist.c.

Referenced by circuit_about_to_free(), and circuit_build_times_mark_circ_as_measurement_only().

◆ circuit_find_circuits_to_upgrade_from_guard_wait()

smartlist_t* circuit_find_circuits_to_upgrade_from_guard_wait ( void  )

Check whether any of the origin circuits that are waiting to see if their guard is good enough to use can be upgraded to "ready". If so, return a new smartlist containing them. Otherwise return NULL.

Definition at line 1965 of file circuitlist.c.

Referenced by circuit_upgrade_circuits_from_guard_wait().

◆ circuit_find_to_cannibalize()

origin_circuit_t* circuit_find_to_cannibalize ( uint8_t  purpose_to_produce,
extend_info_t info,
int  flags 
)

Return a circuit that is open, is CIRCUIT_PURPOSE_C_GENERAL, has a timestamp_dirty value of 0, has flags matching the CIRCLAUNCH_* flags in flags, and if info is defined, does not already use info as any of its hops; or NULL if no circuit fits this description.

The purpose argument refers to the purpose of the circuit we want to create, not the purpose of the circuit we want to cannibalize.

If !CIRCLAUNCH_NEED_UPTIME, prefer returning non-uptime circuits.

To "cannibalize" a circuit means to extend it an extra hop, and use it for some other purpose than we had originally intended. We do this when we want to perform some low-bandwidth task at a specific relay, and we would like the circuit to complete as soon as possible. (If we were going to use a lot of bandwidth, we wouldn't want a circuit with an extra hop. If we didn't care about circuit completion latency, we would just build a new circuit.)

Definition at line 1855 of file circuitlist.c.

◆ circuit_free_()

STATIC void circuit_free_ ( circuit_t circ)

Deallocate space associated with circ.

Definition at line 1126 of file circuitlist.c.

◆ circuit_free_all()

void circuit_free_all ( void  )

Release all storage held by circuits.

Definition at line 1302 of file circuitlist.c.

◆ circuit_get_all_pending_on_channel()

void circuit_get_all_pending_on_channel ( smartlist_t out,
channel_t chan 
)

Append to out all circuits in state CHAN_WAIT waiting for the given connection.

Definition at line 578 of file circuitlist.c.

Referenced by circuit_count_pending_on_channel(), and entry_guard_chan_failed().

◆ circuit_get_by_circid_channel()

circuit_t* circuit_get_by_circid_channel ( circid_t  circ_id,
channel_t chan 
)

Return a circ such that:

  • circ->n_circ_id or circ->p_circ_id is equal to circ_id, and
  • circ is attached to chan, either as p_chan or n_chan.
  • circ is not marked for close. Return NULL if no such circuit exists.

Definition at line 1510 of file circuitlist.c.

Referenced by command_process_created_cell(), command_process_destroy_cell(), and command_process_relay_cell().

◆ circuit_get_by_circid_channel_even_if_marked()

circuit_t* circuit_get_by_circid_channel_even_if_marked ( circid_t  circ_id,
channel_t chan 
)

Return a circ such that:

  • circ->n_circ_id or circ->p_circ_id is equal to circ_id, and
  • circ is attached to chan, either as p_chan or n_chan. Return NULL if no such circuit exists.

Definition at line 1525 of file circuitlist.c.

Referenced by channel_note_destroy_not_pending(), channel_note_destroy_pending(), and circuitmux_set_policy().

◆ circuit_get_by_circid_channel_impl()

static circuit_t* circuit_get_by_circid_channel_impl ( circid_t  circ_id,
channel_t chan,
int *  found_entry_out 
)
inlinestatic

Return a circ such that:

  • circ->n_circ_id or circ->p_circ_id is equal to circ_id, and
  • circ is attached to chan, either as p_chan or n_chan. Return NULL if no such circuit exists.

If found_entry_out is provided, set it to true if we have a placeholder entry for circid/chan, and leave it unset otherwise.

Definition at line 1442 of file circuitlist.c.

Referenced by circuit_get_by_circid_channel(), circuit_get_by_circid_channel_even_if_marked(), and circuit_id_in_use_on_channel().

◆ circuit_get_by_edge_conn()

circuit_t* circuit_get_by_edge_conn ( edge_connection_t conn)

Return the circuit that a given edge connection is using.

Definition at line 1571 of file circuitlist.c.

Referenced by connection_exit_about_to_close().

◆ circuit_get_by_global_id()

origin_circuit_t* circuit_get_by_global_id ( uint32_t  id)

Return the circuit whose global ID is id, or NULL if no such circuit exists.

Definition at line 1418 of file circuitlist.c.

Referenced by get_circ().

◆ circuit_get_cpath_hop()

crypt_path_t* circuit_get_cpath_hop ( origin_circuit_t circ,
int  hopnum 
)

Return the hopnumth hop in circ->cpath, or NULL if there aren't that many hops in the list. hopnum starts at 1. Returns NULL if hopnum is 0 or negative.

Definition at line 2029 of file circuitlist.c.

Referenced by circpad_padding_is_from_expected_hop(), circpad_send_command_to_hop(), and circuit_get_nth_node().

◆ circuit_get_cpath_len()

int circuit_get_cpath_len ( origin_circuit_t circ)

Return the number of hops in circuit's path. If circ has no entries, or is NULL, returns 0.

Definition at line 1993 of file circuitlist.c.

Referenced by circpad_send_command_to_hop(), circuit_build_failed(), circuit_build_no_more_hops(), and onion_extend_cpath().

◆ circuit_get_cpath_opened_len()

int circuit_get_cpath_opened_len ( const origin_circuit_t circ)

Return the number of opened hops in circuit's path. If circ has no entries, or is NULL, returns 0.

Definition at line 2009 of file circuitlist.c.

Referenced by circuit_timeout_want_to_count_circ().

◆ circuit_get_global_list()

smartlist_t* circuit_get_global_list ( void  )

◆ circuit_get_global_origin_circuit_list()

smartlist_t* circuit_get_global_origin_circuit_list ( void  )

Return a pointer to the global list of origin circuits.

Definition at line 703 of file circuitlist.c.

Referenced by circuit_add_to_origin_circuit_list(), circuit_any_opened_circuits(), and circuit_expire_waiting_for_better_guard().

◆ circuit_get_next_by_purpose()

origin_circuit_t* circuit_get_next_by_purpose ( origin_circuit_t start,
uint8_t  purpose 
)

Return the first circuit originating here in global_circuitlist after start whose purpose is purpose. Return NULL if no circuit is found. If start is NULL, begin at the start of the list.

Definition at line 1769 of file circuitlist.c.

◆ circuit_get_next_intro_circ()

origin_circuit_t* circuit_get_next_intro_circ ( const origin_circuit_t start,
bool  want_client_circ 
)

Return the first introduction circuit originating from the global circuit list after start or at the start of the list if start is NULL. Return NULL if no circuit is found.

If want_client_circ is true, then we are looking for client-side introduction circuits: A client introduction point circuit has a purpose of either CIRCUIT_PURPOSE_C_INTRODUCING, CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT or CIRCUIT_PURPOSE_C_INTRODUCE_ACKED. This does not return a circuit marked for close, but it returns circuits regardless of their circuit state.

If want_client_circ is false, then we are looking for service-side introduction circuits: A service introduction point circuit has a purpose of either CIRCUIT_PURPOSE_S_ESTABLISH_INTRO or CIRCUIT_PURPOSE_S_INTRO. This does not return circuits marked for close, or in any state other than open.

Definition at line 1686 of file circuitlist.c.

Referenced by hs_client_close_intro_circuits_from_desc().

◆ circuit_get_next_service_rp_circ()

origin_circuit_t* circuit_get_next_service_rp_circ ( origin_circuit_t start)

Return the first service rendezvous circuit originating from the global circuit list after start or at the start of the list if start is NULL. Return NULL if no circuit is found.

A service rendezvous point circuit has a purpose of either CIRCUIT_PURPOSE_S_CONNECT_REND or CIRCUIT_PURPOSE_S_REND_JOINED. This does not return a circuit marked for close and its state must be open.

Definition at line 1738 of file circuitlist.c.

Referenced by close_service_rp_circuits().

◆ circuit_get_streams_max_data_age()

static uint32_t circuit_get_streams_max_data_age ( const edge_connection_t stream,
uint32_t  now 
)
static

Return the age in timestamp units of the oldest buffer chunk on any stream in the linked list stream, where age is taken in timestamp units before the timestamp now.

Definition at line 2501 of file circuitlist.c.

Referenced by circuit_max_queued_data_age().

◆ circuit_id_in_use_on_channel()

int circuit_id_in_use_on_channel ( circid_t  circ_id,
channel_t chan 
)

Return true iff the circuit ID circ_id is currently used by a circuit, marked or not, on chan, or if the circ ID is reserved until a queued destroy cell can be sent.

(Return 1 if the circuit is present, marked or not; Return 2 if the circuit ID is pending a destroy.)

Definition at line 1539 of file circuitlist.c.

◆ circuit_id_when_marked_unusable_on_channel()

time_t circuit_id_when_marked_unusable_on_channel ( circid_t  circ_id,
channel_t chan 
)

Helper for debugging 12184. Returns the time since which 'circ_id' has been marked unusable on 'chan'.

Definition at line 1552 of file circuitlist.c.

◆ circuit_initial_package_window()

int32_t circuit_initial_package_window ( void  )

Pick a reasonable package_window to start out for our circuits. Originally this was hard-coded at 1000, but now the consensus votes on the answer. See proposal 168.

Definition at line 975 of file circuitlist.c.

Referenced by init_circuit_base().

◆ circuit_mark_all_dirty_circs_as_unusable()

void circuit_mark_all_dirty_circs_as_unusable ( void  )

Go through the circuitlist; for each circuit that starts at us and is dirty, frob its timestamp_dirty so we won't use it for any new streams.

This is useful for letting the user change pseudonyms, so new streams will not be linkable to old streams.

Definition at line 2064 of file circuitlist.c.

Referenced by circuit_note_clock_jumped(), and directory_info_has_arrived().

◆ circuit_mark_all_unused_circs()

void circuit_mark_all_unused_circs ( void  )

Go through the circuitlist; mark-for-close each circuit that starts at us but has not yet been used.

Definition at line 2045 of file circuitlist.c.

Referenced by circuit_note_clock_jumped(), and directory_info_has_arrived().

◆ circuit_mark_for_close_()

void circuit_mark_for_close_ ( circuit_t circ,
int  reason,
int  line,
const char *  file 
)

Mark circ to be closed next time we call circuit_close_all_marked(). Do any cleanup needed:

  • If state is onionskin_pending, remove circ from the onion_pending list.
  • If circ isn't open yet: call circuit_build_failed() if we're the origin.
  • If purpose is C_INTRODUCE_ACK_WAIT, report the intro point failure we just had to the hidden service client module.
  • If purpose is C_INTRODUCING and reason isn't TIMEOUT, report to the hidden service client module that the intro point we just tried may be unreachable.
  • Send appropriate destroys and edge_destroys for conns and streams attached to circ.
  • If circ->rend_splice is set (we are the midpoint of a joined rendezvous stream), then mark the other circuit to close as well.

Definition at line 2155 of file circuitlist.c.

◆ circuit_max_queued_cell_age()

STATIC uint32_t circuit_max_queued_cell_age ( const circuit_t c,
uint32_t  now 
)

Return the age of the oldest cell queued on c, in timestamp units. Return 0 if there are no cells queued on c. Requires that now be the current coarse timestamp.

This function will return incorrect results if the oldest cell queued on the circuit is older than about 2**32 msec (about 49 days) old.

Definition at line 2457 of file circuitlist.c.

Referenced by circuit_max_queued_item_age().

◆ circuit_max_queued_data_age()

STATIC uint32_t circuit_max_queued_data_age ( const circuit_t c,
uint32_t  now 
)

Return the age in timestamp units of the oldest buffer chunk on any stream attached to the circuit c, where age is taken before the timestamp now.

Definition at line 2522 of file circuitlist.c.

Referenced by circuit_max_queued_item_age().

◆ circuit_max_queued_item_age()

STATIC uint32_t circuit_max_queued_item_age ( const circuit_t c,
uint32_t  now 
)

Return the age of the oldest cell or stream buffer chunk on the circuit c, where age is taken in timestamp units before the timestamp now

Definition at line 2537 of file circuitlist.c.

◆ circuit_purpose_to_controller_hs_state_string()

const char* circuit_purpose_to_controller_hs_state_string ( uint8_t  purpose)

Return a string specifying the state of the hidden-service circuit purpose purpose, or NULL if purpose is not a hidden-service-related circuit purpose.

Definition at line 843 of file circuitlist.c.

◆ circuit_purpose_to_controller_string()

const char* circuit_purpose_to_controller_string ( uint8_t  purpose)

Map a circuit purpose to a string suitable to be displayed to a controller.

Definition at line 782 of file circuitlist.c.

◆ circuit_purpose_to_string()

const char* circuit_purpose_to_string ( uint8_t  purpose)

Return a human-readable string for the circuit purpose purpose.

Definition at line 903 of file circuitlist.c.

Referenced by circuit_change_purpose().

◆ circuit_remove_from_origin_circuit_list()

static void circuit_remove_from_origin_circuit_list ( origin_circuit_t origin_circ)
static

Remove origin_circ from the global list of origin circuits. Called when we are freeing a circuit.

Definition at line 629 of file circuitlist.c.

Referenced by circuit_free_().

◆ circuit_set_n_circid_chan()

void circuit_set_n_circid_chan ( circuit_t circ,
circid_t  id,
channel_t chan 
)

Set the n_conn field of a circuit circ, along with the corresponding circuit ID, and add the circuit as appropriate to the (chan,id)->circuit map.

Definition at line 474 of file circuitlist.c.

Referenced by circuit_about_to_free_atexit().

◆ circuit_set_p_circid_chan()

void circuit_set_p_circid_chan ( or_circuit_t or_circ,
circid_t  id,
channel_t chan 
)

Set the p_conn field of a circuit circ, along with the corresponding circuit ID, and add the circuit as appropriate to the (chan,id)->circuit map.

Definition at line 451 of file circuitlist.c.

Referenced by circuit_about_to_free_atexit().

◆ circuit_set_state()

void circuit_set_state ( circuit_t circ,
uint8_t  state 
)

Change the state of circ to state, adding it to or removing it from lists as appropriate.

Definition at line 543 of file circuitlist.c.

Referenced by circuit_extend_to_new_exit(), and origin_circuit_init().

◆ circuit_state_publish()

static void circuit_state_publish ( const circuit_t circ)
static

Helper function to publish a state change message

circuit_set_state() calls this to notify subscribers about a change of the state of an origin circuit. circ must be an origin circuit.

Definition at line 523 of file circuitlist.c.

◆ circuit_state_to_string()

const char* circuit_state_to_string ( int  state)

Function to make circ->state human-readable

Definition at line 762 of file circuitlist.c.

◆ circuit_synchronize_written_or_bandwidth()

void circuit_synchronize_written_or_bandwidth ( const circuit_t c,
circuit_channel_direction_t  dir 
)

Report any queued cells on or_circuits as written in our bandwidth totals, for the specified channel direction.

When we close a circuit or clear its cell queues, we've read data and recorded those bytes in our read statistics, but we're not going to write it. This discrepancy can be used by an adversary to infer information from our public relay statistics and perform attacks such as guard discovery.

This function is in the critical path of circuit_mark_for_close(). It must be (and is) O(1)!

See https://bugs.torproject.org/tpo/core/tor/23512

Definition at line 2092 of file circuitlist.c.

◆ circuit_unlink_all_from_channel()

void circuit_unlink_all_from_channel ( channel_t chan,
int  reason 
)

For each circuit that has chan as n_chan or p_chan, unlink the circuit from the chan,circid map, and mark it for close if it hasn't been marked already.

Definition at line 1588 of file circuitlist.c.

◆ circuits_compare_by_oldest_queued_item_()

static int circuits_compare_by_oldest_queued_item_ ( const void **  a_,
const void **  b_ 
)
static

Helper to sort a list of circuit_t by age of oldest item, in descending order.

Definition at line 2550 of file circuitlist.c.

◆ circuits_handle_oom()

size_t circuits_handle_oom ( size_t  current_allocation)

We're out of memory for cells, having allocated current_allocation bytes' worth. Kill the 'worst' circuits until we're under FRACTION_OF_DATA_TO_RETAIN_ON_OOM of our maximum usage.

Return the number of bytes removed.

Definition at line 2593 of file circuitlist.c.

◆ conn_get_buffer_age()

static uint32_t conn_get_buffer_age ( const connection_t conn,
uint32_t  now_ts 
)
static

Return the age of the oldest buffer chunk on conn, where age is taken in timestamp units before the time now. If the connection has no data, treat it as having age zero.

Definition at line 2481 of file circuitlist.c.

Referenced by circuit_get_streams_max_data_age(), and conns_compare_by_buffer_age_().

◆ conns_compare_by_buffer_age_()

static int conns_compare_by_buffer_age_ ( const void **  a_,
const void **  b_ 
)
static

Helper to sort a list of circuit_t by age of oldest item, in descending order.

Definition at line 2570 of file circuitlist.c.

◆ get_circuit_purpose_needed_to_cannibalize()

static uint8_t get_circuit_purpose_needed_to_cannibalize ( uint8_t  purpose)
static

We are trying to create a circuit of purpose purpose and we are looking for cannibalizable circuits. Return the circuit purpose we would be willing to cannibalize.

Definition at line 1824 of file circuitlist.c.

Referenced by circuit_find_to_cannibalize().

◆ HT_HEAD()

static HT_HEAD ( HT_PROTOTYPE chan_circid_map,
HT_PROTOTYPE chan_circid_circuit_map_t 
)
static

Map from [chan,circid] to circuit.

Definition at line 216 of file circuitlist.c.

◆ init_circuit_base()

static void init_circuit_base ( circuit_t circ)
static

Initialize the common elements in a circuit_t, and add it to the global list.

Definition at line 989 of file circuitlist.c.

◆ marked_circuit_free_cells()

static void marked_circuit_free_cells ( circuit_t circ)
static

Given a marked circuit circ, aggressively free its cell queues to recover memory.

Definition at line 2358 of file circuitlist.c.

◆ marked_circuit_free_stream_bytes()

static size_t marked_circuit_free_stream_bytes ( circuit_t c)
static

Aggressively free buffer contents on all the buffers of all streams on circuit c. Return the number of bytes recovered.

Definition at line 2413 of file circuitlist.c.

◆ marked_circuit_streams_free_bytes()

static size_t marked_circuit_streams_free_bytes ( edge_connection_t stream)
static

Aggressively free buffer contents on all the buffers of all streams in the list starting at stream. Return the number of bytes recovered.

Definition at line 2397 of file circuitlist.c.

Referenced by marked_circuit_free_stream_bytes().

◆ n_cells_in_circ_queues()

STATIC size_t n_cells_in_circ_queues ( const circuit_t c)

Return the number of cells used by the circuit c's cell queues.

Definition at line 2424 of file circuitlist.c.

◆ or_circuit_new()

or_circuit_t* or_circuit_new ( circid_t  p_circ_id,
channel_t p_chan 
)

Allocate a new or_circuit_t, connected to p_chan as p_circ_id. If p_chan is NULL, the circuit is unattached.

Definition at line 1091 of file circuitlist.c.

◆ origin_circuit_new()

origin_circuit_t* origin_circuit_new ( void  )

Allocate space for a new circuit, initializing with p_circ_id and p_conn. Add it to the global circuit list.

Definition at line 1018 of file circuitlist.c.

Referenced by origin_circuit_init().

◆ TO_OR_CIRCUIT()

or_circuit_t* TO_OR_CIRCUIT ( circuit_t x)

◆ TO_ORIGIN_CIRCUIT()

origin_circuit_t* TO_ORIGIN_CIRCUIT ( circuit_t x)

Variable Documentation

◆ any_opened_circs_cached_val

int any_opened_circs_cached_val = 0
static

A cached value of the current state of the origin circuit list. Has the value 1 if we saw any opened circuits recently (since the last call to circuit_any_opened_circuits(), which gets called around once a second by circuit_expire_building). 0 otherwise.

Definition at line 146 of file circuitlist.c.

Referenced by circuit_any_opened_circuits_cached(), and circuit_cache_opened_circuit_state().

◆ circuits_pending_chans

smartlist_t* circuits_pending_chans = NULL
static

A list of all the circuits in CIRCUIT_STATE_CHAN_WAIT.

Definition at line 127 of file circuitlist.c.

Referenced by circuit_about_to_free(), and circuit_get_all_pending_on_channel().

◆ circuits_pending_close

smartlist_t* circuits_pending_close = NULL
static

A list of all the circuits that have been marked with circuit_mark_for_close and which are waiting for circuit_about_to_free.

Definition at line 135 of file circuitlist.c.

Referenced by circuit_close_all_marked().

◆ circuits_pending_other_guards

smartlist_t* circuits_pending_other_guards = NULL
static

List of all the (origin) circuits whose state is CIRCUIT_STATE_GUARD_WAIT.

Definition at line 131 of file circuitlist.c.

Referenced by circuit_about_to_free(), and circuit_find_circuits_to_upgrade_from_guard_wait().

◆ global_circuitlist

smartlist_t* global_circuitlist = NULL
static

A global list of all circuits at this hop.

Definition at line 120 of file circuitlist.c.

Referenced by circuit_get_global_list().

◆ global_origin_circuit_list

smartlist_t* global_origin_circuit_list = NULL
static

A global list of all origin circuits. Every element of this is also an element of global_circuitlist.

Definition at line 124 of file circuitlist.c.

Referenced by circuit_get_global_origin_circuit_list().