Back to index

tor  0.2.3.18-rc
Functions
connection_or.h File Reference

Header file for connection_or.c. More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

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.
void connection_or_clear_identity_map (void)
 Remove all entries from the identity-to-orconn map, and clear all identities in OR conns.
void clear_broken_connection_map (int disable)
 Forget all recorded states for failed connections.
or_connection_tconnection_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.
void connection_or_set_bad_connections (const char *digest, int force)
 Go through all the OR connections (or if digest is non-NULL, just the OR connections with that digest), and set the is_bad_for_new_circs flag based on the rules in connection_or_group_set_badness() (or just always set it if force is true).
int connection_or_reached_eof (or_connection_t *conn)
 We've received an EOF from conn.
int connection_or_process_inbuf (or_connection_t *conn)
 Handle any new bytes that have come in on connection conn.
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.
int connection_or_finished_flushing (or_connection_t *conn)
 Connection conn has finished writing and has no bytes left on its outbuf.
int connection_or_finished_connecting (or_connection_t *conn)
 Connected handler for OR connections: begin the TLS handshake.
void connection_or_about_to_close (or_connection_t *conn)
 Called when we're about to finally unlink and free an OR connection: perform necessary accounting and cleanup.
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.
void connection_or_update_token_buckets (smartlist_t *conns, const or_options_t *options)
 Either our set of relays or our per-conn rate limits have changed.
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.
or_connection_tconnection_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.
void connection_or_report_broken_states (int severity, int domain)
 Report a list of the top states for failed OR connections at log level severity, in log domain domain.
int connection_tls_start_handshake (or_connection_t *conn, int receiving)
 Begin the tls handshake with conn.
int connection_tls_continue_handshake (or_connection_t *conn)
 Move forward with the tls handshake.
int connection_init_or_handshake_state (or_connection_t *conn, int started_here)
 Allocate a new connection handshake state for the connection conn.
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)
 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.
int connection_or_client_learned_peer_id (or_connection_t *conn, const uint8_t *peer_id)
 Called when we (as a connection initiator) have definitively, authenticatedly, learned that ID of the Tor instance on the other side of conn is peer_id.
