mirror of
https://github.com/jackjackbits/bitchat.git
synced 2026-01-10 13:08:13 -05:00
tor by default, small (#564)
* feat(tor): Tor-by-default scaffold and integration - Add TorManager with static/dlopen start, torrc generation, SOCKS probe - Add TorURLSession; route Nostr/Web fetches via SOCKS proxy - Add chat system messages for Tor status; show progress (macOS) and ready - Disable ControlPort bootstrap monitor on iOS; keep it on macOS - Make Tor waits non-blocking; avoid main-actor stalls on startup - Queue & flush Nostr subscriptions on relay connect; skip duplicates - Always rewrite torrc at launch to fix iOS container path mismatches - Link libz; add project wiring for tor-nolzma.xcframework - Minor fixes: SOCKS probe resumeOnce guard, entitlement for network.server (macOS) * iOS: deterministic Tor recovery + 100% gating; BLE-first; session rebuild - Restart/wake Tor on foreground via ControlPort (ACTIVE/SHUTDOWN), avoid restarts during bootstrap; add NWPathMonitor to trigger checks - Use NWConnection control polling for GETINFO; remove blocking CFStream readers to avoid QoS inversions; compute readiness from SOCKS + 100% - Rebuild TorURLSession on resume; reset Nostr connections to rebind - Gate all internet after full bootstrap; keep BLE mesh startup fast - Fix Swift 6 capture issues; hop UI updates to @MainActor - Remove Tor progress spam; persist initial "starting tor..." system message * UI: show Tor system messages only in geohash channels (not mesh) - Gate "starting tor..." and readiness/timeout messages to geohash view - Add helper addGeohashOnlySystemMessage() to avoid posting to mesh timeline - Persist system messages in geohash backing store via addPublicSystemMessage() * Relays: treat repeated -1011 handshake failures as permanent; skip reconnects - Classify NSURLErrorBadServerResponse as permanent and stop retrying - Filter permanently-failed relays from subscribe/connect attempts - Avoid reconnect scheduling for permanently failed relays * Embed Tor via tor_api; deterministic restart + Nostr gating; add Tor notifications - Run Tor via tor_api in a dedicated thread with OwningControllerFD - Cleanly stop Tor on background; restart on .active (single instance) - Avoid fallback to tor_main/dlopen; add is-running check to prevent duplicates - Fix argv lifetime in C glue to avoid strcmp crash on start - Gate Nostr connect/subscribe/send until Tor is fully ready - Rebuild URLSession + reset relays after Tor readiness (scene-based) - Remove TorDidBecomeReady double-reset and appDidBecomeActive resubscribe - Add TorWillRestart/TorDidBecomeReady notifications and chat system messages - Debounce path-change restarts; ACTIVE poke first; coalesce subs; cancel stale reconnect timers - Project: add CTorHost.c and TorNotifications.swift to targets; fix libz.tbd path * Defer Nostr setup logs until Tor is ready; fix subscribe coalescing and reconnect generation - Move "Connecting to Nostr relays" log after awaitReady() - Log "Queuing subscription" when Tor not ready; only coalesce when handler exists - Clear coalescer on unsubscribe - Cancel stale reconnect timers using connectionGeneration - Remove app-level TorDidBecomeReady reset to avoid duplicate reconnects - Debounce path-change restarts * Gate Nostr init/subscription logs until Tor is ready - ChatViewModel: await Tor readiness before initializing Nostr and logging - Only log GeoDM subscription when Tor is ready to avoid early noise * Make Nostr connect single-sourced; defer DM subscription until connected - Remove duplicate connect call from ChatViewModel; let scene-based flow connect - Setup DM subscription once on first connection via sink - Reduce early subscription send/cancel noise after Tor restarts * On launch, queue Nostr subscriptions without initiating connects; let centralized connect handle it - In subscribe(), if no connections exist, just list relays and queue subs - Avoids early send/cancel churn before connect() runs post-Tor-ready * Always queue subscriptions and flush on connection; avoid immediate sends - Prevents early send/cancel churn at launch and during reconnects - If relays are already connected, flush immediately; otherwise pending until connected * UI: scope Tor restart messages to geohash channels; skip initial foreground restart on cold launch to avoid confusing system message in #mesh * geo: disable background sampling + notifications\n- Gate sampling to foreground only (beginGeohashSampling, watchers)\n- Suppress geohash activity notifications unless app is active\n- Stop sampling explicitly on background scene phase * Update BitchatApp.swift Co-authored-by: asmo <asmogo@protonmail.com> * Update BitchatApp.swift Co-authored-by: asmo <asmogo@protonmail.com> * Update BitchatApp.swift Co-authored-by: asmo <asmogo@protonmail.com> * Update bitchat/BitchatApp.swift Co-authored-by: asmo <asmogo@protonmail.com> * Update bitchat/BitchatApp.swift Co-authored-by: asmo <asmogo@protonmail.com> * fix(iOS App): resolve merge artifacts in scenePhase handler\n- Remove duplicate didEnterBackground state\n- Fix switch/if braces and logic for foreground restart gating --------- Co-authored-by: jack <jackjackbits@users.noreply.github.com> Co-authored-by: asmo <asmogo@protonmail.com>
This commit is contained in:
12
Frameworks/README.md
Normal file
12
Frameworks/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
Place Tor.xcframework here
|
||||
|
||||
Instructions
|
||||
- Obtain a prebuilt Tor Apple xcframework (iCepa/Onion Browser lineage) or build your own minimal client-only Tor.
|
||||
- Rename it (if needed) to `Tor.xcframework` and drop it in this `Frameworks/` directory.
|
||||
- Regenerate the Xcode project if you use XcodeGen (`project.yml` already references `Frameworks/Tor.xcframework`).
|
||||
- Build the app; `TorManager` will automatically bootstrap Tor and route all networking through it.
|
||||
|
||||
Notes
|
||||
- For iOS, the framework will be embedded and code-signed automatically.
|
||||
- For macOS, it will be linked and embedded as well (you may prefer a system tor for smaller bundles).
|
||||
|
||||
41
Frameworks/tor-nolzma.xcframework/Info.plist
Normal file
41
Frameworks/tor-nolzma.xcframework/Info.plist
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AvailableLibraries</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>BinaryPath</key>
|
||||
<string>tor-nolzma.framework/tor-nolzma</string>
|
||||
<key>LibraryIdentifier</key>
|
||||
<string>ios-arm64</string>
|
||||
<key>LibraryPath</key>
|
||||
<string>tor-nolzma.framework</string>
|
||||
<key>SupportedArchitectures</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>SupportedPlatform</key>
|
||||
<string>ios</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>BinaryPath</key>
|
||||
<string>tor-nolzma.framework/tor-nolzma</string>
|
||||
<key>LibraryIdentifier</key>
|
||||
<string>macos-arm64</string>
|
||||
<key>LibraryPath</key>
|
||||
<string>tor-nolzma.framework</string>
|
||||
<key>SupportedArchitectures</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>SupportedPlatform</key>
|
||||
<string>macos</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XFWK</string>
|
||||
<key>XCFrameworkFormatVersion</key>
|
||||
<string>1.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,324 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file config.h
|
||||
* \brief Header file for config.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONFIG_H
|
||||
#define TOR_CONFIG_H
|
||||
|
||||
#include "app/config/or_options_st.h"
|
||||
#include "lib/testsupport/testsupport.h"
|
||||
#include "app/config/quiet_level.h"
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(DARWIN)
|
||||
#define KERNEL_MAY_SUPPORT_IPFW
|
||||
#endif
|
||||
|
||||
/** Lowest allowable value for HeartbeatPeriod; if this is too low, we might
|
||||
* expose more information than we're comfortable with. */
|
||||
#define MIN_HEARTBEAT_PERIOD (30*60)
|
||||
|
||||
/** Maximum default value for MaxMemInQueues, in bytes. */
|
||||
#if SIZEOF_VOID_P >= 8
|
||||
#define MAX_DEFAULT_MEMORY_QUEUE_SIZE (UINT64_C(8) << 30)
|
||||
#else
|
||||
#define MAX_DEFAULT_MEMORY_QUEUE_SIZE (UINT64_C(2) << 30)
|
||||
#endif
|
||||
|
||||
MOCK_DECL(const or_options_t *, get_options, (void));
|
||||
MOCK_DECL(or_options_t *, get_options_mutable, (void));
|
||||
int set_options(or_options_t *new_val, char **msg);
|
||||
void config_free_all(void);
|
||||
const char *safe_str_client(const char *address);
|
||||
const char *safe_str(const char *address);
|
||||
const char *escaped_safe_str_client(const char *address);
|
||||
const char *escaped_safe_str(const char *address);
|
||||
void init_protocol_warning_severity_level(void);
|
||||
int get_protocol_warning_severity_level(void);
|
||||
|
||||
#define LOG_PROTOCOL_WARN (get_protocol_warning_severity_level())
|
||||
|
||||
/** Pattern for backing up configuration files */
|
||||
#define CONFIG_BACKUP_PATTERN "%s.orig.1"
|
||||
|
||||
/** An error from options_trial_assign() or options_init_from_string(). */
|
||||
typedef enum setopt_err_t {
|
||||
SETOPT_OK = 0,
|
||||
SETOPT_ERR_MISC = -1,
|
||||
SETOPT_ERR_PARSE = -2,
|
||||
SETOPT_ERR_TRANSITION = -3,
|
||||
SETOPT_ERR_SETTING = -4,
|
||||
} setopt_err_t;
|
||||
setopt_err_t options_trial_assign(struct config_line_t *list, unsigned flags,
|
||||
char **msg);
|
||||
|
||||
void options_init(or_options_t *options);
|
||||
|
||||
#define OPTIONS_DUMP_MINIMAL 1
|
||||
#define OPTIONS_DUMP_ALL 2
|
||||
char *options_dump(const or_options_t *options, int how_to_dump);
|
||||
int options_init_from_torrc(int argc, char **argv);
|
||||
setopt_err_t options_init_from_string(const char *cf_defaults, const char *cf,
|
||||
int command, const char *command_arg, char **msg);
|
||||
int option_is_recognized(const char *key);
|
||||
const char *option_get_canonical_name(const char *key);
|
||||
struct config_line_t *option_get_assignment(const or_options_t *options,
|
||||
const char *key);
|
||||
int options_save_current(void);
|
||||
const char *get_torrc_fname(int defaults_fname);
|
||||
typedef enum {
|
||||
DIRROOT_DATADIR,
|
||||
DIRROOT_CACHEDIR,
|
||||
DIRROOT_KEYDIR
|
||||
} directory_root_t;
|
||||
|
||||
MOCK_DECL(char *,
|
||||
options_get_dir_fname2_suffix,
|
||||
(const or_options_t *options,
|
||||
directory_root_t roottype,
|
||||
const char *sub1, const char *sub2,
|
||||
const char *suffix));
|
||||
|
||||
/* These macros wrap options_get_dir_fname2_suffix to provide a more
|
||||
* convenient API for finding filenames that Tor uses inside its storage
|
||||
* They are named according to a pattern:
|
||||
* (options_)?get_(cache|key|data)dir_fname(2)?(_suffix)?
|
||||
*
|
||||
* Macros that begin with options_ take an options argument; the others
|
||||
* work with respect to the global options.
|
||||
*
|
||||
* Each macro works relative to the data directory, the key directory,
|
||||
* or the cache directory, as determined by which one is mentioned.
|
||||
*
|
||||
* Macro variants with "2" in their name take two path components; others
|
||||
* take one.
|
||||
*
|
||||
* Macro variants with "_suffix" at the end take an additional suffix
|
||||
* that gets appended to the end of the file
|
||||
*/
|
||||
#define options_get_datadir_fname2_suffix(options, sub1, sub2, suffix) \
|
||||
options_get_dir_fname2_suffix((options), DIRROOT_DATADIR, \
|
||||
(sub1), (sub2), (suffix))
|
||||
#define options_get_cachedir_fname2_suffix(options, sub1, sub2, suffix) \
|
||||
options_get_dir_fname2_suffix((options), DIRROOT_CACHEDIR, \
|
||||
(sub1), (sub2), (suffix))
|
||||
#define options_get_keydir_fname2_suffix(options, sub1, sub2, suffix) \
|
||||
options_get_dir_fname2_suffix((options), DIRROOT_KEYDIR, \
|
||||
(sub1), (sub2), (suffix))
|
||||
|
||||
#define options_get_datadir_fname(opts,sub1) \
|
||||
options_get_datadir_fname2_suffix((opts),(sub1), NULL, NULL)
|
||||
#define options_get_datadir_fname2(opts,sub1,sub2) \
|
||||
options_get_datadir_fname2_suffix((opts),(sub1), (sub2), NULL)
|
||||
|
||||
#define get_datadir_fname2_suffix(sub1, sub2, suffix) \
|
||||
options_get_datadir_fname2_suffix(get_options(), (sub1), (sub2), (suffix))
|
||||
#define get_datadir_fname(sub1) \
|
||||
get_datadir_fname2_suffix((sub1), NULL, NULL)
|
||||
#define get_datadir_fname2(sub1,sub2) \
|
||||
get_datadir_fname2_suffix((sub1), (sub2), NULL)
|
||||
#define get_datadir_fname_suffix(sub1, suffix) \
|
||||
get_datadir_fname2_suffix((sub1), NULL, (suffix))
|
||||
|
||||
/** DOCDOC */
|
||||
#define options_get_keydir_fname(options, sub1) \
|
||||
options_get_keydir_fname2_suffix((options), (sub1), NULL, NULL)
|
||||
#define get_keydir_fname_suffix(sub1, suffix) \
|
||||
options_get_keydir_fname2_suffix(get_options(), (sub1), NULL, suffix)
|
||||
#define get_keydir_fname(sub1) \
|
||||
options_get_keydir_fname2_suffix(get_options(), (sub1), NULL, NULL)
|
||||
|
||||
#define get_cachedir_fname(sub1) \
|
||||
options_get_cachedir_fname2_suffix(get_options(), (sub1), NULL, NULL)
|
||||
#define get_cachedir_fname_suffix(sub1, suffix) \
|
||||
options_get_cachedir_fname2_suffix(get_options(), (sub1), NULL, (suffix))
|
||||
|
||||
#define safe_str_client(address) \
|
||||
safe_str_client_opts(NULL, address)
|
||||
#define safe_str(address) \
|
||||
safe_str_opts(NULL, address)
|
||||
|
||||
const char * safe_str_client_opts(const or_options_t *options,
|
||||
const char *address);
|
||||
const char * safe_str_opts(const or_options_t *options,
|
||||
const char *address);
|
||||
|
||||
int using_default_dir_authorities(const or_options_t *options);
|
||||
|
||||
int create_keys_directory(const or_options_t *options);
|
||||
|
||||
int check_or_create_data_subdir(const char *subdir);
|
||||
int write_to_data_subdir(const char* subdir, const char* fname,
|
||||
const char* str, const char* descr);
|
||||
|
||||
int get_num_cpus(const or_options_t *options);
|
||||
|
||||
MOCK_DECL(const smartlist_t *,get_configured_ports,(void));
|
||||
int port_binds_ipv4(const port_cfg_t *port);
|
||||
int port_binds_ipv6(const port_cfg_t *port);
|
||||
int portconf_get_first_advertised_port(int listener_type,
|
||||
int address_family);
|
||||
#define portconf_get_primary_dir_port() \
|
||||
(portconf_get_first_advertised_port(CONN_TYPE_DIR_LISTENER, AF_INET))
|
||||
const tor_addr_t *portconf_get_first_advertised_addr(int listener_type,
|
||||
int address_family);
|
||||
int port_exists_by_type_addr_port(int listener_type, const tor_addr_t *addr,
|
||||
int port, int check_wildcard);
|
||||
int port_exists_by_type_addr32h_port(int listener_type, uint32_t addr_ipv4h,
|
||||
int port, int check_wildcard);
|
||||
|
||||
char *get_first_listener_addrport_string(int listener_type);
|
||||
|
||||
int options_need_geoip_info(const or_options_t *options,
|
||||
const char **reason_out);
|
||||
|
||||
int getinfo_helper_config(control_connection_t *conn,
|
||||
const char *question, char **answer,
|
||||
const char **errmsg);
|
||||
|
||||
int init_cookie_authentication(const char *fname, const char *header,
|
||||
int cookie_len, int group_readable,
|
||||
uint8_t **cookie_out, int *cookie_is_set_out);
|
||||
|
||||
or_options_t *options_new(void);
|
||||
|
||||
/** Options settings parsed from the command-line. */
|
||||
typedef struct {
|
||||
/** List of options that can only be set from the command-line */
|
||||
struct config_line_t *cmdline_opts;
|
||||
/** List of other options, to be handled by the general Tor configuration
|
||||
system. */
|
||||
struct config_line_t *other_opts;
|
||||
/** Subcommand that Tor has been told to run */
|
||||
tor_cmdline_mode_t command;
|
||||
/** Argument for the command mode, if any. */
|
||||
const char *command_arg;
|
||||
/** How quiet have we been told to be? */
|
||||
quiet_level_t quiet_level;
|
||||
} parsed_cmdline_t;
|
||||
|
||||
parsed_cmdline_t *config_parse_commandline(int argc, char **argv,
|
||||
int ignore_errors);
|
||||
void parsed_cmdline_free_(parsed_cmdline_t *cmdline);
|
||||
#define parsed_cmdline_free(c) \
|
||||
FREE_AND_NULL(parsed_cmdline_t, parsed_cmdline_free_, (c))
|
||||
|
||||
void config_register_addressmaps(const or_options_t *options);
|
||||
/* XXXX move to connection_edge.h */
|
||||
int addressmap_register_auto(const char *from, const char *to,
|
||||
time_t expires,
|
||||
addressmap_entry_source_t addrmap_source,
|
||||
const char **msg);
|
||||
|
||||
int port_cfg_line_extract_addrport(const char *line,
|
||||
char **addrport_out,
|
||||
int *is_unix_out,
|
||||
const char **rest_out);
|
||||
|
||||
/** Represents the information stored in a torrc Bridge line. */
|
||||
typedef struct bridge_line_t {
|
||||
tor_addr_t addr; /* The IP address of the bridge. */
|
||||
uint16_t port; /* The TCP port of the bridge. */
|
||||
char *transport_name; /* The name of the pluggable transport that
|
||||
should be used to connect to the bridge. */
|
||||
char digest[DIGEST_LEN]; /* The bridge's identity key digest. */
|
||||
smartlist_t *socks_args; /* SOCKS arguments for the pluggable
|
||||
transport proxy. */
|
||||
} bridge_line_t;
|
||||
|
||||
void bridge_line_free_(bridge_line_t *bridge_line);
|
||||
#define bridge_line_free(line) \
|
||||
FREE_AND_NULL(bridge_line_t, bridge_line_free_, (line))
|
||||
bridge_line_t *parse_bridge_line(const char *line);
|
||||
|
||||
/* Port helper functions. */
|
||||
int options_any_client_port_set(const or_options_t *options);
|
||||
int port_parse_config(smartlist_t *out,
|
||||
const struct config_line_t *ports,
|
||||
const char *portname,
|
||||
int listener_type,
|
||||
const char *defaultaddr,
|
||||
int defaultport,
|
||||
const unsigned flags);
|
||||
|
||||
#define CL_PORT_NO_STREAM_OPTIONS (1u<<0)
|
||||
#define CL_PORT_WARN_NONLOCAL (1u<<1)
|
||||
/* Was CL_PORT_ALLOW_EXTRA_LISTENADDR (1u<<2) */
|
||||
#define CL_PORT_SERVER_OPTIONS (1u<<3)
|
||||
#define CL_PORT_FORBID_NONLOCAL (1u<<4)
|
||||
#define CL_PORT_TAKES_HOSTNAMES (1u<<5)
|
||||
#define CL_PORT_IS_UNIXSOCKET (1u<<6)
|
||||
#define CL_PORT_DFLT_GROUP_WRITABLE (1u<<7)
|
||||
|
||||
port_cfg_t *port_cfg_new(size_t namelen);
|
||||
#define port_cfg_free(port) \
|
||||
FREE_AND_NULL(port_cfg_t, port_cfg_free_, (port))
|
||||
void port_cfg_free_(port_cfg_t *port);
|
||||
|
||||
int port_count_real_listeners(const smartlist_t *ports,
|
||||
int listenertype,
|
||||
int count_sockets);
|
||||
int pt_parse_transport_line(const or_options_t *options,
|
||||
const char *line, int validate_only,
|
||||
int server);
|
||||
int config_ensure_bandwidth_cap(uint64_t *value, const char *desc, char **msg);
|
||||
|
||||
#ifdef CONFIG_PRIVATE
|
||||
|
||||
MOCK_DECL(STATIC int, options_act,(const or_options_t *old_options));
|
||||
MOCK_DECL(STATIC int, options_act_reversible,(const or_options_t *old_options,
|
||||
char **msg));
|
||||
struct config_mgr_t;
|
||||
STATIC const struct config_mgr_t *get_options_mgr(void);
|
||||
|
||||
#define or_options_free(opt) \
|
||||
FREE_AND_NULL(or_options_t, or_options_free_, (opt))
|
||||
STATIC void or_options_free_(or_options_t *options);
|
||||
STATIC int options_validate_single_onion(or_options_t *options,
|
||||
char **msg);
|
||||
STATIC int parse_tcp_proxy_line(const char *line, or_options_t *options,
|
||||
char **msg);
|
||||
STATIC int consider_adding_dir_servers(const or_options_t *options,
|
||||
const or_options_t *old_options);
|
||||
STATIC void add_default_trusted_dir_authorities(dirinfo_type_t type);
|
||||
MOCK_DECL(STATIC void, add_default_fallback_dir_servers, (void));
|
||||
STATIC int parse_dir_authority_line(const char *line,
|
||||
dirinfo_type_t required_type,
|
||||
int validate_only);
|
||||
STATIC int parse_dir_fallback_line(const char *line, int validate_only);
|
||||
|
||||
STATIC uint64_t compute_real_max_mem_in_queues(const uint64_t val,
|
||||
bool is_server);
|
||||
STATIC int open_and_add_file_log(const log_severity_list_t *severity,
|
||||
const char *fname,
|
||||
int truncate_log);
|
||||
STATIC int options_init_logs(const or_options_t *old_options,
|
||||
const or_options_t *options, int validate_only);
|
||||
|
||||
STATIC int options_create_directories(char **msg_out);
|
||||
struct log_transaction_t;
|
||||
STATIC struct log_transaction_t *options_start_log_transaction(
|
||||
const or_options_t *old_options,
|
||||
char **msg_out);
|
||||
STATIC void options_commit_log_transaction(struct log_transaction_t *xn);
|
||||
STATIC void options_rollback_log_transaction(struct log_transaction_t *xn);
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
int options_validate(const or_options_t *old_options,
|
||||
or_options_t *options,
|
||||
char **msg);
|
||||
#endif
|
||||
|
||||
STATIC int parse_ports(or_options_t *options, int validate_only,
|
||||
char **msg, int *n_ports_out,
|
||||
int *world_writable_control_socket);
|
||||
|
||||
#endif /* defined(CONFIG_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CONFIG_H) */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,103 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file or_state_st.h
|
||||
*
|
||||
* \brief The or_state_t structure, which represents Tor's state file.
|
||||
*/
|
||||
|
||||
#ifndef TOR_OR_STATE_ST_H
|
||||
#define TOR_OR_STATE_ST_H
|
||||
|
||||
#include "lib/cc/torint.h"
|
||||
struct smartlist_t;
|
||||
struct config_suite_t;
|
||||
|
||||
/** Persistent state for an onion router, as saved to disk. */
|
||||
struct or_state_t {
|
||||
uint32_t magic_;
|
||||
/** The time at which we next plan to write the state to the disk. Equal to
|
||||
* TIME_MAX if there are no saveable changes, 0 if there are changes that
|
||||
* should be saved right away. */
|
||||
time_t next_write;
|
||||
|
||||
/** When was the state last written to disk? */
|
||||
time_t LastWritten;
|
||||
|
||||
/** Fields for accounting bandwidth use. */
|
||||
time_t AccountingIntervalStart;
|
||||
uint64_t AccountingBytesReadInInterval;
|
||||
uint64_t AccountingBytesWrittenInInterval;
|
||||
int AccountingSecondsActive;
|
||||
int AccountingSecondsToReachSoftLimit;
|
||||
time_t AccountingSoftLimitHitAt;
|
||||
uint64_t AccountingBytesAtSoftLimit;
|
||||
uint64_t AccountingExpectedUsage;
|
||||
|
||||
/** A list of guard-related configuration lines. */
|
||||
struct config_line_t *Guard;
|
||||
|
||||
struct config_line_t *TransportProxies;
|
||||
|
||||
/** These fields hold information on the history of bandwidth usage for
|
||||
* servers. The "Ends" fields hold the time when we last updated the
|
||||
* bandwidth usage. The "Interval" fields hold the granularity, in seconds,
|
||||
* of the entries of Values. The "Values" lists hold decimal string
|
||||
* representations of the number of bytes read or written in each
|
||||
* interval. The "Maxima" list holds decimal strings describing the highest
|
||||
* rate achieved during the interval.
|
||||
*/
|
||||
time_t BWHistoryReadEnds;
|
||||
int BWHistoryReadInterval;
|
||||
struct smartlist_t *BWHistoryReadValues;
|
||||
struct smartlist_t *BWHistoryReadMaxima;
|
||||
time_t BWHistoryWriteEnds;
|
||||
int BWHistoryWriteInterval;
|
||||
struct smartlist_t *BWHistoryWriteValues;
|
||||
struct smartlist_t *BWHistoryWriteMaxima;
|
||||
time_t BWHistoryIPv6ReadEnds;
|
||||
int BWHistoryIPv6ReadInterval;
|
||||
struct smartlist_t *BWHistoryIPv6ReadValues;
|
||||
struct smartlist_t *BWHistoryIPv6ReadMaxima;
|
||||
time_t BWHistoryIPv6WriteEnds;
|
||||
int BWHistoryIPv6WriteInterval;
|
||||
struct smartlist_t *BWHistoryIPv6WriteValues;
|
||||
struct smartlist_t *BWHistoryIPv6WriteMaxima;
|
||||
time_t BWHistoryDirReadEnds;
|
||||
int BWHistoryDirReadInterval;
|
||||
struct smartlist_t *BWHistoryDirReadValues;
|
||||
struct smartlist_t *BWHistoryDirReadMaxima;
|
||||
time_t BWHistoryDirWriteEnds;
|
||||
int BWHistoryDirWriteInterval;
|
||||
struct smartlist_t *BWHistoryDirWriteValues;
|
||||
struct smartlist_t *BWHistoryDirWriteMaxima;
|
||||
|
||||
/** Build time histogram */
|
||||
struct config_line_t * BuildtimeHistogram;
|
||||
int TotalBuildTimes;
|
||||
int CircuitBuildAbandonedCount;
|
||||
|
||||
/** What version of Tor wrote this state file? */
|
||||
char *TorVersion;
|
||||
|
||||
/** Holds any unrecognized values we found in the state file, in the order
|
||||
* in which we found them. */
|
||||
struct config_line_t *ExtraLines;
|
||||
|
||||
/** When did we last rotate our onion key? "0" for 'no idea'. */
|
||||
time_t LastRotatedOnionKey;
|
||||
|
||||
/**
|
||||
* State objects for individual modules.
|
||||
*
|
||||
* Never access this field or its members directly: instead, use the module
|
||||
* in question to get its relevant state object if you must.
|
||||
*/
|
||||
struct config_suite_t *substates_;
|
||||
};
|
||||
|
||||
#endif /* !defined(TOR_OR_STATE_ST_H) */
|
||||
@@ -0,0 +1,30 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file quiet_level.h
|
||||
* \brief Declare the quiet_level enumeration and global.
|
||||
**/
|
||||
|
||||
#ifndef QUIET_LEVEL_H
|
||||
#define QUIET_LEVEL_H
|
||||
|
||||
/** Enumeration to define how quietly Tor should log at startup. */
|
||||
typedef enum {
|
||||
/** Default quiet level: we log everything of level NOTICE or higher. */
|
||||
QUIET_NONE = 0,
|
||||
/** "--hush" quiet level: we log everything of level WARNING or higher. */
|
||||
QUIET_HUSH = 1 ,
|
||||
/** "--quiet" quiet level: we log nothing at all. */
|
||||
QUIET_SILENT = 2
|
||||
} quiet_level_t;
|
||||
|
||||
/** How quietly should Tor log at startup? */
|
||||
extern quiet_level_t quiet_level;
|
||||
|
||||
void add_default_log_for_quiet_level(quiet_level_t quiet);
|
||||
|
||||
#endif /* !defined(QUIET_LEVEL_H) */
|
||||
@@ -0,0 +1,67 @@
|
||||
/* Copyright (c) 2020-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file resolve_addr.h
|
||||
* \brief Header file for resolve_addr.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONFIG_RESOLVE_ADDR_H
|
||||
#define TOR_CONFIG_RESOLVE_ADDR_H
|
||||
|
||||
#include "app/config/config.h"
|
||||
#include "core/mainloop/connection.h"
|
||||
|
||||
#include "app/config/or_options_st.h"
|
||||
|
||||
/** Method used to resolved an address. In other words, how was the address
|
||||
* discovered by tor. */
|
||||
typedef enum {
|
||||
/* Default value. Indicate that no method found the address. */
|
||||
RESOLVED_ADDR_NONE = 0,
|
||||
/* Found from the "Address" configuration option. */
|
||||
RESOLVED_ADDR_CONFIGURED = 1,
|
||||
/* Found from the "ORPort" configuration option. */
|
||||
RESOLVED_ADDR_CONFIGURED_ORPORT = 2,
|
||||
/* Found by resolving the local hostname. */
|
||||
RESOLVED_ADDR_GETHOSTNAME = 3,
|
||||
/* Found by querying the local interface(s). */
|
||||
RESOLVED_ADDR_INTERFACE = 4,
|
||||
/* Found by resolving the hostname from the Address configuration option. */
|
||||
RESOLVED_ADDR_RESOLVED = 5,
|
||||
} resolved_addr_method_t;
|
||||
|
||||
const char *resolved_addr_method_to_str(const resolved_addr_method_t method);
|
||||
|
||||
#define get_orport_addr(family) \
|
||||
(portconf_get_first_advertised_addr(CONN_TYPE_OR_LISTENER, family))
|
||||
|
||||
bool find_my_address(const or_options_t *options, int family,
|
||||
int warn_severity, tor_addr_t *addr_out,
|
||||
resolved_addr_method_t *method_out, char **hostname_out);
|
||||
|
||||
void resolved_addr_get_last(int family, tor_addr_t *addr_out);
|
||||
void resolved_addr_reset_last(int family);
|
||||
void resolved_addr_set_last(const tor_addr_t *addr,
|
||||
const resolved_addr_method_t method_used,
|
||||
const char *hostname_used);
|
||||
|
||||
void resolved_addr_get_suggested(int family, tor_addr_t *addr_out);
|
||||
void resolved_addr_set_suggested(const tor_addr_t *addr);
|
||||
|
||||
bool resolved_addr_is_configured(int family);
|
||||
|
||||
MOCK_DECL(bool, is_local_to_resolve_addr, (const tor_addr_t *addr));
|
||||
|
||||
#ifdef RESOLVE_ADDR_PRIVATE
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
|
||||
void resolve_addr_reset_suggested(int family);
|
||||
|
||||
#endif /* TOR_UNIT_TESTS */
|
||||
|
||||
#endif /* defined(RESOLVE_ADDR_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CONFIG_RESOLVE_ADDR_H) */
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file statefile.h
|
||||
*
|
||||
* \brief Header for statefile.c
|
||||
*/
|
||||
|
||||
#ifndef TOR_STATEFILE_H
|
||||
#define TOR_STATEFILE_H
|
||||
|
||||
MOCK_DECL(or_state_t *,get_or_state,(void));
|
||||
int did_last_state_file_write_fail(void);
|
||||
int or_state_save(time_t now);
|
||||
|
||||
void save_transport_to_state(const char *transport_name,
|
||||
const tor_addr_t *addr, uint16_t port);
|
||||
char *get_stored_bindaddr_for_server_transport(const char *transport);
|
||||
int or_state_load(void);
|
||||
int or_state_loaded(void);
|
||||
void or_state_free_all(void);
|
||||
void or_state_mark_dirty(or_state_t *state, time_t when);
|
||||
|
||||
#ifdef STATEFILE_PRIVATE
|
||||
STATIC struct config_line_t *get_transport_in_state_by_name(
|
||||
const char *transport);
|
||||
STATIC void or_state_free_(or_state_t *state);
|
||||
#define or_state_free(st) FREE_AND_NULL(or_state_t, or_state_free_, (st))
|
||||
STATIC or_state_t *or_state_new(void);
|
||||
struct config_mgr_t;
|
||||
STATIC const struct config_mgr_t *get_state_mgr(void);
|
||||
STATIC void or_state_remove_obsolete_lines(struct config_line_t **extra_lines);
|
||||
#endif /* defined(STATEFILE_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_STATEFILE_H) */
|
||||
@@ -0,0 +1,34 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file tor_cmdline_mode.h
|
||||
* \brief Declare the tor_cmdline_mode_t enumeration
|
||||
**/
|
||||
|
||||
#ifndef TOR_CMDLINE_MODE_H
|
||||
#define TOR_CMDLINE_MODE_H
|
||||
|
||||
/**
|
||||
* Enumeration to describe which command Tor is running. These commands
|
||||
* are controlled by command-line options.
|
||||
**/
|
||||
typedef enum {
|
||||
CMD_RUN_TOR=0, /**< The default: run Tor as a daemon. */
|
||||
CMD_LIST_FINGERPRINT, /**< Running --list-fingerprint. */
|
||||
CMD_HASH_PASSWORD, /**< Running --hash-password. */
|
||||
CMD_VERIFY_CONFIG, /**< Running --verify-config. */
|
||||
CMD_DUMP_CONFIG, /**< Running --dump-config. */
|
||||
CMD_KEYGEN, /**< Running --keygen */
|
||||
CMD_KEY_EXPIRATION, /**< Running --key-expiration */
|
||||
CMD_IMMEDIATE, /**< Special value: indicates a command that is handled
|
||||
* immediately during configuration processing. */
|
||||
CMD_RUN_UNITTESTS, /**< Special value: indicates that we have entered
|
||||
* the Tor code from the unit tests, not from the
|
||||
* regular Tor binary at all. */
|
||||
} tor_cmdline_mode_t;
|
||||
|
||||
#endif /* !defined(TOR_CMDLINE_MODE_H) */
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file main.h
|
||||
* \brief Header file for main.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_MAIN_H
|
||||
#define TOR_MAIN_H
|
||||
|
||||
void handle_signals(void);
|
||||
void activate_signal(int signal_num);
|
||||
|
||||
int try_locking(const or_options_t *options, int err_if_locked);
|
||||
int have_lockfile(void);
|
||||
void release_lockfile(void);
|
||||
|
||||
void tor_remove_file(const char *filename);
|
||||
|
||||
int tor_init(int argc, char **argv);
|
||||
|
||||
int run_tor_main_loop(void);
|
||||
|
||||
void pubsub_install(void);
|
||||
void pubsub_connect(void);
|
||||
|
||||
#endif /* !defined(TOR_MAIN_H) */
|
||||
@@ -0,0 +1,29 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file ntmain.h
|
||||
* \brief Header file for ntmain.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_NTMAIN_H
|
||||
#define TOR_NTMAIN_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NT_SERVICE
|
||||
#endif
|
||||
|
||||
#ifdef NT_SERVICE
|
||||
int nt_service_parse_options(int argc, char **argv, int *should_exit);
|
||||
int nt_service_is_stopping(void);
|
||||
void nt_service_set_state(DWORD state);
|
||||
#else
|
||||
#define nt_service_is_stopping() 0
|
||||
#define nt_service_parse_options(a, b, c) (0)
|
||||
#define nt_service_set_state(s) STMT_NIL
|
||||
#endif /* defined(NT_SERVICE) */
|
||||
|
||||
#endif /* !defined(TOR_NTMAIN_H) */
|
||||
@@ -0,0 +1,17 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file risky_options.h
|
||||
* \brief Header for risky_options.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_RISKY_OPTIONS_H
|
||||
#define TOR_RISKY_OPTIONS_H
|
||||
|
||||
extern const char risky_option_list[];
|
||||
|
||||
#endif /* !defined(TOR_RISKY_OPTIONS_H) */
|
||||
@@ -0,0 +1,18 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file shutdown.h
|
||||
* \brief Header file for shutdown.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_SHUTDOWN_H
|
||||
#define TOR_SHUTDOWN_H
|
||||
|
||||
void tor_cleanup(void);
|
||||
void tor_free_all(int postfork);
|
||||
|
||||
#endif /* !defined(TOR_SHUTDOWN_H) */
|
||||
@@ -0,0 +1,53 @@
|
||||
/* Copyright (c) 2003-2004, Roger Dingledine
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file subsysmgr.h
|
||||
* @brief Header for subsysmgr.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_SUBSYSMGR_T
|
||||
#define TOR_SUBSYSMGR_T
|
||||
|
||||
#include "lib/subsys/subsys.h"
|
||||
|
||||
extern const struct subsys_fns_t *tor_subsystems[];
|
||||
extern const unsigned n_tor_subsystems;
|
||||
|
||||
int subsystems_init(void);
|
||||
int subsystems_init_upto(int level);
|
||||
|
||||
struct pubsub_builder_t;
|
||||
int subsystems_add_pubsub_upto(struct pubsub_builder_t *builder,
|
||||
int target_level);
|
||||
int subsystems_add_pubsub(struct pubsub_builder_t *builder);
|
||||
|
||||
void subsystems_shutdown(void);
|
||||
void subsystems_shutdown_downto(int level);
|
||||
|
||||
void subsystems_prefork(void);
|
||||
void subsystems_postfork(void);
|
||||
void subsystems_thread_cleanup(void);
|
||||
|
||||
void subsystems_dump_list(void);
|
||||
|
||||
struct config_mgr_t;
|
||||
int subsystems_register_options_formats(struct config_mgr_t *mgr);
|
||||
int subsystems_register_state_formats(struct config_mgr_t *mgr);
|
||||
struct or_options_t;
|
||||
struct or_state_t;
|
||||
int subsystems_set_options(const struct config_mgr_t *mgr,
|
||||
struct or_options_t *options);
|
||||
int subsystems_set_state(const struct config_mgr_t *mgr,
|
||||
struct or_state_t *state);
|
||||
int subsystems_flush_state(const struct config_mgr_t *mgr,
|
||||
struct or_state_t *state);
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
int subsystems_get_options_idx(const subsys_fns_t *sys);
|
||||
int subsystems_get_state_idx(const subsys_fns_t *sys);
|
||||
#endif
|
||||
|
||||
#endif /* !defined(TOR_SUBSYSMGR_T) */
|
||||
@@ -0,0 +1,91 @@
|
||||
/* Copyright (c) 2017-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file hs_ntor.h
|
||||
* @brief Header for hs_ntor.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_HS_NTOR_H
|
||||
#define TOR_HS_NTOR_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
struct ed25519_public_key_t;
|
||||
struct curve25519_public_key_t;
|
||||
struct curve25519_keypair_t;
|
||||
|
||||
/* Output length of KDF for key expansion */
|
||||
#define HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN \
|
||||
(DIGEST256_LEN*2 + CIPHER256_KEY_LEN*2)
|
||||
|
||||
/* Key material needed to encode/decode INTRODUCE1 cells */
|
||||
typedef struct hs_ntor_intro_cell_keys_t {
|
||||
/* Key used for encryption of encrypted INTRODUCE1 blob */
|
||||
uint8_t enc_key[CIPHER256_KEY_LEN];
|
||||
/* MAC key used to protect encrypted INTRODUCE1 blob */
|
||||
uint8_t mac_key[DIGEST256_LEN];
|
||||
} hs_ntor_intro_cell_keys_t;
|
||||
|
||||
/* Key material needed to encode/decode RENDEZVOUS1 cells */
|
||||
typedef struct hs_ntor_rend_cell_keys_t {
|
||||
/* This is the MAC of the HANDSHAKE_INFO field */
|
||||
uint8_t rend_cell_auth_mac[DIGEST256_LEN];
|
||||
/* This is the key seed used to derive further rendezvous crypto keys as
|
||||
* detailed in section 4.2.1 of rend-spec-ng.txt. */
|
||||
uint8_t ntor_key_seed[DIGEST256_LEN];
|
||||
} hs_ntor_rend_cell_keys_t;
|
||||
|
||||
#define SUBCRED_LEN DIGEST256_LEN
|
||||
|
||||
/**
|
||||
* A 'subcredential' used to prove knowledge of a hidden service.
|
||||
**/
|
||||
typedef struct hs_subcredential_t {
|
||||
uint8_t subcred[SUBCRED_LEN];
|
||||
} hs_subcredential_t;
|
||||
|
||||
int hs_ntor_client_get_introduce1_keys(
|
||||
const struct ed25519_public_key_t *intro_auth_pubkey,
|
||||
const struct curve25519_public_key_t *intro_enc_pubkey,
|
||||
const struct curve25519_keypair_t *client_ephemeral_enc_keypair,
|
||||
const hs_subcredential_t *subcredential,
|
||||
hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out);
|
||||
|
||||
int hs_ntor_client_get_rendezvous1_keys(
|
||||
const struct ed25519_public_key_t *intro_auth_pubkey,
|
||||
const struct curve25519_keypair_t *client_ephemeral_enc_keypair,
|
||||
const struct curve25519_public_key_t *intro_enc_pubkey,
|
||||
const struct curve25519_public_key_t *service_ephemeral_rend_pubkey,
|
||||
hs_ntor_rend_cell_keys_t *hs_ntor_rend_cell_keys_out);
|
||||
|
||||
int hs_ntor_service_get_introduce1_keys_multi(
|
||||
const struct ed25519_public_key_t *intro_auth_pubkey,
|
||||
const struct curve25519_keypair_t *intro_enc_keypair,
|
||||
const struct curve25519_public_key_t *client_ephemeral_enc_pubkey,
|
||||
size_t n_subcredentials,
|
||||
const hs_subcredential_t *subcredentials,
|
||||
hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out);
|
||||
|
||||
int hs_ntor_service_get_introduce1_keys(
|
||||
const struct ed25519_public_key_t *intro_auth_pubkey,
|
||||
const struct curve25519_keypair_t *intro_enc_keypair,
|
||||
const struct curve25519_public_key_t *client_ephemeral_enc_pubkey,
|
||||
const hs_subcredential_t *subcredential,
|
||||
hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out);
|
||||
|
||||
int hs_ntor_service_get_rendezvous1_keys(
|
||||
const struct ed25519_public_key_t *intro_auth_pubkey,
|
||||
const struct curve25519_keypair_t *intro_enc_keypair,
|
||||
const struct curve25519_keypair_t *service_ephemeral_rend_keypair,
|
||||
const struct curve25519_public_key_t *client_ephemeral_enc_pubkey,
|
||||
hs_ntor_rend_cell_keys_t *hs_ntor_rend_cell_keys_out);
|
||||
|
||||
int hs_ntor_circuit_key_expansion(const uint8_t *ntor_key_seed,
|
||||
size_t seed_len,
|
||||
uint8_t *keys_out, size_t keys_out_len);
|
||||
|
||||
int hs_ntor_client_rendezvous2_mac_is_good(
|
||||
const hs_ntor_rend_cell_keys_t *hs_ntor_rend_cell_keys,
|
||||
const uint8_t *rcvd_mac);
|
||||
|
||||
#endif /* !defined(TOR_HS_NTOR_H) */
|
||||
@@ -0,0 +1,66 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file onion_crypto.h
|
||||
* \brief Header file for onion_crypto.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_ONION_CRYPTO_H
|
||||
#define TOR_ONION_CRYPTO_H
|
||||
|
||||
#include "lib/crypt_ops/crypto_ed25519.h"
|
||||
|
||||
typedef struct server_onion_keys_t {
|
||||
uint8_t my_identity[DIGEST_LEN];
|
||||
ed25519_public_key_t my_ed_identity;
|
||||
crypto_pk_t *onion_key;
|
||||
crypto_pk_t *last_onion_key;
|
||||
struct di_digest256_map_t *curve25519_key_map;
|
||||
struct curve25519_keypair_t *junk_keypair;
|
||||
} server_onion_keys_t;
|
||||
|
||||
void onion_handshake_state_release(onion_handshake_state_t *state);
|
||||
|
||||
/**
|
||||
* Parameters negotiated as part of a circuit handshake.
|
||||
*/
|
||||
typedef struct circuit_params_t {
|
||||
/** Is true if congestion control is enabled in consensus or param,
|
||||
* as per congestion_control_enabled() result. */
|
||||
bool cc_enabled;
|
||||
/** The number of cells in a sendme increment. Only used if cc_enabled=1. */
|
||||
uint8_t sendme_inc_cells;
|
||||
} circuit_params_t;
|
||||
|
||||
int onion_skin_create(int type,
|
||||
const extend_info_t *node,
|
||||
onion_handshake_state_t *state_out,
|
||||
uint8_t *onion_skin_out,
|
||||
size_t onion_skin_out_maxlen);
|
||||
int onion_skin_server_handshake(int type,
|
||||
const uint8_t *onion_skin, size_t onionskin_len,
|
||||
const server_onion_keys_t *keys,
|
||||
const circuit_params_t *ns_params,
|
||||
uint8_t *reply_out,
|
||||
size_t reply_out_maxlen,
|
||||
uint8_t *keys_out, size_t key_out_len,
|
||||
uint8_t *rend_nonce_out,
|
||||
circuit_params_t *negotiated_params_out);
|
||||
int onion_skin_client_handshake(int type,
|
||||
const onion_handshake_state_t *handshake_state,
|
||||
const uint8_t *reply, size_t reply_len,
|
||||
uint8_t *keys_out, size_t key_out_len,
|
||||
uint8_t *rend_authenticator_out,
|
||||
circuit_params_t *negotiated_params_out,
|
||||
const char **msg_out);
|
||||
|
||||
server_onion_keys_t *server_onion_keys_new(void);
|
||||
void server_onion_keys_free_(server_onion_keys_t *keys);
|
||||
#define server_onion_keys_free(keys) \
|
||||
FREE_AND_NULL(server_onion_keys_t, server_onion_keys_free_, (keys))
|
||||
|
||||
#endif /* !defined(TOR_ONION_CRYPTO_H) */
|
||||
@@ -0,0 +1,41 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file onion_fast.h
|
||||
* \brief Header file for onion_fast.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_ONION_FAST_H
|
||||
#define TOR_ONION_FAST_H
|
||||
|
||||
#define CREATE_FAST_LEN DIGEST_LEN
|
||||
#define CREATED_FAST_LEN (DIGEST_LEN*2)
|
||||
|
||||
typedef struct fast_handshake_state_t {
|
||||
uint8_t state[DIGEST_LEN];
|
||||
} fast_handshake_state_t;
|
||||
|
||||
void fast_handshake_state_free_(fast_handshake_state_t *victim);
|
||||
#define fast_handshake_state_free(st) \
|
||||
FREE_AND_NULL(fast_handshake_state_t, fast_handshake_state_free_, (st))
|
||||
|
||||
int fast_onionskin_create(fast_handshake_state_t **handshake_state_out,
|
||||
uint8_t *handshake_out);
|
||||
|
||||
int fast_server_handshake(const uint8_t *message_in,
|
||||
uint8_t *handshake_reply_out,
|
||||
uint8_t *key_out,
|
||||
size_t key_out_len);
|
||||
|
||||
int fast_client_handshake(const fast_handshake_state_t *handshake_state,
|
||||
const uint8_t *handshake_reply_out,
|
||||
uint8_t *key_out,
|
||||
size_t key_out_len,
|
||||
const char **msg_out);
|
||||
|
||||
#endif /* !defined(TOR_ONION_FAST_H) */
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/* Copyright (c) 2012-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file onion_ntor.h
|
||||
* @brief Header for onion_ntor.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_ONION_NTOR_H
|
||||
#define TOR_ONION_NTOR_H
|
||||
|
||||
#include "lib/cc/torint.h"
|
||||
|
||||
struct di_digest256_map_t;
|
||||
struct curve25519_public_key_t;
|
||||
struct curve25519_keypair_t;
|
||||
|
||||
/** State to be maintained by a client between sending an ntor onionskin
|
||||
* and receiving a reply. */
|
||||
typedef struct ntor_handshake_state_t ntor_handshake_state_t;
|
||||
|
||||
/** Length of an ntor onionskin, as sent from the client to server. */
|
||||
#define NTOR_ONIONSKIN_LEN 84
|
||||
/** Length of an ntor reply, as sent from server to client. */
|
||||
#define NTOR_REPLY_LEN 64
|
||||
|
||||
void ntor_handshake_state_free_(ntor_handshake_state_t *state);
|
||||
#define ntor_handshake_state_free(state) \
|
||||
FREE_AND_NULL(ntor_handshake_state_t, ntor_handshake_state_free_, (state))
|
||||
|
||||
int onion_skin_ntor_create(const uint8_t *router_id,
|
||||
const struct curve25519_public_key_t *router_key,
|
||||
ntor_handshake_state_t **handshake_state_out,
|
||||
uint8_t *onion_skin_out);
|
||||
|
||||
int onion_skin_ntor_server_handshake(const uint8_t *onion_skin,
|
||||
const struct di_digest256_map_t *private_keys,
|
||||
const struct curve25519_keypair_t *junk_keypair,
|
||||
const uint8_t *my_node_id,
|
||||
uint8_t *handshake_reply_out,
|
||||
uint8_t *key_out,
|
||||
size_t key_out_len);
|
||||
|
||||
int onion_skin_ntor_client_handshake(
|
||||
const ntor_handshake_state_t *handshake_state,
|
||||
const uint8_t *handshake_reply,
|
||||
uint8_t *key_out,
|
||||
size_t key_out_len,
|
||||
const char **msg_out);
|
||||
|
||||
#ifdef ONION_NTOR_PRIVATE
|
||||
#include "lib/crypt_ops/crypto_curve25519.h"
|
||||
|
||||
/** Storage held by a client while waiting for an ntor reply from a server. */
|
||||
struct ntor_handshake_state_t {
|
||||
/** Identity digest of the router we're talking to. */
|
||||
uint8_t router_id[DIGEST_LEN];
|
||||
/** Onion key of the router we're talking to. */
|
||||
curve25519_public_key_t pubkey_B;
|
||||
|
||||
/**
|
||||
* Short-lived keypair for use with this handshake.
|
||||
* @{ */
|
||||
curve25519_secret_key_t seckey_x;
|
||||
curve25519_public_key_t pubkey_X;
|
||||
/** @} */
|
||||
};
|
||||
#endif /* defined(ONION_NTOR_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_ONION_NTOR_H) */
|
||||
@@ -0,0 +1,140 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file onion_ntor_v3.h
|
||||
* @brief Header for core/crypto/onion_ntor_v3.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_CORE_CRYPTO_ONION_NTOR_V3_H
|
||||
#define TOR_CORE_CRYPTO_ONION_NTOR_V3_H
|
||||
|
||||
#include "lib/cc/torint.h"
|
||||
#include "lib/testsupport/testsupport.h"
|
||||
#include "lib/crypt_ops/crypto_cipher.h"
|
||||
#include "lib/crypt_ops/crypto_curve25519.h"
|
||||
#include "lib/crypt_ops/crypto_ed25519.h"
|
||||
#include "lib/malloc/malloc.h"
|
||||
|
||||
/**
|
||||
* Client-side state held while an ntor v3 handshake is in progress.
|
||||
**/
|
||||
typedef struct ntor3_handshake_state_t ntor3_handshake_state_t;
|
||||
|
||||
/**
|
||||
* Server-side state held while the relay is handling a client's
|
||||
* encapsulated message, before replying to the v3 handshake.
|
||||
**/
|
||||
typedef struct ntor3_server_handshake_state_t ntor3_server_handshake_state_t;
|
||||
|
||||
void ntor3_handshake_state_free_(ntor3_handshake_state_t *st);
|
||||
#define ntor3_handshake_state_free(ptr) \
|
||||
FREE_AND_NULL(ntor3_handshake_state_t, ntor3_handshake_state_free_, (ptr))
|
||||
void ntor3_server_handshake_state_free_(ntor3_server_handshake_state_t *st);
|
||||
#define ntor3_server_handshake_state_free(ptr) \
|
||||
FREE_AND_NULL(ntor3_server_handshake_state_t, \
|
||||
ntor3_server_handshake_state_free_, (ptr))
|
||||
|
||||
int onion_skin_ntor3_create(const ed25519_public_key_t *relay_id,
|
||||
const curve25519_public_key_t *relay_key,
|
||||
const uint8_t *verification,
|
||||
const size_t verification_len,
|
||||
const uint8_t *message,
|
||||
const size_t message_len,
|
||||
ntor3_handshake_state_t **handshake_state_out,
|
||||
uint8_t **onion_skin_out,
|
||||
size_t *onion_skin_len_out);
|
||||
|
||||
int onion_ntor3_client_handshake(
|
||||
const ntor3_handshake_state_t *handshake_state,
|
||||
const uint8_t *handshake_reply,
|
||||
size_t reply_len,
|
||||
const uint8_t *verification,
|
||||
size_t verification_len,
|
||||
uint8_t *keys_out,
|
||||
size_t keys_out_len,
|
||||
uint8_t **message_out,
|
||||
size_t *message_len_out);
|
||||
|
||||
struct di_digest256_map_t;
|
||||
int onion_skin_ntor3_server_handshake_part1(
|
||||
const struct di_digest256_map_t *private_keys,
|
||||
const curve25519_keypair_t *junk_key,
|
||||
const ed25519_public_key_t *my_id,
|
||||
const uint8_t *client_handshake,
|
||||
size_t client_handshake_len,
|
||||
const uint8_t *verification,
|
||||
size_t verification_len,
|
||||
uint8_t **client_message_out,
|
||||
size_t *client_message_len_out,
|
||||
ntor3_server_handshake_state_t **state_out);
|
||||
|
||||
int onion_skin_ntor3_server_handshake_part2(
|
||||
const ntor3_server_handshake_state_t *state,
|
||||
const uint8_t *verification,
|
||||
size_t verification_len,
|
||||
const uint8_t *server_message,
|
||||
size_t server_message_len,
|
||||
uint8_t **handshake_out,
|
||||
size_t *handshake_len_out,
|
||||
uint8_t *keys_out,
|
||||
size_t keys_out_len);
|
||||
|
||||
#ifdef ONION_NTOR_V3_PRIVATE
|
||||
struct ntor3_handshake_state_t {
|
||||
/** Ephemeral (x,X) keypair. */
|
||||
curve25519_keypair_t client_keypair;
|
||||
/** Relay's ed25519 identity key (ID) */
|
||||
ed25519_public_key_t relay_id;
|
||||
/** Relay's public key (B) */
|
||||
curve25519_public_key_t relay_key;
|
||||
/** Shared secret (Bx). */
|
||||
uint8_t bx[CURVE25519_OUTPUT_LEN];
|
||||
/** MAC of the client's encrypted message data (MAC) */
|
||||
uint8_t msg_mac[DIGEST256_LEN];
|
||||
};
|
||||
|
||||
struct ntor3_server_handshake_state_t {
|
||||
/** Relay's ed25519 identity key (ID) */
|
||||
ed25519_public_key_t my_id;
|
||||
/** Relay's public key (B) */
|
||||
curve25519_public_key_t my_key;
|
||||
/** Client's public ephemeral key (X). */
|
||||
curve25519_public_key_t client_key;
|
||||
|
||||
/** Shared secret (Xb) */
|
||||
uint8_t xb[CURVE25519_OUTPUT_LEN];
|
||||
/** MAC of the client's encrypted message data */
|
||||
uint8_t msg_mac[DIGEST256_LEN];
|
||||
};
|
||||
|
||||
STATIC int onion_skin_ntor3_create_nokeygen(
|
||||
const curve25519_keypair_t *client_keypair,
|
||||
const ed25519_public_key_t *relay_id,
|
||||
const curve25519_public_key_t *relay_key,
|
||||
const uint8_t *verification,
|
||||
const size_t verification_len,
|
||||
const uint8_t *message,
|
||||
const size_t message_len,
|
||||
ntor3_handshake_state_t **handshake_state_out,
|
||||
uint8_t **onion_skin_out,
|
||||
size_t *onion_skin_len_out);
|
||||
|
||||
STATIC int onion_skin_ntor3_server_handshake_part2_nokeygen(
|
||||
const curve25519_keypair_t *relay_keypair_y,
|
||||
const ntor3_server_handshake_state_t *state,
|
||||
const uint8_t *verification,
|
||||
size_t verification_len,
|
||||
const uint8_t *server_message,
|
||||
size_t server_message_len,
|
||||
uint8_t **handshake_out,
|
||||
size_t *handshake_len_out,
|
||||
uint8_t *keys_out,
|
||||
size_t keys_out_len);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !defined(TOR_CORE_CRYPTO_ONION_NTOR_V3_H) */
|
||||
@@ -0,0 +1,40 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file onion_tap.h
|
||||
* \brief Header file for onion_tap.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_ONION_TAP_H
|
||||
#define TOR_ONION_TAP_H
|
||||
|
||||
#define TAP_ONIONSKIN_CHALLENGE_LEN (PKCS1_OAEP_PADDING_OVERHEAD+\
|
||||
CIPHER_KEY_LEN+\
|
||||
DH1024_KEY_LEN)
|
||||
#define TAP_ONIONSKIN_REPLY_LEN (DH1024_KEY_LEN+DIGEST_LEN)
|
||||
|
||||
struct crypto_dh_t;
|
||||
struct crypto_pk_t;
|
||||
|
||||
int onion_skin_TAP_create(struct crypto_pk_t *router_key,
|
||||
struct crypto_dh_t **handshake_state_out,
|
||||
char *onion_skin_out);
|
||||
|
||||
int onion_skin_TAP_server_handshake(const char *onion_skin,
|
||||
struct crypto_pk_t *private_key,
|
||||
struct crypto_pk_t *prev_private_key,
|
||||
char *handshake_reply_out,
|
||||
char *key_out,
|
||||
size_t key_out_len);
|
||||
|
||||
int onion_skin_TAP_client_handshake(struct crypto_dh_t *handshake_state,
|
||||
const char *handshake_reply,
|
||||
char *key_out,
|
||||
size_t key_out_len,
|
||||
const char **msg_out);
|
||||
|
||||
#endif /* !defined(TOR_ONION_TAP_H) */
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file relay.h
|
||||
* \brief Header file for relay.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_RELAY_CRYPTO_H
|
||||
#define TOR_RELAY_CRYPTO_H
|
||||
|
||||
int relay_crypto_init(relay_crypto_t *crypto,
|
||||
const char *key_data, size_t key_data_len,
|
||||
int reverse, int is_hs_v3);
|
||||
|
||||
int relay_decrypt_cell(circuit_t *circ, cell_t *cell,
|
||||
cell_direction_t cell_direction,
|
||||
crypt_path_t **layer_hint, char *recognized);
|
||||
void relay_encrypt_cell_outbound(cell_t *cell, origin_circuit_t *or_circ,
|
||||
crypt_path_t *layer_hint);
|
||||
void relay_encrypt_cell_inbound(cell_t *cell, or_circuit_t *or_circ);
|
||||
|
||||
void relay_crypto_clear(relay_crypto_t *crypto);
|
||||
|
||||
void relay_crypto_assert_ok(const relay_crypto_t *crypto);
|
||||
|
||||
uint8_t *relay_crypto_get_sendme_digest(relay_crypto_t *crypto);
|
||||
|
||||
void relay_crypto_record_sendme_digest(relay_crypto_t *crypto,
|
||||
bool is_foward_digest);
|
||||
|
||||
void
|
||||
relay_crypt_one_payload(crypto_cipher_t *cipher, uint8_t *in);
|
||||
|
||||
void
|
||||
relay_set_digest(crypto_digest_t *digest, cell_t *cell);
|
||||
|
||||
#endif /* !defined(TOR_RELAY_CRYPTO_H) */
|
||||
|
||||
@@ -0,0 +1,396 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file connection.h
|
||||
* \brief Header file for connection.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONNECTION_H
|
||||
#define TOR_CONNECTION_H
|
||||
|
||||
#include "lib/smartlist_core/smartlist_core.h"
|
||||
#include "lib/log/log.h"
|
||||
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
struct listener_connection_t;
|
||||
struct connection_t;
|
||||
struct dir_connection_t;
|
||||
struct or_connection_t;
|
||||
struct edge_connection_t;
|
||||
struct entry_connection_t;
|
||||
struct control_connection_t;
|
||||
struct port_cfg_t;
|
||||
struct tor_addr_t;
|
||||
struct or_options_t;
|
||||
|
||||
struct listener_connection_t *TO_LISTENER_CONN(struct connection_t *);
|
||||
const struct listener_connection_t *CONST_TO_LISTENER_CONN(
|
||||
const struct connection_t *);
|
||||
|
||||
struct buf_t;
|
||||
|
||||
#define CONN_TYPE_MIN_ 3
|
||||
/** Type for sockets listening for OR connections. */
|
||||
#define CONN_TYPE_OR_LISTENER 3
|
||||
/** A bidirectional TLS connection transmitting a sequence of cells.
|
||||
* May be from an OR to an OR, or from an OP to an OR. */
|
||||
#define CONN_TYPE_OR 4
|
||||
/** A TCP connection from an onion router to a stream's destination. */
|
||||
#define CONN_TYPE_EXIT 5
|
||||
/** Type for sockets listening for SOCKS connections. */
|
||||
#define CONN_TYPE_AP_LISTENER 6
|
||||
/** A SOCKS proxy connection from the user application to the onion
|
||||
* proxy. */
|
||||
#define CONN_TYPE_AP 7
|
||||
/** Type for sockets listening for HTTP connections to the directory server. */
|
||||
#define CONN_TYPE_DIR_LISTENER 8
|
||||
/** Type for HTTP connections to the directory server. */
|
||||
#define CONN_TYPE_DIR 9
|
||||
/* Type 10 is unused. */
|
||||
/** Type for listening for connections from user interface process. */
|
||||
#define CONN_TYPE_CONTROL_LISTENER 11
|
||||
/** Type for connections from user interface process. */
|
||||
#define CONN_TYPE_CONTROL 12
|
||||
/** Type for sockets listening for transparent connections redirected by pf or
|
||||
* netfilter. */
|
||||
#define CONN_TYPE_AP_TRANS_LISTENER 13
|
||||
/** Type for sockets listening for transparent connections redirected by
|
||||
* natd. */
|
||||
#define CONN_TYPE_AP_NATD_LISTENER 14
|
||||
/** Type for sockets listening for DNS requests. */
|
||||
#define CONN_TYPE_AP_DNS_LISTENER 15
|
||||
|
||||
/** Type for connections from the Extended ORPort. */
|
||||
#define CONN_TYPE_EXT_OR 16
|
||||
/** Type for sockets listening for Extended ORPort connections. */
|
||||
#define CONN_TYPE_EXT_OR_LISTENER 17
|
||||
/** Type for sockets listening for HTTP CONNECT tunnel connections. */
|
||||
#define CONN_TYPE_AP_HTTP_CONNECT_LISTENER 18
|
||||
/** Type for sockets listening for Metrics query connections. */
|
||||
#define CONN_TYPE_METRICS_LISTENER 19
|
||||
/** Type for connections from metrics listener. */
|
||||
#define CONN_TYPE_METRICS 20
|
||||
|
||||
#define CONN_TYPE_MAX_ 21
|
||||
/* !!!! If _CONN_TYPE_MAX is ever over 31, we must grow the type field in
|
||||
* struct connection_t. */
|
||||
|
||||
/* Proxy client handshake states */
|
||||
/* We use a proxy but we haven't even connected to it yet. */
|
||||
#define PROXY_INFANT 1
|
||||
/* We use an HTTP proxy and we've sent the CONNECT command. */
|
||||
#define PROXY_HTTPS_WANT_CONNECT_OK 2
|
||||
/* We use a SOCKS4 proxy and we've sent the CONNECT command. */
|
||||
#define PROXY_SOCKS4_WANT_CONNECT_OK 3
|
||||
/* We use a SOCKS5 proxy and we try to negotiate without
|
||||
any authentication . */
|
||||
#define PROXY_SOCKS5_WANT_AUTH_METHOD_NONE 4
|
||||
/* We use a SOCKS5 proxy and we try to negotiate with
|
||||
Username/Password authentication . */
|
||||
#define PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929 5
|
||||
/* We use a SOCKS5 proxy and we just sent our credentials. */
|
||||
#define PROXY_SOCKS5_WANT_AUTH_RFC1929_OK 6
|
||||
/* We use a SOCKS5 proxy and we just sent our CONNECT command. */
|
||||
#define PROXY_SOCKS5_WANT_CONNECT_OK 7
|
||||
/* We use an HAPROXY proxy and we just sent the proxy header. */
|
||||
#define PROXY_HAPROXY_WAIT_FOR_FLUSH 8
|
||||
/* We use a proxy and we CONNECTed successfully!. */
|
||||
#define PROXY_CONNECTED 9
|
||||
|
||||
/** State for any listener connection. */
|
||||
#define LISTENER_STATE_READY 0
|
||||
|
||||
/**
|
||||
* This struct associates an old listener connection to be replaced
|
||||
* by new connection described by port configuration. Only used when
|
||||
* moving listeners to/from wildcard IP address.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
struct connection_t *old_conn; /* Old listener connection to be replaced */
|
||||
const struct port_cfg_t *new_port; /* New port configuration */
|
||||
} listener_replacement_t;
|
||||
|
||||
const char *conn_type_to_string(int type);
|
||||
const char *conn_state_to_string(int type, int state);
|
||||
int conn_listener_type_supports_af_unix(int type);
|
||||
|
||||
const char *connection_describe(const connection_t *conn);
|
||||
const char *connection_describe_peer(const connection_t *conn);
|
||||
|
||||
struct dir_connection_t *dir_connection_new(int socket_family);
|
||||
struct or_connection_t *or_connection_new(int type, int socket_family);
|
||||
struct edge_connection_t *edge_connection_new(int type, int socket_family);
|
||||
struct entry_connection_t *entry_connection_new(int type, int socket_family);
|
||||
struct control_connection_t *control_connection_new(int socket_family);
|
||||
struct listener_connection_t *listener_connection_new(int type,
|
||||
int socket_family);
|
||||
struct connection_t *connection_new(int type, int socket_family);
|
||||
int connection_init_accepted_conn(struct connection_t *conn,
|
||||
const struct listener_connection_t *listener);
|
||||
void connection_link_connections(struct connection_t *conn_a,
|
||||
struct connection_t *conn_b);
|
||||
MOCK_DECL(void,connection_free_,(struct connection_t *conn));
|
||||
#define connection_free(conn) \
|
||||
FREE_AND_NULL(struct connection_t, connection_free_, (conn))
|
||||
void connection_free_all(void);
|
||||
void connection_about_to_close_connection(struct connection_t *conn);
|
||||
void connection_close_immediate(struct connection_t *conn);
|
||||
void connection_mark_for_close_(struct connection_t *conn,
|
||||
int line, const char *file);
|
||||
MOCK_DECL(void, connection_mark_for_close_internal_,
|
||||
(struct connection_t *conn, int line, const char *file));
|
||||
|
||||
#define connection_mark_for_close(c) \
|
||||
connection_mark_for_close_((c), __LINE__, SHORT_FILE__)
|
||||
#define connection_mark_for_close_internal(c) \
|
||||
connection_mark_for_close_internal_((c), __LINE__, SHORT_FILE__)
|
||||
|
||||
/**
|
||||
* Mark 'c' for close, but try to hold it open until all the data is written.
|
||||
* Use the _internal versions of connection_mark_for_close; this should be
|
||||
* called when you either are sure that if this is an or_connection_t the
|
||||
* controlling channel has been notified (e.g. with
|
||||
* connection_or_notify_error()), or you actually are the
|
||||
* connection_or_close_for_error() or connection_or_close_normally function.
|
||||
* For all other cases, use connection_mark_and_flush() instead, which
|
||||
* checks for struct or_connection_t properly, instead. See below.
|
||||
*/
|
||||
#define connection_mark_and_flush_internal_(c,line,file) \
|
||||
do { \
|
||||
struct connection_t *tmp_conn__ = (c); \
|
||||
connection_mark_for_close_internal_(tmp_conn__, (line), (file)); \
|
||||
tmp_conn__->hold_open_until_flushed = 1; \
|
||||
} while (0)
|
||||
|
||||
#define connection_mark_and_flush_internal(c) \
|
||||
connection_mark_and_flush_internal_((c), __LINE__, SHORT_FILE__)
|
||||
|
||||
/**
|
||||
* Mark 'c' for close, but try to hold it open until all the data is written.
|
||||
*/
|
||||
#define connection_mark_and_flush_(c,line,file) \
|
||||
do { \
|
||||
struct connection_t *tmp_conn_ = (c); \
|
||||
if (tmp_conn_->type == CONN_TYPE_OR) { \
|
||||
log_warn(LD_CHANNEL | LD_BUG, \
|
||||
"Something tried to close (and flush) an or_connection_t" \
|
||||
" without going through channels at %s:%d", \
|
||||
file, line); \
|
||||
connection_or_close_for_error(TO_OR_CONN(tmp_conn_), 1); \
|
||||
} else { \
|
||||
connection_mark_and_flush_internal_(c, line, file); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define connection_mark_and_flush(c) \
|
||||
connection_mark_and_flush_((c), __LINE__, SHORT_FILE__)
|
||||
|
||||
void connection_expire_held_open(void);
|
||||
|
||||
int connection_connect(struct connection_t *conn, const char *address,
|
||||
const struct tor_addr_t *addr,
|
||||
uint16_t port, int *socket_error);
|
||||
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
|
||||
int connection_connect_unix(struct connection_t *conn, const char *socket_path,
|
||||
int *socket_error);
|
||||
|
||||
#endif /* defined(HAVE_SYS_UN_H) */
|
||||
|
||||
/** Maximum size of information that we can fit into SOCKS5 username
|
||||
or password fields. */
|
||||
#define MAX_SOCKS5_AUTH_FIELD_SIZE 255
|
||||
|
||||
/** Total maximum size of information that we can fit into SOCKS5
|
||||
username and password fields. */
|
||||
#define MAX_SOCKS5_AUTH_SIZE_TOTAL 2*MAX_SOCKS5_AUTH_FIELD_SIZE
|
||||
|
||||
int connection_proxy_connect(struct connection_t *conn, int type);
|
||||
int connection_read_proxy_handshake(struct connection_t *conn);
|
||||
void log_failed_proxy_connection(struct connection_t *conn);
|
||||
int get_proxy_addrport(struct tor_addr_t *addr, uint16_t *port,
|
||||
int *proxy_type,
|
||||
int *is_pt_out, const struct connection_t *conn);
|
||||
|
||||
int retry_all_listeners(struct smartlist_t *new_conns,
|
||||
int close_all_noncontrol);
|
||||
|
||||
void connection_mark_all_noncontrol_listeners(void);
|
||||
void connection_mark_all_noncontrol_connections(void);
|
||||
|
||||
ssize_t connection_bucket_write_limit(struct connection_t *conn, time_t now);
|
||||
bool connection_dir_is_global_write_low(const struct connection_t *conn,
|
||||
size_t attempt);
|
||||
void connection_bucket_init(void);
|
||||
void connection_bucket_adjust(const struct or_options_t *options);
|
||||
void connection_bucket_refill_all(time_t now,
|
||||
uint32_t now_ts);
|
||||
void connection_read_bw_exhausted(struct connection_t *conn,
|
||||
bool is_global_bw);
|
||||
void connection_write_bw_exhausted(struct connection_t *conn,
|
||||
bool is_global_bw);
|
||||
void connection_consider_empty_read_buckets(struct connection_t *conn);
|
||||
void connection_consider_empty_write_buckets(struct connection_t *conn);
|
||||
|
||||
int connection_handle_read(struct connection_t *conn);
|
||||
|
||||
int connection_buf_get_bytes(char *string, size_t len,
|
||||
struct connection_t *conn);
|
||||
int connection_buf_get_line(struct connection_t *conn, char *data,
|
||||
size_t *data_len);
|
||||
int connection_fetch_from_buf_http(struct connection_t *conn,
|
||||
char **headers_out, size_t max_headerlen,
|
||||
char **body_out, size_t *body_used,
|
||||
size_t max_bodylen, int force_complete);
|
||||
|
||||
int connection_wants_to_flush(struct connection_t *conn);
|
||||
int connection_outbuf_too_full(struct connection_t *conn);
|
||||
int connection_handle_write(struct connection_t *conn, int force);
|
||||
int connection_flush(struct connection_t *conn);
|
||||
int connection_process_inbuf(struct connection_t *conn, int package_partial);
|
||||
|
||||
MOCK_DECL(void, connection_write_to_buf_impl_,
|
||||
(const char *string, size_t len, struct connection_t *conn,
|
||||
int zlib));
|
||||
/* DOCDOC connection_write_to_buf */
|
||||
static void connection_buf_add(const char *string, size_t len,
|
||||
struct connection_t *conn);
|
||||
void connection_dir_buf_add(const char *string, size_t len,
|
||||
struct dir_connection_t *dir_conn, int done);
|
||||
static inline void
|
||||
connection_buf_add(const char *string, size_t len, struct connection_t *conn)
|
||||
{
|
||||
connection_write_to_buf_impl_(string, len, conn, 0);
|
||||
}
|
||||
void connection_buf_add_compress(const char *string, size_t len,
|
||||
struct dir_connection_t *conn, int done);
|
||||
void connection_buf_add_buf(struct connection_t *conn, struct buf_t *buf);
|
||||
|
||||
size_t connection_get_inbuf_len(const struct connection_t *conn);
|
||||
size_t connection_get_outbuf_len(const struct connection_t *conn);
|
||||
struct connection_t *connection_get_by_global_id(uint64_t id);
|
||||
|
||||
struct connection_t *connection_get_by_type(int type);
|
||||
MOCK_DECL(struct connection_t *,connection_get_by_type_nonlinked,(int type));
|
||||
MOCK_DECL(struct connection_t *,connection_get_by_type_addr_port_purpose,
|
||||
(int type,
|
||||
const struct tor_addr_t *addr,
|
||||
uint16_t port, int purpose));
|
||||
struct connection_t *connection_get_by_type_state(int type, int state);
|
||||
struct connection_t *connection_get_by_type_state_rendquery(
|
||||
int type, int state,
|
||||
const char *rendquery);
|
||||
struct smartlist_t *connection_list_by_type_state(int type, int state);
|
||||
struct smartlist_t *connection_list_by_type_purpose(int type, int purpose);
|
||||
struct smartlist_t *connection_dir_list_by_purpose_and_resource(
|
||||
int purpose,
|
||||
const char *resource);
|
||||
struct smartlist_t *connection_dir_list_by_purpose_resource_and_state(
|
||||
int purpose,
|
||||
const char *resource,
|
||||
int state);
|
||||
|
||||
#define CONN_LEN_AND_FREE_TEMPLATE(sl) \
|
||||
STMT_BEGIN \
|
||||
int len = smartlist_len(sl); \
|
||||
smartlist_free(sl); \
|
||||
return len; \
|
||||
STMT_END
|
||||
|
||||
/** Return a count of directory connections that are fetching the item
|
||||
* described by <b>purpose</b>/<b>resource</b>. */
|
||||
static inline int
|
||||
connection_dir_count_by_purpose_and_resource(
|
||||
int purpose,
|
||||
const char *resource)
|
||||
{
|
||||
struct smartlist_t *conns = connection_dir_list_by_purpose_and_resource(
|
||||
purpose,
|
||||
resource);
|
||||
CONN_LEN_AND_FREE_TEMPLATE(conns);
|
||||
}
|
||||
|
||||
/** Return a count of directory connections that are fetching the item
|
||||
* described by <b>purpose</b>/<b>resource</b>/<b>state</b>. */
|
||||
static inline int
|
||||
connection_dir_count_by_purpose_resource_and_state(
|
||||
int purpose,
|
||||
const char *resource,
|
||||
int state)
|
||||
{
|
||||
struct smartlist_t *conns =
|
||||
connection_dir_list_by_purpose_resource_and_state(
|
||||
purpose,
|
||||
resource,
|
||||
state);
|
||||
CONN_LEN_AND_FREE_TEMPLATE(conns);
|
||||
}
|
||||
|
||||
#undef CONN_LEN_AND_FREE_TEMPLATE
|
||||
|
||||
int any_other_active_or_conns(const struct or_connection_t *this_conn);
|
||||
|
||||
/* || 0 is for -Wparentheses-equality (-Wall?) appeasement under clang */
|
||||
#define connection_speaks_cells(conn) (((conn)->type == CONN_TYPE_OR) || 0)
|
||||
int connection_is_listener(struct connection_t *conn);
|
||||
int connection_state_is_open(struct connection_t *conn);
|
||||
int connection_state_is_connecting(struct connection_t *conn);
|
||||
|
||||
char *alloc_http_authenticator(const char *authenticator);
|
||||
|
||||
void assert_connection_ok(struct connection_t *conn, time_t now);
|
||||
int connection_or_nonopen_was_started_here(struct or_connection_t *conn);
|
||||
void connection_dump_buffer_mem_stats(int severity);
|
||||
|
||||
MOCK_DECL(void, clock_skew_warning,
|
||||
(const struct connection_t *conn, long apparent_skew, int trusted,
|
||||
log_domain_mask_t domain, const char *received,
|
||||
const char *source));
|
||||
|
||||
int connection_is_moribund(struct connection_t *conn);
|
||||
void connection_check_oos(int n_socks, int failed);
|
||||
|
||||
/** Execute the statement <b>stmt</b>, which may log events concerning the
|
||||
* connection <b>conn</b>. To prevent infinite loops, disable log messages
|
||||
* being sent to controllers if <b>conn</b> is a control connection.
|
||||
*
|
||||
* Stmt must not contain any return or goto statements.
|
||||
*/
|
||||
#define CONN_LOG_PROTECT(conn, stmt) \
|
||||
STMT_BEGIN \
|
||||
int _log_conn_is_control; \
|
||||
tor_assert(conn); \
|
||||
_log_conn_is_control = (conn->type == CONN_TYPE_CONTROL); \
|
||||
if (_log_conn_is_control) \
|
||||
disable_control_logging(); \
|
||||
STMT_BEGIN stmt; STMT_END; \
|
||||
if (_log_conn_is_control) \
|
||||
enable_control_logging(); \
|
||||
STMT_END
|
||||
|
||||
#ifdef CONNECTION_PRIVATE
|
||||
STATIC void connection_free_minimal(struct connection_t *conn);
|
||||
|
||||
/* Used only by connection.c and test*.c */
|
||||
MOCK_DECL(STATIC int,connection_connect_sockaddr,
|
||||
(struct connection_t *conn,
|
||||
const struct sockaddr *sa,
|
||||
socklen_t sa_len,
|
||||
const struct sockaddr *bindaddr,
|
||||
socklen_t bindaddr_len,
|
||||
int *socket_error));
|
||||
MOCK_DECL(STATIC void, kill_conn_list_for_oos, (struct smartlist_t *conns));
|
||||
MOCK_DECL(STATIC struct smartlist_t *, pick_oos_victims, (int n));
|
||||
|
||||
#endif /* defined(CONNECTION_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CONNECTION_H) */
|
||||
@@ -0,0 +1,43 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2024, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file cpuworker.h
|
||||
* \brief Header file for cpuworker.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CPUWORKER_H
|
||||
#define TOR_CPUWORKER_H
|
||||
|
||||
int cpuworker_init(void);
|
||||
void cpuworker_free_all(void);
|
||||
void cpuworkers_rotate_keyinfo(void);
|
||||
|
||||
void cpuworker_consensus_has_changed(const networkstatus_t *ns);
|
||||
|
||||
struct workqueue_entry_t;
|
||||
enum workqueue_reply_t;
|
||||
enum workqueue_priority_t;
|
||||
MOCK_DECL(struct workqueue_entry_t *, cpuworker_queue_work, (
|
||||
enum workqueue_priority_t priority,
|
||||
enum workqueue_reply_t (*fn)(void *, void *),
|
||||
void (*reply_fn)(void *),
|
||||
void *arg));
|
||||
|
||||
struct create_cell_t;
|
||||
int assign_onionskin_to_cpuworker(or_circuit_t *circ,
|
||||
struct create_cell_t *onionskin);
|
||||
|
||||
uint64_t estimated_usec_for_onionskins(uint32_t n_requests,
|
||||
uint16_t onionskin_type);
|
||||
void cpuworker_log_onionskin_overhead(int severity, int onionskin_type,
|
||||
const char *onionskin_type_name);
|
||||
void cpuworker_cancel_circ_handshake(or_circuit_t *circ);
|
||||
|
||||
unsigned int cpuworker_get_n_threads(void);
|
||||
|
||||
#endif /* !defined(TOR_CPUWORKER_H) */
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file mainloop.h
|
||||
* \brief Header file for mainloop.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_MAINLOOP_H
|
||||
#define TOR_MAINLOOP_H
|
||||
|
||||
int have_completed_a_circuit(void);
|
||||
void note_that_we_completed_a_circuit(void);
|
||||
void note_that_we_maybe_cant_complete_circuits(void);
|
||||
|
||||
int connection_add_impl(connection_t *conn, int is_connecting);
|
||||
#define connection_add(conn) connection_add_impl((conn), 0)
|
||||
#define connection_add_connecting(conn) connection_add_impl((conn), 1)
|
||||
int connection_remove(connection_t *conn);
|
||||
void connection_unregister_events(connection_t *conn);
|
||||
int connection_in_array(connection_t *conn);
|
||||
void add_connection_to_closeable_list(connection_t *conn);
|
||||
int connection_is_on_closeable_list(connection_t *conn);
|
||||
|
||||
MOCK_DECL(smartlist_t *, get_connection_array, (void));
|
||||
MOCK_DECL(uint64_t,get_bytes_read,(void));
|
||||
MOCK_DECL(uint64_t,get_bytes_written,(void));
|
||||
void stats_increment_bytes_read_and_written(uint64_t r, uint64_t w);
|
||||
|
||||
/** Bitmask for events that we can turn on and off with
|
||||
* connection_watch_events. */
|
||||
typedef enum watchable_events {
|
||||
/* Yes, it is intentional that these match Libevent's EV_READ and EV_WRITE */
|
||||
READ_EVENT=0x02, /**< We want to know when a connection is readable */
|
||||
WRITE_EVENT=0x04 /**< We want to know when a connection is writable */
|
||||
} watchable_events_t;
|
||||
void connection_watch_events(connection_t *conn, watchable_events_t events);
|
||||
int connection_is_reading(const connection_t *conn);
|
||||
MOCK_DECL(void,connection_stop_reading,(connection_t *conn));
|
||||
MOCK_DECL(void,connection_start_reading,(connection_t *conn));
|
||||
|
||||
int connection_is_writing(connection_t *conn);
|
||||
MOCK_DECL(void,connection_stop_writing,(connection_t *conn));
|
||||
MOCK_DECL(void,connection_start_writing,(connection_t *conn));
|
||||
|
||||
void tor_shutdown_event_loop_and_exit(int exitcode);
|
||||
int tor_event_loop_shutdown_is_pending(void);
|
||||
|
||||
void connection_stop_reading_from_linked_conn(connection_t *conn);
|
||||
|
||||
MOCK_DECL(int, connection_count_moribund, (void));
|
||||
|
||||
void directory_all_unreachable(time_t now);
|
||||
void directory_info_has_arrived(time_t now, int from_cache, int suppress_logs);
|
||||
|
||||
void ip_address_changed(int on_client_conn);
|
||||
void dns_servers_relaunch_checks(void);
|
||||
void reset_all_main_loop_timers(void);
|
||||
void reschedule_directory_downloads(void);
|
||||
void reschedule_or_state_save(void);
|
||||
void mainloop_schedule_postloop_cleanup(void);
|
||||
void rescan_periodic_events(const or_options_t *options);
|
||||
MOCK_DECL(void, schedule_rescan_periodic_events,(void));
|
||||
|
||||
void update_current_time(time_t now);
|
||||
|
||||
MOCK_DECL(long,get_uptime,(void));
|
||||
MOCK_DECL(void,reset_uptime,(void));
|
||||
|
||||
unsigned get_signewnym_epoch(void);
|
||||
|
||||
int do_main_loop(void);
|
||||
|
||||
void reset_main_loop_counters(void);
|
||||
uint64_t get_main_loop_success_count(void);
|
||||
uint64_t get_main_loop_error_count(void);
|
||||
uint64_t get_main_loop_idle_count(void);
|
||||
|
||||
void periodic_events_on_new_options(const or_options_t *options);
|
||||
|
||||
void do_signewnym(time_t);
|
||||
time_t get_last_signewnym_time(void);
|
||||
|
||||
void mainloop_schedule_shutdown(int delay_sec);
|
||||
|
||||
void tor_init_connection_lists(void);
|
||||
void initialize_mainloop_events(void);
|
||||
void initialize_periodic_events(void);
|
||||
void tor_mainloop_free_all(void);
|
||||
|
||||
struct token_bucket_rw_t;
|
||||
|
||||
extern time_t time_of_process_start;
|
||||
extern struct token_bucket_rw_t global_bucket;
|
||||
extern struct token_bucket_rw_t global_relayed_bucket;
|
||||
|
||||
#ifdef MAINLOOP_PRIVATE
|
||||
STATIC int run_main_loop_until_done(void);
|
||||
STATIC void close_closeable_connections(void);
|
||||
STATIC void teardown_periodic_events(void);
|
||||
STATIC int get_my_roles(const or_options_t *);
|
||||
STATIC int check_network_participation_callback(time_t now,
|
||||
const or_options_t *options);
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
extern smartlist_t *connection_array;
|
||||
|
||||
/* We need the periodic_event_item_t definition. */
|
||||
#include "core/mainloop/periodic.h"
|
||||
extern periodic_event_item_t mainloop_periodic_events[];
|
||||
#endif /* defined(TOR_UNIT_TESTS) */
|
||||
#endif /* defined(MAINLOOP_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_MAINLOOP_H) */
|
||||
@@ -0,0 +1,61 @@
|
||||
/* Copyright (c) 2001, Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file mainloop_pubsub.h
|
||||
* @brief Header for mainloop_pubsub.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_MAINLOOP_PUBSUB_H
|
||||
#define TOR_MAINLOOP_PUBSUB_H
|
||||
|
||||
struct pubsub_builder_t;
|
||||
|
||||
/**
|
||||
* Describe when and how messages are delivered on message channel.
|
||||
*
|
||||
* Every message channel must be associated with one of these strategies.
|
||||
**/
|
||||
typedef enum {
|
||||
/**
|
||||
* Never deliver messages automatically.
|
||||
*
|
||||
* If a message channel uses this strategy, then no matter now many
|
||||
* messages are published on it, they are not delivered until something
|
||||
* manually calls dispatch_flush() for that channel
|
||||
**/
|
||||
DELIV_NEVER=0,
|
||||
/**
|
||||
* Deliver messages promptly, via the event loop.
|
||||
*
|
||||
* If a message channel uses this strategy, then publishing a messages
|
||||
* that channel activates an event that causes messages to be handled
|
||||
* later in the mainloop. The messages will be processed at some point
|
||||
* very soon, delaying only for pending IO events and the like.
|
||||
*
|
||||
* Generally this is the best choice for a delivery strategy, since
|
||||
* it avoids stack explosion.
|
||||
**/
|
||||
DELIV_PROMPT,
|
||||
/**
|
||||
* Deliver messages immediately, skipping the event loop.
|
||||
*
|
||||
* Every event on this channel is flushed immediately after it is queued,
|
||||
* using the stack.
|
||||
*
|
||||
* This delivery type should be used with caution, since it can cause
|
||||
* unexpected call chains, resource starvation, and the like.
|
||||
**/
|
||||
DELIV_IMMEDIATE,
|
||||
} deliv_strategy_t;
|
||||
|
||||
int tor_mainloop_connect_pubsub(struct pubsub_builder_t *builder);
|
||||
void tor_mainloop_connect_pubsub_events(void);
|
||||
int tor_mainloop_set_delivery_strategy(const char *msg_channel_name,
|
||||
deliv_strategy_t strategy);
|
||||
void tor_mainloop_disconnect_pubsub(void);
|
||||
|
||||
#endif /* !defined(TOR_MAINLOOP_PUBSUB_H) */
|
||||
@@ -0,0 +1,23 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file mainloop_state_st.h
|
||||
* @brief Declare a state structure for mainloop-relevant fields
|
||||
**/
|
||||
|
||||
#ifndef TOR_CORE_MAINLOOP_MAINLOOP_STATE_ST_H
|
||||
#define TOR_CORE_MAINLOOP_MAINLOOP_STATE_ST_H
|
||||
|
||||
#include "lib/conf/confdecl.h"
|
||||
|
||||
#define CONF_CONTEXT STRUCT
|
||||
#include "core/mainloop/mainloop_state.inc"
|
||||
#undef CONF_CONTEXT
|
||||
|
||||
typedef struct mainloop_state_t mainloop_state_t;
|
||||
|
||||
#endif /* !defined(TOR_CORE_MAINLOOP_MAINLOOP_STATE_ST_H) */
|
||||
@@ -0,0 +1,17 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file mainloop_sys.h
|
||||
* @brief Header for mainloop_sys.c
|
||||
**/
|
||||
|
||||
#ifndef MAINLOOP_SYS_H
|
||||
#define MAINLOOP_SYS_H
|
||||
|
||||
extern const struct subsys_fns_t sys_mainloop;
|
||||
|
||||
#endif /* !defined(MAINLOOP_SYS_H) */
|
||||
@@ -0,0 +1,32 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file netstatus.h
|
||||
* @brief Header for netstatus.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_NETSTATUS_H
|
||||
#define TOR_NETSTATUS_H
|
||||
|
||||
int net_is_disabled(void);
|
||||
int net_is_completely_disabled(void);
|
||||
|
||||
void note_user_activity(time_t now);
|
||||
void reset_user_activity(time_t now);
|
||||
time_t get_last_user_activity_time(void);
|
||||
|
||||
void set_network_participation(bool participation);
|
||||
bool is_participating_on_network(void);
|
||||
|
||||
struct mainloop_state_t;
|
||||
|
||||
void netstatus_flush_to_state(struct mainloop_state_t *state, time_t now);
|
||||
void netstatus_load_from_state(const struct mainloop_state_t *state,
|
||||
time_t now);
|
||||
void netstatus_note_clock_jumped(time_t seconds_diff);
|
||||
|
||||
#endif /* !defined(TOR_NETSTATUS_H) */
|
||||
@@ -0,0 +1,109 @@
|
||||
/* Copyright (c) 2015-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file periodic.h
|
||||
* @brief Header for periodic.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_PERIODIC_H
|
||||
#define TOR_PERIODIC_H
|
||||
|
||||
#define PERIODIC_EVENT_NO_UPDATE (-1)
|
||||
|
||||
/* Tor roles for which a periodic event item is for. An event can be for
|
||||
* multiple roles, they can be combined. */
|
||||
#define PERIODIC_EVENT_ROLE_CLIENT (1U << 0)
|
||||
#define PERIODIC_EVENT_ROLE_RELAY (1U << 1)
|
||||
#define PERIODIC_EVENT_ROLE_BRIDGE (1U << 2)
|
||||
#define PERIODIC_EVENT_ROLE_DIRAUTH (1U << 3)
|
||||
#define PERIODIC_EVENT_ROLE_BRIDGEAUTH (1U << 4)
|
||||
#define PERIODIC_EVENT_ROLE_HS_SERVICE (1U << 5)
|
||||
#define PERIODIC_EVENT_ROLE_DIRSERVER (1U << 6)
|
||||
#define PERIODIC_EVENT_ROLE_CONTROLEV (1U << 7)
|
||||
|
||||
#define PERIODIC_EVENT_ROLE_NET_PARTICIPANT (1U << 8)
|
||||
#define PERIODIC_EVENT_ROLE_ALL (1U << 9)
|
||||
|
||||
/* Helper macro to make it a bit less annoying to defined groups of roles that
|
||||
* are often used. */
|
||||
|
||||
/* Router that is a Bridge or Relay. */
|
||||
#define PERIODIC_EVENT_ROLE_ROUTER \
|
||||
(PERIODIC_EVENT_ROLE_BRIDGE | PERIODIC_EVENT_ROLE_RELAY)
|
||||
/* Authorities that is both bridge and directory. */
|
||||
#define PERIODIC_EVENT_ROLE_AUTHORITIES \
|
||||
(PERIODIC_EVENT_ROLE_BRIDGEAUTH | PERIODIC_EVENT_ROLE_DIRAUTH)
|
||||
|
||||
/*
|
||||
* Event flags which can change the behavior of an event.
|
||||
*/
|
||||
|
||||
/* Indicate that the event needs the network meaning that if we are in
|
||||
* DisableNetwork or hibernation mode, the event won't be enabled. This obey
|
||||
* the net_is_disabled() check. */
|
||||
#define PERIODIC_EVENT_FLAG_NEED_NET (1U << 0)
|
||||
|
||||
/* Indicate that if the event is enabled, it needs to be run once before
|
||||
* it becomes disabled.
|
||||
*/
|
||||
#define PERIODIC_EVENT_FLAG_RUN_ON_DISABLE (1U << 1)
|
||||
|
||||
/** Callback function for a periodic event to take action. The return value
|
||||
* influences the next time the function will get called. Return
|
||||
* PERIODIC_EVENT_NO_UPDATE to not update <b>last_action_time</b> and be polled
|
||||
* again in the next second. If a positive value is returned it will update the
|
||||
* interval time. */
|
||||
typedef int (*periodic_event_helper_t)(time_t now,
|
||||
const or_options_t *options);
|
||||
|
||||
struct mainloop_event_t;
|
||||
|
||||
/** A single item for the periodic-events-function table. */
|
||||
typedef struct periodic_event_item_t {
|
||||
periodic_event_helper_t fn; /**< The function to run the event */
|
||||
time_t last_action_time; /**< The last time the function did something */
|
||||
struct mainloop_event_t *ev; /**< Libevent callback we're using to implement
|
||||
* this */
|
||||
const char *name; /**< Name of the function -- for debug */
|
||||
|
||||
/* Bitmask of roles define above for which this event applies. */
|
||||
uint32_t roles;
|
||||
/* Bitmask of flags which can change the behavior of the event. */
|
||||
uint32_t flags;
|
||||
/* Indicate that this event has been enabled that is scheduled. */
|
||||
unsigned int enabled : 1;
|
||||
} periodic_event_item_t;
|
||||
|
||||
/** events will get their interval from first execution */
|
||||
#ifndef COCCI
|
||||
#define PERIODIC_EVENT(fn, r, f) { fn##_callback, 0, NULL, #fn, r, f, 0 }
|
||||
#define END_OF_PERIODIC_EVENTS { NULL, 0, NULL, NULL, 0, 0, 0 }
|
||||
#endif
|
||||
|
||||
/* Return true iff the given event was setup before thus is enabled to be
|
||||
* scheduled. */
|
||||
static inline int
|
||||
periodic_event_is_enabled(const periodic_event_item_t *item)
|
||||
{
|
||||
return item->enabled;
|
||||
}
|
||||
|
||||
void periodic_event_launch(periodic_event_item_t *event);
|
||||
void periodic_event_connect(periodic_event_item_t *event);
|
||||
//void periodic_event_disconnect(periodic_event_item_t *event);
|
||||
void periodic_event_reschedule(periodic_event_item_t *event);
|
||||
void periodic_event_enable(periodic_event_item_t *event);
|
||||
void periodic_event_disable(periodic_event_item_t *event);
|
||||
void periodic_event_schedule_and_disable(periodic_event_item_t *event);
|
||||
|
||||
void periodic_events_register(periodic_event_item_t *item);
|
||||
void periodic_events_connect_all(void);
|
||||
void periodic_events_reset_all(void);
|
||||
periodic_event_item_t *periodic_events_find(const char *name);
|
||||
void periodic_events_rescan_by_roles(int roles, bool net_disabled);
|
||||
void periodic_events_disconnect_all(void);
|
||||
|
||||
int safe_timer_diff(time_t now, time_t next);
|
||||
|
||||
#endif /* !defined(TOR_PERIODIC_H) */
|
||||
@@ -0,0 +1,51 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file addr_policy_st.h
|
||||
* @brief Address policy structures.
|
||||
**/
|
||||
|
||||
#ifndef TOR_ADDR_POLICY_ST_H
|
||||
#define TOR_ADDR_POLICY_ST_H
|
||||
|
||||
#include "lib/cc/torint.h"
|
||||
#include "lib/net/address.h"
|
||||
|
||||
/** What action type does an address policy indicate: accept or reject? */
|
||||
typedef enum {
|
||||
ADDR_POLICY_ACCEPT=1,
|
||||
ADDR_POLICY_REJECT=2,
|
||||
} addr_policy_action_t;
|
||||
#define addr_policy_action_bitfield_t ENUM_BF(addr_policy_action_t)
|
||||
|
||||
/** A reference-counted address policy rule. */
|
||||
struct addr_policy_t {
|
||||
int refcnt; /**< Reference count */
|
||||
/** What to do when the policy matches.*/
|
||||
addr_policy_action_bitfield_t policy_type:2;
|
||||
unsigned int is_private:1; /**< True iff this is the pseudo-address,
|
||||
* "private". */
|
||||
unsigned int is_canonical:1; /**< True iff this policy is the canonical
|
||||
* copy (stored in a hash table to avoid
|
||||
* duplication of common policies) */
|
||||
maskbits_t maskbits; /**< Accept/reject all addresses <b>a</b> such that the
|
||||
* first <b>maskbits</b> bits of <b>a</b> match
|
||||
* <b>addr</b>. */
|
||||
/** Base address to accept or reject.
|
||||
*
|
||||
* Note that wildcards are treated
|
||||
* differently depending on address family. An AF_UNSPEC address means
|
||||
* "All addresses, IPv4 or IPv6." An AF_INET address with maskbits==0 means
|
||||
* "All IPv4 addresses" and an AF_INET6 address with maskbits == 0 means
|
||||
* "All IPv6 addresses".
|
||||
**/
|
||||
tor_addr_t addr;
|
||||
uint16_t prt_min; /**< Lowest port number to accept/reject. */
|
||||
uint16_t prt_max; /**< Highest port number to accept/reject. */
|
||||
};
|
||||
|
||||
#endif /* !defined(TOR_ADDR_POLICY_ST_H) */
|
||||
@@ -0,0 +1,32 @@
|
||||
/* Copyright (c) 2018-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file address_set.h
|
||||
* \brief Types to handle sets of addresses.
|
||||
**/
|
||||
|
||||
#ifndef TOR_ADDRESS_SET_H
|
||||
#define TOR_ADDRESS_SET_H
|
||||
|
||||
#include "orconfig.h"
|
||||
#include "lib/cc/torint.h"
|
||||
#include "lib/container/bloomfilt.h"
|
||||
|
||||
struct tor_addr_t;
|
||||
|
||||
/**
|
||||
* An address_set_t represents a set of tor_addr_t values. The implementation
|
||||
* is probabilistic: false negatives cannot occur but false positives are
|
||||
* possible.
|
||||
*/
|
||||
typedef struct bloomfilt_t address_set_t;
|
||||
|
||||
address_set_t *address_set_new(int max_addresses_guess);
|
||||
#define address_set_free(set) bloomfilt_free(set)
|
||||
void address_set_add(address_set_t *set, const struct tor_addr_t *addr);
|
||||
void address_set_add_ipv4h(address_set_t *set, uint32_t addr);
|
||||
int address_set_probably_contains(const address_set_t *set,
|
||||
const struct tor_addr_t *addr);
|
||||
|
||||
#endif /* !defined(TOR_ADDRESS_SET_H) */
|
||||
@@ -0,0 +1,34 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file cell_queue_st.h
|
||||
* @brief Cell queue structures
|
||||
**/
|
||||
|
||||
#ifndef PACKED_CELL_ST_H
|
||||
#define PACKED_CELL_ST_H
|
||||
|
||||
#include "tor_queue.h"
|
||||
|
||||
/** A cell as packed for writing to the network. */
|
||||
struct packed_cell_t {
|
||||
/** Next cell queued on this circuit. */
|
||||
TOR_SIMPLEQ_ENTRY(packed_cell_t) next;
|
||||
char body[CELL_MAX_NETWORK_SIZE]; /**< Cell as packed for network. */
|
||||
uint32_t inserted_timestamp; /**< Time (in timestamp units) when this cell
|
||||
* was inserted */
|
||||
};
|
||||
|
||||
/** A queue of cells on a circuit, waiting to be added to the
|
||||
* or_connection_t's outbuf. */
|
||||
struct cell_queue_t {
|
||||
/** Linked list of packed_cell_t*/
|
||||
TOR_SIMPLEQ_HEAD(cell_simpleq_t, packed_cell_t) head;
|
||||
int n; /**< The number of cells in the queue. */
|
||||
};
|
||||
|
||||
#endif /* !defined(PACKED_CELL_ST_H) */
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file cell_st.h
|
||||
* @brief Fixed-size cell structure.
|
||||
**/
|
||||
|
||||
#ifndef CELL_ST_H
|
||||
#define CELL_ST_H
|
||||
|
||||
/** Parsed onion routing cell. All communication between nodes
|
||||
* is via cells. */
|
||||
struct cell_t {
|
||||
circid_t circ_id; /**< Circuit which received the cell. */
|
||||
uint8_t command; /**< Type of the cell: one of CELL_PADDING, CELL_CREATE,
|
||||
* CELL_DESTROY, etc */
|
||||
uint8_t payload[CELL_PAYLOAD_SIZE]; /**< Cell body. */
|
||||
};
|
||||
|
||||
#endif /* !defined(CELL_ST_H) */
|
||||
@@ -0,0 +1,775 @@
|
||||
/* * Copyright (c) 2012-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file channel.h
|
||||
* \brief Header file for channel.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_CHANNEL_H
|
||||
#define TOR_CHANNEL_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
#include "core/or/circuitmux.h"
|
||||
#include "lib/container/handles.h"
|
||||
#include "lib/crypt_ops/crypto_ed25519.h"
|
||||
|
||||
#include "ext/ht.h"
|
||||
#include "tor_queue.h"
|
||||
|
||||
#define tor_timer_t timeout
|
||||
struct tor_timer_t;
|
||||
|
||||
/* Channel handler function pointer typedefs */
|
||||
typedef void (*channel_listener_fn_ptr)(channel_listener_t *, channel_t *);
|
||||
typedef void (*channel_cell_handler_fn_ptr)(channel_t *, cell_t *);
|
||||
|
||||
/**
|
||||
* This enum is used by channelpadding to decide when to pad channels.
|
||||
* Don't add values to it without updating the checks in
|
||||
* channelpadding_decide_to_pad_channel().
|
||||
*/
|
||||
typedef enum {
|
||||
CHANNEL_USED_NOT_USED_FOR_FULL_CIRCS = 0,
|
||||
CHANNEL_USED_FOR_FULL_CIRCS,
|
||||
CHANNEL_USED_FOR_USER_TRAFFIC,
|
||||
} channel_usage_info_t;
|
||||
|
||||
/** Possible rules for generating circuit IDs on an OR connection. */
|
||||
typedef enum {
|
||||
CIRC_ID_TYPE_LOWER=0, /**< Pick from 0..1<<15-1. */
|
||||
CIRC_ID_TYPE_HIGHER=1, /**< Pick from 1<<15..1<<16-1. */
|
||||
/** The other side of a connection is an OP: never create circuits to it,
|
||||
* and let it use any circuit ID it wants. */
|
||||
CIRC_ID_TYPE_NEITHER=2
|
||||
} circ_id_type_t;
|
||||
#define circ_id_type_bitfield_t ENUM_BF(circ_id_type_t)
|
||||
|
||||
/* channel states for channel_t */
|
||||
|
||||
typedef enum {
|
||||
/**
|
||||
* Closed state - channel is inactive
|
||||
*
|
||||
* Permitted transitions from:
|
||||
* - CHANNEL_STATE_CLOSING
|
||||
* Permitted transitions to:
|
||||
* - CHANNEL_STATE_OPENING
|
||||
*/
|
||||
CHANNEL_STATE_CLOSED = 0,
|
||||
/**
|
||||
* Opening state - channel is trying to connect
|
||||
*
|
||||
* Permitted transitions from:
|
||||
* - CHANNEL_STATE_CLOSED
|
||||
* Permitted transitions to:
|
||||
* - CHANNEL_STATE_CLOSING
|
||||
* - CHANNEL_STATE_ERROR
|
||||
* - CHANNEL_STATE_OPEN
|
||||
*/
|
||||
CHANNEL_STATE_OPENING,
|
||||
/**
|
||||
* Open state - channel is active and ready for use
|
||||
*
|
||||
* Permitted transitions from:
|
||||
* - CHANNEL_STATE_MAINT
|
||||
* - CHANNEL_STATE_OPENING
|
||||
* Permitted transitions to:
|
||||
* - CHANNEL_STATE_CLOSING
|
||||
* - CHANNEL_STATE_ERROR
|
||||
* - CHANNEL_STATE_MAINT
|
||||
*/
|
||||
CHANNEL_STATE_OPEN,
|
||||
/**
|
||||
* Maintenance state - channel is temporarily offline for subclass specific
|
||||
* maintenance activities such as TLS renegotiation.
|
||||
*
|
||||
* Permitted transitions from:
|
||||
* - CHANNEL_STATE_OPEN
|
||||
* Permitted transitions to:
|
||||
* - CHANNEL_STATE_CLOSING
|
||||
* - CHANNEL_STATE_ERROR
|
||||
* - CHANNEL_STATE_OPEN
|
||||
*/
|
||||
CHANNEL_STATE_MAINT,
|
||||
/**
|
||||
* Closing state - channel is shutting down
|
||||
*
|
||||
* Permitted transitions from:
|
||||
* - CHANNEL_STATE_MAINT
|
||||
* - CHANNEL_STATE_OPEN
|
||||
* Permitted transitions to:
|
||||
* - CHANNEL_STATE_CLOSED,
|
||||
* - CHANNEL_STATE_ERROR
|
||||
*/
|
||||
CHANNEL_STATE_CLOSING,
|
||||
/**
|
||||
* Error state - channel has experienced a permanent error
|
||||
*
|
||||
* Permitted transitions from:
|
||||
* - CHANNEL_STATE_CLOSING
|
||||
* - CHANNEL_STATE_MAINT
|
||||
* - CHANNEL_STATE_OPENING
|
||||
* - CHANNEL_STATE_OPEN
|
||||
* Permitted transitions to:
|
||||
* - None
|
||||
*/
|
||||
CHANNEL_STATE_ERROR,
|
||||
/**
|
||||
* Placeholder for maximum state value
|
||||
*/
|
||||
CHANNEL_STATE_LAST
|
||||
} channel_state_t;
|
||||
|
||||
/* channel listener states for channel_listener_t */
|
||||
|
||||
typedef enum {
|
||||
/**
|
||||
* Closed state - channel listener is inactive
|
||||
*
|
||||
* Permitted transitions from:
|
||||
* - CHANNEL_LISTENER_STATE_CLOSING
|
||||
* Permitted transitions to:
|
||||
* - CHANNEL_LISTENER_STATE_LISTENING
|
||||
*/
|
||||
CHANNEL_LISTENER_STATE_CLOSED = 0,
|
||||
/**
|
||||
* Listening state - channel listener is listening for incoming
|
||||
* connections
|
||||
*
|
||||
* Permitted transitions from:
|
||||
* - CHANNEL_LISTENER_STATE_CLOSED
|
||||
* Permitted transitions to:
|
||||
* - CHANNEL_LISTENER_STATE_CLOSING
|
||||
* - CHANNEL_LISTENER_STATE_ERROR
|
||||
*/
|
||||
CHANNEL_LISTENER_STATE_LISTENING,
|
||||
/**
|
||||
* Closing state - channel listener is shutting down
|
||||
*
|
||||
* Permitted transitions from:
|
||||
* - CHANNEL_LISTENER_STATE_LISTENING
|
||||
* Permitted transitions to:
|
||||
* - CHANNEL_LISTENER_STATE_CLOSED,
|
||||
* - CHANNEL_LISTENER_STATE_ERROR
|
||||
*/
|
||||
CHANNEL_LISTENER_STATE_CLOSING,
|
||||
/**
|
||||
* Error state - channel listener has experienced a permanent error
|
||||
*
|
||||
* Permitted transitions from:
|
||||
* - CHANNEL_STATE_CLOSING
|
||||
* - CHANNEL_STATE_LISTENING
|
||||
* Permitted transitions to:
|
||||
* - None
|
||||
*/
|
||||
CHANNEL_LISTENER_STATE_ERROR,
|
||||
/**
|
||||
* Placeholder for maximum state value
|
||||
*/
|
||||
CHANNEL_LISTENER_STATE_LAST
|
||||
} channel_listener_state_t;
|
||||
|
||||
/**
|
||||
* Channel struct; see the channel_t typedef in or.h. A channel is an
|
||||
* abstract interface for the OR-to-OR connection, similar to connection_or_t,
|
||||
* but without the strong coupling to the underlying TLS implementation. They
|
||||
* are constructed by calling a protocol-specific function to open a channel
|
||||
* to a particular node, and once constructed support the abstract operations
|
||||
* defined below.
|
||||
*/
|
||||
struct channel_t {
|
||||
/** Magic number for type-checking cast macros */
|
||||
uint32_t magic;
|
||||
|
||||
/** List entry for hashtable for global-identifier lookup. */
|
||||
HT_ENTRY(channel_t) gidmap_node;
|
||||
|
||||
/** Handle entry for handle-based lookup */
|
||||
HANDLE_ENTRY(channel, channel_t);
|
||||
|
||||
/** Current channel state */
|
||||
channel_state_t state;
|
||||
|
||||
/** Globally unique ID number for a channel over the lifetime of a Tor
|
||||
* process. This may not be 0.
|
||||
*/
|
||||
uint64_t global_identifier;
|
||||
|
||||
/** Should we expect to see this channel in the channel lists? */
|
||||
unsigned char registered:1;
|
||||
|
||||
/** has this channel ever been open? */
|
||||
unsigned int has_been_open:1;
|
||||
|
||||
/**
|
||||
* This field indicates if the other side has enabled or disabled
|
||||
* padding via either the link protocol version or
|
||||
* channelpadding_negotiate cells.
|
||||
*
|
||||
* Clients can override this with ConnectionPadding in torrc to
|
||||
* disable or force padding to relays, but relays cannot override the
|
||||
* client's request.
|
||||
*/
|
||||
unsigned int padding_enabled:1;
|
||||
|
||||
/** Cached value of our decision to pad (to avoid expensive
|
||||
* checks during critical path statistics counting). */
|
||||
unsigned int currently_padding:1;
|
||||
|
||||
/** Is there a pending netflow padding callback? */
|
||||
unsigned int pending_padding_callback:1;
|
||||
|
||||
/** Is our peer likely to consider this channel canonical? */
|
||||
unsigned int is_canonical_to_peer:1;
|
||||
|
||||
/** Has this channel ever been used for non-directory traffic?
|
||||
* Used to decide what channels to pad, and when. */
|
||||
channel_usage_info_t channel_usage;
|
||||
|
||||
/** When should we send a cell for netflow padding? 0 means no padding is
|
||||
* scheduled. */
|
||||
monotime_coarse_t next_padding_time;
|
||||
|
||||
/** The callback pointer for the padding callbacks */
|
||||
struct tor_timer_t *padding_timer;
|
||||
/** The handle to this channel (to free on canceled timers) */
|
||||
struct channel_handle_t *timer_handle;
|
||||
|
||||
/** If not UNSPEC, the address that the peer says we have. */
|
||||
tor_addr_t addr_according_to_peer;
|
||||
|
||||
/**
|
||||
* These two fields specify the minimum and maximum negotiated timeout
|
||||
* values for inactivity (send or receive) before we decide to pad a
|
||||
* channel. These fields can be set either via a PADDING_NEGOTIATE cell,
|
||||
* or the torrc option ReducedConnectionPadding. The consensus parameters
|
||||
* nf_ito_low and nf_ito_high are used to ensure that padding can only be
|
||||
* negotiated to be less frequent than what is specified in the consensus.
|
||||
* (This is done to prevent wingnut clients from requesting excessive
|
||||
* padding).
|
||||
*
|
||||
* The actual timeout value is randomly chosen between these two values
|
||||
* as per the table in channelpadding_get_netflow_inactive_timeout_ms(),
|
||||
* after ensuring that these values do not specify lower timeouts than
|
||||
* the consensus parameters.
|
||||
*
|
||||
* If these are 0, we have not negotiated or specified custom padding
|
||||
* times, and instead use consensus defaults. */
|
||||
uint16_t padding_timeout_low_ms;
|
||||
uint16_t padding_timeout_high_ms;
|
||||
|
||||
/** Why did we close?
|
||||
*/
|
||||
enum {
|
||||
CHANNEL_NOT_CLOSING = 0,
|
||||
CHANNEL_CLOSE_REQUESTED,
|
||||
CHANNEL_CLOSE_FROM_BELOW,
|
||||
CHANNEL_CLOSE_FOR_ERROR
|
||||
} reason_for_closing;
|
||||
|
||||
/** State variable for use by the scheduler */
|
||||
enum {
|
||||
/**
|
||||
* The channel is not open, or it has a full output buffer but no queued
|
||||
* cells.
|
||||
*/
|
||||
SCHED_CHAN_IDLE = 0,
|
||||
/**
|
||||
* The channel has space on its output buffer to write, but no queued
|
||||
* cells.
|
||||
*/
|
||||
SCHED_CHAN_WAITING_FOR_CELLS,
|
||||
/**
|
||||
* The scheduler has queued cells but no output buffer space to write.
|
||||
*/
|
||||
SCHED_CHAN_WAITING_TO_WRITE,
|
||||
/**
|
||||
* The scheduler has both queued cells and output buffer space, and is
|
||||
* eligible for the scheduler loop.
|
||||
*/
|
||||
SCHED_CHAN_PENDING
|
||||
} scheduler_state;
|
||||
|
||||
/** Heap index for use by the scheduler */
|
||||
int sched_heap_idx;
|
||||
|
||||
/** Timestamps for both cell channels and listeners */
|
||||
time_t timestamp_created; /* Channel created */
|
||||
time_t timestamp_active; /* Any activity */
|
||||
|
||||
/**
|
||||
* This is a monotonic timestamp that marks when we
|
||||
* believe the channel has actually sent or received data to/from
|
||||
* the wire. Right now, it is used to determine when we should send
|
||||
* a padding cell for channelpadding.
|
||||
*
|
||||
* XXX: Are we setting timestamp_xfer_ms in the right places to
|
||||
* accurately reflect actual network data transfer? Or might this be
|
||||
* very wrong wrt when bytes actually go on the wire?
|
||||
*/
|
||||
monotime_coarse_t timestamp_xfer;
|
||||
|
||||
/* Methods implemented by the lower layer */
|
||||
|
||||
/** Free a channel */
|
||||
void (*free_fn)(channel_t *);
|
||||
/** Close an open channel */
|
||||
void (*close)(channel_t *);
|
||||
/** Describe the transport subclass for this channel */
|
||||
const char * (*describe_transport)(channel_t *);
|
||||
/** Optional method to dump transport-specific statistics on the channel */
|
||||
void (*dumpstats)(channel_t *, int);
|
||||
|
||||
/** Registered handlers for incoming cells */
|
||||
channel_cell_handler_fn_ptr cell_handler;
|
||||
|
||||
/* Methods implemented by the lower layer */
|
||||
|
||||
/**
|
||||
* Ask the lower layer for an estimate of the average overhead for
|
||||
* transmissions on this channel.
|
||||
*/
|
||||
double (*get_overhead_estimate)(channel_t *);
|
||||
/*
|
||||
* Ask the underlying transport what the remote endpoint address is, in a
|
||||
* tor_addr_t. Write the address out to the provided tor_addr_t *, and
|
||||
* return 1 if successful or 0 if no address available.
|
||||
*/
|
||||
int (*get_remote_addr)(const channel_t *, tor_addr_t *);
|
||||
int (*get_transport_name)(channel_t *chan, char **transport_out);
|
||||
|
||||
/**
|
||||
* Get a human-readable text description of the remote endpoint, for
|
||||
* logging.
|
||||
*/
|
||||
const char * (*describe_peer)(const channel_t *);
|
||||
/** Check if the lower layer has queued writes */
|
||||
int (*has_queued_writes)(channel_t *);
|
||||
/**
|
||||
* Ask the lower layer if this is 'canonical', for a transport-specific
|
||||
* definition of canonical.
|
||||
*/
|
||||
int (*is_canonical)(channel_t *);
|
||||
/** Check if this channel matches a specified extend_info_t */
|
||||
int (*matches_extend_info)(channel_t *, extend_info_t *);
|
||||
/** Check if this channel matches a target address when extending */
|
||||
int (*matches_target)(channel_t *, const tor_addr_t *);
|
||||
/* Ask the lower layer how many bytes it has queued but not yet sent */
|
||||
size_t (*num_bytes_queued)(channel_t *);
|
||||
/* Ask the lower layer how many cells can be written */
|
||||
int (*num_cells_writeable)(channel_t *);
|
||||
/* Write a cell to an open channel */
|
||||
int (*write_cell)(channel_t *, cell_t *);
|
||||
/** Write a packed cell to an open channel */
|
||||
int (*write_packed_cell)(channel_t *, packed_cell_t *);
|
||||
/** Write a variable-length cell to an open channel */
|
||||
int (*write_var_cell)(channel_t *, var_cell_t *);
|
||||
|
||||
/**
|
||||
* Hash of the public RSA key for the other side's RSA identity key -- or
|
||||
* zeroes if we don't have an RSA identity in mind for the other side, and
|
||||
* it hasn't shown us one.
|
||||
*
|
||||
* Note that this is the RSA identity that we hope the other side has -- not
|
||||
* necessarily its true identity. Don't believe this identity unless
|
||||
* authentication has happened.
|
||||
*/
|
||||
char identity_digest[DIGEST_LEN];
|
||||
/**
|
||||
* Ed25519 key for the other side of this channel -- or zeroes if we don't
|
||||
* have an Ed25519 identity in mind for the other side, and it hasn't shown
|
||||
* us one.
|
||||
*
|
||||
* Note that this is the identity that we hope the other side has -- not
|
||||
* necessarily its true identity. Don't believe this identity unless
|
||||
* authentication has happened.
|
||||
*/
|
||||
struct ed25519_public_key_t ed25519_identity;
|
||||
|
||||
/**
|
||||
* Linked list of channels with the same RSA identity digest, for use with
|
||||
* the digest->channel map
|
||||
*/
|
||||
TOR_LIST_ENTRY(channel_t) next_with_same_id;
|
||||
|
||||
/** Circuit mux for circuits sending on this channel */
|
||||
circuitmux_t *cmux;
|
||||
|
||||
/** Circuit ID generation stuff for use by circuitbuild.c */
|
||||
|
||||
/**
|
||||
* When we send CREATE cells along this connection, which half of the
|
||||
* space should we use?
|
||||
*/
|
||||
circ_id_type_bitfield_t circ_id_type:2;
|
||||
/* DOCDOC */
|
||||
unsigned wide_circ_ids:1;
|
||||
|
||||
/** For how many circuits are we n_chan? What about p_chan? */
|
||||
unsigned int num_n_circuits, num_p_circuits;
|
||||
|
||||
/**
|
||||
* True iff this channel shouldn't get any new circs attached to it,
|
||||
* because the connection is too old, or because there's a better one.
|
||||
* More generally, this flag is used to note an unhealthy connection;
|
||||
* for example, if a bad connection fails we shouldn't assume that the
|
||||
* router itself has a problem.
|
||||
*/
|
||||
unsigned int is_bad_for_new_circs:1;
|
||||
|
||||
/** True iff we have decided that the other end of this connection
|
||||
* is a client or bridge relay. Connections with this flag set should never
|
||||
* be used to satisfy an EXTEND request. */
|
||||
unsigned int is_client:1;
|
||||
|
||||
/** Set if the channel was initiated remotely (came from a listener) */
|
||||
unsigned int is_incoming:1;
|
||||
|
||||
/** Set by lower layer if this is local; i.e., everything it communicates
|
||||
* with for this channel returns true for is_local_addr(). This is used
|
||||
* to decide whether to declare reachability when we receive something on
|
||||
* this channel in circuitbuild.c
|
||||
*/
|
||||
unsigned int is_local:1;
|
||||
|
||||
/** Have we logged a warning about circID exhaustion on this channel?
|
||||
* If so, when? */
|
||||
ratelim_t last_warned_circ_ids_exhausted;
|
||||
|
||||
/** Channel timestamps for cell channels */
|
||||
time_t timestamp_client; /*(< Client used this, according to relay.c */
|
||||
time_t timestamp_recv; /**< Cell received from lower layer */
|
||||
time_t timestamp_xmit; /**< Cell sent to lower layer */
|
||||
|
||||
/** Timestamp for run_connection_housekeeping(). We update this once a
|
||||
* second when we run housekeeping and find a circuit on this channel, and
|
||||
* whenever we add a circuit to the channel. */
|
||||
time_t timestamp_last_had_circuits;
|
||||
|
||||
/** Unique ID for measuring direct network status requests;vtunneled ones
|
||||
* come over a circuit_t, which has a dirreq_id field as well, but is a
|
||||
* distinct namespace. */
|
||||
uint64_t dirreq_id;
|
||||
|
||||
/** Channel counters for cells and bytes we have received. */
|
||||
uint64_t n_cells_recved, n_bytes_recved;
|
||||
/** Channel counters for cells and bytes we have sent. */
|
||||
uint64_t n_cells_xmitted, n_bytes_xmitted;
|
||||
};
|
||||
|
||||
struct channel_listener_t {
|
||||
/** Current channel listener state */
|
||||
channel_listener_state_t state;
|
||||
|
||||
/** Globally unique ID number for a channel over the lifetime of a Tor
|
||||
* process.
|
||||
*/
|
||||
uint64_t global_identifier;
|
||||
|
||||
/** Should we expect to see this channel in the channel lists? */
|
||||
unsigned char registered:1;
|
||||
|
||||
/** Why did we close?
|
||||
*/
|
||||
enum {
|
||||
CHANNEL_LISTENER_NOT_CLOSING = 0,
|
||||
CHANNEL_LISTENER_CLOSE_REQUESTED,
|
||||
CHANNEL_LISTENER_CLOSE_FROM_BELOW,
|
||||
CHANNEL_LISTENER_CLOSE_FOR_ERROR
|
||||
} reason_for_closing;
|
||||
|
||||
/** Timestamps for both cell channels and listeners */
|
||||
time_t timestamp_created; /* Channel created */
|
||||
time_t timestamp_active; /* Any activity */
|
||||
|
||||
/* Methods implemented by the lower layer */
|
||||
|
||||
/** Free a channel */
|
||||
void (*free_fn)(channel_listener_t *);
|
||||
/** Close an open channel */
|
||||
void (*close)(channel_listener_t *);
|
||||
/** Describe the transport subclass for this channel */
|
||||
const char * (*describe_transport)(channel_listener_t *);
|
||||
/** Optional method to dump transport-specific statistics on the channel */
|
||||
void (*dumpstats)(channel_listener_t *, int);
|
||||
|
||||
/** Registered listen handler to call on incoming connection */
|
||||
channel_listener_fn_ptr listener;
|
||||
|
||||
/** List of pending incoming connections */
|
||||
smartlist_t *incoming_list;
|
||||
|
||||
/** Timestamps for listeners */
|
||||
time_t timestamp_accepted;
|
||||
|
||||
/** Counters for listeners */
|
||||
uint64_t n_accepted;
|
||||
};
|
||||
|
||||
/* Channel state manipulations */
|
||||
|
||||
int channel_state_is_valid(channel_state_t state);
|
||||
int channel_listener_state_is_valid(channel_listener_state_t state);
|
||||
|
||||
int channel_state_can_transition(channel_state_t from, channel_state_t to);
|
||||
int channel_listener_state_can_transition(channel_listener_state_t from,
|
||||
channel_listener_state_t to);
|
||||
|
||||
const char * channel_state_to_string(channel_state_t state);
|
||||
const char *
|
||||
channel_listener_state_to_string(channel_listener_state_t state);
|
||||
|
||||
/* Abstract channel operations */
|
||||
|
||||
void channel_mark_for_close(channel_t *chan);
|
||||
int channel_write_packed_cell(channel_t *chan, packed_cell_t *cell);
|
||||
|
||||
void channel_listener_mark_for_close(channel_listener_t *chan_l);
|
||||
void channel_mark_as_used_for_origin_circuit(channel_t *chan);
|
||||
|
||||
/* Channel callback registrations */
|
||||
|
||||
/* Listener callback */
|
||||
void channel_listener_set_listener_fn(channel_listener_t *chan,
|
||||
channel_listener_fn_ptr listener);
|
||||
|
||||
/* Incoming cell callbacks */
|
||||
channel_cell_handler_fn_ptr channel_get_cell_handler(channel_t *chan);
|
||||
|
||||
void channel_set_cell_handlers(channel_t *chan,
|
||||
channel_cell_handler_fn_ptr cell_handler);
|
||||
|
||||
/* Clean up closed channels and channel listeners periodically; these are
|
||||
* called from run_scheduled_events() in main.c.
|
||||
*/
|
||||
void channel_run_cleanup(void);
|
||||
void channel_listener_run_cleanup(void);
|
||||
|
||||
/* Close all channels and deallocate everything */
|
||||
void channel_free_all(void);
|
||||
|
||||
/* Dump some statistics in the log */
|
||||
void channel_dumpstats(int severity);
|
||||
void channel_listener_dumpstats(int severity);
|
||||
|
||||
#ifdef CHANNEL_OBJECT_PRIVATE
|
||||
|
||||
#ifdef CHANNEL_FILE_PRIVATE
|
||||
|
||||
STATIC void channel_add_to_digest_map(channel_t *chan);
|
||||
STATIC bool channel_matches_target_addr_for_extend(
|
||||
channel_t *chan,
|
||||
const tor_addr_t *target_ipv4_addr,
|
||||
const tor_addr_t *target_ipv6_addr);
|
||||
#endif /* defined(CHANNEL_FILE_PRIVATE) */
|
||||
|
||||
/* Channel operations for subclasses and internal use only */
|
||||
|
||||
/* Initialize a newly allocated channel - do this first in subclass
|
||||
* constructors.
|
||||
*/
|
||||
|
||||
void channel_init(channel_t *chan);
|
||||
void channel_init_listener(channel_listener_t *chan);
|
||||
|
||||
/* Channel registration/unregistration */
|
||||
void channel_register(channel_t *chan);
|
||||
void channel_unregister(channel_t *chan);
|
||||
|
||||
/* Channel listener registration/unregistration */
|
||||
void channel_listener_register(channel_listener_t *chan_l);
|
||||
void channel_listener_unregister(channel_listener_t *chan_l);
|
||||
|
||||
/* Close from below */
|
||||
void channel_close_from_lower_layer(channel_t *chan);
|
||||
void channel_close_for_error(channel_t *chan);
|
||||
void channel_closed(channel_t *chan);
|
||||
|
||||
/* Free a channel */
|
||||
void channel_free_(channel_t *chan);
|
||||
#define channel_free(chan) FREE_AND_NULL(channel_t, channel_free_, (chan))
|
||||
void channel_listener_free_(channel_listener_t *chan_l);
|
||||
#define channel_listener_free(chan_l) \
|
||||
FREE_AND_NULL(channel_listener_t, channel_listener_free_, (chan_l))
|
||||
|
||||
/* State/metadata setters */
|
||||
|
||||
void channel_change_state(channel_t *chan, channel_state_t to_state);
|
||||
void channel_change_state_open(channel_t *chan);
|
||||
void channel_clear_identity_digest(channel_t *chan);
|
||||
void channel_clear_remote_end(channel_t *chan);
|
||||
void channel_mark_local(channel_t *chan);
|
||||
void channel_mark_incoming(channel_t *chan);
|
||||
void channel_mark_outgoing(channel_t *chan);
|
||||
void channel_mark_remote(channel_t *chan);
|
||||
void channel_set_identity_digest(channel_t *chan,
|
||||
const char *identity_digest,
|
||||
const struct ed25519_public_key_t *ed_identity);
|
||||
|
||||
void channel_listener_change_state(channel_listener_t *chan_l,
|
||||
channel_listener_state_t to_state);
|
||||
|
||||
/* Timestamp updates */
|
||||
void channel_timestamp_created(channel_t *chan);
|
||||
void channel_timestamp_active(channel_t *chan);
|
||||
void channel_timestamp_recv(channel_t *chan);
|
||||
void channel_timestamp_xmit(channel_t *chan);
|
||||
|
||||
void channel_listener_timestamp_created(channel_listener_t *chan_l);
|
||||
void channel_listener_timestamp_active(channel_listener_t *chan_l);
|
||||
void channel_listener_timestamp_accepted(channel_listener_t *chan_l);
|
||||
|
||||
/* Incoming channel handling */
|
||||
void channel_listener_process_incoming(channel_listener_t *listener);
|
||||
void channel_listener_queue_incoming(channel_listener_t *listener,
|
||||
channel_t *incoming);
|
||||
|
||||
/* Incoming cell handling */
|
||||
void channel_process_cell(channel_t *chan, cell_t *cell);
|
||||
|
||||
/* Request from lower layer for more cells if available */
|
||||
MOCK_DECL(ssize_t, channel_flush_some_cells,
|
||||
(channel_t *chan, ssize_t num_cells));
|
||||
|
||||
/* Query if data available on this channel */
|
||||
MOCK_DECL(int, channel_more_to_flush, (channel_t *chan));
|
||||
|
||||
/* Notify flushed outgoing for dirreq handling */
|
||||
void channel_notify_flushed(channel_t *chan);
|
||||
|
||||
/* Handle stuff we need to do on open like notifying circuits */
|
||||
void channel_do_open_actions(channel_t *chan);
|
||||
|
||||
#endif /* defined(CHANNEL_OBJECT_PRIVATE) */
|
||||
|
||||
/* Helper functions to perform operations on channels */
|
||||
|
||||
int channel_send_destroy(circid_t circ_id, channel_t *chan,
|
||||
int reason);
|
||||
|
||||
/*
|
||||
* Outside abstract interfaces that should eventually get turned into
|
||||
* something transport/address format independent.
|
||||
*/
|
||||
|
||||
channel_t * channel_connect(const tor_addr_t *addr, uint16_t port,
|
||||
const char *rsa_id_digest,
|
||||
const struct ed25519_public_key_t *ed_id);
|
||||
|
||||
MOCK_DECL(channel_t *, channel_get_for_extend,(
|
||||
const char *rsa_id_digest,
|
||||
const struct ed25519_public_key_t *ed_id,
|
||||
const tor_addr_t *target_ipv4_addr,
|
||||
const tor_addr_t *target_ipv6_addr,
|
||||
bool for_origin_circ,
|
||||
const char **msg_out,
|
||||
int *launch_out));
|
||||
|
||||
/* Ask which of two channels is better for circuit-extension purposes */
|
||||
int channel_is_better(channel_t *a, channel_t *b);
|
||||
|
||||
/** Channel lookups
|
||||
*/
|
||||
|
||||
channel_t * channel_find_by_global_id(uint64_t global_identifier);
|
||||
channel_t * channel_find_by_remote_identity(const char *rsa_id_digest,
|
||||
const struct ed25519_public_key_t *ed_id);
|
||||
|
||||
/** For things returned by channel_find_by_remote_digest(), walk the list.
|
||||
* The RSA key will match for all returned elements; the Ed25519 key might not.
|
||||
*/
|
||||
channel_t * channel_next_with_rsa_identity(channel_t *chan);
|
||||
|
||||
/*
|
||||
* Helper macros to lookup state of given channel.
|
||||
*/
|
||||
|
||||
#define CHANNEL_IS_CLOSED(chan) (channel_is_in_state((chan), \
|
||||
CHANNEL_STATE_CLOSED))
|
||||
#define CHANNEL_IS_OPENING(chan) (channel_is_in_state((chan), \
|
||||
CHANNEL_STATE_OPENING))
|
||||
#define CHANNEL_IS_OPEN(chan) (channel_is_in_state((chan), \
|
||||
CHANNEL_STATE_OPEN))
|
||||
#define CHANNEL_IS_MAINT(chan) (channel_is_in_state((chan), \
|
||||
CHANNEL_STATE_MAINT))
|
||||
#define CHANNEL_IS_CLOSING(chan) (channel_is_in_state((chan), \
|
||||
CHANNEL_STATE_CLOSING))
|
||||
#define CHANNEL_IS_ERROR(chan) (channel_is_in_state((chan), \
|
||||
CHANNEL_STATE_ERROR))
|
||||
|
||||
#define CHANNEL_FINISHED(chan) (CHANNEL_IS_CLOSED(chan) || \
|
||||
CHANNEL_IS_ERROR(chan))
|
||||
|
||||
#define CHANNEL_CONDEMNED(chan) (CHANNEL_IS_CLOSING(chan) || \
|
||||
CHANNEL_FINISHED(chan))
|
||||
|
||||
#define CHANNEL_CAN_HANDLE_CELLS(chan) (CHANNEL_IS_OPENING(chan) || \
|
||||
CHANNEL_IS_OPEN(chan) || \
|
||||
CHANNEL_IS_MAINT(chan))
|
||||
|
||||
static inline int
|
||||
channel_is_in_state(channel_t *chan, channel_state_t state)
|
||||
{
|
||||
return chan->state == state;
|
||||
}
|
||||
|
||||
/*
|
||||
* Metadata queries/updates
|
||||
*/
|
||||
|
||||
const char * channel_describe_transport(channel_t *chan);
|
||||
MOCK_DECL(void, channel_dump_statistics, (channel_t *chan, int severity));
|
||||
void channel_dump_transport_statistics(channel_t *chan, int severity);
|
||||
MOCK_DECL(int, channel_get_addr_if_possible, (const channel_t *chan,
|
||||
tor_addr_t *addr_out));
|
||||
MOCK_DECL(const char *, channel_describe_peer,(channel_t *chan));
|
||||
int channel_has_queued_writes(channel_t *chan);
|
||||
int channel_is_bad_for_new_circs(channel_t *chan);
|
||||
void channel_mark_bad_for_new_circs(channel_t *chan);
|
||||
int channel_is_canonical(channel_t *chan);
|
||||
int channel_is_client(const channel_t *chan);
|
||||
int channel_is_local(channel_t *chan);
|
||||
int channel_is_incoming(channel_t *chan);
|
||||
int channel_is_outgoing(channel_t *chan);
|
||||
void channel_mark_client(channel_t *chan);
|
||||
void channel_clear_client(channel_t *chan);
|
||||
int channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info);
|
||||
int channel_remote_identity_matches(const channel_t *chan,
|
||||
const char *rsa_id_digest,
|
||||
const ed25519_public_key_t *ed_id);
|
||||
unsigned int channel_num_circuits(channel_t *chan);
|
||||
MOCK_DECL(void,channel_set_circid_type,(channel_t *chan,
|
||||
crypto_pk_t *identity_rcvd,
|
||||
int consider_identity));
|
||||
void channel_timestamp_client(channel_t *chan);
|
||||
|
||||
const char * channel_listener_describe_transport(channel_listener_t *chan_l);
|
||||
void channel_listener_dump_statistics(channel_listener_t *chan_l,
|
||||
int severity);
|
||||
void channel_listener_dump_transport_statistics(channel_listener_t *chan_l,
|
||||
int severity);
|
||||
void channel_check_for_duplicates(void);
|
||||
|
||||
void channel_update_bad_for_new_circs(const char *digest, int force);
|
||||
|
||||
/* Flow control queries */
|
||||
int channel_num_cells_writeable(channel_t *chan);
|
||||
|
||||
/* Timestamp queries */
|
||||
time_t channel_when_created(channel_t *chan);
|
||||
time_t channel_when_last_client(channel_t *chan);
|
||||
time_t channel_when_last_xmit(channel_t *chan);
|
||||
|
||||
/* Counter queries */
|
||||
int packed_cell_is_destroy(channel_t *chan,
|
||||
const packed_cell_t *packed_cell,
|
||||
circid_t *circid_out);
|
||||
|
||||
/* Declare the handle helpers */
|
||||
HANDLE_DECL(channel, channel_t,)
|
||||
#define channel_handle_free(h) \
|
||||
FREE_AND_NULL(channel_handle_t, channel_handle_free_, (h))
|
||||
#undef tor_timer_t
|
||||
|
||||
#endif /* !defined(TOR_CHANNEL_H) */
|
||||
@@ -0,0 +1,42 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file circuitbuild.h
|
||||
* \brief Header file for circuitbuild.c.
|
||||
**/
|
||||
#ifndef TOR_CHANNELPADDING_H
|
||||
#define TOR_CHANNELPADDING_H
|
||||
|
||||
#include "trunnel/channelpadding_negotiation.h"
|
||||
|
||||
#define CHANNELPADDING_SOS_PARAM "nf_pad_single_onion"
|
||||
#define CHANNELPADDING_SOS_DEFAULT 1
|
||||
|
||||
typedef enum {
|
||||
CHANNELPADDING_WONTPAD,
|
||||
CHANNELPADDING_PADLATER,
|
||||
CHANNELPADDING_PADDING_SCHEDULED,
|
||||
CHANNELPADDING_PADDING_ALREADY_SCHEDULED,
|
||||
CHANNELPADDING_PADDING_SENT,
|
||||
} channelpadding_decision_t;
|
||||
|
||||
channelpadding_decision_t channelpadding_decide_to_pad_channel(channel_t
|
||||
*chan);
|
||||
int channelpadding_update_padding_for_channel(channel_t *,
|
||||
const channelpadding_negotiate_t
|
||||
*chan);
|
||||
|
||||
void channelpadding_disable_padding_on_channel(channel_t *chan);
|
||||
void channelpadding_reduce_padding_on_channel(channel_t *chan);
|
||||
int channelpadding_send_enable_command(channel_t *chan, uint16_t low_timeout,
|
||||
uint16_t high_timeout);
|
||||
|
||||
int channelpadding_get_circuits_available_timeout(void);
|
||||
unsigned int channelpadding_get_channel_idle_timeout(const channel_t *, int);
|
||||
void channelpadding_new_consensus_params(const networkstatus_t *ns);
|
||||
|
||||
#endif /* !defined(TOR_CHANNELPADDING_H) */
|
||||
@@ -0,0 +1,82 @@
|
||||
/* * Copyright (c) 2012-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file channeltls.h
|
||||
* \brief Header file for channeltls.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_CHANNELTLS_H
|
||||
#define TOR_CHANNELTLS_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
#include "core/or/channel.h"
|
||||
|
||||
struct ed25519_public_key_t;
|
||||
struct curve25519_public_key_t;
|
||||
|
||||
#define TLS_PER_CELL_OVERHEAD 29
|
||||
|
||||
#define BASE_CHAN_TO_TLS(c) (channel_tls_from_base((c)))
|
||||
#define TLS_CHAN_TO_BASE(c) (channel_tls_to_base((c)))
|
||||
#define CONST_BASE_CHAN_TO_TLS(c) (channel_tls_from_base_const((c)))
|
||||
#define CONST_TLS_CHAN_TO_BASE(c) (channel_tls_to_base_const((c)))
|
||||
|
||||
#define TLS_CHAN_MAGIC 0x8a192427U
|
||||
|
||||
#ifdef CHANNEL_OBJECT_PRIVATE
|
||||
|
||||
struct channel_tls_t {
|
||||
/* Base channel_t struct */
|
||||
channel_t base_;
|
||||
/* or_connection_t pointer */
|
||||
or_connection_t *conn;
|
||||
};
|
||||
|
||||
#endif /* defined(CHANNEL_OBJECT_PRIVATE) */
|
||||
|
||||
channel_t * channel_tls_connect(const tor_addr_t *addr, uint16_t port,
|
||||
const char *id_digest,
|
||||
const struct ed25519_public_key_t *ed_id);
|
||||
channel_listener_t * channel_tls_get_listener(void);
|
||||
channel_listener_t * channel_tls_start_listener(void);
|
||||
channel_t * channel_tls_handle_incoming(or_connection_t *orconn);
|
||||
|
||||
/* Casts */
|
||||
|
||||
channel_t * channel_tls_to_base(channel_tls_t *tlschan);
|
||||
channel_tls_t * channel_tls_from_base(channel_t *chan);
|
||||
const channel_t * channel_tls_to_base_const(const channel_tls_t *tlschan);
|
||||
const channel_tls_t * channel_tls_from_base_const(const channel_t *chan);
|
||||
|
||||
/* Things for connection_or.c to call back into */
|
||||
void channel_tls_handle_cell(cell_t *cell, or_connection_t *conn);
|
||||
void channel_tls_handle_state_change_on_orconn(channel_tls_t *chan,
|
||||
or_connection_t *conn,
|
||||
uint8_t state);
|
||||
void channel_tls_handle_var_cell(var_cell_t *var_cell,
|
||||
or_connection_t *conn);
|
||||
void channel_tls_update_marks(or_connection_t *conn);
|
||||
|
||||
/* Cleanup at shutdown */
|
||||
void channel_tls_free_all(void);
|
||||
|
||||
extern uint64_t stats_n_authorize_cells_processed;
|
||||
extern uint64_t stats_n_authenticate_cells_processed;
|
||||
extern uint64_t stats_n_versions_cells_processed;
|
||||
extern uint64_t stats_n_netinfo_cells_processed;
|
||||
extern uint64_t stats_n_vpadding_cells_processed;
|
||||
extern uint64_t stats_n_certs_cells_processed;
|
||||
extern uint64_t stats_n_auth_challenge_cells_processed;
|
||||
|
||||
#ifdef CHANNELTLS_PRIVATE
|
||||
STATIC void channel_tls_process_certs_cell(var_cell_t *cell,
|
||||
channel_tls_t *tlschan);
|
||||
STATIC void channel_tls_process_auth_challenge_cell(var_cell_t *cell,
|
||||
channel_tls_t *tlschan);
|
||||
STATIC void channel_tls_common_init(channel_tls_t *tlschan);
|
||||
STATIC void channel_tls_process_authenticate_cell(var_cell_t *cell,
|
||||
channel_tls_t *tlschan);
|
||||
#endif /* defined(CHANNELTLS_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CHANNELTLS_H) */
|
||||
@@ -0,0 +1,274 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file circuit_st.h
|
||||
* @brief Base circuit structure.
|
||||
**/
|
||||
|
||||
#ifndef CIRCUIT_ST_H
|
||||
#define CIRCUIT_ST_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
|
||||
#include "lib/container/handles.h"
|
||||
|
||||
#include "core/or/cell_queue_st.h"
|
||||
#include "ext/ht.h"
|
||||
|
||||
struct hs_token_t;
|
||||
struct circpad_machine_spec_t;
|
||||
struct circpad_machine_runtime_t;
|
||||
struct congestion_control_t;
|
||||
|
||||
/** Number of padding state machines on a circuit. */
|
||||
#define CIRCPAD_MAX_MACHINES (2)
|
||||
|
||||
/** "magic" value for an origin_circuit_t */
|
||||
#define ORIGIN_CIRCUIT_MAGIC 0x35315243u
|
||||
/** "magic" value for an or_circuit_t */
|
||||
#define OR_CIRCUIT_MAGIC 0x98ABC04Fu
|
||||
/** "magic" value for a circuit that would have been freed by circuit_free,
|
||||
* but which we're keeping around until a cpuworker reply arrives. See
|
||||
* circuit_free() for more documentation. */
|
||||
#define DEAD_CIRCUIT_MAGIC 0xdeadc14c
|
||||
|
||||
/**
|
||||
* A circuit is a path over the onion routing
|
||||
* network. Applications can connect to one end of the circuit, and can
|
||||
* create exit connections at the other end of the circuit. AP and exit
|
||||
* connections have only one circuit associated with them (and thus these
|
||||
* connection types are closed when the circuit is closed), whereas
|
||||
* OR connections multiplex many circuits at once, and stay standing even
|
||||
* when there are no circuits running over them.
|
||||
*
|
||||
* A circuit_t structure can fill one of two roles. First, a or_circuit_t
|
||||
* links two connections together: either an edge connection and an OR
|
||||
* connection, or two OR connections. (When joined to an OR connection, a
|
||||
* circuit_t affects only cells sent to a particular circID on that
|
||||
* connection. When joined to an edge connection, a circuit_t affects all
|
||||
* data.)
|
||||
|
||||
* Second, an origin_circuit_t holds the cipher keys and state for sending data
|
||||
* along a given circuit. At the OP, it has a sequence of ciphers, each
|
||||
* of which is shared with a single OR along the circuit. Separate
|
||||
* ciphers are used for data going "forward" (away from the OP) and
|
||||
* "backward" (towards the OP). At the OR, a circuit has only two stream
|
||||
* ciphers: one for data going forward, and one for data going backward.
|
||||
*/
|
||||
struct circuit_t {
|
||||
uint32_t magic; /**< For memory and type debugging: must equal
|
||||
* ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */
|
||||
|
||||
/** Handle entry for handle-based lookup */
|
||||
HANDLE_ENTRY(circuit, circuit_t);
|
||||
|
||||
/** The channel that is next in this circuit. */
|
||||
channel_t *n_chan;
|
||||
|
||||
/**
|
||||
* The circuit_id used in the next (forward) hop of this circuit;
|
||||
* this is unique to n_chan, but this ordered pair is globally
|
||||
* unique:
|
||||
*
|
||||
* (n_chan->global_identifier, n_circ_id)
|
||||
*/
|
||||
circid_t n_circ_id;
|
||||
|
||||
/** Queue of cells waiting to be transmitted on n_chan */
|
||||
cell_queue_t n_chan_cells;
|
||||
|
||||
/**
|
||||
* The hop to which we want to extend this circuit. Should be NULL if
|
||||
* the circuit has attached to a channel.
|
||||
*/
|
||||
extend_info_t *n_hop;
|
||||
|
||||
/** True iff we are waiting for n_chan_cells to become less full before
|
||||
* allowing any more cells on this circuit. (Origin circuit only.) */
|
||||
unsigned int circuit_blocked_on_n_chan : 1;
|
||||
/** True iff we are waiting for p_chan_cells to become less full before
|
||||
* allowing any more cells on this circuit. (OR circuit only.) */
|
||||
unsigned int circuit_blocked_on_p_chan : 1;
|
||||
|
||||
/** True iff we have queued a delete backwards on this circuit, but not put
|
||||
* it on the output buffer. */
|
||||
unsigned int p_delete_pending : 1;
|
||||
/** True iff we have queued a delete forwards on this circuit, but not put
|
||||
* it on the output buffer. */
|
||||
unsigned int n_delete_pending : 1;
|
||||
|
||||
/** True iff this circuit has received a DESTROY cell in either direction */
|
||||
unsigned int received_destroy : 1;
|
||||
|
||||
/** True iff we have sent a sufficiently random data cell since last
|
||||
* we reset send_randomness_after_n_cells. */
|
||||
unsigned int have_sent_sufficiently_random_cell : 1;
|
||||
|
||||
uint8_t state; /**< Current status of this circuit. */
|
||||
uint8_t purpose; /**< Why are we creating this circuit? */
|
||||
|
||||
/** How many relay data cells can we package (read from edge streams)
|
||||
* on this circuit before we receive a circuit-level sendme cell asking
|
||||
* for more? */
|
||||
int package_window;
|
||||
/** How many relay data cells will we deliver (write to edge streams)
|
||||
* on this circuit? When deliver_window gets low, we send some
|
||||
* circuit-level sendme cells to indicate that we're willing to accept
|
||||
* more. */
|
||||
int deliver_window;
|
||||
/**
|
||||
* How many cells do we have until we need to send one that contains
|
||||
* sufficient randomness? Used to ensure that authenticated SENDME cells
|
||||
* will reflect some unpredictable information.
|
||||
**/
|
||||
uint16_t send_randomness_after_n_cells;
|
||||
|
||||
/** FIFO containing the digest of the cells that are just before a SENDME is
|
||||
* sent by the client. It is done at the last cell before our package_window
|
||||
* goes down to 0 which is when we expect a SENDME.
|
||||
*
|
||||
* Our current circuit package window is capped to 1000
|
||||
* (CIRCWINDOW_START_MAX) which is also the start value. The increment is
|
||||
* set to 100 (CIRCWINDOW_INCREMENT) which means we don't allow more than
|
||||
* 1000/100 = 10 outstanding SENDME cells worth of data. Meaning that this
|
||||
* list can not contain more than 10 digests of DIGEST_LEN bytes (20).
|
||||
*
|
||||
* At position i in the list, the digest corresponds to the
|
||||
* (CIRCWINDOW_INCREMENT * i)-nth cell received since we expect a SENDME to
|
||||
* be received containing that cell digest.
|
||||
*
|
||||
* For example, position 2 (starting at 0) means that we've received 300
|
||||
* cells so the 300th cell digest is kept at index 2.
|
||||
*
|
||||
* At maximum, this list contains 200 bytes plus the smartlist overhead. */
|
||||
smartlist_t *sendme_last_digests;
|
||||
|
||||
/** Temporary field used during circuits_handle_oom. */
|
||||
uint32_t age_tmp;
|
||||
|
||||
/** For storage while n_chan is pending (state CIRCUIT_STATE_CHAN_WAIT). */
|
||||
struct create_cell_t *n_chan_create_cell;
|
||||
|
||||
/** When did circuit construction actually begin (ie send the
|
||||
* CREATE cell or begin cannibalization).
|
||||
*
|
||||
* Note: This timer will get reset if we decide to cannibalize
|
||||
* a circuit. It may also get reset during certain phases of hidden
|
||||
* service circuit use.
|
||||
*
|
||||
* We keep this timestamp with a higher resolution than most so that the
|
||||
* circuit-build-time tracking code can get millisecond resolution.
|
||||
*/
|
||||
struct timeval timestamp_began;
|
||||
|
||||
/** This timestamp marks when the init_circuit_base constructor ran. */
|
||||
struct timeval timestamp_created;
|
||||
|
||||
/** When the circuit was first used, or 0 if the circuit is clean.
|
||||
*
|
||||
* XXXX Note that some code will artificially adjust this value backward
|
||||
* in time in order to indicate that a circuit shouldn't be used for new
|
||||
* streams, but that it can stay alive as long as it has streams on it.
|
||||
* That's a kludge we should fix.
|
||||
*
|
||||
* XXX The CBT code uses this field to record when HS-related
|
||||
* circuits entered certain states. This usage probably won't
|
||||
* interfere with this field's primary purpose, but we should
|
||||
* document it more thoroughly to make sure of that.
|
||||
*
|
||||
* XXX The SocksPort option KeepaliveIsolateSOCKSAuth will artificially
|
||||
* adjust this value forward each time a suitable stream is attached to an
|
||||
* already constructed circuit, potentially keeping the circuit alive
|
||||
* indefinitely.
|
||||
*/
|
||||
time_t timestamp_dirty;
|
||||
|
||||
uint16_t marked_for_close; /**< Should we close this circuit at the end of
|
||||
* the main loop? (If true, holds the line number
|
||||
* where this circuit was marked.) */
|
||||
const char *marked_for_close_file; /**< For debugging: in which file was this
|
||||
* circuit marked for close? */
|
||||
/** For what reason (See END_CIRC_REASON...) is this circuit being closed?
|
||||
* This field is set in circuit_mark_for_close and used later in
|
||||
* circuit_about_to_free. */
|
||||
int marked_for_close_reason;
|
||||
/** As marked_for_close_reason, but reflects the underlying reason for
|
||||
* closing this circuit.
|
||||
*/
|
||||
int marked_for_close_orig_reason;
|
||||
|
||||
/** Unique ID for measuring tunneled network status requests. */
|
||||
uint64_t dirreq_id;
|
||||
|
||||
/** Index in smartlist of all circuits (global_circuitlist). */
|
||||
int global_circuitlist_idx;
|
||||
|
||||
/** Various statistics about cells being added to or removed from this
|
||||
* circuit's queues; used only if CELL_STATS events are enabled and
|
||||
* cleared after being sent to control port. */
|
||||
smartlist_t *testing_cell_stats;
|
||||
|
||||
/** If set, points to an HS token that this circuit might be carrying.
|
||||
* Used by the HS circuitmap. */
|
||||
struct hs_token_t *hs_token;
|
||||
/** Hashtable node: used to look up the circuit by its HS token using the HS
|
||||
circuitmap. */
|
||||
HT_ENTRY(circuit_t) hs_circuitmap_node;
|
||||
|
||||
/** Adaptive Padding state machines: these are immutable. The state machines
|
||||
* that come from the consensus are saved to a global structure, to avoid
|
||||
* per-circuit allocations. This merely points to the global copy in
|
||||
* origin_padding_machines or relay_padding_machines that should never
|
||||
* change or get deallocated.
|
||||
*
|
||||
* Each element of this array corresponds to a different padding machine,
|
||||
* and we can have up to CIRCPAD_MAX_MACHINES such machines. */
|
||||
const struct circpad_machine_spec_t *padding_machine[CIRCPAD_MAX_MACHINES];
|
||||
|
||||
/** Adaptive Padding machine runtime info for above machines. This is
|
||||
* the per-circuit mutable information, such as the current state and
|
||||
* histogram token counts. Some of it is optional (aka NULL).
|
||||
* If a machine is being shut down, these indexes can be NULL
|
||||
* without the corresponding padding_machine being NULL, while we
|
||||
* wait for the other end to respond to our shutdown request.
|
||||
*
|
||||
* Each element of this array corresponds to a different padding machine,
|
||||
* and we can have up to CIRCPAD_MAX_MACHINES such machines. */
|
||||
struct circpad_machine_runtime_t *padding_info[CIRCPAD_MAX_MACHINES];
|
||||
|
||||
/** padding_machine_ctr increments each time a new padding machine
|
||||
* is negotiated. It is used for shutdown conditions, to ensure
|
||||
* that STOP commands actually correspond to the current machine,
|
||||
* and not a previous one. */
|
||||
uint32_t padding_machine_ctr;
|
||||
|
||||
/** Congestion control fields */
|
||||
struct congestion_control_t *ccontrol;
|
||||
|
||||
/** Conflux linked circuit information.
|
||||
*
|
||||
* If this is non-NULL, the circuit is linked and part of a usable set,
|
||||
* and for origin_circuit_t subtypes, the circuit purpose is
|
||||
* CIRCUIT_PURPOSE_CONFLUX_LINKED.
|
||||
*
|
||||
* If this is NULL, the circuit could still be part of a pending conflux
|
||||
* object, in which case the conflux_pending_nonce field is set, and for
|
||||
* origin_circuit_t subtypes, the purpose is
|
||||
* CIRCUIT_PURPOSE_CONFLUX_UNLINKED.
|
||||
*/
|
||||
struct conflux_t *conflux;
|
||||
|
||||
/** If set, this circuit is considered *unlinked* and in the pending pool.
|
||||
* The nonce value is used to find the other legs. Origin circuits that
|
||||
* have this set are in the CIRCUIT_PURPOSE_CONFLUX_UNLINKED purpose.
|
||||
*
|
||||
* If this is NULL, and conflux object is set, it means this circuit is
|
||||
* linked and thus part of a usable set. */
|
||||
uint8_t *conflux_pending_nonce;
|
||||
};
|
||||
|
||||
#endif /* !defined(CIRCUIT_ST_H) */
|
||||
@@ -0,0 +1,96 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file circuitbuild.h
|
||||
* \brief Header file for circuitbuild.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CIRCUITBUILD_H
|
||||
#define TOR_CIRCUITBUILD_H
|
||||
|
||||
struct ed25519_public_key_t;
|
||||
struct curve25519_public_key_t;
|
||||
|
||||
int route_len_for_purpose(uint8_t purpose, extend_info_t *exit_ei);
|
||||
char *circuit_list_path(origin_circuit_t *circ, int verbose);
|
||||
char *circuit_list_path_for_controller(origin_circuit_t *circ);
|
||||
void circuit_log_path(int severity, unsigned int domain,
|
||||
origin_circuit_t *circ);
|
||||
origin_circuit_t *origin_circuit_init(uint8_t purpose, int flags);
|
||||
origin_circuit_t *circuit_establish_circuit(uint8_t purpose,
|
||||
extend_info_t *exit,
|
||||
int flags);
|
||||
MOCK_DECL(origin_circuit_t *, circuit_establish_circuit_conflux, (
|
||||
const uint8_t *nonce,
|
||||
uint8_t purpose,
|
||||
extend_info_t *exit,
|
||||
int flags));
|
||||
|
||||
struct circuit_guard_state_t *origin_circuit_get_guard_state(
|
||||
origin_circuit_t *circ);
|
||||
int circuit_handle_first_hop(origin_circuit_t *circ);
|
||||
void circuit_n_chan_done(channel_t *chan, int status,
|
||||
int close_origin_circuits);
|
||||
int circuit_timeout_want_to_count_circ(const origin_circuit_t *circ);
|
||||
int circuit_send_next_onion_skin(origin_circuit_t *circ);
|
||||
void circuit_note_clock_jumped(int64_t seconds_elapsed, bool was_idle);
|
||||
struct created_cell_t;
|
||||
int circuit_finish_handshake(origin_circuit_t *circ,
|
||||
const struct created_cell_t *created_cell);
|
||||
int circuit_truncated(origin_circuit_t *circ, int reason);
|
||||
MOCK_DECL(int, circuit_all_predicted_ports_handled, (time_t now,
|
||||
int *need_uptime,
|
||||
int *need_capacity));
|
||||
|
||||
int circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info);
|
||||
int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info);
|
||||
int circuit_can_use_tap(const origin_circuit_t *circ);
|
||||
int circuit_has_usable_onion_key(const origin_circuit_t *circ);
|
||||
const uint8_t *build_state_get_exit_rsa_id(cpath_build_state_t *state);
|
||||
MOCK_DECL(const node_t *,
|
||||
build_state_get_exit_node,(cpath_build_state_t *state));
|
||||
const char *build_state_get_exit_nickname(cpath_build_state_t *state);
|
||||
|
||||
struct circuit_guard_state_t;
|
||||
|
||||
const node_t *choose_good_entry_server(const origin_circuit_t *circ,
|
||||
uint8_t purpose,
|
||||
cpath_build_state_t *state,
|
||||
struct circuit_guard_state_t **guard_state_out);
|
||||
void circuit_upgrade_circuits_from_guard_wait(void);
|
||||
|
||||
MOCK_DECL(channel_t *, channel_connect_for_circuit,(const extend_info_t *ei));
|
||||
|
||||
struct create_cell_t;
|
||||
MOCK_DECL(int,
|
||||
circuit_deliver_create_cell,(circuit_t *circ,
|
||||
const struct create_cell_t *create_cell,
|
||||
int relayed));
|
||||
|
||||
int client_circ_negotiation_message(const extend_info_t *ei,
|
||||
uint8_t **msg_out,
|
||||
size_t *msg_len_out);
|
||||
|
||||
#ifdef CIRCUITBUILD_PRIVATE
|
||||
STATIC circid_t get_unique_circ_id_by_chan(channel_t *chan);
|
||||
STATIC int new_route_len(uint8_t purpose, extend_info_t *exit_ei,
|
||||
const smartlist_t *nodes);
|
||||
MOCK_DECL(STATIC int, count_acceptable_nodes, (const smartlist_t *nodes,
|
||||
int direct));
|
||||
|
||||
STATIC int onion_extend_cpath(origin_circuit_t *circ);
|
||||
|
||||
STATIC int
|
||||
onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit_ei);
|
||||
STATIC int cpath_build_state_to_crn_flags(const cpath_build_state_t *state);
|
||||
STATIC int cpath_build_state_to_crn_ipv6_extend_flag(
|
||||
const cpath_build_state_t *state,
|
||||
int cur_len);
|
||||
|
||||
#endif /* defined(CIRCUITBUILD_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CIRCUITBUILD_H) */
|
||||
@@ -0,0 +1,273 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file circuitlist.h
|
||||
* \brief Header file for circuitlist.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CIRCUITLIST_H
|
||||
#define TOR_CIRCUITLIST_H
|
||||
|
||||
#include "lib/container/handles.h"
|
||||
#include "lib/testsupport/testsupport.h"
|
||||
#include "feature/hs/hs_ident.h"
|
||||
#include "core/or/ocirc_event.h"
|
||||
|
||||
/** Circuit state: I'm the origin, still haven't done all my handshakes. */
|
||||
#define CIRCUIT_STATE_BUILDING 0
|
||||
/** Circuit state: Waiting to process the onionskin. */
|
||||
#define CIRCUIT_STATE_ONIONSKIN_PENDING 1
|
||||
/** Circuit state: I'd like to deliver a create, but my n_chan is still
|
||||
* connecting. */
|
||||
#define CIRCUIT_STATE_CHAN_WAIT 2
|
||||
/** Circuit state: the circuit is open but we don't want to actually use it
|
||||
* until we find out if a better guard will be available.
|
||||
*/
|
||||
#define CIRCUIT_STATE_GUARD_WAIT 3
|
||||
/** Circuit state: onionskin(s) processed, ready to send/receive cells. */
|
||||
#define CIRCUIT_STATE_OPEN 4
|
||||
|
||||
#define CIRCUIT_PURPOSE_MIN_ 1
|
||||
|
||||
/* these circuits were initiated elsewhere */
|
||||
#define CIRCUIT_PURPOSE_OR_MIN_ 1
|
||||
/** OR-side circuit purpose: normal circuit, at OR. */
|
||||
#define CIRCUIT_PURPOSE_OR 1
|
||||
/** OR-side circuit purpose: At OR, from the service, waiting for intro from
|
||||
* clients. */
|
||||
#define CIRCUIT_PURPOSE_INTRO_POINT 2
|
||||
/** OR-side circuit purpose: At OR, from the client, waiting for the service.
|
||||
*/
|
||||
#define CIRCUIT_PURPOSE_REND_POINT_WAITING 3
|
||||
/** OR-side circuit purpose: At OR, both circuits have this purpose. */
|
||||
#define CIRCUIT_PURPOSE_REND_ESTABLISHED 4
|
||||
#define CIRCUIT_PURPOSE_OR_MAX_ 4
|
||||
|
||||
/* these circuits originate at this node */
|
||||
|
||||
/* here's how circ client-side purposes work:
|
||||
* normal circuits are C_GENERAL.
|
||||
* circuits that are c_introducing are either on their way to
|
||||
* becoming open, or they are open and waiting for a
|
||||
* suitable rendcirc before they send the intro.
|
||||
* circuits that are c_introduce_ack_wait have sent the intro,
|
||||
* but haven't gotten a response yet.
|
||||
* circuits that are c_establish_rend are either on their way
|
||||
* to becoming open, or they are open and have sent the
|
||||
* establish_rendezvous cell but haven't received an ack.
|
||||
* circuits that are c_rend_ready are open and have received a
|
||||
* rend ack, but haven't heard from the service yet.
|
||||
* circuits that are c_rend_ready_intro_acked are open, and
|
||||
* some intro circ has sent its intro and received an ack.
|
||||
* circuits that are c_rend_joined are open, have heard from
|
||||
* the service, and are talking to it.
|
||||
*/
|
||||
/** Client-side circuit purpose: Normal circuit, with cpath. */
|
||||
#define CIRCUIT_PURPOSE_C_GENERAL 5
|
||||
#define CIRCUIT_PURPOSE_C_HS_MIN_ 6
|
||||
/** Client-side circuit purpose: at the client, connecting to intro point. */
|
||||
#define CIRCUIT_PURPOSE_C_INTRODUCING 6
|
||||
/** Client-side circuit purpose: at the client, sent INTRODUCE1 to intro point,
|
||||
* waiting for ACK/NAK. */
|
||||
#define CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT 7
|
||||
/** Client-side circuit purpose: at the client, introduced and acked, closing.
|
||||
*/
|
||||
#define CIRCUIT_PURPOSE_C_INTRODUCE_ACKED 8
|
||||
/** Client-side circuit purpose: at the client, waiting for ack. */
|
||||
#define CIRCUIT_PURPOSE_C_ESTABLISH_REND 9
|
||||
/** Client-side circuit purpose: at the client, waiting for the service. */
|
||||
#define CIRCUIT_PURPOSE_C_REND_READY 10
|
||||
/** Client-side circuit purpose: at the client, waiting for the service,
|
||||
* INTRODUCE has been acknowledged. */
|
||||
#define CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED 11
|
||||
/** Client-side circuit purpose: at the client, rendezvous established. */
|
||||
#define CIRCUIT_PURPOSE_C_REND_JOINED 12
|
||||
/** This circuit is used for getting hsdirs */
|
||||
#define CIRCUIT_PURPOSE_C_HSDIR_GET 13
|
||||
#define CIRCUIT_PURPOSE_C_HS_MAX_ 13
|
||||
/** This circuit is used for build time measurement only */
|
||||
#define CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT 14
|
||||
/** This circuit is being held open by circuit padding */
|
||||
#define CIRCUIT_PURPOSE_C_CIRCUIT_PADDING 15
|
||||
#define CIRCUIT_PURPOSE_C_MAX_ 15
|
||||
|
||||
#define CIRCUIT_PURPOSE_S_HS_MIN_ 16
|
||||
/** Hidden-service-side circuit purpose: at the service, waiting for
|
||||
* introductions. */
|
||||
#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 16
|
||||
/** Hidden-service-side circuit purpose: at the service, successfully
|
||||
* established intro. */
|
||||
#define CIRCUIT_PURPOSE_S_INTRO 17
|
||||
/** Hidden-service-side circuit purpose: at the service, connecting to rend
|
||||
* point. */
|
||||
#define CIRCUIT_PURPOSE_S_CONNECT_REND 18
|
||||
/** Hidden-service-side circuit purpose: at the service, rendezvous
|
||||
* established. */
|
||||
#define CIRCUIT_PURPOSE_S_REND_JOINED 19
|
||||
/** This circuit is used for uploading hsdirs */
|
||||
#define CIRCUIT_PURPOSE_S_HSDIR_POST 20
|
||||
#define CIRCUIT_PURPOSE_S_HS_MAX_ 20
|
||||
|
||||
/** A testing circuit; not meant to be used for actual traffic. It is used for
|
||||
* bandwidth measurement, reachability test and address discovery from an
|
||||
* authority using the NETINFO cell. */
|
||||
#define CIRCUIT_PURPOSE_TESTING 21
|
||||
/** A controller made this circuit and Tor should not cannibalize it or attach
|
||||
* streams to it without explicitly being told. */
|
||||
#define CIRCUIT_PURPOSE_CONTROLLER 22
|
||||
/** This circuit is used for path bias probing only */
|
||||
#define CIRCUIT_PURPOSE_PATH_BIAS_TESTING 23
|
||||
|
||||
/** This circuit is used for vanguards/restricted paths.
|
||||
*
|
||||
* This type of circuit is *only* created preemptively and never
|
||||
* on-demand. When an HS operation needs to take place (e.g. connect to an
|
||||
* intro point), these circuits are then cannibalized and repurposed to the
|
||||
* actual needed HS purpose. */
|
||||
#define CIRCUIT_PURPOSE_HS_VANGUARDS 24
|
||||
|
||||
/**
|
||||
* These two purposes are for conflux. The first is for circuits that are
|
||||
* being built, but not yet linked. The second is for circuits that are
|
||||
* linked and ready to use for streams. */
|
||||
#define CIRCUIT_PURPOSE_CONFLUX_UNLINKED 25
|
||||
#define CIRCUIT_PURPOSE_CONFLUX_LINKED 26
|
||||
|
||||
#define CIRCUIT_PURPOSE_MAX_ 26
|
||||
/** A catch-all for unrecognized purposes. Currently we don't expect
|
||||
* to make or see any circuits with this purpose. */
|
||||
#define CIRCUIT_PURPOSE_UNKNOWN 255
|
||||
|
||||
/** True iff the circuit purpose <b>p</b> is for a circuit that
|
||||
* originated at this node. */
|
||||
#define CIRCUIT_PURPOSE_IS_ORIGIN(p) ((p)>CIRCUIT_PURPOSE_OR_MAX_)
|
||||
/** True iff the circuit purpose <b>p</b> is for a circuit that originated
|
||||
* here to serve as a client. (Hidden services don't count here.) */
|
||||
#define CIRCUIT_PURPOSE_IS_CLIENT(p) \
|
||||
((p)> CIRCUIT_PURPOSE_OR_MAX_ && \
|
||||
(p)<=CIRCUIT_PURPOSE_C_MAX_)
|
||||
/** True iff the circuit_t <b>c</b> is actually an origin_circuit_t. */
|
||||
#define CIRCUIT_IS_ORIGIN(c) (CIRCUIT_PURPOSE_IS_ORIGIN((c)->purpose))
|
||||
/** True iff the circuit purpose <b>p</b> is for an established rendezvous
|
||||
* circuit. */
|
||||
#define CIRCUIT_PURPOSE_IS_ESTABLISHED_REND(p) \
|
||||
((p) == CIRCUIT_PURPOSE_C_REND_JOINED || \
|
||||
(p) == CIRCUIT_PURPOSE_S_REND_JOINED)
|
||||
/** True iff the circuit_t c is actually an or_circuit_t */
|
||||
#define CIRCUIT_IS_ORCIRC(c) (((circuit_t *)(c))->magic == OR_CIRCUIT_MAGIC)
|
||||
|
||||
/** True iff this circuit purpose should count towards the global
|
||||
* pending rate limit (set by MaxClientCircuitsPending). We count all
|
||||
* general purpose circuits, as well as the first step of client onion
|
||||
* service connections (HSDir gets). */
|
||||
#define CIRCUIT_PURPOSE_COUNTS_TOWARDS_MAXPENDING(p) \
|
||||
((p) == CIRCUIT_PURPOSE_C_GENERAL || \
|
||||
(p) == CIRCUIT_PURPOSE_C_HSDIR_GET)
|
||||
|
||||
/** Stats. */
|
||||
extern double cc_stats_circ_close_cwnd_ma;
|
||||
extern double cc_stats_circ_close_ss_cwnd_ma;
|
||||
extern uint64_t cc_stats_circs_closed;
|
||||
|
||||
/** Convert a circuit_t* to a pointer to the enclosing or_circuit_t. Assert
|
||||
* if the cast is impossible. */
|
||||
or_circuit_t *TO_OR_CIRCUIT(circuit_t *);
|
||||
const or_circuit_t *CONST_TO_OR_CIRCUIT(const circuit_t *);
|
||||
/** Convert a circuit_t* to a pointer to the enclosing origin_circuit_t.
|
||||
* Assert if the cast is impossible. */
|
||||
origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *);
|
||||
const origin_circuit_t *CONST_TO_ORIGIN_CIRCUIT(const circuit_t *);
|
||||
|
||||
MOCK_DECL(smartlist_t *, circuit_get_global_list, (void));
|
||||
smartlist_t *circuit_get_global_origin_circuit_list(void);
|
||||
int circuit_any_opened_circuits(void);
|
||||
int circuit_any_opened_circuits_cached(void);
|
||||
void circuit_cache_opened_circuit_state(int circuits_are_opened);
|
||||
|
||||
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);
|
||||
void circuit_dump_by_conn(connection_t *conn, int severity);
|
||||
void circuit_set_p_circid_chan(or_circuit_t *circ, circid_t id,
|
||||
channel_t *chan);
|
||||
void circuit_set_n_circid_chan(circuit_t *circ, circid_t id,
|
||||
channel_t *chan);
|
||||
void channel_mark_circid_unusable(channel_t *chan, circid_t id);
|
||||
void channel_mark_circid_usable(channel_t *chan, circid_t id);
|
||||
time_t circuit_id_when_marked_unusable_on_channel(circid_t circ_id,
|
||||
channel_t *chan);
|
||||
int circuit_event_status(origin_circuit_t *circ, circuit_status_event_t tp,
|
||||
int reason_code);
|
||||
void circuit_set_state(circuit_t *circ, uint8_t state);
|
||||
void circuit_close_all_marked(void);
|
||||
int32_t circuit_initial_package_window(void);
|
||||
origin_circuit_t *origin_circuit_new(void);
|
||||
or_circuit_t *or_circuit_new(circid_t p_circ_id, channel_t *p_chan);
|
||||
circuit_t *circuit_get_by_circid_channel(circid_t circ_id,
|
||||
channel_t *chan);
|
||||
circuit_t *
|
||||
circuit_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);
|
||||
circuit_t *circuit_get_by_edge_conn(edge_connection_t *conn);
|
||||
void circuit_unlink_all_from_channel(channel_t *chan, int reason);
|
||||
origin_circuit_t *circuit_get_by_global_id(uint32_t id);
|
||||
origin_circuit_t *circuit_get_next_by_purpose(origin_circuit_t *start,
|
||||
uint8_t purpose);
|
||||
origin_circuit_t *circuit_get_next_intro_circ(const origin_circuit_t *start,
|
||||
bool want_client_circ);
|
||||
origin_circuit_t *circuit_get_next_service_rp_circ(origin_circuit_t *start);
|
||||
origin_circuit_t *circuit_get_next_service_hsdir_circ(origin_circuit_t *start);
|
||||
origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose,
|
||||
extend_info_t *info, int flags);
|
||||
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);
|
||||
MOCK_DECL(void, circuit_mark_for_close_, (circuit_t *circ, int reason,
|
||||
int line, const char *cfile));
|
||||
int circuit_get_cpath_len(origin_circuit_t *circ);
|
||||
int circuit_get_cpath_opened_len(const origin_circuit_t *);
|
||||
void circuit_clear_cpath(origin_circuit_t *circ);
|
||||
crypt_path_t *circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum);
|
||||
void circuit_get_all_pending_on_channel(smartlist_t *out,
|
||||
channel_t *chan);
|
||||
int circuit_count_pending_on_channel(channel_t *chan);
|
||||
|
||||
#define circuit_mark_for_close(c, reason) \
|
||||
circuit_mark_for_close_((c), (reason), __LINE__, SHORT_FILE__)
|
||||
|
||||
MOCK_DECL(void, assert_circuit_ok,(const circuit_t *c));
|
||||
void circuit_free_all(void);
|
||||
size_t circuits_handle_oom(size_t current_allocation);
|
||||
|
||||
void circuit_clear_testing_cell_stats(circuit_t *circ);
|
||||
|
||||
void channel_note_destroy_pending(channel_t *chan, circid_t id);
|
||||
MOCK_DECL(void, channel_note_destroy_not_pending,
|
||||
(channel_t *chan, circid_t id));
|
||||
|
||||
smartlist_t *circuit_find_circuits_to_upgrade_from_guard_wait(void);
|
||||
|
||||
bool circuit_is_queue_full(const circuit_t *circ, cell_direction_t direction);
|
||||
|
||||
/* Declare the handle helpers */
|
||||
HANDLE_DECL(circuit, circuit_t, )
|
||||
#define circuit_handle_free(h) \
|
||||
FREE_AND_NULL(circuit_handle_t, circuit_handle_free_, (h))
|
||||
|
||||
#ifdef CIRCUITLIST_PRIVATE
|
||||
STATIC void circuit_free_(circuit_t *circ);
|
||||
#define circuit_free(circ) FREE_AND_NULL(circuit_t, circuit_free_, (circ))
|
||||
STATIC size_t n_cells_in_circ_queues(const circuit_t *c);
|
||||
STATIC uint32_t circuit_max_queued_data_age(const circuit_t *c, uint32_t now);
|
||||
STATIC uint32_t circuit_max_queued_cell_age(const circuit_t *c, uint32_t now);
|
||||
STATIC uint32_t circuit_max_queued_item_age(const circuit_t *c, uint32_t now);
|
||||
#endif /* defined(CIRCUITLIST_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CIRCUITLIST_H) */
|
||||
@@ -0,0 +1,218 @@
|
||||
/* * Copyright (c) 2012-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file circuitmux.h
|
||||
* \brief Header file for circuitmux.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_CIRCUITMUX_H
|
||||
#define TOR_CIRCUITMUX_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
#include "lib/testsupport/testsupport.h"
|
||||
|
||||
typedef struct circuitmux_policy_t circuitmux_policy_t;
|
||||
typedef struct circuitmux_policy_data_t circuitmux_policy_data_t;
|
||||
typedef struct circuitmux_policy_circ_data_t circuitmux_policy_circ_data_t;
|
||||
|
||||
struct circuitmux_policy_t {
|
||||
/* Allocate cmux-wide policy-specific data */
|
||||
circuitmux_policy_data_t * (*alloc_cmux_data)(circuitmux_t *cmux);
|
||||
/* Free cmux-wide policy-specific data */
|
||||
void (*free_cmux_data)(circuitmux_t *cmux,
|
||||
circuitmux_policy_data_t *pol_data);
|
||||
/* Allocate circuit policy-specific data for a newly attached circuit */
|
||||
circuitmux_policy_circ_data_t *
|
||||
(*alloc_circ_data)(circuitmux_t *cmux,
|
||||
circuitmux_policy_data_t *pol_data,
|
||||
circuit_t *circ,
|
||||
cell_direction_t direction,
|
||||
unsigned int cell_count);
|
||||
/* Free circuit policy-specific data */
|
||||
void (*free_circ_data)(circuitmux_t *cmux,
|
||||
circuitmux_policy_data_t *pol_data,
|
||||
circuit_t *circ,
|
||||
circuitmux_policy_circ_data_t *pol_circ_data);
|
||||
/* Notify that a circuit has become active/inactive */
|
||||
void (*notify_circ_active)(circuitmux_t *cmux,
|
||||
circuitmux_policy_data_t *pol_data,
|
||||
circuit_t *circ,
|
||||
circuitmux_policy_circ_data_t *pol_circ_data);
|
||||
void (*notify_circ_inactive)(circuitmux_t *cmux,
|
||||
circuitmux_policy_data_t *pol_data,
|
||||
circuit_t *circ,
|
||||
circuitmux_policy_circ_data_t *pol_circ_data);
|
||||
/* Notify of arriving/transmitted cells on a circuit */
|
||||
void (*notify_set_n_cells)(circuitmux_t *cmux,
|
||||
circuitmux_policy_data_t *pol_data,
|
||||
circuit_t *circ,
|
||||
circuitmux_policy_circ_data_t *pol_circ_data,
|
||||
unsigned int n_cells);
|
||||
void (*notify_xmit_cells)(circuitmux_t *cmux,
|
||||
circuitmux_policy_data_t *pol_data,
|
||||
circuit_t *circ,
|
||||
circuitmux_policy_circ_data_t *pol_circ_data,
|
||||
unsigned int n_cells);
|
||||
/* Choose a circuit */
|
||||
circuit_t * (*pick_active_circuit)(circuitmux_t *cmux,
|
||||
circuitmux_policy_data_t *pol_data);
|
||||
/* Optional: channel comparator for use by the scheduler */
|
||||
int (*cmp_cmux)(circuitmux_t *cmux_1, circuitmux_policy_data_t *pol_data_1,
|
||||
circuitmux_t *cmux_2, circuitmux_policy_data_t *pol_data_2);
|
||||
};
|
||||
|
||||
/*
|
||||
* Circuitmux policy implementations can subclass this to store circuitmux-
|
||||
* wide data; it just has the magic number in the base struct.
|
||||
*/
|
||||
|
||||
struct circuitmux_policy_data_t {
|
||||
uint32_t magic;
|
||||
};
|
||||
|
||||
/*
|
||||
* Circuitmux policy implementations can subclass this to store circuit-
|
||||
* specific data; it just has the magic number in the base struct.
|
||||
*/
|
||||
|
||||
struct circuitmux_policy_circ_data_t {
|
||||
uint32_t magic;
|
||||
};
|
||||
|
||||
/*
|
||||
* Upcast #defines for the above types
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert a circuitmux_policy_data_t subtype to a circuitmux_policy_data_t.
|
||||
*/
|
||||
|
||||
#define TO_CMUX_POL_DATA(x) (&((x)->base_))
|
||||
|
||||
/**
|
||||
* Convert a circuitmux_policy_circ_data_t subtype to a
|
||||
* circuitmux_policy_circ_data_t.
|
||||
*/
|
||||
|
||||
#define TO_CMUX_POL_CIRC_DATA(x) (&((x)->base_))
|
||||
|
||||
/* Consistency check */
|
||||
void circuitmux_assert_okay(circuitmux_t *cmux);
|
||||
|
||||
/* Create/destroy */
|
||||
circuitmux_t * circuitmux_alloc(void);
|
||||
void circuitmux_detach_all_circuits(circuitmux_t *cmux,
|
||||
smartlist_t *detached_out);
|
||||
void circuitmux_free_(circuitmux_t *cmux);
|
||||
#define circuitmux_free(cmux) \
|
||||
FREE_AND_NULL(circuitmux_t, circuitmux_free_, (cmux))
|
||||
|
||||
/* Policy control */
|
||||
void circuitmux_clear_policy(circuitmux_t *cmux);
|
||||
MOCK_DECL(const circuitmux_policy_t *,
|
||||
circuitmux_get_policy, (circuitmux_t *cmux));
|
||||
void circuitmux_set_policy(circuitmux_t *cmux,
|
||||
const circuitmux_policy_t *pol);
|
||||
|
||||
/* Status inquiries */
|
||||
cell_direction_t circuitmux_attached_circuit_direction(
|
||||
circuitmux_t *cmux,
|
||||
circuit_t *circ);
|
||||
int circuitmux_is_circuit_attached(circuitmux_t *cmux, circuit_t *circ);
|
||||
int circuitmux_is_circuit_active(circuitmux_t *cmux, circuit_t *circ);
|
||||
unsigned int circuitmux_num_cells_for_circuit(circuitmux_t *cmux,
|
||||
circuit_t *circ);
|
||||
MOCK_DECL(unsigned int, circuitmux_num_cells, (circuitmux_t *cmux));
|
||||
unsigned int circuitmux_num_circuits(circuitmux_t *cmux);
|
||||
unsigned int circuitmux_num_active_circuits(circuitmux_t *cmux);
|
||||
|
||||
/* Debugging interface - slow. */
|
||||
int64_t circuitmux_count_queued_destroy_cells(const channel_t *chan,
|
||||
const circuitmux_t *cmux);
|
||||
|
||||
/* Channel interface */
|
||||
circuit_t * circuitmux_get_first_active_circuit(circuitmux_t *cmux,
|
||||
destroy_cell_queue_t **destroy_queue_out);
|
||||
void circuitmux_notify_xmit_cells(circuitmux_t *cmux, circuit_t *circ,
|
||||
unsigned int n_cells);
|
||||
void circuitmux_notify_xmit_destroy(circuitmux_t *cmux);
|
||||
|
||||
/* Circuit interface */
|
||||
MOCK_DECL(void, circuitmux_attach_circuit, (circuitmux_t *cmux,
|
||||
circuit_t *circ,
|
||||
cell_direction_t direction));
|
||||
MOCK_DECL(void, circuitmux_detach_circuit,
|
||||
(circuitmux_t *cmux, circuit_t *circ));
|
||||
void circuitmux_clear_num_cells(circuitmux_t *cmux, circuit_t *circ);
|
||||
void circuitmux_set_num_cells(circuitmux_t *cmux, circuit_t *circ,
|
||||
unsigned int n_cells);
|
||||
|
||||
void circuitmux_append_destroy_cell(channel_t *chan,
|
||||
circuitmux_t *cmux, circid_t circ_id,
|
||||
uint8_t reason);
|
||||
void circuitmux_mark_destroyed_circids_usable(circuitmux_t *cmux,
|
||||
channel_t *chan);
|
||||
|
||||
/* Optional interchannel comparisons for scheduling */
|
||||
MOCK_DECL(int, circuitmux_compare_muxes,
|
||||
(circuitmux_t *cmux_1, circuitmux_t *cmux_2));
|
||||
|
||||
#ifdef CIRCUITMUX_PRIVATE
|
||||
|
||||
#include "core/or/destroy_cell_queue_st.h"
|
||||
|
||||
/*
|
||||
* Map of muxinfos for circuitmux_t to use; struct is defined below (name
|
||||
* of struct must match HT_HEAD line).
|
||||
*/
|
||||
typedef HT_HEAD(chanid_circid_muxinfo_map, chanid_circid_muxinfo_t)
|
||||
chanid_circid_muxinfo_map_t;
|
||||
|
||||
/*
|
||||
* Structures for circuitmux.c
|
||||
*/
|
||||
|
||||
struct circuitmux_t {
|
||||
/* Keep count of attached, active circuits */
|
||||
unsigned int n_circuits, n_active_circuits;
|
||||
|
||||
/* Total number of queued cells on all circuits */
|
||||
unsigned int n_cells;
|
||||
|
||||
/*
|
||||
* Map from (channel ID, circuit ID) pairs to circuit_muxinfo_t
|
||||
*/
|
||||
chanid_circid_muxinfo_map_t *chanid_circid_map;
|
||||
|
||||
/** List of queued destroy cells */
|
||||
destroy_cell_queue_t destroy_cell_queue;
|
||||
/** Boolean: True iff the last cell to circuitmux_get_first_active_circuit
|
||||
* returned the destroy queue. Used to force alternation between
|
||||
* destroy/non-destroy cells.
|
||||
*
|
||||
* XXXX There is no reason to think that alternating is a particularly good
|
||||
* approach -- it's just designed to prevent destroys from starving other
|
||||
* cells completely.
|
||||
*/
|
||||
unsigned int last_cell_was_destroy : 1;
|
||||
/** Destroy counter: increment this when a destroy gets queued, decrement
|
||||
* when we unqueue it, so we can test to make sure they don't starve.
|
||||
*/
|
||||
int64_t destroy_ctr;
|
||||
|
||||
/*
|
||||
* Circuitmux policy; if this is non-NULL, it can override the built-
|
||||
* in round-robin active circuits behavior. This is how EWMA works in
|
||||
* the new circuitmux_t world.
|
||||
*/
|
||||
const circuitmux_policy_t *policy;
|
||||
|
||||
/* Policy-specific data */
|
||||
circuitmux_policy_data_t *policy_data;
|
||||
};
|
||||
|
||||
#endif /* defined(CIRCUITMUX_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CIRCUITMUX_H) */
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/* * Copyright (c) 2012-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file circuitmux_ewma.h
|
||||
* \brief Header file for circuitmux_ewma.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_CIRCUITMUX_EWMA_H
|
||||
#define TOR_CIRCUITMUX_EWMA_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
#include "core/or/circuitmux.h"
|
||||
|
||||
/* The public EWMA policy callbacks object. */
|
||||
extern circuitmux_policy_t ewma_policy;
|
||||
|
||||
/* Externally visible EWMA functions */
|
||||
void cmux_ewma_set_options(const or_options_t *options,
|
||||
const networkstatus_t *consensus);
|
||||
|
||||
void circuitmux_ewma_free_all(void);
|
||||
|
||||
#ifdef CIRCUITMUX_EWMA_PRIVATE
|
||||
|
||||
/*** EWMA structures ***/
|
||||
|
||||
typedef struct cell_ewma_t cell_ewma_t;
|
||||
typedef struct ewma_policy_data_t ewma_policy_data_t;
|
||||
typedef struct ewma_policy_circ_data_t ewma_policy_circ_data_t;
|
||||
|
||||
/**
|
||||
* The cell_ewma_t structure keeps track of how many cells a circuit has
|
||||
* transferred recently. It keeps an EWMA (exponentially weighted moving
|
||||
* average) of the number of cells flushed from the circuit queue onto a
|
||||
* connection in channel_flush_from_first_active_circuit().
|
||||
*/
|
||||
|
||||
struct cell_ewma_t {
|
||||
/** The last 'tick' at which we recalibrated cell_count.
|
||||
*
|
||||
* A cell sent at exactly the start of this tick has weight 1.0. Cells sent
|
||||
* since the start of this tick have weight greater than 1.0; ones sent
|
||||
* earlier have less weight. */
|
||||
unsigned int last_adjusted_tick;
|
||||
/** The EWMA of the cell count. */
|
||||
double cell_count;
|
||||
/** True iff this is the cell count for a circuit's previous
|
||||
* channel. */
|
||||
unsigned int is_for_p_chan : 1;
|
||||
/** The position of the circuit within the OR connection's priority
|
||||
* queue. */
|
||||
int heap_index;
|
||||
};
|
||||
|
||||
struct ewma_policy_data_t {
|
||||
circuitmux_policy_data_t base_;
|
||||
|
||||
/**
|
||||
* Priority queue of cell_ewma_t for circuits with queued cells waiting
|
||||
* for room to free up on the channel that owns this circuitmux. Kept
|
||||
* in heap order according to EWMA. This was formerly in channel_t, and
|
||||
* in or_connection_t before that.
|
||||
*/
|
||||
smartlist_t *active_circuit_pqueue;
|
||||
|
||||
/**
|
||||
* The tick on which the cell_ewma_ts in active_circuit_pqueue last had
|
||||
* their ewma values rescaled. This was formerly in channel_t, and in
|
||||
* or_connection_t before that.
|
||||
*/
|
||||
unsigned int active_circuit_pqueue_last_recalibrated;
|
||||
};
|
||||
|
||||
struct ewma_policy_circ_data_t {
|
||||
circuitmux_policy_circ_data_t base_;
|
||||
|
||||
/**
|
||||
* The EWMA count for the number of cells flushed from this circuit
|
||||
* onto this circuitmux. Used to determine which circuit to flush
|
||||
* from next. This was formerly in circuit_t and or_circuit_t.
|
||||
*/
|
||||
cell_ewma_t cell_ewma;
|
||||
|
||||
/**
|
||||
* Pointer back to the circuit_t this is for; since we're separating
|
||||
* out circuit selection policy like this, we can't attach cell_ewma_t
|
||||
* to the circuit_t any more, so we can't use SUBTYPE_P directly to a
|
||||
* circuit_t like before; instead get it here.
|
||||
*/
|
||||
circuit_t *circ;
|
||||
};
|
||||
|
||||
#define EWMA_POL_DATA_MAGIC 0x2fd8b16aU
|
||||
#define EWMA_POL_CIRC_DATA_MAGIC 0x761e7747U
|
||||
|
||||
/*** Downcasts for the above types ***/
|
||||
|
||||
/**
|
||||
* Downcast a circuitmux_policy_data_t to an ewma_policy_data_t and assert
|
||||
* if the cast is impossible.
|
||||
*/
|
||||
|
||||
static inline ewma_policy_data_t *
|
||||
TO_EWMA_POL_DATA(circuitmux_policy_data_t *pol)
|
||||
{
|
||||
if (!pol) return NULL;
|
||||
else {
|
||||
tor_assertf(pol->magic == EWMA_POL_DATA_MAGIC,
|
||||
"Mismatch: %"PRIu32" != %"PRIu32,
|
||||
pol->magic, EWMA_POL_DATA_MAGIC);
|
||||
return DOWNCAST(ewma_policy_data_t, pol);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Downcast a circuitmux_policy_circ_data_t to an ewma_policy_circ_data_t
|
||||
* and assert if the cast is impossible.
|
||||
*/
|
||||
|
||||
static inline ewma_policy_circ_data_t *
|
||||
TO_EWMA_POL_CIRC_DATA(circuitmux_policy_circ_data_t *pol)
|
||||
{
|
||||
if (!pol) return NULL;
|
||||
else {
|
||||
tor_assertf(pol->magic == EWMA_POL_CIRC_DATA_MAGIC,
|
||||
"Mismatch: %"PRIu32" != %"PRIu32,
|
||||
pol->magic, EWMA_POL_CIRC_DATA_MAGIC);
|
||||
return DOWNCAST(ewma_policy_circ_data_t, pol);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC unsigned cell_ewma_get_current_tick_and_fraction(double *remainder_out);
|
||||
STATIC void cell_ewma_initialize_ticks(void);
|
||||
|
||||
#endif /* defined(CIRCUITMUX_EWMA_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CIRCUITMUX_EWMA_H) */
|
||||
@@ -0,0 +1,832 @@
|
||||
/*
|
||||
* Copyright (c) 2017-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file circuitpadding.h
|
||||
* \brief Header file for circuitpadding.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CIRCUITPADDING_H
|
||||
#define TOR_CIRCUITPADDING_H
|
||||
|
||||
#include "trunnel/circpad_negotiation.h"
|
||||
#include "lib/evloop/timers.h"
|
||||
|
||||
struct circuit_t;
|
||||
struct origin_circuit_t;
|
||||
struct cell_t;
|
||||
|
||||
/**
|
||||
* Signed error return with the specific property that negative
|
||||
* values mean error codes of various semantics, 0 means success,
|
||||
* and positive values are unused.
|
||||
*
|
||||
* XXX: Tor uses this concept a lot but just calls it int. Should we move
|
||||
* this somewhere centralized? Where?
|
||||
*/
|
||||
typedef int signed_error_t;
|
||||
|
||||
/**
|
||||
* These constants specify the types of events that can cause
|
||||
* transitions between state machine states.
|
||||
*
|
||||
* Note that SENT and RECV are relative to this endpoint. For
|
||||
* relays, SENT means packets destined towards the client and
|
||||
* RECV means packets destined towards the relay. On the client,
|
||||
* SENT means packets destined towards the relay, where as RECV
|
||||
* means packets destined towards the client.
|
||||
*/
|
||||
typedef enum {
|
||||
/* A non-padding cell was received. */
|
||||
CIRCPAD_EVENT_NONPADDING_RECV = 0,
|
||||
/* A non-padding cell was sent. */
|
||||
CIRCPAD_EVENT_NONPADDING_SENT = 1,
|
||||
/* A padding cell (RELAY_COMMAND_DROP) was sent. */
|
||||
CIRCPAD_EVENT_PADDING_SENT = 2,
|
||||
/* A padding cell was received. */
|
||||
CIRCPAD_EVENT_PADDING_RECV = 3,
|
||||
/* We tried to schedule padding but we ended up picking the infinity bin
|
||||
* which means that padding was delayed infinitely */
|
||||
CIRCPAD_EVENT_INFINITY = 4,
|
||||
/* All histogram bins are empty (we are out of tokens) */
|
||||
CIRCPAD_EVENT_BINS_EMPTY = 5,
|
||||
/* This state has used up its cell count */
|
||||
CIRCPAD_EVENT_LENGTH_COUNT = 6
|
||||
} circpad_event_t;
|
||||
#define CIRCPAD_NUM_EVENTS ((int)CIRCPAD_EVENT_LENGTH_COUNT+1)
|
||||
|
||||
/** Boolean type that says if we decided to transition states or not */
|
||||
typedef enum {
|
||||
CIRCPAD_STATE_UNCHANGED = 0,
|
||||
CIRCPAD_STATE_CHANGED = 1
|
||||
} circpad_decision_t;
|
||||
|
||||
/** The type for the things in histogram bins (aka tokens) */
|
||||
typedef uint32_t circpad_hist_token_t;
|
||||
|
||||
/** The type for histogram indexes (needs to be negative for errors) */
|
||||
typedef int8_t circpad_hist_index_t;
|
||||
|
||||
/** The type for absolute time, from monotime_absolute_usec() */
|
||||
typedef uint64_t circpad_time_t;
|
||||
|
||||
/** The type for timer delays, in microseconds */
|
||||
typedef uint32_t circpad_delay_t;
|
||||
#define CIRCPAD_DELAY_UNITS_PER_SECOND (1000*1000)
|
||||
|
||||
/**
|
||||
* An infinite padding cell delay means don't schedule any padding --
|
||||
* simply wait until a different event triggers a transition.
|
||||
*
|
||||
* This means that the maximum delay we can schedule is UINT32_MAX-1
|
||||
* microseconds, or about 4300 seconds (1.25 hours).
|
||||
* XXX: Is this enough if we want to simulate light, intermittent
|
||||
* activity on an onion service?
|
||||
*/
|
||||
#define CIRCPAD_DELAY_INFINITE (UINT32_MAX)
|
||||
|
||||
/**
|
||||
* This is the maximum delay that the circuit padding system can have, in
|
||||
* seconds.
|
||||
*/
|
||||
#define CIRCPAD_DELAY_MAX_SECS \
|
||||
((CIRCPAD_DELAY_INFINITE/CIRCPAD_DELAY_UNITS_PER_SECOND)+1)
|
||||
|
||||
/**
|
||||
* Macro to clarify when we're checking the infinity bin.
|
||||
*
|
||||
* Works with either circpad_state_t or circpad_machine_runtime_t
|
||||
*/
|
||||
#define CIRCPAD_INFINITY_BIN(mi) ((mi)->histogram_len-1)
|
||||
|
||||
/**
|
||||
* These constants form a bitfield that specifies when a state machine
|
||||
* should be applied to a circuit.
|
||||
*
|
||||
* If any of these elements is set, then the circuit will be tested against
|
||||
* that specific condition. If an element is unset, then we don't test it.
|
||||
* (E.g., if neither NO_STREAMS or STREAMS are set, then we will not care
|
||||
* whether a circuit has streams attached when we apply a state machine.)
|
||||
*
|
||||
* The helper function circpad_circuit_state() converts circuit state
|
||||
* flags into this more compact representation.
|
||||
*/
|
||||
typedef enum {
|
||||
/* Only apply machine if the circuit is still building */
|
||||
CIRCPAD_CIRC_BUILDING = 1<<0,
|
||||
/* Only apply machine if the circuit is open */
|
||||
CIRCPAD_CIRC_OPENED = 1<<1,
|
||||
/* Only apply machine if the circuit has no attached streams */
|
||||
CIRCPAD_CIRC_NO_STREAMS = 1<<2,
|
||||
/* Only apply machine if the circuit has attached streams */
|
||||
CIRCPAD_CIRC_STREAMS = 1<<3,
|
||||
/* Only apply machine if the circuit still allows RELAY_EARLY cells */
|
||||
CIRCPAD_CIRC_HAS_RELAY_EARLY = 1<<4,
|
||||
/* Only apply machine if the circuit has depleted its RELAY_EARLY cells
|
||||
* allowance. */
|
||||
CIRCPAD_CIRC_HAS_NO_RELAY_EARLY = 1<<5
|
||||
} circpad_circuit_state_t;
|
||||
|
||||
/** Bitmask that says "apply this machine to all states" */
|
||||
#define CIRCPAD_STATE_ALL \
|
||||
(CIRCPAD_CIRC_BUILDING|CIRCPAD_CIRC_OPENED| \
|
||||
CIRCPAD_CIRC_STREAMS|CIRCPAD_CIRC_NO_STREAMS| \
|
||||
CIRCPAD_CIRC_HAS_RELAY_EARLY|CIRCPAD_CIRC_HAS_NO_RELAY_EARLY)
|
||||
|
||||
/**
|
||||
* A compact circuit purpose bitfield mask that allows us to compactly
|
||||
* specify which circuit purposes a machine should apply to.
|
||||
*
|
||||
* The helper function circpad_circ_purpose_to_mask() converts circuit
|
||||
* purposes into bit positions in this bitmask.
|
||||
*/
|
||||
typedef uint32_t circpad_purpose_mask_t;
|
||||
|
||||
/** Bitmask that says "apply this machine to all purposes". */
|
||||
#define CIRCPAD_PURPOSE_ALL (0xFFFFFFFF)
|
||||
|
||||
/**
|
||||
* This type specifies all of the conditions that must be met before
|
||||
* a client decides to initiate padding on a circuit.
|
||||
*
|
||||
* A circuit must satisfy every sub-field in this type in order
|
||||
* to be considered to match the conditions.
|
||||
*/
|
||||
typedef struct circpad_machine_conditions_t {
|
||||
/** Only apply the machine *if* the circuit has at least this many hops */
|
||||
unsigned min_hops : 3;
|
||||
|
||||
/** Only apply the machine *if* vanguards are enabled */
|
||||
unsigned requires_vanguards : 1;
|
||||
|
||||
/**
|
||||
* This machine is ok to use if reduced padding is set in consensus
|
||||
* or torrc. This machine will still be applied even if reduced padding
|
||||
* is not set; this flag only acts to exclude machines that don't have
|
||||
* it set when reduced padding is requested. Therefore, reduced padding
|
||||
* machines should appear at the lowest priority in the padding machine
|
||||
* lists (aka first in the list), so that non-reduced padding machines
|
||||
* for the same purpose are given a chance to apply when reduced padding
|
||||
* is not requested. */
|
||||
unsigned reduced_padding_ok : 1;
|
||||
|
||||
/** Only apply the machine *if* the circuit's state matches any of
|
||||
* the bits set in this bitmask. */
|
||||
circpad_circuit_state_t apply_state_mask;
|
||||
|
||||
/** Only apply a machine *if* the circuit's purpose matches one
|
||||
* of the bits set in this bitmask */
|
||||
circpad_purpose_mask_t apply_purpose_mask;
|
||||
|
||||
/** Keep a machine if any of the circuits's state machine's match
|
||||
* the bits set in this bitmask, but don't apply new machines if
|
||||
* they match this mask. */
|
||||
circpad_circuit_state_t keep_state_mask;
|
||||
|
||||
/** Keep a machine if any of the circuits's state machine's match
|
||||
* the bits set in this bitmask, but don't apply new machines if
|
||||
* they match this mask. */
|
||||
circpad_purpose_mask_t keep_purpose_mask;
|
||||
|
||||
} circpad_machine_conditions_t;
|
||||
|
||||
/**
|
||||
* Token removal strategy options.
|
||||
*
|
||||
* The WTF-PAD histograms are meant to specify a target distribution to shape
|
||||
* traffic towards. This is accomplished by removing tokens from the histogram
|
||||
* when either padding or non-padding cells are sent.
|
||||
*
|
||||
* When we see a non-padding cell at a particular time since the last cell, you
|
||||
* remove a token from the corresponding delay bin. These flags specify
|
||||
* which bin to choose if that bin is already empty.
|
||||
*/
|
||||
typedef enum {
|
||||
/** Don't remove any tokens */
|
||||
CIRCPAD_TOKEN_REMOVAL_NONE = 0,
|
||||
/**
|
||||
* Remove from the first non-zero higher bin index when current is zero.
|
||||
* This is the recommended strategy from the Adaptive Padding paper. */
|
||||
CIRCPAD_TOKEN_REMOVAL_HIGHER = 1,
|
||||
/** Remove from the first non-zero lower bin index when current is empty. */
|
||||
CIRCPAD_TOKEN_REMOVAL_LOWER = 2,
|
||||
/** Remove from the closest non-zero bin index when current is empty. */
|
||||
CIRCPAD_TOKEN_REMOVAL_CLOSEST = 3,
|
||||
/** Remove from the closest bin by time value (since bins are
|
||||
* exponentially spaced). */
|
||||
CIRCPAD_TOKEN_REMOVAL_CLOSEST_USEC = 4,
|
||||
/** Only remove from the exact bin corresponding to this delay. If
|
||||
* the bin is 0, simply do nothing. Don't pick another bin. */
|
||||
CIRCPAD_TOKEN_REMOVAL_EXACT = 5
|
||||
} circpad_removal_t;
|
||||
|
||||
/**
|
||||
* Distribution types supported by circpad_distribution_sample().
|
||||
*
|
||||
* These can be used instead of histograms for the inter-packet
|
||||
* timing distribution, or to specify a distribution on the number
|
||||
* of cells that can be sent while in a specific state of the state
|
||||
* machine.
|
||||
*
|
||||
* Each distribution takes up to two parameters which are described below. */
|
||||
typedef enum {
|
||||
/* No probability distribution is used */
|
||||
CIRCPAD_DIST_NONE = 0,
|
||||
/* Uniform distribution: param1 is lower bound and param2 is upper bound */
|
||||
CIRCPAD_DIST_UNIFORM = 1,
|
||||
/* Logistic distribution: param1 is Mu, param2 is sigma. */
|
||||
CIRCPAD_DIST_LOGISTIC = 2,
|
||||
/* Log-logistic distribution: param1 is Alpha, param2 is 1.0/Beta */
|
||||
CIRCPAD_DIST_LOG_LOGISTIC = 3,
|
||||
/* Geometric distribution: param1 is 'p' (success probability) */
|
||||
CIRCPAD_DIST_GEOMETRIC = 4,
|
||||
/* Weibull distribution: param1 is k, param2 is Lambda */
|
||||
CIRCPAD_DIST_WEIBULL = 5,
|
||||
/* Generalized Pareto distribution: param1 is sigma, param2 is xi */
|
||||
CIRCPAD_DIST_PARETO = 6
|
||||
} circpad_distribution_type_t;
|
||||
|
||||
/**
|
||||
* Distribution information.
|
||||
*
|
||||
* This type specifies a specific distribution above, as well as
|
||||
* up to two parameters for that distribution. The specific
|
||||
* per-distribution meaning of these parameters is specified
|
||||
* in circpad_distribution_sample().
|
||||
*/
|
||||
typedef struct circpad_distribution_t {
|
||||
circpad_distribution_type_t type;
|
||||
double param1;
|
||||
double param2;
|
||||
} circpad_distribution_t;
|
||||
|
||||
/** State number type. Represents current state of state machine. */
|
||||
typedef uint16_t circpad_statenum_t;
|
||||
#define CIRCPAD_STATENUM_MAX (UINT16_MAX)
|
||||
|
||||
/** A histogram can be used to sample padding delays given a machine state.
|
||||
* This constant defines the maximum histogram width (i.e. the max number of
|
||||
* bins).
|
||||
*
|
||||
* The current limit is arbitrary and could be raised if there is a need,
|
||||
* however too many bins will be hard to serialize in the future.
|
||||
*
|
||||
* Memory concerns are not so great here since the corresponding histogram and
|
||||
* histogram_edges arrays are global and not per-circuit.
|
||||
*
|
||||
* If we ever upgrade this to a value that can't be represented by 8-bits we
|
||||
* also need to upgrade circpad_hist_index_t.
|
||||
*/
|
||||
#define CIRCPAD_MAX_HISTOGRAM_LEN (100)
|
||||
|
||||
/**
|
||||
* A state of a padding state machine. The information here are immutable and
|
||||
* represent the initial form of the state; it does not get updated as things
|
||||
* happen. The mutable information that gets updated in runtime are carried in
|
||||
* a circpad_machine_runtime_t.
|
||||
*
|
||||
* This struct describes the histograms and/or probability distributions, as
|
||||
* well as parameters of a single state in the adaptive padding machine.
|
||||
* Instances of this struct exist in global circpad machine definitions that
|
||||
* come from torrc or the consensus.
|
||||
*/
|
||||
typedef struct circpad_state_t {
|
||||
/**
|
||||
* If a histogram is used for this state, this specifies the number of bins
|
||||
* of this histogram. Histograms must have at least 2 bins.
|
||||
*
|
||||
* In particular, the following histogram:
|
||||
*
|
||||
* Tokens
|
||||
* +
|
||||
* 10 | +----+
|
||||
* 9 | | | +---------+
|
||||
* 8 | | | | |
|
||||
* 7 | | | +-----+ |
|
||||
* 6 +----+ Bin+-----+ | +---------------+
|
||||
* 5 | | #1 | | | | |
|
||||
* | Bin| | Bin | Bin | Bin #4 | Bin #5 |
|
||||
* | #0 | | #2 | #3 | | (infinity bin)|
|
||||
* | | | | | | |
|
||||
* | | | | | | |
|
||||
* 0 +----+----+-----+-----+---------+---------------+
|
||||
* 0 100 200 350 500 1000 inf microseconds
|
||||
*
|
||||
* would be specified the following way:
|
||||
* histogram_len = 6;
|
||||
* histogram[] = { 6, 10, 6, 7, 9, 6 }
|
||||
* histogram_edges[] = { 0, 100, 200, 350, 500, 1000 }
|
||||
*
|
||||
* The final bin is called the "infinity bin" and if it's chosen we don't
|
||||
* schedule any padding. The infinity bin is strange because its lower edge
|
||||
* is the max value of possible non-infinite delay allowed by this histogram,
|
||||
* and its upper edge is CIRCPAD_DELAY_INFINITE. You can tell if the infinity
|
||||
* bin is chosen by inspecting its bin index or inspecting its upper edge.
|
||||
*
|
||||
* If a delay probability distribution is used for this state, this is set
|
||||
* to 0. */
|
||||
circpad_hist_index_t histogram_len;
|
||||
/** The histogram itself: an array of uint16s of tokens, whose
|
||||
* widths are exponentially spaced, in microseconds.
|
||||
*
|
||||
* This array must have histogram_len elements that are strictly
|
||||
* monotonically increasing. */
|
||||
circpad_hist_token_t histogram[CIRCPAD_MAX_HISTOGRAM_LEN];
|
||||
/* The histogram bin edges in usec.
|
||||
*
|
||||
* Each element of this array specifies the left edge of the corresponding
|
||||
* bin. The rightmost edge is always infinity and is not specified in this
|
||||
* array.
|
||||
*
|
||||
* This array must have histogram_len elements. */
|
||||
circpad_delay_t histogram_edges[CIRCPAD_MAX_HISTOGRAM_LEN+1];
|
||||
/** Total number of tokens in this histogram. This is a constant and is *not*
|
||||
* decremented every time we spend a token. It's used for initializing and
|
||||
* refilling the histogram. */
|
||||
uint32_t histogram_total_tokens;
|
||||
|
||||
/**
|
||||
* Represents a delay probability distribution (aka IAT distribution). It's a
|
||||
* parametrized way of encoding inter-packet delay information in
|
||||
* microseconds. It can be used instead of histograms.
|
||||
*
|
||||
* If it is used, token_removal below must be set to
|
||||
* CIRCPAD_TOKEN_REMOVAL_NONE.
|
||||
*
|
||||
* Start_usec, range_sec, and rtt_estimates are still applied to the
|
||||
* results of sampling from this distribution (range_sec is used as a max).
|
||||
*/
|
||||
circpad_distribution_t iat_dist;
|
||||
/* If a delay probability distribution is used, this is used as the max
|
||||
* value we can sample from the distribution. However, RTT measurements and
|
||||
* dist_added_shift gets applied on top of this value to derive the final
|
||||
* padding delay. */
|
||||
circpad_delay_t dist_max_sample_usec;
|
||||
/* If a delay probability distribution is used and this is set, we will add
|
||||
* this value on top of the value sampled from the IAT distribution to
|
||||
* derive the final padding delay (We also add the RTT measurement if it's
|
||||
* enabled.). */
|
||||
circpad_delay_t dist_added_shift_usec;
|
||||
|
||||
/**
|
||||
* The length dist is a parameterized way of encoding how long this
|
||||
* state machine runs in terms of sent padding cells or all
|
||||
* sent cells. Values are sampled from this distribution, clamped
|
||||
* to max_len, and then start_len is added to that value.
|
||||
*
|
||||
* It may be specified instead of or in addition to
|
||||
* the infinity bins and bins empty conditions. */
|
||||
circpad_distribution_t length_dist;
|
||||
/** A minimum length value, added to the output of length_dist */
|
||||
uint16_t start_length;
|
||||
/** A cap on the length value that can be sampled from the length_dist */
|
||||
uint64_t max_length;
|
||||
|
||||
/** Should we decrement length when we see a nonpadding packet?
|
||||
* XXX: Are there any machines that actually want to set this to 0? There may
|
||||
* not be. OTOH, it's only a bit.. */
|
||||
unsigned length_includes_nonpadding : 1;
|
||||
|
||||
/**
|
||||
* This is an array that specifies the next state to transition to upon
|
||||
* receipt an event matching the indicated array index.
|
||||
*
|
||||
* This aborts our scheduled packet and switches to the state
|
||||
* corresponding to the index of the array. Tokens are filled upon
|
||||
* this transition.
|
||||
*
|
||||
* States are allowed to transition to themselves, which means re-schedule
|
||||
* a new padding timer. They are also allowed to temporarily "transition"
|
||||
* to the "IGNORE" and "CANCEL" pseudo-states. See defines below
|
||||
* for details on state behavior and meaning.
|
||||
*/
|
||||
circpad_statenum_t next_state[CIRCPAD_NUM_EVENTS];
|
||||
|
||||
/**
|
||||
* If true, estimate the RTT from this relay to the exit/website and add that
|
||||
* to start_usec for use as the histogram bin 0 start delay.
|
||||
*
|
||||
* Right now this is only supported for relay-side state machines.
|
||||
*/
|
||||
unsigned use_rtt_estimate : 1;
|
||||
|
||||
/** This specifies the token removal strategy to use upon padding and
|
||||
* non-padding activity. */
|
||||
circpad_removal_t token_removal;
|
||||
} circpad_state_t;
|
||||
|
||||
/**
|
||||
* The start state for this machine.
|
||||
*
|
||||
* In the original WTF-PAD, this is only used for transition to/from
|
||||
* the burst state. All other fields are not used. But to simplify the
|
||||
* code we've made it a first-class state. This has no performance
|
||||
* consequences, but may make naive serialization of the state machine
|
||||
* large, if we're not careful about how we represent empty fields.
|
||||
*/
|
||||
#define CIRCPAD_STATE_START 0
|
||||
|
||||
/**
|
||||
* The burst state for this machine.
|
||||
*
|
||||
* In the original Adaptive Padding algorithm and in WTF-PAD
|
||||
* (https://www.freehaven.net/anonbib/cache/ShWa-Timing06.pdf and
|
||||
* https://www.cs.kau.se/pulls/hot/thebasketcase-wtfpad/), the burst
|
||||
* state serves to detect bursts in traffic. This is done by using longer
|
||||
* delays in its histogram, which represent the expected delays between
|
||||
* bursts of packets in the target stream. If this delay expires without a
|
||||
* real packet being sent, the burst state sends a padding packet and then
|
||||
* immediately transitions to the gap state, which is used to generate
|
||||
* a synthetic padding packet train. In this implementation, this transition
|
||||
* needs to be explicitly specified in the burst state's transition events.
|
||||
*
|
||||
* Because of this flexibility, other padding mechanisms can transition
|
||||
* between these two states arbitrarily, to encode other dynamics of
|
||||
* target traffic.
|
||||
*/
|
||||
#define CIRCPAD_STATE_BURST 1
|
||||
|
||||
/**
|
||||
* The gap state for this machine.
|
||||
*
|
||||
* In the original Adaptive Padding algorithm and in WTF-PAD, the gap
|
||||
* state serves to simulate an artificial packet train composed of padding
|
||||
* packets. It does this by specifying much lower inter-packet delays than
|
||||
* the burst state, and transitioning back to itself after padding is sent
|
||||
* if these timers expire before real traffic is sent. If real traffic is
|
||||
* sent, it transitions back to the burst state.
|
||||
*
|
||||
* Again, in this implementation, these transitions must be specified
|
||||
* explicitly, and other transitions are also permitted.
|
||||
*/
|
||||
#define CIRCPAD_STATE_GAP 2
|
||||
|
||||
/**
|
||||
* End is a pseudo-state that causes the machine to go completely
|
||||
* idle, and optionally get torn down (depending on the
|
||||
* value of circpad_machine_spec_t.should_negotiate_end)
|
||||
*
|
||||
* End MUST NOT occupy a slot in the machine state array.
|
||||
*/
|
||||
#define CIRCPAD_STATE_END CIRCPAD_STATENUM_MAX
|
||||
|
||||
/**
|
||||
* "Ignore" is a pseudo-state that means "do not react to this
|
||||
* event".
|
||||
*
|
||||
* "Ignore" MUST NOT occupy a slot in the machine state array.
|
||||
*/
|
||||
#define CIRCPAD_STATE_IGNORE (CIRCPAD_STATENUM_MAX-1)
|
||||
|
||||
/**
|
||||
* "Cancel" is a pseudo-state that means "cancel pending timers,
|
||||
* but remain in your current state".
|
||||
*
|
||||
* Cancel MUST NOT occupy a slot in the machine state array.
|
||||
*/
|
||||
#define CIRCPAD_STATE_CANCEL (CIRCPAD_STATENUM_MAX-2)
|
||||
|
||||
/**
|
||||
* Since we have 3 pseudo-states, the max state array length is
|
||||
* up to one less than cancel's statenum.
|
||||
*/
|
||||
#define CIRCPAD_MAX_MACHINE_STATES (CIRCPAD_STATE_CANCEL-1)
|
||||
|
||||
/**
|
||||
* Mutable padding machine info.
|
||||
*
|
||||
* This structure contains mutable information about a padding
|
||||
* machine. The mutable information must be kept separate because
|
||||
* it exists per-circuit, where as the machines themselves are global.
|
||||
* This separation is done to conserve space in the circuit structure.
|
||||
*
|
||||
* This is the per-circuit state that changes regarding the global state
|
||||
* machine. Some parts of it are optional (ie NULL).
|
||||
*
|
||||
* XXX: Play with layout to minimize space on x64 Linux (most common relay).
|
||||
*/
|
||||
typedef struct circpad_machine_runtime_t {
|
||||
/** The callback pointer for the padding callbacks.
|
||||
*
|
||||
* These timers stick around the machineinfo until the machineinfo's circuit
|
||||
* is closed, at which point the timer is cancelled. For this reason it's
|
||||
* safe to assume that the machineinfo exists if this timer gets
|
||||
* triggered. */
|
||||
tor_timer_t *padding_timer;
|
||||
|
||||
/** The circuit for this machine */
|
||||
struct circuit_t *on_circ;
|
||||
|
||||
/** A mutable copy of the histogram for the current state.
|
||||
* NULL if remove_tokens is false for that state */
|
||||
circpad_hist_token_t *histogram;
|
||||
/** Length of the above histogram.
|
||||
* XXX: This field *could* be removed at the expense of added
|
||||
* complexity+overhead for reaching back into the immutable machine
|
||||
* state every time we need to inspect the histogram. It's only a byte,
|
||||
* though, so it seemed worth it.
|
||||
*/
|
||||
circpad_hist_index_t histogram_len;
|
||||
/** Remove token from this index upon sending padding */
|
||||
circpad_hist_index_t chosen_bin;
|
||||
|
||||
/** Stop padding/transition if this many cells sent */
|
||||
uint64_t state_length;
|
||||
#define CIRCPAD_STATE_LENGTH_INFINITE UINT64_MAX
|
||||
|
||||
/** A scaled count of padding packets sent, used to limit padding overhead.
|
||||
* When this reaches UINT16_MAX, we cut it and nonpadding_sent in half. */
|
||||
uint16_t padding_sent;
|
||||
/** A scaled count of non-padding packets sent, used to limit padding
|
||||
* overhead. When this reaches UINT16_MAX, we cut it and padding_sent in
|
||||
* half. */
|
||||
uint16_t nonpadding_sent;
|
||||
|
||||
/**
|
||||
* Timestamp of the most recent cell event (sent, received, padding,
|
||||
* non-padding), in seconds from approx_time().
|
||||
*
|
||||
* Used as an emergency break to stop holding padding circuits open.
|
||||
*/
|
||||
time_t last_cell_time_sec;
|
||||
|
||||
/**
|
||||
* EWMA estimate of the RTT of the circuit from this hop
|
||||
* to the exit end, in microseconds. */
|
||||
circpad_delay_t rtt_estimate_usec;
|
||||
|
||||
/**
|
||||
* The last time we got an event relevant to estimating
|
||||
* the RTT. Monotonic time in microseconds since system
|
||||
* start.
|
||||
*/
|
||||
circpad_time_t last_received_time_usec;
|
||||
|
||||
/**
|
||||
* The time at which we scheduled a non-padding packet,
|
||||
* or selected an infinite delay.
|
||||
*
|
||||
* Monotonic time in microseconds since system start.
|
||||
* This is 0 if we haven't chosen a padding delay.
|
||||
*/
|
||||
circpad_time_t padding_scheduled_at_usec;
|
||||
|
||||
/** What state is this machine in? */
|
||||
circpad_statenum_t current_state;
|
||||
|
||||
/** Machine counter, for shutdown sync.
|
||||
*
|
||||
* Set from circuit_t.padding_machine_ctr, which is incremented each
|
||||
* padding machine instantiation.
|
||||
*/
|
||||
uint32_t machine_ctr;
|
||||
|
||||
/**
|
||||
* True if we have scheduled a timer for padding.
|
||||
*
|
||||
* This is 1 if a timer is pending. It is 0 if
|
||||
* no timer is scheduled. (It can be 0 even when
|
||||
* padding_was_scheduled_at_usec is non-zero).
|
||||
*/
|
||||
unsigned is_padding_timer_scheduled : 1;
|
||||
|
||||
/**
|
||||
* If this is true, we have seen full duplex behavior.
|
||||
* Stop updating the RTT.
|
||||
*/
|
||||
unsigned stop_rtt_update : 1;
|
||||
|
||||
/** Max number of padding machines on each circuit. If changed,
|
||||
* also ensure the machine_index bitwith supports the new size. */
|
||||
#define CIRCPAD_MAX_MACHINES (2)
|
||||
/** Which padding machine index was this for.
|
||||
* (make sure changes to the bitwidth can support the
|
||||
* CIRCPAD_MAX_MACHINES define). */
|
||||
unsigned machine_index : 1;
|
||||
|
||||
} circpad_machine_runtime_t;
|
||||
|
||||
/** Helper macro to get an actual state machine from a machineinfo */
|
||||
#define CIRCPAD_GET_MACHINE(machineinfo) \
|
||||
((machineinfo)->on_circ->padding_machine[(machineinfo)->machine_index])
|
||||
|
||||
/**
|
||||
* This specifies a particular padding machine to use after negotiation.
|
||||
*
|
||||
* The constants for machine_num_t are in trunnel.
|
||||
* We want to be able to define extra numbers in the consensus/torrc, though.
|
||||
*/
|
||||
typedef uint8_t circpad_machine_num_t;
|
||||
|
||||
/** Global state machine structure from the consensus */
|
||||
typedef struct circpad_machine_spec_t {
|
||||
/* Just a user-friendly machine name for logs */
|
||||
const char *name;
|
||||
|
||||
/** Global machine number */
|
||||
circpad_machine_num_t machine_num;
|
||||
|
||||
/** Which machine index slot should this machine go into in
|
||||
* the array on the circuit_t */
|
||||
unsigned machine_index : 1;
|
||||
|
||||
/** Send a padding negotiate to shut down machine at end state? */
|
||||
unsigned should_negotiate_end : 1;
|
||||
|
||||
// These next three fields are origin machine-only...
|
||||
/** Origin side or relay side */
|
||||
unsigned is_origin_side : 1;
|
||||
|
||||
/** Which hop in the circuit should we send padding to/from?
|
||||
* 1-indexed (ie: hop #1 is guard, #2 middle, #3 exit). */
|
||||
unsigned target_hopnum : 3;
|
||||
|
||||
/** If this flag is enabled, don't close circuits that use this machine even
|
||||
* if another part of Tor wants to close this circuit.
|
||||
*
|
||||
* If this flag is set, the circuitpadding subsystem will close circuits the
|
||||
* moment the machine transitions to the END state, and only if the circuit
|
||||
* has already been asked to be closed by another part of Tor.
|
||||
*
|
||||
* Circuits that should have been closed but were kept open by a padding
|
||||
* machine are re-purposed to CIRCUIT_PURPOSE_C_CIRCUIT_PADDING, hence
|
||||
* machines should take that purpose into account if they are filtering
|
||||
* circuits by purpose. */
|
||||
unsigned manage_circ_lifetime : 1;
|
||||
|
||||
/** This machine only kills fascists if the following conditions are met. */
|
||||
circpad_machine_conditions_t conditions;
|
||||
|
||||
/** How many padding cells can be sent before we apply overhead limits?
|
||||
* XXX: Note that we can only allow up to 64k of padding cells on an
|
||||
* otherwise quiet circuit. Is this enough? It's 33MB. */
|
||||
uint16_t allowed_padding_count;
|
||||
|
||||
/** Padding percent cap: Stop padding if we exceed this percent overhead.
|
||||
* 0 means no limit. Overhead is defined as percent of total traffic, so
|
||||
* that we can use 0..100 here. This is the same definition as used in
|
||||
* Prop#265. */
|
||||
uint8_t max_padding_percent;
|
||||
|
||||
/** State array: indexed by circpad_statenum_t */
|
||||
circpad_state_t *states;
|
||||
|
||||
/**
|
||||
* Number of states this machine has (ie: length of the states array).
|
||||
* XXX: This field is not needed other than for safety. */
|
||||
circpad_statenum_t num_states;
|
||||
} circpad_machine_spec_t;
|
||||
|
||||
void circpad_new_consensus_params(const networkstatus_t *ns);
|
||||
|
||||
int circpad_marked_circuit_for_padding(circuit_t *circ, int reason);
|
||||
|
||||
/**
|
||||
* The following are event call-in points that are of interest to
|
||||
* the state machines. They are called during cell processing. */
|
||||
void circpad_deliver_unrecognized_cell_events(struct circuit_t *circ,
|
||||
cell_direction_t dir);
|
||||
void circpad_deliver_sent_relay_cell_events(struct circuit_t *circ,
|
||||
uint8_t relay_command);
|
||||
void circpad_deliver_recognized_relay_cell_events(struct circuit_t *circ,
|
||||
uint8_t relay_command,
|
||||
crypt_path_t *layer_hint);
|
||||
|
||||
/** Cell events are delivered by the above delivery functions */
|
||||
void circpad_cell_event_nonpadding_sent(struct circuit_t *on_circ);
|
||||
void circpad_cell_event_nonpadding_received(struct circuit_t *on_circ);
|
||||
void circpad_cell_event_padding_sent(struct circuit_t *on_circ);
|
||||
void circpad_cell_event_padding_received(struct circuit_t *on_circ);
|
||||
|
||||
/** Internal events are events the machines send to themselves */
|
||||
circpad_decision_t
|
||||
circpad_internal_event_infinity(circpad_machine_runtime_t *mi);
|
||||
circpad_decision_t
|
||||
circpad_internal_event_bins_empty(circpad_machine_runtime_t *);
|
||||
circpad_decision_t circpad_internal_event_state_length_up(
|
||||
circpad_machine_runtime_t *);
|
||||
|
||||
/** Machine creation events are events that cause us to set up or
|
||||
* tear down padding state machines. */
|
||||
void circpad_machine_event_circ_added_hop(struct origin_circuit_t *on_circ);
|
||||
void circpad_machine_event_circ_built(struct origin_circuit_t *circ);
|
||||
void circpad_machine_event_circ_purpose_changed(struct origin_circuit_t *circ);
|
||||
void circpad_machine_event_circ_has_streams(struct origin_circuit_t *circ);
|
||||
void circpad_machine_event_circ_has_no_streams(struct origin_circuit_t *circ);
|
||||
void
|
||||
circpad_machine_event_circ_has_no_relay_early(struct origin_circuit_t *circ);
|
||||
|
||||
void circpad_machines_init(void);
|
||||
void circpad_machines_free(void);
|
||||
void circpad_register_padding_machine(circpad_machine_spec_t *machine,
|
||||
smartlist_t *machine_list);
|
||||
|
||||
void circpad_machine_states_init(circpad_machine_spec_t *machine,
|
||||
circpad_statenum_t num_states);
|
||||
|
||||
void circpad_circuit_free_all_machineinfos(struct circuit_t *circ);
|
||||
|
||||
bool circpad_padding_is_from_expected_hop(struct circuit_t *circ,
|
||||
crypt_path_t *from_hop);
|
||||
|
||||
/** Serializaton functions for writing to/from torrc and consensus */
|
||||
char *circpad_machine_spec_to_string(const circpad_machine_spec_t *machine);
|
||||
const circpad_machine_spec_t *circpad_string_to_machine(const char *str);
|
||||
|
||||
/* Padding negotiation between client and middle */
|
||||
signed_error_t circpad_handle_padding_negotiate(struct circuit_t *circ,
|
||||
struct cell_t *cell);
|
||||
signed_error_t circpad_handle_padding_negotiated(struct circuit_t *circ,
|
||||
struct cell_t *cell,
|
||||
crypt_path_t *layer_hint);
|
||||
signed_error_t circpad_negotiate_padding(struct origin_circuit_t *circ,
|
||||
circpad_machine_num_t machine,
|
||||
uint8_t target_hopnum,
|
||||
uint8_t command,
|
||||
uint32_t machine_ctr);
|
||||
bool circpad_padding_negotiated(struct circuit_t *circ,
|
||||
circpad_machine_num_t machine,
|
||||
uint8_t command,
|
||||
uint8_t response,
|
||||
uint32_t machine_ctr);
|
||||
|
||||
circpad_purpose_mask_t circpad_circ_purpose_to_mask(uint8_t circ_purpose);
|
||||
|
||||
int circpad_check_received_cell(cell_t *cell, circuit_t *circ,
|
||||
crypt_path_t *layer_hint,
|
||||
const relay_header_t *rh);
|
||||
|
||||
MOCK_DECL(circpad_decision_t,
|
||||
circpad_machine_schedule_padding,(circpad_machine_runtime_t *));
|
||||
|
||||
MOCK_DECL(circpad_decision_t,
|
||||
circpad_machine_spec_transition, (circpad_machine_runtime_t *mi,
|
||||
circpad_event_t event));
|
||||
|
||||
circpad_decision_t circpad_send_padding_cell_for_callback(
|
||||
circpad_machine_runtime_t *mi);
|
||||
|
||||
void circpad_free_all(void);
|
||||
|
||||
#ifdef CIRCUITPADDING_PRIVATE
|
||||
STATIC void machine_spec_free_(circpad_machine_spec_t *m);
|
||||
#define machine_spec_free(chan) \
|
||||
FREE_AND_NULL(circpad_machine_spec_t,machine_spec_free_, (m))
|
||||
|
||||
STATIC circpad_delay_t
|
||||
circpad_machine_sample_delay(circpad_machine_runtime_t *mi);
|
||||
|
||||
STATIC bool
|
||||
circpad_machine_reached_padding_limit(circpad_machine_runtime_t *mi);
|
||||
|
||||
STATIC circpad_delay_t
|
||||
circpad_histogram_bin_to_usec(const circpad_machine_runtime_t *mi,
|
||||
circpad_hist_index_t bin);
|
||||
|
||||
STATIC const circpad_state_t *
|
||||
circpad_machine_current_state(const circpad_machine_runtime_t *mi);
|
||||
|
||||
STATIC void circpad_machine_remove_token(circpad_machine_runtime_t *mi);
|
||||
|
||||
STATIC circpad_hist_index_t circpad_histogram_usec_to_bin(
|
||||
const circpad_machine_runtime_t *mi,
|
||||
circpad_delay_t us);
|
||||
|
||||
STATIC circpad_machine_runtime_t *circpad_circuit_machineinfo_new(
|
||||
struct circuit_t *on_circ,
|
||||
int machine_index);
|
||||
STATIC void circpad_machine_remove_higher_token(circpad_machine_runtime_t *mi,
|
||||
circpad_delay_t target_bin_us);
|
||||
STATIC void circpad_machine_remove_lower_token(circpad_machine_runtime_t *mi,
|
||||
circpad_delay_t target_bin_us);
|
||||
STATIC void circpad_machine_remove_closest_token(circpad_machine_runtime_t *mi,
|
||||
circpad_delay_t target_bin_us,
|
||||
bool use_usec);
|
||||
STATIC void circpad_machine_setup_tokens(circpad_machine_runtime_t *mi);
|
||||
|
||||
MOCK_DECL(STATIC signed_error_t,
|
||||
circpad_send_command_to_hop,(struct origin_circuit_t *circ, uint8_t hopnum,
|
||||
uint8_t relay_command, const uint8_t *payload,
|
||||
ssize_t payload_len));
|
||||
|
||||
MOCK_DECL(STATIC const node_t *,
|
||||
circuit_get_nth_node,(origin_circuit_t *circ, int hop));
|
||||
|
||||
STATIC circpad_delay_t
|
||||
histogram_get_bin_upper_bound(const circpad_machine_runtime_t *mi,
|
||||
circpad_hist_index_t bin);
|
||||
|
||||
STATIC void
|
||||
circpad_add_matching_machines(origin_circuit_t *on_circ,
|
||||
smartlist_t *machines_sl);
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
extern smartlist_t *origin_padding_machines;
|
||||
extern smartlist_t *relay_padding_machines;
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* defined(CIRCUITPADDING_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CIRCUITPADDING_H) */
|
||||
@@ -0,0 +1,35 @@
|
||||
/* Copyright (c) 2018 The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file circuitpadding_machines.h
|
||||
* \brief Header file for circuitpadding_machines.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CIRCUITPADDING_MACHINES_H
|
||||
#define TOR_CIRCUITPADDING_MACHINES_H
|
||||
|
||||
void circpad_machine_relay_hide_intro_circuits(smartlist_t *machines_sl);
|
||||
void circpad_machine_client_hide_intro_circuits(smartlist_t *machines_sl);
|
||||
void circpad_machine_relay_hide_rend_circuits(smartlist_t *machines_sl);
|
||||
void circpad_machine_client_hide_rend_circuits(smartlist_t *machines_sl);
|
||||
|
||||
#ifdef CIRCUITPADDING_MACHINES_PRIVATE
|
||||
|
||||
/** State of the padding machines that actually sends padding */
|
||||
#define CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP CIRCPAD_STATE_BURST
|
||||
|
||||
/** Constants defining the amount of padding that a machine will send to hide
|
||||
* HS circuits. The actual value is sampled uniformly random between the
|
||||
* min/max values.
|
||||
*/
|
||||
|
||||
/** Minimum number of relay-side padding cells to be sent by this machine */
|
||||
#define INTRO_MACHINE_MINIMUM_PADDING 7
|
||||
/** Maximum number of relay-side padding cells to be sent by this machine.
|
||||
* The actual value will be sampled between the min and max.*/
|
||||
#define INTRO_MACHINE_MAXIMUM_PADDING 10
|
||||
|
||||
#endif /* defined(CIRCUITPADDING_MACHINES_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CIRCUITPADDING_MACHINES_H) */
|
||||
@@ -0,0 +1,212 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file circuitstats.h
|
||||
* \brief Header file for circuitstats.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_CIRCUITSTATS_H
|
||||
#define TOR_CIRCUITSTATS_H
|
||||
|
||||
const circuit_build_times_t *get_circuit_build_times(void);
|
||||
circuit_build_times_t *get_circuit_build_times_mutable(void);
|
||||
double get_circuit_build_close_time_ms(void);
|
||||
double get_circuit_build_timeout_ms(void);
|
||||
|
||||
int circuit_build_times_disabled(const or_options_t *options);
|
||||
int circuit_build_times_disabled_(const or_options_t *options,
|
||||
int ignore_consensus);
|
||||
|
||||
/** A build_time_t is milliseconds */
|
||||
typedef uint32_t build_time_t;
|
||||
|
||||
int circuit_build_times_enough_to_compute(const circuit_build_times_t *cbt);
|
||||
void circuit_build_times_update_state(const circuit_build_times_t *cbt,
|
||||
or_state_t *state);
|
||||
int circuit_build_times_parse_state(circuit_build_times_t *cbt,
|
||||
or_state_t *state);
|
||||
void circuit_build_times_count_timeout(circuit_build_times_t *cbt,
|
||||
int did_onehop);
|
||||
int circuit_build_times_count_close(circuit_build_times_t *cbt,
|
||||
int did_onehop, time_t start_time);
|
||||
void circuit_build_times_set_timeout(circuit_build_times_t *cbt);
|
||||
int circuit_build_times_add_time(circuit_build_times_t *cbt,
|
||||
build_time_t time);
|
||||
int circuit_build_times_needs_circuits(const circuit_build_times_t *cbt);
|
||||
void circuit_build_times_handle_completed_hop(origin_circuit_t *circ);
|
||||
|
||||
int circuit_build_times_needs_circuits_now(const circuit_build_times_t *cbt);
|
||||
void circuit_build_times_init(circuit_build_times_t *cbt);
|
||||
void circuit_build_times_free_timeouts(circuit_build_times_t *cbt);
|
||||
void circuit_build_times_new_consensus_params(circuit_build_times_t *cbt,
|
||||
const networkstatus_t *ns);
|
||||
double circuit_build_times_timeout_rate(const circuit_build_times_t *cbt);
|
||||
double circuit_build_times_close_rate(const circuit_build_times_t *cbt);
|
||||
|
||||
void circuit_build_times_update_last_circ(circuit_build_times_t *cbt);
|
||||
void circuit_build_times_mark_circ_as_measurement_only(origin_circuit_t *circ);
|
||||
void circuit_build_times_reset(circuit_build_times_t *cbt);
|
||||
|
||||
/** Total size of the circuit timeout history to accumulate.
|
||||
* 1000 is approx 2.5 days worth of continual-use circuits. */
|
||||
#define CBT_NCIRCUITS_TO_OBSERVE 1000
|
||||
|
||||
/** Width of the histogram bins in milliseconds */
|
||||
#define CBT_BIN_WIDTH ((build_time_t)10)
|
||||
|
||||
/** Number of modes to use in the weighted-avg computation of Xm */
|
||||
#define CBT_DEFAULT_NUM_XM_MODES 10
|
||||
#define CBT_MIN_NUM_XM_MODES 1
|
||||
#define CBT_MAX_NUM_XM_MODES 20
|
||||
|
||||
/**
|
||||
* CBT_BUILD_ABANDONED is our flag value to represent a force-closed
|
||||
* circuit (Aka a 'right-censored' pareto value).
|
||||
*/
|
||||
#define CBT_BUILD_ABANDONED ((build_time_t)(INT32_MAX-1))
|
||||
#define CBT_BUILD_TIME_MAX ((build_time_t)(INT32_MAX))
|
||||
|
||||
/** Save state every 10 circuits */
|
||||
#define CBT_SAVE_STATE_EVERY 10
|
||||
|
||||
/* Circuit build times consensus parameters */
|
||||
|
||||
/**
|
||||
* How long to wait before actually closing circuits that take too long to
|
||||
* build in terms of CDF quantile.
|
||||
*/
|
||||
#define CBT_DEFAULT_CLOSE_QUANTILE 99
|
||||
#define CBT_MIN_CLOSE_QUANTILE CBT_MIN_QUANTILE_CUTOFF
|
||||
#define CBT_MAX_CLOSE_QUANTILE CBT_MAX_QUANTILE_CUTOFF
|
||||
|
||||
/**
|
||||
* How many circuits count as recent when considering if the
|
||||
* connection has gone gimpy or changed.
|
||||
*/
|
||||
#define CBT_DEFAULT_RECENT_CIRCUITS 20
|
||||
#define CBT_MIN_RECENT_CIRCUITS 3
|
||||
#define CBT_MAX_RECENT_CIRCUITS 1000
|
||||
|
||||
/**
|
||||
* Maximum count of timeouts that finish the first hop in the past
|
||||
* RECENT_CIRCUITS before calculating a new timeout.
|
||||
*
|
||||
* This tells us whether to abandon timeout history and set
|
||||
* the timeout back to whatever circuit_build_times_get_initial_timeout()
|
||||
* gives us.
|
||||
*/
|
||||
#define CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT (CBT_DEFAULT_RECENT_CIRCUITS*9/10)
|
||||
#define CBT_MIN_MAX_RECENT_TIMEOUT_COUNT 3
|
||||
#define CBT_MAX_MAX_RECENT_TIMEOUT_COUNT 10000
|
||||
|
||||
/** Minimum circuits before estimating a timeout */
|
||||
#define CBT_DEFAULT_MIN_CIRCUITS_TO_OBSERVE 100
|
||||
#define CBT_MIN_MIN_CIRCUITS_TO_OBSERVE 1
|
||||
#define CBT_MAX_MIN_CIRCUITS_TO_OBSERVE 10000
|
||||
|
||||
/** Cutoff percentile on the CDF for our timeout estimation. */
|
||||
#define CBT_DEFAULT_QUANTILE_CUTOFF 80
|
||||
#define CBT_MIN_QUANTILE_CUTOFF 10
|
||||
#define CBT_MAX_QUANTILE_CUTOFF 99
|
||||
double circuit_build_times_quantile_cutoff(void);
|
||||
|
||||
/** How often in seconds should we build a test circuit */
|
||||
#define CBT_DEFAULT_TEST_FREQUENCY 10
|
||||
#define CBT_MIN_TEST_FREQUENCY 1
|
||||
#define CBT_MAX_TEST_FREQUENCY INT32_MAX
|
||||
|
||||
/** Lowest allowable value for CircuitBuildTimeout in milliseconds */
|
||||
#define CBT_DEFAULT_TIMEOUT_MIN_VALUE (CBT_BIN_WIDTH)
|
||||
#define CBT_MIN_TIMEOUT_MIN_VALUE CBT_BIN_WIDTH
|
||||
#define CBT_MAX_TIMEOUT_MIN_VALUE INT32_MAX
|
||||
|
||||
/** Initial circuit build timeout in milliseconds */
|
||||
#define CBT_DEFAULT_TIMEOUT_INITIAL_VALUE (60*1000)
|
||||
#define CBT_MIN_TIMEOUT_INITIAL_VALUE CBT_MIN_TIMEOUT_MIN_VALUE
|
||||
#define CBT_MAX_TIMEOUT_INITIAL_VALUE INT32_MAX
|
||||
int32_t circuit_build_times_initial_timeout(void);
|
||||
|
||||
#if CBT_DEFAULT_MAX_RECENT_TIMEOUT_COUNT < CBT_MIN_MAX_RECENT_TIMEOUT_COUNT
|
||||
#error "RECENT_CIRCUITS is set too low."
|
||||
#endif
|
||||
|
||||
#ifdef CIRCUITSTATS_PRIVATE
|
||||
STATIC double circuit_build_times_calculate_timeout(circuit_build_times_t *cbt,
|
||||
double quantile);
|
||||
STATIC int circuit_build_times_update_alpha(circuit_build_times_t *cbt);
|
||||
|
||||
/* Network liveness functions */
|
||||
STATIC int circuit_build_times_network_check_changed(
|
||||
circuit_build_times_t *cbt);
|
||||
STATIC build_time_t circuit_build_times_get_xm(circuit_build_times_t *cbt);
|
||||
#endif /* defined(CIRCUITSTATS_PRIVATE) */
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
build_time_t circuit_build_times_generate_sample(circuit_build_times_t *cbt,
|
||||
double q_lo, double q_hi);
|
||||
double circuit_build_times_cdf(circuit_build_times_t *cbt, double x);
|
||||
void circuit_build_times_initial_alpha(circuit_build_times_t *cbt,
|
||||
double quantile, double time_ms);
|
||||
void circuitbuild_running_unit_tests(void);
|
||||
#endif /* defined(TOR_UNIT_TESTS) */
|
||||
|
||||
/* Network liveness functions */
|
||||
void circuit_build_times_network_is_live(circuit_build_times_t *cbt);
|
||||
int circuit_build_times_network_check_live(const circuit_build_times_t *cbt);
|
||||
void circuit_build_times_network_circ_success(circuit_build_times_t *cbt);
|
||||
|
||||
/** Information about the state of our local network connection */
|
||||
typedef struct {
|
||||
/** The timestamp we last completed a TLS handshake or received a cell */
|
||||
time_t network_last_live;
|
||||
/** If the network is not live, how many timeouts has this caused? */
|
||||
int nonlive_timeouts;
|
||||
/** Circular array of circuits that have made it to the first hop. Slot is
|
||||
* 1 if circuit timed out, 0 if circuit succeeded */
|
||||
int8_t *timeouts_after_firsthop;
|
||||
/** Number of elements allocated for the above array */
|
||||
int num_recent_circs;
|
||||
/** Index into circular array. */
|
||||
int after_firsthop_idx;
|
||||
} network_liveness_t;
|
||||
|
||||
/** Structure for circuit build times history */
|
||||
struct circuit_build_times_t {
|
||||
/** The circular array of recorded build times in milliseconds */
|
||||
build_time_t circuit_build_times[CBT_NCIRCUITS_TO_OBSERVE];
|
||||
/** Current index in the circuit_build_times circular array */
|
||||
int build_times_idx;
|
||||
/** Total number of build times accumulated. Max CBT_NCIRCUITS_TO_OBSERVE */
|
||||
int total_build_times;
|
||||
/** Information about the state of our local network connection */
|
||||
network_liveness_t liveness;
|
||||
/** Last time we built a circuit. Used to decide to build new test circs */
|
||||
time_t last_circ_at;
|
||||
/** "Minimum" value of our pareto distribution (actually mode) */
|
||||
build_time_t Xm;
|
||||
/** alpha exponent for pareto dist. */
|
||||
double alpha;
|
||||
/** Have we computed a timeout? */
|
||||
int have_computed_timeout;
|
||||
/** The exact value for that timeout in milliseconds. Stored as a double
|
||||
* to maintain precision from calculations to and from quantile value. */
|
||||
double timeout_ms;
|
||||
/** How long we wait before actually closing the circuit. */
|
||||
double close_ms;
|
||||
/** Total succeeded counts. Old measurements may be scaled downward if
|
||||
* we've seen a lot of circuits. */
|
||||
uint32_t num_circ_succeeded;
|
||||
/** Total timeout counts. Old measurements may be scaled downward if
|
||||
* we've seen a lot of circuits. */
|
||||
uint32_t num_circ_timeouts;
|
||||
/** Total closed counts. Old measurements may be scaled downward if
|
||||
* we've seen a lot of circuits.*/
|
||||
uint32_t num_circ_closed;
|
||||
|
||||
};
|
||||
|
||||
#endif /* !defined(TOR_CIRCUITSTATS_H) */
|
||||
@@ -0,0 +1,111 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file circuituse.h
|
||||
* \brief Header file for circuituse.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CIRCUITUSE_H
|
||||
#define TOR_CIRCUITUSE_H
|
||||
|
||||
void circuit_expire_building(void);
|
||||
void circuit_expire_waiting_for_better_guard(void);
|
||||
void circuit_remove_handled_ports(smartlist_t *needed_ports);
|
||||
int circuit_stream_is_being_handled(entry_connection_t *conn, uint16_t port,
|
||||
int min);
|
||||
void circuit_log_ancient_one_hop_circuits(int age);
|
||||
#if 0
|
||||
int circuit_conforms_to_options(const origin_circuit_t *circ,
|
||||
const or_options_t *options);
|
||||
#endif
|
||||
void circuit_build_needed_circs(time_t now);
|
||||
void circuit_expire_old_circs_as_needed(time_t now);
|
||||
void circuit_detach_stream(circuit_t *circ, edge_connection_t *conn);
|
||||
|
||||
void circuit_expire_old_circuits_serverside(time_t now);
|
||||
|
||||
void reset_bandwidth_test(void);
|
||||
int circuit_enough_testing_circs(void);
|
||||
|
||||
void circuit_has_opened(origin_circuit_t *circ);
|
||||
void circuit_try_attaching_streams(origin_circuit_t *circ);
|
||||
void circuit_build_failed(origin_circuit_t *circ);
|
||||
|
||||
/** Flag to set when a circuit should have only a single hop. */
|
||||
#define CIRCLAUNCH_ONEHOP_TUNNEL (1<<0)
|
||||
/** Flag to set when a circuit needs to be built of high-uptime nodes */
|
||||
#define CIRCLAUNCH_NEED_UPTIME (1<<1)
|
||||
/** Flag to set when a circuit needs to be built of high-capacity nodes */
|
||||
#define CIRCLAUNCH_NEED_CAPACITY (1<<2)
|
||||
/** Flag to set when the last hop of a circuit doesn't need to be an
|
||||
* exit node. */
|
||||
#define CIRCLAUNCH_IS_INTERNAL (1<<3)
|
||||
/** Flag to set when we are trying to launch a self-testing circuit to our
|
||||
* IPv6 ORPort. We need to apply some additional filters on the second-last
|
||||
* node in the circuit. (We are both the client and the last node in the
|
||||
* circuit.) */
|
||||
#define CIRCLAUNCH_IS_IPV6_SELFTEST (1<<5)
|
||||
/** Flag to set when a circuit needs the exit to support conflux. */
|
||||
#define CIRCLAUNCH_NEED_CONFLUX (1<<6)
|
||||
|
||||
origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
|
||||
extend_info_t *info,
|
||||
int flags);
|
||||
origin_circuit_t *circuit_launch(uint8_t purpose, int flags);
|
||||
void circuit_reset_failure_count(int timeout);
|
||||
int connection_ap_handshake_attach_chosen_circuit(entry_connection_t *conn,
|
||||
origin_circuit_t *circ,
|
||||
crypt_path_t *cpath);
|
||||
int connection_ap_handshake_attach_circuit(entry_connection_t *conn);
|
||||
|
||||
void circuit_change_purpose(circuit_t *circ, uint8_t new_purpose);
|
||||
|
||||
int hostname_in_track_host_exits(const or_options_t *options,
|
||||
const char *address);
|
||||
void mark_circuit_unusable_for_new_conns(origin_circuit_t *circ);
|
||||
|
||||
int circuit_purpose_is_hidden_service(uint8_t);
|
||||
|
||||
/* Series of helper functions for hidden services. */
|
||||
bool circuit_purpose_is_hs_client(const uint8_t purpose);
|
||||
bool circuit_purpose_is_hs_service(const uint8_t purpose);
|
||||
bool circuit_purpose_is_hs_vanguards(const uint8_t purpose);
|
||||
|
||||
bool circuit_is_hs_v3(const circuit_t *circ);
|
||||
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);
|
||||
|
||||
int circuit_should_use_vanguards(uint8_t);
|
||||
void circuit_sent_valid_data(origin_circuit_t *circ, uint16_t relay_body_len);
|
||||
void circuit_read_valid_data(origin_circuit_t *circ, uint16_t relay_body_len);
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
/* Used only by circuituse.c and test_circuituse.c */
|
||||
|
||||
STATIC int circuit_is_available_for_use(const circuit_t *circ);
|
||||
|
||||
STATIC int needs_exit_circuits(time_t now,
|
||||
int *port_needs_uptime,
|
||||
int *port_needs_capacity);
|
||||
STATIC int needs_hs_server_circuits(time_t now,
|
||||
int num_uptime_internal);
|
||||
|
||||
STATIC int needs_hs_client_circuits(time_t now,
|
||||
int *needs_uptime,
|
||||
int *needs_capacity,
|
||||
int num_internal,
|
||||
int num_uptime_internal);
|
||||
|
||||
STATIC int needs_circuits_for_build(int num);
|
||||
|
||||
#endif /* defined(TOR_UNIT_TESTS) */
|
||||
|
||||
#endif /* !defined(TOR_CIRCUITUSE_H) */
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file command.h
|
||||
* \brief Header file for command.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_COMMAND_H
|
||||
#define TOR_COMMAND_H
|
||||
|
||||
#include "core/or/channel.h"
|
||||
|
||||
void command_process_cell(channel_t *chan, cell_t *cell);
|
||||
void command_setup_channel(channel_t *chan);
|
||||
void command_setup_listener(channel_listener_t *chan_l);
|
||||
|
||||
const char *cell_command_to_string(uint8_t command);
|
||||
|
||||
extern uint64_t stats_n_padding_cells_processed;
|
||||
extern uint64_t stats_n_create_cells_processed;
|
||||
extern uint64_t stats_n_created_cells_processed;
|
||||
extern uint64_t stats_n_relay_cells_processed;
|
||||
extern uint64_t stats_n_destroy_cells_processed;
|
||||
|
||||
#endif /* !defined(TOR_COMMAND_H) */
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/* Copyright (c) 2019-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file conflux.h
|
||||
* \brief Public APIs for conflux multipath support
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONFLUX_H
|
||||
#define TOR_CONFLUX_H
|
||||
|
||||
#include "core/or/circuit_st.h"
|
||||
#include "core/or/conflux_st.h"
|
||||
|
||||
typedef struct conflux_t conflux_t;
|
||||
typedef struct conflux_leg_t conflux_leg_t;
|
||||
|
||||
/** Helpers to iterate over legs with better semantic. */
|
||||
#define CONFLUX_FOR_EACH_LEG_BEGIN(cfx, var) \
|
||||
SMARTLIST_FOREACH_BEGIN(cfx->legs, conflux_leg_t *, var)
|
||||
#define CONFLUX_FOR_EACH_LEG_END(var) \
|
||||
SMARTLIST_FOREACH_END(var)
|
||||
|
||||
/** Helper: Return the number of legs a conflux object has. */
|
||||
#define CONFLUX_NUM_LEGS(cfx) (smartlist_len(cfx->legs))
|
||||
|
||||
/** A cell for the out-of-order queue.
|
||||
* XXX: Consider trying to use packed_cell_t instead here? */
|
||||
typedef struct {
|
||||
/**
|
||||
* Absolute sequence number of this cell, computed from the
|
||||
* relative sequence number of the conflux cell. */
|
||||
uint64_t seq;
|
||||
|
||||
/**
|
||||
* Heap index of this cell, for use in in the conflux_t ooo_q heap.
|
||||
*/
|
||||
int heap_idx;
|
||||
|
||||
/** The cell here is always guaranteed to have removed its
|
||||
* extra conflux sequence number, for ease of processing */
|
||||
cell_t cell;
|
||||
} conflux_cell_t;
|
||||
|
||||
size_t conflux_handle_oom(size_t bytes_to_remove);
|
||||
uint64_t conflux_get_total_bytes_allocation(void);
|
||||
uint64_t conflux_get_circ_bytes_allocation(const circuit_t *circ);
|
||||
|
||||
void conflux_update_rtt(conflux_t *cfx, circuit_t *circ, uint64_t rtt_usec);
|
||||
|
||||
circuit_t *conflux_decide_circ_for_send(conflux_t *cfx,
|
||||
circuit_t *orig_circ,
|
||||
uint8_t relay_command);
|
||||
circuit_t *conflux_decide_next_circ(conflux_t *cfx);
|
||||
|
||||
int conflux_process_switch_command(circuit_t *in_circ,
|
||||
crypt_path_t *layer_hint, cell_t *cell,
|
||||
relay_header_t *rh);
|
||||
bool conflux_should_multiplex(int relay_command);
|
||||
bool conflux_process_cell(conflux_t *cfx, circuit_t *in_circ,
|
||||
crypt_path_t *layer_hint,
|
||||
cell_t *cell);
|
||||
conflux_cell_t *conflux_dequeue_cell(conflux_t *cfx);
|
||||
void conflux_note_cell_sent(conflux_t *cfx, circuit_t *circ,
|
||||
uint8_t relay_command);
|
||||
|
||||
/* Private section starts. */
|
||||
#ifdef TOR_CONFLUX_PRIVATE
|
||||
|
||||
const struct congestion_control_t *circuit_ccontrol(const circuit_t *);
|
||||
conflux_leg_t *conflux_get_leg(conflux_t *cfx, const circuit_t *circ);
|
||||
uint64_t conflux_get_max_seq_recv(const conflux_t *cfx);
|
||||
uint64_t conflux_get_max_seq_sent(const conflux_t *cfx);
|
||||
|
||||
/*
|
||||
* Unit tests declaractions.
|
||||
*/
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
|
||||
#endif /* defined(TOR_UNIT_TESTS) */
|
||||
|
||||
#endif /* defined(TOR_CONFLUX_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CONFLUX_H) */
|
||||
@@ -0,0 +1,50 @@
|
||||
/* Copyright (c) 2023, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file conflux_cell.h
|
||||
* \brief Header file for conflux_cell.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONFLUX_CELL_H
|
||||
#define TOR_CONFLUX_CELL_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
|
||||
typedef struct conflux_cell_link_t {
|
||||
uint8_t version;
|
||||
uint8_t desired_ux;
|
||||
uint8_t nonce[DIGEST256_LEN];
|
||||
|
||||
uint64_t last_seqno_sent;
|
||||
uint64_t last_seqno_recv;
|
||||
} conflux_cell_link_t;
|
||||
|
||||
conflux_cell_link_t *conflux_cell_new_link(const uint8_t *nonce,
|
||||
uint64_t last_sent,
|
||||
uint64_t last_recv,
|
||||
uint8_t ux);
|
||||
|
||||
conflux_cell_link_t *conflux_cell_parse_link(const cell_t *cell,
|
||||
const uint16_t cell_len);
|
||||
conflux_cell_link_t *conflux_cell_parse_linked(const cell_t *cell,
|
||||
const uint16_t cell_le);
|
||||
uint32_t conflux_cell_parse_switch(const cell_t *cell,
|
||||
const uint16_t rh_len);
|
||||
|
||||
bool conflux_cell_send_link(const conflux_cell_link_t *link,
|
||||
origin_circuit_t *circ);
|
||||
bool conflux_cell_send_linked(const conflux_cell_link_t *link,
|
||||
or_circuit_t *circ);
|
||||
bool conflux_cell_send_linked_ack(origin_circuit_t *circ);
|
||||
bool conflux_send_switch_command(circuit_t *send_circ, uint64_t relative_seq);
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
|
||||
STATIC ssize_t
|
||||
build_link_cell(const conflux_cell_link_t *link, uint8_t *cell_out);
|
||||
|
||||
#endif /* TOR_UNIT_TESTS */
|
||||
|
||||
#endif /* TOR_CONFLUX_CELL_H */
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/* Copyright (c) 2023, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file conflux_params.h
|
||||
* \brief Header file for conflux_params.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONFLUX_PARAMS_H
|
||||
#define TOR_CONFLUX_PARAMS_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
|
||||
bool conflux_is_enabled(const struct circuit_t *circ);
|
||||
uint8_t conflux_params_get_max_linked_set(void);
|
||||
uint8_t conflux_params_get_max_prebuilt(void);
|
||||
uint8_t conflux_params_get_max_unlinked_leg_retry(void);
|
||||
uint8_t conflux_params_get_num_legs_set(void);
|
||||
uint8_t conflux_params_get_max_legs_set(void);
|
||||
uint8_t conflux_params_get_drain_pct(void);
|
||||
uint8_t conflux_params_get_send_pct(void);
|
||||
|
||||
void conflux_params_new_consensus(const networkstatus_t *ns);
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
extern uint32_t max_unlinked_leg_retry;
|
||||
#endif
|
||||
|
||||
#endif /* TOR_CONFLUX_PARAMS_H */
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/* Copyright (c) 2023, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file conflux_pool.h
|
||||
* \brief Header file for conflux_pool.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONFLUX_POOL_H
|
||||
#define TOR_CONFLUX_POOL_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
|
||||
void conflux_pool_init(void);
|
||||
void conflux_pool_free_all(void);
|
||||
|
||||
origin_circuit_t *conflux_get_circ_for_conn(const entry_connection_t *conn,
|
||||
time_t now);
|
||||
|
||||
void conflux_predict_new(time_t now);
|
||||
|
||||
bool conflux_launch_leg(const uint8_t *nonce);
|
||||
|
||||
void conflux_add_guards_to_exclude_list(const origin_circuit_t *circ,
|
||||
smartlist_t *excluded);
|
||||
void conflux_add_middles_to_exclude_list(const origin_circuit_t *circ,
|
||||
smartlist_t *excluded);
|
||||
|
||||
void conflux_circuit_has_closed(circuit_t *circ);
|
||||
void conflux_circuit_has_opened(origin_circuit_t *orig_circ);
|
||||
void conflux_circuit_about_to_free(circuit_t *circ);
|
||||
|
||||
void conflux_process_link(circuit_t *circ, const cell_t *cell,
|
||||
const uint16_t cell_len);
|
||||
void conflux_process_linked(circuit_t *circ, crypt_path_t *layer_hint,
|
||||
const cell_t *cell, const uint16_t cell_len);
|
||||
void conflux_process_linked_ack(circuit_t *circ);
|
||||
|
||||
typedef struct conflux_t conflux_t;
|
||||
void conflux_log_set(int loglevel, const conflux_t *cfx, bool is_client);
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
bool launch_new_set(int num_legs);
|
||||
digest256map_t *get_linked_pool(bool is_client);
|
||||
digest256map_t *get_unlinked_pool(bool is_client);
|
||||
extern uint8_t DEFAULT_CLIENT_UX;
|
||||
extern uint8_t DEFAULT_EXIT_UX;
|
||||
#endif /* defined(UNIT_TESTS) */
|
||||
|
||||
#endif /* TOR_CONFLUX_POOL_H */
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
/* Copyright (c) 2019-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file conflux_st.h
|
||||
* \brief Structure definitions for conflux multipath
|
||||
**/
|
||||
|
||||
#ifndef CONFLUX_ST_H
|
||||
#define CONFLUX_ST_H
|
||||
|
||||
#include "core/or/circuit_st.h"
|
||||
#include "core/or/cell_st.h"
|
||||
#include "lib/defs/digest_sizes.h"
|
||||
|
||||
/**
|
||||
* Specifies which conflux alg is in use.
|
||||
*/
|
||||
typedef enum {
|
||||
CONFLUX_ALG_MINRTT = 0,
|
||||
CONFLUX_ALG_LOWRTT = 1,
|
||||
CONFLUX_ALG_CWNDRTT = 2,
|
||||
} conflux_alg_t;
|
||||
|
||||
/** XXX: Cached consensus params+scheduling alg */
|
||||
struct conflux_params_t {
|
||||
conflux_alg_t alg;
|
||||
};
|
||||
|
||||
struct conflux_leg_t {
|
||||
/**
|
||||
* For computing ooo_q insertion sequence numbers: Highest absolute
|
||||
* sequence number received on each leg, before delivery.
|
||||
*
|
||||
* As a receiver, this allows us to compute the absolute sequence number
|
||||
* of a cell for delivery or insertion into the ooo_q. When a SWITCH cell
|
||||
* is received on a leg, the absolute sequence number of that cell is
|
||||
* the relative sequence number in that cell, plus the absolute sequence
|
||||
* number of that leg from this array. The leg's sequence number
|
||||
* is then updated to this value immediately.
|
||||
*
|
||||
* In this way, we are able to assign absolute sequence numbers to cells
|
||||
* immediately, regardless of how many legs or leg switches have occurred,
|
||||
* and regardless of the delivery status of each cell versus if it must be
|
||||
* queued.
|
||||
*/
|
||||
uint64_t last_seq_recv;
|
||||
|
||||
/**
|
||||
* For relative sequencing: Highest absolute sequence number sent on each
|
||||
* circuit. The overall absolute current sent sequence number is the highest
|
||||
* of these values.
|
||||
*
|
||||
* As a sender, this allows us to compute a relative sequence number when
|
||||
* switching legs. When switching legs, the sender looks up its current
|
||||
* absolute sequence number as the maximum of all legs. The sender then
|
||||
* compares that to the current sequence number on the leg it is about to
|
||||
* send on, and then computes the relative sequence number as the difference
|
||||
* between the overall absolute sequence number and the sequence number
|
||||
* from the sending leg.
|
||||
*
|
||||
* In this way, we can use much smaller relative sequence numbers on the
|
||||
* wire, as opposed to larger absolute values, at the expense of this
|
||||
* bookkeeping overhead on each end.
|
||||
*/
|
||||
uint64_t last_seq_sent;
|
||||
|
||||
/**
|
||||
* Current round-trip of the circuit, in usec.
|
||||
*
|
||||
* XXX: In theory, we could use the congestion control RTTs directly off the
|
||||
* circs, but congestion control code has assumptions about the RTT being 0
|
||||
* at the start of the circuit, which will *not* be the case here, because we
|
||||
* get an RTT off the link circuit. */
|
||||
uint64_t circ_rtts_usec;
|
||||
|
||||
/** Exit side only: When was the LINKED cell sent? Used for RTT measurement
|
||||
* that sets circ_rtts_usec when the LINKED_ACK is received. */
|
||||
uint64_t linked_sent_usec;
|
||||
|
||||
/** Circuit of this leg. */
|
||||
circuit_t *circ;
|
||||
};
|
||||
|
||||
/** Fields for conflux multipath support */
|
||||
struct conflux_t {
|
||||
/** Cached parameters for this circuit */
|
||||
struct conflux_params_t params;
|
||||
|
||||
/**
|
||||
* List of all linked conflux_leg_t for this set. Once a leg is in that list,
|
||||
* it can be used to transmit data. */
|
||||
smartlist_t *legs;
|
||||
|
||||
/**
|
||||
* Out-of-order priority queue of conflux_cell_t *, heapified
|
||||
* on conflux_cell_t.seq number (lowest at top of heap).
|
||||
*
|
||||
* XXX: We are most likely to insert cells at either the head or the tail.
|
||||
* Verify that is fast-path wrt smartlist priority queues, and not a memmove
|
||||
* nightmare. If so, we may need a real linked list, or a packed_cell_t list.
|
||||
*/
|
||||
smartlist_t *ooo_q;
|
||||
|
||||
/**
|
||||
* Absolute sequence number of cells delivered to streams since start.
|
||||
* (ie: this is updated *after* dequeue from the ooo_q priority queue). */
|
||||
uint64_t last_seq_delivered;
|
||||
|
||||
/**
|
||||
* The estimated remaining number of cells we can send on this circuit
|
||||
* before we are allowed to switch legs. */
|
||||
uint64_t cells_until_switch;
|
||||
|
||||
/** Current circuit leg. Only use this with conflux_get_circ_for_leg() for
|
||||
* bounds checking. */
|
||||
struct conflux_leg_t *curr_leg;
|
||||
|
||||
/** Previous circuit leg. Only use this with conflux_get_circ_for_leg() for
|
||||
* bounds checking. */
|
||||
struct conflux_leg_t *prev_leg;
|
||||
|
||||
/** The nonce that joins these */
|
||||
uint8_t nonce[DIGEST256_LEN];
|
||||
|
||||
/** Indicate if this conflux set is in full teardown. We mark it at the first
|
||||
* close in case of a total teardown so we avoid recursive calls of circuit
|
||||
* mark for close. */
|
||||
bool in_full_teardown;
|
||||
|
||||
/** Number of leg launch that we've done for this set. We keep this value
|
||||
* because there is a maximum allowed in order to avoid side channel(s). */
|
||||
unsigned int num_leg_launch;
|
||||
|
||||
/**
|
||||
* PolicyHint: Predicted ports/protocol shorthand..
|
||||
*
|
||||
* XXX: This might be redundant to the circuit's exitpolicy.
|
||||
*/
|
||||
};
|
||||
|
||||
#endif /* !defined(CONFLUX_ST_H) */
|
||||
@@ -0,0 +1,23 @@
|
||||
/* Copyright (c) 2023, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file conflux_sys.h
|
||||
* \brief Header file for conflux_sys.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONFLUX_SYS_H
|
||||
#define TOR_CONFLUX_SYS_H
|
||||
|
||||
extern const struct subsys_fns_t sys_conflux;
|
||||
|
||||
/**
|
||||
* Subsystem level.
|
||||
*
|
||||
* Defined here so that it can be shared between the real and stub
|
||||
* definitions.
|
||||
**/
|
||||
#define CONFLUX_SUBSYS_LEVEL (10)
|
||||
|
||||
#endif /* TOR_CONFLUX_SYS_H */
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/* Copyright (c) 2023, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file conflux_util.h
|
||||
* \brief Header file for conflux_util.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONFLUX_UTIL_H
|
||||
#define TOR_CONFLUX_UTIL_H
|
||||
|
||||
/* Forward decls */
|
||||
typedef struct edge_connection_t edge_connection_t;
|
||||
typedef struct crypt_path_t crypt_path_t;
|
||||
typedef struct origin_circuit_t origin_circuit_t;
|
||||
typedef struct conflux_t conflux_t;
|
||||
|
||||
/* True iff the given circuit_t circ is conflux related. */
|
||||
static inline bool
|
||||
CIRCUIT_IS_CONFLUX(const circuit_t *circ)
|
||||
{
|
||||
if (circ->conflux_pending_nonce) {
|
||||
if (CIRCUIT_IS_ORIGIN(circ))
|
||||
tor_assert_nonfatal(circ->purpose == CIRCUIT_PURPOSE_CONFLUX_UNLINKED);
|
||||
return true;
|
||||
} else if (circ->conflux) {
|
||||
if (CIRCUIT_IS_ORIGIN(circ))
|
||||
tor_assert_nonfatal(circ->purpose == CIRCUIT_PURPOSE_CONFLUX_LINKED);
|
||||
return true;
|
||||
} else {
|
||||
/* We don't assert on purposes here because we can end up in this branch
|
||||
* with circ->conflux being NULL but for a conflux purpose. This happens in
|
||||
* the about_to_free() code path. */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const uint8_t *conflux_get_nonce(const circuit_t *circ);
|
||||
uint64_t conflux_get_circ_rtt(const circuit_t *circ);
|
||||
|
||||
int circuit_get_package_window(circuit_t *circ,
|
||||
const crypt_path_t *cpath);
|
||||
bool conflux_can_send(conflux_t *cfx);
|
||||
|
||||
bool edge_uses_cpath(const edge_connection_t *conn,
|
||||
const crypt_path_t *cpath);
|
||||
crypt_path_t *conflux_get_destination_hop(circuit_t *circ);
|
||||
bool conflux_validate_source_hop(circuit_t *in_circ,
|
||||
crypt_path_t *layer_hint);
|
||||
uint64_t edge_get_max_rtt(const edge_connection_t *stream);
|
||||
bool relay_crypt_from_last_hop(const origin_circuit_t *circ,
|
||||
const crypt_path_t *layer_hint);
|
||||
|
||||
void conflux_update_p_streams(origin_circuit_t *, edge_connection_t *);
|
||||
void conflux_update_half_streams(origin_circuit_t *, smartlist_t *);
|
||||
void conflux_update_n_streams(or_circuit_t *, edge_connection_t *);
|
||||
void conflux_update_resolving_streams(or_circuit_t *, edge_connection_t *);
|
||||
void conflux_sync_circ_fields(conflux_t *cfx, origin_circuit_t *ref_circ);
|
||||
void conflux_validate_stream_lists(const conflux_t *cfx);
|
||||
void conflux_validate_legs(const conflux_t *cfx);
|
||||
|
||||
#endif /* TOR_CONFLUX_UTIL_H */
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
/* Copyright (c) 2019-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file congestion_control_common.h
|
||||
* \brief Public APIs for congestion control
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONGESTION_CONTROL_COMMON_H
|
||||
#define TOR_CONGESTION_CONTROL_COMMON_H
|
||||
|
||||
#include "core/crypto/onion_crypto.h"
|
||||
#include "core/or/crypt_path_st.h"
|
||||
#include "core/or/circuit_st.h"
|
||||
|
||||
/* The maximum whole number of cells that can fit in a
|
||||
* full TLS record. This is 31. */
|
||||
#define TLS_RECORD_MAX_CELLS ((16 * 1024) / CELL_MAX_NETWORK_SIZE)
|
||||
|
||||
typedef struct congestion_control_t congestion_control_t;
|
||||
|
||||
/**
|
||||
* Specifies the path type to help choose congestion control
|
||||
* parameters. Since these paths are different lengths, they
|
||||
* will need different queue parameters. */
|
||||
typedef enum {
|
||||
CC_PATH_EXIT = 0,
|
||||
CC_PATH_ONION = 1,
|
||||
CC_PATH_ONION_SOS = 2,
|
||||
CC_PATH_ONION_VG = 3,
|
||||
CC_PATH_SBWS = 4,
|
||||
} cc_path_t;
|
||||
|
||||
/** The length of a path for sbws measurement */
|
||||
#define SBWS_ROUTE_LEN 2
|
||||
|
||||
/** Wrapper for the free function, set the CC pointer to NULL after free */
|
||||
#define congestion_control_free(cc) \
|
||||
FREE_AND_NULL(congestion_control_t, congestion_control_free_, cc)
|
||||
|
||||
void congestion_control_free_(congestion_control_t *cc);
|
||||
|
||||
struct circuit_params_t;
|
||||
congestion_control_t *congestion_control_new(
|
||||
const struct circuit_params_t *params,
|
||||
cc_path_t path);
|
||||
|
||||
int congestion_control_dispatch_cc_alg(congestion_control_t *cc,
|
||||
circuit_t *circ);
|
||||
|
||||
void congestion_control_note_cell_sent(congestion_control_t *cc,
|
||||
const circuit_t *circ,
|
||||
const crypt_path_t *cpath);
|
||||
|
||||
bool congestion_control_update_circuit_estimates(congestion_control_t *,
|
||||
const circuit_t *);
|
||||
|
||||
int congestion_control_get_package_window(const circuit_t *,
|
||||
const crypt_path_t *);
|
||||
|
||||
int sendme_get_inc_count(const circuit_t *, const crypt_path_t *);
|
||||
bool circuit_sent_cell_for_sendme(const circuit_t *, const crypt_path_t *);
|
||||
bool is_monotime_clock_reliable(void);
|
||||
|
||||
void congestion_control_new_consensus_params(const networkstatus_t *ns);
|
||||
|
||||
bool congestion_control_enabled(void);
|
||||
|
||||
int congestion_control_build_ext_request(uint8_t **msg_out,
|
||||
size_t *msg_len_out);
|
||||
int congestion_control_parse_ext_request(const uint8_t *msg,
|
||||
const size_t msg_len);
|
||||
int congestion_control_build_ext_response(const circuit_params_t *our_params,
|
||||
const circuit_params_t *circ_params,
|
||||
uint8_t **msg_out,
|
||||
size_t *msg_len_out);
|
||||
int congestion_control_parse_ext_response(const uint8_t *msg,
|
||||
const size_t msg_len,
|
||||
circuit_params_t *params_out);
|
||||
bool congestion_control_validate_sendme_increment(uint8_t sendme_inc);
|
||||
char *congestion_control_get_control_port_fields(const origin_circuit_t *);
|
||||
|
||||
uint64_t congestion_control_get_num_rtt_reset(void);
|
||||
uint64_t congestion_control_get_num_clock_stalls(void);
|
||||
|
||||
extern uint64_t cc_stats_circs_created;
|
||||
|
||||
/* Ugh, C.. these are private. Use the getter instead, when
|
||||
* external to the congestion control code. */
|
||||
extern uint32_t or_conn_highwater;
|
||||
extern uint32_t or_conn_lowwater;
|
||||
extern int32_t cell_queue_high;
|
||||
extern int32_t cell_queue_low;
|
||||
extern uint8_t cc_sendme_inc;
|
||||
|
||||
/** Stop writing on an orconn when its outbuf is this large */
|
||||
static inline uint32_t
|
||||
or_conn_highwatermark(void)
|
||||
{
|
||||
return or_conn_highwater;
|
||||
}
|
||||
|
||||
/** Resume writing on an orconn when its outbuf is less than this */
|
||||
static inline uint32_t
|
||||
or_conn_lowwatermark(void)
|
||||
{
|
||||
return or_conn_lowwater;
|
||||
}
|
||||
|
||||
/** Stop reading on edge connections when we have this many cells
|
||||
* waiting on the appropriate queue. */
|
||||
static inline int32_t
|
||||
cell_queue_highwatermark(void)
|
||||
{
|
||||
return cell_queue_high;
|
||||
}
|
||||
|
||||
/** Start reading from edge connections again when we get down to this many
|
||||
* cells. */
|
||||
static inline int32_t
|
||||
cell_queue_lowwatermark(void)
|
||||
{
|
||||
return cell_queue_low;
|
||||
}
|
||||
|
||||
/** Returns the sendme inc rate cached from the most recent consensus */
|
||||
static inline uint8_t
|
||||
congestion_control_sendme_inc(void)
|
||||
{
|
||||
return cc_sendme_inc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute an N-count EWMA, aka N-EWMA. N-EWMA is defined as:
|
||||
* EWMA = alpha*value + (1-alpha)*EWMA_prev
|
||||
* with alpha = 2/(N+1).
|
||||
*
|
||||
* This works out to:
|
||||
* EWMA = value*2/(N+1) + EMA_prev*(N-1)/(N+1)
|
||||
* = (value*2 + EWMA_prev*(N-1))/(N+1)
|
||||
*/
|
||||
static inline uint64_t
|
||||
n_count_ewma(uint64_t curr, uint64_t prev, uint64_t N)
|
||||
{
|
||||
if (prev == 0)
|
||||
return curr;
|
||||
else
|
||||
return (2*curr + (N-1)*prev)/(N+1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that gives us a percentile weighted-average between
|
||||
* two values. The pct_max argument specifies the percentage weight of the
|
||||
* maximum of a and b, when computing this weighted-average.
|
||||
*
|
||||
* This also allows this function to be used as either MIN() or a MAX()
|
||||
* by this parameterization. It is MIN() when pct_max==0;
|
||||
* it is MAX() when pct_max==100; it is avg() when pct_max==50; it is a
|
||||
* weighted-average for values in between.
|
||||
*/
|
||||
static inline uint64_t
|
||||
percent_max_mix(uint64_t a, uint64_t b, uint8_t pct_max)
|
||||
{
|
||||
uint64_t max = MAX(a, b);
|
||||
uint64_t min = MIN(a, b);
|
||||
|
||||
if (BUG(pct_max > 100)) {
|
||||
return max;
|
||||
}
|
||||
|
||||
return pct_max*max/100 + (100-pct_max)*min/100;
|
||||
}
|
||||
|
||||
/* Private section starts. */
|
||||
#ifdef TOR_CONGESTION_CONTROL_COMMON_PRIVATE
|
||||
STATIC uint64_t congestion_control_update_circuit_rtt(congestion_control_t *,
|
||||
uint64_t);
|
||||
|
||||
STATIC bool time_delta_stalled_or_jumped(const congestion_control_t *cc,
|
||||
uint64_t old_delta, uint64_t new_delta);
|
||||
|
||||
STATIC void enqueue_timestamp(smartlist_t *timestamps_u64,
|
||||
uint64_t timestamp_usec);
|
||||
|
||||
/*
|
||||
* Unit tests declaractions.
|
||||
*/
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
|
||||
extern bool is_monotime_clock_broken;
|
||||
extern cc_alg_t cc_alg;
|
||||
void congestion_control_set_cc_enabled(void);
|
||||
void congestion_control_set_cc_disabled(void);
|
||||
|
||||
#endif /* defined(TOR_UNIT_TESTS) */
|
||||
|
||||
#endif /* defined(TOR_CONGESTION_CONTROL_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CONGESTION_CONTROL_COMMON_H) */
|
||||
@@ -0,0 +1,52 @@
|
||||
/* Copyright (c) 2019-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file congestion_control_flow.h
|
||||
* \brief APIs for stream flow control on congestion controlled circuits.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONGESTION_CONTROL_FLOW_H
|
||||
#define TOR_CONGESTION_CONTROL_FLOW_H
|
||||
|
||||
#include "core/or/crypt_path_st.h"
|
||||
#include "core/or/circuit_st.h"
|
||||
#include "core/or/edge_connection_st.h"
|
||||
|
||||
void flow_control_new_consensus_params(const struct networkstatus_t *);
|
||||
|
||||
bool circuit_process_stream_xoff(edge_connection_t *conn,
|
||||
const crypt_path_t *layer_hint,
|
||||
const cell_t *cell);
|
||||
bool circuit_process_stream_xon(edge_connection_t *conn,
|
||||
const crypt_path_t *layer_hint,
|
||||
const cell_t *cell);
|
||||
|
||||
int flow_control_decide_xoff(edge_connection_t *stream);
|
||||
void flow_control_decide_xon(edge_connection_t *stream, size_t n_written);
|
||||
|
||||
void flow_control_note_sent_data(edge_connection_t *stream, size_t len);
|
||||
|
||||
bool edge_uses_flow_control(const edge_connection_t *stream);
|
||||
|
||||
bool conn_uses_flow_control(connection_t *stream);
|
||||
|
||||
/** Metricsport externs */
|
||||
extern uint64_t cc_stats_flow_num_xoff_sent;
|
||||
extern uint64_t cc_stats_flow_num_xon_sent;
|
||||
extern double cc_stats_flow_xoff_outbuf_ma;
|
||||
extern double cc_stats_flow_xon_outbuf_ma;
|
||||
|
||||
/* Private section starts. */
|
||||
#ifdef TOR_CONGESTION_CONTROL_FLOW_PRIVATE
|
||||
|
||||
/*
|
||||
* Unit tests declaractions.
|
||||
*/
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
|
||||
#endif /* defined(TOR_UNIT_TESTS) */
|
||||
|
||||
#endif /* defined(TOR_CONGESTION_CONTROL_FLOW_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CONGESTION_CONTROL_FLOW_H) */
|
||||
@@ -0,0 +1,242 @@
|
||||
/* Copyright (c) 2019-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file congestion_control_st.h
|
||||
* \brief Structure definitions for congestion control.
|
||||
**/
|
||||
|
||||
#ifndef CONGESTION_CONTROL_ST_H
|
||||
#define CONGESTION_CONTROL_ST_H
|
||||
|
||||
#include "core/or/crypt_path_st.h"
|
||||
#include "core/or/circuit_st.h"
|
||||
|
||||
/** Signifies which sendme algorithm to use */
|
||||
typedef enum {
|
||||
/** OG Tor fixed-sized circ and stream windows. It sucks, but it is important
|
||||
* to make sure that the new algs can compete with the old garbage. */
|
||||
CC_ALG_SENDME = 0,
|
||||
|
||||
/**
|
||||
* Prop#324 TOR_WESTWOOD - Deliberately aggressive. Westwood may not even
|
||||
* converge to fairness in some cases because max RTT will also increase
|
||||
* on congestion, which boosts the Westwood RTT congestion threshold. So it
|
||||
* can cause runaway queue bloat, which may or may not lead to a robot
|
||||
* uprising... Ok that's Westworld, not Westwood. Still, we need to test
|
||||
* Vegas and NOLA against something more aggressive to ensure they do not
|
||||
* starve in the presence of cheaters. We also need to make sure cheaters
|
||||
* trigger the oomkiller in those cases.
|
||||
*/
|
||||
CC_ALG_WESTWOOD = 1,
|
||||
|
||||
/**
|
||||
* Prop#324 TOR_VEGAS - TCP Vegas-style BDP tracker. Because Vegas backs off
|
||||
* whenever it detects queue delay, it can be beaten out by more aggressive
|
||||
* algs. However, in live network testing, it seems to do just fine against
|
||||
* current SENDMEs. It outperforms Westwood and does not stall. */
|
||||
CC_ALG_VEGAS = 2,
|
||||
|
||||
/**
|
||||
* Prop#324: TOR_NOLA - NOLA looks the BDP right in the eye and uses it
|
||||
* immediately as CWND. No slow start, no other congestion signals, no delay,
|
||||
* no bullshit. Like TOR_VEGAS, it also uses aggressive BDP estimates, to
|
||||
* avoid out-competition. It seems a bit better throughput than Vegas, but
|
||||
* its aggressive BDP and rapid updates may lead to more queue latency. */
|
||||
CC_ALG_NOLA = 3,
|
||||
} cc_alg_t;
|
||||
|
||||
/* Total number of CC algs in cc_alg_t enum */
|
||||
#define NUM_CC_ALGS (CC_ALG_NOLA+1)
|
||||
|
||||
/** Signifies how we estimate circuit BDP */
|
||||
typedef enum {
|
||||
/* CWND-based BDP will respond to changes in RTT only, and is relative
|
||||
* to cwnd growth. So in slow-start, this will under-estimate BDP */
|
||||
BDP_ALG_CWND_RTT = 0,
|
||||
|
||||
/* Sendme-based BDP will quickly measure BDP in less than
|
||||
* a cwnd worth of data when in use. So it should be good for slow-start.
|
||||
* But if the link goes idle, it will be vastly lower than true BDP. Thus,
|
||||
* this estimate gets reset when the cwnd is not fully utilized. */
|
||||
BDP_ALG_SENDME_RATE = 1,
|
||||
|
||||
/* Inflight BDP is similar to the cwnd estimator, except it uses
|
||||
* packets inflight minus local circuit queues instead of current cwnd.
|
||||
* Because it is strictly less than or equal to the cwnd, it will cause
|
||||
* the cwnd to drift downward. It is only used if the local OR connection
|
||||
* is blocked. */
|
||||
BDP_ALG_INFLIGHT_RTT = 2,
|
||||
|
||||
/* The Piecewise BDP estimator uses the CWND estimator before there
|
||||
* are sufficient SENDMEs to calculate the SENDME estimator. At that
|
||||
* point, it uses the SENDME estimator, unless the local OR connection
|
||||
* becomes blocked. In that case, it switches to the inflight estimator. */
|
||||
BDP_ALG_PIECEWISE = 3,
|
||||
|
||||
} bdp_alg_t;
|
||||
|
||||
/** Total number of BDP algs in bdp_alg_t enum */
|
||||
#define NUM_BDP_ALGS (BDP_ALG_PIECEWISE+1)
|
||||
|
||||
/** Vegas algorithm parameters. */
|
||||
struct vegas_params_t {
|
||||
/** The slow-start cwnd cap for RFC3742 */
|
||||
uint32_t ss_cwnd_cap;
|
||||
/** The maximum slow-start cwnd */
|
||||
uint32_t ss_cwnd_max;
|
||||
/** The queue use allowed before we exit slow start */
|
||||
uint16_t gamma;
|
||||
/** The queue use below which we increment cwnd */
|
||||
uint16_t alpha;
|
||||
/** The queue use above which we decrement cwnd */
|
||||
uint16_t beta;
|
||||
/** The queue use at which we cap cwnd in steady state */
|
||||
uint16_t delta;
|
||||
/** Weighted average (percent) between cwnd estimator and
|
||||
* piecewise estimator. */
|
||||
uint8_t bdp_mix_pct;
|
||||
};
|
||||
|
||||
/** Fields common to all congestion control algorithms */
|
||||
struct congestion_control_t {
|
||||
/**
|
||||
* Smartlist of uint64_t monotime usec timestamps of when we sent a data
|
||||
* cell that is pending a sendme. FIFO queue that is managed similar to
|
||||
* sendme_last_digests. */
|
||||
smartlist_t *sendme_pending_timestamps;
|
||||
|
||||
/** RTT time data for congestion control. */
|
||||
uint64_t ewma_rtt_usec;
|
||||
uint64_t min_rtt_usec;
|
||||
uint64_t max_rtt_usec;
|
||||
|
||||
/* Vegas BDP estimate */
|
||||
uint64_t bdp;
|
||||
|
||||
/** Congestion window */
|
||||
uint64_t cwnd;
|
||||
|
||||
/** Number of cells in-flight (sent but awaiting SENDME ack). */
|
||||
uint64_t inflight;
|
||||
|
||||
/**
|
||||
* For steady-state: the number of sendme acks until we will acknowledge
|
||||
* a congestion event again. It starts out as the number of sendme acks
|
||||
* in a congestion window and is decremented each ack. When this reaches
|
||||
* 0, it means we should examine our congestion algorithm conditions.
|
||||
* In this way, we only react to one congestion event per congestion window.
|
||||
*
|
||||
* It is also reset to 0 immediately whenever the circuit's orconn is
|
||||
* blocked, and when a previously blocked orconn is unblocked.
|
||||
*/
|
||||
uint16_t next_cc_event;
|
||||
|
||||
/** Counts down until we process a cwnd worth of SENDME acks.
|
||||
* Used to track full cwnd status. */
|
||||
uint16_t next_cwnd_event;
|
||||
|
||||
/** Are we in slow start? */
|
||||
bool in_slow_start;
|
||||
|
||||
/** Has the cwnd become full since last cwnd update? */
|
||||
bool cwnd_full;
|
||||
|
||||
/** Is the local channel blocked on us? That's a congestion signal */
|
||||
bool blocked_chan;
|
||||
|
||||
/* The following parameters are cached from consensus values upon
|
||||
* circuit setup. */
|
||||
|
||||
/** Percent of cwnd to increment by during slow start */
|
||||
uint16_t cwnd_inc_pct_ss;
|
||||
|
||||
/** Number of cells to increment cwnd by during steady state */
|
||||
uint16_t cwnd_inc;
|
||||
|
||||
/** Minimum congestion window (must be at least sendme_inc) */
|
||||
uint16_t cwnd_min;
|
||||
|
||||
/**
|
||||
* Number of times per congestion window to update based on congestion
|
||||
* signals */
|
||||
uint8_t cwnd_inc_rate;
|
||||
|
||||
/**
|
||||
* Number of cells to ack with every sendme. Taken from consensus parameter
|
||||
* and negotiation during circuit setup. */
|
||||
uint8_t sendme_inc;
|
||||
|
||||
/** Which congestion control algorithm to use. Taken from
|
||||
* consensus parameter and negotiation during circuit setup. */
|
||||
cc_alg_t cc_alg;
|
||||
|
||||
/** Which algorithm to estimate circuit bandwidth with. Taken from
|
||||
* consensus parameter during circuit setup. */
|
||||
bdp_alg_t bdp_alg;
|
||||
|
||||
/** Vegas-specific parameters. These should not be accessed anywhere
|
||||
* other than the congestion_control_vegas.c file. */
|
||||
struct vegas_params_t vegas_params;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the number of sendme acks we will receive before we update cwnd.
|
||||
*
|
||||
* Congestion control literature recommends only one update of cwnd per
|
||||
* cwnd worth of acks. However, we can also tune this to be more frequent
|
||||
* by increasing the 'cc_cwnd_inc_rate' consensus parameter. This tuning
|
||||
* only applies after slow start.
|
||||
*
|
||||
* If this returns 0 due to high cwnd_inc_rate, the calling code will
|
||||
* update every sendme ack.
|
||||
*/
|
||||
static inline uint64_t CWND_UPDATE_RATE(const struct congestion_control_t *cc)
|
||||
{
|
||||
/* We add cwnd_inc_rate*sendme_inc/2 to round to nearest integer number
|
||||
* of acks */
|
||||
|
||||
if (cc->in_slow_start) {
|
||||
return 1;
|
||||
} else {
|
||||
return ((cc->cwnd + cc->cwnd_inc_rate*cc->sendme_inc/2)
|
||||
/ (cc->cwnd_inc_rate*cc->sendme_inc));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives us the number of SENDMEs in a CWND, rounded.
|
||||
*/
|
||||
static inline uint64_t SENDME_PER_CWND(const struct congestion_control_t *cc)
|
||||
{
|
||||
/* We add cwnd_inc_rate*sendme_inc/2 to round to nearest integer number
|
||||
* of acks */
|
||||
return ((cc->cwnd + cc->sendme_inc/2)/cc->sendme_inc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount to increment the congestion window each update,
|
||||
* during slow start.
|
||||
*
|
||||
* Congestion control literature recommends either doubling the cwnd
|
||||
* every cwnd during slow start, or some similar exponential growth
|
||||
* (such as 50% more every cwnd, for Vegas).
|
||||
*
|
||||
* This is controlled by a consensus parameter 'cwnd_inc_pct_ss', which
|
||||
* allows us to specify the percent of the current consensus window
|
||||
* to update by.
|
||||
*/
|
||||
static inline uint64_t CWND_INC_SS(const struct congestion_control_t *cc)
|
||||
{
|
||||
return (cc->cwnd_inc_pct_ss*cc->cwnd/100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount to increment (and for Vegas, also decrement) the
|
||||
* congestion window by, every update period.
|
||||
*
|
||||
* This is controlled by the cc_cwnd_inc consensus parameter.
|
||||
*/
|
||||
#define CWND_INC(cc) ((cc)->cwnd_inc)
|
||||
|
||||
#endif /* !defined(CONGESTION_CONTROL_ST_H) */
|
||||
@@ -0,0 +1,54 @@
|
||||
/* Copyright (c) 2019-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file congestion_control_vegas.h
|
||||
* \brief Private-ish APIs for the TOR_VEGAS congestion control algorithm
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONGESTION_CONTROL_VEGAS_H
|
||||
#define TOR_CONGESTION_CONTROL_VEGAS_H
|
||||
|
||||
#include "core/or/crypt_path_st.h"
|
||||
#include "core/or/circuit_st.h"
|
||||
|
||||
extern double cc_stats_vegas_exit_ss_cwnd_ma;
|
||||
extern double cc_stats_vegas_exit_ss_bdp_ma;
|
||||
extern double cc_stats_vegas_exit_ss_inc_ma;
|
||||
extern double cc_stats_vegas_gamma_drop_ma;
|
||||
extern double cc_stats_vegas_delta_drop_ma;
|
||||
extern double cc_stats_vegas_ss_csig_blocked_ma;
|
||||
extern double cc_stats_vegas_csig_blocked_ma;
|
||||
extern uint64_t cc_stats_vegas_above_delta;
|
||||
extern uint64_t cc_stats_vegas_above_ss_cwnd_max;
|
||||
|
||||
extern double cc_stats_vegas_csig_alpha_ma;
|
||||
extern double cc_stats_vegas_csig_beta_ma;
|
||||
extern double cc_stats_vegas_csig_delta_ma;
|
||||
|
||||
extern double cc_stats_vegas_ss_queue_ma;
|
||||
extern double cc_stats_vegas_queue_ma;
|
||||
extern double cc_stats_vegas_bdp_ma;
|
||||
|
||||
extern uint64_t cc_stats_vegas_below_ss_inc_floor;
|
||||
extern uint64_t cc_stats_vegas_circ_exited_ss;
|
||||
|
||||
/* Processing SENDME cell. */
|
||||
int congestion_control_vegas_process_sendme(struct congestion_control_t *cc,
|
||||
const circuit_t *circ);
|
||||
void congestion_control_vegas_set_params(struct congestion_control_t *cc,
|
||||
cc_path_t path);
|
||||
|
||||
/* Private section starts. */
|
||||
#ifdef TOR_CONGESTION_CONTROL_VEGAS_PRIVATE
|
||||
|
||||
/*
|
||||
* Unit tests declaractions.
|
||||
*/
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
|
||||
#endif /* defined(TOR_UNIT_TESTS) */
|
||||
|
||||
#endif /* defined(TOR_CONGESTION_CONTROL_VEGAS_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CONGESTION_CONTROL_VEGAS_H) */
|
||||
@@ -0,0 +1,311 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file connection_edge.h
|
||||
* \brief Header file for connection_edge.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONNECTION_EDGE_H
|
||||
#define TOR_CONNECTION_EDGE_H
|
||||
|
||||
#include "lib/testsupport/testsupport.h"
|
||||
|
||||
#include "feature/hs/hs_service.h"
|
||||
|
||||
edge_connection_t *TO_EDGE_CONN(connection_t *);
|
||||
entry_connection_t *TO_ENTRY_CONN(connection_t *);
|
||||
entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *);
|
||||
|
||||
const edge_connection_t *CONST_TO_EDGE_CONN(const connection_t *);
|
||||
const entry_connection_t *CONST_TO_ENTRY_CONN(const connection_t *);
|
||||
const entry_connection_t *CONST_EDGE_TO_ENTRY_CONN(const edge_connection_t *);
|
||||
|
||||
#define EXIT_CONN_STATE_MIN_ 1
|
||||
/** State for an exit connection: waiting for response from DNS farm. */
|
||||
#define EXIT_CONN_STATE_RESOLVING 1
|
||||
/** State for an exit connection: waiting for connect() to finish. */
|
||||
#define EXIT_CONN_STATE_CONNECTING 2
|
||||
/** State for an exit connection: open and ready to transmit data. */
|
||||
#define EXIT_CONN_STATE_OPEN 3
|
||||
/** State for an exit connection: waiting to be removed. */
|
||||
#define EXIT_CONN_STATE_RESOLVEFAILED 4
|
||||
#define EXIT_CONN_STATE_MAX_ 4
|
||||
|
||||
/* The AP state values must be disjoint from the EXIT state values. */
|
||||
#define AP_CONN_STATE_MIN_ 5
|
||||
/** State for a SOCKS connection: waiting for SOCKS request. */
|
||||
#define AP_CONN_STATE_SOCKS_WAIT 5
|
||||
/** State for a SOCKS connection: got a y.onion URL; waiting to receive
|
||||
* rendezvous descriptor. */
|
||||
#define AP_CONN_STATE_RENDDESC_WAIT 6
|
||||
/** The controller will attach this connection to a circuit; it isn't our
|
||||
* job to do so. */
|
||||
#define AP_CONN_STATE_CONTROLLER_WAIT 7
|
||||
/** State for a SOCKS connection: waiting for a completed circuit. */
|
||||
#define AP_CONN_STATE_CIRCUIT_WAIT 8
|
||||
/** State for a SOCKS connection: sent BEGIN, waiting for CONNECTED. */
|
||||
#define AP_CONN_STATE_CONNECT_WAIT 9
|
||||
/** State for a SOCKS connection: sent RESOLVE, waiting for RESOLVED. */
|
||||
#define AP_CONN_STATE_RESOLVE_WAIT 10
|
||||
/** State for a SOCKS connection: ready to send and receive. */
|
||||
#define AP_CONN_STATE_OPEN 11
|
||||
/** State for a transparent natd connection: waiting for original
|
||||
* destination. */
|
||||
#define AP_CONN_STATE_NATD_WAIT 12
|
||||
/** State for an HTTP tunnel: waiting for an HTTP CONNECT command. */
|
||||
#define AP_CONN_STATE_HTTP_CONNECT_WAIT 13
|
||||
#define AP_CONN_STATE_MAX_ 13
|
||||
|
||||
#define EXIT_PURPOSE_MIN_ 1
|
||||
/** This exit stream wants to do an ordinary connect. */
|
||||
#define EXIT_PURPOSE_CONNECT 1
|
||||
/** This exit stream wants to do a resolve (either normal or reverse). */
|
||||
#define EXIT_PURPOSE_RESOLVE 2
|
||||
#define EXIT_PURPOSE_MAX_ 2
|
||||
|
||||
/** True iff the AP_CONN_STATE_* value <b>s</b> means that the corresponding
|
||||
* edge connection is not attached to any circuit. */
|
||||
#define AP_CONN_STATE_IS_UNATTACHED(s) \
|
||||
((s) <= AP_CONN_STATE_CIRCUIT_WAIT || (s) == AP_CONN_STATE_NATD_WAIT)
|
||||
|
||||
#define connection_mark_unattached_ap(conn, endreason) \
|
||||
connection_mark_unattached_ap_((conn), (endreason), __LINE__, SHORT_FILE__)
|
||||
|
||||
/** Possible return values for parse_extended_hostname. */
|
||||
typedef enum hostname_type_t {
|
||||
BAD_HOSTNAME,
|
||||
EXIT_HOSTNAME,
|
||||
NORMAL_HOSTNAME,
|
||||
ONION_V3_HOSTNAME,
|
||||
} hostname_type_t;
|
||||
|
||||
MOCK_DECL(void,connection_mark_unattached_ap_,
|
||||
(entry_connection_t *conn, int endreason,
|
||||
int line, const char *file));
|
||||
int connection_edge_reached_eof(edge_connection_t *conn);
|
||||
int connection_edge_process_inbuf(edge_connection_t *conn,
|
||||
int package_partial);
|
||||
int connection_edge_destroy(circid_t circ_id, edge_connection_t *conn);
|
||||
int connection_edge_end(edge_connection_t *conn, uint8_t reason);
|
||||
int connection_edge_end_errno(edge_connection_t *conn);
|
||||
void connection_edge_end_close(edge_connection_t *conn, uint8_t reason);
|
||||
int connection_edge_flushed_some(edge_connection_t *conn);
|
||||
int connection_edge_finished_flushing(edge_connection_t *conn);
|
||||
int connection_edge_finished_connecting(edge_connection_t *conn);
|
||||
|
||||
void connection_entry_set_controller_wait(entry_connection_t *conn);
|
||||
|
||||
void connection_ap_about_to_close(entry_connection_t *edge_conn);
|
||||
void connection_exit_about_to_close(edge_connection_t *edge_conn);
|
||||
|
||||
MOCK_DECL(int,
|
||||
connection_ap_handshake_send_begin,(entry_connection_t *ap_conn));
|
||||
int connection_ap_handshake_send_resolve(entry_connection_t *ap_conn);
|
||||
|
||||
entry_connection_t *connection_ap_make_link(connection_t *partner,
|
||||
char *address, uint16_t port,
|
||||
const char *digest,
|
||||
int session_group,
|
||||
int isolation_flags,
|
||||
int use_begindir, int want_onehop);
|
||||
void connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
|
||||
size_t replylen,
|
||||
int endreason);
|
||||
MOCK_DECL(void,connection_ap_handshake_socks_resolved,
|
||||
(entry_connection_t *conn,
|
||||
int answer_type,
|
||||
size_t answer_len,
|
||||
const uint8_t *answer,
|
||||
int ttl,
|
||||
time_t expires));
|
||||
void connection_ap_handshake_socks_resolved_addr(entry_connection_t *conn,
|
||||
const tor_addr_t *answer,
|
||||
int ttl,
|
||||
time_t expires);
|
||||
|
||||
int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
|
||||
int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ);
|
||||
void connection_exit_connect(edge_connection_t *conn);
|
||||
int connection_edge_is_rendezvous_stream(const edge_connection_t *conn);
|
||||
int connection_ap_can_use_exit(const entry_connection_t *conn,
|
||||
const node_t *exit);
|
||||
void connection_ap_expire_beginning(void);
|
||||
void connection_ap_rescan_and_attach_pending(void);
|
||||
void connection_ap_attach_pending(int retry);
|
||||
void connection_ap_mark_as_pending_circuit_(entry_connection_t *entry_conn,
|
||||
const char *file, int line);
|
||||
#define connection_ap_mark_as_pending_circuit(c) \
|
||||
connection_ap_mark_as_pending_circuit_((c), __FILE__, __LINE__)
|
||||
void connection_ap_mark_as_non_pending_circuit(entry_connection_t *entry_conn);
|
||||
void connection_ap_mark_as_waiting_for_renddesc(
|
||||
entry_connection_t *entry_conn);
|
||||
|
||||
#define CONNECTION_AP_EXPECT_NONPENDING(c) do { \
|
||||
if (ENTRY_TO_CONN(c)->state == AP_CONN_STATE_CIRCUIT_WAIT) { \
|
||||
log_warn(LD_BUG, "At %s:%d: %p was unexpectedly in circuit_wait.", \
|
||||
__FILE__, __LINE__, (c)); \
|
||||
connection_ap_mark_as_non_pending_circuit(c); \
|
||||
} \
|
||||
} while (0)
|
||||
void connection_ap_fail_onehop(const char *failed_digest,
|
||||
cpath_build_state_t *build_state);
|
||||
void circuit_discard_optional_exit_enclaves(extend_info_t *info);
|
||||
int connection_ap_detach_retriable(entry_connection_t *conn,
|
||||
origin_circuit_t *circ,
|
||||
int reason);
|
||||
int connection_ap_process_transparent(entry_connection_t *conn);
|
||||
|
||||
int address_is_invalid_destination(const char *address, int client);
|
||||
|
||||
MOCK_DECL(int, connection_ap_rewrite_and_attach_if_allowed,
|
||||
(entry_connection_t *conn,
|
||||
origin_circuit_t *circ,
|
||||
crypt_path_t *cpath));
|
||||
int connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
|
||||
origin_circuit_t *circ,
|
||||
crypt_path_t *cpath);
|
||||
|
||||
#if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H)
|
||||
int get_pf_socket(void);
|
||||
#endif
|
||||
|
||||
int connection_edge_compatible_with_circuit(const entry_connection_t *conn,
|
||||
const origin_circuit_t *circ);
|
||||
int connection_edge_update_circuit_isolation(const entry_connection_t *conn,
|
||||
origin_circuit_t *circ,
|
||||
int dry_run);
|
||||
void circuit_clear_isolation(origin_circuit_t *circ);
|
||||
streamid_t get_unique_stream_id_by_circ(origin_circuit_t *circ);
|
||||
|
||||
void connection_edge_free_all(void);
|
||||
|
||||
void connection_ap_warn_and_unmark_if_pending_circ(
|
||||
entry_connection_t *entry_conn,
|
||||
const char *where);
|
||||
|
||||
/** Lowest value for DNS ttl clipping excluding the random addition. */
|
||||
#define MIN_DNS_TTL (5*60)
|
||||
/** Highest value for DNS ttl clipping excluding the random addition. */
|
||||
#define MAX_DNS_TTL (60*60)
|
||||
/** How long do we keep DNS cache entries before purging them (regardless of
|
||||
* their TTL)? */
|
||||
#define MAX_DNS_ENTRY_AGE (3*60*60)
|
||||
/** How long do we cache/tell clients to cache DNS records when no TTL is
|
||||
* known? */
|
||||
#define DEFAULT_DNS_TTL (30*60)
|
||||
/** How much should we +- each TTL to make it fuzzy with uniform sampling at
|
||||
* exits? The value 4 minutes was chosen so that the lowest possible clip is
|
||||
* 60s. Such low clips were used in the past for all TTLs due to a bug in Tor,
|
||||
* see "The effect of DNS on Tor's Anonymity" by Greschbach et al. In other
|
||||
* words, sampling such low clips is unlikely to cause any breakage at exits.
|
||||
*/
|
||||
#define FUZZY_DNS_TTL (4*60)
|
||||
|
||||
uint32_t clip_dns_ttl(uint32_t ttl);
|
||||
uint32_t clip_dns_fuzzy_ttl(uint32_t ttl);
|
||||
|
||||
int connection_half_edge_is_valid_data(const smartlist_t *half_conns,
|
||||
streamid_t stream_id);
|
||||
int connection_half_edge_is_valid_sendme(const smartlist_t *half_conns,
|
||||
streamid_t stream_id);
|
||||
int connection_half_edge_is_valid_connected(const smartlist_t *half_conns,
|
||||
streamid_t stream_id);
|
||||
int connection_half_edge_is_valid_end(smartlist_t *half_conns,
|
||||
streamid_t stream_id);
|
||||
int connection_half_edge_is_valid_resolved(smartlist_t *half_conns,
|
||||
streamid_t stream_id);
|
||||
bool connection_half_edges_waiting(const origin_circuit_t *circ);
|
||||
|
||||
size_t half_streams_get_total_allocation(void);
|
||||
struct half_edge_t;
|
||||
void half_edge_free_(struct half_edge_t *he);
|
||||
#define half_edge_free(he) \
|
||||
FREE_AND_NULL(half_edge_t, half_edge_free_, (he))
|
||||
|
||||
/** @name Begin-cell flags
|
||||
*
|
||||
* These flags are used in RELAY_BEGIN cells to change the default behavior
|
||||
* of the cell.
|
||||
*
|
||||
* @{
|
||||
**/
|
||||
/** When this flag is set, the client is willing to get connected to IPv6
|
||||
* addresses */
|
||||
#define BEGIN_FLAG_IPV6_OK (1u<<0)
|
||||
/** When this flag is set, the client DOES NOT support connecting to IPv4
|
||||
* addresses. (The sense of this flag is inverted from IPV6_OK, so that the
|
||||
* old default behavior of Tor is equivalent to having all flags set to 0.)
|
||||
**/
|
||||
#define BEGIN_FLAG_IPV4_NOT_OK (1u<<1)
|
||||
/** When this flag is set, if we find both an IPv4 and an IPv6 address,
|
||||
* we use the IPv6 address. Otherwise we use the IPv4 address. */
|
||||
#define BEGIN_FLAG_IPV6_PREFERRED (1u<<2)
|
||||
/**@}*/
|
||||
|
||||
#ifdef CONNECTION_EDGE_PRIVATE
|
||||
|
||||
STATIC bool parse_extended_hostname(char *address, hostname_type_t *type_out);
|
||||
|
||||
/** A parsed BEGIN or BEGIN_DIR cell */
|
||||
typedef struct begin_cell_t {
|
||||
/** The address the client has asked us to connect to, or NULL if this is
|
||||
* a BEGIN_DIR cell*/
|
||||
char *address;
|
||||
/** The flags specified in the BEGIN cell's body. One or more of
|
||||
* BEGIN_FLAG_*. */
|
||||
uint32_t flags;
|
||||
/** The client's requested port. */
|
||||
uint16_t port;
|
||||
/** The client's requested Stream ID */
|
||||
uint16_t stream_id;
|
||||
/** True iff this is a BEGIN_DIR cell. */
|
||||
unsigned is_begindir : 1;
|
||||
} begin_cell_t;
|
||||
|
||||
STATIC int begin_cell_parse(const cell_t *cell, begin_cell_t *bcell,
|
||||
uint8_t *end_reason_out);
|
||||
STATIC int connected_cell_format_payload(uint8_t *payload_out,
|
||||
const tor_addr_t *addr,
|
||||
uint32_t ttl);
|
||||
|
||||
typedef struct {
|
||||
/** Original address, after we lowercased it but before we started
|
||||
* mapping it.
|
||||
*/
|
||||
char orig_address[MAX_SOCKS_ADDR_LEN];
|
||||
/** True iff the address has been automatically remapped to a local
|
||||
* address in VirtualAddrNetwork. (Only set true when we do a resolve
|
||||
* and get a virtual address; not when we connect to the address.) */
|
||||
int automap;
|
||||
/** If this connection has a .exit address, who put it there? */
|
||||
addressmap_entry_source_t exit_source;
|
||||
/** If we've rewritten the address, when does this map expire? */
|
||||
time_t map_expires;
|
||||
/** If we should close the connection, this is the end_reason to pass
|
||||
* to connection_mark_unattached_ap */
|
||||
int end_reason;
|
||||
/** True iff we should close the connection, either because of error or
|
||||
* because of successful early RESOLVED reply. */
|
||||
int should_close;
|
||||
} rewrite_result_t;
|
||||
|
||||
STATIC void connection_ap_handshake_rewrite(entry_connection_t *conn,
|
||||
rewrite_result_t *out);
|
||||
|
||||
STATIC int connection_ap_process_http_connect(entry_connection_t *conn);
|
||||
STATIC void export_hs_client_circuit_id(edge_connection_t *edge_conn,
|
||||
hs_circuit_id_protocol_t protocol);
|
||||
|
||||
struct half_edge_t;
|
||||
STATIC void connection_half_edge_add(const edge_connection_t *conn,
|
||||
origin_circuit_t *circ);
|
||||
STATIC struct half_edge_t *connection_half_edge_find_stream_id(
|
||||
const smartlist_t *half_conns,
|
||||
streamid_t stream_id);
|
||||
#endif /* defined(CONNECTION_EDGE_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_CONNECTION_EDGE_H) */
|
||||
@@ -0,0 +1,136 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file connection_or.h
|
||||
* \brief Header file for connection_or.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CONNECTION_OR_H
|
||||
#define TOR_CONNECTION_OR_H
|
||||
|
||||
struct ed25519_public_key_t;
|
||||
struct ed25519_keypair_t;
|
||||
|
||||
or_connection_t *TO_OR_CONN(connection_t *);
|
||||
const or_connection_t *CONST_TO_OR_CONN(const connection_t *);
|
||||
|
||||
#include "core/or/orconn_event.h"
|
||||
|
||||
void connection_or_clear_identity(or_connection_t *conn);
|
||||
void connection_or_clear_identity_map(void);
|
||||
void clear_broken_connection_map(int disable);
|
||||
|
||||
void connection_or_block_renegotiation(or_connection_t *conn);
|
||||
int connection_or_reached_eof(or_connection_t *conn);
|
||||
int connection_or_process_inbuf(or_connection_t *conn);
|
||||
ssize_t connection_or_num_cells_writeable(or_connection_t *conn);
|
||||
int connection_or_flushed_some(or_connection_t *conn);
|
||||
int connection_or_finished_flushing(or_connection_t *conn);
|
||||
int connection_or_finished_connecting(or_connection_t *conn);
|
||||
void connection_or_about_to_close(or_connection_t *conn);
|
||||
int connection_or_digest_is_known_relay(const char *id_digest);
|
||||
void connection_or_update_token_buckets(smartlist_t *conns,
|
||||
const or_options_t *options);
|
||||
|
||||
void connection_or_connect_failed(or_connection_t *conn,
|
||||
int reason, const char *msg);
|
||||
void connection_or_notify_error(or_connection_t *conn,
|
||||
int reason, const char *msg);
|
||||
MOCK_DECL(or_connection_t *,
|
||||
connection_or_connect,
|
||||
(const tor_addr_t *addr, uint16_t port,
|
||||
const char *id_digest,
|
||||
const struct ed25519_public_key_t *ed_id,
|
||||
channel_tls_t *chan));
|
||||
|
||||
void connection_or_close_normally(or_connection_t *orconn, int flush);
|
||||
MOCK_DECL(void,connection_or_close_for_error,
|
||||
(or_connection_t *orconn, int flush));
|
||||
|
||||
void connection_or_report_broken_states(int severity, int domain);
|
||||
|
||||
void connection_or_event_status(or_connection_t *conn,
|
||||
or_conn_status_event_t tp, int reason);
|
||||
|
||||
MOCK_DECL(int,connection_tls_start_handshake,(or_connection_t *conn,
|
||||
int receiving));
|
||||
int connection_tls_continue_handshake(or_connection_t *conn);
|
||||
void connection_or_set_canonical(or_connection_t *or_conn,
|
||||
int is_canonical);
|
||||
|
||||
int connection_init_or_handshake_state(or_connection_t *conn,
|
||||
int started_here);
|
||||
void connection_or_init_conn_from_address(or_connection_t *conn,
|
||||
const tor_addr_t *addr,
|
||||
uint16_t port,
|
||||
const char *rsa_id_digest,
|
||||
const struct ed25519_public_key_t *ed_id,
|
||||
int started_here);
|
||||
int connection_or_client_learned_peer_id(or_connection_t *conn,
|
||||
const uint8_t *rsa_peer_id,
|
||||
const struct ed25519_public_key_t *ed_peer_id);
|
||||
const struct ed25519_public_key_t *connection_or_get_alleged_ed25519_id(
|
||||
const or_connection_t *conn);
|
||||
time_t connection_or_client_used(or_connection_t *conn);
|
||||
MOCK_DECL(int, connection_or_get_num_circuits, (or_connection_t *conn));
|
||||
void or_handshake_state_free_(or_handshake_state_t *state);
|
||||
#define or_handshake_state_free(state) \
|
||||
FREE_AND_NULL(or_handshake_state_t, or_handshake_state_free_, (state))
|
||||
void or_handshake_state_record_cell(or_connection_t *conn,
|
||||
or_handshake_state_t *state,
|
||||
const cell_t *cell,
|
||||
int incoming);
|
||||
void or_handshake_state_record_var_cell(or_connection_t *conn,
|
||||
or_handshake_state_t *state,
|
||||
const var_cell_t *cell,
|
||||
int incoming);
|
||||
|
||||
int connection_or_set_state_open(or_connection_t *conn);
|
||||
void connection_or_write_cell_to_buf(const cell_t *cell,
|
||||
or_connection_t *conn);
|
||||
MOCK_DECL(void,connection_or_write_var_cell_to_buf,(const var_cell_t *cell,
|
||||
or_connection_t *conn));
|
||||
int connection_or_send_versions(or_connection_t *conn, int v3_plus);
|
||||
MOCK_DECL(int,connection_or_send_netinfo,(or_connection_t *conn));
|
||||
|
||||
int is_or_protocol_version_known(uint16_t version);
|
||||
|
||||
void cell_pack(packed_cell_t *dest, const cell_t *src, int wide_circ_ids);
|
||||
int var_cell_pack_header(const var_cell_t *cell, char *hdr_out,
|
||||
int wide_circ_ids);
|
||||
var_cell_t *var_cell_new(uint16_t payload_len);
|
||||
var_cell_t *var_cell_copy(const var_cell_t *src);
|
||||
void var_cell_free_(var_cell_t *cell);
|
||||
#define var_cell_free(cell) FREE_AND_NULL(var_cell_t, var_cell_free_, (cell))
|
||||
|
||||
/* DOCDOC */
|
||||
#define MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS 4
|
||||
#define MIN_LINK_PROTO_FOR_CHANNEL_PADDING 5
|
||||
#define MAX_LINK_PROTO MIN_LINK_PROTO_FOR_CHANNEL_PADDING
|
||||
|
||||
int connection_or_single_set_badness_(time_t now,
|
||||
or_connection_t *or_conn,
|
||||
int force);
|
||||
void connection_or_group_set_badness_(smartlist_t *group, int force);
|
||||
|
||||
#ifdef CONNECTION_OR_PRIVATE
|
||||
STATIC int should_connect_to_relay(const or_connection_t *or_conn);
|
||||
STATIC void note_or_connect_failed(const or_connection_t *or_conn);
|
||||
#endif /* defined(CONNECTION_OR_PRIVATE) */
|
||||
|
||||
/*
|
||||
* Call this when changing connection state, so notifications to the owning
|
||||
* channel can be handled.
|
||||
*/
|
||||
MOCK_DECL(void, connection_or_change_state,
|
||||
(or_connection_t *conn, uint8_t state));
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
extern int testing__connection_or_pretend_TLSSECRET_is_supported;
|
||||
#endif
|
||||
|
||||
#endif /* !defined(TOR_CONNECTION_OR_H) */
|
||||
@@ -0,0 +1,194 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file connection_st.h
|
||||
* @brief Base connection structure.
|
||||
**/
|
||||
|
||||
#ifndef CONNECTION_ST_H
|
||||
#define CONNECTION_ST_H
|
||||
|
||||
struct buf_t;
|
||||
|
||||
/* Values for connection_t.magic: used to make sure that downcasts (casts from
|
||||
* connection_t to foo_connection_t) are safe. */
|
||||
#define BASE_CONNECTION_MAGIC 0x7C3C304Eu
|
||||
#define OR_CONNECTION_MAGIC 0x7D31FF03u
|
||||
#define EDGE_CONNECTION_MAGIC 0xF0374013u
|
||||
#define ENTRY_CONNECTION_MAGIC 0xbb4a5703
|
||||
#define DIR_CONNECTION_MAGIC 0x9988ffeeu
|
||||
#define CONTROL_CONNECTION_MAGIC 0x8abc765du
|
||||
#define LISTENER_CONNECTION_MAGIC 0x1a1ac741u
|
||||
|
||||
/** Description of a connection to another host or process, and associated
|
||||
* data.
|
||||
*
|
||||
* A connection is named based on what it's connected to -- an "OR
|
||||
* connection" has a Tor node on the other end, an "exit
|
||||
* connection" has a website or other server on the other end, and an
|
||||
* "AP connection" has an application proxy (and thus a user) on the
|
||||
* other end.
|
||||
*
|
||||
* Every connection has a type and a state. Connections never change
|
||||
* their type, but can go through many state changes in their lifetime.
|
||||
*
|
||||
* Every connection has two associated input and output buffers.
|
||||
* Listeners don't use them. For non-listener connections, incoming
|
||||
* data is appended to conn->inbuf, and outgoing data is taken from
|
||||
* conn->outbuf. Connections differ primarily in the functions called
|
||||
* to fill and drain these buffers.
|
||||
*/
|
||||
struct connection_t {
|
||||
uint32_t magic; /**< For memory debugging: must equal one of
|
||||
* *_CONNECTION_MAGIC. */
|
||||
|
||||
uint8_t state; /**< Current state of this connection. */
|
||||
unsigned int type:5; /**< What kind of connection is this? */
|
||||
unsigned int purpose:5; /**< Only used for DIR and EXIT types currently. */
|
||||
|
||||
/* The next fields are all one-bit booleans. Some are only applicable to
|
||||
* connection subtypes, but we hold them here anyway, to save space.
|
||||
*/
|
||||
unsigned int read_blocked_on_bw:1; /**< Boolean: should we start reading
|
||||
* again once the bandwidth throttler allows it? */
|
||||
unsigned int write_blocked_on_bw:1; /**< Boolean: should we start writing
|
||||
* again once the bandwidth throttler allows
|
||||
* writes? */
|
||||
unsigned int hold_open_until_flushed:1; /**< Despite this connection's being
|
||||
* marked for close, do we flush it
|
||||
* before closing it? */
|
||||
unsigned int inbuf_reached_eof:1; /**< Boolean: did read() return 0 on this
|
||||
* conn? */
|
||||
/** Set to 1 when we're inside connection_flushed_some to keep us from
|
||||
* calling connection_handle_write() recursively. */
|
||||
unsigned int in_flushed_some:1;
|
||||
/** True if connection_handle_write is currently running on this connection.
|
||||
*/
|
||||
unsigned int in_connection_handle_write:1;
|
||||
/** If true, then we treat this connection as remote for the purpose of
|
||||
* rate-limiting, no matter what its address is. */
|
||||
unsigned int always_rate_limit_as_remote:1;
|
||||
|
||||
/* For linked connections:
|
||||
*/
|
||||
unsigned int linked:1; /**< True if there is, or has been, a linked_conn. */
|
||||
/** True iff we'd like to be notified about read events from the
|
||||
* linked conn. */
|
||||
unsigned int reading_from_linked_conn:1;
|
||||
/** True iff we're willing to write to the linked conn. */
|
||||
unsigned int writing_to_linked_conn:1;
|
||||
/** True iff we're currently able to read on the linked conn, and our
|
||||
* read_event should be made active with libevent. */
|
||||
unsigned int active_on_link:1;
|
||||
/** True iff we've called connection_close_immediate() on this linked
|
||||
* connection. */
|
||||
unsigned int linked_conn_is_closed:1;
|
||||
/** True iff this connection was opened from a listener and thus we've
|
||||
* received this connection. Else, it means we've initiated an outbound
|
||||
* connection. */
|
||||
unsigned int from_listener:1;
|
||||
|
||||
/** CONNECT/SOCKS proxy client handshake state (for outgoing connections). */
|
||||
unsigned int proxy_state:4;
|
||||
|
||||
/** Our socket; set to TOR_INVALID_SOCKET if this connection is closed,
|
||||
* or has no socket. */
|
||||
tor_socket_t s;
|
||||
int conn_array_index; /**< Index into the global connection array. */
|
||||
|
||||
struct event *read_event; /**< Libevent event structure. */
|
||||
struct event *write_event; /**< Libevent event structure. */
|
||||
struct buf_t *inbuf; /**< Buffer holding data read over this connection. */
|
||||
struct buf_t *outbuf; /**< Buffer holding data to write over this
|
||||
* connection. */
|
||||
time_t timestamp_last_read_allowed; /**< When was the last time libevent said
|
||||
* we could read? */
|
||||
time_t timestamp_last_write_allowed; /**< When was the last time libevent
|
||||
* said we could write? */
|
||||
|
||||
time_t timestamp_created; /**< When was this connection_t created? */
|
||||
|
||||
int socket_family; /**< Address family of this connection's socket. Usually
|
||||
* AF_INET, but it can also be AF_UNIX, or AF_INET6 */
|
||||
/**
|
||||
* IP address on the internet of this connection's peer, usually.
|
||||
*
|
||||
* This address may come from several sources. If this is an outbound
|
||||
* connection, it is the address we are trying to connect to--either
|
||||
* directly through `s`, or via a proxy. (If we used a proxy, then
|
||||
* `getpeername(s)` will not give this address.)
|
||||
*
|
||||
* For incoming connections, this field is the address we got from
|
||||
* getpeername() or accept(), as updated by any proxy that we
|
||||
* are using (for example, an ExtORPort proxy).
|
||||
*
|
||||
* For listeners, this is the address we are trying to bind to.
|
||||
*
|
||||
* If this connection is using a unix socket, then this address is a null
|
||||
* address, and the real address is in the `address` field.
|
||||
*
|
||||
* If this connection represents a request made somewhere other than via
|
||||
* TCP (for example, a UDP dns request, or a controller resolve request),
|
||||
* then this address is the address that originated the request.
|
||||
*
|
||||
* TECHNICAL DEBT:
|
||||
*
|
||||
* There are a few places in the code that modify this address,
|
||||
* or use it in other ways that we don't currently like. Please don't add
|
||||
* any more!
|
||||
*
|
||||
* The misuses of this field include:
|
||||
* * Setting it on linked connections, possibly.
|
||||
* * Updating it based on the Forwarded-For header-- Forwarded-For is
|
||||
* set by a proxy, but not a local trusted proxy.
|
||||
**/
|
||||
tor_addr_t addr;
|
||||
uint16_t port; /**< If non-zero, port that socket "s" is directly connected
|
||||
* to; may be the port for a proxy or pluggable transport,
|
||||
* see "address" for the port at the final destination. */
|
||||
uint16_t marked_for_close; /**< Should we close this conn on the next
|
||||
* iteration of the main loop? (If true, holds
|
||||
* the line number where this connection was
|
||||
* marked.) */
|
||||
const char *marked_for_close_file; /**< For debugging: in which file were
|
||||
* we marked for close? */
|
||||
/**
|
||||
* String address of the peer of this connection.
|
||||
*
|
||||
* TECHNICAL DEBT:
|
||||
*
|
||||
* This field serves many purposes, and they're not all pretty. In addition
|
||||
* to describing the peer we're connected to, it can also hold:
|
||||
*
|
||||
* * An address we're trying to resolve (as an exit).
|
||||
* * A unix address we're trying to bind to (as a listener).
|
||||
**/
|
||||
char *address;
|
||||
/** Another connection that's connected to this one in lieu of a socket. */
|
||||
struct connection_t *linked_conn;
|
||||
|
||||
/** Unique identifier for this connection on this Tor instance. */
|
||||
uint64_t global_identifier;
|
||||
|
||||
/** Bytes read since last call to control_event_conn_bandwidth_used().
|
||||
* Only used if we're configured to emit CONN_BW events. */
|
||||
uint32_t n_read_conn_bw;
|
||||
|
||||
/** Bytes written since last call to control_event_conn_bandwidth_used().
|
||||
* Only used if we're configured to emit CONN_BW events. */
|
||||
uint32_t n_written_conn_bw;
|
||||
};
|
||||
|
||||
/** True iff <b>x</b> is an edge connection. */
|
||||
#define CONN_IS_EDGE(x) \
|
||||
((x)->type == CONN_TYPE_EXIT || (x)->type == CONN_TYPE_AP)
|
||||
|
||||
/** True iff the purpose of <b>conn</b> means that it's a server-side
|
||||
* directory connection. */
|
||||
#define DIR_CONN_IS_SERVER(conn) ((conn)->purpose == DIR_PURPOSE_SERVER)
|
||||
|
||||
#endif /* !defined(CONNECTION_ST_H) */
|
||||
@@ -0,0 +1,41 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file cpath_build_state_st.h
|
||||
* @brief Circuit-build-stse structure
|
||||
**/
|
||||
|
||||
#ifndef CIRCUIT_BUILD_STATE_ST_ST_H
|
||||
#define CIRCUIT_BUILD_STATE_ST_ST_H
|
||||
|
||||
/** Information used to build a circuit. */
|
||||
struct cpath_build_state_t {
|
||||
/** Intended length of the final circuit. */
|
||||
int desired_path_len;
|
||||
/** How to extend to the planned exit node. */
|
||||
extend_info_t *chosen_exit;
|
||||
/** Whether every node in the circ must have adequate uptime. */
|
||||
unsigned int need_uptime : 1;
|
||||
/** Whether every node in the circ must have adequate capacity. */
|
||||
unsigned int need_capacity : 1;
|
||||
/** Whether the last hop was picked with exiting in mind. */
|
||||
unsigned int is_internal : 1;
|
||||
/** Is this an IPv6 ORPort self-testing circuit? */
|
||||
unsigned int is_ipv6_selftest : 1;
|
||||
/** Did we pick this as a one-hop tunnel (not safe for other streams)?
|
||||
* These are for encrypted dir conns that exit to this router, not
|
||||
* for arbitrary exits from the circuit. */
|
||||
unsigned int onehop_tunnel : 1;
|
||||
/** Indicating the exit needs to support Conflux. */
|
||||
unsigned int need_conflux: 1;
|
||||
/** How many times has building a circuit for this task failed? */
|
||||
int failure_count;
|
||||
/** At what time should we give up on this task? */
|
||||
time_t expiry_time;
|
||||
};
|
||||
|
||||
#endif /* !defined(CIRCUIT_BUILD_STATE_ST_ST_H) */
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* \file crypt_path.h
|
||||
* \brief Header file for crypt_path.c.
|
||||
**/
|
||||
|
||||
#ifndef CRYPT_PATH_H
|
||||
#define CRYPT_PATH_H
|
||||
|
||||
void cpath_assert_layer_ok(const crypt_path_t *cp);
|
||||
|
||||
void cpath_assert_ok(const crypt_path_t *cp);
|
||||
|
||||
int cpath_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
|
||||
|
||||
int cpath_init_circuit_crypto(crypt_path_t *cpath,
|
||||
const char *key_data, size_t key_data_len,
|
||||
int reverse, int is_hs_v3);
|
||||
|
||||
void
|
||||
cpath_free(crypt_path_t *victim);
|
||||
|
||||
void cpath_extend_linked_list(crypt_path_t **head_ptr, crypt_path_t *new_hop);
|
||||
|
||||
void
|
||||
cpath_crypt_cell(const crypt_path_t *cpath, uint8_t *payload, bool is_decrypt);
|
||||
|
||||
struct crypto_digest_t *
|
||||
cpath_get_incoming_digest(const crypt_path_t *cpath);
|
||||
|
||||
void cpath_sendme_record_cell_digest(crypt_path_t *cpath,
|
||||
bool is_foward_digest);
|
||||
|
||||
void
|
||||
cpath_set_cell_forward_digest(crypt_path_t *cpath, cell_t *cell);
|
||||
|
||||
crypt_path_t *cpath_get_next_non_open_hop(crypt_path_t *cpath);
|
||||
|
||||
void cpath_sendme_circuit_record_inbound_cell(crypt_path_t *cpath);
|
||||
|
||||
uint8_t *cpath_get_sendme_digest(crypt_path_t *cpath);
|
||||
|
||||
#if defined(TOR_UNIT_TESTS)
|
||||
unsigned int cpath_get_n_hops(crypt_path_t **head_ptr);
|
||||
#endif /* defined(TOR_UNIT_TESTS) */
|
||||
|
||||
#endif /* !defined(CRYPT_PATH_H) */
|
||||
@@ -0,0 +1,27 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file crypt_path_reference_st.h
|
||||
* @brief reference-counting structure for crypt_path_t
|
||||
**/
|
||||
|
||||
#ifndef CRYPT_PATH_REFERENCE_ST_H
|
||||
#define CRYPT_PATH_REFERENCE_ST_H
|
||||
|
||||
/** A reference-counted pointer to a crypt_path_t, used only to share
|
||||
* the final rendezvous cpath to be used on a service-side rendezvous
|
||||
* circuit among multiple circuits built in parallel to the same
|
||||
* destination rendezvous point. */
|
||||
struct crypt_path_reference_t {
|
||||
/** The reference count. */
|
||||
unsigned int refcount;
|
||||
/** The pointer. Set to NULL when the crypt_path_t is put into use
|
||||
* on an opened rendezvous circuit. */
|
||||
crypt_path_t *cpath;
|
||||
};
|
||||
|
||||
#endif /* !defined(CRYPT_PATH_REFERENCE_ST_H) */
|
||||
@@ -0,0 +1,98 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file crypt_path_st.h
|
||||
* @brief Path structures for origin circuits.
|
||||
**/
|
||||
|
||||
#ifndef CRYPT_PATH_ST_H
|
||||
#define CRYPT_PATH_ST_H
|
||||
|
||||
#include "core/or/relay_crypto_st.h"
|
||||
struct crypto_dh_t;
|
||||
|
||||
#define CRYPT_PATH_MAGIC 0x70127012u
|
||||
|
||||
struct fast_handshake_state_t;
|
||||
struct ntor_handshake_state_t;
|
||||
struct crypto_dh_t;
|
||||
struct onion_handshake_state_t {
|
||||
/** One of `ONION_HANDSHAKE_TYPE_*`. Determines which member of the union
|
||||
* is accessible. */
|
||||
uint16_t tag;
|
||||
union {
|
||||
struct fast_handshake_state_t *fast;
|
||||
struct crypto_dh_t *tap;
|
||||
struct ntor_handshake_state_t *ntor;
|
||||
struct ntor3_handshake_state_t *ntor3;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct congestion_control_t;
|
||||
|
||||
/** Macro to encapsulate private members of a struct.
|
||||
*
|
||||
* Renames 'x' to 'x_crypt_path_private_field'.
|
||||
*/
|
||||
#define CRYPT_PATH_PRIV_FIELD(x) x ## _crypt_path_private_field
|
||||
|
||||
#ifdef CRYPT_PATH_PRIVATE
|
||||
|
||||
/* Helper macro to access private members of a struct. */
|
||||
#define pvt_crypto CRYPT_PATH_PRIV_FIELD(crypto)
|
||||
|
||||
#endif /* defined(CRYPT_PATH_PRIVATE) */
|
||||
|
||||
/** Holds accounting information for a single step in the layered encryption
|
||||
* performed by a circuit. Used only at the client edge of a circuit. */
|
||||
struct crypt_path_t {
|
||||
uint32_t magic;
|
||||
|
||||
/** Current state of the handshake as performed with the OR at this
|
||||
* step. */
|
||||
onion_handshake_state_t handshake_state;
|
||||
/** Diffie-hellman handshake state for performing an introduction
|
||||
* operations */
|
||||
struct crypto_dh_t *rend_dh_handshake_state;
|
||||
|
||||
/** Negotiated key material shared with the OR at this step. */
|
||||
char rend_circ_nonce[DIGEST_LEN];/* KH in tor-spec.txt */
|
||||
|
||||
/** Information to extend to the OR at this step. */
|
||||
extend_info_t *extend_info;
|
||||
|
||||
/** Is the circuit built to this step? Must be one of:
|
||||
* - CPATH_STATE_CLOSED (The circuit has not been extended to this step)
|
||||
* - CPATH_STATE_AWAITING_KEYS (We have sent an EXTEND/CREATE to this step
|
||||
* and not received an EXTENDED/CREATED)
|
||||
* - CPATH_STATE_OPEN (The circuit has been extended to this step) */
|
||||
uint8_t state;
|
||||
#define CPATH_STATE_CLOSED 0
|
||||
#define CPATH_STATE_AWAITING_KEYS 1
|
||||
#define CPATH_STATE_OPEN 2
|
||||
struct crypt_path_t *next; /**< Link to next crypt_path_t in the circuit.
|
||||
* (The list is circular, so the last node
|
||||
* links to the first.) */
|
||||
struct crypt_path_t *prev; /**< Link to previous crypt_path_t in the
|
||||
* circuit. */
|
||||
|
||||
int package_window; /**< How many cells are we allowed to originate ending
|
||||
* at this step? */
|
||||
int deliver_window; /**< How many cells are we willing to deliver originating
|
||||
* at this step? */
|
||||
|
||||
/** Congestion control info */
|
||||
struct congestion_control_t *ccontrol;
|
||||
|
||||
/*********************** Private members ****************************/
|
||||
|
||||
/** Private member: Cryptographic state used for encrypting and
|
||||
* authenticating relay cells to and from this hop. */
|
||||
relay_crypto_t CRYPT_PATH_PRIV_FIELD(crypto);
|
||||
};
|
||||
|
||||
#endif /* !defined(CRYPT_PATH_ST_H) */
|
||||
@@ -0,0 +1,33 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file destroy_cell_queue_st.h
|
||||
* @brief Destroy-cell queue structures
|
||||
**/
|
||||
|
||||
#ifndef DESTROY_CELL_QUEUE_ST_H
|
||||
#define DESTROY_CELL_QUEUE_ST_H
|
||||
|
||||
#include "core/or/cell_queue_st.h"
|
||||
|
||||
/** A single queued destroy cell. */
|
||||
struct destroy_cell_t {
|
||||
TOR_SIMPLEQ_ENTRY(destroy_cell_t) next;
|
||||
circid_t circid;
|
||||
uint32_t inserted_timestamp; /**< Time (in timestamp units) when this cell
|
||||
* was inserted */
|
||||
uint8_t reason;
|
||||
};
|
||||
|
||||
/** A queue of destroy cells on a channel. */
|
||||
struct destroy_cell_queue_t {
|
||||
/** Linked list of packed_cell_t */
|
||||
TOR_SIMPLEQ_HEAD(dcell_simpleq_t, destroy_cell_t) head;
|
||||
int n; /**< The number of cells in the queue. */
|
||||
};
|
||||
|
||||
#endif /* !defined(DESTROY_CELL_QUEUE_ST_H) */
|
||||
@@ -0,0 +1,183 @@
|
||||
/* Copyright (c) 2018-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/*
|
||||
* \file dos.h
|
||||
* \brief Header file for dos.c
|
||||
*/
|
||||
|
||||
#ifndef TOR_DOS_H
|
||||
#define TOR_DOS_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
|
||||
#include "lib/evloop/token_bucket.h"
|
||||
|
||||
/* Structure that keeps stats of circuit creation per client connection IP. */
|
||||
typedef struct cc_client_stats_t {
|
||||
/* Number of allocated circuits remaining for this address. It is
|
||||
* decremented every time a new circuit is seen for this client address and
|
||||
* if the count goes to 0, we have a positive detection. */
|
||||
uint32_t circuit_bucket;
|
||||
|
||||
/* When was the last time we've refilled the circuit bucket? This is used to
|
||||
* know if we need to refill the bucket when a new circuit is seen. It is
|
||||
* synchronized using approx_time(). */
|
||||
time_t last_circ_bucket_refill_ts;
|
||||
|
||||
/* This client address was detected to be above the circuit creation rate
|
||||
* and this timestamp indicates until when it should remain marked as
|
||||
* detected so we can apply a defense for the address. It is synchronized
|
||||
* using the approx_time(). */
|
||||
time_t marked_until_ts;
|
||||
} cc_client_stats_t;
|
||||
|
||||
/* Structure that keeps stats of client connection per-IP. */
|
||||
typedef struct conn_client_stats_t {
|
||||
/* Concurrent connection count from the specific address. 2^32 - 1 is most
|
||||
* likely way too big for the amount of allowed file descriptors. */
|
||||
uint32_t concurrent_count;
|
||||
|
||||
/* Connect count from the specific address. We use a token bucket here to
|
||||
* track the rate and burst of connections from the same IP address.*/
|
||||
token_bucket_ctr_t connect_count;
|
||||
|
||||
/* The client address attempted too many connections, per the connect_count
|
||||
* rules, and thus is marked so defense(s) can be applied. It is
|
||||
* synchronized using the approx_time(). */
|
||||
time_t marked_until_ts;
|
||||
} conn_client_stats_t;
|
||||
|
||||
/* This object is a top level object that contains everything related to the
|
||||
* per-IP client DoS mitigation. Because it is per-IP, it is used in the geoip
|
||||
* clientmap_entry_t object. */
|
||||
typedef struct dos_client_stats_t {
|
||||
/* Client connection statistics. */
|
||||
conn_client_stats_t conn_stats;
|
||||
|
||||
/* Circuit creation statistics. This is only used if the circuit creation
|
||||
* subsystem has been enabled (dos_cc_enabled). */
|
||||
cc_client_stats_t cc_stats;
|
||||
|
||||
/** Number of times the circ_max_cell_queue_size limit has been reached. */
|
||||
uint32_t num_circ_max_cell_queue_size;
|
||||
} dos_client_stats_t;
|
||||
|
||||
/* General API. */
|
||||
|
||||
/* Stub. */
|
||||
struct clientmap_entry_t;
|
||||
|
||||
void dos_init(void);
|
||||
void dos_free_all(void);
|
||||
void dos_consensus_has_changed(const networkstatus_t *ns);
|
||||
int dos_enabled(void);
|
||||
void dos_log_heartbeat(void);
|
||||
void dos_geoip_entry_init(struct clientmap_entry_t *geoip_ent);
|
||||
void dos_geoip_entry_about_to_free(const struct clientmap_entry_t *geoip_ent);
|
||||
|
||||
void dos_new_client_conn(or_connection_t *or_conn,
|
||||
const char *transport_name);
|
||||
void dos_close_client_conn(const or_connection_t *or_conn);
|
||||
|
||||
int dos_should_refuse_single_hop_client(void);
|
||||
void dos_note_refuse_single_hop_client(void);
|
||||
void dos_note_circ_max_outq(const channel_t *chan);
|
||||
|
||||
uint32_t dos_get_num_cc_marked_addr(void);
|
||||
uint32_t dos_get_num_cc_marked_addr_maxq(void);
|
||||
uint64_t dos_get_num_cc_rejected(void);
|
||||
uint64_t dos_get_num_conn_addr_rejected(void);
|
||||
uint64_t dos_get_num_conn_addr_connect_rejected(void);
|
||||
uint64_t dos_get_num_single_hop_refused(void);
|
||||
|
||||
/*
|
||||
* Circuit creation DoS mitigation subsystemn interface.
|
||||
*/
|
||||
|
||||
/* DoSCircuitCreationEnabled default. Disabled by default. */
|
||||
#define DOS_CC_ENABLED_DEFAULT 0
|
||||
/* DoSCircuitCreationDefenseType maps to the dos_cc_defense_type_t enum. */
|
||||
#define DOS_CC_DEFENSE_TYPE_DEFAULT DOS_CC_DEFENSE_REFUSE_CELL
|
||||
/* DoSCircuitCreationMinConnections default */
|
||||
#define DOS_CC_MIN_CONCURRENT_CONN_DEFAULT 3
|
||||
/* DoSCircuitCreationRateTenths is 3 per seconds. */
|
||||
#define DOS_CC_CIRCUIT_RATE_DEFAULT 3
|
||||
/* DoSCircuitCreationBurst default. */
|
||||
#define DOS_CC_CIRCUIT_BURST_DEFAULT 90
|
||||
/* DoSCircuitCreationDefenseTimePeriod in seconds. */
|
||||
#define DOS_CC_DEFENSE_TIME_PERIOD_DEFAULT (60 * 60)
|
||||
|
||||
/* Type of defense that we can use for the circuit creation DoS mitigation. */
|
||||
typedef enum dos_cc_defense_type_t {
|
||||
/* No defense used. */
|
||||
DOS_CC_DEFENSE_NONE = 1,
|
||||
/* Refuse any cells which means a DESTROY cell will be sent back. */
|
||||
DOS_CC_DEFENSE_REFUSE_CELL = 2,
|
||||
|
||||
/* Maximum value that can be used. Useful for the boundaries of the
|
||||
* consensus parameter. */
|
||||
DOS_CC_DEFENSE_MAX = 2,
|
||||
} dos_cc_defense_type_t;
|
||||
|
||||
void dos_cc_new_create_cell(channel_t *channel);
|
||||
dos_cc_defense_type_t dos_cc_get_defense_type(channel_t *chan);
|
||||
|
||||
/*
|
||||
* Concurrent connection DoS mitigation interface.
|
||||
*/
|
||||
|
||||
/* DoSConnectionEnabled default. Disabled by default. */
|
||||
#define DOS_CONN_ENABLED_DEFAULT 0
|
||||
/* DoSConnectionMaxConcurrentCount default. */
|
||||
#define DOS_CONN_MAX_CONCURRENT_COUNT_DEFAULT 100
|
||||
/* DoSConnectionDefenseType maps to the dos_conn_defense_type_t enum. */
|
||||
#define DOS_CONN_DEFENSE_TYPE_DEFAULT DOS_CONN_DEFENSE_CLOSE
|
||||
/* DoSConnectionConnectRate default. Per second. */
|
||||
#define DOS_CONN_CONNECT_RATE_DEFAULT 20
|
||||
/* DoSConnectionConnectBurst default. Per second. */
|
||||
#define DOS_CONN_CONNECT_BURST_DEFAULT 40
|
||||
/* DoSConnectionConnectDefenseTimePeriod default. Set to 24 hours. */
|
||||
#define DOS_CONN_CONNECT_DEFENSE_TIME_PERIOD_DEFAULT (24 * 60 * 60)
|
||||
/* DoSCircuitCreationDefenseTimePeriod minimum value. Because we add a random
|
||||
* offset to the marked timestamp, we need the minimum value to be non zero.
|
||||
* We consider that 10 seconds is an acceptable lower bound. */
|
||||
#define DOS_CONN_CONNECT_DEFENSE_TIME_PERIOD_MIN (10)
|
||||
|
||||
/* Type of defense that we can use for the concurrent connection DoS
|
||||
* mitigation. */
|
||||
typedef enum dos_conn_defense_type_t {
|
||||
/* No defense used. */
|
||||
DOS_CONN_DEFENSE_NONE = 1,
|
||||
/* Close immediately the connection meaning refuse it. */
|
||||
DOS_CONN_DEFENSE_CLOSE = 2,
|
||||
|
||||
/* Maximum value that can be used. Useful for the boundaries of the
|
||||
* consensus parameter. */
|
||||
DOS_CONN_DEFENSE_MAX = 2,
|
||||
} dos_conn_defense_type_t;
|
||||
|
||||
dos_conn_defense_type_t dos_conn_addr_get_defense_type(const tor_addr_t *addr);
|
||||
|
||||
#ifdef DOS_PRIVATE
|
||||
|
||||
STATIC uint32_t get_param_conn_max_concurrent_count(
|
||||
const networkstatus_t *ns);
|
||||
STATIC uint32_t get_param_cc_circuit_burst(const networkstatus_t *ns);
|
||||
STATIC uint32_t get_param_cc_min_concurrent_connection(
|
||||
const networkstatus_t *ns);
|
||||
STATIC uint32_t get_param_conn_connect_burst(const networkstatus_t *ns);
|
||||
|
||||
STATIC uint64_t get_circuit_rate_per_second(void);
|
||||
STATIC void cc_stats_refill_bucket(cc_client_stats_t *stats,
|
||||
const tor_addr_t *addr);
|
||||
|
||||
MOCK_DECL(STATIC unsigned int, get_param_cc_enabled,
|
||||
(const networkstatus_t *ns));
|
||||
MOCK_DECL(STATIC unsigned int, get_param_conn_enabled,
|
||||
(const networkstatus_t *ns));
|
||||
|
||||
#endif /* defined(DOS_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_DOS_H) */
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/* Copyright (c) 2021-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file dos_config.h
|
||||
* @brief Header for core/or/dos_config.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_CORE_OR_DOS_CONFIG_H
|
||||
#define TOR_CORE_OR_DOS_CONFIG_H
|
||||
|
||||
#include "lib/conf/conftypes.h"
|
||||
|
||||
extern const struct config_format_t dos_options_fmt;
|
||||
|
||||
#endif /* !defined(TOR_CORE_OR_DOS_CONFIG_H) */
|
||||
@@ -0,0 +1,20 @@
|
||||
/* Copyright (c) 2021-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file dos_options_st.h
|
||||
* @brief Structure dos_options_t to hold options for the DoS subsystem.
|
||||
**/
|
||||
|
||||
#ifndef TOR_CORE_OR_DOS_OPTIONS_ST_H
|
||||
#define TOR_CORE_OR_DOS_OPTIONS_ST_H
|
||||
|
||||
#include "lib/conf/confdecl.h"
|
||||
|
||||
#define CONF_CONTEXT STRUCT
|
||||
#include "core/or/dos_options.inc"
|
||||
#undef CONF_CONTEXT
|
||||
|
||||
typedef struct dos_options_t dos_options_t;
|
||||
|
||||
#endif /* !defined(TOR_CORE_OR_DOS_OPTIONS_ST_H) */
|
||||
@@ -0,0 +1,25 @@
|
||||
/* Copyright (c) 2021-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file dos_sys.h
|
||||
* @brief Header for core/or/dos_sys.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_CORE_OR_DOS_SYS_H
|
||||
#define TOR_CORE_OR_DOS_SYS_H
|
||||
|
||||
struct dos_options_t;
|
||||
const struct dos_options_t *dos_get_options(void);
|
||||
|
||||
extern const struct subsys_fns_t sys_dos;
|
||||
|
||||
/**
|
||||
* Subsystem level for the metrics system.
|
||||
*
|
||||
* Defined here so that it can be shared between the real and stub
|
||||
* definitions.
|
||||
**/
|
||||
#define DOS_SUBSYS_LEVEL (21)
|
||||
|
||||
#endif /* !defined(TOR_CORE_OR_DOS_SYS_H) */
|
||||
@@ -0,0 +1,134 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file edge_connection_st.h
|
||||
* @brief Edge-connection structure.
|
||||
**/
|
||||
|
||||
#ifndef EDGE_CONNECTION_ST_H
|
||||
#define EDGE_CONNECTION_ST_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
|
||||
#include "core/or/connection_st.h"
|
||||
#include "lib/evloop/token_bucket.h"
|
||||
|
||||
/** Subtype of connection_t for an "edge connection" -- that is, an entry (ap)
|
||||
* connection, or an exit. */
|
||||
struct edge_connection_t {
|
||||
connection_t base_;
|
||||
|
||||
struct edge_connection_t *next_stream; /**< Points to the next stream at this
|
||||
* edge, if any */
|
||||
int package_window; /**< How many more relay cells can I send into the
|
||||
* circuit? */
|
||||
int deliver_window; /**< How many more relay cells can end at me? */
|
||||
|
||||
/** The circuit (if any) that this edge connection is using.
|
||||
* Note that edges that use conflux should use the helpers
|
||||
* in conflux_util.c instead of accessing this directly. */
|
||||
struct circuit_t *on_circuit;
|
||||
|
||||
/** A pointer to which node in the circ this conn exits at. Set for AP
|
||||
* connections and for hidden service exit connections.
|
||||
* Note that edges that use conflux should use the helpers
|
||||
* in conflux_util.c instead of accessing this directly. */
|
||||
struct crypt_path_t *cpath_layer;
|
||||
|
||||
/* Hidden service connection identifier for edge connections. Used by the HS
|
||||
* client-side code to identify client SOCKS connections and by the
|
||||
* service-side code to match HS circuits with their streams. */
|
||||
struct hs_ident_edge_conn_t *hs_ident;
|
||||
|
||||
uint32_t address_ttl; /**< TTL for address-to-addr mapping on exit
|
||||
* connection. Exit connections only. */
|
||||
uint32_t begincell_flags; /** Flags sent or received in the BEGIN cell
|
||||
* for this connection */
|
||||
|
||||
streamid_t stream_id; /**< The stream ID used for this edge connection on its
|
||||
* circuit */
|
||||
|
||||
/** The reason why this connection is closing; passed to the controller. */
|
||||
uint16_t end_reason;
|
||||
|
||||
/** Bytes read since last call to control_event_stream_bandwidth_used() */
|
||||
uint32_t n_read;
|
||||
|
||||
/** Bytes written since last call to control_event_stream_bandwidth_used() */
|
||||
uint32_t n_written;
|
||||
|
||||
/** True iff this connection is for a DNS request only. */
|
||||
unsigned int is_dns_request:1;
|
||||
/** True iff this connection is for a PTR DNS request. (exit only) */
|
||||
unsigned int is_reverse_dns_lookup:1;
|
||||
|
||||
unsigned int edge_has_sent_end:1; /**< For debugging; only used on edge
|
||||
* connections. Set once we've set the stream end,
|
||||
* and check in connection_about_to_close_connection().
|
||||
*/
|
||||
|
||||
/** Unique ID for directory requests; this used to be in connection_t, but
|
||||
* that's going away and being used on channels instead. We still tag
|
||||
* edge connections with dirreq_id from circuits, so it's copied here. */
|
||||
uint64_t dirreq_id;
|
||||
|
||||
/* The following are flow control fields */
|
||||
|
||||
/** Used for rate limiting the read side of this edge connection when
|
||||
* congestion control is enabled on its circuit. The XON cell ewma_drain_rate
|
||||
* parameter is used to set the bucket limits. */
|
||||
token_bucket_rw_t bucket;
|
||||
|
||||
/**
|
||||
* Monotime timestamp of the last time we sent a flow control message
|
||||
* for this edge, used to compute advisory rates */
|
||||
uint64_t drain_start_usec;
|
||||
|
||||
/**
|
||||
* Number of bytes written since we either emptied our buffers,
|
||||
* or sent an advisory drate rate. Can wrap, buf if so,
|
||||
* we must reset the usec timestamp above. (Or make this u64, idk).
|
||||
*/
|
||||
uint32_t drained_bytes;
|
||||
uint32_t prev_drained_bytes;
|
||||
|
||||
/**
|
||||
* N_EWMA of the drain rate of writes on this edge conn
|
||||
* while buffers were present.
|
||||
*/
|
||||
uint32_t ewma_drain_rate;
|
||||
|
||||
/**
|
||||
* The ewma drain rate the last time we sent an xon.
|
||||
*/
|
||||
uint32_t ewma_rate_last_sent;
|
||||
|
||||
/**
|
||||
* The following fields are used to count the total bytes sent on this
|
||||
* stream, and compare them to the number of XON and XOFFs received, so
|
||||
* that clients can check rate limits of XOFF/XON to prevent dropmark
|
||||
* attacks. */
|
||||
uint32_t total_bytes_xmit;
|
||||
|
||||
/** Number of XOFFs received */
|
||||
uint8_t num_xoff_recv;
|
||||
|
||||
/** Number of XONs received */
|
||||
uint8_t num_xon_recv;
|
||||
|
||||
/**
|
||||
* Flag that tells us if an XOFF has been sent; cleared when we send an XON.
|
||||
* Used to avoid sending multiple */
|
||||
uint8_t xoff_sent : 1;
|
||||
|
||||
/** Flag that tells us if an XOFF has been received; cleared when we get
|
||||
* an XON. Used to ensure that this edge keeps reads on its edge socket
|
||||
* disabled. */
|
||||
uint8_t xoff_received : 1;
|
||||
};
|
||||
|
||||
#endif /* !defined(EDGE_CONNECTION_ST_H) */
|
||||
@@ -0,0 +1,108 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file entry_connection_st.h
|
||||
* @brief Entry connection structure.
|
||||
**/
|
||||
|
||||
#ifndef ENTRY_CONNECTION_ST_H
|
||||
#define ENTRY_CONNECTION_ST_H
|
||||
|
||||
#include "core/or/edge_connection_st.h"
|
||||
|
||||
/** Subtype of edge_connection_t for an "entry connection" -- that is, a SOCKS
|
||||
* connection, a DNS request, a TransPort connection or a NATD connection */
|
||||
struct entry_connection_t {
|
||||
struct edge_connection_t edge_;
|
||||
|
||||
/** Nickname of planned exit node -- used with .exit support. */
|
||||
/* XXX prop220: we need to make chosen_exit_name able to encode Ed IDs too.
|
||||
* That's logically part of the UI parts for prop220 though. */
|
||||
char *chosen_exit_name;
|
||||
|
||||
socks_request_t *socks_request; /**< SOCKS structure describing request (AP
|
||||
* only.) */
|
||||
|
||||
/* === Isolation related, AP only. === */
|
||||
entry_port_cfg_t entry_cfg;
|
||||
/** AP only: The newnym epoch in which we created this connection. */
|
||||
unsigned nym_epoch;
|
||||
|
||||
/** AP only: The original requested address before we rewrote it. */
|
||||
char *original_dest_address;
|
||||
/* Other fields to isolate on already exist. The ClientAddr is addr. The
|
||||
ClientProtocol is a combination of type and socks_request->
|
||||
socks_version. SocksAuth is socks_request->username/password.
|
||||
DestAddr is in socks_request->address. */
|
||||
|
||||
/** Number of times we've reassigned this application connection to
|
||||
* a new circuit. We keep track because the timeout is longer if we've
|
||||
* already retried several times. */
|
||||
uint8_t num_socks_retries;
|
||||
|
||||
/** For AP connections only: buffer for data that we have sent
|
||||
* optimistically, which we might need to re-send if we have to
|
||||
* retry this connection. */
|
||||
struct buf_t *pending_optimistic_data;
|
||||
/* For AP connections only: buffer for data that we previously sent
|
||||
* optimistically which we are currently re-sending as we retry this
|
||||
* connection. */
|
||||
struct buf_t *sending_optimistic_data;
|
||||
|
||||
/** If this is a DNSPort connection, this field holds the pending DNS
|
||||
* request that we're going to try to answer. */
|
||||
struct evdns_server_request *dns_server_request;
|
||||
|
||||
#define DEBUGGING_17659
|
||||
|
||||
#ifdef DEBUGGING_17659
|
||||
uint16_t marked_pending_circ_line;
|
||||
const char *marked_pending_circ_file;
|
||||
#endif
|
||||
|
||||
#define NUM_CIRCUITS_LAUNCHED_THRESHOLD 10
|
||||
/** Number of times we've launched a circuit to handle this stream. If
|
||||
* it gets too high, that could indicate an inconsistency between our
|
||||
* "launch a circuit to handle this stream" logic and our "attach our
|
||||
* stream to one of the available circuits" logic. */
|
||||
unsigned int num_circuits_launched:4;
|
||||
|
||||
/** True iff this stream must attach to a one-hop circuit (e.g. for
|
||||
* begin_dir). */
|
||||
unsigned int want_onehop:1;
|
||||
/** True iff this stream should use a BEGIN_DIR relay command to establish
|
||||
* itself rather than BEGIN (either via onehop or via a whole circuit). */
|
||||
unsigned int use_begindir:1;
|
||||
|
||||
/** For AP connections only. If 1, and we fail to reach the chosen exit,
|
||||
* stop requiring it. */
|
||||
unsigned int chosen_exit_optional:1;
|
||||
/** For AP connections only. If non-zero, this exit node was picked as
|
||||
* a result of the TrackHostExit, and the value decrements every time
|
||||
* we fail to complete a circuit to our chosen exit -- if it reaches
|
||||
* zero, abandon the associated mapaddress. */
|
||||
unsigned int chosen_exit_retries:3;
|
||||
|
||||
/** True iff this is an AP connection that came from a transparent or
|
||||
* NATd connection */
|
||||
unsigned int is_transparent_ap:1;
|
||||
|
||||
/** For AP connections only: Set if this connection's target exit node
|
||||
* allows optimistic data (that is, data sent on this stream before
|
||||
* the exit has sent a CONNECTED cell) and we have chosen to use it.
|
||||
*/
|
||||
unsigned int may_use_optimistic_data : 1;
|
||||
|
||||
/** True iff this is a connection to a HS that has PoW defenses enabled,
|
||||
* so we know not to apply the usual SOCKS timeout. */
|
||||
unsigned int hs_with_pow_conn : 1;
|
||||
};
|
||||
|
||||
/** Cast a entry_connection_t subtype pointer to a edge_connection_t **/
|
||||
#define ENTRY_TO_EDGE_CONN(c) (&(((c))->edge_))
|
||||
|
||||
#endif /* !defined(ENTRY_CONNECTION_ST_H) */
|
||||
@@ -0,0 +1,61 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file entry_port_cfg_st.h
|
||||
* @brief Configuration structure for client ports.
|
||||
**/
|
||||
|
||||
#ifndef ENTRY_PORT_CFG_ST_H
|
||||
#define ENTRY_PORT_CFG_ST_H
|
||||
|
||||
#include "lib/cc/torint.h"
|
||||
#include "core/or/or.h"
|
||||
|
||||
struct entry_port_cfg_t {
|
||||
/* Client port types (socks, dns, trans, natd) only: */
|
||||
uint8_t isolation_flags; /**< Zero or more isolation flags */
|
||||
int session_group; /**< A session group, or -1 if this port is not in a
|
||||
* session group. */
|
||||
|
||||
/* Socks only: */
|
||||
/** When both no-auth and user/pass are advertised by a SOCKS client, select
|
||||
* no-auth. */
|
||||
unsigned int socks_prefer_no_auth : 1;
|
||||
/** When ISO_SOCKSAUTH is in use, Keep-Alive circuits indefinitely. */
|
||||
unsigned int socks_iso_keep_alive : 1;
|
||||
|
||||
/* Client port types only: */
|
||||
unsigned int ipv4_traffic : 1;
|
||||
unsigned int ipv6_traffic : 1;
|
||||
unsigned int prefer_ipv6 : 1;
|
||||
unsigned int dns_request : 1;
|
||||
unsigned int onion_traffic : 1;
|
||||
|
||||
/** For a socks listener: should we cache IPv4/IPv6 DNS information that
|
||||
* exit nodes tell us?
|
||||
*
|
||||
* @{ */
|
||||
unsigned int cache_ipv4_answers : 1;
|
||||
unsigned int cache_ipv6_answers : 1;
|
||||
/** @} */
|
||||
/** For a socks listeners: if we find an answer in our client-side DNS cache,
|
||||
* should we use it?
|
||||
*
|
||||
* @{ */
|
||||
unsigned int use_cached_ipv4_answers : 1;
|
||||
unsigned int use_cached_ipv6_answers : 1;
|
||||
/** @} */
|
||||
/** For socks listeners: When we can automap an address to IPv4 or IPv6,
|
||||
* do we prefer IPv6? */
|
||||
unsigned int prefer_ipv6_virtaddr : 1;
|
||||
|
||||
/** For socks listeners: can we send back the extended SOCKS5 error code? */
|
||||
unsigned int extended_socks5_codes : 1;
|
||||
|
||||
};
|
||||
|
||||
#endif /* !defined(ENTRY_PORT_CFG_ST_H) */
|
||||
@@ -0,0 +1,47 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file extend_info_st.h
|
||||
* @brief Extend-info structure.
|
||||
**/
|
||||
|
||||
#ifndef EXTEND_INFO_ST_H
|
||||
#define EXTEND_INFO_ST_H
|
||||
|
||||
#include "lib/crypt_ops/crypto_curve25519.h"
|
||||
#include "lib/crypt_ops/crypto_ed25519.h"
|
||||
|
||||
/** Largest number of addresses we handle in an extend_info.
|
||||
*
|
||||
* More are permitted in an EXTEND cell, but we won't handle them. */
|
||||
#define EXTEND_INFO_MAX_ADDRS 2
|
||||
|
||||
/** Information on router used when extending a circuit. We don't need a
|
||||
* full routerinfo_t to extend: we only need addr:port:keyid to build an OR
|
||||
* connection, and onion_key to create the onionskin. Note that for one-hop
|
||||
* general-purpose tunnels, the onion_key is NULL. */
|
||||
struct extend_info_t {
|
||||
char nickname[MAX_HEX_NICKNAME_LEN+1]; /**< This router's nickname for
|
||||
* display. */
|
||||
/** Hash of this router's RSA identity key. */
|
||||
char identity_digest[DIGEST_LEN];
|
||||
/** Ed25519 identity for this router, if any. */
|
||||
ed25519_public_key_t ed_identity;
|
||||
/** IP/Port values for this hop's ORPort(s). Any unused values are set
|
||||
* to a null address. */
|
||||
tor_addr_port_t orports[EXTEND_INFO_MAX_ADDRS];
|
||||
/** TAP onion key for this hop. */
|
||||
crypto_pk_t *onion_key;
|
||||
/** Ntor onion key for this hop. */
|
||||
curve25519_public_key_t curve25519_onion_key;
|
||||
/** True if this hop is to be used as an _exit_,
|
||||
* and it also supports supports NtorV3 _and_ negotiation
|
||||
* of congestion control parameters */
|
||||
bool exit_supports_congestion_control;
|
||||
};
|
||||
|
||||
#endif /* !defined(EXTEND_INFO_ST_H) */
|
||||
@@ -0,0 +1,44 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file extendinfo.h
|
||||
* @brief Header for core/or/extendinfo.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_CORE_OR_EXTENDINFO_H
|
||||
#define TOR_CORE_OR_EXTENDINFO_H
|
||||
|
||||
extend_info_t *extend_info_new(const char *nickname,
|
||||
const char *rsa_id_digest,
|
||||
const struct ed25519_public_key_t *ed_id,
|
||||
crypto_pk_t *onion_key,
|
||||
const struct curve25519_public_key_t *ntor_key,
|
||||
const tor_addr_t *addr, uint16_t port,
|
||||
const struct protover_summary_flags_t *pv,
|
||||
bool for_exit_use);
|
||||
extend_info_t *extend_info_from_node(const node_t *r, int for_direct_connect,
|
||||
bool for_exit);
|
||||
extend_info_t *extend_info_dup(extend_info_t *info);
|
||||
void extend_info_free_(extend_info_t *info);
|
||||
#define extend_info_free(info) \
|
||||
FREE_AND_NULL(extend_info_t, extend_info_free_, (info))
|
||||
int extend_info_addr_is_allowed(const tor_addr_t *addr);
|
||||
int extend_info_supports_tap(const extend_info_t* ei);
|
||||
int extend_info_supports_ntor(const extend_info_t* ei);
|
||||
int extend_info_supports_ntor_v3(const extend_info_t *ei);
|
||||
int extend_info_has_preferred_onion_key(const extend_info_t* ei);
|
||||
bool extend_info_has_orport(const extend_info_t *ei,
|
||||
const tor_addr_t *addr, uint16_t port);
|
||||
int extend_info_add_orport(extend_info_t *ei,
|
||||
const tor_addr_t *addr,
|
||||
uint16_t port);
|
||||
const tor_addr_port_t *extend_info_get_orport(const extend_info_t *ei,
|
||||
int family);
|
||||
const tor_addr_port_t *extend_info_pick_orport(const extend_info_t *ei);
|
||||
bool extend_info_any_orport_addr_is_internal(const extend_info_t *ei);
|
||||
|
||||
#endif /* !defined(TOR_CORE_OR_EXTENDINFO_H) */
|
||||
@@ -0,0 +1,50 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file half_edge_st.h
|
||||
* @brief Half-open connection structure.
|
||||
**/
|
||||
|
||||
#ifndef HALF_EDGE_ST_H
|
||||
#define HALF_EDGE_ST_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
|
||||
/**
|
||||
* Struct to track a connection that we closed that the other end
|
||||
* still thinks is open. Exists in origin_circuit_t.half_streams until
|
||||
* we get an end cell or a resolved cell for this stream id.
|
||||
*/
|
||||
typedef struct half_edge_t {
|
||||
/** stream_id for the half-closed connection */
|
||||
streamid_t stream_id;
|
||||
|
||||
/** How many sendme's can the other end still send, based on how
|
||||
* much data we had sent at the time of close */
|
||||
int sendmes_pending;
|
||||
|
||||
/** How much more data can the other end still send, based on
|
||||
* our deliver window */
|
||||
int data_pending;
|
||||
|
||||
/**
|
||||
* Monotime timestamp of when the other end should have successfully
|
||||
* shut down the stream and stop sending data, based on the larger
|
||||
* of circuit RTT and CBT. Used if 'used_ccontrol' is true, to expire
|
||||
* the half_edge at this monotime timestamp. */
|
||||
uint64_t end_ack_expected_usec;
|
||||
|
||||
/**
|
||||
* Did this edge use congestion control? If so, use
|
||||
* timer instead of pending data approach */
|
||||
unsigned int used_ccontrol : 1;
|
||||
|
||||
/** Is there a connected cell pending? */
|
||||
unsigned int connected_pending : 1;
|
||||
} half_edge_t;
|
||||
|
||||
#endif /* !defined(HALF_EDGE_ST_H) */
|
||||
@@ -0,0 +1,29 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file listener_connection_st.h
|
||||
* @brief Listener connection structure.
|
||||
**/
|
||||
|
||||
#ifndef LISTENER_CONNECTION_ST_H
|
||||
#define LISTENER_CONNECTION_ST_H
|
||||
|
||||
#include "core/or/connection_st.h"
|
||||
|
||||
/** Subtype of connection_t; used for a listener socket. */
|
||||
struct listener_connection_t {
|
||||
connection_t base_;
|
||||
|
||||
/** If the connection is a CONN_TYPE_AP_DNS_LISTENER, this field points
|
||||
* to the evdns_server_port it uses to listen to and answer connections. */
|
||||
struct evdns_server_port *dns_server_port;
|
||||
|
||||
entry_port_cfg_t entry_cfg;
|
||||
|
||||
};
|
||||
|
||||
#endif /* !defined(LISTENER_CONNECTION_ST_H) */
|
||||
@@ -0,0 +1,72 @@
|
||||
/* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file ocirc_event.h
|
||||
* \brief Header file for ocirc_event.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_OCIRC_EVENT_H
|
||||
#define TOR_OCIRC_EVENT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "lib/cc/torint.h"
|
||||
#include "lib/pubsub/pubsub.h"
|
||||
|
||||
/** Used to indicate the type of a circuit event passed to the controller.
|
||||
* The various types are defined in control-spec.txt */
|
||||
typedef enum circuit_status_event_t {
|
||||
CIRC_EVENT_LAUNCHED = 0,
|
||||
CIRC_EVENT_BUILT = 1,
|
||||
CIRC_EVENT_EXTENDED = 2,
|
||||
CIRC_EVENT_FAILED = 3,
|
||||
CIRC_EVENT_CLOSED = 4,
|
||||
} circuit_status_event_t;
|
||||
|
||||
/** Message for origin circuit state update */
|
||||
typedef struct ocirc_state_msg_t {
|
||||
uint32_t gid; /**< global ID (only origin circuits have them) */
|
||||
int state; /**< new circuit state */
|
||||
bool onehop; /**< one-hop circuit? */
|
||||
} ocirc_state_msg_t;
|
||||
|
||||
DECLARE_MESSAGE(ocirc_state, ocirc_state, ocirc_state_msg_t *);
|
||||
|
||||
/**
|
||||
* Message when a channel gets associated to a circuit.
|
||||
*
|
||||
* This doesn't always correspond to something in circuitbuild.c
|
||||
* setting the n_chan field in the circuit. For some reason, if
|
||||
* circuit_handle_first_hop() launches a new circuit, it doesn't set
|
||||
* the n_chan field.
|
||||
*/
|
||||
typedef struct ocirc_chan_msg_t {
|
||||
uint32_t gid; /**< global ID */
|
||||
uint64_t chan; /**< channel ID */
|
||||
bool onehop; /**< one-hop circuit? */
|
||||
} ocirc_chan_msg_t;
|
||||
|
||||
DECLARE_MESSAGE(ocirc_chan, ocirc_chan, ocirc_chan_msg_t *);
|
||||
|
||||
/**
|
||||
* Message for origin circuit status event
|
||||
*
|
||||
* This contains information that ends up in CIRC control protocol events.
|
||||
*/
|
||||
typedef struct ocirc_cevent_msg_t {
|
||||
uint32_t gid; /**< global ID */
|
||||
int evtype; /**< event type */
|
||||
int reason; /**< reason */
|
||||
bool onehop; /**< one-hop circuit? */
|
||||
} ocirc_cevent_msg_t;
|
||||
|
||||
DECLARE_MESSAGE(ocirc_cevent, ocirc_cevent, ocirc_cevent_msg_t *);
|
||||
|
||||
#ifdef OCIRC_EVENT_PRIVATE
|
||||
void ocirc_state_publish(ocirc_state_msg_t *msg);
|
||||
void ocirc_chan_publish(ocirc_chan_msg_t *msg);
|
||||
void ocirc_cevent_publish(ocirc_cevent_msg_t *msg);
|
||||
#endif
|
||||
|
||||
#endif /* !defined(TOR_OCIRC_EVENT_H) */
|
||||
@@ -0,0 +1,91 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file onion.h
|
||||
* \brief Header file for onion.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_ONION_H
|
||||
#define TOR_ONION_H
|
||||
|
||||
struct create_cell_t;
|
||||
struct curve25519_keypair_t;
|
||||
struct curve25519_public_key_t;
|
||||
#include "lib/crypt_ops/crypto_ed25519.h"
|
||||
|
||||
#define MAX_ONIONSKIN_CHALLENGE_LEN 255
|
||||
#define MAX_ONIONSKIN_REPLY_LEN 255
|
||||
|
||||
/** A parsed CREATE, CREATE_FAST, or CREATE2 cell. */
|
||||
typedef struct create_cell_t {
|
||||
/** The cell command. One of CREATE{,_FAST,2} */
|
||||
uint8_t cell_type;
|
||||
/** One of the ONION_HANDSHAKE_TYPE_* values */
|
||||
uint16_t handshake_type;
|
||||
/** The number of bytes used in <b>onionskin</b>. */
|
||||
uint16_t handshake_len;
|
||||
/** The client-side message for the circuit creation handshake. */
|
||||
uint8_t onionskin[CELL_PAYLOAD_SIZE - 4];
|
||||
} create_cell_t;
|
||||
|
||||
/** A parsed CREATED, CREATED_FAST, or CREATED2 cell. */
|
||||
typedef struct created_cell_t {
|
||||
/** The cell command. One of CREATED{,_FAST,2} */
|
||||
uint8_t cell_type;
|
||||
/** The number of bytes used in <b>reply</b>. */
|
||||
uint16_t handshake_len;
|
||||
/** The server-side message for the circuit creation handshake. */
|
||||
uint8_t reply[CELL_PAYLOAD_SIZE - 2];
|
||||
} created_cell_t;
|
||||
|
||||
/** A parsed RELAY_EXTEND or RELAY_EXTEND2 cell */
|
||||
typedef struct extend_cell_t {
|
||||
/** One of RELAY_EXTEND or RELAY_EXTEND2 */
|
||||
uint8_t cell_type;
|
||||
/** An IPv4 address and port for the node we're connecting to. */
|
||||
tor_addr_port_t orport_ipv4;
|
||||
/** An IPv6 address and port for the node we're connecting to. */
|
||||
tor_addr_port_t orport_ipv6;
|
||||
/** Identity fingerprint of the node we're connecting to.*/
|
||||
uint8_t node_id[DIGEST_LEN];
|
||||
/** Ed25519 public identity key. Zero if not set. */
|
||||
struct ed25519_public_key_t ed_pubkey;
|
||||
/** The "create cell" embedded in this extend cell. Note that unlike the
|
||||
* create cells we generate ourselves, this create cell can have a handshake
|
||||
* type we don't recognize. */
|
||||
create_cell_t create_cell;
|
||||
} extend_cell_t;
|
||||
|
||||
/** A parsed RELAY_EXTEND or RELAY_EXTEND2 cell */
|
||||
typedef struct extended_cell_t {
|
||||
/** One of RELAY_EXTENDED or RELAY_EXTENDED2. */
|
||||
uint8_t cell_type;
|
||||
/** The "created cell" embedded in this extended cell. */
|
||||
created_cell_t created_cell;
|
||||
} extended_cell_t;
|
||||
|
||||
void create_cell_init(create_cell_t *cell_out, uint8_t cell_type,
|
||||
uint16_t handshake_type, uint16_t handshake_len,
|
||||
const uint8_t *onionskin);
|
||||
int create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in);
|
||||
int created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in);
|
||||
MOCK_DECL(int,extend_cell_parse,(extend_cell_t *cell_out,
|
||||
const uint8_t command,
|
||||
const uint8_t *payload_in,
|
||||
size_t payload_len));
|
||||
int extended_cell_parse(extended_cell_t *cell_out, const uint8_t command,
|
||||
const uint8_t *payload_in, size_t payload_len);
|
||||
|
||||
int create_cell_format(cell_t *cell_out, const create_cell_t *cell_in);
|
||||
int create_cell_format_relayed(cell_t *cell_out, const create_cell_t *cell_in);
|
||||
int created_cell_format(cell_t *cell_out, const created_cell_t *cell_in);
|
||||
int extend_cell_format(uint8_t *command_out, uint16_t *len_out,
|
||||
uint8_t *payload_out, const extend_cell_t *cell_in);
|
||||
int extended_cell_format(uint8_t *command_out, uint16_t *len_out,
|
||||
uint8_t *payload_out, const extended_cell_t *cell_in);
|
||||
|
||||
#endif /* !defined(TOR_ONION_H) */
|
||||
@@ -0,0 +1,993 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file or.h
|
||||
* \brief Master header file for Tor-specific functionality.
|
||||
**/
|
||||
|
||||
#ifndef TOR_OR_H
|
||||
#define TOR_OR_H
|
||||
|
||||
#include "orconfig.h"
|
||||
#include "lib/cc/torint.h"
|
||||
|
||||
#ifdef HAVE_SIGNAL_H
|
||||
#include <signal.h>
|
||||
#endif
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#include "lib/arch/bytes.h"
|
||||
#include "lib/cc/compat_compiler.h"
|
||||
#include "lib/container/map.h"
|
||||
#include "lib/buf/buffers.h"
|
||||
#include "lib/container/smartlist.h"
|
||||
#include "lib/crypt_ops/crypto_cipher.h"
|
||||
#include "lib/crypt_ops/crypto_rsa.h"
|
||||
#include "lib/ctime/di_ops.h"
|
||||
#include "lib/defs/dh_sizes.h"
|
||||
#include "lib/encoding/binascii.h"
|
||||
#include "lib/encoding/cstring.h"
|
||||
#include "lib/encoding/time_fmt.h"
|
||||
#include "lib/err/torerr.h"
|
||||
#include "lib/fs/dir.h"
|
||||
#include "lib/fs/files.h"
|
||||
#include "lib/fs/mmap.h"
|
||||
#include "lib/fs/path.h"
|
||||
#include "lib/fs/userdb.h"
|
||||
#include "lib/geoip/country.h"
|
||||
#include "lib/intmath/addsub.h"
|
||||
#include "lib/intmath/bits.h"
|
||||
#include "lib/intmath/cmp.h"
|
||||
#include "lib/intmath/logic.h"
|
||||
#include "lib/intmath/muldiv.h"
|
||||
#include "lib/log/escape.h"
|
||||
#include "lib/log/ratelim.h"
|
||||
#include "lib/log/util_bug.h"
|
||||
#include "lib/malloc/malloc.h"
|
||||
#include "lib/net/address.h"
|
||||
#include "lib/net/inaddr.h"
|
||||
#include "lib/net/socket.h"
|
||||
#include "lib/string/compat_ctype.h"
|
||||
#include "lib/string/compat_string.h"
|
||||
#include "lib/string/parse_int.h"
|
||||
#include "lib/string/printf.h"
|
||||
#include "lib/string/scanf.h"
|
||||
#include "lib/string/util_string.h"
|
||||
#include "lib/testsupport/testsupport.h"
|
||||
#include "lib/thread/threads.h"
|
||||
#include "lib/time/compat_time.h"
|
||||
#include "lib/wallclock/approx_time.h"
|
||||
#include "lib/wallclock/timeval.h"
|
||||
|
||||
#include "ht.h"
|
||||
|
||||
// These, more than other includes, are for keeping the other struct
|
||||
// definitions working. We should remove them when we minimize our includes.
|
||||
#include "core/or/entry_port_cfg_st.h"
|
||||
|
||||
struct ed25519_public_key_t;
|
||||
struct curve25519_public_key_t;
|
||||
|
||||
/* These signals are defined to help handle_control_signal work.
|
||||
*/
|
||||
#ifndef SIGHUP
|
||||
#define SIGHUP 1
|
||||
#endif
|
||||
#ifndef SIGINT
|
||||
#define SIGINT 2
|
||||
#endif
|
||||
#ifndef SIGUSR1
|
||||
#define SIGUSR1 10
|
||||
#endif
|
||||
#ifndef SIGUSR2
|
||||
#define SIGUSR2 12
|
||||
#endif
|
||||
#ifndef SIGTERM
|
||||
#define SIGTERM 15
|
||||
#endif
|
||||
/* Controller signals start at a high number so we don't
|
||||
* conflict with system-defined signals. */
|
||||
#define SIGNEWNYM 129
|
||||
#define SIGCLEARDNSCACHE 130
|
||||
#define SIGHEARTBEAT 131
|
||||
#define SIGACTIVE 132
|
||||
#define SIGDORMANT 133
|
||||
|
||||
#if (SIZEOF_CELL_T != 0)
|
||||
/* On Irix, stdlib.h defines a cell_t type, so we need to make sure
|
||||
* that our stuff always calls cell_t something different. */
|
||||
#define cell_t tor_cell_t
|
||||
#endif
|
||||
|
||||
/** Helper macro: Given a pointer to to.base_, of type from*, return &to. */
|
||||
#define DOWNCAST(to, ptr) ((to*)SUBTYPE_P(ptr, to, base_))
|
||||
|
||||
/** Length of longest allowable configured nickname. */
|
||||
#define MAX_NICKNAME_LEN 19
|
||||
/** Length of a router identity encoded as a hexadecimal digest, plus
|
||||
* possible dollar sign. */
|
||||
#define MAX_HEX_NICKNAME_LEN (HEX_DIGEST_LEN+1)
|
||||
/** Maximum length of verbose router identifier: dollar sign, hex ID digest,
|
||||
* equal sign or tilde, nickname. */
|
||||
#define MAX_VERBOSE_NICKNAME_LEN (1+HEX_DIGEST_LEN+1+MAX_NICKNAME_LEN)
|
||||
|
||||
/** For HTTP parsing: Maximum number of bytes we'll accept in the headers
|
||||
* of an HTTP request or response. */
|
||||
#define MAX_HEADERS_SIZE 50000
|
||||
|
||||
/** Maximum size, in bytes, of a single router descriptor uploaded to us
|
||||
* as a directory authority. Caches and clients fetch whatever descriptors
|
||||
* the authorities tell them to fetch, and don't care about size. */
|
||||
#define MAX_DESCRIPTOR_UPLOAD_SIZE 20000
|
||||
|
||||
/** Maximum size of a single extrainfo document, as above. */
|
||||
#define MAX_EXTRAINFO_UPLOAD_SIZE 50000
|
||||
|
||||
/** Minimum lifetime for an onion key in days. */
|
||||
#define MIN_ONION_KEY_LIFETIME_DAYS (1)
|
||||
|
||||
/** Maximum lifetime for an onion key in days. */
|
||||
#define MAX_ONION_KEY_LIFETIME_DAYS (90)
|
||||
|
||||
/** Default lifetime for an onion key in days. */
|
||||
#define DEFAULT_ONION_KEY_LIFETIME_DAYS (28)
|
||||
|
||||
/** Minimum grace period for acceptance of an onion key in days.
|
||||
* The maximum value is defined in proposal #274 as being the current network
|
||||
* consensus parameter for "onion-key-rotation-days". */
|
||||
#define MIN_ONION_KEY_GRACE_PERIOD_DAYS (1)
|
||||
|
||||
/** Default grace period for acceptance of an onion key in days. */
|
||||
#define DEFAULT_ONION_KEY_GRACE_PERIOD_DAYS (7)
|
||||
|
||||
/** How often we should check the network consensus if it is time to rotate or
|
||||
* expire onion keys. */
|
||||
#define ONION_KEY_CONSENSUS_CHECK_INTERVAL (60*60)
|
||||
|
||||
/** How often do we rotate TLS contexts? */
|
||||
#define MAX_SSL_KEY_LIFETIME_INTERNAL (2*60*60)
|
||||
|
||||
/** How old do we allow a router to get before removing it
|
||||
* from the router list? In seconds. */
|
||||
#define ROUTER_MAX_AGE (60*60*48)
|
||||
/** How old can a router get before we (as a server) will no longer
|
||||
* consider it live? In seconds. */
|
||||
#define ROUTER_MAX_AGE_TO_PUBLISH (60*60*24)
|
||||
/** How old do we let a saved descriptor get before force-removing it? */
|
||||
#define OLD_ROUTER_DESC_MAX_AGE (60*60*24*5)
|
||||
|
||||
/* Proxy client types */
|
||||
#define PROXY_NONE 0
|
||||
#define PROXY_CONNECT 1
|
||||
#define PROXY_SOCKS4 2
|
||||
#define PROXY_SOCKS5 3
|
||||
#define PROXY_HAPROXY 4
|
||||
/* !!!! If there is ever a PROXY_* type over 7, we must grow the proxy_type
|
||||
* field in or_connection_t */
|
||||
|
||||
/* Pluggable transport proxy type. Don't use this in or_connection_t,
|
||||
* instead use the actual underlying proxy type (see above). */
|
||||
#define PROXY_PLUGGABLE 5
|
||||
|
||||
/** How many circuits do we want simultaneously in-progress to handle
|
||||
* a given stream? */
|
||||
#define MIN_CIRCUITS_HANDLING_STREAM 2
|
||||
|
||||
/* These RELAY_COMMAND constants define values for relay cell commands, and
|
||||
* must match those defined in tor-spec.txt. */
|
||||
#define RELAY_COMMAND_BEGIN 1
|
||||
#define RELAY_COMMAND_DATA 2
|
||||
#define RELAY_COMMAND_END 3
|
||||
#define RELAY_COMMAND_CONNECTED 4
|
||||
|
||||
#define RELAY_COMMAND_SENDME 5
|
||||
#define RELAY_COMMAND_EXTEND 6
|
||||
#define RELAY_COMMAND_EXTENDED 7
|
||||
#define RELAY_COMMAND_TRUNCATE 8
|
||||
#define RELAY_COMMAND_TRUNCATED 9
|
||||
#define RELAY_COMMAND_DROP 10
|
||||
|
||||
#define RELAY_COMMAND_RESOLVE 11
|
||||
#define RELAY_COMMAND_RESOLVED 12
|
||||
|
||||
#define RELAY_COMMAND_BEGIN_DIR 13
|
||||
#define RELAY_COMMAND_EXTEND2 14
|
||||
#define RELAY_COMMAND_EXTENDED2 15
|
||||
|
||||
/* Conflux */
|
||||
#define RELAY_COMMAND_CONFLUX_LINK 19
|
||||
#define RELAY_COMMAND_CONFLUX_LINKED 20
|
||||
#define RELAY_COMMAND_CONFLUX_LINKED_ACK 21
|
||||
#define RELAY_COMMAND_CONFLUX_SWITCH 22
|
||||
|
||||
#define RELAY_COMMAND_ESTABLISH_INTRO 32
|
||||
#define RELAY_COMMAND_ESTABLISH_RENDEZVOUS 33
|
||||
#define RELAY_COMMAND_INTRODUCE1 34
|
||||
#define RELAY_COMMAND_INTRODUCE2 35
|
||||
#define RELAY_COMMAND_RENDEZVOUS1 36
|
||||
#define RELAY_COMMAND_RENDEZVOUS2 37
|
||||
#define RELAY_COMMAND_INTRO_ESTABLISHED 38
|
||||
#define RELAY_COMMAND_RENDEZVOUS_ESTABLISHED 39
|
||||
#define RELAY_COMMAND_INTRODUCE_ACK 40
|
||||
|
||||
#define RELAY_COMMAND_PADDING_NEGOTIATE 41
|
||||
#define RELAY_COMMAND_PADDING_NEGOTIATED 42
|
||||
|
||||
#define RELAY_COMMAND_XOFF 43
|
||||
#define RELAY_COMMAND_XON 44
|
||||
|
||||
/* Reasons why an OR connection is closed. */
|
||||
#define END_OR_CONN_REASON_DONE 1
|
||||
#define END_OR_CONN_REASON_REFUSED 2 /* connection refused */
|
||||
#define END_OR_CONN_REASON_OR_IDENTITY 3
|
||||
#define END_OR_CONN_REASON_CONNRESET 4 /* connection reset by peer */
|
||||
#define END_OR_CONN_REASON_TIMEOUT 5
|
||||
#define END_OR_CONN_REASON_NO_ROUTE 6 /* no route to host/net */
|
||||
#define END_OR_CONN_REASON_IO_ERROR 7 /* read/write error */
|
||||
#define END_OR_CONN_REASON_RESOURCE_LIMIT 8 /* sockets, buffers, etc */
|
||||
#define END_OR_CONN_REASON_PT_MISSING 9 /* PT failed or not available */
|
||||
#define END_OR_CONN_REASON_TLS_ERROR 10 /* Problem in TLS protocol */
|
||||
#define END_OR_CONN_REASON_MISC 11
|
||||
|
||||
/* Reasons why we (or a remote OR) might close a stream. See tor-spec.txt for
|
||||
* documentation of these. The values must match. */
|
||||
#define END_STREAM_REASON_MISC 1
|
||||
#define END_STREAM_REASON_RESOLVEFAILED 2
|
||||
#define END_STREAM_REASON_CONNECTREFUSED 3
|
||||
#define END_STREAM_REASON_EXITPOLICY 4
|
||||
#define END_STREAM_REASON_DESTROY 5
|
||||
#define END_STREAM_REASON_DONE 6
|
||||
#define END_STREAM_REASON_TIMEOUT 7
|
||||
#define END_STREAM_REASON_NOROUTE 8
|
||||
#define END_STREAM_REASON_HIBERNATING 9
|
||||
#define END_STREAM_REASON_INTERNAL 10
|
||||
#define END_STREAM_REASON_RESOURCELIMIT 11
|
||||
#define END_STREAM_REASON_CONNRESET 12
|
||||
#define END_STREAM_REASON_TORPROTOCOL 13
|
||||
#define END_STREAM_REASON_NOTDIRECTORY 14
|
||||
#define END_STREAM_REASON_ENTRYPOLICY 15
|
||||
|
||||
/* These high-numbered end reasons are not part of the official spec,
|
||||
* and are not intended to be put in relay end cells. They are here
|
||||
* to be more informative when sending back socks replies to the
|
||||
* application. */
|
||||
/* XXXX 256 is no longer used; feel free to reuse it. */
|
||||
/** We were unable to attach the connection to any circuit at all. */
|
||||
/* XXXX the ways we use this one don't make a lot of sense. */
|
||||
#define END_STREAM_REASON_CANT_ATTACH 257
|
||||
/** We can't connect to any directories at all, so we killed our streams
|
||||
* before they can time out. */
|
||||
#define END_STREAM_REASON_NET_UNREACHABLE 258
|
||||
/** This is a SOCKS connection, and the client used (or misused) the SOCKS
|
||||
* protocol in a way we couldn't handle. */
|
||||
#define END_STREAM_REASON_SOCKSPROTOCOL 259
|
||||
/** This is a transparent proxy connection, but we can't extract the original
|
||||
* target address:port. */
|
||||
#define END_STREAM_REASON_CANT_FETCH_ORIG_DEST 260
|
||||
/** This is a connection on the NATD port, and the destination IP:Port was
|
||||
* either ill-formed or out-of-range. */
|
||||
#define END_STREAM_REASON_INVALID_NATD_DEST 261
|
||||
/** The target address is in a private network (like 127.0.0.1 or 10.0.0.1);
|
||||
* you don't want to do that over a randomly chosen exit */
|
||||
#define END_STREAM_REASON_PRIVATE_ADDR 262
|
||||
/** This is an HTTP tunnel connection and the client used or misused HTTP in a
|
||||
* way we can't handle.
|
||||
*/
|
||||
#define END_STREAM_REASON_HTTPPROTOCOL 263
|
||||
|
||||
/** Bitwise-and this value with endreason to mask out all flags. */
|
||||
#define END_STREAM_REASON_MASK 511
|
||||
|
||||
/** Bitwise-or this with the argument to control_event_stream_status
|
||||
* to indicate that the reason came from an END cell. */
|
||||
#define END_STREAM_REASON_FLAG_REMOTE 512
|
||||
/** Bitwise-or this with the argument to control_event_stream_status
|
||||
* to indicate that we already sent a CLOSED stream event. */
|
||||
#define END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED 1024
|
||||
/** Bitwise-or this with endreason to indicate that we already sent
|
||||
* a socks reply, and no further reply needs to be sent from
|
||||
* connection_mark_unattached_ap(). */
|
||||
#define END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED 2048
|
||||
|
||||
/* 'type' values to use in RESOLVED cells. Specified in tor-spec.txt. */
|
||||
#define RESOLVED_TYPE_HOSTNAME 0
|
||||
#define RESOLVED_TYPE_IPV4 4
|
||||
#define RESOLVED_TYPE_IPV6 6
|
||||
#define RESOLVED_TYPE_ERROR_TRANSIENT 0xF0
|
||||
#define RESOLVED_TYPE_ERROR 0xF1
|
||||
|
||||
/* Negative reasons are internal: we never send them in a DESTROY or TRUNCATE
|
||||
* call; they only go to the controller for tracking */
|
||||
|
||||
/* Closing introduction point that were opened in parallel. */
|
||||
#define END_CIRC_REASON_IP_NOW_REDUNDANT -4
|
||||
|
||||
/** Our post-timeout circuit time measurement period expired.
|
||||
* We must give up now */
|
||||
#define END_CIRC_REASON_MEASUREMENT_EXPIRED -3
|
||||
|
||||
/** We couldn't build a path for this circuit. */
|
||||
#define END_CIRC_REASON_NOPATH -2
|
||||
/** Catch-all "other" reason for closing origin circuits. */
|
||||
#define END_CIRC_AT_ORIGIN -1
|
||||
|
||||
/* Reasons why we (or a remote OR) might close a circuit. See tor-spec.txt
|
||||
* section 5.4 for documentation of these. */
|
||||
#define END_CIRC_REASON_MIN_ 0
|
||||
#define END_CIRC_REASON_NONE 0
|
||||
#define END_CIRC_REASON_TORPROTOCOL 1
|
||||
#define END_CIRC_REASON_INTERNAL 2
|
||||
#define END_CIRC_REASON_REQUESTED 3
|
||||
#define END_CIRC_REASON_HIBERNATING 4
|
||||
#define END_CIRC_REASON_RESOURCELIMIT 5
|
||||
#define END_CIRC_REASON_CONNECTFAILED 6
|
||||
#define END_CIRC_REASON_OR_IDENTITY 7
|
||||
#define END_CIRC_REASON_CHANNEL_CLOSED 8
|
||||
#define END_CIRC_REASON_FINISHED 9
|
||||
#define END_CIRC_REASON_TIMEOUT 10
|
||||
#define END_CIRC_REASON_DESTROYED 11
|
||||
#define END_CIRC_REASON_NOSUCHSERVICE 12
|
||||
#define END_CIRC_REASON_MAX_ 12
|
||||
|
||||
/** Bitwise-OR this with the argument to circuit_mark_for_close() or
|
||||
* control_event_circuit_status() to indicate that the reason was
|
||||
* passed through from a destroy or truncate cell. */
|
||||
#define END_CIRC_REASON_FLAG_REMOTE 512
|
||||
|
||||
/** Length of v2 descriptor ID (32 base32 chars = 160 bits).
|
||||
*
|
||||
* XXX: It is still used by v3 code but should be renamed or maybe removed. */
|
||||
#define REND_DESC_ID_V2_LEN_BASE32 BASE32_DIGEST_LEN
|
||||
|
||||
/** Maximum length of authorized client names for a hidden service. */
|
||||
#define REND_CLIENTNAME_MAX_LEN 16
|
||||
|
||||
/** Length of the rendezvous cookie that is used to connect circuits at the
|
||||
* rendezvous point. */
|
||||
#define REND_COOKIE_LEN DIGEST_LEN
|
||||
|
||||
/** Client authorization type that a hidden service performs. */
|
||||
typedef enum rend_auth_type_t {
|
||||
REND_NO_AUTH = 0,
|
||||
REND_V3_AUTH = 1, /* Dummy flag to allow adding v3 services on the
|
||||
* control port */
|
||||
} rend_auth_type_t;
|
||||
|
||||
/* Stub because we can't include hs_ident.h. */
|
||||
struct hs_ident_edge_conn_t;
|
||||
struct hs_ident_dir_conn_t;
|
||||
struct hs_ident_circuit_t;
|
||||
|
||||
typedef struct hsdir_index_t hsdir_index_t;
|
||||
|
||||
/** Time interval for tracking replays of DH public keys received in
|
||||
* INTRODUCE2 cells. Used only to avoid launching multiple
|
||||
* simultaneous attempts to connect to the same rendezvous point. */
|
||||
#define REND_REPLAY_TIME_INTERVAL (5 * 60)
|
||||
|
||||
/** Used to indicate which way a cell is going on a circuit. */
|
||||
typedef enum {
|
||||
CELL_DIRECTION_IN=1, /**< The cell is moving towards the origin. */
|
||||
CELL_DIRECTION_OUT=2, /**< The cell is moving away from the origin. */
|
||||
} cell_direction_t;
|
||||
|
||||
/**
|
||||
* An enum to allow us to specify which channel in a circuit
|
||||
* we're interested in.
|
||||
*
|
||||
* This is needed because our data structures and other fields
|
||||
* for channel delivery are disassociated from the channel.
|
||||
*/
|
||||
typedef enum {
|
||||
CIRCUIT_N_CHAN = 0,
|
||||
CIRCUIT_P_CHAN = 1
|
||||
} circuit_channel_direction_t;
|
||||
|
||||
/** Initial value for both sides of a circuit transmission window when the
|
||||
* circuit is initialized. Measured in cells. */
|
||||
#define CIRCWINDOW_START 1000
|
||||
#define CIRCWINDOW_START_MIN 100
|
||||
#define CIRCWINDOW_START_MAX 1000
|
||||
/** Amount to increment a circuit window when we get a circuit SENDME. */
|
||||
#define CIRCWINDOW_INCREMENT 100
|
||||
/** Initial value on both sides of a stream transmission window when the
|
||||
* stream is initialized. Measured in cells. */
|
||||
#define STREAMWINDOW_START 500
|
||||
#define STREAMWINDOW_START_MAX 500
|
||||
/** Amount to increment a stream window when we get a stream SENDME. */
|
||||
#define STREAMWINDOW_INCREMENT 50
|
||||
|
||||
/** Maximum number of queued cells on a circuit for which we are the
|
||||
* midpoint before we give up and kill it. This must be >= circwindow
|
||||
* to avoid killing innocent circuits, and >= circwindow*2 to give
|
||||
* leaky-pipe a chance of working someday. The ORCIRC_MAX_MIDDLE_KILL_THRESH
|
||||
* ratio controls the margin of error between emitting a warning and
|
||||
* killing the circuit.
|
||||
*/
|
||||
#define ORCIRC_MAX_MIDDLE_CELLS (CIRCWINDOW_START_MAX*2)
|
||||
/** Ratio of hard (circuit kill) to soft (warning) thresholds for the
|
||||
* ORCIRC_MAX_MIDDLE_CELLS tests.
|
||||
*/
|
||||
#define ORCIRC_MAX_MIDDLE_KILL_THRESH (1.1f)
|
||||
|
||||
/* Cell commands. These values are defined in tor-spec.txt. */
|
||||
#define CELL_PADDING 0
|
||||
#define CELL_CREATE 1
|
||||
#define CELL_CREATED 2
|
||||
#define CELL_RELAY 3
|
||||
#define CELL_DESTROY 4
|
||||
#define CELL_CREATE_FAST 5
|
||||
#define CELL_CREATED_FAST 6
|
||||
#define CELL_VERSIONS 7
|
||||
#define CELL_NETINFO 8
|
||||
#define CELL_RELAY_EARLY 9
|
||||
#define CELL_CREATE2 10
|
||||
#define CELL_CREATED2 11
|
||||
#define CELL_PADDING_NEGOTIATE 12
|
||||
|
||||
#define CELL_VPADDING 128
|
||||
#define CELL_CERTS 129
|
||||
#define CELL_AUTH_CHALLENGE 130
|
||||
#define CELL_AUTHENTICATE 131
|
||||
#define CELL_AUTHORIZE 132
|
||||
#define CELL_COMMAND_MAX_ 132
|
||||
|
||||
/** How long to test reachability before complaining to the user. */
|
||||
#define TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT (20*60)
|
||||
|
||||
/** Legal characters in a nickname. */
|
||||
#define LEGAL_NICKNAME_CHARACTERS \
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
|
||||
/** Name chosen by routers that don't configure nicknames */
|
||||
#define UNNAMED_ROUTER_NICKNAME "Unnamed"
|
||||
|
||||
/** Number of bytes in a SOCKS4 header. */
|
||||
#define SOCKS4_NETWORK_LEN 8
|
||||
|
||||
/*
|
||||
* Relay payload:
|
||||
* Relay command [1 byte]
|
||||
* Recognized [2 bytes]
|
||||
* Stream ID [2 bytes]
|
||||
* Partial SHA-1 [4 bytes]
|
||||
* Length [2 bytes]
|
||||
* Relay payload [498 bytes]
|
||||
*/
|
||||
|
||||
/** Number of bytes in a cell, minus cell header. */
|
||||
#define CELL_PAYLOAD_SIZE 509
|
||||
/** Number of bytes in a cell transmitted over the network, in the longest
|
||||
* form */
|
||||
#define CELL_MAX_NETWORK_SIZE 514
|
||||
|
||||
/** Maximum length of a header on a variable-length cell. */
|
||||
#define VAR_CELL_MAX_HEADER_SIZE 7
|
||||
|
||||
static int get_cell_network_size(int wide_circ_ids);
|
||||
static inline int get_cell_network_size(int wide_circ_ids)
|
||||
{
|
||||
return wide_circ_ids ? CELL_MAX_NETWORK_SIZE : CELL_MAX_NETWORK_SIZE - 2;
|
||||
}
|
||||
static int get_var_cell_header_size(int wide_circ_ids);
|
||||
static inline int get_var_cell_header_size(int wide_circ_ids)
|
||||
{
|
||||
return wide_circ_ids ? VAR_CELL_MAX_HEADER_SIZE :
|
||||
VAR_CELL_MAX_HEADER_SIZE - 2;
|
||||
}
|
||||
static int get_circ_id_size(int wide_circ_ids);
|
||||
static inline int get_circ_id_size(int wide_circ_ids)
|
||||
{
|
||||
return wide_circ_ids ? 4 : 2;
|
||||
}
|
||||
|
||||
/** Number of bytes in a relay cell's header (not including general cell
|
||||
* header). */
|
||||
#define RELAY_HEADER_SIZE (1+2+2+4+2)
|
||||
/** Largest number of bytes that can fit in a relay cell payload. */
|
||||
#define RELAY_PAYLOAD_SIZE (CELL_PAYLOAD_SIZE-RELAY_HEADER_SIZE)
|
||||
|
||||
/** Identifies a circuit on an or_connection */
|
||||
typedef uint32_t circid_t;
|
||||
/** Identifies a stream on a circuit */
|
||||
typedef uint16_t streamid_t;
|
||||
|
||||
/* channel_t typedef; struct channel_t is in channel.h */
|
||||
|
||||
typedef struct channel_t channel_t;
|
||||
|
||||
/* channel_listener_t typedef; struct channel_listener_t is in channel.h */
|
||||
|
||||
typedef struct channel_listener_t channel_listener_t;
|
||||
|
||||
/* TLS channel stuff */
|
||||
|
||||
typedef struct channel_tls_t channel_tls_t;
|
||||
|
||||
/* circuitmux_t typedef; struct circuitmux_t is in circuitmux.h */
|
||||
|
||||
typedef struct circuitmux_t circuitmux_t;
|
||||
|
||||
typedef struct cell_t cell_t;
|
||||
typedef struct var_cell_t var_cell_t;
|
||||
typedef struct packed_cell_t packed_cell_t;
|
||||
typedef struct cell_queue_t cell_queue_t;
|
||||
typedef struct destroy_cell_t destroy_cell_t;
|
||||
typedef struct destroy_cell_queue_t destroy_cell_queue_t;
|
||||
typedef struct ext_or_cmd_t ext_or_cmd_t;
|
||||
|
||||
/** Beginning of a RELAY cell payload. */
|
||||
typedef struct {
|
||||
uint8_t command; /**< The end-to-end relay command. */
|
||||
uint16_t recognized; /**< Used to tell whether cell is for us. */
|
||||
streamid_t stream_id; /**< Which stream is this cell associated with? */
|
||||
char integrity[4]; /**< Used to tell whether cell is corrupted. */
|
||||
uint16_t length; /**< How long is the payload body? */
|
||||
} relay_header_t;
|
||||
|
||||
typedef struct socks_request_t socks_request_t;
|
||||
typedef struct entry_port_cfg_t entry_port_cfg_t;
|
||||
typedef struct server_port_cfg_t server_port_cfg_t;
|
||||
|
||||
/** Minimum length of the random part of an AUTH_CHALLENGE cell. */
|
||||
#define OR_AUTH_CHALLENGE_LEN 32
|
||||
|
||||
/**
|
||||
* @name Certificate types for CERTS cells.
|
||||
*
|
||||
* These values are defined by the protocol, and affect how an X509
|
||||
* certificate in a CERTS cell is interpreted and used.
|
||||
*
|
||||
* @{ */
|
||||
/** A certificate that authenticates a TLS link key. The subject key
|
||||
* must match the key used in the TLS handshake; it must be signed by
|
||||
* the identity key. */
|
||||
#define OR_CERT_TYPE_TLS_LINK 1
|
||||
/** A self-signed identity certificate. The subject key must be a
|
||||
* 1024-bit RSA key. */
|
||||
#define OR_CERT_TYPE_ID_1024 2
|
||||
/** A certificate that authenticates a key used in an AUTHENTICATE cell
|
||||
* in the v3 handshake. The subject key must be a 1024-bit RSA key; it
|
||||
* must be signed by the identity key */
|
||||
#define OR_CERT_TYPE_AUTH_1024 3
|
||||
/* DOCDOC */
|
||||
#define OR_CERT_TYPE_RSA_ED_CROSSCERT 7
|
||||
/**@}*/
|
||||
|
||||
/** The first supported type of AUTHENTICATE cell. It contains
|
||||
* a bunch of structures signed with an RSA1024 key. The signed
|
||||
* structures include a HMAC using negotiated TLS secrets, and a digest
|
||||
* of all cells sent or received before the AUTHENTICATE cell (including
|
||||
* the random server-generated AUTH_CHALLENGE cell).
|
||||
*/
|
||||
#define AUTHTYPE_RSA_SHA256_TLSSECRET 1
|
||||
/** As AUTHTYPE_RSA_SHA256_TLSSECRET, but instead of using the
|
||||
* negotiated TLS secrets, uses exported keying material from the TLS
|
||||
* session as described in RFC 5705.
|
||||
*
|
||||
* Not used by today's tors, since everything that supports this
|
||||
* also supports ED25519_SHA256_5705, which is better.
|
||||
**/
|
||||
#define AUTHTYPE_RSA_SHA256_RFC5705 2
|
||||
/** As AUTHTYPE_RSA_SHA256_RFC5705, but uses an Ed25519 identity key to
|
||||
* authenticate. */
|
||||
#define AUTHTYPE_ED25519_SHA256_RFC5705 3
|
||||
/*
|
||||
* NOTE: authchallenge_type_is_better() relies on these AUTHTYPE codes
|
||||
* being sorted in order of preference. If we someday add one with
|
||||
* a higher numerical value that we don't like as much, we should revise
|
||||
* authchallenge_type_is_better().
|
||||
*/
|
||||
|
||||
/** The length of the part of the AUTHENTICATE cell body that the client and
|
||||
* server can generate independently (when using RSA_SHA256_TLSSECRET). It
|
||||
* contains everything except the client's timestamp, the client's randomly
|
||||
* generated nonce, and the signature. */
|
||||
#define V3_AUTH_FIXED_PART_LEN (8+(32*6))
|
||||
/** The length of the part of the AUTHENTICATE cell body that the client
|
||||
* signs. */
|
||||
#define V3_AUTH_BODY_LEN (V3_AUTH_FIXED_PART_LEN + 8 + 16)
|
||||
|
||||
typedef struct or_handshake_certs_t or_handshake_certs_t;
|
||||
typedef struct or_handshake_state_t or_handshake_state_t;
|
||||
|
||||
/** Length of Extended ORPort connection identifier. */
|
||||
#define EXT_OR_CONN_ID_LEN DIGEST_LEN /* 20 */
|
||||
|
||||
typedef struct connection_t connection_t;
|
||||
typedef struct control_connection_t control_connection_t;
|
||||
typedef struct dir_connection_t dir_connection_t;
|
||||
typedef struct edge_connection_t edge_connection_t;
|
||||
typedef struct entry_connection_t entry_connection_t;
|
||||
typedef struct listener_connection_t listener_connection_t;
|
||||
typedef struct or_connection_t or_connection_t;
|
||||
|
||||
/** Cast a connection_t subtype pointer to a connection_t **/
|
||||
#define TO_CONN(c) (&(((c)->base_)))
|
||||
|
||||
/** Cast a entry_connection_t subtype pointer to a connection_t **/
|
||||
#define ENTRY_TO_CONN(c) (TO_CONN(ENTRY_TO_EDGE_CONN(c)))
|
||||
|
||||
typedef struct addr_policy_t addr_policy_t;
|
||||
|
||||
typedef struct cached_dir_t cached_dir_t;
|
||||
|
||||
/** Enum used to remember where a signed_descriptor_t is stored and how to
|
||||
* manage the memory for signed_descriptor_body. */
|
||||
typedef enum {
|
||||
/** The descriptor isn't stored on disk at all: the copy in memory is
|
||||
* canonical; the saved_offset field is meaningless. */
|
||||
SAVED_NOWHERE=0,
|
||||
/** The descriptor is stored in the cached_routers file: the
|
||||
* signed_descriptor_body is meaningless; the signed_descriptor_len and
|
||||
* saved_offset are used to index into the mmaped cache file. */
|
||||
SAVED_IN_CACHE,
|
||||
/** The descriptor is stored in the cached_routers.new file: the
|
||||
* signed_descriptor_body and saved_offset fields are both set. */
|
||||
/* FFFF (We could also mmap the file and grow the mmap as needed, or
|
||||
* lazy-load the descriptor text by using seek and read. We don't, for
|
||||
* now.)
|
||||
*/
|
||||
SAVED_IN_JOURNAL
|
||||
} saved_location_t;
|
||||
#define saved_location_bitfield_t ENUM_BF(saved_location_t)
|
||||
|
||||
/** Enumeration: what directory object is being downloaded?
|
||||
* This determines which schedule is selected to perform the download. */
|
||||
typedef enum {
|
||||
DL_SCHED_GENERIC = 0,
|
||||
DL_SCHED_CONSENSUS = 1,
|
||||
DL_SCHED_BRIDGE = 2,
|
||||
} download_schedule_t;
|
||||
#define download_schedule_bitfield_t ENUM_BF(download_schedule_t)
|
||||
|
||||
/** Enumeration: is the download schedule for downloading from an authority,
|
||||
* or from any available directory mirror?
|
||||
* During bootstrap, "any" means a fallback (or an authority, if there
|
||||
* are no fallbacks).
|
||||
* When we have a valid consensus, "any" means any directory server. */
|
||||
typedef enum {
|
||||
DL_WANT_ANY_DIRSERVER = 0,
|
||||
DL_WANT_AUTHORITY = 1,
|
||||
} download_want_authority_t;
|
||||
#define download_want_authority_bitfield_t \
|
||||
ENUM_BF(download_want_authority_t)
|
||||
|
||||
/** Enumeration: do we want to increment the schedule position each time a
|
||||
* connection is attempted (these attempts can be concurrent), or do we want
|
||||
* to increment the schedule position after a connection fails? */
|
||||
typedef enum {
|
||||
DL_SCHED_INCREMENT_FAILURE = 0,
|
||||
DL_SCHED_INCREMENT_ATTEMPT = 1,
|
||||
} download_schedule_increment_t;
|
||||
#define download_schedule_increment_bitfield_t \
|
||||
ENUM_BF(download_schedule_increment_t)
|
||||
|
||||
typedef struct download_status_t download_status_t;
|
||||
|
||||
/** If n_download_failures is this high, the download can never happen. */
|
||||
#define IMPOSSIBLE_TO_DOWNLOAD 255
|
||||
|
||||
/** The max size we expect router descriptor annotations we create to
|
||||
* be. We'll accept larger ones if we see them on disk, but we won't
|
||||
* create any that are larger than this. */
|
||||
#define ROUTER_ANNOTATION_BUF_LEN 256
|
||||
|
||||
typedef struct signed_descriptor_t signed_descriptor_t;
|
||||
|
||||
/** Flags used to summarize the declared protocol versions of a relay,
|
||||
* so we don't need to parse them again and again. */
|
||||
typedef struct protover_summary_flags_t {
|
||||
/** True iff we have a proto line for this router, or a versions line
|
||||
* from which we could infer the protocols. */
|
||||
unsigned int protocols_known:1;
|
||||
|
||||
/** True iff this router has a version or protocol list that allows it to
|
||||
* accept EXTEND2 cells. This requires Relay=2. */
|
||||
unsigned int supports_extend2_cells:1;
|
||||
|
||||
/** True iff this router has a version or protocol list that allows it to
|
||||
* accept IPv6 connections. This requires Relay=2 or Relay=3. */
|
||||
unsigned int supports_accepting_ipv6_extends:1;
|
||||
|
||||
/** True iff this router has a version or protocol list that allows it to
|
||||
* initiate IPv6 connections. This requires Relay=3. */
|
||||
unsigned int supports_initiating_ipv6_extends:1;
|
||||
|
||||
/** True iff this router has a version or protocol list that allows it to
|
||||
* consider IPv6 connections canonical. This requires Relay=3. */
|
||||
unsigned int supports_canonical_ipv6_conns:1;
|
||||
|
||||
/** True iff this router has a protocol list that allows it to negotiate
|
||||
* ed25519 identity keys on a link handshake with us. This
|
||||
* requires LinkAuth=3. */
|
||||
unsigned int supports_ed25519_link_handshake_compat:1;
|
||||
|
||||
/** True iff this router has a protocol list that allows it to negotiate
|
||||
* ed25519 identity keys on a link handshake, at all. This requires some
|
||||
* LinkAuth=X for X >= 3. */
|
||||
unsigned int supports_ed25519_link_handshake_any:1;
|
||||
|
||||
/** True iff this router has a protocol list that allows it to be an
|
||||
* introduction point supporting ed25519 authentication key which is part of
|
||||
* the v3 protocol detailed in proposal 224. This requires HSIntro=4. */
|
||||
unsigned int supports_ed25519_hs_intro : 1;
|
||||
|
||||
/** True iff this router has a protocol list that allows it to support the
|
||||
* ESTABLISH_INTRO DoS cell extension. Requires HSIntro=5. */
|
||||
unsigned int supports_establish_intro_dos_extension : 1;
|
||||
|
||||
/** True iff this router has a protocol list that allows it to be an hidden
|
||||
* service directory supporting version 3 as seen in proposal 224. This
|
||||
* requires HSDir=2. */
|
||||
unsigned int supports_v3_hsdir : 1;
|
||||
|
||||
/** True iff this router has a protocol list that allows it to be an hidden
|
||||
* service rendezvous point supporting version 3 as seen in proposal 224.
|
||||
* This requires HSRend=2. */
|
||||
unsigned int supports_v3_rendezvous_point: 1;
|
||||
|
||||
/** True iff this router has a protocol list that allows clients to
|
||||
* negotiate hs circuit setup padding. Requires Padding=2. */
|
||||
unsigned int supports_hs_setup_padding : 1;
|
||||
|
||||
/** True iff this router supports congestion control.
|
||||
* Requires both FlowCtrl=2 *and* Relay=4 */
|
||||
unsigned int supports_congestion_control : 1;
|
||||
|
||||
/** True iff this router supports conflux. Requires Relay=5 */
|
||||
unsigned int supports_conflux : 1;
|
||||
} protover_summary_flags_t;
|
||||
|
||||
typedef struct routerinfo_t routerinfo_t;
|
||||
typedef struct extrainfo_t extrainfo_t;
|
||||
typedef struct routerstatus_t routerstatus_t;
|
||||
|
||||
typedef struct microdesc_t microdesc_t;
|
||||
typedef struct node_t node_t;
|
||||
typedef struct vote_microdesc_hash_t vote_microdesc_hash_t;
|
||||
typedef struct vote_routerstatus_t vote_routerstatus_t;
|
||||
typedef struct document_signature_t document_signature_t;
|
||||
typedef struct networkstatus_voter_info_t networkstatus_voter_info_t;
|
||||
typedef struct networkstatus_sr_info_t networkstatus_sr_info_t;
|
||||
|
||||
/** Enumerates recognized flavors of a consensus networkstatus document. All
|
||||
* flavors of a consensus are generated from the same set of votes, but they
|
||||
* present different types information to different versions of Tor. */
|
||||
typedef enum {
|
||||
FLAV_NS = 0,
|
||||
FLAV_MICRODESC = 1,
|
||||
} consensus_flavor_t;
|
||||
|
||||
/** How many different consensus flavors are there? */
|
||||
#define N_CONSENSUS_FLAVORS ((int)(FLAV_MICRODESC)+1)
|
||||
|
||||
typedef struct networkstatus_t networkstatus_t;
|
||||
typedef struct ns_detached_signatures_t ns_detached_signatures_t;
|
||||
typedef struct desc_store_t desc_store_t;
|
||||
typedef struct routerlist_t routerlist_t;
|
||||
typedef struct extend_info_t extend_info_t;
|
||||
typedef struct authority_cert_t authority_cert_t;
|
||||
|
||||
/** Bitfield enum type listing types of information that directory authorities
|
||||
* can be authoritative about, and that directory caches may or may not cache.
|
||||
*
|
||||
* Note that the granularity here is based on authority granularity and on
|
||||
* cache capabilities. Thus, one particular bit may correspond in practice to
|
||||
* a few types of directory info, so long as every authority that pronounces
|
||||
* officially about one of the types prounounces officially about all of them,
|
||||
* and so long as every cache that caches one of them caches all of them.
|
||||
*/
|
||||
typedef enum {
|
||||
NO_DIRINFO = 0,
|
||||
/** Serves/signs v3 directory information: votes, consensuses, certs */
|
||||
V3_DIRINFO = 1 << 2,
|
||||
/** Serves bridge descriptors. */
|
||||
BRIDGE_DIRINFO = 1 << 4,
|
||||
/** Serves extrainfo documents. */
|
||||
EXTRAINFO_DIRINFO=1 << 5,
|
||||
/** Serves microdescriptors. */
|
||||
MICRODESC_DIRINFO=1 << 6,
|
||||
} dirinfo_type_t;
|
||||
|
||||
#define ALL_DIRINFO ((dirinfo_type_t)((1<<7)-1))
|
||||
|
||||
#define ONION_HANDSHAKE_TYPE_TAP 0x0000
|
||||
#define ONION_HANDSHAKE_TYPE_FAST 0x0001
|
||||
#define ONION_HANDSHAKE_TYPE_NTOR 0x0002
|
||||
#define ONION_HANDSHAKE_TYPE_NTOR_V3 0x0003
|
||||
#define MAX_ONION_HANDSHAKE_TYPE 0x0003
|
||||
|
||||
typedef struct onion_handshake_state_t onion_handshake_state_t;
|
||||
typedef struct relay_crypto_t relay_crypto_t;
|
||||
typedef struct crypt_path_t crypt_path_t;
|
||||
typedef struct crypt_path_reference_t crypt_path_reference_t;
|
||||
|
||||
#define CPATH_KEY_MATERIAL_LEN (20*2+16*2)
|
||||
|
||||
typedef struct cpath_build_state_t cpath_build_state_t;
|
||||
|
||||
struct create_cell_t;
|
||||
|
||||
/** Entry in the cell stats list of a circuit; used only if CELL_STATS
|
||||
* events are enabled. */
|
||||
typedef struct testing_cell_stats_entry_t {
|
||||
uint8_t command; /**< cell command number. */
|
||||
/** Waiting time in centiseconds if this event is for a removed cell,
|
||||
* or 0 if this event is for adding a cell to the queue. 22 bits can
|
||||
* store more than 11 hours, enough to assume that a circuit with this
|
||||
* delay would long have been closed. */
|
||||
unsigned int waiting_time:22;
|
||||
unsigned int removed:1; /**< 0 for added to, 1 for removed from queue. */
|
||||
unsigned int exitward:1; /**< 0 for app-ward, 1 for exit-ward. */
|
||||
} testing_cell_stats_entry_t;
|
||||
|
||||
typedef struct circuit_t circuit_t;
|
||||
typedef struct origin_circuit_t origin_circuit_t;
|
||||
typedef struct or_circuit_t or_circuit_t;
|
||||
|
||||
/** Largest number of relay_early cells that we can send on a given
|
||||
* circuit. */
|
||||
#define MAX_RELAY_EARLY_CELLS_PER_CIRCUIT 8
|
||||
|
||||
typedef enum path_state_t path_state_t;
|
||||
#define path_state_bitfield_t ENUM_BF(path_state_t)
|
||||
|
||||
#if REND_COOKIE_LEN != DIGEST_LEN
|
||||
#error "The REND_TOKEN_LEN macro assumes REND_COOKIE_LEN == DIGEST_LEN"
|
||||
#endif
|
||||
#define REND_TOKEN_LEN DIGEST_LEN
|
||||
|
||||
/** Convert a circuit subtype to a circuit_t. */
|
||||
#define TO_CIRCUIT(x) (&((x)->base_))
|
||||
|
||||
/** @name Isolation flags
|
||||
|
||||
Ways to isolate client streams
|
||||
|
||||
@{
|
||||
*/
|
||||
/** Isolate based on destination port */
|
||||
#define ISO_DESTPORT (1u<<0)
|
||||
/** Isolate based on destination address */
|
||||
#define ISO_DESTADDR (1u<<1)
|
||||
/** Isolate based on SOCKS authentication */
|
||||
#define ISO_SOCKSAUTH (1u<<2)
|
||||
/** Isolate based on client protocol choice */
|
||||
#define ISO_CLIENTPROTO (1u<<3)
|
||||
/** Isolate based on client address */
|
||||
#define ISO_CLIENTADDR (1u<<4)
|
||||
/** Isolate based on session group (always on). */
|
||||
#define ISO_SESSIONGRP (1u<<5)
|
||||
/** Isolate based on newnym epoch (always on). */
|
||||
#define ISO_NYM_EPOCH (1u<<6)
|
||||
/** Isolate all streams (Internal only). */
|
||||
#define ISO_STREAM (1u<<7)
|
||||
/**@}*/
|
||||
|
||||
/** Default isolation level for ports. */
|
||||
#define ISO_DEFAULT (ISO_CLIENTADDR|ISO_SOCKSAUTH|ISO_SESSIONGRP|ISO_NYM_EPOCH)
|
||||
|
||||
/** Indicates that we haven't yet set a session group on a port_cfg_t. */
|
||||
#define SESSION_GROUP_UNSET -1
|
||||
/** Session group reserved for directory connections */
|
||||
#define SESSION_GROUP_DIRCONN -2
|
||||
/** Session group reserved for resolve requests launched by a controller */
|
||||
#define SESSION_GROUP_CONTROL_RESOLVE -3
|
||||
/** First automatically allocated session group number */
|
||||
#define SESSION_GROUP_FIRST_AUTO -4
|
||||
|
||||
typedef struct port_cfg_t port_cfg_t;
|
||||
typedef struct routerset_t routerset_t;
|
||||
|
||||
/** A magic value for the (Socks|OR|...)Port options below, telling Tor
|
||||
* to pick its own port. */
|
||||
#define CFG_AUTO_PORT 0xc4005e
|
||||
|
||||
typedef struct or_options_t or_options_t;
|
||||
|
||||
typedef struct or_state_t or_state_t;
|
||||
|
||||
#define MAX_SOCKS_ADDR_LEN 256
|
||||
|
||||
/********************************* circuitbuild.c **********************/
|
||||
|
||||
/** How many hops does a general-purpose circuit have by default? */
|
||||
#define DEFAULT_ROUTE_LEN 3
|
||||
|
||||
/* Circuit Build Timeout "public" structures. */
|
||||
|
||||
/** Precision multiplier for the Bw weights */
|
||||
#define BW_WEIGHT_SCALE 10000
|
||||
#define BW_MIN_WEIGHT_SCALE 1
|
||||
#define BW_MAX_WEIGHT_SCALE INT32_MAX
|
||||
|
||||
typedef struct circuit_build_times_t circuit_build_times_t;
|
||||
|
||||
/********************************* config.c ***************************/
|
||||
|
||||
/********************************* connection_edge.c *************************/
|
||||
|
||||
/** Enumerates possible origins of a client-side address mapping. */
|
||||
typedef enum {
|
||||
/** We're remapping this address because the controller told us to. */
|
||||
ADDRMAPSRC_CONTROLLER,
|
||||
/** We're remapping this address because of an AutomapHostsOnResolve
|
||||
* configuration. */
|
||||
ADDRMAPSRC_AUTOMAP,
|
||||
/** We're remapping this address because our configuration (via torrc, the
|
||||
* command line, or a SETCONF command) told us to. */
|
||||
ADDRMAPSRC_TORRC,
|
||||
/** We're remapping this address because we have TrackHostExit configured,
|
||||
* and we want to remember to use the same exit next time. */
|
||||
ADDRMAPSRC_TRACKEXIT,
|
||||
/** We're remapping this address because we got a DNS resolution from a
|
||||
* Tor server that told us what its value was. */
|
||||
ADDRMAPSRC_DNS,
|
||||
|
||||
/** No remapping has occurred. This isn't a possible value for an
|
||||
* addrmap_entry_t; it's used as a null value when we need to answer "Why
|
||||
* did this remapping happen." */
|
||||
ADDRMAPSRC_NONE
|
||||
} addressmap_entry_source_t;
|
||||
#define addressmap_entry_source_bitfield_t ENUM_BF(addressmap_entry_source_t)
|
||||
|
||||
#define WRITE_STATS_INTERVAL (24*60*60)
|
||||
|
||||
/********************************* dirvote.c ************************/
|
||||
|
||||
typedef struct vote_timing_t vote_timing_t;
|
||||
|
||||
/********************************* microdesc.c *************************/
|
||||
|
||||
typedef struct microdesc_cache_t microdesc_cache_t;
|
||||
|
||||
/** The maximum number of non-circuit-build-timeout failures a hidden
|
||||
* service client will tolerate while trying to build a circuit to an
|
||||
* introduction point. */
|
||||
#define MAX_INTRO_POINT_REACHABILITY_FAILURES 5
|
||||
|
||||
/** The minimum and maximum number of distinct INTRODUCE2 cells which a
|
||||
* hidden service's introduction point will receive before it begins to
|
||||
* expire. */
|
||||
#define INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS 16384
|
||||
/* Double the minimum value so the interval is [min, min * 2]. */
|
||||
#define INTRO_POINT_MAX_LIFETIME_INTRODUCTIONS \
|
||||
(INTRO_POINT_MIN_LIFETIME_INTRODUCTIONS * 2)
|
||||
|
||||
/** The minimum number of seconds that an introduction point will last
|
||||
* before expiring due to old age. (If it receives
|
||||
* INTRO_POINT_LIFETIME_INTRODUCTIONS INTRODUCE2 cells, it may expire
|
||||
* sooner.)
|
||||
*
|
||||
* XXX Should this be configurable? */
|
||||
#define INTRO_POINT_LIFETIME_MIN_SECONDS (18*60*60)
|
||||
/** The maximum number of seconds that an introduction point will last
|
||||
* before expiring due to old age.
|
||||
*
|
||||
* XXX Should this be configurable? */
|
||||
#define INTRO_POINT_LIFETIME_MAX_SECONDS (24*60*60)
|
||||
|
||||
/** The maximum number of circuit creation retry we do to an intro point
|
||||
* before giving up. We try to reuse intro point that fails during their
|
||||
* lifetime so this is a hard limit on the amount of time we do that. */
|
||||
#define MAX_INTRO_POINT_CIRCUIT_RETRIES 3
|
||||
|
||||
/********************************* routerlist.c ***************************/
|
||||
|
||||
typedef struct dir_server_t dir_server_t;
|
||||
|
||||
#define RELAY_REQUIRED_MIN_BANDWIDTH (75*1024)
|
||||
#define BRIDGE_REQUIRED_MIN_BANDWIDTH (50*1024)
|
||||
|
||||
#define ROUTER_MAX_DECLARED_BANDWIDTH INT32_MAX
|
||||
|
||||
typedef struct tor_version_t tor_version_t;
|
||||
|
||||
#endif /* !defined(TOR_OR_H) */
|
||||
@@ -0,0 +1,107 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
#ifndef OR_CIRCUIT_ST_H
|
||||
#define OR_CIRCUIT_ST_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
|
||||
#include "core/or/circuit_st.h"
|
||||
#include "core/or/crypt_path_st.h"
|
||||
|
||||
#include "lib/evloop/token_bucket.h"
|
||||
|
||||
struct onion_queue_t;
|
||||
|
||||
/** An or_circuit_t holds information needed to implement a circuit at an
|
||||
* OR. */
|
||||
struct or_circuit_t {
|
||||
circuit_t base_;
|
||||
|
||||
/** Pointer to an entry on the onion queue, if this circuit is waiting for a
|
||||
* chance to give an onionskin to a cpuworker. Used only in onion.c */
|
||||
struct onion_queue_t *onionqueue_entry;
|
||||
/** Pointer to a workqueue entry, if this circuit has given an onionskin to
|
||||
* a cpuworker and is waiting for a response. Used to decide whether it is
|
||||
* safe to free a circuit or if it is still in use by a cpuworker. */
|
||||
struct workqueue_entry_t *workqueue_entry;
|
||||
|
||||
/** The circuit_id used in the previous (backward) hop of this circuit. */
|
||||
circid_t p_circ_id;
|
||||
/** Queue of cells waiting to be transmitted on p_conn. */
|
||||
cell_queue_t p_chan_cells;
|
||||
/** The channel that is previous in this circuit. */
|
||||
channel_t *p_chan;
|
||||
/** Linked list of Exit streams associated with this circuit.
|
||||
*
|
||||
* Note that any updates to this pointer must be followed with
|
||||
* conflux_update_n_streams() to keep the other legs n_streams
|
||||
* in sync. */
|
||||
edge_connection_t *n_streams;
|
||||
/** Linked list of Exit streams associated with this circuit that are
|
||||
* still being resolved.
|
||||
*
|
||||
* Just like with n_streams, any updates to this pointer must
|
||||
* be followed with conflux_update_resolving_streams().
|
||||
*/
|
||||
edge_connection_t *resolving_streams;
|
||||
|
||||
/** Cryptographic state used for encrypting and authenticating relay
|
||||
* cells to and from this hop. */
|
||||
relay_crypto_t crypto;
|
||||
|
||||
/** Points to spliced circuit if purpose is REND_ESTABLISHED, and circuit
|
||||
* is not marked for close. */
|
||||
struct or_circuit_t *rend_splice;
|
||||
|
||||
/** Stores KH for the handshake. */
|
||||
char rend_circ_nonce[DIGEST_LEN];/* KH in tor-spec.txt */
|
||||
|
||||
/** Number of cells which we have discarded because of having no next hop,
|
||||
* despite not recognizing the cell. */
|
||||
uint32_t n_cells_discarded_at_end;
|
||||
|
||||
/** How many more relay_early cells can we send on this circuit, according
|
||||
* to the specification? */
|
||||
unsigned int remaining_relay_early_cells : 4;
|
||||
|
||||
/* We have already received an INTRODUCE1 cell on this circuit. */
|
||||
unsigned int already_received_introduce1 : 1;
|
||||
|
||||
/** If set, this circuit carries HS traffic. Consider it in any HS
|
||||
* statistics. */
|
||||
unsigned int circuit_carries_hs_traffic_stats : 1;
|
||||
|
||||
/** True iff this circuit was made with a CREATE_FAST cell, or a CREATE[2]
|
||||
* cell with a TAP handshake. If this is the case and this is a rend circuit,
|
||||
* this is a v2 circuit, otherwise if this is a rend circuit it's a v3
|
||||
* circuit. */
|
||||
bool used_legacy_circuit_handshake;
|
||||
|
||||
/** Number of cells that were removed from circuit queue; reset every
|
||||
* time when writing buffer stats to disk. */
|
||||
uint32_t processed_cells;
|
||||
|
||||
/** Total time in milliseconds that cells spent in both app-ward and
|
||||
* exit-ward queues of this circuit; reset every time when writing
|
||||
* buffer stats to disk. */
|
||||
uint64_t total_cell_waiting_time;
|
||||
|
||||
/** If set, the DoS defenses are enabled on this circuit meaning that the
|
||||
* introduce2_bucket is initialized and used. */
|
||||
unsigned int introduce2_dos_defense_enabled : 1;
|
||||
/** If set, the DoS defenses were explicitly enabled through the
|
||||
* ESTABLISH_INTRO cell extension. If unset, the consensus is used to learn
|
||||
* if the defenses can be enabled or not. */
|
||||
unsigned int introduce2_dos_defense_explicit : 1;
|
||||
|
||||
/** INTRODUCE2 cell bucket controlling how much can go on this circuit. Only
|
||||
* used if this is a service introduction circuit at the intro point
|
||||
* (purpose = CIRCUIT_PURPOSE_INTRO_POINT). */
|
||||
token_bucket_ctr_t introduce2_bucket;
|
||||
};
|
||||
|
||||
#endif /* !defined(OR_CIRCUIT_ST_H) */
|
||||
@@ -0,0 +1,111 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file or_connection_st.h
|
||||
* @brief OR connection structure.
|
||||
**/
|
||||
|
||||
#ifndef OR_CONNECTION_ST_H
|
||||
#define OR_CONNECTION_ST_H
|
||||
|
||||
#include "core/or/connection_st.h"
|
||||
#include "lib/evloop/token_bucket.h"
|
||||
|
||||
struct tor_tls_t;
|
||||
|
||||
/** Subtype of connection_t for an "OR connection" -- that is, one that speaks
|
||||
* cells over TLS. */
|
||||
struct or_connection_t {
|
||||
connection_t base_;
|
||||
|
||||
/** Hash of the public RSA key for the other side's identity key, or zeroes
|
||||
* if the other side hasn't shown us a valid identity key. */
|
||||
char identity_digest[DIGEST_LEN];
|
||||
|
||||
/** This is the ClientHash value we expect to receive from the
|
||||
* client during the Extended ORPort authentication protocol. We
|
||||
* compute it upon receiving the ClientNonce from the client, and we
|
||||
* compare it with the actual ClientHash value sent by the
|
||||
* client. */
|
||||
char *ext_or_auth_correct_client_hash;
|
||||
/** String carrying the name of the pluggable transport
|
||||
* (e.g. "obfs2") that is obfuscating this connection. If no
|
||||
* pluggable transports are used, it's NULL. */
|
||||
char *ext_or_transport;
|
||||
|
||||
char *nickname; /**< Nickname of OR on other side (if any). */
|
||||
|
||||
struct tor_tls_t *tls; /**< TLS connection state. */
|
||||
int tls_error; /**< Last tor_tls error code. */
|
||||
/** When we last used this conn for any client traffic. If not
|
||||
* recent, we can rate limit it further. */
|
||||
|
||||
/* Channel using this connection */
|
||||
channel_tls_t *chan;
|
||||
|
||||
/**
|
||||
* The "canonical" address and port for this relay's ORPort, if this is
|
||||
* a known relay.
|
||||
*
|
||||
* An ORPort is "canonical" in this sense only if it is the same ORPort
|
||||
* that is listed for this identity in the consensus we have.
|
||||
*
|
||||
* This field may be set on outbound connections for _any_ relay, and on
|
||||
* inbound connections after authentication. If we don't know the relay's
|
||||
* identity, or if we don't have the relay's identity in our consensus, we
|
||||
* leave this address as UNSPEC.
|
||||
**/
|
||||
tor_addr_port_t canonical_orport;
|
||||
|
||||
/** Should this connection be used for extending circuits to the server
|
||||
* matching the <b>identity_digest</b> field? Set to true if we're pretty
|
||||
* sure we aren't getting MITMed, either because we're connected to an
|
||||
* address listed in a server descriptor, or because an authenticated
|
||||
* NETINFO cell listed the address we're connected to as recognized. */
|
||||
unsigned int is_canonical:1;
|
||||
|
||||
/** True iff this is an outgoing connection. */
|
||||
unsigned int is_outgoing:1;
|
||||
unsigned int proxy_type:3; /**< One of PROXY_NONE...PROXY_HAPROXY */
|
||||
unsigned int wide_circ_ids:1;
|
||||
/** True iff a failure on this connection indicates a possible
|
||||
* bootstrapping problem. We set this as true if we notice that this
|
||||
* connection could handle a pending origin circuit, or if we launch it to
|
||||
* handle an origin circuit. */
|
||||
unsigned int potentially_used_for_bootstrapping:1;
|
||||
/** True iff this connection has had its bootstrap failure logged with
|
||||
* control_event_bootstrap_problem. */
|
||||
unsigned int have_noted_bootstrap_problem:1;
|
||||
/** True iff this is a client connection and its address has been put in the
|
||||
* geoip cache and handled by the DoS mitigation subsystem. We use this to
|
||||
* insure we have a coherent count of concurrent connection. */
|
||||
unsigned int tracked_for_dos_mitigation : 1;
|
||||
/** True iff this connection is using a pluggable transport */
|
||||
unsigned int is_pt : 1;
|
||||
|
||||
uint16_t link_proto; /**< What protocol version are we using? 0 for
|
||||
* "none negotiated yet." */
|
||||
uint16_t idle_timeout; /**< How long can this connection sit with no
|
||||
* circuits on it before we close it? Based on
|
||||
* IDLE_CIRCUIT_TIMEOUT_{NON,}CANONICAL and
|
||||
* on is_canonical, randomized. */
|
||||
or_handshake_state_t *handshake_state; /**< If we are setting this connection
|
||||
* up, state information to do so. */
|
||||
|
||||
time_t timestamp_lastempty; /**< When was the outbuf last completely empty?*/
|
||||
|
||||
token_bucket_rw_t bucket; /**< Used for rate limiting when the connection is
|
||||
* in state CONN_OPEN. */
|
||||
|
||||
/*
|
||||
* Count the number of bytes flushed out on this orconn, and the number of
|
||||
* bytes TLS actually sent - used for overhead estimation for scheduling.
|
||||
*/
|
||||
uint64_t bytes_xmitted, bytes_xmitted_by_tls;
|
||||
};
|
||||
|
||||
#endif /* !defined(OR_CONNECTION_ST_H) */
|
||||
@@ -0,0 +1,45 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file or_handshake_certs_st.h
|
||||
* @brief OR handshake certs structure
|
||||
**/
|
||||
|
||||
#ifndef OR_HANDSHAKE_CERTS_ST
|
||||
#define OR_HANDSHAKE_CERTS_ST
|
||||
|
||||
struct tor_x509_cert_t;
|
||||
|
||||
/** Structure to hold all the certificates we've received on an OR connection
|
||||
*/
|
||||
struct or_handshake_certs_t {
|
||||
/** True iff we originated this connection. */
|
||||
int started_here;
|
||||
/** The cert for the 'auth' RSA key that's supposed to sign the AUTHENTICATE
|
||||
* cell. Signed with the RSA identity key. */
|
||||
struct tor_x509_cert_t *auth_cert;
|
||||
/** The cert for the 'link' RSA key that was used to negotiate the TLS
|
||||
* connection. Signed with the RSA identity key. */
|
||||
struct tor_x509_cert_t *link_cert;
|
||||
/** A self-signed identity certificate: the RSA identity key signed
|
||||
* with itself. */
|
||||
struct tor_x509_cert_t *id_cert;
|
||||
/** The Ed25519 signing key, signed with the Ed25519 identity key. */
|
||||
struct tor_cert_st *ed_id_sign;
|
||||
/** A digest of the X509 link certificate for the TLS connection, signed
|
||||
* with the Ed25519 siging key. */
|
||||
struct tor_cert_st *ed_sign_link;
|
||||
/** The Ed25519 authentication key (that's supposed to sign an AUTHENTICATE
|
||||
* cell) , signed with the Ed25519 siging key. */
|
||||
struct tor_cert_st *ed_sign_auth;
|
||||
/** The Ed25519 identity key, crosssigned with the RSA identity key. */
|
||||
uint8_t *ed_rsa_crosscert;
|
||||
/** The length of <b>ed_rsa_crosscert</b> in bytes */
|
||||
size_t ed_rsa_crosscert_len;
|
||||
};
|
||||
|
||||
#endif /* !defined(OR_HANDSHAKE_CERTS_ST) */
|
||||
@@ -0,0 +1,82 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file or_handshake_state_st.h
|
||||
* @brief OR handshake state structure
|
||||
**/
|
||||
|
||||
#ifndef OR_HANDSHAKE_STATE_ST
|
||||
#define OR_HANDSHAKE_STATE_ST
|
||||
|
||||
/** Stores flags and information related to the portion of a v2/v3 Tor OR
|
||||
* connection handshake that happens after the TLS handshake is finished.
|
||||
*/
|
||||
struct or_handshake_state_t {
|
||||
/** When was the VERSIONS cell sent on this connection? Used to get
|
||||
* an estimate of the skew in the returning NETINFO reply. */
|
||||
time_t sent_versions_at;
|
||||
/** True iff we originated this connection */
|
||||
unsigned int started_here : 1;
|
||||
/** True iff we have received and processed a VERSIONS cell. */
|
||||
unsigned int received_versions : 1;
|
||||
/** True iff we have received and processed an AUTH_CHALLENGE cell */
|
||||
unsigned int received_auth_challenge : 1;
|
||||
/** True iff we have received and processed a CERTS cell. */
|
||||
unsigned int received_certs_cell : 1;
|
||||
/** True iff we have received and processed an AUTHENTICATE cell */
|
||||
unsigned int received_authenticate : 1;
|
||||
|
||||
/* True iff we've received valid authentication to some identity. */
|
||||
unsigned int authenticated : 1;
|
||||
unsigned int authenticated_rsa : 1;
|
||||
unsigned int authenticated_ed25519 : 1;
|
||||
|
||||
/* True iff we have sent a netinfo cell */
|
||||
unsigned int sent_netinfo : 1;
|
||||
|
||||
/** The signing->ed25519 link certificate corresponding to the x509
|
||||
* certificate we used on the TLS connection (if this is a server-side
|
||||
* connection). We make a copy of this here to prevent a race condition
|
||||
* caused by TLS context rotation. */
|
||||
struct tor_cert_st *own_link_cert;
|
||||
|
||||
/** True iff we should feed outgoing cells into digest_sent and
|
||||
* digest_received respectively.
|
||||
*
|
||||
* From the server's side of the v3 handshake, we want to capture everything
|
||||
* from the VERSIONS cell through and including the AUTH_CHALLENGE cell.
|
||||
* From the client's, we want to capture everything from the VERSIONS cell
|
||||
* through but *not* including the AUTHENTICATE cell.
|
||||
*
|
||||
* @{ */
|
||||
unsigned int digest_sent_data : 1;
|
||||
unsigned int digest_received_data : 1;
|
||||
/**@}*/
|
||||
|
||||
/** Identity RSA digest that we have received and authenticated for our peer
|
||||
* on this connection. */
|
||||
uint8_t authenticated_rsa_peer_id[DIGEST_LEN];
|
||||
/** Identity Ed25519 public key that we have received and authenticated for
|
||||
* our peer on this connection. */
|
||||
ed25519_public_key_t authenticated_ed25519_peer_id;
|
||||
|
||||
/** Digests of the cells that we have sent or received as part of a V3
|
||||
* handshake. Used for making and checking AUTHENTICATE cells.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
crypto_digest_t *digest_sent;
|
||||
crypto_digest_t *digest_received;
|
||||
/** @} */
|
||||
|
||||
/** Certificates that a connection initiator sent us in a CERTS cell; we're
|
||||
* holding on to them until we get an AUTHENTICATE cell.
|
||||
*/
|
||||
or_handshake_certs_t *certs;
|
||||
};
|
||||
|
||||
#endif /* !defined(OR_HANDSHAKE_STATE_ST) */
|
||||
@@ -0,0 +1,17 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file or_periodic.h
|
||||
* @brief Header for core/or/or_periodic.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_CORE_OR_OR_PERIODIC_H
|
||||
#define TOR_CORE_OR_OR_PERIODIC_H
|
||||
|
||||
void or_register_periodic_events(void);
|
||||
|
||||
#endif /* !defined(TOR_CORE_OR_OR_PERIODIC_H) */
|
||||
@@ -0,0 +1,21 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file or_sys.h
|
||||
* @brief Header for core/or/or_sys.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_CORE_OR_OR_SYS_H
|
||||
#define TOR_CORE_OR_OR_SYS_H
|
||||
|
||||
extern const struct subsys_fns_t sys_or;
|
||||
|
||||
struct pubsub_connector_t;
|
||||
int ocirc_add_pubsub(struct pubsub_connector_t *connector);
|
||||
int orconn_add_pubsub(struct pubsub_connector_t *connector);
|
||||
|
||||
#endif /* !defined(TOR_CORE_OR_OR_SYS_H) */
|
||||
@@ -0,0 +1,103 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file orconn_event.h
|
||||
* \brief Header file for orconn_event.c
|
||||
*
|
||||
* The OR_CONN_STATE_* symbols are here to make it easier for
|
||||
* subscribers to make decisions based on the messages that they
|
||||
* receive.
|
||||
**/
|
||||
|
||||
#ifndef TOR_ORCONN_EVENT_H
|
||||
#define TOR_ORCONN_EVENT_H
|
||||
|
||||
#include "lib/pubsub/pubsub.h"
|
||||
|
||||
/**
|
||||
* @name States of OR connections
|
||||
*
|
||||
* These must be in a partial ordering such that usually no OR
|
||||
* connection will transition from a higher-numbered state to a
|
||||
* lower-numbered one. Code such as bto_update_best() depends on this
|
||||
* ordering to determine the best state it's seen so far.
|
||||
* @{ */
|
||||
#define OR_CONN_STATE_MIN_ 1
|
||||
/** State for a connection to an OR: waiting for connect() to finish. */
|
||||
#define OR_CONN_STATE_CONNECTING 1
|
||||
/** State for a connection to an OR: waiting for proxy handshake to complete */
|
||||
#define OR_CONN_STATE_PROXY_HANDSHAKING 2
|
||||
/** State for an OR connection client: SSL is handshaking, not done
|
||||
* yet. */
|
||||
#define OR_CONN_STATE_TLS_HANDSHAKING 3
|
||||
/** State for a connection to an OR: We're doing a second SSL handshake for
|
||||
* renegotiation purposes. (V2 handshake only.) */
|
||||
#define OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING 4
|
||||
/** State for a connection at an OR: We're waiting for the client to
|
||||
* renegotiate (to indicate a v2 handshake) or send a versions cell (to
|
||||
* indicate a v3 handshake) */
|
||||
#define OR_CONN_STATE_TLS_SERVER_RENEGOTIATING 5
|
||||
/** State for an OR connection: We're done with our SSL handshake, we've done
|
||||
* renegotiation, but we haven't yet negotiated link protocol versions and
|
||||
* sent a netinfo cell. */
|
||||
#define OR_CONN_STATE_OR_HANDSHAKING_V2 6
|
||||
/** State for an OR connection: We're done with our SSL handshake, but we
|
||||
* haven't yet negotiated link protocol versions, done a V3 handshake, and
|
||||
* sent a netinfo cell. */
|
||||
#define OR_CONN_STATE_OR_HANDSHAKING_V3 7
|
||||
/** State for an OR connection: Ready to send/receive cells. */
|
||||
#define OR_CONN_STATE_OPEN 8
|
||||
#define OR_CONN_STATE_MAX_ 8
|
||||
/** @} */
|
||||
|
||||
/** Used to indicate the type of an OR connection event passed to the
|
||||
* controller. The various types are defined in control-spec.txt */
|
||||
typedef enum or_conn_status_event_t {
|
||||
OR_CONN_EVENT_LAUNCHED = 0,
|
||||
OR_CONN_EVENT_CONNECTED = 1,
|
||||
OR_CONN_EVENT_FAILED = 2,
|
||||
OR_CONN_EVENT_CLOSED = 3,
|
||||
OR_CONN_EVENT_NEW = 4,
|
||||
} or_conn_status_event_t;
|
||||
|
||||
/**
|
||||
* Message for orconn state update
|
||||
*
|
||||
* This contains information about internal state changes of
|
||||
* or_connection_t objects. The chan and proxy_type fields are
|
||||
* additional information that a subscriber may need to make
|
||||
* decisions.
|
||||
**/
|
||||
typedef struct orconn_state_msg_t {
|
||||
uint64_t gid; /**< connection's global ID */
|
||||
uint64_t chan; /**< associated channel ID */
|
||||
int proxy_type; /**< connection's proxy type */
|
||||
uint8_t state; /**< new connection state */
|
||||
} orconn_state_msg_t;
|
||||
|
||||
DECLARE_MESSAGE(orconn_state, orconn_state, orconn_state_msg_t *);
|
||||
|
||||
/**
|
||||
* Message for orconn status event
|
||||
*
|
||||
* This contains information that ends up in ORCONN control protocol
|
||||
* events.
|
||||
**/
|
||||
typedef struct orconn_status_msg_t {
|
||||
uint64_t gid; /**< connection's global ID */
|
||||
int status; /**< or_conn_status_event_t */
|
||||
int reason; /**< reason */
|
||||
} orconn_status_msg_t;
|
||||
|
||||
DECLARE_MESSAGE(orconn_status, orconn_status, orconn_status_msg_t *);
|
||||
|
||||
#ifdef ORCONN_EVENT_PRIVATE
|
||||
void orconn_state_publish(orconn_state_msg_t *);
|
||||
void orconn_status_publish(orconn_status_msg_t *);
|
||||
#endif
|
||||
|
||||
#endif /* !defined(TOR_ORCONN_EVENT_H) */
|
||||
@@ -0,0 +1,315 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file origin_circuit_st.h
|
||||
* @brief Origin circuit structure.
|
||||
**/
|
||||
|
||||
#ifndef ORIGIN_CIRCUIT_ST_H
|
||||
#define ORIGIN_CIRCUIT_ST_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
|
||||
#include "core/or/circuit_st.h"
|
||||
|
||||
struct onion_queue_t;
|
||||
|
||||
/**
|
||||
* Describes the circuit building process in simplified terms based
|
||||
* on the path bias accounting state for a circuit.
|
||||
*
|
||||
* NOTE: These state values are enumerated in the order for which we
|
||||
* expect circuits to transition through them. If you add states,
|
||||
* you need to preserve this overall ordering. The various pathbias
|
||||
* state transition and accounting functions (pathbias_mark_* and
|
||||
* pathbias_count_*) contain ordinal comparisons to enforce proper
|
||||
* state transitions for corrections.
|
||||
*
|
||||
* This state machine and the associated logic was created to prevent
|
||||
* miscounting due to unknown cases of circuit reuse. See also tickets
|
||||
* #6475 and #7802.
|
||||
*/
|
||||
enum path_state_t {
|
||||
/** This circuit is "new". It has not yet completed a first hop
|
||||
* or been counted by the path bias code. */
|
||||
PATH_STATE_NEW_CIRC = 0,
|
||||
/** This circuit has completed one/two hops, and has been counted by
|
||||
* the path bias logic. */
|
||||
PATH_STATE_BUILD_ATTEMPTED = 1,
|
||||
/** This circuit has been completely built */
|
||||
PATH_STATE_BUILD_SUCCEEDED = 2,
|
||||
/** Did we try to attach any SOCKS streams or hidserv introductions to
|
||||
* this circuit?
|
||||
*
|
||||
* Note: If we ever implement end-to-end stream timing through test
|
||||
* stream probes (#5707), we must *not* set this for those probes
|
||||
* (or any other automatic streams) because the adversary could
|
||||
* just tag at a later point.
|
||||
*/
|
||||
PATH_STATE_USE_ATTEMPTED = 3,
|
||||
/** Did any SOCKS streams or hidserv introductions actually succeed on
|
||||
* this circuit?
|
||||
*
|
||||
* If any streams detach/fail from this circuit, the code transitions
|
||||
* the circuit back to PATH_STATE_USE_ATTEMPTED to ensure we probe. See
|
||||
* pathbias_mark_use_rollback() for that.
|
||||
*/
|
||||
PATH_STATE_USE_SUCCEEDED = 4,
|
||||
|
||||
/**
|
||||
* This is a special state to indicate that we got a corrupted
|
||||
* relay cell on a circuit and we don't intend to probe it.
|
||||
*/
|
||||
PATH_STATE_USE_FAILED = 5,
|
||||
|
||||
/**
|
||||
* This is a special state to indicate that we already counted
|
||||
* the circuit. Used to guard against potential state machine
|
||||
* violations.
|
||||
*/
|
||||
PATH_STATE_ALREADY_COUNTED = 6,
|
||||
};
|
||||
|
||||
/** An origin_circuit_t holds data necessary to build and use a circuit.
|
||||
*/
|
||||
struct origin_circuit_t {
|
||||
circuit_t base_;
|
||||
|
||||
/** Linked list of AP streams (or EXIT streams if hidden service)
|
||||
* associated with this circuit.
|
||||
*
|
||||
* Any updates to this pointer must be followed with
|
||||
* conflux_update_p_streams(). */
|
||||
edge_connection_t *p_streams;
|
||||
|
||||
/** Smartlist of half-closed streams (half_edge_t*) that still
|
||||
* have pending activity.
|
||||
*
|
||||
* Any updates to this pointer must be followed with
|
||||
* conflux_update_half_streams().
|
||||
*/
|
||||
smartlist_t *half_streams;
|
||||
|
||||
/** Bytes read on this circuit since last call to
|
||||
* control_event_circ_bandwidth_used(). Only used if we're configured
|
||||
* to emit CIRC_BW events. */
|
||||
uint32_t n_read_circ_bw;
|
||||
|
||||
/** Bytes written to on this circuit since last call to
|
||||
* control_event_circ_bandwidth_used(). Only used if we're configured
|
||||
* to emit CIRC_BW events. */
|
||||
uint32_t n_written_circ_bw;
|
||||
|
||||
/** Total known-valid relay cell bytes since last call to
|
||||
* control_event_circ_bandwidth_used(). Only used if we're configured
|
||||
* to emit CIRC_BW events. */
|
||||
uint32_t n_delivered_read_circ_bw;
|
||||
|
||||
/** Total written relay cell bytes since last call to
|
||||
* control_event_circ_bandwidth_used(). Only used if we're configured
|
||||
* to emit CIRC_BW events. */
|
||||
uint32_t n_delivered_written_circ_bw;
|
||||
|
||||
/** Total overhead data in all known-valid relay data cells since last
|
||||
* call to control_event_circ_bandwidth_used(). Only used if we're
|
||||
* configured to emit CIRC_BW events. */
|
||||
uint32_t n_overhead_read_circ_bw;
|
||||
|
||||
/** Total written overhead data in all relay data cells since last call to
|
||||
* control_event_circ_bandwidth_used(). Only used if we're configured
|
||||
* to emit CIRC_BW events. */
|
||||
uint32_t n_overhead_written_circ_bw;
|
||||
|
||||
/** Build state for this circuit. It includes the intended path
|
||||
* length, the chosen exit router, rendezvous information, etc.
|
||||
*/
|
||||
cpath_build_state_t *build_state;
|
||||
/** The doubly-linked list of crypt_path_t entries, one per hop,
|
||||
* for this circuit. This includes ciphers for each hop,
|
||||
* integrity-checking digests for each hop, and package/delivery
|
||||
* windows for each hop.
|
||||
*/
|
||||
crypt_path_t *cpath;
|
||||
|
||||
/** Holds hidden service identifier on either client or service side. This
|
||||
* is for both introduction and rendezvous circuit. */
|
||||
struct hs_ident_circuit_t *hs_ident;
|
||||
|
||||
/** Holds the data that the entry guard system uses to track the
|
||||
* status of the guard this circuit is using, and thereby to determine
|
||||
* whether this circuit can be used. */
|
||||
struct circuit_guard_state_t *guard_state;
|
||||
|
||||
/** Index into global_origin_circuit_list for this circuit. -1 if not
|
||||
* present. */
|
||||
int global_origin_circuit_list_idx;
|
||||
|
||||
/** How many more relay_early cells can we send on this circuit, according
|
||||
* to the specification? */
|
||||
unsigned int remaining_relay_early_cells : 4;
|
||||
|
||||
/** Set if this circuit is insanely old and we already informed the user */
|
||||
unsigned int is_ancient : 1;
|
||||
|
||||
/** Set if this circuit has already been opened. Used to detect
|
||||
* cannibalized circuits. */
|
||||
unsigned int has_opened : 1;
|
||||
|
||||
/**
|
||||
* Path bias state machine. Used to ensure integrity of our
|
||||
* circuit building and usage accounting. See path_state_t
|
||||
* for more details.
|
||||
*/
|
||||
path_state_bitfield_t path_state : 3;
|
||||
|
||||
/* If this flag is set, we should not consider attaching any more
|
||||
* connections to this circuit. */
|
||||
unsigned int unusable_for_new_conns : 1;
|
||||
|
||||
/* If this flag is set (due to padding negotiation failure), we should
|
||||
* not try to negotiate further circuit padding. */
|
||||
unsigned padding_negotiation_failed : 1;
|
||||
|
||||
/**
|
||||
* If this flag is set, then a controller chose the first hop of this
|
||||
* circuit's path, and it's okay to ignore checks that we'd usually do
|
||||
* on this circuit's first hop.
|
||||
*
|
||||
* This flag is distinct from the CIRCUIT_PURPOSE_CONTROLLER purpose: the
|
||||
* purpose indicates _what tor can use the circuit for_. Controller-created
|
||||
* circuits can still have the CIRCUIT_PURPOSE_GENERAL purpose if Tor is
|
||||
* allowed to attach streams to them.
|
||||
*/
|
||||
unsigned first_hop_from_controller : 1;
|
||||
|
||||
/**
|
||||
* If true, this circuit's path has been chosen, in full or in part,
|
||||
* by the controller API, and it's okay to ignore checks that we'd
|
||||
* usually do on the path as whole. */
|
||||
unsigned int any_hop_from_controller : 1;
|
||||
|
||||
/**
|
||||
* Tristate variable to guard against pathbias miscounting
|
||||
* due to circuit purpose transitions changing the decision
|
||||
* of pathbias_should_count(). This variable is informational
|
||||
* only. The current results of pathbias_should_count() are
|
||||
* the official decision for pathbias accounting.
|
||||
*/
|
||||
uint8_t pathbias_shouldcount;
|
||||
#define PATHBIAS_SHOULDCOUNT_UNDECIDED 0
|
||||
#define PATHBIAS_SHOULDCOUNT_IGNORED 1
|
||||
#define PATHBIAS_SHOULDCOUNT_COUNTED 2
|
||||
|
||||
/** For path probing. Store the temporary probe stream ID
|
||||
* for response comparison */
|
||||
streamid_t pathbias_probe_id;
|
||||
|
||||
/** For path probing. Store the temporary probe address nonce
|
||||
* (in host byte order) for response comparison. */
|
||||
uint32_t pathbias_probe_nonce;
|
||||
|
||||
/** This is nonzero iff hs_with_pow_circ is set and there was a valid proof
|
||||
* of work solution associated with this circuit. */
|
||||
uint32_t hs_pow_effort;
|
||||
|
||||
/** Set iff this is a hidden-service circuit for a HS with PoW defenses
|
||||
* enabled, so that we know to be more lenient with timing out the
|
||||
* circuit-build to allow the service time to work through the queue of
|
||||
* requests. */
|
||||
unsigned int hs_with_pow_circ : 1;
|
||||
|
||||
/** Set iff this intro circ required a pow, and it has already queued
|
||||
* the pow with the cpuworker and is awaiting a reply. */
|
||||
unsigned int hs_currently_solving_pow : 1;
|
||||
|
||||
/** Set iff this circuit has been given a relaxed timeout because
|
||||
* no circuits have opened. Used to prevent spamming logs. */
|
||||
unsigned int relaxed_timeout : 1;
|
||||
|
||||
/** What commands were sent over this circuit that decremented the
|
||||
* RELAY_EARLY counter? This is for debugging task 878. */
|
||||
uint8_t relay_early_commands[MAX_RELAY_EARLY_CELLS_PER_CIRCUIT];
|
||||
|
||||
/** How many RELAY_EARLY cells have been sent over this circuit? This is
|
||||
* for debugging task 878, too. */
|
||||
int relay_early_cells_sent;
|
||||
|
||||
/** The next stream_id that will be tried when we're attempting to
|
||||
* construct a new AP stream originating at this circuit. */
|
||||
streamid_t next_stream_id;
|
||||
|
||||
/* The intro key replaces the hidden service's public key if purpose is
|
||||
* S_ESTABLISH_INTRO or S_INTRO, provided that no unversioned rendezvous
|
||||
* descriptor is used. */
|
||||
crypto_pk_t *intro_key;
|
||||
|
||||
/** Quasi-global identifier for this circuit; used for control.c */
|
||||
/* XXXX NM This can get re-used after 2**32 circuits. */
|
||||
uint32_t global_identifier;
|
||||
|
||||
/** True if we have associated one stream to this circuit, thereby setting
|
||||
* the isolation parameters for this circuit. Note that this doesn't
|
||||
* necessarily mean that we've <em>attached</em> any streams to the circuit:
|
||||
* we may only have marked up this circuit during the launch process.
|
||||
*/
|
||||
unsigned int isolation_values_set : 1;
|
||||
/** True iff any stream has <em>ever</em> been attached to this circuit.
|
||||
*
|
||||
* In a better world we could use timestamp_dirty for this, but
|
||||
* timestamp_dirty is far too overloaded at the moment.
|
||||
*/
|
||||
unsigned int isolation_any_streams_attached : 1;
|
||||
|
||||
/** A bitfield of ISO_* flags for every isolation field such that this
|
||||
* circuit has had streams with more than one value for that field
|
||||
* attached to it. */
|
||||
uint8_t isolation_flags_mixed;
|
||||
|
||||
/** @name Isolation parameters
|
||||
*
|
||||
* If any streams have been associated with this circ (isolation_values_set
|
||||
* == 1), and all streams associated with the circuit have had the same
|
||||
* value for some field ((isolation_flags_mixed & ISO_FOO) == 0), then these
|
||||
* elements hold the value for that field.
|
||||
*
|
||||
* Note again that "associated" is not the same as "attached": we
|
||||
* preliminarily associate streams with a circuit while the circuit is being
|
||||
* launched, so that we can tell whether we need to launch more circuits.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
uint8_t client_proto_type;
|
||||
uint8_t client_proto_socksver;
|
||||
uint16_t dest_port;
|
||||
tor_addr_t client_addr;
|
||||
char *dest_address;
|
||||
int session_group;
|
||||
unsigned nym_epoch;
|
||||
size_t socks_username_len;
|
||||
uint8_t socks_password_len;
|
||||
/* Note that the next two values are NOT NUL-terminated; see
|
||||
socks_username_len and socks_password_len for their lengths. */
|
||||
char *socks_username;
|
||||
char *socks_password;
|
||||
/** Global identifier for the first stream attached here; used by
|
||||
* ISO_STREAM. */
|
||||
uint64_t associated_isolated_stream_global_id;
|
||||
/**@}*/
|
||||
/** A list of addr_policy_t for this circuit in particular. Used by
|
||||
* adjust_exit_policy_from_exitpolicy_failure.
|
||||
*/
|
||||
smartlist_t *prepend_policy;
|
||||
|
||||
/** How long do we wait before closing this circuit if it remains
|
||||
* completely idle after it was built, in seconds? This value
|
||||
* is randomized on a per-circuit basis from CircuitsAvailableTimoeut
|
||||
* to 2*CircuitsAvailableTimoeut. */
|
||||
int circuit_idle_timeout;
|
||||
|
||||
};
|
||||
|
||||
#endif /* !defined(ORIGIN_CIRCUIT_ST_H) */
|
||||
@@ -0,0 +1,192 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file policies.h
|
||||
* \brief Header file for policies.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_POLICIES_H
|
||||
#define TOR_POLICIES_H
|
||||
|
||||
/* (length of
|
||||
* "accept6 [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]/128:65535-65535\n"
|
||||
* plus a terminating NUL, rounded up to a nice number.)
|
||||
*/
|
||||
#define POLICY_BUF_LEN 72
|
||||
|
||||
#define EXIT_POLICY_IPV6_ENABLED (1 << 0)
|
||||
#define EXIT_POLICY_REJECT_PRIVATE (1 << 1)
|
||||
#define EXIT_POLICY_ADD_DEFAULT (1 << 2)
|
||||
#define EXIT_POLICY_REJECT_LOCAL_INTERFACES (1 << 3)
|
||||
#define EXIT_POLICY_ADD_REDUCED (1 << 4)
|
||||
#define EXIT_POLICY_OPTION_MAX EXIT_POLICY_ADD_REDUCED
|
||||
/* All options set: used for unit testing */
|
||||
#define EXIT_POLICY_OPTION_ALL ((EXIT_POLICY_OPTION_MAX << 1) - 1)
|
||||
|
||||
typedef enum firewall_connection_t {
|
||||
FIREWALL_OR_CONNECTION = 0,
|
||||
FIREWALL_DIR_CONNECTION = 1
|
||||
} firewall_connection_t;
|
||||
|
||||
typedef int exit_policy_parser_cfg_t;
|
||||
|
||||
/** Outcome of applying an address policy to an address. */
|
||||
typedef enum {
|
||||
/** The address was accepted */
|
||||
ADDR_POLICY_ACCEPTED=0,
|
||||
/** The address was rejected */
|
||||
ADDR_POLICY_REJECTED=-1,
|
||||
/** Part of the address was unknown, but as far as we can tell, it was
|
||||
* accepted. */
|
||||
ADDR_POLICY_PROBABLY_ACCEPTED=1,
|
||||
/** Part of the address was unknown, but as far as we can tell, it was
|
||||
* rejected. */
|
||||
ADDR_POLICY_PROBABLY_REJECTED=2,
|
||||
} addr_policy_result_t;
|
||||
|
||||
/** A single entry in a parsed policy summary, describing a range of ports. */
|
||||
typedef struct short_policy_entry_t {
|
||||
uint16_t min_port, max_port;
|
||||
} short_policy_entry_t;
|
||||
|
||||
/** A short_poliy_t is the parsed version of a policy summary. */
|
||||
typedef struct short_policy_t {
|
||||
/** True if the members of 'entries' are port ranges to accept; false if
|
||||
* they are port ranges to reject */
|
||||
unsigned int is_accept : 1;
|
||||
/** The actual number of values in 'entries'. */
|
||||
unsigned int n_entries : 31;
|
||||
/** An array of 0 or more short_policy_entry_t values, each describing a
|
||||
* range of ports that this policy accepts or rejects (depending on the
|
||||
* value of is_accept).
|
||||
*/
|
||||
short_policy_entry_t entries[FLEXIBLE_ARRAY_MEMBER];
|
||||
} short_policy_t;
|
||||
|
||||
int firewall_is_fascist_or(void);
|
||||
int firewall_is_fascist_dir(void);
|
||||
int reachable_addr_use_ipv6(const or_options_t *options);
|
||||
int reachable_addr_prefer_ipv6_orport(const or_options_t *options);
|
||||
int reachable_addr_prefer_ipv6_dirport(const or_options_t *options);
|
||||
|
||||
int reachable_addr_allows_addr(const tor_addr_t *addr,
|
||||
uint16_t port,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, int pref_ipv6);
|
||||
|
||||
int reachable_addr_allows_rs(const routerstatus_t *rs,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only);
|
||||
int reachable_addr_allows_node(const node_t *node,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only);
|
||||
int reachable_addr_allows_dir_server(const dir_server_t *ds,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only);
|
||||
|
||||
void reachable_addr_choose_from_rs(const routerstatus_t *rs,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, tor_addr_port_t* ap);
|
||||
void reachable_addr_choose_from_ls(const smartlist_t *lspecs,
|
||||
int pref_only, tor_addr_port_t* ap);
|
||||
void reachable_addr_choose_from_node(const node_t *node,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, tor_addr_port_t* ap);
|
||||
void reachable_addr_choose_from_dir_server(const dir_server_t *ds,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, tor_addr_port_t* ap);
|
||||
|
||||
int dir_policy_permits_address(const tor_addr_t *addr);
|
||||
int socks_policy_permits_address(const tor_addr_t *addr);
|
||||
int metrics_policy_permits_address(const tor_addr_t *addr);
|
||||
int authdir_policy_permits_address(const tor_addr_t *addr, uint16_t port);
|
||||
int authdir_policy_valid_address(const tor_addr_t *addr, uint16_t port);
|
||||
int authdir_policy_badexit_address(const tor_addr_t *addr, uint16_t port);
|
||||
int authdir_policy_middleonly_address(const tor_addr_t *addr, uint16_t port);
|
||||
|
||||
int policy_using_default_exit_options(const or_options_t *or_options);
|
||||
int validate_addr_policies(const or_options_t *options, char **msg);
|
||||
void policy_expand_private(smartlist_t **policy);
|
||||
void policy_expand_unspec(smartlist_t **policy);
|
||||
int policies_parse_from_options(const or_options_t *options);
|
||||
|
||||
addr_policy_t *addr_policy_get_canonical_entry(addr_policy_t *ent);
|
||||
int addr_policies_eq(const smartlist_t *a, const smartlist_t *b);
|
||||
MOCK_DECL(addr_policy_result_t, compare_tor_addr_to_addr_policy,
|
||||
(const tor_addr_t *addr, uint16_t port, const smartlist_t *policy));
|
||||
addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr,
|
||||
uint16_t port, const node_t *node);
|
||||
|
||||
int policies_parse_exit_policy_from_options(
|
||||
const or_options_t *or_options,
|
||||
const tor_addr_t *ipv4_local_address,
|
||||
const tor_addr_t *ipv6_local_address,
|
||||
smartlist_t **result);
|
||||
struct config_line_t;
|
||||
int policies_parse_exit_policy(struct config_line_t *cfg, smartlist_t **dest,
|
||||
exit_policy_parser_cfg_t options,
|
||||
const smartlist_t *configured_addresses);
|
||||
void policies_parse_exit_policy_reject_private(
|
||||
smartlist_t **dest,
|
||||
int ipv6_exit,
|
||||
const smartlist_t *configured_addresses,
|
||||
int reject_interface_addresses,
|
||||
int reject_configured_port_addresses);
|
||||
void policies_exit_policy_append_reject_star(smartlist_t **dest);
|
||||
void addr_policy_append_reject_addr(smartlist_t **dest,
|
||||
const tor_addr_t *addr);
|
||||
void addr_policy_append_reject_addr_list(smartlist_t **dest,
|
||||
const smartlist_t *addrs);
|
||||
void policies_set_node_exitpolicy_to_reject_all(node_t *exitrouter);
|
||||
int exit_policy_is_general_exit(smartlist_t *policy);
|
||||
int policy_is_reject_star(const smartlist_t *policy, sa_family_t family,
|
||||
int reject_by_default);
|
||||
char * policy_dump_to_string(const smartlist_t *policy_list,
|
||||
int include_ipv4,
|
||||
int include_ipv6);
|
||||
int getinfo_helper_policies(control_connection_t *conn,
|
||||
const char *question, char **answer,
|
||||
const char **errmsg);
|
||||
int policy_write_item(char *buf, size_t buflen, const addr_policy_t *item,
|
||||
int format_for_desc);
|
||||
|
||||
void addr_policy_list_free_(smartlist_t *p);
|
||||
#define addr_policy_list_free(lst) \
|
||||
FREE_AND_NULL(smartlist_t, addr_policy_list_free_, (lst))
|
||||
void addr_policy_free_(addr_policy_t *p);
|
||||
#define addr_policy_free(p) \
|
||||
FREE_AND_NULL(addr_policy_t, addr_policy_free_, (p))
|
||||
void policies_free_all(void);
|
||||
|
||||
char *policy_summarize(smartlist_t *policy, sa_family_t family);
|
||||
|
||||
short_policy_t *parse_short_policy(const char *summary);
|
||||
char *write_short_policy(const short_policy_t *policy);
|
||||
void short_policy_free_(short_policy_t *policy);
|
||||
#define short_policy_free(p) \
|
||||
FREE_AND_NULL(short_policy_t, short_policy_free_, (p))
|
||||
int short_policy_is_reject_star(const short_policy_t *policy);
|
||||
addr_policy_result_t compare_tor_addr_to_short_policy(
|
||||
const tor_addr_t *addr, uint16_t port,
|
||||
const short_policy_t *policy);
|
||||
|
||||
#ifdef POLICIES_PRIVATE
|
||||
STATIC void append_exit_policy_string(smartlist_t **policy, const char *more);
|
||||
STATIC int reachable_addr_allows(const tor_addr_t *addr,
|
||||
uint16_t port,
|
||||
smartlist_t *firewall_policy,
|
||||
int pref_only, int pref_ipv6);
|
||||
STATIC const tor_addr_port_t * reachable_addr_choose(
|
||||
const tor_addr_port_t *a,
|
||||
const tor_addr_port_t *b,
|
||||
int want_a,
|
||||
firewall_connection_t fw_connection,
|
||||
int pref_only, int pref_ipv6);
|
||||
|
||||
#endif /* defined(POLICIES_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_POLICIES_H) */
|
||||
@@ -0,0 +1,41 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file port_cfg_st.h
|
||||
* @brief Listener port configuration structure.
|
||||
**/
|
||||
|
||||
#ifndef PORT_CFG_ST_H
|
||||
#define PORT_CFG_ST_H
|
||||
|
||||
#include "core/or/entry_port_cfg_st.h"
|
||||
#include "core/or/server_port_cfg_st.h"
|
||||
|
||||
/** Configuration for a single port that we're listening on. */
|
||||
struct port_cfg_t {
|
||||
tor_addr_t addr; /**< The actual IP to listen on, if !is_unix_addr. */
|
||||
int port; /**< The configured port, or CFG_AUTO_PORT to tell Tor to pick its
|
||||
* own port. */
|
||||
uint8_t type; /**< One of CONN_TYPE_*_LISTENER */
|
||||
unsigned is_unix_addr : 1; /**< True iff this is an AF_UNIX address. */
|
||||
|
||||
unsigned is_group_writable : 1;
|
||||
unsigned is_world_writable : 1;
|
||||
unsigned relax_dirmode_check : 1;
|
||||
unsigned explicit_addr : 1; /** Indicate if address was explicitly set or
|
||||
* we are using the default address. */
|
||||
|
||||
entry_port_cfg_t entry_cfg;
|
||||
|
||||
server_port_cfg_t server_cfg;
|
||||
|
||||
/* Unix sockets only: */
|
||||
/** Path for an AF_UNIX address */
|
||||
char unix_addr[FLEXIBLE_ARRAY_MEMBER];
|
||||
};
|
||||
|
||||
#endif /* !defined(PORT_CFG_ST_H) */
|
||||
@@ -0,0 +1,128 @@
|
||||
/* Copyright (c) 2016-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file protover.h
|
||||
* \brief Headers and type declarations for protover.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_PROTOVER_H
|
||||
#define TOR_PROTOVER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "lib/cc/torint.h"
|
||||
#include "lib/testsupport/testsupport.h"
|
||||
struct smartlist_t;
|
||||
|
||||
/** The first version of Tor that included "proto" entries in its
|
||||
* descriptors. Authorities should use this to decide whether to
|
||||
* guess proto lines. */
|
||||
/* This is a guess. */
|
||||
/// C_RUST_COUPLED: src/rust/protover/protover.rs
|
||||
/// `FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS`
|
||||
#define FIRST_TOR_VERSION_TO_ADVERTISE_PROTOCOLS "0.2.9.3-alpha"
|
||||
|
||||
/** The protover version number that signifies ed25519 link handshake support
|
||||
*/
|
||||
#define PROTOVER_LINKAUTH_ED25519_HANDSHAKE 3
|
||||
|
||||
/** The protover version number that signifies extend2 cell support */
|
||||
#define PROTOVER_RELAY_EXTEND2 2
|
||||
/** The protover version number where relays can accept IPv6 connections */
|
||||
#define PROTOVER_RELAY_ACCEPT_IPV6 2
|
||||
/** The protover version number where relays can initiate IPv6 extends */
|
||||
#define PROTOVER_RELAY_EXTEND_IPV6 3
|
||||
/** The protover version number where relays can consider IPv6 connections
|
||||
* canonical */
|
||||
#define PROTOVER_RELAY_CANONICAL_IPV6 3
|
||||
/** The protover version number where relays can accept ntorv3 */
|
||||
#define PROTOVER_RELAY_NTOR_V3 4
|
||||
/** The protover that signals conflux support. */
|
||||
#define PROTOVER_CONFLUX_V1 1
|
||||
|
||||
/** The protover version number that signifies HSv3 intro point support */
|
||||
#define PROTOVER_HS_INTRO_V3 4
|
||||
/** The protover version number where intro points support denial of service
|
||||
* resistance */
|
||||
#define PROTOVER_HS_INTRO_DOS 5
|
||||
|
||||
/** The protover version number that signifies HSv3 rendezvous point support */
|
||||
#define PROTOVER_HS_RENDEZVOUS_POINT_V3 2
|
||||
|
||||
/** The protover version number that signifies HSDir support for HSv3 */
|
||||
#define PROTOVER_HSDIR_V3 2
|
||||
|
||||
/** The protover that signals support for HS circuit setup padding machines */
|
||||
#define PROTOVER_HS_SETUP_PADDING 2
|
||||
|
||||
/** The protover that signals support for congestion control */
|
||||
#define PROTOVER_FLOWCTRL_CC 2
|
||||
|
||||
/** List of recognized subprotocols. */
|
||||
/// C_RUST_COUPLED: src/rust/protover/ffi.rs `translate_to_rust`
|
||||
/// C_RUST_COUPLED: src/rust/protover/protover.rs `Proto`
|
||||
typedef enum protocol_type_t {
|
||||
PRT_LINK = 0,
|
||||
PRT_LINKAUTH = 1,
|
||||
PRT_RELAY = 2,
|
||||
PRT_DIRCACHE = 3,
|
||||
PRT_HSDIR = 4,
|
||||
PRT_HSINTRO = 5,
|
||||
PRT_HSREND = 6,
|
||||
PRT_DESC = 7,
|
||||
PRT_MICRODESC = 8,
|
||||
PRT_CONS = 9,
|
||||
PRT_PADDING = 10,
|
||||
PRT_FLOWCTRL = 11,
|
||||
PRT_CONFLUX = 12,
|
||||
} protocol_type_t;
|
||||
|
||||
bool protover_list_is_invalid(const char *s);
|
||||
const char *protover_get_supported(const protocol_type_t type);
|
||||
int protover_all_supported(const char *s, char **missing);
|
||||
int protover_is_supported_here(protocol_type_t pr, uint32_t ver);
|
||||
const char *protover_get_supported_protocols(void);
|
||||
const char *protover_get_recommended_client_protocols(void);
|
||||
const char *protover_get_recommended_relay_protocols(void);
|
||||
const char *protover_get_required_client_protocols(void);
|
||||
const char *protover_get_required_relay_protocols(void);
|
||||
|
||||
char *protover_compute_vote(const struct smartlist_t *list_of_proto_strings,
|
||||
int threshold);
|
||||
const char *protover_compute_for_old_tor(const char *version);
|
||||
int protocol_list_supports_protocol(const char *list, protocol_type_t tp,
|
||||
uint32_t version);
|
||||
int protocol_list_supports_protocol_or_later(const char *list,
|
||||
protocol_type_t tp,
|
||||
uint32_t version);
|
||||
|
||||
void protover_free_all(void);
|
||||
|
||||
#ifdef PROTOVER_PRIVATE
|
||||
/** Represents a set of ranges of subprotocols of a given type. */
|
||||
typedef struct proto_entry_t {
|
||||
/** The name of the protocol.
|
||||
*
|
||||
* (This needs to handle voting on protocols which
|
||||
* we don't recognize yet, so it's a char* rather than a protocol_type_t.)
|
||||
*/
|
||||
char *name;
|
||||
/** Bitmask of supported protocols. Version 'x' is included in this
|
||||
* entry if and only if bit '1<<x' is set here. */
|
||||
uint64_t bitmask;
|
||||
} proto_entry_t;
|
||||
|
||||
#if defined(TOR_UNIT_TESTS)
|
||||
STATIC struct smartlist_t *parse_protocol_list(const char *s);
|
||||
STATIC char *encode_protocol_list(const struct smartlist_t *sl);
|
||||
STATIC const char *protocol_type_to_str(protocol_type_t pr);
|
||||
STATIC int str_to_protocol_type(const char *s, protocol_type_t *pr_out);
|
||||
STATIC void proto_entry_free_(proto_entry_t *entry);
|
||||
#endif /* defined(TOR_UNIT_TESTS) */
|
||||
|
||||
#define proto_entry_free(entry) \
|
||||
FREE_AND_NULL(proto_entry_t, proto_entry_free_, (entry))
|
||||
|
||||
#endif /* defined(PROTOVER_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_PROTOVER_H) */
|
||||
@@ -0,0 +1,34 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file reasons.h
|
||||
* \brief Header file for reasons.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_REASONS_H
|
||||
#define TOR_REASONS_H
|
||||
|
||||
#include "lib/net/socks5_status.h"
|
||||
enum bandwidth_weight_rule_t;
|
||||
|
||||
const char *stream_end_reason_to_control_string(int reason);
|
||||
const char *stream_end_reason_to_string(int reason);
|
||||
socks5_reply_status_t stream_end_reason_to_socks5_response(int reason);
|
||||
uint8_t errno_to_stream_end_reason(int e);
|
||||
|
||||
const char *orconn_end_reason_to_control_string(int r);
|
||||
int tls_error_to_orconn_end_reason(int e);
|
||||
int errno_to_orconn_end_reason(int e);
|
||||
|
||||
const char *circuit_end_reason_to_control_string(int reason);
|
||||
const char *socks4_response_code_to_string(uint8_t code);
|
||||
const char *socks5_response_code_to_string(uint8_t code);
|
||||
|
||||
const char *bandwidth_weight_rule_to_string(enum bandwidth_weight_rule_t rule);
|
||||
const char *end_reason_to_http_connect_response_line(int endreason);
|
||||
|
||||
#endif /* !defined(TOR_REASONS_H) */
|
||||
@@ -0,0 +1,147 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file relay.h
|
||||
* \brief Header file for relay.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_RELAY_H
|
||||
#define TOR_RELAY_H
|
||||
|
||||
extern uint64_t stats_n_relay_cells_relayed;
|
||||
extern uint64_t stats_n_relay_cells_delivered;
|
||||
extern uint64_t stats_n_circ_max_cell_reached;
|
||||
extern uint64_t stats_n_circ_max_cell_outq_reached;
|
||||
|
||||
const char *relay_command_to_string(uint8_t command);
|
||||
|
||||
void relay_consensus_has_changed(const networkstatus_t *ns);
|
||||
uint32_t relay_get_param_max_circuit_cell_queue_size(
|
||||
const networkstatus_t *ns);
|
||||
int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
cell_direction_t cell_direction);
|
||||
size_t cell_queues_get_total_allocation(void);
|
||||
|
||||
void relay_header_pack(uint8_t *dest, const relay_header_t *src);
|
||||
void relay_header_unpack(relay_header_t *dest, const uint8_t *src);
|
||||
MOCK_DECL(int,
|
||||
relay_send_command_from_edge_,(streamid_t stream_id, circuit_t *circ,
|
||||
uint8_t relay_command, const char *payload,
|
||||
size_t payload_len, crypt_path_t *cpath_layer,
|
||||
const char *filename, int lineno));
|
||||
/* Indicates to relay_send_command_from_edge() that it is a control cell. */
|
||||
#define CONTROL_CELL_ID 0
|
||||
#define relay_send_command_from_edge(stream_id, circ, relay_command, payload, \
|
||||
payload_len, cpath_layer) \
|
||||
relay_send_command_from_edge_((stream_id), (circ), (relay_command), \
|
||||
(payload), (payload_len), (cpath_layer), \
|
||||
__FILE__, __LINE__)
|
||||
int connection_edge_send_command(edge_connection_t *fromconn,
|
||||
uint8_t relay_command, const char *payload,
|
||||
size_t payload_len);
|
||||
int connection_edge_package_raw_inbuf(edge_connection_t *conn,
|
||||
int package_partial,
|
||||
int *max_cells);
|
||||
void connection_edge_consider_sending_sendme(edge_connection_t *conn);
|
||||
void circuit_reset_sendme_randomness(circuit_t *circ);
|
||||
|
||||
extern uint64_t stats_n_data_cells_packaged;
|
||||
extern uint64_t stats_n_data_bytes_packaged;
|
||||
extern uint64_t stats_n_data_cells_received;
|
||||
extern uint64_t stats_n_data_bytes_received;
|
||||
|
||||
extern uint64_t oom_stats_n_bytes_removed_dns;
|
||||
extern uint64_t oom_stats_n_bytes_removed_cell;
|
||||
extern uint64_t oom_stats_n_bytes_removed_geoip;
|
||||
extern uint64_t oom_stats_n_bytes_removed_hsdir;
|
||||
|
||||
void dump_cell_pool_usage(int severity);
|
||||
size_t packed_cell_mem_cost(void);
|
||||
|
||||
int have_been_under_memory_pressure(void);
|
||||
|
||||
/* For channeltls.c */
|
||||
void packed_cell_free_(packed_cell_t *cell);
|
||||
#define packed_cell_free(cell) \
|
||||
FREE_AND_NULL(packed_cell_t, packed_cell_free_, (cell))
|
||||
|
||||
void cell_queue_init(cell_queue_t *queue);
|
||||
void cell_queue_clear(cell_queue_t *queue);
|
||||
void cell_queue_append(cell_queue_t *queue, packed_cell_t *cell);
|
||||
void cell_queue_append_packed_copy(circuit_t *circ, cell_queue_t *queue,
|
||||
int exitward, const cell_t *cell,
|
||||
int wide_circ_ids, int use_stats);
|
||||
|
||||
int append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
|
||||
cell_t *cell, cell_direction_t direction,
|
||||
streamid_t fromstream);
|
||||
|
||||
void destroy_cell_queue_init(destroy_cell_queue_t *queue);
|
||||
void destroy_cell_queue_clear(destroy_cell_queue_t *queue);
|
||||
void destroy_cell_queue_append(destroy_cell_queue_t *queue,
|
||||
circid_t circid,
|
||||
uint8_t reason);
|
||||
|
||||
void channel_unlink_all_circuits(channel_t *chan, smartlist_t *detached_out);
|
||||
MOCK_DECL(int, channel_flush_from_first_active_circuit,
|
||||
(channel_t *chan, int max));
|
||||
MOCK_DECL(int, circuit_package_relay_cell, (cell_t *cell, circuit_t *circ,
|
||||
cell_direction_t cell_direction,
|
||||
crypt_path_t *layer_hint, streamid_t on_stream,
|
||||
const char *filename, int lineno));
|
||||
|
||||
void update_circuit_on_cmux_(circuit_t *circ, cell_direction_t direction,
|
||||
const char *file, int lineno);
|
||||
#define update_circuit_on_cmux(circ, direction) \
|
||||
update_circuit_on_cmux_((circ), (direction), SHORT_FILE__, __LINE__)
|
||||
|
||||
int append_address_to_payload(uint8_t *payload_out, const tor_addr_t *addr);
|
||||
const uint8_t *decode_address_from_payload(tor_addr_t *addr_out,
|
||||
const uint8_t *payload,
|
||||
int payload_len);
|
||||
void circuit_clear_cell_queue(circuit_t *circ, channel_t *chan);
|
||||
|
||||
circid_t packed_cell_get_circid(const packed_cell_t *cell, int wide_circ_ids);
|
||||
uint8_t packed_cell_get_command(const packed_cell_t *cell, int wide_circ_ids);
|
||||
|
||||
#ifdef RELAY_PRIVATE
|
||||
STATIC int
|
||||
handle_relay_cell_command(cell_t *cell, circuit_t *circ,
|
||||
edge_connection_t *conn, crypt_path_t *layer_hint,
|
||||
relay_header_t *rh, int optimistic_data);
|
||||
|
||||
STATIC int connected_cell_parse(const relay_header_t *rh, const cell_t *cell,
|
||||
tor_addr_t *addr_out, int *ttl_out);
|
||||
/** An address-and-ttl tuple as yielded by resolved_cell_parse */
|
||||
typedef struct address_ttl_t {
|
||||
tor_addr_t addr;
|
||||
char *hostname;
|
||||
int ttl;
|
||||
} address_ttl_t;
|
||||
STATIC void address_ttl_free_(address_ttl_t *addr);
|
||||
#define address_ttl_free(addr) \
|
||||
FREE_AND_NULL(address_ttl_t, address_ttl_free_, (addr))
|
||||
STATIC int resolved_cell_parse(const cell_t *cell, const relay_header_t *rh,
|
||||
smartlist_t *addresses_out, int *errcode_out);
|
||||
STATIC int connection_edge_process_resolved_cell(edge_connection_t *conn,
|
||||
const cell_t *cell,
|
||||
const relay_header_t *rh);
|
||||
STATIC packed_cell_t *packed_cell_new(void);
|
||||
STATIC packed_cell_t *cell_queue_pop(cell_queue_t *queue);
|
||||
STATIC destroy_cell_t *destroy_cell_queue_pop(destroy_cell_queue_t *queue);
|
||||
STATIC int cell_queues_check_size(void);
|
||||
STATIC int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
edge_connection_t *conn,
|
||||
crypt_path_t *layer_hint);
|
||||
STATIC size_t get_pad_cell_offset(size_t payload_len);
|
||||
STATIC size_t connection_edge_get_inbuf_bytes_to_package(size_t n_available,
|
||||
int package_partial,
|
||||
circuit_t *on_circuit);
|
||||
|
||||
#endif /* defined(RELAY_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_RELAY_H) */
|
||||
@@ -0,0 +1,38 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file relay_crypto_st.h
|
||||
* @brief Relay-cell encryption state structure.
|
||||
**/
|
||||
|
||||
#ifndef RELAY_CRYPTO_ST_H
|
||||
#define RELAY_CRYPTO_ST_H
|
||||
|
||||
#define crypto_cipher_t aes_cnt_cipher_t
|
||||
struct crypto_cipher_t;
|
||||
struct crypto_digest_t;
|
||||
|
||||
struct relay_crypto_t {
|
||||
/* crypto environments */
|
||||
/** Encryption key and counter for cells heading towards the OR at this
|
||||
* step. */
|
||||
struct crypto_cipher_t *f_crypto;
|
||||
/** Encryption key and counter for cells heading back from the OR at this
|
||||
* step. */
|
||||
struct crypto_cipher_t *b_crypto;
|
||||
|
||||
/** Digest state for cells heading towards the OR at this step. */
|
||||
struct crypto_digest_t *f_digest; /* for integrity checking */
|
||||
/** Digest state for cells heading away from the OR at this step. */
|
||||
struct crypto_digest_t *b_digest;
|
||||
|
||||
/** Digest used for the next SENDME cell if any. */
|
||||
uint8_t sendme_digest[DIGEST_LEN];
|
||||
};
|
||||
#undef crypto_cipher_t
|
||||
|
||||
#endif /* !defined(RELAY_CRYPTO_ST_H) */
|
||||
@@ -0,0 +1,219 @@
|
||||
/* * Copyright (c) 2017-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file scheduler.h
|
||||
* \brief Header file for scheduler*.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_SCHEDULER_H
|
||||
#define TOR_SCHEDULER_H
|
||||
|
||||
#include "core/or/or.h"
|
||||
#include "core/or/channel.h"
|
||||
#include "lib/testsupport/testsupport.h"
|
||||
|
||||
/** Scheduler type, we build an ordered list with those values from the
|
||||
* parsed strings in Schedulers. The reason to do such a thing is so we can
|
||||
* quickly and without parsing strings select the scheduler at anytime. */
|
||||
typedef enum {
|
||||
SCHEDULER_NONE = -1,
|
||||
SCHEDULER_VANILLA = 1,
|
||||
SCHEDULER_KIST = 2,
|
||||
SCHEDULER_KIST_LITE = 3,
|
||||
} scheduler_types_t;
|
||||
|
||||
/**
|
||||
* A scheduler implementation is a collection of function pointers. If you
|
||||
* would like to add a new scheduler called foo, create scheduler_foo.c,
|
||||
* implement at least the mandatory ones, and implement get_foo_scheduler()
|
||||
* that returns a complete scheduler_t for your foo scheduler. See
|
||||
* scheduler_kist.c for an example.
|
||||
*
|
||||
* These function pointers SHOULD NOT be used anywhere outside of the
|
||||
* scheduling source files. The rest of Tor should communicate with the
|
||||
* scheduling system through the functions near the bottom of this file, and
|
||||
* those functions will call into the current scheduler implementation as
|
||||
* necessary.
|
||||
*
|
||||
* If your scheduler doesn't need to implement something (for example: it
|
||||
* doesn't create any state for itself, thus it has nothing to free when Tor
|
||||
* is shutting down), then set that function pointer to NULL.
|
||||
*/
|
||||
typedef struct scheduler_t {
|
||||
/* Scheduler type. This is used for logging when the scheduler is switched
|
||||
* during runtime. */
|
||||
scheduler_types_t type;
|
||||
|
||||
/* (Optional) To be called when we want to prepare a scheduler for use.
|
||||
* Perhaps Tor just started and we are the lucky chosen scheduler, or
|
||||
* perhaps Tor is switching to this scheduler. No matter the case, this is
|
||||
* where we would prepare any state and initialize parameters. You might
|
||||
* think of this as the opposite of free_all(). */
|
||||
void (*init)(void);
|
||||
|
||||
/* (Optional) To be called when we want to tell the scheduler to delete all
|
||||
* of its state (if any). Perhaps Tor is shutting down or perhaps we are
|
||||
* switching schedulers. */
|
||||
void (*free_all)(void);
|
||||
|
||||
/* (Mandatory) Libevent controls the main event loop in Tor, and this is
|
||||
* where we register with libevent the next execution of run_sched_ev [which
|
||||
* ultimately calls run()]. */
|
||||
void (*schedule)(void);
|
||||
|
||||
/* (Mandatory) This is the heart of a scheduler! This is where the
|
||||
* excitement happens! Here libevent has given us the chance to execute, and
|
||||
* we should do whatever we need to do in order to move some cells from
|
||||
* their circuit queues to output buffers in an intelligent manner. We
|
||||
* should do this quickly. When we are done, we'll try to schedule() ourself
|
||||
* if more work needs to be done to setup the next scheduling run. */
|
||||
void (*run)(void);
|
||||
|
||||
/*
|
||||
* External event not related to the scheduler but that can influence it.
|
||||
*/
|
||||
|
||||
/* (Optional) To be called whenever Tor finds out about a new consensus.
|
||||
* First the scheduling system as a whole will react to the new consensus
|
||||
* and change the scheduler if needed. After that, the current scheduler
|
||||
* (which might be new) will call this so it has the chance to react to the
|
||||
* new consensus too. If there's a consensus parameter that your scheduler
|
||||
* wants to keep an eye on, this is where you should check for it. */
|
||||
void (*on_new_consensus)(void);
|
||||
|
||||
/* (Optional) To be called when a channel is being freed. Sometimes channels
|
||||
* go away (for example: the relay on the other end is shutting down). If
|
||||
* the scheduler keeps any channel-specific state and has memory to free
|
||||
* when channels go away, implement this and free it here. */
|
||||
void (*on_channel_free)(const channel_t *);
|
||||
|
||||
/* (Optional) To be called whenever Tor is reloading configuration options.
|
||||
* For example: SIGHUP was issued and Tor is rereading its torrc. A
|
||||
* scheduler should use this as an opportunity to parse and cache torrc
|
||||
* options so that it doesn't have to call get_options() all the time. */
|
||||
void (*on_new_options)(void);
|
||||
} scheduler_t;
|
||||
|
||||
/*****************************************************************************
|
||||
* Globally visible scheduler variables/values
|
||||
*
|
||||
* These are variables/constants that all of Tor should be able to see.
|
||||
*****************************************************************************/
|
||||
|
||||
/* Default interval that KIST runs (in ms). */
|
||||
#define KIST_SCHED_RUN_INTERVAL_DEFAULT 2
|
||||
/* Minimum interval that KIST runs. */
|
||||
#define KIST_SCHED_RUN_INTERVAL_MIN 2
|
||||
/* Maximum interval that KIST runs (in ms). */
|
||||
#define KIST_SCHED_RUN_INTERVAL_MAX 100
|
||||
|
||||
/*****************************************************************************
|
||||
* Globally visible scheduler functions
|
||||
*
|
||||
* These functions are how the rest of Tor communicates with the scheduling
|
||||
* system.
|
||||
*****************************************************************************/
|
||||
|
||||
void scheduler_init(void);
|
||||
void scheduler_free_all(void);
|
||||
void scheduler_conf_changed(void);
|
||||
void scheduler_notify_networkstatus_changed(void);
|
||||
MOCK_DECL(void, scheduler_release_channel, (channel_t *chan));
|
||||
|
||||
/*
|
||||
* Ways for a channel to interact with the scheduling system. A channel only
|
||||
* really knows (i) whether or not it has cells it wants to send, and
|
||||
* (ii) whether or not it would like to write.
|
||||
*/
|
||||
void scheduler_channel_wants_writes(channel_t *chan);
|
||||
MOCK_DECL(void, scheduler_channel_doesnt_want_writes, (channel_t *chan));
|
||||
MOCK_DECL(void, scheduler_channel_has_waiting_cells, (channel_t *chan));
|
||||
|
||||
/*****************************************************************************
|
||||
* Private scheduler functions
|
||||
*
|
||||
* These functions are only visible to the scheduling system, the current
|
||||
* scheduler implementation, and tests.
|
||||
*****************************************************************************/
|
||||
#ifdef SCHEDULER_PRIVATE
|
||||
|
||||
#include "ext/ht.h"
|
||||
|
||||
/*********************************
|
||||
* Defined in scheduler.c
|
||||
*********************************/
|
||||
|
||||
void scheduler_set_channel_state(channel_t *chan, int new_state);
|
||||
const char *get_scheduler_state_string(int scheduler_state);
|
||||
|
||||
/* Triggers a BUG() and extra information with chan if available. */
|
||||
#define SCHED_BUG(cond, chan) \
|
||||
(PREDICT_UNLIKELY(cond) ? \
|
||||
((BUG(cond)) ? (scheduler_bug_occurred(chan), 1) : 0) : 0)
|
||||
|
||||
void scheduler_bug_occurred(const channel_t *chan);
|
||||
|
||||
smartlist_t *get_channels_pending(void);
|
||||
MOCK_DECL(int, scheduler_compare_channels,
|
||||
(const void *c1_v, const void *c2_v));
|
||||
void scheduler_ev_active(void);
|
||||
void scheduler_ev_add(const struct timeval *next_run);
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
extern smartlist_t *channels_pending;
|
||||
extern struct mainloop_event_t *run_sched_ev;
|
||||
extern const scheduler_t *the_scheduler;
|
||||
void scheduler_touch_channel(channel_t *chan);
|
||||
#endif /* defined(TOR_UNIT_TESTS) */
|
||||
|
||||
/*********************************
|
||||
* Defined in scheduler_kist.c
|
||||
*********************************/
|
||||
|
||||
#ifdef SCHEDULER_KIST_PRIVATE
|
||||
|
||||
/* Socket table entry which holds information of a channel's socket and kernel
|
||||
* TCP information. Only used by KIST. */
|
||||
typedef struct socket_table_ent_t {
|
||||
HT_ENTRY(socket_table_ent_t) node;
|
||||
const channel_t *chan;
|
||||
/* Amount written this scheduling run */
|
||||
uint64_t written;
|
||||
/* Amount that can be written this scheduling run */
|
||||
uint64_t limit;
|
||||
/* TCP info from the kernel */
|
||||
uint32_t cwnd;
|
||||
uint32_t unacked;
|
||||
uint32_t mss;
|
||||
uint32_t notsent;
|
||||
} socket_table_ent_t;
|
||||
|
||||
typedef HT_HEAD(outbuf_table_s, outbuf_table_ent_t) outbuf_table_t;
|
||||
|
||||
MOCK_DECL(int, channel_should_write_to_kernel,
|
||||
(outbuf_table_t *table, channel_t *chan));
|
||||
MOCK_DECL(void, channel_write_to_kernel, (channel_t *chan));
|
||||
MOCK_DECL(void, update_socket_info_impl, (socket_table_ent_t *ent));
|
||||
|
||||
int scheduler_can_use_kist(void);
|
||||
void scheduler_kist_set_full_mode(void);
|
||||
void scheduler_kist_set_lite_mode(void);
|
||||
scheduler_t *get_kist_scheduler(void);
|
||||
int kist_scheduler_run_interval(void);
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
extern int32_t sched_run_interval;
|
||||
#endif /* TOR_UNIT_TESTS */
|
||||
|
||||
#endif /* defined(SCHEDULER_KIST_PRIVATE) */
|
||||
|
||||
/*********************************
|
||||
* Defined in scheduler_vanilla.c
|
||||
*********************************/
|
||||
|
||||
scheduler_t *get_vanilla_scheduler(void);
|
||||
|
||||
#endif /* defined(SCHEDULER_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_SCHEDULER_H) */
|
||||
@@ -0,0 +1,83 @@
|
||||
/* Copyright (c) 2019-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file sendme.h
|
||||
* \brief Header file for sendme.c.
|
||||
**/
|
||||
|
||||
#ifndef TOR_SENDME_H
|
||||
#define TOR_SENDME_H
|
||||
|
||||
#include "core/or/edge_connection_st.h"
|
||||
#include "core/or/crypt_path_st.h"
|
||||
#include "core/or/circuit_st.h"
|
||||
|
||||
/* Sending SENDME cell. */
|
||||
void sendme_connection_edge_consider_sending(edge_connection_t *edge_conn);
|
||||
void sendme_circuit_consider_sending(circuit_t *circ,
|
||||
crypt_path_t *layer_hint);
|
||||
|
||||
/* Processing SENDME cell. */
|
||||
int sendme_process_circuit_level(crypt_path_t *layer_hint,
|
||||
circuit_t *circ, const uint8_t *cell_payload,
|
||||
uint16_t cell_payload_len);
|
||||
int sendme_process_circuit_level_impl(crypt_path_t *, circuit_t *);
|
||||
int sendme_process_stream_level(edge_connection_t *conn, circuit_t *circ,
|
||||
uint16_t cell_body_len);
|
||||
|
||||
/* Update deliver window functions. */
|
||||
int sendme_stream_data_received(edge_connection_t *conn);
|
||||
int sendme_circuit_data_received(circuit_t *circ, crypt_path_t *layer_hint);
|
||||
|
||||
/* Update package window functions. */
|
||||
int sendme_note_circuit_data_packaged(circuit_t *circ,
|
||||
crypt_path_t *layer_hint);
|
||||
int sendme_note_stream_data_packaged(edge_connection_t *conn, size_t len);
|
||||
|
||||
/* Record cell digest on circuit. */
|
||||
void sendme_record_cell_digest_on_circ(circuit_t *circ, crypt_path_t *cpath);
|
||||
/* Record cell digest as the SENDME digest. */
|
||||
void sendme_record_received_cell_digest(circuit_t *circ, crypt_path_t *cpath);
|
||||
void sendme_record_sending_cell_digest(circuit_t *circ, crypt_path_t *cpath);
|
||||
|
||||
/* Private section starts. */
|
||||
#ifdef SENDME_PRIVATE
|
||||
|
||||
/* The maximum supported version. Above that value, the cell can't be
|
||||
* recognized as a valid SENDME. */
|
||||
#define SENDME_MAX_SUPPORTED_VERSION 1
|
||||
|
||||
/* The cell version constants for when emitting a cell. */
|
||||
#define SENDME_EMIT_MIN_VERSION_DEFAULT 1
|
||||
#define SENDME_EMIT_MIN_VERSION_MIN 0
|
||||
#define SENDME_EMIT_MIN_VERSION_MAX UINT8_MAX
|
||||
|
||||
/* The cell version constants for when accepting a cell. */
|
||||
#define SENDME_ACCEPT_MIN_VERSION_DEFAULT 0
|
||||
#define SENDME_ACCEPT_MIN_VERSION_MIN 0
|
||||
#define SENDME_ACCEPT_MIN_VERSION_MAX UINT8_MAX
|
||||
|
||||
/*
|
||||
* Unit tests declaractions.
|
||||
*/
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
|
||||
STATIC int get_emit_min_version(void);
|
||||
STATIC int get_accept_min_version(void);
|
||||
|
||||
STATIC bool cell_version_can_be_handled(uint8_t cell_version);
|
||||
|
||||
STATIC ssize_t build_cell_payload_v1(const uint8_t *cell_digest,
|
||||
uint8_t *payload);
|
||||
STATIC bool sendme_is_valid(const circuit_t *circ,
|
||||
const uint8_t *cell_payload,
|
||||
size_t cell_payload_len);
|
||||
STATIC bool circuit_sendme_cell_is_next(int deliver_window,
|
||||
int sendme_inc);
|
||||
|
||||
#endif /* defined(TOR_UNIT_TESTS) */
|
||||
|
||||
#endif /* defined(SENDME_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_SENDME_H) */
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file server_port_cfg_st.h
|
||||
* @brief Configuration structure for server ports.
|
||||
**/
|
||||
|
||||
#ifndef SERVER_PORT_CFG_ST_H
|
||||
#define SERVER_PORT_CFG_ST_H
|
||||
|
||||
struct server_port_cfg_t {
|
||||
/* Server port types (or, dir) only: */
|
||||
unsigned int no_advertise : 1;
|
||||
unsigned int no_listen : 1;
|
||||
unsigned int all_addrs : 1;
|
||||
unsigned int bind_ipv4_only : 1;
|
||||
unsigned int bind_ipv6_only : 1;
|
||||
};
|
||||
|
||||
#endif /* !defined(SERVER_PORT_CFG_ST_H) */
|
||||
@@ -0,0 +1,89 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file socks_request_st.h
|
||||
* @brief Client request structure.
|
||||
**/
|
||||
|
||||
#ifndef SOCKS_REQUEST_ST_H
|
||||
#define SOCKS_REQUEST_ST_H
|
||||
|
||||
#include "lib/net/socks5_status.h"
|
||||
|
||||
#define MAX_SOCKS_REPLY_LEN 1024
|
||||
|
||||
#define SOCKS_NO_AUTH 0x00
|
||||
#define SOCKS_USER_PASS 0x02
|
||||
|
||||
/** Please open a TCP connection to this addr:port. */
|
||||
#define SOCKS_COMMAND_CONNECT 0x01
|
||||
/** Please turn this FQDN into an IP address, privately. */
|
||||
#define SOCKS_COMMAND_RESOLVE 0xF0
|
||||
/** Please turn this IP address into an FQDN, privately. */
|
||||
#define SOCKS_COMMAND_RESOLVE_PTR 0xF1
|
||||
|
||||
/* || 0 is for -Wparentheses-equality (-Wall?) appeasement under clang */
|
||||
#define SOCKS_COMMAND_IS_CONNECT(c) (((c)==SOCKS_COMMAND_CONNECT) || 0)
|
||||
#define SOCKS_COMMAND_IS_RESOLVE(c) ((c)==SOCKS_COMMAND_RESOLVE || \
|
||||
(c)==SOCKS_COMMAND_RESOLVE_PTR)
|
||||
|
||||
/** State of a SOCKS request from a user to an OP. Also used to encode other
|
||||
* information for non-socks user request (such as those on TransPort and
|
||||
* DNSPort) */
|
||||
struct socks_request_t {
|
||||
/** Which version of SOCKS did the client use? One of "0, 4, 5" -- where
|
||||
* 0 means that no socks handshake ever took place, and this is just a
|
||||
* stub connection (e.g. see connection_ap_make_link()). */
|
||||
uint8_t socks_version;
|
||||
/** If using socks5 authentication, which authentication type did we
|
||||
* negotiate? currently we support 0 (no authentication) and 2
|
||||
* (username/password). */
|
||||
uint8_t auth_type;
|
||||
/** What is this stream's goal? One of the SOCKS_COMMAND_* values */
|
||||
uint8_t command;
|
||||
/** Which kind of listener created this stream? */
|
||||
uint8_t listener_type;
|
||||
size_t replylen; /**< Length of <b>reply</b>. */
|
||||
uint8_t reply[MAX_SOCKS_REPLY_LEN]; /**< Write an entry into this string if
|
||||
* we want to specify our own socks reply,
|
||||
* rather than using the default socks4 or
|
||||
* socks5 socks reply. We use this for the
|
||||
* two-stage socks5 handshake.
|
||||
*/
|
||||
char address[MAX_SOCKS_ADDR_LEN]; /**< What address did the client ask to
|
||||
connect to/resolve? */
|
||||
uint16_t port; /**< What port did the client ask to connect to? */
|
||||
unsigned int has_finished : 1; /**< Has the SOCKS handshake finished? Used to
|
||||
* make sure we send back a socks reply for
|
||||
* every connection. */
|
||||
unsigned int got_auth : 1; /**< Have we received any authentication data? */
|
||||
/** If this is set, we will choose "no authentication" instead of
|
||||
* "username/password" authentication if both are offered. Used as input to
|
||||
* parse_socks. */
|
||||
unsigned int socks_prefer_no_auth : 1;
|
||||
/** If set, we can send back the extended error code in the reply. */
|
||||
unsigned int socks_use_extended_errors : 1;
|
||||
/** If non zero, this contains the extended error code that should be used
|
||||
* if the port was configured to use them. */
|
||||
socks5_reply_status_t socks_extended_error_code;
|
||||
|
||||
/** Number of bytes in username; 0 if username is NULL */
|
||||
size_t usernamelen;
|
||||
/** Number of bytes in password; 0 if password is NULL */
|
||||
uint8_t passwordlen;
|
||||
/** The negotiated username value if any (for socks5), or the entire
|
||||
* authentication string (for socks4). This value is NOT nul-terminated;
|
||||
* see usernamelen for its length. */
|
||||
char *username;
|
||||
/** The negotiated password value if any (for socks5). This value is NOT
|
||||
* nul-terminated; see passwordlen for its length. */
|
||||
char *password;
|
||||
|
||||
uint8_t socks5_atyp; /* SOCKS5 address type */
|
||||
};
|
||||
|
||||
#endif /* !defined(SOCKS_REQUEST_ST_H) */
|
||||
@@ -0,0 +1,26 @@
|
||||
/* Copyright (c) 2010-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file status.h
|
||||
* @brief Header for status.c
|
||||
**/
|
||||
|
||||
#ifndef TOR_STATUS_H
|
||||
#define TOR_STATUS_H
|
||||
|
||||
#include "lib/testsupport/testsupport.h"
|
||||
|
||||
void note_connection(bool inbound, const connection_t *conn);
|
||||
void note_circ_closed_for_unrecognized_cells(time_t n_seconds,
|
||||
uint32_t n_cells);
|
||||
|
||||
int log_heartbeat(time_t now);
|
||||
|
||||
#ifdef STATUS_PRIVATE
|
||||
STATIC int count_circuits(void);
|
||||
STATIC char *secs_to_uptime(long secs);
|
||||
STATIC char *bytes_to_usage(uint64_t bytes);
|
||||
#endif
|
||||
|
||||
#endif /* !defined(TOR_STATUS_H) */
|
||||
@@ -0,0 +1,36 @@
|
||||
/* Copyright (c) 2001 Matej Pfajfar.
|
||||
* Copyright (c) 2001-2004, Roger Dingledine.
|
||||
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
||||
* Copyright (c) 2007-2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* @file tor_version_st.h
|
||||
* @brief Parsed Tor version structure.
|
||||
**/
|
||||
|
||||
#ifndef TOR_VERSION_ST_H
|
||||
#define TOR_VERSION_ST_H
|
||||
|
||||
#define MAX_STATUS_TAG_LEN 32
|
||||
/** Structure to hold parsed Tor versions. This is a little messier
|
||||
* than we would like it to be, because we changed version schemes with 0.1.0.
|
||||
*
|
||||
* See version-spec.txt for the whole business.
|
||||
*/
|
||||
struct tor_version_t {
|
||||
int major;
|
||||
int minor;
|
||||
int micro;
|
||||
/** Release status. For version in the post-0.1 format, this is always
|
||||
* VER_RELEASE. */
|
||||
enum { VER_PRE=0, VER_RC=1, VER_RELEASE=2, } status;
|
||||
int patchlevel;
|
||||
char status_tag[MAX_STATUS_TAG_LEN];
|
||||
int svn_revision;
|
||||
|
||||
int git_tag_len;
|
||||
char git_tag[DIGEST_LEN];
|
||||
};
|
||||
|
||||
#endif /* !defined(TOR_VERSION_ST_H) */
|
||||
@@ -0,0 +1,22 @@
|
||||
/* Copyright (c) 2021, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
/**
|
||||
* \file trace_probes_cc.c
|
||||
* \brief The tracing probes for the congestion control subsystem.
|
||||
* Currently, only LTTng-UST probes are available.
|
||||
**/
|
||||
|
||||
#ifndef TOR_TRACE_PROBES_CC_H
|
||||
#define TOR_TRACE_PROBES_CC_H
|
||||
|
||||
#include "lib/trace/events.h"
|
||||
|
||||
/* We only build the following if LTTng instrumentation has been enabled. */
|
||||
#ifdef USE_TRACING_INSTRUMENTATION_LTTNG
|
||||
|
||||
#include "core/or/lttng_cc.inc"
|
||||
|
||||
#endif /* USE_TRACING_INSTRUMENTATION_LTTNG */
|
||||
|
||||
#endif /* !defined(TOR_TRACE_PROBES_CC_H) */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user