connection_or.c File Reference

Functions to handle OR connections, TLS handshaking, and cells on the network. More...

#include "or.h"

Defines

#define OR_CONN_HIGHWATER   (32*1024)
#define OR_CONN_LOWWATER   (16*1024)
#define NEW_CONN_GRACE_PERIOD   (15*60)
#define TIME_BEFORE_OR_CONN_IS_TOO_OLD   (60*60*24*7)

Functions

static int connection_tls_finish_handshake (or_connection_t *conn)
static int connection_or_process_cells_from_inbuf (or_connection_t *conn)
static int connection_or_send_versions (or_connection_t *conn)
static int connection_init_or_handshake_state (or_connection_t *conn, int started_here)
static int connection_or_check_valid_tls_handshake (or_connection_t *conn, int started_here, char *digest_rcvd_out)
void connection_or_remove_from_identity_map (or_connection_t *conn)
void connection_or_clear_identity_map (void)
static void connection_or_set_identity_digest (or_connection_t *conn, const char *digest)
void cell_pack (packed_cell_t *dst, const cell_t *src)
static void cell_unpack (cell_t *dest, const char *src)
void var_cell_pack_header (const var_cell_t *cell, char *hdr_out)
var_cell_tvar_cell_new (uint16_t payload_len)
void var_cell_free (var_cell_t *cell)
int connection_or_reached_eof (or_connection_t *conn)
int connection_or_process_inbuf (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 *or_conn)
int connection_or_digest_is_known_relay (const char *id_digest)
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 int connection_or_is_better (time_t now, const or_connection_t *a, const or_connection_t *b, int forgive_new_connections)
or_connection_tconnection_or_get_for_extend (const char *digest, const tor_addr_t *target_addr, const char **msg_out, int *launch_out)
static void connection_or_group_set_badness (or_connection_t *head)
void connection_or_set_bad_connections (void)
void connection_or_connect_failed (or_connection_t *conn, int reason, const char *msg)
or_connection_tconnection_or_connect (const tor_addr_t *_addr, uint16_t port, const char *id_digest)
int connection_tls_start_handshake (or_connection_t *conn, int receiving)
static void connection_or_tls_renegotiated_cb (tor_tls_t *tls, void *_conn)
int connection_tls_continue_handshake (or_connection_t *conn)
int connection_or_nonopen_was_started_here (or_connection_t *conn)
void or_handshake_state_free (or_handshake_state_t *state)
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)
void connection_or_write_var_cell_to_buf (const var_cell_t *cell, or_connection_t *conn)
static int connection_fetch_var_cell_from_buf (or_connection_t *conn, var_cell_t **out)
int connection_or_send_destroy (circid_t circ_id, or_connection_t *conn, int reason)
int is_or_protocol_version_known (uint16_t v)
int connection_or_send_netinfo (or_connection_t *conn)

Variables

static digestmap_t * orconn_identity_map = NULL
static const uint16_t or_protocol_versions [] = { 1, 2 }
static const int n_or_protocol_versions


Detailed Description

Functions to handle OR connections, TLS handshaking, and cells on the network.


Define Documentation

#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().


Function Documentation

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  ) 

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  ) 

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]

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]

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  ) 

static int connection_or_process_cells_from_inbuf ( or_connection_t conn  )  [static]

int connection_or_process_inbuf ( or_connection_t conn  ) 

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  ) 

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]

void connection_or_set_bad_connections ( void   ) 

Go through all the OR connections, and set the is_bad_for_new_circs flag on:

  • all connections that are too old.
  • all open non-canonical connections for which a canonical connection exists to the same router.
  • all open canonical connections for which a 'better' canonical connection exists to the same router.
  • all open non-canonical connections for which a 'better' non-canonical connection exists to the same router at the same address.

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]

int connection_or_set_state_open ( or_connection_t conn  ) 

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  ) 

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().


Variable Documentation

const int n_or_protocol_versions [static]

Initial value:

  (int)( sizeof(or_protocol_versions)/sizeof(uint16_t) )
Number of versions in or_protocol_versions.

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().


Generated on Tue May 25 00:30:41 2010 for tor by  doxygen 1.5.6