void connection_or_set_circid_type (or_connection_t *conn, crypto_pk_t *identity_rcvd)
 Set the circid_type field of conn (which determines which part of the circuit ID space we're willing to use) based on comparing our ID to identity_rcvd
void or_handshake_state_free (or_handshake_state_t *state)
 Free all storage held by state.
void or_handshake_state_record_cell (or_handshake_state_t *state, const cell_t *cell, int incoming)
 Remember that cell has been transmitted (if incoming is false) or received (if incoming is true) during a V3 handshake using state.
void or_handshake_state_record_var_cell (or_handshake_state_t *state, const var_cell_t *cell, int incoming)
 Remember that a variable-length cell has been transmitted (if incoming is false) or received (if incoming is true) during a V3 handshake using state.
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.
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.
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.
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.
int connection_or_send_versions (or_connection_t *conn, int v3_plus)
 Send a VERSIONS cell on conn, telling the other host about the link protocol versions that this Tor can support.
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.
int connection_or_send_certs_cell (or_connection_t *conn)
 Send a CERTS cell on the connection conn.
int connection_or_send_auth_challenge_cell (or_connection_t *conn)
 Send an AUTH_CHALLENGE cell on the connection conn.
int connection_or_compute_authenticate_cell_body (or_connection_t *conn, uint8_t *out, size_t outlen, crypto_pk_t *signing_key, int server)
 Compute the main body of an AUTHENTICATE cell that a client can use to authenticate itself on a v3 handshake for conn.
int connection_or_send_authenticate_cell (or_connection_t *conn, int type)
 Send an AUTHENTICATE cell on the connection conn.
int is_or_protocol_version_known (uint16_t version)
 Return true iff v is a link protocol version that this Tor implementation believes it can support.
void cell_pack (packed_cell_t *dest, const cell_t *src)
 Pack the cell_t host-order structure src into network-order in the buffer dest.
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.
var_cell_tvar_cell_new (uint16_t payload_len)
 Allocate and return a new var_cell_t with payload_len bytes of payload space.
void var_cell_free (var_cell_t *cell)
 Release all space held by cell.

Detailed Description

Header file for connection_or.c.

Definition in file connection_or.h.


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.

Definition at line 295 of file connection_or.c.

{
  char *dest = dst->body;
  set_uint16(dest, htons(src->circ_id));
  *(uint8_t*)(dest+2) = src->command;
  memcpy(dest+3, src->payload, CELL_PAYLOAD_SIZE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void clear_broken_connection_map ( int  stop_recording)

Forget all recorded states for failed connections.

If stop_recording is true, don't record any more.

Definition at line 184 of file connection_or.c.

Here is the call graph for this function:

Here is the caller graph for this function:

int connection_init_or_handshake_state ( or_connection_t conn,
int  started_here 
)

Allocate a new connection handshake state for the connection conn.

Return 0 on success, -1 on failure.

Definition at line 1626 of file connection_or.c.

{
  or_handshake_state_t *s;
  if (conn->handshake_state) {
    log_warn(LD_BUG, "Duplicate call to connection_init_or_handshake_state!");
    return 0;
  }
  s = conn->handshake_state = tor_malloc_zero(sizeof(or_handshake_state_t));
  s->started_here = started_here ? 1 : 0;
  s->digest_sent_data = 1;
  s->digest_received_data = 1;
  return 0;
}

Here is the caller graph for this function:

Called when we're about to finally unlink and free an OR connection: perform necessary accounting and cleanup.

Definition at line 514 of file connection_or.c.

{
  time_t now = time(NULL);
  connection_t *conn = TO_CONN(or_conn);

  /* Remember why we're closing this connection. */
  if (conn->state != OR_CONN_STATE_OPEN) {
    /* Inform any pending (not attached) circs that they should
     * give up. */
    circuit_n_conn_done(TO_OR_CONN(conn), 0);
    /* now mark things down as needed */
    if (connection_or_nonopen_was_started_here(or_conn)) {
      const or_options_t *options = get_options();
      connection_or_note_state_when_broken(or_conn);
      rep_hist_note_connect_failed(or_conn->identity_digest, now);
      entry_guard_register_connect_status(or_conn->identity_digest,0,
                                          !options->HTTPSProxy, now);
      if (conn->state >= OR_CONN_STATE_TLS_HANDSHAKING) {
        int reason = tls_error_to_orconn_end_reason(or_conn->tls_error);
        control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
                                     reason);
        if (!authdir_mode_tests_reachability(options))
          control_event_bootstrap_problem(
                orconn_end_reason_to_control_string(reason), reason);
      }
    }
  } else if (conn->hold_open_until_flushed) {
    /* We only set hold_open_until_flushed when we're intentionally
     * closing a connection. */
    rep_hist_note_disconnect(or_conn->identity_digest, now);
    control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
                tls_error_to_orconn_end_reason(or_conn->tls_error));
  } else if (!tor_digest_is_zero(or_conn->identity_digest)) {
    rep_hist_note_connection_died(or_conn->identity_digest, now);
    control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
                tls_error_to_orconn_end_reason(or_conn->tls_error));
  }
  /* Now close all the attached circuits on it. */
  circuit_unlink_all_from_or_conn(TO_OR_CONN(conn),
                                  END_CIRC_REASON_OR_CONN_CLOSED);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Remove all entries from the identity-to-orconn map, and clear all identities in OR conns.

Definition at line 99 of file connection_or.c.

{
  smartlist_t *conns = get_connection_array();
  SMARTLIST_FOREACH(conns, connection_t *, conn,
  {
    if (conn->type == CONN_TYPE_OR) {
      or_connection_t *or_conn = TO_OR_CONN(conn);
      memset(or_conn->identity_digest, 0, DIGEST_LEN);
      or_conn->next_with_same_id = NULL;
    }
  });

  digestmap_free(orconn_identity_map, NULL);
  orconn_identity_map = NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int connection_or_client_learned_peer_id ( or_connection_t conn,
const uint8_t *  peer_id 
)

Called when we (as a connection initiator) have definitively, authenticatedly, learned that ID of the Tor instance on the other side of conn is peer_id.

For v1 and v2 handshakes, this is right after we get a certificate chain in a TLS handshake or renegotiation. For v3 handshakes, this is right after we get a certificate chain in a CERTS cell.

If we want any particular ID before, record the one we got.

If we wanted an ID, but we didn't get it, log a warning and return -1.

If we're testing reachability, remember what we learned.

Return 0 on success, -1 on failure.

Definition at line 1499 of file connection_or.c.

{
  const or_options_t *options = get_options();
  int severity = server_mode(options) ? LOG_PROTOCOL_WARN : LOG_WARN;

  if (tor_digest_is_zero(conn->identity_digest)) {
    connection_or_set_identity_digest(conn, (const char*)peer_id);
    tor_free(conn->nickname);
    conn->nickname = tor_malloc(HEX_DIGEST_LEN+2);
    conn->nickname[0] = '$';
    base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1,
                  conn->identity_digest, DIGEST_LEN);
    log_info(LD_HANDSHAKE, "Connected to router %s at %s:%d without knowing "
                    "its key. Hoping for the best.",
                    conn->nickname, conn->_base.address, conn->_base.port);
    /* if it's a bridge and we didn't know its identity fingerprint, now
     * we do -- remember it for future attempts. */
    learned_router_identity(&conn->_base.addr, conn->_base.port,
                            (const char*)peer_id);
  }

  if (tor_memneq(peer_id, conn->identity_digest, DIGEST_LEN)) {
    /* I was aiming for a particular digest. I didn't get it! */
    char seen[HEX_DIGEST_LEN+1];
    char expected[HEX_DIGEST_LEN+1];
    base16_encode(seen, sizeof(seen), (const char*)peer_id, DIGEST_LEN);
    base16_encode(expected, sizeof(expected), conn->identity_digest,
                  DIGEST_LEN);
    log_fn(severity, LD_HANDSHAKE,
           "Tried connecting to router at %s:%d, but identity key was not "
           "as expected: wanted %s but got %s.",
           conn->_base.address, conn->_base.port, expected, seen);
    entry_guard_register_connect_status(conn->identity_digest, 0, 1,
                                        time(NULL));
    control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED,
                                 END_OR_CONN_REASON_OR_IDENTITY);
    if (!authdir_mode_tests_reachability(options))
      control_event_bootstrap_problem(
                                "Unexpected identity in router certificate",
                                END_OR_CONN_REASON_OR_IDENTITY);
    return -1;
  }
  if (authdir_mode_tests_reachability(options)) {
    dirserv_orconn_tls_done(conn->_base.address, conn->_base.port,
                            (const char*)peer_id);
  }

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int connection_or_compute_authenticate_cell_body ( or_connection_t conn,
uint8_t *  out,
size_t  outlen,
crypto_pk_t signing_key,
int  server 
)

Compute the main body of an AUTHENTICATE cell that a client can use to authenticate itself on a v3 handshake for conn.

Write it to the outlen-byte buffer at out.

If server is true, only calculate the first V3_AUTH_FIXED_PART_LEN bytes -- the part of the authenticator that's determined by the rest of the handshake, and which match the provided value exactly.

If server is false and signing_key is NULL, calculate the first V3_AUTH_BODY_LEN bytes of the authenticator (that is, everything that should be signed), but don't actually sign it.

If server is false and signing_key is provided, calculate the entire authenticator, signed with signing_key.

Return the length of the cell body on success, and -1 on failure.

Definition at line 2107 of file connection_or.c.

{
  uint8_t *ptr;

  /* assert state is reasonable XXXX */

  if (outlen < V3_AUTH_FIXED_PART_LEN ||
      (!server && outlen < V3_AUTH_BODY_LEN))
    return -1;

  ptr = out;

  /* Type: 8 bytes. */
  memcpy(ptr, "AUTH0001", 8);
  ptr += 8;

  {
    const tor_cert_t *id_cert=NULL, *link_cert=NULL;
    const digests_t *my_digests, *their_digests;
    const uint8_t *my_id, *their_id, *client_id, *server_id;
    if (tor_tls_get_my_certs(0, &link_cert, &id_cert))
      return -1;
    my_digests = tor_cert_get_id_digests(id_cert);
    their_digests = tor_cert_get_id_digests(conn->handshake_state->id_cert);
    tor_assert(my_digests);
    tor_assert(their_digests);
    my_id = (uint8_t*)my_digests->d[DIGEST_SHA256];
    their_id = (uint8_t*)their_digests->d[DIGEST_SHA256];

    client_id = server ? their_id : my_id;
    server_id = server ? my_id : their_id;

    /* Client ID digest: 32 octets. */
    memcpy(ptr, client_id, 32);
    ptr += 32;

    /* Server ID digest: 32 octets. */
    memcpy(ptr, server_id, 32);
    ptr += 32;
  }

  {
    crypto_digest_t *server_d, *client_d;
    if (server) {
      server_d = conn->handshake_state->digest_sent;
      client_d = conn->handshake_state->digest_received;
    } else {
      client_d = conn->handshake_state->digest_sent;
      server_d = conn->handshake_state->digest_received;
    }

    /* Server log digest : 32 octets */
    crypto_digest_get_digest(server_d, (char*)ptr, 32);
    ptr += 32;

    /* Client log digest : 32 octets */
    crypto_digest_get_digest(client_d, (char*)ptr, 32);
    ptr += 32;
  }

  {
    /* Digest of cert used on TLS link : 32 octets. */
    const tor_cert_t *cert = NULL;
    tor_cert_t *freecert = NULL;
    if (server) {
      tor_tls_get_my_certs(1, &cert, NULL);
    } else {
      freecert = tor_tls_get_peer_cert(conn->tls);
      cert = freecert;
    }
    if (!cert)
      return -1;
    memcpy(ptr, tor_cert_get_cert_digests(cert)->d[DIGEST_SHA256], 32);

    if (freecert)
      tor_cert_free(freecert);
    ptr += 32;
  }

  /* HMAC of clientrandom and serverrandom using master key : 32 octets */
  tor_tls_get_tlssecrets(conn->tls, ptr);
  ptr += 32;

  tor_assert(ptr - out == V3_AUTH_FIXED_PART_LEN);

  if (server)
    return V3_AUTH_FIXED_PART_LEN; // ptr-out

  /* Time: 8 octets. */
  {
    uint64_t now = time(NULL);
    if ((time_t)now < 0)
      return -1;
    set_uint32(ptr, htonl((uint32_t)(now>>32)));
    set_uint32(ptr+4, htonl((uint32_t)now));
    ptr += 8;
  }

  /* Nonce: 16 octets. */
  crypto_rand((char*)ptr, 16);
  ptr += 16;

  tor_assert(ptr - out == V3_AUTH_BODY_LEN);

  if (!signing_key)
    return V3_AUTH_BODY_LEN; // ptr - out

  {
    int siglen;
    char d[32];
    crypto_digest256(d, (char*)out, ptr-out, DIGEST_SHA256);
    siglen = crypto_pk_private_sign(signing_key,
                                    (char*)ptr, outlen - (ptr-out),
                                    d, 32);
    if (siglen < 0)
      return -1;

    ptr += siglen;
    tor_assert(ptr <= out+outlen);
    return (int)(ptr - out);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

Definition at line 1037 of file connection_or.c.

{
  or_connection_t *conn;
  const or_options_t *options = get_options();
  int socket_error = 0;
  tor_addr_t addr;

  int r;
  tor_addr_t proxy_addr;
  uint16_t proxy_port;
  int proxy_type;

  tor_assert(_addr);
  tor_assert(id_digest);
  tor_addr_copy(&addr, _addr);

  if (server_mode(options) && router_digest_is_me(id_digest)) {
    log_info(LD_PROTOCOL,"Client asked me to connect to myself. Refusing.");
    return NULL;
  }

  conn = or_connection_new(tor_addr_family(&addr));

  /* set up conn so it's got all the data we need to remember */
  connection_or_init_conn_from_address(conn, &addr, port, id_digest, 1);
  conn->_base.state = OR_CONN_STATE_CONNECTING;
  control_event_or_conn_status(conn, OR_CONN_EVENT_LAUNCHED, 0);

  conn->is_outgoing = 1;

  /* If we are using a proxy server, find it and use it. */
  r = get_proxy_addrport(&proxy_addr, &proxy_port, &proxy_type, TO_CONN(conn));
  if (r == 0) {
    conn->proxy_type = proxy_type;
    if (proxy_type != PROXY_NONE) {
      tor_addr_copy(&addr, &proxy_addr);
      port = proxy_port;
      conn->_base.proxy_state = PROXY_INFANT;
    }
  } else {
    /* get_proxy_addrport() might fail if we have a Bridge line that
       references a transport, but no ClientTransportPlugin lines
       defining its transport proxy. If this is the case, let's try to
       output a useful log message to the user. */
    const char *transport_name =
      find_transport_name_by_bridge_addrport(&TO_CONN(conn)->addr,
                                             TO_CONN(conn)->port);

    if (transport_name) {
      log_warn(LD_GENERAL, "We were supposed to connect to bridge '%s:%u' "
               "using pluggable transport '%s', but we can't find a pluggable "
               "transport proxy supporting '%s'. This can happen if you "
               "haven't provided a ClientTransportPlugin line, or if "
               "your pluggable transport proxy stopped running.",
               fmt_addr(&TO_CONN(conn)->addr), TO_CONN(conn)->port,
               transport_name, transport_name);
    } else {
      log_warn(LD_GENERAL, "Tried to connect to '%s:%u' through a proxy, but "
               "the proxy address could not be found.",
               fmt_addr(&TO_CONN(conn)->addr), TO_CONN(conn)->port);
    }

    connection_free(TO_CONN(conn));
    return NULL;
  }

  switch (connection_connect(TO_CONN(conn), conn->_base.address,
                             &addr, port, &socket_error)) {
    case -1:
      /* If the connection failed immediately, and we're using
       * a proxy, our proxy is down. Don't blame the Tor server. */
      if (conn->_base.proxy_state == PROXY_INFANT)
        entry_guard_register_connect_status(conn->identity_digest,
                                            0, 1, time(NULL));
      connection_or_connect_failed(conn,
                                   errno_to_orconn_end_reason(socket_error),
                                   tor_socket_strerror(socket_error));
      connection_free(TO_CONN(conn));
      return NULL;
    case 0:
      connection_watch_events(TO_CONN(conn), READ_EVENT | WRITE_EVENT);
      /* writable indicates finish, readable indicates broken link,
         error indicates broken link on windows */
      return conn;
    /* case 1: fall through */
  }

  if (connection_or_finished_connecting(conn) < 0) {
    /* already marked for close */
    return NULL;
  }
  return conn;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

Definition at line 1014 of file connection_or.c.

Here is the call graph for this function:

Here is the caller graph for this function:

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.

Definition at line 559 of file connection_or.c.

{
  if (router_get_consensus_status_by_id(id_digest))
    return 1; /* It's in the consensus: "yes" */
  if (router_get_by_id_digest(id_digest))
    return 1; /* Not in the consensus, but we have a descriptor for
               * it. Probably it was in a recent consensus. "Yes". */
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Connected handler for OR connections: begin the TLS handshake.

Definition at line 479 of file connection_or.c.

{
  const int proxy_type = or_conn->proxy_type;
  connection_t *conn;
  tor_assert(or_conn);
  conn = TO_CONN(or_conn);
  tor_assert(conn->state == OR_CONN_STATE_CONNECTING);

  log_debug(LD_HANDSHAKE,"OR connect() to router at %s:%u finished.",
            conn->address,conn->port);
  control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0);

  if (proxy_type != PROXY_NONE) {
    /* start proxy handshake */
    if (connection_proxy_connect(conn, proxy_type) < 0) {
      connection_mark_for_close(conn);
      return -1;
    }

    connection_start_reading(conn);
    conn->state = OR_CONN_STATE_PROXY_HANDSHAKING;
    return 0;
  }

  if (connection_tls_start_handshake(or_conn, 0) < 0) {
    /* TLS handshaking error of some kind. */
    connection_mark_for_close(conn);
    return -1;
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

Definition at line 457 of file connection_or.c.

{
  tor_assert(conn);
  assert_connection_ok(TO_CONN(conn),0);

  switch (conn->_base.state) {
    case OR_CONN_STATE_PROXY_HANDSHAKING:
    case OR_CONN_STATE_OPEN:
    case OR_CONN_STATE_OR_HANDSHAKING_V2:
    case OR_CONN_STATE_OR_HANDSHAKING_V3:
      break;
    default:
      log_err(LD_BUG,"Called in unexpected state %d.", conn->_base.state);
      tor_fragile_assert();
      return -1;
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Called whenever we have flushed some data on an or_conn: add more data from active circuits.

Definition at line 431 of file connection_or.c.

{
  size_t datalen = connection_get_outbuf_len(TO_CONN(conn));
  /* If we're under the low water mark, add cells until we're just over the
   * high water mark. */
  if (datalen < OR_CONN_LOWWATER) {
    ssize_t n = CEIL_DIV(OR_CONN_HIGHWATER - datalen, CELL_NETWORK_SIZE);
    time_t now = approx_time();
    while (conn->active_circuits && n > 0) {
      int flushed;
      flushed = connection_or_flush_from_first_active_circuit(conn, 1, now);
      n -= flushed;
    }
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

Definition at line 771 of file connection_or.c.

{
  or_connection_t *conn, *best=NULL;
  int n_inprogress_goodaddr = 0, n_old = 0, n_noncanonical = 0, n_possible = 0;
  time_t now = approx_time();

  tor_assert(msg_out);
  tor_assert(launch_out);

  if (!orconn_identity_map) {
    *msg_out = "Router not connected (nothing is).  Connecting.";
    *launch_out = 1;
    return NULL;
  }

  conn = digestmap_get(orconn_identity_map, digest);

  for (; conn; conn = conn->next_with_same_id) {
    tor_assert(conn->_base.magic == OR_CONNECTION_MAGIC);
    tor_assert(conn->_base.type == CONN_TYPE_OR);
    tor_assert(tor_memeq(conn->identity_digest, digest, DIGEST_LEN));
    if (conn->_base.marked_for_close)
      continue;
    /* Never return a connection on which the other end appears to be
     * a client. */
    if (conn->is_connection_with_client) {
      continue;
    }
    /* Never return a non-open connection. */
    if (conn->_base.state != OR_CONN_STATE_OPEN) {
      /* If the address matches, don't launch a new connection for this
       * circuit. */
      if (!tor_addr_compare(&conn->real_addr, target_addr, CMP_EXACT))
        ++n_inprogress_goodaddr;
      continue;
    }
    /* Never return a connection that shouldn't be used for circs. */
    if (conn->is_bad_for_new_circs) {
      ++n_old;
      continue;
    }
    /* Never return a non-canonical connection using a recent link protocol
     * if the address is not what we wanted.
     *
     * (For old link protocols, we can't rely on is_canonical getting
     * set properly if we're talking to the right address, since we might
     * have an out-of-date descriptor, and we will get no NETINFO cell to
     * tell us about the right address.) */
    if (!conn->is_canonical && conn->link_proto >= 2 &&
        tor_addr_compare(&conn->real_addr, target_addr, CMP_EXACT)) {
      ++n_noncanonical;
      continue;
    }

    ++n_possible;

    if (!best) {
      best = conn; /* If we have no 'best' so far, this one is good enough. */
      continue;
    }

    if (connection_or_is_better(now, conn, best, 0))
      best = conn;
  }

  if (best) {
    *msg_out = "Connection is fine; using it.";
    *launch_out = 0;
    return best;
  } else if (n_inprogress_goodaddr) {
    *msg_out = "Connection in progress; waiting.";
    *launch_out = 0;
    return NULL;
  } else if (n_old || n_noncanonical) {
    *msg_out = "Connections all too old, or too non-canonical. "
      " Launching a new one.";
    *launch_out = 1;
    return NULL;
  } else {
    *msg_out = "Not connected. Connecting.";
    *launch_out = 1;
    return NULL;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

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 
)

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. started_here is 1 if we are the initiator of conn and 0 if it's an incoming connection.

Definition at line 657 of file connection_or.c.

{
  const node_t *r = node_get_by_id(id_digest);
  connection_or_set_identity_digest(conn, id_digest);
  connection_or_update_token_buckets_helper(conn, 1, get_options());

  conn->_base.port = port;
  tor_addr_copy(&conn->_base.addr, addr);
  tor_addr_copy(&conn->real_addr, addr);
  if (r) {
    tor_addr_port_t node_ap;
    node_get_pref_orport(r, &node_ap);
    /* XXXX proposal 186 is making this more complex.  For now, a conn
       is canonical when it uses the _preferred_ address. */
    if (tor_addr_eq(&conn->_base.addr, &node_ap.addr))
      conn->is_canonical = 1;
    if (!started_here) {
      /* Override the addr/port, so our log messages will make sense.
       * This is dangerous, since if we ever try looking up a conn by
       * its actual addr/port, we won't remember. Careful! */
      /* XXXX arma: this is stupid, and it's the reason we need real_addr
       * to track is_canonical properly.  What requires it? */
      /* XXXX <arma> i believe the reason we did this, originally, is because
       * we wanted to log what OR a connection was to, and if we logged the
       * right IP address and port 56244, that wouldn't be as helpful. now we
       * log the "right" port too, so we know if it's moria1 or moria2.
       */
      tor_addr_copy(&conn->_base.addr, &node_ap.addr);
      conn->_base.port = node_ap.port;
    }
    conn->nickname = tor_strdup(node_get_nickname(r));
    tor_free(conn->_base.address);
    conn->_base.address = tor_dup_addr(&node_ap.addr);
  } else {
    const char *n;
    /* If we're an authoritative directory server, we may know a
     * nickname for this router. */
    n = dirserv_get_nickname_by_digest(id_digest);
    if (n) {
      conn->nickname = tor_strdup(n);
    } else {
      conn->nickname = tor_malloc(HEX_DIGEST_LEN+2);
      conn->nickname[0] = '$';
      base16_encode(conn->nickname+1, HEX_DIGEST_LEN+1,
                    conn->identity_digest, DIGEST_LEN);
    }
    tor_free(conn->_base.address);
    conn->_base.address = tor_dup_addr(addr);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

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

Don't let the inbuf of a nonopen OR connection grow beyond this many bytes: it's either a broken client, a non-Tor client, or a DOS attempt.

Definition at line 359 of file connection_or.c.

{
#define MAX_OR_INBUF_WHEN_NONOPEN 0

  int ret = 0;
  tor_assert(conn);

  switch (conn->_base.state) {
    case OR_CONN_STATE_PROXY_HANDSHAKING:
      ret = connection_read_proxy_handshake(TO_CONN(conn));

      /* start TLS after handshake completion, or deal with error */
      if (ret == 1) {
        tor_assert(TO_CONN(conn)->proxy_state == PROXY_CONNECTED);
        if (connection_tls_start_handshake(conn, 0) < 0)
          ret = -1;
      }
      if (ret < 0) {
        connection_mark_for_close(TO_CONN(conn));
      }

      return ret;
    case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING:
#ifdef USE_BUFFEREVENTS
      if (tor_tls_server_got_renegotiate(conn->tls))
        connection_or_tls_renegotiated_cb(conn->tls, conn);
      if (conn->_base.marked_for_close)
        return 0;
      /* fall through. */
#endif
    case OR_CONN_STATE_OPEN:
    case OR_CONN_STATE_OR_HANDSHAKING_V2:
    case OR_CONN_STATE_OR_HANDSHAKING_V3:
      return connection_or_process_cells_from_inbuf(conn);
    default:
      break; /* don't do anything */
  }

  /* This check was necessary with 0.2.2, when the TLS_SERVER_RENEGOTIATING
   * check would otherwise just let data accumulate.  It serves no purpose
   * in 0.2.3.
   *
   * XXX024 Remove this check once we verify that the above paragraph is
   * 100% true. */
  if (buf_datalen(conn->_base.inbuf) > MAX_OR_INBUF_WHEN_NONOPEN) {
    log_fn(LOG_PROTOCOL_WARN, LD_NET, "Accumulated too much data (%d bytes) "
           "on nonopen OR connection %s %s:%u in state %s; closing.",
           (int)buf_datalen(conn->_base.inbuf),
           connection_or_nonopen_was_started_here(conn) ? "to" : "from",
           conn->_base.address, conn->_base.port,
           conn_state_to_string(conn->_base.type, conn->_base.state));
    connection_mark_for_close(TO_CONN(conn));
    ret = -1;
  }

  return ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

We've received an EOF from conn.

Mark it for close and return.

Definition at line 346 of file connection_or.c.

{
  log_info(LD_OR,"OR connection reached EOF. Closing.");
  connection_mark_for_close(TO_CONN(conn));
  return 0;
}

Here is the caller graph for this function:

If conn is listed in orconn_identity_map, remove it, and clear conn->identity_digest.

Otherwise do nothing.

Definition at line 62 of file connection_or.c.

{
  or_connection_t *tmp;
  tor_assert(conn);
  if (!orconn_identity_map)
    return;
  tmp = digestmap_get(orconn_identity_map, conn->identity_digest);
  if (!tmp) {
    if (!tor_digest_is_zero(conn->identity_digest)) {
      log_warn(LD_BUG, "Didn't find connection '%s' on identity map when "
               "trying to remove it.",
               conn->nickname ? conn->nickname : "NULL");
    }
    return;
  }
  if (conn == tmp) {
    if (conn->next_with_same_id)
      digestmap_set(orconn_identity_map, conn->identity_digest,
                    conn->next_with_same_id);
    else
      digestmap_remove(orconn_identity_map, conn->identity_digest);
  } else {
    while (tmp->next_with_same_id) {
      if (tmp->next_with_same_id == conn) {
        tmp->next_with_same_id = conn->next_with_same_id;
        break;
      }
      tmp = tmp->next_with_same_id;
    }
  }
  memset(conn->identity_digest, 0, DIGEST_LEN);
  conn->next_with_same_id = NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void connection_or_report_broken_states ( int  severity,
int  domain 
)

Report a list of the top states for failed OR connections at log level severity, in log domain domain.

Definition at line 252 of file connection_or.c.

{
  int total = 0;
  smartlist_t *items;

  if (!broken_connection_counts || disable_broken_connection_counts)
    return;

  items = smartlist_new();
  STRMAP_FOREACH(broken_connection_counts, state, void *, countptr) {
    broken_state_count_t *c = tor_malloc(sizeof(broken_state_count_t));
    c->count = (intptr_t)countptr;
    total += (int)c->count;
    c->state = state;
    smartlist_add(items, c);
  } STRMAP_FOREACH_END;

  smartlist_sort(items, broken_state_count_compare);

  log(severity, domain, "%d connections have failed%s", total,
      smartlist_len(items) > MAX_REASONS_TO_REPORT ? ". Top reasons:" : ":");

  SMARTLIST_FOREACH_BEGIN(items, const broken_state_count_t *, c) {
    if (c_sl_idx > MAX_REASONS_TO_REPORT)
      break;
    log(severity, domain,
        " %d connections died in state %s", (int)c->count, c->state);
  } SMARTLIST_FOREACH_END(c);

  SMARTLIST_FOREACH(items, broken_state_count_t *, c, tor_free(c));
  smartlist_free(items);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Send an AUTH_CHALLENGE cell on the connection conn.

Return 0 on success, -1 on failure.

Definition at line 2062 of file connection_or.c.

{
  var_cell_t *cell;
  uint8_t *cp;
  uint8_t challenge[OR_AUTH_CHALLENGE_LEN];
  tor_assert(conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3);

  if (! conn->handshake_state)
    return -1;

  if (crypto_rand((char*)challenge, OR_AUTH_CHALLENGE_LEN) < 0)
    return -1;
  cell = var_cell_new(OR_AUTH_CHALLENGE_LEN + 4);
  cell->command = CELL_AUTH_CHALLENGE;
  memcpy(cell->payload, challenge, OR_AUTH_CHALLENGE_LEN);
  cp = cell->payload + OR_AUTH_CHALLENGE_LEN;
  set_uint16(cp, htons(1)); /* We recognize one authentication type. */
  set_uint16(cp+2, htons(AUTHTYPE_RSA_SHA256_TLSSECRET));

  connection_or_write_var_cell_to_buf(cell, conn);
  var_cell_free(cell);
  memset(challenge, 0, sizeof(challenge));

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int connection_or_send_authenticate_cell ( or_connection_t conn,
int  authtype 
)

Send an AUTHENTICATE cell on the connection conn.

Return 0 on success, -1 on failure

Definition at line 2236 of file connection_or.c.

{
  var_cell_t *cell;
  crypto_pk_t *pk = tor_tls_get_my_client_auth_key();
  int authlen;
  size_t cell_maxlen;
  /* XXXX make sure we're actually supposed to send this! */

  if (!pk) {
    log_warn(LD_BUG, "Can't compute authenticate cell: no client auth key");
    return -1;
  }
  if (authtype != AUTHTYPE_RSA_SHA256_TLSSECRET) {
    log_warn(LD_BUG, "Tried to send authenticate cell with unknown "
             "authentication type %d", authtype);
    return -1;
  }

  cell_maxlen = 4 + /* overhead */
    V3_AUTH_BODY_LEN + /* Authentication body */
    crypto_pk_keysize(pk) + /* Max signature length */
    16 /* add a few extra bytes just in case. */;

  cell = var_cell_new(cell_maxlen);
  cell->command = CELL_AUTHENTICATE;
  set_uint16(cell->payload, htons(AUTHTYPE_RSA_SHA256_TLSSECRET));
  /* skip over length ; we don't know that yet. */

  authlen = connection_or_compute_authenticate_cell_body(conn,
                                                         cell->payload+4,
                                                         cell_maxlen-4,
                                                         pk,
                                                         0 /* not server */);
  if (authlen < 0) {
    log_warn(LD_BUG, "Unable to compute authenticate cell!");
    var_cell_free(cell);
    return -1;
  }
  tor_assert(authlen + 4 <= cell->payload_len);
  set_uint16(cell->payload+2, htons(authlen));
  cell->payload_len = authlen + 4;

  connection_or_write_var_cell_to_buf(cell, conn);
  var_cell_free(cell);

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Send a CERTS cell on the connection conn.

Return 0 on success, -1 on failure.

Definition at line 2010 of file connection_or.c.

{
  const tor_cert_t *link_cert = NULL, *id_cert = NULL;
  const uint8_t *link_encoded = NULL, *id_encoded = NULL;
  size_t link_len, id_len;
  var_cell_t *cell;
  size_t cell_len;
  ssize_t pos;
  int server_mode;

  tor_assert(conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3);

  if (! conn->handshake_state)
    return -1;
  server_mode = ! conn->handshake_state->started_here;
  if (tor_tls_get_my_certs(server_mode, &link_cert, &id_cert) < 0)
    return -1;
  tor_cert_get_der(link_cert, &link_encoded, &link_len);
  tor_cert_get_der(id_cert, &id_encoded, &id_len);

  cell_len = 1 /* 1 byte: num certs in cell */ +
             2 * ( 1 + 2 ) /* For each cert: 1 byte for type, 2 for length */ +
             link_len + id_len;
  cell = var_cell_new(cell_len);
  cell->command = CELL_CERTS;
  cell->payload[0] = 2;
  pos = 1;

  if (server_mode)
    cell->payload[pos] = OR_CERT_TYPE_TLS_LINK; /* Link cert  */
  else
    cell->payload[pos] = OR_CERT_TYPE_AUTH_1024; /* client authentication */
  set_uint16(&cell->payload[pos+1], htons(link_len));
  memcpy(&cell->payload[pos+3], link_encoded, link_len);
  pos += 3 + link_len;

  cell->payload[pos] = OR_CERT_TYPE_ID_1024; /* ID cert */
  set_uint16(&cell->payload[pos+1], htons(id_len));
  memcpy(&cell->payload[pos+3], id_encoded, id_len);
  pos += 3 + id_len;

  tor_assert(pos == (int)cell_len); /* Otherwise we just smashed the heap */

  connection_or_write_var_cell_to_buf(cell, conn);
  var_cell_free(cell);

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

Definition at line 1884 of file connection_or.c.

{
  cell_t cell;

  tor_assert(conn);

  memset(&cell, 0, sizeof(cell_t));
  cell.circ_id = circ_id;
  cell.command = CELL_DESTROY;
  cell.payload[0] = (uint8_t) reason;
  log_debug(LD_OR,"Sending destroy (circID %d).", circ_id);

  connection_or_write_cell_to_buf(&cell, conn);
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Send a NETINFO cell on conn, telling the other server what we know about their address, our address, and the current time.

Definition at line 1958 of file connection_or.c.

{
  cell_t cell;
  time_t now = time(NULL);
  const routerinfo_t *me;
  int len;
  uint8_t *out;

  tor_assert(conn->handshake_state);

  memset(&cell, 0, sizeof(cell_t));
  cell.command = CELL_NETINFO;

  /* Timestamp. */
  set_uint32(cell.payload, htonl((uint32_t)now));

  /* Their address. */
  out = cell.payload + 4;
  /* We use &conn->real_addr below, unless it hasn't yet been set. If it
   * hasn't yet been set, we know that _base.addr hasn't been tampered with
   * yet either. */
  len = append_address_to_payload(out, !tor_addr_is_null(&conn->real_addr)
                                       ? &conn->real_addr : &conn->_base.addr);
  if (len<0)
    return -1;
  out += len;

  /* My address -- only include it if I'm a public relay, or if I'm a
   * bridge and this is an incoming connection. If I'm a bridge and this
   * is an outgoing connection, act like a normal client and omit it. */
  if ((public_server_mode(get_options()) || !conn->is_outgoing) &&
      (me = router_get_my_routerinfo())) {
    tor_addr_t my_addr;
    *out++ = 1; /* only one address is supported. */

    tor_addr_from_ipv4h(&my_addr, me->addr);
    len = append_address_to_payload(out, &my_addr);
    if (len < 0)
      return -1;
  } else {
    *out = 0;
  }

  conn->handshake_state->digest_sent_data = 0;
  connection_or_write_cell_to_buf(&cell, conn);

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int connection_or_send_versions ( or_connection_t conn,
int  v3_plus 
)

Send a VERSIONS cell on conn, telling the other host about the link protocol versions that this Tor can support.

If v3_plus, this is part of a V3 protocol handshake, so only allow protocol version v3 or later. If not v3_plus, this is not part of a v3 protocol handshake, so don't allow protocol v3 or later.

Definition at line 1928 of file connection_or.c.

{
  var_cell_t *cell;
  int i;
  int n_versions = 0;
  const int min_version = v3_plus ? 3 : 0;
  const int max_version = v3_plus ? UINT16_MAX : 2;
  tor_assert(conn->handshake_state &&
             !conn->handshake_state->sent_versions_at);
  cell = var_cell_new(n_or_protocol_versions * 2);
  cell->command = CELL_VERSIONS;
  for (i = 0; i < n_or_protocol_versions; ++i) {
    uint16_t v = or_protocol_versions[i];
    if (v < min_version || v > max_version)
      continue;
    set_uint16(cell->payload+(2*n_versions), htons(v));
    ++n_versions;
  }
  cell->payload_len = n_versions * 2;

  connection_or_write_var_cell_to_buf(cell, conn);
  conn->handshake_state->sent_versions_at = time(NULL);

  var_cell_free(cell);
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void connection_or_set_bad_connections ( const char *  digest,
int  force 
)

Go through all the OR connections (or if digest is non-NULL, just the OR connections with that digest), and set the is_bad_for_new_circs flag based on the rules in connection_or_group_set_badness() (or just always set it if force is true).

Definition at line 996 of file connection_or.c.

{
  if (!orconn_identity_map)
    return;

  DIGESTMAP_FOREACH(orconn_identity_map, identity, or_connection_t *, conn) {
    if (!digest || tor_memeq(digest, conn->identity_digest, DIGEST_LEN))
      connection_or_group_set_badness(conn, force);
  } DIGESTMAP_FOREACH_END;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void connection_or_set_circid_type ( or_connection_t conn,
crypto_pk_t identity_rcvd 
)

Set the circid_type field of conn (which determines which part of the circuit ID space we're willing to use) based on comparing our ID to identity_rcvd

Definition at line 1377 of file connection_or.c.

{
  const int started_here = connection_or_nonopen_was_started_here(conn);
  crypto_pk_t *our_identity =
    started_here ? get_tlsclient_identity_key() :
                   get_server_identity_key();

  if (identity_rcvd) {
    if (crypto_pk_cmp_keys(our_identity, identity_rcvd)<0) {
      conn->circ_id_type = CIRC_ID_TYPE_LOWER;
    } else {
      conn->circ_id_type = CIRC_ID_TYPE_HIGHER;
    }
  } else {
    conn->circ_id_type = CIRC_ID_TYPE_NEITHER;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

Definition at line 1733 of file connection_or.c.

{
  int started_here = connection_or_nonopen_was_started_here(conn);
  time_t now = time(NULL);
  conn->_base.state = OR_CONN_STATE_OPEN;
  control_event_or_conn_status(conn, OR_CONN_EVENT_CONNECTED, 0);

  if (started_here) {
    circuit_build_times_network_is_live(&circ_times);
    rep_hist_note_connect_succeeded(conn->identity_digest, now);
    if (entry_guard_register_connect_status(conn->identity_digest,
                                            1, 0, now) < 0) {
      /* Close any circuits pending on this conn. We leave it in state
       * 'open' though, because it didn't actually *fail* -- we just
       * chose not to use it. (Otherwise
       * connection_about_to_close_connection() will call a big pile of
       * functions to indicate we shouldn't try it again.) */
      log_debug(LD_OR, "New entry guard was reachable, but closing this "
                "connection so we can retry the earlier entry guards.");
      circuit_n_conn_done(conn, 0);
      return -1;
    }
    router_set_status(conn->identity_digest, 1);
  } else {
    /* only report it to the geoip module if it's not a known router */
    if (!router_get_by_id_digest(conn->identity_digest)) {
      geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &TO_CONN(conn)->addr,
                             now);
    }
  }

  or_handshake_state_free(conn->handshake_state);
  conn->handshake_state = NULL;
  IF_HAS_BUFFEREVENT(TO_CONN(conn), {
    connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
  }) ELSE_IF_NO_BUFFEREVENT {
    connection_start_reading(TO_CONN(conn));
  }

  circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void connection_or_update_token_buckets ( smartlist_t conns,
const or_options_t options 
)

Either our set of relays or our per-conn rate limits have changed.

Go through all the OR connections and update their token buckets to make sure they don't exceed their maximum values.

Definition at line 641 of file connection_or.c.

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 1782 of file connection_or.c.

Here is the call graph for this function:

Here is the caller graph for this function:

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.

Definition at line 1805 of file connection_or.c.

Here is the call graph for this function:

Here is the caller graph for this function:

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.

Definition at line 1214 of file connection_or.c.

{
  int result;
  check_no_tls_errors();
 again:
  if (conn->_base.state == OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING) {
    // log_notice(LD_OR, "Renegotiate with %p", conn->tls);
    result = tor_tls_renegotiate(conn->tls);
    // log_notice(LD_OR, "Result: %d", result);
  } else {
    tor_assert(conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING);
    // log_notice(LD_OR, "Continue handshake with %p", conn->tls);
    result = tor_tls_handshake(conn->tls);
    // log_notice(LD_OR, "Result: %d", result);
  }
  switch (result) {
    CASE_TOR_TLS_ERROR_ANY:
    log_info(LD_OR,"tls error [%s]. breaking connection.",
             tor_tls_err_to_string(result));
      return -1;
    case TOR_TLS_DONE:
      if (! tor_tls_used_v1_handshake(conn->tls)) {
        if (!tor_tls_is_server(conn->tls)) {
          if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) {
            if (tor_tls_received_v3_certificate(conn->tls)) {
              log_info(LD_OR, "Client got a v3 cert!  Moving on to v3 "
                         "handshake.");
              return connection_or_launch_v3_or_handshake(conn);
            } else {
              log_debug(LD_OR, "Done with initial SSL handshake (client-side)."
                        " Requesting renegotiation.");
              conn->_base.state = OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING;
              goto again;
            }
          }
          // log_notice(LD_OR,"Done. state was %d.", conn->_base.state);
        } else {
          /* v2/v3 handshake, but not a client. */
          log_debug(LD_OR, "Done with initial SSL handshake (server-side). "
                           "Expecting renegotiation or VERSIONS cell");
          tor_tls_set_renegotiate_callback(conn->tls,
                                           connection_or_tls_renegotiated_cb,
                                           conn);
          conn->_base.state = OR_CONN_STATE_TLS_SERVER_RENEGOTIATING;
          connection_stop_writing(TO_CONN(conn));
          connection_start_reading(TO_CONN(conn));
          return 0;
        }
      }
      return connection_tls_finish_handshake(conn);
    case TOR_TLS_WANTWRITE:
      connection_start_writing(TO_CONN(conn));
      log_debug(LD_OR,"wanted write");
      return 0;
    case TOR_TLS_WANTREAD: /* handshaking conns are *always* reading */
      log_debug(LD_OR,"wanted read");
      return 0;
    case TOR_TLS_CLOSE:
      log_info(LD_OR,"tls closed. breaking connection.");
      return -1;
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

Definition at line 1141 of file connection_or.c.

{
  conn->_base.state = OR_CONN_STATE_TLS_HANDSHAKING;
  tor_assert(!conn->tls);
  conn->tls = tor_tls_new(conn->_base.s, receiving);
  if (!conn->tls) {
    log_warn(LD_BUG,"tor_tls_new failed. Closing.");
    return -1;
  }
  tor_tls_set_logged_address(conn->tls, // XXX client and relay?
      escaped_safe_str(conn->_base.address));

#ifdef USE_BUFFEREVENTS
  if (connection_type_uses_bufferevent(TO_CONN(conn))) {
    const int filtering = get_options()->_UseFilteringSSLBufferevents;
    struct bufferevent *b =
      tor_tls_init_bufferevent(conn->tls, conn->_base.bufev, conn->_base.s,
                               receiving, filtering);
    if (!b) {
      log_warn(LD_BUG,"tor_tls_init_bufferevent failed. Closing.");
      return -1;
    }
    conn->_base.bufev = b;
    if (conn->bucket_cfg)
      tor_set_bufferevent_rate_limit(conn->_base.bufev, conn->bucket_cfg);
    connection_enable_rate_limiting(TO_CONN(conn));

    connection_configure_bufferevent_callbacks(TO_CONN(conn));
    bufferevent_setcb(b,
                      connection_handle_read_cb,
                      connection_handle_write_cb,
                      connection_or_handle_event_cb,/* overriding this one*/
                      TO_CONN(conn));
  }
#endif
  connection_start_reading(TO_CONN(conn));
  log_debug(LD_HANDSHAKE,"starting TLS handshake on fd %d", conn->_base.s);
  note_crypto_pk_op(receiving ? TLS_HANDSHAKE_S : TLS_HANDSHAKE_C);

  IF_HAS_BUFFEREVENT(TO_CONN(conn), {
    /* ???? */;
  }) ELSE_IF_NO_BUFFEREVENT {
    if (connection_tls_continue_handshake(conn) < 0)
      return -1;
  }
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

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.

Definition at line 1909 of file connection_or.c.

{
  int i;
  for (i = 0; i < n_or_protocol_versions; ++i) {
    if (or_protocol_versions[i] == v)
      return 1;
  }
  return 0;
}

Here is the caller graph for this function:

Free all storage held by state.

Definition at line 1642 of file connection_or.c.

{
  if (!state)
    return;
  crypto_digest_free(state->digest_sent);
  crypto_digest_free(state->digest_received);
  tor_cert_free(state->auth_cert);
  tor_cert_free(state->id_cert);
  memset(state, 0xBE, sizeof(or_handshake_state_t));
  tor_free(state);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void or_handshake_state_record_cell ( or_handshake_state_t state,
const cell_t cell,
int  incoming 
)

Remember that cell has been transmitted (if incoming is false) or received (if incoming is true) during a V3 handshake using state.

(We don't record the cell, but we keep a digest of everything sent or received during the v3 handshake, and the client signs it in an authenticate cell.)

Definition at line 1664 of file connection_or.c.

{
  crypto_digest_t *d, **dptr;
  packed_cell_t packed;
  if (incoming) {
    if (!state->digest_received_data)
      return;
  } else {
    if (!state->digest_sent_data)
      return;
  }
  if (!incoming) {
    log_warn(LD_BUG, "We shouldn't be sending any non-variable-length cells "
             "while making a handshake digest.  But we think we are sending "
             "one with type %d.", (int)cell->command);
  }
  dptr = incoming ? &state->digest_received : &state->digest_sent;
  if (! *dptr)
    *dptr = crypto_digest256_new(DIGEST_SHA256);

  d = *dptr;
  /* Re-packing like this is a little inefficient, but we don't have to do
     this very often at all. */
  cell_pack(&packed, cell);
  crypto_digest_add_bytes(d, packed.body, sizeof(packed.body));
  memset(&packed, 0, sizeof(packed));
}

Here is the call graph for this function:

Here is the caller graph for this function:

void or_handshake_state_record_var_cell ( or_handshake_state_t state,
const var_cell_t cell,
int  incoming 
)

Remember that a variable-length cell has been transmitted (if incoming is false) or received (if incoming is true) during a V3 handshake using state.

(We don't record the cell, but we keep a digest of everything sent or received during the v3 handshake, and the client signs it in an authenticate cell.)

Definition at line 1703 of file connection_or.c.

{
  crypto_digest_t *d, **dptr;
  char buf[VAR_CELL_HEADER_SIZE];
  if (incoming) {
    if (!state->digest_received_data)
      return;
  } else {
    if (!state->digest_sent_data)
      return;
  }
  dptr = incoming ? &state->digest_received : &state->digest_sent;
  if (! *dptr)
    *dptr = crypto_digest256_new(DIGEST_SHA256);

  d = *dptr;

  var_cell_pack_header(cell, buf);
  crypto_digest_add_bytes(d, buf, sizeof(buf));
  crypto_digest_add_bytes(d, (const char *)cell->payload, cell->payload_len);

  memset(buf, 0, sizeof(buf));
}

Here is the call graph for this function:

Here is the caller graph for this function:

void var_cell_free ( var_cell_t cell)

Release all space held by cell.

Definition at line 339 of file connection_or.c.

{
  tor_free(cell);
}

Here is the caller graph for this function:

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.

Definition at line 327 of file connection_or.c.

{
  size_t size = STRUCT_OFFSET(var_cell_t, payload) + payload_len;
  var_cell_t *cell = tor_malloc(size);
  cell->payload_len = payload_len;
  cell->command = 0;
  cell->circ_id = 0;
  return cell;
}

Here is the caller graph for this function:

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.

Definition at line 317 of file connection_or.c.

{
  set_uint16(hdr_out, htons(cell->circ_id));
  set_uint8(hdr_out+2, cell->command);
  set_uint16(hdr_out+3, htons(cell->payload_len));
}

Here is the call graph for this function:

Here is the caller graph for this function: