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:
jack
2025-09-11 19:08:43 +02:00
committed by GitHub
parent 6e1fb15edf
commit 5f44af19da
1496 changed files with 236105 additions and 108 deletions

12
Frameworks/README.md Normal file
View 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).

View 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>

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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) */

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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) */

View File

@@ -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