#include "or.h"
#define OR_CONN_HIGHWATER (32*1024) |
When adding cells to an OR connection's outbuf, keep adding until the outbuf is at least this long, or we run out of cells.
Referenced by connection_or_flushed_some().
#define OR_CONN_LOWWATER (16*1024) |
Add cells to an OR connection's outbuf whenever the outbuf's data length drops below this size.
Referenced by connection_or_flushed_some().
#define TIME_BEFORE_OR_CONN_IS_TOO_OLD (60*60*24*7) |
How old do we let a connection to an OR get before deciding it's too old for new circuits?
Referenced by connection_or_group_set_badness().
void cell_pack | ( | packed_cell_t * | dst, | |
const cell_t * | src | |||
) |
Pack the cell_t host-order structure src into network-order in the buffer dest. See tor-spec.txt for details about the wire format.
Note that this function doesn't touch dst->next: the caller should set it or clear it as appropriate.
References packed_cell_t::body, CELL_PAYLOAD_SIZE, cell_t::circ_id, cell_t::command, and cell_t::payload.
Referenced by connection_or_write_cell_to_buf(), and packed_cell_copy().
static void cell_unpack | ( | cell_t * | dest, | |
const char * | src | |||
) | [static] |
Unpack the network-order buffer src into a host-order cell_t structure dest.
References CELL_PAYLOAD_SIZE, cell_t::circ_id, cell_t::command, and cell_t::payload.
Referenced by connection_or_process_cells_from_inbuf().
static int connection_fetch_var_cell_from_buf | ( | or_connection_t * | conn, | |
var_cell_t ** | out | |||
) | [static] |
See whether there's a variable-length cell waiting on conn's inbuf. Return values as for fetch_var_cell_from_buf().
References or_connection_t::_base, fetch_var_cell_from_buf(), connection_t::inbuf, and or_connection_t::link_proto.
Referenced by connection_or_process_cells_from_inbuf().
static int connection_init_or_handshake_state | ( | or_connection_t * | conn, | |
int | started_here | |||
) | [static] |
Allocate a new connection handshake state for the connection conn. Return 0 on success, -1 on failure.
References or_connection_t::handshake_state, and or_handshake_state_t::started_here.
Referenced by connection_tls_finish_handshake().
static int connection_or_check_valid_tls_handshake | ( | or_connection_t * | conn, | |
int | started_here, | |||
char * | digest_rcvd_out | |||
) | [static] |
Conn just completed its handshake. Return 0 if all is well, and return -1 if he is lying, broken, or otherwise something is wrong.
If we initiated this connection (started_here is true), make sure the other side sent a correctly formed certificate. If I initiated the connection, make sure it's the right guy.
Otherwise (if we _didn't_ initiate this connection), it's okay for the certificate to be weird or absent.
If we return 0, and the certificate is as expected, write a hash of the identity key into digest_rcvd, which must have DIGEST_LEN space in it. (If we return -1 this buffer is undefined.) If the certificate is invalid or missing on an incoming connection, we return 0 and set digest_rcvd to DIGEST_LEN 0 bytes.
As side effects, 1) Set conn->circ_id_type according to tor-spec.txt. 2) If we're an authdirserver and we initiated the connection: drop all descriptors that claim to be on that IP/port but that aren't this guy; and note that this guy is reachable.
References or_connection_t::_base, connection_t::address, authdir_mode_tests_reachability(), base16_encode(), or_connection_t::circ_id_type, CIRC_ID_TYPE_HIGHER, CIRC_ID_TYPE_LOWER, CIRC_ID_TYPE_NEITHER, connection_or_set_identity_digest(), control_event_bootstrap_problem(), control_event_or_conn_status(), crypto_free_pk_env(), crypto_pk_cmp_keys(), crypto_pk_get_digest(), DIGEST_LEN, dirserv_orconn_tls_done(), entry_guard_register_connect_status(), get_identity_key(), get_options(), HEX_DIGEST_LEN, or_connection_t::identity_digest, LD_HANDSHAKE, or_connection_t::nickname, connection_t::port, safe_str_client(), server_mode(), or_connection_t::tls, tor_assert, tor_digest_is_zero(), tor_free, tor_tls_peer_has_cert(), and tor_tls_verify().
Referenced by connection_tls_finish_handshake().
void connection_or_clear_identity_map | ( | void | ) |
Remove all entries from the identity-to-orconn map, and clear all identities in OR conns.
References CONN_TYPE_OR, DIGEST_LEN, get_connection_array(), and TO_OR_CONN().
Referenced by connection_free_all().
or_connection_t* connection_or_connect | ( | const tor_addr_t * | _addr, | |
uint16_t | port, | |||
const char * | id_digest | |||
) |
Launch a new OR connection to addr:port and expect to handshake with an OR with identity digest id_digest.
If id_digest is me, do nothing. If we're already connected to it, return that connection. If the connect() is in progress, set the new conn's state to 'connecting' and return it. If connect() succeeds, call connection_tls_start_handshake() on it.
This function is called from router_retry_connections(), for ORs connecting to ORs, and circuit_establish_circuit(), for OPs connecting to ORs.
Return the launched conn, or NULL if it failed.
References or_connection_t::_base, connection_t::address, connection_connect(), connection_free(), connection_or_connect_failed(), connection_or_finished_connecting(), connection_or_init_conn_from_address(), connection_watch_events(), control_event_or_conn_status(), entry_guard_register_connect_status(), errno_to_orconn_end_reason(), get_options(), or_options_t::HttpsProxy, or_options_t::HttpsProxyAddr, or_options_t::HttpsProxyPort, or_connection_t::identity_digest, LD_PROTOCOL, OR_CONN_STATE_CONNECTING, or_connection_new(), router_digest_is_me(), server_mode(), or_options_t::Socks4Proxy, or_options_t::Socks4ProxyAddr, or_options_t::Socks4ProxyPort, or_options_t::Socks5Proxy, or_options_t::Socks5ProxyAddr, or_options_t::Socks5ProxyPort, connection_t::state, TO_CONN, tor_addr_copy(), and tor_assert.
Referenced by circuit_extend(), circuit_handle_first_hop(), and dirserv_single_reachability_test().
void connection_or_connect_failed | ( | or_connection_t * | conn, | |
int | reason, | |||
const char * | msg | |||
) |
conn is in the 'connecting' state, and it failed to complete a TCP connection. Send notifications appropriately.
reason specifies the or_conn_end_reason for the failure; msg specifies the strerror-style error message.
References authdir_mode_tests_reachability(), control_event_bootstrap_problem(), control_event_or_conn_status(), and get_options().
Referenced by connection_handle_read_impl(), connection_handle_write_impl(), connection_or_connect(), and run_connection_housekeeping().
int connection_or_digest_is_known_relay | ( | const char * | id_digest | ) |
Return 1 if identity digest id_digest is known to be a currently or recently running relay. Otherwise return 0.
References router_get_by_digest(), and router_get_consensus_status_by_id().
Referenced by connection_exit_begin_conn(), and connection_or_init_conn_from_address().
int connection_or_finished_connecting | ( | or_connection_t * | or_conn | ) |
Connected handler for OR connections: begin the TLS handshake.
References connection_t::address, connection_proxy_connect(), connection_start_reading(), connection_tls_start_handshake(), control_event_bootstrap(), get_options(), LD_HANDSHAKE, OR_CONN_STATE_CONNECTING, OR_CONN_STATE_PROXY_HANDSHAKING, connection_t::port, connection_t::state, TO_CONN, and tor_assert.
Referenced by connection_finished_connecting(), and connection_or_connect().
int connection_or_finished_flushing | ( | or_connection_t * | conn | ) |
Connection conn has finished writing and has no bytes left on its outbuf.
Otherwise it's in state "open": stop writing and return.
If conn is broken, mark it for close and return -1, else return 0.
References or_connection_t::_base, assert_connection_ok(), connection_stop_writing(), LD_BUG, OR_CONN_STATE_OPEN, OR_CONN_STATE_OR_HANDSHAKING, OR_CONN_STATE_PROXY_HANDSHAKING, connection_t::state, TO_CONN, tor_assert, and tor_fragile_assert.
Referenced by connection_finished_flushing().
int connection_or_flushed_some | ( | or_connection_t * | conn | ) |
Called whenever we have flushed some data on an or_conn: add more data from active circuits.
References or_connection_t::_base, or_connection_t::active_circuits, approx_time(), buf_datalen(), CELL_NETWORK_SIZE, connection_or_flush_from_first_active_circuit(), OR_CONN_HIGHWATER, OR_CONN_LOWWATER, and connection_t::outbuf.
Referenced by connection_flushed_some().
or_connection_t* connection_or_get_for_extend | ( | const char * | digest, | |
const tor_addr_t * | target_addr, | |||
const char ** | msg_out, | |||
int * | launch_out | |||
) |
Return the OR connection we should use to extend a circuit to the router whose identity is digest, and whose address we believe (or have been told in an extend cell) is target_addr. If there is no good connection, set *msg_out to a message describing the connection's state and our next action, and set launch_out to a boolean for whether we should launch a new connection or not.
References or_connection_t::_base, approx_time(), CONN_TYPE_OR, connection_or_is_better(), DIGEST_LEN, digestmap_get(), or_connection_t::identity_digest, or_connection_t::is_bad_for_new_circs, or_connection_t::is_canonical, or_connection_t::link_proto, connection_t::magic, connection_t::marked_for_close, or_connection_t::next_with_same_id, OR_CONN_STATE_OPEN, orconn_identity_map, or_connection_t::real_addr, connection_t::state, tor_addr_compare(), tor_assert, and connection_t::type.
Referenced by circuit_extend(), and circuit_handle_first_hop().
static void connection_or_group_set_badness | ( | or_connection_t * | head | ) | [static] |
Given the head of the linked list for all the or_connections with a given identity, set elements of that list as is_bad_for_new_circs() as appropriate. Helper for connection_or_set_bad_connections().
References or_connection_t::_base, connection_t::address, connection_or_is_better(), or_connection_t::is_bad_for_new_circs, or_connection_t::is_canonical, LD_OR, connection_t::marked_for_close, or_connection_t::next_with_same_id, OR_CONN_STATE_OPEN, connection_t::port, or_connection_t::real_addr, connection_t::s, connection_t::state, TIME_BEFORE_OR_CONN_IS_TOO_OLD, connection_t::timestamp_created, and tor_addr_compare().
Referenced by connection_or_set_bad_connections().
static void connection_or_init_conn_from_address | ( | or_connection_t * | conn, | |
const tor_addr_t * | addr, | |||
uint16_t | port, | |||
const char * | id_digest, | |||
int | started_here | |||
) | [static] |
If we don't necessarily know the router we're connecting to, but we have an addr/port/id_digest, then fill in as much as we can. Start by checking to see if this describes a router we know.
References or_connection_t::_base, routerinfo_t::addr, connection_t::addr, routerinfo_t::address, connection_t::address, or_connection_t::bandwidthburst, or_options_t::BandwidthBurst, or_connection_t::bandwidthrate, or_options_t::BandwidthRate, base16_encode(), connection_or_digest_is_known_relay(), connection_or_set_identity_digest(), DIGEST_LEN, dirserv_get_nickname_by_digest(), get_options(), HEX_DIGEST_LEN, or_connection_t::identity_digest, or_connection_t::is_canonical, networkstatus_get_param(), routerinfo_t::nickname, or_connection_t::nickname, routerinfo_t::or_port, or_options_t::PerConnBWBurst, or_options_t::PerConnBWRate, connection_t::port, or_connection_t::read_bucket, or_connection_t::real_addr, router_get_by_digest(), tor_addr_copy(), tor_addr_eq_ipv4h(), tor_addr_from_ipv4h, tor_dup_addr(), tor_free, and or_connection_t::write_bucket.
Referenced by connection_or_connect(), and connection_tls_finish_handshake().
static int connection_or_is_better | ( | time_t | now, | |
const or_connection_t * | a, | |||
const or_connection_t * | b, | |||
int | forgive_new_connections | |||
) | [static] |
Return true iff a is "better" than b for new circuits.
A more canonical connection is always better than a less canonical connection. That aside, a connection is better if it has circuits and the other does not, or if it was created more recently.
Requires that both input connections are open; not is_bad_for_new_circs, and not impossibly non-canonical.
If forgive_new_connections is true, then we do not call abetter than b simply because b has no circuits, unless b is also relatively old.
Do not definitively deprecate a new connection with no circuits on it until this much time has passed.
References or_connection_t::_base, or_connection_t::is_canonical, or_connection_t::n_circuits, and connection_t::timestamp_created.
Referenced by connection_or_get_for_extend(), and connection_or_group_set_badness().
int connection_or_nonopen_was_started_here | ( | or_connection_t * | conn | ) |
Return 1 if we initiated this connection, or 0 if it started out as an incoming connection.
References or_connection_t::_base, CONN_TYPE_OR, or_connection_t::handshake_state, or_handshake_state_t::started_here, or_connection_t::tls, tor_assert, tor_tls_is_server(), and connection_t::type.
Referenced by connection_about_to_close_connection(), connection_or_set_state_open(), connection_tls_finish_handshake(), and onionskin_answer().
static int connection_or_process_cells_from_inbuf | ( | or_connection_t * | conn | ) | [static] |
Process cells from conn's inbuf.
Loop: while inbuf contains a cell, pull it off the inbuf, unpack it, and hand it to command_process_cell().
Always return 0.
References or_connection_t::_base, buf_datalen(), CELL_NETWORK_SIZE, cell_unpack(), circ_times, circuit_build_times_network_is_live(), command_process_cell(), command_process_var_cell(), connection_fetch_from_buf(), connection_fetch_var_cell_from_buf(), connection_t::inbuf, LD_OR, connection_t::s, or_connection_t::tls, TO_CONN, tor_tls_get_pending_bytes(), and var_cell_free().
Referenced by connection_or_process_inbuf().
int connection_or_process_inbuf | ( | or_connection_t * | conn | ) |
Handle any new bytes that have come in on connection conn. If conn is in 'open' state, hand it to connection_or_process_cells_from_inbuf() (else do nothing).
References or_connection_t::_base, connection_or_process_cells_from_inbuf(), connection_read_proxy_handshake(), connection_tls_start_handshake(), OR_CONN_STATE_OPEN, OR_CONN_STATE_OR_HANDSHAKING, OR_CONN_STATE_PROXY_HANDSHAKING, connection_t::state, TO_CONN, and tor_assert.
Referenced by connection_process_inbuf().
int connection_or_reached_eof | ( | or_connection_t * | conn | ) |
We've received an EOF from conn. Mark it for close and return.
References LD_OR, and TO_CONN.
Referenced by connection_reached_eof().
void connection_or_remove_from_identity_map | ( | or_connection_t * | conn | ) |
If conn is listed in orconn_identity_map, remove it, and clear conn->identity_digest. Otherwise do nothing.
References DIGEST_LEN, digestmap_get(), digestmap_remove(), digestmap_set(), or_connection_t::identity_digest, LD_BUG, or_connection_t::next_with_same_id, or_connection_t::nickname, orconn_identity_map, tor_assert, and tor_digest_is_zero().
Referenced by _connection_free(), connection_free(), connection_or_set_identity_digest(), and connection_unlink().
int connection_or_send_destroy | ( | circid_t | circ_id, | |
or_connection_t * | conn, | |||
int | reason | |||
) |
Write a destroy cell with circ ID circ_id and reason reason onto OR connection conn. Don't perform range-checking on reason: we may want to propagate reasons from other cells.
Return 0.
References cell_t::circ_id, cell_t::command, connection_or_write_cell_to_buf(), LD_OR, cell_t::payload, and tor_assert.
Referenced by _circuit_mark_for_close(), command_process_create_cell(), and connection_edge_process_relay_cell().
int connection_or_send_netinfo | ( | or_connection_t * | conn | ) |
Send a NETINFO cell on conn, telling the other server what we know about their address, our address, and the current time.
References or_connection_t::_base, routerinfo_t::addr, connection_t::addr, append_address_to_payload(), cell_t::command, connection_or_write_cell_to_buf(), cell_t::payload, router_get_my_routerinfo(), set_uint32(), and tor_addr_from_ipv4h.
Referenced by command_process_versions_cell().
static int connection_or_send_versions | ( | or_connection_t * | conn | ) | [static] |
Send a VERSIONS cell on conn, telling the other host about the link protocol versions that this Tor can support.
References var_cell_t::command, connection_or_write_var_cell_to_buf(), or_connection_t::handshake_state, n_or_protocol_versions, or_protocol_versions, var_cell_t::payload, or_handshake_state_t::sent_versions_at, set_uint16(), tor_assert, var_cell_free(), and var_cell_new().
Referenced by connection_tls_finish_handshake().
void connection_or_set_bad_connections | ( | void | ) |
Go through all the OR connections, and set the is_bad_for_new_circs flag on:
See connection_or_is_better() for our idea of what makes one OR connection better than another.
References connection_or_group_set_badness(), and orconn_identity_map.
Referenced by run_scheduled_events().
static void connection_or_set_identity_digest | ( | or_connection_t * | conn, | |
const char * | digest | |||
) | [static] |
Change conn->identity_digest to digest, and add conn into orconn_digest_map.
References connection_or_remove_from_identity_map(), DIGEST_LEN, digestmap_new(), digestmap_set(), or_connection_t::identity_digest, or_connection_t::next_with_same_id, orconn_identity_map, tor_assert, and tor_digest_is_zero().
Referenced by connection_or_check_valid_tls_handshake(), and connection_or_init_conn_from_address().
int connection_or_set_state_open | ( | or_connection_t * | conn | ) |
Set conn's state to OR_CONN_STATE_OPEN, and tell other subsystems as appropriate. Called when we are done with all TLS and OR handshaking.
References or_connection_t::_base, circ_times, circuit_build_times_network_is_live(), circuit_n_conn_done(), connection_or_nonopen_was_started_here(), connection_start_reading(), control_event_or_conn_status(), entry_guard_register_connect_status(), GEOIP_CLIENT_CONNECT, geoip_note_client_seen(), or_connection_t::handshake_state, or_connection_t::identity_digest, LD_OR, OR_CONN_STATE_OPEN, or_handshake_state_free(), rep_hist_note_connect_succeeded(), router_get_by_digest(), router_set_status(), connection_t::state, TO_CONN, tor_addr_family(), and tor_addr_to_ipv4h().
Referenced by command_process_netinfo_cell(), and connection_tls_finish_handshake().
static void connection_or_tls_renegotiated_cb | ( | tor_tls_t * | tls, | |
void * | _conn | |||
) | [static] |
Invoked on the server side from inside tor_tls_read() when the server gets a successful TLS renegotiation from the client.
References connection_tls_finish_handshake(), TO_CONN, tor_tls_block_renegotiation(), and tor_tls_set_renegotiate_callback().
Referenced by connection_tls_continue_handshake().
void connection_or_write_cell_to_buf | ( | const cell_t * | cell, | |
or_connection_t * | conn | |||
) |
Pack cell into wire-format, and write it onto conn's outbuf. For cells that use or affect a circuit, this should only be called by connection_or_flush_from_first_active_circuit().
References approx_time(), packed_cell_t::body, CELL_NETWORK_SIZE, cell_pack(), cell_t::command, or_connection_t::timestamp_last_added_nonpadding, TO_CONN, and tor_assert.
Referenced by connection_or_send_destroy(), connection_or_send_netinfo(), and run_connection_housekeeping().
void connection_or_write_var_cell_to_buf | ( | const var_cell_t * | cell, | |
or_connection_t * | conn | |||
) |
Pack a variable-length cell into wire-format, and write it onto conn's outbuf. Right now, this DOES NOT support cells that affect a circuit.
References approx_time(), var_cell_t::command, var_cell_t::payload, var_cell_t::payload_len, or_connection_t::timestamp_last_added_nonpadding, TO_CONN, tor_assert, VAR_CELL_HEADER_SIZE, and var_cell_pack_header().
Referenced by connection_or_send_versions().
int connection_tls_continue_handshake | ( | or_connection_t * | conn | ) |
Move forward with the tls handshake. If it finishes, hand conn to connection_tls_finish_handshake().
Return -1 if conn is broken, else return 0.
References or_connection_t::_base, CASE_TOR_TLS_ERROR_ANY, connection_or_tls_renegotiated_cb(), connection_start_reading(), connection_start_writing(), connection_stop_writing(), connection_tls_finish_handshake(), LD_OR, OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING, OR_CONN_STATE_TLS_HANDSHAKING, OR_CONN_STATE_TLS_SERVER_RENEGOTIATING, connection_t::state, or_connection_t::tls, TO_CONN, tor_assert, tor_tls_err_to_string(), tor_tls_handshake(), tor_tls_is_server(), tor_tls_renegotiate(), tor_tls_set_renegotiate_callback(), and tor_tls_used_v1_handshake().
Referenced by connection_handle_write_impl(), connection_read_to_buf(), and connection_tls_start_handshake().
static int connection_tls_finish_handshake | ( | or_connection_t * | conn | ) | [static] |
The tls handshake is finished.
Make sure we are happy with the person we just handshaked with.
If he initiated the connection, make sure he's not already connected, then initialize conn from the information in router.
If all is successful, call circuit_n_conn_done() to handle events that have been pending on the <tls handshake completion. Also set the directory to be dirty (only matters if I'm an authdirserver).
References or_connection_t::_base, connection_t::addr, connection_t::address, circ_times, circuit_build_times_network_is_live(), connection_init_or_handshake_state(), connection_or_check_valid_tls_handshake(), connection_or_init_conn_from_address(), connection_or_nonopen_was_started_here(), connection_or_send_versions(), connection_or_set_state_open(), DIGEST_LEN, directory_set_dirty(), LD_HANDSHAKE, or_connection_t::link_proto, OR_CONN_STATE_OR_HANDSHAKING, connection_t::port, safe_str_client(), connection_t::state, or_connection_t::tls, tor_tls_block_renegotiation(), and tor_tls_used_v1_handshake().
Referenced by connection_or_tls_renegotiated_cb(), and connection_tls_continue_handshake().
int connection_tls_start_handshake | ( | or_connection_t * | conn, | |
int | receiving | |||
) |
Begin the tls handshake with conn. receiving is 0 if we initiated the connection, else it's 1.
Assign a new tls object to conn->tls, begin reading on conn, and pass conn to connection_tls_continue_handshake().
Return -1 if conn is broken, else return 0.
References or_connection_t::_base, connection_t::address, connection_start_reading(), connection_tls_continue_handshake(), escaped_safe_str(), LD_BUG, LD_HANDSHAKE, note_crypto_pk_op(), OR_CONN_STATE_TLS_HANDSHAKING, connection_t::s, connection_t::state, or_connection_t::tls, TO_CONN, tor_tls_new(), and tor_tls_set_logged_address().
Referenced by connection_init_accepted_conn(), connection_or_finished_connecting(), and connection_or_process_inbuf().
int is_or_protocol_version_known | ( | uint16_t | v | ) |
Return true iff v is a link protocol version that this Tor implementation believes it can support.
References n_or_protocol_versions, and or_protocol_versions.
Referenced by command_process_versions_cell().
void or_handshake_state_free | ( | or_handshake_state_t * | state | ) |
Free all storage held by state.
References tor_free.
Referenced by _connection_free(), and connection_or_set_state_open().
void var_cell_free | ( | var_cell_t * | cell | ) |
Release all space held by cell.
References tor_free.
Referenced by connection_or_process_cells_from_inbuf(), and connection_or_send_versions().
var_cell_t* var_cell_new | ( | uint16_t | payload_len | ) |
Allocate and return a new var_cell_t with payload_len bytes of payload space.
References var_cell_t::circ_id, var_cell_t::command, and var_cell_t::payload_len.
Referenced by connection_or_send_versions(), and fetch_var_cell_from_buf().
void var_cell_pack_header | ( | const var_cell_t * | cell, | |
char * | hdr_out | |||
) |
Write the header of cell into the first VAR_CELL_HEADER_SIZE bytes of hdr_out.
References var_cell_t::circ_id, var_cell_t::command, var_cell_t::payload_len, and set_uint16().
Referenced by connection_or_write_var_cell_to_buf().
const int n_or_protocol_versions [static] |
Initial value:
(int)( sizeof(or_protocol_versions)/sizeof(uint16_t) )
Referenced by connection_or_send_versions(), and is_or_protocol_version_known().
const uint16_t or_protocol_versions[] = { 1, 2 } [static] |
Array of recognized link protocol versions.
Referenced by connection_or_send_versions(), and is_or_protocol_version_known().
digestmap_t* orconn_identity_map = NULL [static] |
Map from identity digest of connected OR or desired OR to a connection_t with that identity digest. If there is more than one such connection_t, they form a linked list, with next_with_same_id as the next pointer.
Referenced by connection_or_get_for_extend(), connection_or_remove_from_identity_map(), connection_or_set_bad_connections(), and connection_or_set_identity_digest().