mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-09-21 05:26:20 +02:00
Use channel_t rather than or_connection_t for circuits
This commit is contained in:
parent
15303c32ec
commit
32337502f1
@ -12,9 +12,11 @@
|
|||||||
#define CIRCUIT_PRIVATE
|
#define CIRCUIT_PRIVATE
|
||||||
|
|
||||||
#include "or.h"
|
#include "or.h"
|
||||||
|
#include "channel.h"
|
||||||
#include "circuitbuild.h"
|
#include "circuitbuild.h"
|
||||||
#include "circuitlist.h"
|
#include "circuitlist.h"
|
||||||
#include "circuituse.h"
|
#include "circuituse.h"
|
||||||
|
#include "command.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "confparse.h"
|
#include "confparse.h"
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
@ -125,6 +127,9 @@ static int unit_tests = 0;
|
|||||||
|
|
||||||
/********* END VARIABLES ************/
|
/********* END VARIABLES ************/
|
||||||
|
|
||||||
|
static channel_t * channel_connect_for_circuit(const tor_addr_t *addr,
|
||||||
|
uint16_t port,
|
||||||
|
const char *id_digest);
|
||||||
static int circuit_deliver_create_cell(circuit_t *circ,
|
static int circuit_deliver_create_cell(circuit_t *circ,
|
||||||
uint8_t cell_type, const char *payload);
|
uint8_t cell_type, const char *payload);
|
||||||
static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit);
|
static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit);
|
||||||
@ -141,6 +146,22 @@ static void bridge_free(bridge_info_t *bridge);
|
|||||||
static int entry_guard_inc_first_hop_count(entry_guard_t *guard);
|
static int entry_guard_inc_first_hop_count(entry_guard_t *guard);
|
||||||
static void pathbias_count_success(origin_circuit_t *circ);
|
static void pathbias_count_success(origin_circuit_t *circ);
|
||||||
|
|
||||||
|
/** This function tries to get a channel to the specified endpoint,
|
||||||
|
* and then calls command_setup_channel() to give it the right
|
||||||
|
* callbacks.
|
||||||
|
*/
|
||||||
|
static channel_t *
|
||||||
|
channel_connect_for_circuit(const tor_addr_t *addr, uint16_t port,
|
||||||
|
const char *id_digest)
|
||||||
|
{
|
||||||
|
channel_t *chan;
|
||||||
|
|
||||||
|
chan = channel_connect(addr, port, id_digest);
|
||||||
|
if (chan) command_setup_channel(chan);
|
||||||
|
|
||||||
|
return chan;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function decides if CBT learning should be disabled. It returns
|
* This function decides if CBT learning should be disabled. It returns
|
||||||
* true if one or more of the following four conditions are met:
|
* true if one or more of the following four conditions are met:
|
||||||
@ -1683,26 +1704,30 @@ circuit_build_times_set_timeout(circuit_build_times_t *cbt)
|
|||||||
* Return it, or 0 if can't get a unique circ_id.
|
* Return it, or 0 if can't get a unique circ_id.
|
||||||
*/
|
*/
|
||||||
static circid_t
|
static circid_t
|
||||||
get_unique_circ_id_by_conn(or_connection_t *conn)
|
get_unique_circ_id_by_chan(channel_t *chan)
|
||||||
{
|
{
|
||||||
circid_t test_circ_id;
|
circid_t test_circ_id;
|
||||||
circid_t attempts=0;
|
circid_t attempts=0;
|
||||||
circid_t high_bit;
|
circid_t high_bit;
|
||||||
|
|
||||||
tor_assert(conn);
|
tor_assert(chan);
|
||||||
if (conn->circ_id_type == CIRC_ID_TYPE_NEITHER) {
|
tor_assert(!(chan->is_listener));
|
||||||
log_warn(LD_BUG, "Trying to pick a circuit ID for a connection from "
|
|
||||||
|
if (chan->u.cell_chan.circ_id_type == CIRC_ID_TYPE_NEITHER) {
|
||||||
|
log_warn(LD_BUG,
|
||||||
|
"Trying to pick a circuit ID for a connection from "
|
||||||
"a client with no identity.");
|
"a client with no identity.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
high_bit = (conn->circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0;
|
high_bit =
|
||||||
|
(chan->u.cell_chan.circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0;
|
||||||
do {
|
do {
|
||||||
/* Sequentially iterate over test_circ_id=1...1<<15-1 until we find a
|
/* Sequentially iterate over test_circ_id=1...1<<15-1 until we find a
|
||||||
* circID such that (high_bit|test_circ_id) is not already used. */
|
* circID such that (high_bit|test_circ_id) is not already used. */
|
||||||
test_circ_id = conn->next_circ_id++;
|
test_circ_id = chan->u.cell_chan.next_circ_id++;
|
||||||
if (test_circ_id == 0 || test_circ_id >= 1<<15) {
|
if (test_circ_id == 0 || test_circ_id >= 1<<15) {
|
||||||
test_circ_id = 1;
|
test_circ_id = 1;
|
||||||
conn->next_circ_id = 2;
|
chan->u.cell_chan.next_circ_id = 2;
|
||||||
}
|
}
|
||||||
if (++attempts > 1<<15) {
|
if (++attempts > 1<<15) {
|
||||||
/* Make sure we don't loop forever if all circ_id's are used. This
|
/* Make sure we don't loop forever if all circ_id's are used. This
|
||||||
@ -1712,7 +1737,7 @@ get_unique_circ_id_by_conn(or_connection_t *conn)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
test_circ_id |= high_bit;
|
test_circ_id |= high_bit;
|
||||||
} while (circuit_id_in_use_on_orconn(test_circ_id, conn));
|
} while (circuit_id_in_use_on_channel(test_circ_id, chan));
|
||||||
return test_circ_id;
|
return test_circ_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1891,9 +1916,9 @@ onion_populate_cpath(origin_circuit_t *circ)
|
|||||||
origin_circuit_t *
|
origin_circuit_t *
|
||||||
origin_circuit_init(uint8_t purpose, int flags)
|
origin_circuit_init(uint8_t purpose, int flags)
|
||||||
{
|
{
|
||||||
/* sets circ->p_circ_id and circ->p_conn */
|
/* sets circ->p_circ_id and circ->p_chan */
|
||||||
origin_circuit_t *circ = origin_circuit_new();
|
origin_circuit_t *circ = origin_circuit_new();
|
||||||
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OR_WAIT);
|
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_CHAN_WAIT);
|
||||||
circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
|
circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
|
||||||
circ->build_state->onehop_tunnel =
|
circ->build_state->onehop_tunnel =
|
||||||
((flags & CIRCLAUNCH_ONEHOP_TUNNEL) ? 1 : 0);
|
((flags & CIRCLAUNCH_ONEHOP_TUNNEL) ? 1 : 0);
|
||||||
@ -1945,7 +1970,7 @@ int
|
|||||||
circuit_handle_first_hop(origin_circuit_t *circ)
|
circuit_handle_first_hop(origin_circuit_t *circ)
|
||||||
{
|
{
|
||||||
crypt_path_t *firsthop;
|
crypt_path_t *firsthop;
|
||||||
or_connection_t *n_conn;
|
channel_t *n_chan;
|
||||||
int err_reason = 0;
|
int err_reason = 0;
|
||||||
const char *msg = NULL;
|
const char *msg = NULL;
|
||||||
int should_launch = 0;
|
int should_launch = 0;
|
||||||
@ -1959,12 +1984,12 @@ circuit_handle_first_hop(origin_circuit_t *circ)
|
|||||||
fmt_addr(&firsthop->extend_info->addr),
|
fmt_addr(&firsthop->extend_info->addr),
|
||||||
firsthop->extend_info->port);
|
firsthop->extend_info->port);
|
||||||
|
|
||||||
n_conn = connection_or_get_for_extend(firsthop->extend_info->identity_digest,
|
n_chan = channel_get_for_extend(firsthop->extend_info->identity_digest,
|
||||||
&firsthop->extend_info->addr,
|
&firsthop->extend_info->addr,
|
||||||
&msg,
|
&msg,
|
||||||
&should_launch);
|
&should_launch);
|
||||||
|
|
||||||
if (!n_conn) {
|
if (!n_chan) {
|
||||||
/* not currently connected in a useful way. */
|
/* not currently connected in a useful way. */
|
||||||
log_info(LD_CIRC, "Next router is %s: %s",
|
log_info(LD_CIRC, "Next router is %s: %s",
|
||||||
safe_str_client(extend_info_describe(firsthop->extend_info)),
|
safe_str_client(extend_info_describe(firsthop->extend_info)),
|
||||||
@ -1974,10 +1999,11 @@ circuit_handle_first_hop(origin_circuit_t *circ)
|
|||||||
if (should_launch) {
|
if (should_launch) {
|
||||||
if (circ->build_state->onehop_tunnel)
|
if (circ->build_state->onehop_tunnel)
|
||||||
control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DIR, 0);
|
control_event_bootstrap(BOOTSTRAP_STATUS_CONN_DIR, 0);
|
||||||
n_conn = connection_or_connect(&firsthop->extend_info->addr,
|
n_chan = channel_connect_for_circuit(
|
||||||
|
&firsthop->extend_info->addr,
|
||||||
firsthop->extend_info->port,
|
firsthop->extend_info->port,
|
||||||
firsthop->extend_info->identity_digest);
|
firsthop->extend_info->identity_digest);
|
||||||
if (!n_conn) { /* connect failed, forget the whole thing */
|
if (!n_chan) { /* connect failed, forget the whole thing */
|
||||||
log_info(LD_CIRC,"connect to firsthop failed. Closing.");
|
log_info(LD_CIRC,"connect to firsthop failed. Closing.");
|
||||||
return -END_CIRC_REASON_CONNECTFAILED;
|
return -END_CIRC_REASON_CONNECTFAILED;
|
||||||
}
|
}
|
||||||
@ -1985,13 +2011,13 @@ circuit_handle_first_hop(origin_circuit_t *circ)
|
|||||||
|
|
||||||
log_debug(LD_CIRC,"connecting in progress (or finished). Good.");
|
log_debug(LD_CIRC,"connecting in progress (or finished). Good.");
|
||||||
/* return success. The onion/circuit/etc will be taken care of
|
/* return success. The onion/circuit/etc will be taken care of
|
||||||
* automatically (may already have been) whenever n_conn reaches
|
* automatically (may already have been) whenever n_chan reaches
|
||||||
* OR_CONN_STATE_OPEN.
|
* OR_CONN_STATE_OPEN.
|
||||||
*/
|
*/
|
||||||
return 0;
|
return 0;
|
||||||
} else { /* it's already open. use it. */
|
} else { /* it's already open. use it. */
|
||||||
tor_assert(!circ->_base.n_hop);
|
tor_assert(!circ->_base.n_hop);
|
||||||
circ->_base.n_conn = n_conn;
|
circ->_base.n_chan = n_chan;
|
||||||
log_debug(LD_CIRC,"Conn open. Delivering first onion skin.");
|
log_debug(LD_CIRC,"Conn open. Delivering first onion skin.");
|
||||||
if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) {
|
if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) {
|
||||||
log_info(LD_CIRC,"circuit_send_next_onion_skin failed.");
|
log_info(LD_CIRC,"circuit_send_next_onion_skin failed.");
|
||||||
@ -2007,48 +2033,51 @@ circuit_handle_first_hop(origin_circuit_t *circ)
|
|||||||
* Status is 1 if connect succeeded, or 0 if connect failed.
|
* Status is 1 if connect succeeded, or 0 if connect failed.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
circuit_n_conn_done(or_connection_t *or_conn, int status)
|
circuit_n_chan_done(channel_t *chan, int status)
|
||||||
{
|
{
|
||||||
smartlist_t *pending_circs;
|
smartlist_t *pending_circs;
|
||||||
int err_reason = 0;
|
int err_reason = 0;
|
||||||
|
|
||||||
log_debug(LD_CIRC,"or_conn to %s/%s, status=%d",
|
tor_assert(chan);
|
||||||
or_conn->nickname ? or_conn->nickname : "NULL",
|
tor_assert(!(chan->is_listener));
|
||||||
or_conn->_base.address, status);
|
|
||||||
|
log_debug(LD_CIRC,"chan to %s/%s, status=%d",
|
||||||
|
chan->u.cell_chan.nickname ?
|
||||||
|
chan->u.cell_chan.nickname : "NULL",
|
||||||
|
channel_get_canonical_remote_descr(chan), status);
|
||||||
|
|
||||||
pending_circs = smartlist_new();
|
pending_circs = smartlist_new();
|
||||||
circuit_get_all_pending_on_or_conn(pending_circs, or_conn);
|
circuit_get_all_pending_on_channel(pending_circs, chan);
|
||||||
|
|
||||||
SMARTLIST_FOREACH_BEGIN(pending_circs, circuit_t *, circ)
|
SMARTLIST_FOREACH_BEGIN(pending_circs, circuit_t *, circ)
|
||||||
{
|
{
|
||||||
/* These checks are redundant wrt get_all_pending_on_or_conn, but I'm
|
/* These checks are redundant wrt get_all_pending_on_or_conn, but I'm
|
||||||
* leaving them in in case it's possible for the status of a circuit to
|
* leaving them in in case it's possible for the status of a circuit to
|
||||||
* change as we're going down the list. */
|
* change as we're going down the list. */
|
||||||
if (circ->marked_for_close || circ->n_conn || !circ->n_hop ||
|
if (circ->marked_for_close || circ->n_chan || !circ->n_hop ||
|
||||||
circ->state != CIRCUIT_STATE_OR_WAIT)
|
circ->state != CIRCUIT_STATE_CHAN_WAIT)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (tor_digest_is_zero(circ->n_hop->identity_digest)) {
|
if (tor_digest_is_zero(circ->n_hop->identity_digest)) {
|
||||||
/* Look at addr/port. This is an unkeyed connection. */
|
/* Look at addr/port. This is an unkeyed connection. */
|
||||||
if (!tor_addr_eq(&circ->n_hop->addr, &or_conn->_base.addr) ||
|
if (!channel_matches_extend_info(chan, circ->n_hop))
|
||||||
circ->n_hop->port != or_conn->_base.port)
|
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
/* We expected a key. See if it's the right one. */
|
/* We expected a key. See if it's the right one. */
|
||||||
if (tor_memneq(or_conn->identity_digest,
|
if (tor_memneq(chan->u.cell_chan.identity_digest,
|
||||||
circ->n_hop->identity_digest, DIGEST_LEN))
|
circ->n_hop->identity_digest, DIGEST_LEN))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!status) { /* or_conn failed; close circ */
|
if (!status) { /* chan failed; close circ */
|
||||||
log_info(LD_CIRC,"or_conn failed. Closing circ.");
|
log_info(LD_CIRC,"Channel failed; closing circ.");
|
||||||
circuit_mark_for_close(circ, END_CIRC_REASON_OR_CONN_CLOSED);
|
circuit_mark_for_close(circ, END_CIRC_REASON_CHANNEL_CLOSED);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
log_debug(LD_CIRC, "Found circ, sending create cell.");
|
log_debug(LD_CIRC, "Found circ, sending create cell.");
|
||||||
/* circuit_deliver_create_cell will set n_circ_id and add us to
|
/* circuit_deliver_create_cell will set n_circ_id and add us to
|
||||||
* orconn_circuid_circuit_map, so we don't need to call
|
* chan_circuid_circuit_map, so we don't need to call
|
||||||
* set_circid_orconn here. */
|
* set_circid_chan here. */
|
||||||
circ->n_conn = or_conn;
|
circ->n_chan = chan;
|
||||||
extend_info_free(circ->n_hop);
|
extend_info_free(circ->n_hop);
|
||||||
circ->n_hop = NULL;
|
circ->n_hop = NULL;
|
||||||
|
|
||||||
@ -2064,13 +2093,13 @@ circuit_n_conn_done(or_connection_t *or_conn, int status)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* pull the create cell out of circ->onionskin, and send it */
|
/* pull the create cell out of circ->onionskin, and send it */
|
||||||
tor_assert(circ->n_conn_onionskin);
|
tor_assert(circ->n_chan_onionskin);
|
||||||
if (circuit_deliver_create_cell(circ,CELL_CREATE,
|
if (circuit_deliver_create_cell(circ,CELL_CREATE,
|
||||||
circ->n_conn_onionskin)<0) {
|
circ->n_chan_onionskin)<0) {
|
||||||
circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
|
circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tor_free(circ->n_conn_onionskin);
|
tor_free(circ->n_chan_onionskin);
|
||||||
circuit_set_state(circ, CIRCUIT_STATE_OPEN);
|
circuit_set_state(circ, CIRCUIT_STATE_OPEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2079,7 +2108,7 @@ circuit_n_conn_done(or_connection_t *or_conn, int status)
|
|||||||
smartlist_free(pending_circs);
|
smartlist_free(pending_circs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Find a new circid that isn't currently in use on the circ->n_conn
|
/** Find a new circid that isn't currently in use on the circ->n_chan
|
||||||
* for the outgoing
|
* for the outgoing
|
||||||
* circuit <b>circ</b>, and deliver a cell of type <b>cell_type</b>
|
* circuit <b>circ</b>, and deliver a cell of type <b>cell_type</b>
|
||||||
* (either CELL_CREATE or CELL_CREATE_FAST) with payload <b>payload</b>
|
* (either CELL_CREATE or CELL_CREATE_FAST) with payload <b>payload</b>
|
||||||
@ -2094,29 +2123,29 @@ circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type,
|
|||||||
circid_t id;
|
circid_t id;
|
||||||
|
|
||||||
tor_assert(circ);
|
tor_assert(circ);
|
||||||
tor_assert(circ->n_conn);
|
tor_assert(circ->n_chan);
|
||||||
tor_assert(payload);
|
tor_assert(payload);
|
||||||
tor_assert(cell_type == CELL_CREATE || cell_type == CELL_CREATE_FAST);
|
tor_assert(cell_type == CELL_CREATE || cell_type == CELL_CREATE_FAST);
|
||||||
|
|
||||||
id = get_unique_circ_id_by_conn(circ->n_conn);
|
id = get_unique_circ_id_by_chan(circ->n_chan);
|
||||||
if (!id) {
|
if (!id) {
|
||||||
log_warn(LD_CIRC,"failed to get unique circID.");
|
log_warn(LD_CIRC,"failed to get unique circID.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
log_debug(LD_CIRC,"Chosen circID %u.", id);
|
log_debug(LD_CIRC,"Chosen circID %u.", id);
|
||||||
circuit_set_n_circid_orconn(circ, id, circ->n_conn);
|
circuit_set_n_circid_chan(circ, id, circ->n_chan);
|
||||||
|
|
||||||
memset(&cell, 0, sizeof(cell_t));
|
memset(&cell, 0, sizeof(cell_t));
|
||||||
cell.command = cell_type;
|
cell.command = cell_type;
|
||||||
cell.circ_id = circ->n_circ_id;
|
cell.circ_id = circ->n_circ_id;
|
||||||
|
|
||||||
memcpy(cell.payload, payload, ONIONSKIN_CHALLENGE_LEN);
|
memcpy(cell.payload, payload, ONIONSKIN_CHALLENGE_LEN);
|
||||||
append_cell_to_circuit_queue(circ, circ->n_conn, &cell,
|
append_cell_to_circuit_queue(circ, circ->n_chan, &cell,
|
||||||
CELL_DIRECTION_OUT, 0);
|
CELL_DIRECTION_OUT, 0);
|
||||||
|
|
||||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||||
/* mark it so it gets better rate limiting treatment. */
|
/* mark it so it gets better rate limiting treatment. */
|
||||||
circ->n_conn->client_used = time(NULL);
|
channel_timestamp_client(circ->n_chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -2218,7 +2247,8 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
|
|||||||
else
|
else
|
||||||
control_event_bootstrap(BOOTSTRAP_STATUS_CIRCUIT_CREATE, 0);
|
control_event_bootstrap(BOOTSTRAP_STATUS_CIRCUIT_CREATE, 0);
|
||||||
|
|
||||||
node = node_get_by_id(circ->_base.n_conn->identity_digest);
|
tor_assert(!(circ->_base.n_chan->is_listener));
|
||||||
|
node = node_get_by_id(circ->_base.n_chan->u.cell_chan.identity_digest);
|
||||||
fast = should_use_create_fast_for_circuit(circ);
|
fast = should_use_create_fast_for_circuit(circ);
|
||||||
if (!fast) {
|
if (!fast) {
|
||||||
/* We are an OR and we know the right onion key: we should
|
/* We are an OR and we know the right onion key: we should
|
||||||
@ -2386,7 +2416,7 @@ circuit_note_clock_jumped(int seconds_elapsed)
|
|||||||
int
|
int
|
||||||
circuit_extend(cell_t *cell, circuit_t *circ)
|
circuit_extend(cell_t *cell, circuit_t *circ)
|
||||||
{
|
{
|
||||||
or_connection_t *n_conn;
|
channel_t *n_chan;
|
||||||
relay_header_t rh;
|
relay_header_t rh;
|
||||||
char *onionskin;
|
char *onionskin;
|
||||||
char *id_digest=NULL;
|
char *id_digest=NULL;
|
||||||
@ -2396,9 +2426,9 @@ circuit_extend(cell_t *cell, circuit_t *circ)
|
|||||||
const char *msg = NULL;
|
const char *msg = NULL;
|
||||||
int should_launch = 0;
|
int should_launch = 0;
|
||||||
|
|
||||||
if (circ->n_conn) {
|
if (circ->n_chan) {
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||||
"n_conn already set. Bug/attack. Closing.");
|
"n_chan already set. Bug/attack. Closing.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (circ->n_hop) {
|
if (circ->n_hop) {
|
||||||
@ -2457,19 +2487,22 @@ circuit_extend(cell_t *cell, circuit_t *circ)
|
|||||||
/* Next, check if we're being asked to connect to the hop that the
|
/* Next, check if we're being asked to connect to the hop that the
|
||||||
* extend cell came from. There isn't any reason for that, and it can
|
* extend cell came from. There isn't any reason for that, and it can
|
||||||
* assist circular-path attacks. */
|
* assist circular-path attacks. */
|
||||||
if (tor_memeq(id_digest, TO_OR_CIRCUIT(circ)->p_conn->identity_digest,
|
tor_assert(!(TO_OR_CIRCUIT(circ)->p_chan->is_listener));
|
||||||
|
if (tor_memeq(id_digest,
|
||||||
|
TO_OR_CIRCUIT(circ)->p_chan->
|
||||||
|
u.cell_chan.identity_digest,
|
||||||
DIGEST_LEN)) {
|
DIGEST_LEN)) {
|
||||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||||
"Client asked me to extend back to the previous hop.");
|
"Client asked me to extend back to the previous hop.");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
n_conn = connection_or_get_for_extend(id_digest,
|
n_chan = channel_get_for_extend(id_digest,
|
||||||
&n_addr,
|
&n_addr,
|
||||||
&msg,
|
&msg,
|
||||||
&should_launch);
|
&should_launch);
|
||||||
|
|
||||||
if (!n_conn) {
|
if (!n_chan) {
|
||||||
log_debug(LD_CIRC|LD_OR,"Next router (%s:%d): %s",
|
log_debug(LD_CIRC|LD_OR,"Next router (%s:%d): %s",
|
||||||
fmt_addr(&n_addr), (int)n_port, msg?msg:"????");
|
fmt_addr(&n_addr), (int)n_port, msg?msg:"????");
|
||||||
|
|
||||||
@ -2478,31 +2511,32 @@ circuit_extend(cell_t *cell, circuit_t *circ)
|
|||||||
NULL /*onion_key*/,
|
NULL /*onion_key*/,
|
||||||
&n_addr, n_port);
|
&n_addr, n_port);
|
||||||
|
|
||||||
circ->n_conn_onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
|
circ->n_chan_onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
|
||||||
memcpy(circ->n_conn_onionskin, onionskin, ONIONSKIN_CHALLENGE_LEN);
|
memcpy(circ->n_chan_onionskin, onionskin, ONIONSKIN_CHALLENGE_LEN);
|
||||||
circuit_set_state(circ, CIRCUIT_STATE_OR_WAIT);
|
circuit_set_state(circ, CIRCUIT_STATE_CHAN_WAIT);
|
||||||
|
|
||||||
if (should_launch) {
|
if (should_launch) {
|
||||||
/* we should try to open a connection */
|
/* we should try to open a connection */
|
||||||
n_conn = connection_or_connect(&n_addr, n_port, id_digest);
|
n_chan = channel_connect_for_circuit(&n_addr, n_port, id_digest);
|
||||||
if (!n_conn) {
|
if (!n_chan) {
|
||||||
log_info(LD_CIRC,"Launching n_conn failed. Closing circuit.");
|
log_info(LD_CIRC,"Launching n_chan failed. Closing circuit.");
|
||||||
circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED);
|
circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
log_debug(LD_CIRC,"connecting in progress (or finished). Good.");
|
log_debug(LD_CIRC,"connecting in progress (or finished). Good.");
|
||||||
}
|
}
|
||||||
/* return success. The onion/circuit/etc will be taken care of
|
/* return success. The onion/circuit/etc will be taken care of
|
||||||
* automatically (may already have been) whenever n_conn reaches
|
* automatically (may already have been) whenever n_chan reaches
|
||||||
* OR_CONN_STATE_OPEN.
|
* OR_CONN_STATE_OPEN.
|
||||||
*/
|
*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tor_assert(!circ->n_hop); /* Connection is already established. */
|
tor_assert(!circ->n_hop); /* Connection is already established. */
|
||||||
circ->n_conn = n_conn;
|
circ->n_chan = n_chan;
|
||||||
log_debug(LD_CIRC,"n_conn is %s:%u",
|
log_debug(LD_CIRC,
|
||||||
n_conn->_base.address,n_conn->_base.port);
|
"n_chan is %s",
|
||||||
|
channel_get_canonical_remote_descr(n_chan));
|
||||||
|
|
||||||
if (circuit_deliver_create_cell(circ, CELL_CREATE, onionskin) < 0)
|
if (circuit_deliver_create_cell(circ, CELL_CREATE, onionskin) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -2699,8 +2733,9 @@ pathbias_count_first_hop(origin_circuit_t *circ)
|
|||||||
if (!circ->has_opened) {
|
if (!circ->has_opened) {
|
||||||
entry_guard_t *guard;
|
entry_guard_t *guard;
|
||||||
|
|
||||||
|
tor_assert(!(circ->_base.n_chan->is_listener));
|
||||||
guard = entry_guard_get_by_id_digest(
|
guard = entry_guard_get_by_id_digest(
|
||||||
circ->_base.n_conn->identity_digest);
|
circ->_base.n_chan->u.cell_chan.identity_digest);
|
||||||
if (guard) {
|
if (guard) {
|
||||||
if (circ->path_state == PATH_STATE_NEW_CIRC) {
|
if (circ->path_state == PATH_STATE_NEW_CIRC) {
|
||||||
circ->path_state = PATH_STATE_DID_FIRST_HOP;
|
circ->path_state = PATH_STATE_DID_FIRST_HOP;
|
||||||
@ -2770,6 +2805,7 @@ pathbias_count_success(origin_circuit_t *circ)
|
|||||||
static ratelim_t success_notice_limit =
|
static ratelim_t success_notice_limit =
|
||||||
RATELIM_INIT(SUCCESS_NOTICE_INTERVAL);
|
RATELIM_INIT(SUCCESS_NOTICE_INTERVAL);
|
||||||
char *rate_msg = NULL;
|
char *rate_msg = NULL;
|
||||||
|
entry_guard_t *guard = NULL;
|
||||||
|
|
||||||
/* We can't do path bias accounting without entry guards.
|
/* We can't do path bias accounting without entry guards.
|
||||||
* Testing and controller circuits also have no guards. */
|
* Testing and controller circuits also have no guards. */
|
||||||
@ -2804,8 +2840,10 @@ pathbias_count_success(origin_circuit_t *circ)
|
|||||||
|
|
||||||
/* Don't count cannibalized/reused circs for path bias */
|
/* Don't count cannibalized/reused circs for path bias */
|
||||||
if (!circ->has_opened) {
|
if (!circ->has_opened) {
|
||||||
entry_guard_t *guard =
|
tor_assert(!(circ->_base.n_chan->is_listener));
|
||||||
entry_guard_get_by_id_digest(circ->_base.n_conn->identity_digest);
|
guard =
|
||||||
|
entry_guard_get_by_id_digest(circ->_base.n_chan->
|
||||||
|
u.cell_chan.identity_digest);
|
||||||
|
|
||||||
if (guard) {
|
if (guard) {
|
||||||
if (circ->path_state == PATH_STATE_DID_FIRST_HOP) {
|
if (circ->path_state == PATH_STATE_DID_FIRST_HOP) {
|
||||||
@ -3021,7 +3059,7 @@ circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer, int reason)
|
|||||||
* just give up.
|
* just give up.
|
||||||
*/
|
*/
|
||||||
circuit_mark_for_close(TO_CIRCUIT(circ),
|
circuit_mark_for_close(TO_CIRCUIT(circ),
|
||||||
END_CIRC_REASON_FLAG_REMOTE|reason);
|
END_CIRC_REASON_FLAG_REMOTE|END_CIRC_REASON_CHANNEL_CLOSED|reason);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -3095,12 +3133,12 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload,
|
|||||||
circ->is_first_hop = (cell_type == CELL_CREATED_FAST);
|
circ->is_first_hop = (cell_type == CELL_CREATED_FAST);
|
||||||
|
|
||||||
append_cell_to_circuit_queue(TO_CIRCUIT(circ),
|
append_cell_to_circuit_queue(TO_CIRCUIT(circ),
|
||||||
circ->p_conn, &cell, CELL_DIRECTION_IN, 0);
|
circ->p_chan, &cell, CELL_DIRECTION_IN, 0);
|
||||||
log_debug(LD_CIRC,"Finished sending '%s' cell.",
|
log_debug(LD_CIRC,"Finished sending '%s' cell.",
|
||||||
circ->is_first_hop ? "created_fast" : "created");
|
circ->is_first_hop ? "created_fast" : "created");
|
||||||
|
|
||||||
if (!is_local_addr(&circ->p_conn->_base.addr) &&
|
if (!channel_is_local(circ->p_chan) &&
|
||||||
!connection_or_nonopen_was_started_here(circ->p_conn)) {
|
!channel_is_outgoing(circ->p_chan)) {
|
||||||
/* record that we could process create cells from a non-local conn
|
/* record that we could process create cells from a non-local conn
|
||||||
* that we didn't initiate; presumably this means that create cells
|
* that we didn't initiate; presumably this means that create cells
|
||||||
* can reach us too. */
|
* can reach us too. */
|
||||||
|
@ -22,7 +22,7 @@ origin_circuit_t *circuit_establish_circuit(uint8_t purpose,
|
|||||||
extend_info_t *exit,
|
extend_info_t *exit,
|
||||||
int flags);
|
int flags);
|
||||||
int circuit_handle_first_hop(origin_circuit_t *circ);
|
int circuit_handle_first_hop(origin_circuit_t *circ);
|
||||||
void circuit_n_conn_done(or_connection_t *or_conn, int status);
|
void circuit_n_chan_done(channel_t *chan, int status);
|
||||||
int inform_testing_reachability(void);
|
int inform_testing_reachability(void);
|
||||||
int circuit_timeout_want_to_count_circ(origin_circuit_t *circ);
|
int circuit_timeout_want_to_count_circ(origin_circuit_t *circ);
|
||||||
int circuit_send_next_onion_skin(origin_circuit_t *circ);
|
int circuit_send_next_onion_skin(origin_circuit_t *circ);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
#include "or.h"
|
#include "or.h"
|
||||||
|
#include "channel.h"
|
||||||
#include "circuitbuild.h"
|
#include "circuitbuild.h"
|
||||||
#include "circuitlist.h"
|
#include "circuitlist.h"
|
||||||
#include "circuituse.h"
|
#include "circuituse.h"
|
||||||
@ -34,8 +35,8 @@
|
|||||||
/** A global list of all circuits at this hop. */
|
/** A global list of all circuits at this hop. */
|
||||||
circuit_t *global_circuitlist=NULL;
|
circuit_t *global_circuitlist=NULL;
|
||||||
|
|
||||||
/** A list of all the circuits in CIRCUIT_STATE_OR_WAIT. */
|
/** A list of all the circuits in CIRCUIT_STATE_CHAN_WAIT. */
|
||||||
static smartlist_t *circuits_pending_or_conns=NULL;
|
static smartlist_t *circuits_pending_chans = NULL;
|
||||||
|
|
||||||
static void circuit_free(circuit_t *circ);
|
static void circuit_free(circuit_t *circ);
|
||||||
static void circuit_free_cpath(crypt_path_t *cpath);
|
static void circuit_free_cpath(crypt_path_t *cpath);
|
||||||
@ -44,154 +45,156 @@ static void cpath_ref_decref(crypt_path_reference_t *cpath_ref);
|
|||||||
|
|
||||||
/********* END VARIABLES ************/
|
/********* END VARIABLES ************/
|
||||||
|
|
||||||
/** A map from OR connection and circuit ID to circuit. (Lookup performance is
|
/** A map from channel and circuit ID to circuit. (Lookup performance is
|
||||||
* very important here, since we need to do it every time a cell arrives.) */
|
* very important here, since we need to do it every time a cell arrives.) */
|
||||||
typedef struct orconn_circid_circuit_map_t {
|
typedef struct chan_circid_circuit_map_t {
|
||||||
HT_ENTRY(orconn_circid_circuit_map_t) node;
|
HT_ENTRY(chan_circid_circuit_map_t) node;
|
||||||
or_connection_t *or_conn;
|
channel_t *chan;
|
||||||
circid_t circ_id;
|
circid_t circ_id;
|
||||||
circuit_t *circuit;
|
circuit_t *circuit;
|
||||||
} orconn_circid_circuit_map_t;
|
} chan_circid_circuit_map_t;
|
||||||
|
|
||||||
/** Helper for hash tables: compare the OR connection and circuit ID for a and
|
/** Helper for hash tables: compare the channel and circuit ID for a and
|
||||||
* b, and return less than, equal to, or greater than zero appropriately.
|
* b, and return less than, equal to, or greater than zero appropriately.
|
||||||
*/
|
*/
|
||||||
static INLINE int
|
static INLINE int
|
||||||
_orconn_circid_entries_eq(orconn_circid_circuit_map_t *a,
|
_chan_circid_entries_eq(chan_circid_circuit_map_t *a,
|
||||||
orconn_circid_circuit_map_t *b)
|
chan_circid_circuit_map_t *b)
|
||||||
{
|
{
|
||||||
return a->or_conn == b->or_conn && a->circ_id == b->circ_id;
|
return a->chan == b->chan && a->circ_id == b->circ_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Helper: return a hash based on circuit ID and the pointer value of
|
/** Helper: return a hash based on circuit ID and the pointer value of
|
||||||
* or_conn in <b>a</b>. */
|
* chan in <b>a</b>. */
|
||||||
static INLINE unsigned int
|
static INLINE unsigned int
|
||||||
_orconn_circid_entry_hash(orconn_circid_circuit_map_t *a)
|
_chan_circid_entry_hash(chan_circid_circuit_map_t *a)
|
||||||
{
|
{
|
||||||
return (((unsigned)a->circ_id)<<8) ^ (unsigned)(uintptr_t)(a->or_conn);
|
return (((unsigned)a->circ_id)<<8) ^ (unsigned)(uintptr_t)(a->chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Map from [orconn,circid] to circuit. */
|
/** Map from [chan,circid] to circuit. */
|
||||||
static HT_HEAD(orconn_circid_map, orconn_circid_circuit_map_t)
|
static HT_HEAD(chan_circid_map, chan_circid_circuit_map_t)
|
||||||
orconn_circid_circuit_map = HT_INITIALIZER();
|
chan_circid_map = HT_INITIALIZER();
|
||||||
HT_PROTOTYPE(orconn_circid_map, orconn_circid_circuit_map_t, node,
|
HT_PROTOTYPE(chan_circid_map, chan_circid_circuit_map_t, node,
|
||||||
_orconn_circid_entry_hash, _orconn_circid_entries_eq)
|
_chan_circid_entry_hash, _chan_circid_entries_eq)
|
||||||
HT_GENERATE(orconn_circid_map, orconn_circid_circuit_map_t, node,
|
HT_GENERATE(chan_circid_map, chan_circid_circuit_map_t, node,
|
||||||
_orconn_circid_entry_hash, _orconn_circid_entries_eq, 0.6,
|
_chan_circid_entry_hash, _chan_circid_entries_eq, 0.6,
|
||||||
malloc, realloc, free)
|
malloc, realloc, free)
|
||||||
|
|
||||||
/** The most recently returned entry from circuit_get_by_circid_orconn;
|
/** The most recently returned entry from circuit_get_by_circid_chan;
|
||||||
* used to improve performance when many cells arrive in a row from the
|
* used to improve performance when many cells arrive in a row from the
|
||||||
* same circuit.
|
* same circuit.
|
||||||
*/
|
*/
|
||||||
orconn_circid_circuit_map_t *_last_circid_orconn_ent = NULL;
|
chan_circid_circuit_map_t *_last_circid_chan_ent = NULL;
|
||||||
|
|
||||||
/** Implementation helper for circuit_set_{p,n}_circid_orconn: A circuit ID
|
/** Implementation helper for circuit_set_{p,n}_circid_channel: A circuit ID
|
||||||
* and/or or_connection for circ has just changed from <b>old_conn, old_id</b>
|
* and/or channel for circ has just changed from <b>old_chan, old_id</b>
|
||||||
* to <b>conn, id</b>. Adjust the conn,circid map as appropriate, removing
|
* to <b>chan, id</b>. Adjust the chan,circid map as appropriate, removing
|
||||||
* the old entry (if any) and adding a new one. */
|
* the old entry (if any) and adding a new one. */
|
||||||
static void
|
static void
|
||||||
circuit_set_circid_orconn_helper(circuit_t *circ, int direction,
|
circuit_set_circid_chan_helper(circuit_t *circ, int direction,
|
||||||
circid_t id,
|
circid_t id,
|
||||||
or_connection_t *conn)
|
channel_t *chan)
|
||||||
{
|
{
|
||||||
orconn_circid_circuit_map_t search;
|
chan_circid_circuit_map_t search;
|
||||||
orconn_circid_circuit_map_t *found;
|
chan_circid_circuit_map_t *found;
|
||||||
or_connection_t *old_conn, **conn_ptr;
|
channel_t *old_chan, **chan_ptr;
|
||||||
circid_t old_id, *circid_ptr;
|
circid_t old_id, *circid_ptr;
|
||||||
int was_active, make_active;
|
int was_active, make_active;
|
||||||
|
|
||||||
|
if (chan) tor_assert(!(chan->is_listener));
|
||||||
|
|
||||||
if (direction == CELL_DIRECTION_OUT) {
|
if (direction == CELL_DIRECTION_OUT) {
|
||||||
conn_ptr = &circ->n_conn;
|
chan_ptr = &circ->n_chan;
|
||||||
circid_ptr = &circ->n_circ_id;
|
circid_ptr = &circ->n_circ_id;
|
||||||
was_active = circ->next_active_on_n_conn != NULL;
|
was_active = circ->next_active_on_n_chan != NULL;
|
||||||
make_active = circ->n_conn_cells.n > 0;
|
make_active = circ->n_chan_cells.n > 0;
|
||||||
} else {
|
} else {
|
||||||
or_circuit_t *c = TO_OR_CIRCUIT(circ);
|
or_circuit_t *c = TO_OR_CIRCUIT(circ);
|
||||||
conn_ptr = &c->p_conn;
|
chan_ptr = &c->p_chan;
|
||||||
circid_ptr = &c->p_circ_id;
|
circid_ptr = &c->p_circ_id;
|
||||||
was_active = c->next_active_on_p_conn != NULL;
|
was_active = c->next_active_on_p_chan != NULL;
|
||||||
make_active = c->p_conn_cells.n > 0;
|
make_active = c->p_chan_cells.n > 0;
|
||||||
}
|
}
|
||||||
old_conn = *conn_ptr;
|
old_chan = *chan_ptr;
|
||||||
old_id = *circid_ptr;
|
old_id = *circid_ptr;
|
||||||
|
|
||||||
if (id == old_id && conn == old_conn)
|
if (id == old_id && chan == old_chan)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_last_circid_orconn_ent &&
|
if (_last_circid_chan_ent &&
|
||||||
((old_id == _last_circid_orconn_ent->circ_id &&
|
((old_id == _last_circid_chan_ent->circ_id &&
|
||||||
old_conn == _last_circid_orconn_ent->or_conn) ||
|
old_chan == _last_circid_chan_ent->chan) ||
|
||||||
(id == _last_circid_orconn_ent->circ_id &&
|
(id == _last_circid_chan_ent->circ_id &&
|
||||||
conn == _last_circid_orconn_ent->or_conn))) {
|
chan == _last_circid_chan_ent->chan))) {
|
||||||
_last_circid_orconn_ent = NULL;
|
_last_circid_chan_ent = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (old_conn) { /* we may need to remove it from the conn-circid map */
|
if (old_chan) { /* we may need to remove it from the conn-circid map */
|
||||||
tor_assert(old_conn->_base.magic == OR_CONNECTION_MAGIC);
|
tor_assert(!(old_chan->is_listener));
|
||||||
search.circ_id = old_id;
|
search.circ_id = old_id;
|
||||||
search.or_conn = old_conn;
|
search.chan = old_chan;
|
||||||
found = HT_REMOVE(orconn_circid_map, &orconn_circid_circuit_map, &search);
|
found = HT_REMOVE(chan_circid_map, &chan_circid_map, &search);
|
||||||
if (found) {
|
if (found) {
|
||||||
tor_free(found);
|
tor_free(found);
|
||||||
--old_conn->n_circuits;
|
--old_chan->u.cell_chan.n_circuits;
|
||||||
}
|
}
|
||||||
if (was_active && old_conn != conn)
|
if (was_active && old_chan != chan)
|
||||||
make_circuit_inactive_on_conn(circ,old_conn);
|
make_circuit_inactive_on_chan(circ, old_chan);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Change the values only after we have possibly made the circuit inactive
|
/* Change the values only after we have possibly made the circuit inactive
|
||||||
* on the previous conn. */
|
* on the previous chan. */
|
||||||
*conn_ptr = conn;
|
*chan_ptr = chan;
|
||||||
*circid_ptr = id;
|
*circid_ptr = id;
|
||||||
|
|
||||||
if (conn == NULL)
|
if (chan == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* now add the new one to the conn-circid map */
|
/* now add the new one to the conn-circid map */
|
||||||
search.circ_id = id;
|
search.circ_id = id;
|
||||||
search.or_conn = conn;
|
search.chan = chan;
|
||||||
found = HT_FIND(orconn_circid_map, &orconn_circid_circuit_map, &search);
|
found = HT_FIND(chan_circid_map, &chan_circid_map, &search);
|
||||||
if (found) {
|
if (found) {
|
||||||
found->circuit = circ;
|
found->circuit = circ;
|
||||||
} else {
|
} else {
|
||||||
found = tor_malloc_zero(sizeof(orconn_circid_circuit_map_t));
|
found = tor_malloc_zero(sizeof(chan_circid_circuit_map_t));
|
||||||
found->circ_id = id;
|
found->circ_id = id;
|
||||||
found->or_conn = conn;
|
found->chan = chan;
|
||||||
found->circuit = circ;
|
found->circuit = circ;
|
||||||
HT_INSERT(orconn_circid_map, &orconn_circid_circuit_map, found);
|
HT_INSERT(chan_circid_map, &chan_circid_map, found);
|
||||||
}
|
}
|
||||||
if (make_active && old_conn != conn)
|
if (make_active && old_chan != chan)
|
||||||
make_circuit_active_on_conn(circ,conn);
|
make_circuit_active_on_chan(circ,chan);
|
||||||
|
|
||||||
++conn->n_circuits;
|
++chan->u.cell_chan.n_circuits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the p_conn field of a circuit <b>circ</b>, along
|
/** Set the p_conn field of a circuit <b>circ</b>, along
|
||||||
* with the corresponding circuit ID, and add the circuit as appropriate
|
* with the corresponding circuit ID, and add the circuit as appropriate
|
||||||
* to the (orconn,id)-\>circuit map. */
|
* to the (chan,id)-\>circuit map. */
|
||||||
void
|
void
|
||||||
circuit_set_p_circid_orconn(or_circuit_t *circ, circid_t id,
|
circuit_set_p_circid_chan(or_circuit_t *circ, circid_t id,
|
||||||
or_connection_t *conn)
|
channel_t *chan)
|
||||||
{
|
{
|
||||||
circuit_set_circid_orconn_helper(TO_CIRCUIT(circ), CELL_DIRECTION_IN,
|
circuit_set_circid_chan_helper(TO_CIRCUIT(circ), CELL_DIRECTION_IN,
|
||||||
id, conn);
|
id, chan);
|
||||||
|
|
||||||
if (conn)
|
if (chan)
|
||||||
tor_assert(bool_eq(circ->p_conn_cells.n, circ->next_active_on_p_conn));
|
tor_assert(bool_eq(circ->p_chan_cells.n, circ->next_active_on_p_chan));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the n_conn field of a circuit <b>circ</b>, along
|
/** Set the n_conn field of a circuit <b>circ</b>, along
|
||||||
* with the corresponding circuit ID, and add the circuit as appropriate
|
* with the corresponding circuit ID, and add the circuit as appropriate
|
||||||
* to the (orconn,id)-\>circuit map. */
|
* to the (chan,id)-\>circuit map. */
|
||||||
void
|
void
|
||||||
circuit_set_n_circid_orconn(circuit_t *circ, circid_t id,
|
circuit_set_n_circid_chan(circuit_t *circ, circid_t id,
|
||||||
or_connection_t *conn)
|
channel_t *chan)
|
||||||
{
|
{
|
||||||
circuit_set_circid_orconn_helper(circ, CELL_DIRECTION_OUT, id, conn);
|
circuit_set_circid_chan_helper(circ, CELL_DIRECTION_OUT, id, chan);
|
||||||
|
|
||||||
if (conn)
|
if (chan)
|
||||||
tor_assert(bool_eq(circ->n_conn_cells.n, circ->next_active_on_n_conn));
|
tor_assert(bool_eq(circ->n_chan_cells.n, circ->next_active_on_n_chan));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Change the state of <b>circ</b> to <b>state</b>, adding it to or removing
|
/** Change the state of <b>circ</b> to <b>state</b>, adding it to or removing
|
||||||
@ -202,18 +205,18 @@ circuit_set_state(circuit_t *circ, uint8_t state)
|
|||||||
tor_assert(circ);
|
tor_assert(circ);
|
||||||
if (state == circ->state)
|
if (state == circ->state)
|
||||||
return;
|
return;
|
||||||
if (!circuits_pending_or_conns)
|
if (!circuits_pending_chans)
|
||||||
circuits_pending_or_conns = smartlist_new();
|
circuits_pending_chans = smartlist_new();
|
||||||
if (circ->state == CIRCUIT_STATE_OR_WAIT) {
|
if (circ->state == CIRCUIT_STATE_CHAN_WAIT) {
|
||||||
/* remove from waiting-circuit list. */
|
/* remove from waiting-circuit list. */
|
||||||
smartlist_remove(circuits_pending_or_conns, circ);
|
smartlist_remove(circuits_pending_chans, circ);
|
||||||
}
|
}
|
||||||
if (state == CIRCUIT_STATE_OR_WAIT) {
|
if (state == CIRCUIT_STATE_CHAN_WAIT) {
|
||||||
/* add to waiting-circuit list. */
|
/* add to waiting-circuit list. */
|
||||||
smartlist_add(circuits_pending_or_conns, circ);
|
smartlist_add(circuits_pending_chans, circ);
|
||||||
}
|
}
|
||||||
if (state == CIRCUIT_STATE_OPEN)
|
if (state == CIRCUIT_STATE_OPEN)
|
||||||
tor_assert(!circ->n_conn_onionskin);
|
tor_assert(!circ->n_chan_onionskin);
|
||||||
circ->state = state;
|
circ->state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,31 +235,31 @@ circuit_add(circuit_t *circ)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Append to <b>out</b> all circuits in state OR_WAIT waiting for
|
/** Append to <b>out</b> all circuits in state CHAN_WAIT waiting for
|
||||||
* the given connection. */
|
* the given connection. */
|
||||||
void
|
void
|
||||||
circuit_get_all_pending_on_or_conn(smartlist_t *out, or_connection_t *or_conn)
|
circuit_get_all_pending_on_channel(smartlist_t *out, channel_t *chan)
|
||||||
{
|
{
|
||||||
tor_assert(out);
|
tor_assert(out);
|
||||||
tor_assert(or_conn);
|
tor_assert(chan);
|
||||||
|
tor_assert(!(chan->is_listener));
|
||||||
|
|
||||||
if (!circuits_pending_or_conns)
|
if (!circuits_pending_chans)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SMARTLIST_FOREACH_BEGIN(circuits_pending_or_conns, circuit_t *, circ) {
|
SMARTLIST_FOREACH_BEGIN(circuits_pending_chans, circuit_t *, circ) {
|
||||||
if (circ->marked_for_close)
|
if (circ->marked_for_close)
|
||||||
continue;
|
continue;
|
||||||
if (!circ->n_hop)
|
if (!circ->n_hop)
|
||||||
continue;
|
continue;
|
||||||
tor_assert(circ->state == CIRCUIT_STATE_OR_WAIT);
|
tor_assert(circ->state == CIRCUIT_STATE_CHAN_WAIT);
|
||||||
if (tor_digest_is_zero(circ->n_hop->identity_digest)) {
|
if (tor_digest_is_zero(circ->n_hop->identity_digest)) {
|
||||||
/* Look at addr/port. This is an unkeyed connection. */
|
/* Look at addr/port. This is an unkeyed connection. */
|
||||||
if (!tor_addr_eq(&circ->n_hop->addr, &or_conn->_base.addr) ||
|
if (!channel_matches_extend_info(chan, circ->n_hop))
|
||||||
circ->n_hop->port != or_conn->_base.port)
|
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
/* We expected a key. See if it's the right one. */
|
/* We expected a key. See if it's the right one. */
|
||||||
if (tor_memneq(or_conn->identity_digest,
|
if (tor_memneq(chan->u.cell_chan.identity_digest,
|
||||||
circ->n_hop->identity_digest, DIGEST_LEN))
|
circ->n_hop->identity_digest, DIGEST_LEN))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -264,19 +267,24 @@ circuit_get_all_pending_on_or_conn(smartlist_t *out, or_connection_t *or_conn)
|
|||||||
} SMARTLIST_FOREACH_END(circ);
|
} SMARTLIST_FOREACH_END(circ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the number of circuits in state OR_WAIT, waiting for the given
|
/** Return the number of circuits in state CHAN_WAIT, waiting for the given
|
||||||
* connection. */
|
* channel. */
|
||||||
int
|
int
|
||||||
circuit_count_pending_on_or_conn(or_connection_t *or_conn)
|
circuit_count_pending_on_channel(channel_t *chan)
|
||||||
{
|
{
|
||||||
int cnt;
|
int cnt;
|
||||||
smartlist_t *sl = smartlist_new();
|
smartlist_t *sl = smartlist_new();
|
||||||
circuit_get_all_pending_on_or_conn(sl, or_conn);
|
|
||||||
|
tor_assert(chan);
|
||||||
|
tor_assert(!(chan->is_listener));
|
||||||
|
|
||||||
|
circuit_get_all_pending_on_channel(sl, chan);
|
||||||
cnt = smartlist_len(sl);
|
cnt = smartlist_len(sl);
|
||||||
smartlist_free(sl);
|
smartlist_free(sl);
|
||||||
log_debug(LD_CIRC,"or_conn to %s at %s, %d pending circs",
|
log_debug(LD_CIRC,"or_conn to %s at %s, %d pending circs",
|
||||||
or_conn->nickname ? or_conn->nickname : "NULL",
|
chan->u.cell_chan.nickname ?
|
||||||
or_conn->_base.address,
|
chan->u.cell_chan.nickname : "NULL",
|
||||||
|
channel_get_canonical_remote_descr(chan),
|
||||||
cnt);
|
cnt);
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
@ -324,7 +332,7 @@ circuit_state_to_string(int state)
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case CIRCUIT_STATE_BUILDING: return "doing handshakes";
|
case CIRCUIT_STATE_BUILDING: return "doing handshakes";
|
||||||
case CIRCUIT_STATE_ONIONSKIN_PENDING: return "processing the onion";
|
case CIRCUIT_STATE_ONIONSKIN_PENDING: return "processing the onion";
|
||||||
case CIRCUIT_STATE_OR_WAIT: return "connecting to server";
|
case CIRCUIT_STATE_CHAN_WAIT: return "connecting to server";
|
||||||
case CIRCUIT_STATE_OPEN: return "open";
|
case CIRCUIT_STATE_OPEN: return "open";
|
||||||
default:
|
default:
|
||||||
log_warn(LD_BUG, "Unknown circuit state %d", state);
|
log_warn(LD_BUG, "Unknown circuit state %d", state);
|
||||||
@ -522,7 +530,7 @@ init_circuit_base(circuit_t *circ)
|
|||||||
circ->n_cell_ewma.last_adjusted_tick = cell_ewma_get_tick();
|
circ->n_cell_ewma.last_adjusted_tick = cell_ewma_get_tick();
|
||||||
circ->n_cell_ewma.cell_count = 0.0;
|
circ->n_cell_ewma.cell_count = 0.0;
|
||||||
circ->n_cell_ewma.heap_index = -1;
|
circ->n_cell_ewma.heap_index = -1;
|
||||||
circ->n_cell_ewma.is_for_p_conn = 0;
|
circ->n_cell_ewma.is_for_p_chan = 0;
|
||||||
|
|
||||||
circuit_add(circ);
|
circuit_add(circ);
|
||||||
}
|
}
|
||||||
@ -556,7 +564,7 @@ origin_circuit_new(void)
|
|||||||
/** Allocate a new or_circuit_t, connected to <b>p_conn</b> as
|
/** Allocate a new or_circuit_t, connected to <b>p_conn</b> as
|
||||||
* <b>p_circ_id</b>. If <b>p_conn</b> is NULL, the circuit is unattached. */
|
* <b>p_circ_id</b>. If <b>p_conn</b> is NULL, the circuit is unattached. */
|
||||||
or_circuit_t *
|
or_circuit_t *
|
||||||
or_circuit_new(circid_t p_circ_id, or_connection_t *p_conn)
|
or_circuit_new(circid_t p_circ_id, channel_t *p_chan)
|
||||||
{
|
{
|
||||||
/* CircIDs */
|
/* CircIDs */
|
||||||
or_circuit_t *circ;
|
or_circuit_t *circ;
|
||||||
@ -564,8 +572,8 @@ or_circuit_new(circid_t p_circ_id, or_connection_t *p_conn)
|
|||||||
circ = tor_malloc_zero(sizeof(or_circuit_t));
|
circ = tor_malloc_zero(sizeof(or_circuit_t));
|
||||||
circ->_base.magic = OR_CIRCUIT_MAGIC;
|
circ->_base.magic = OR_CIRCUIT_MAGIC;
|
||||||
|
|
||||||
if (p_conn)
|
if (p_chan)
|
||||||
circuit_set_p_circid_orconn(circ, p_circ_id, p_conn);
|
circuit_set_p_circid_chan(circ, p_circ_id, p_chan);
|
||||||
|
|
||||||
circ->remaining_relay_early_cells = MAX_RELAY_EARLY_CELLS_PER_CIRCUIT;
|
circ->remaining_relay_early_cells = MAX_RELAY_EARLY_CELLS_PER_CIRCUIT;
|
||||||
|
|
||||||
@ -576,7 +584,7 @@ or_circuit_new(circid_t p_circ_id, or_connection_t *p_conn)
|
|||||||
/* Initialize the cell counts to 0 */
|
/* Initialize the cell counts to 0 */
|
||||||
circ->p_cell_ewma.cell_count = 0.0;
|
circ->p_cell_ewma.cell_count = 0.0;
|
||||||
circ->p_cell_ewma.last_adjusted_tick = cell_ewma_get_tick();
|
circ->p_cell_ewma.last_adjusted_tick = cell_ewma_get_tick();
|
||||||
circ->p_cell_ewma.is_for_p_conn = 1;
|
circ->p_cell_ewma.is_for_p_chan = 1;
|
||||||
|
|
||||||
/* It's not in any heap yet. */
|
/* It's not in any heap yet. */
|
||||||
circ->p_cell_ewma.heap_index = -1;
|
circ->p_cell_ewma.heap_index = -1;
|
||||||
@ -641,22 +649,22 @@ circuit_free(circuit_t *circ)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* remove from map. */
|
/* remove from map. */
|
||||||
circuit_set_p_circid_orconn(ocirc, 0, NULL);
|
circuit_set_p_circid_chan(ocirc, 0, NULL);
|
||||||
|
|
||||||
/* Clear cell queue _after_ removing it from the map. Otherwise our
|
/* Clear cell queue _after_ removing it from the map. Otherwise our
|
||||||
* "active" checks will be violated. */
|
* "active" checks will be violated. */
|
||||||
cell_queue_clear(ô->p_conn_cells);
|
cell_queue_clear(ô->p_chan_cells);
|
||||||
}
|
}
|
||||||
|
|
||||||
extend_info_free(circ->n_hop);
|
extend_info_free(circ->n_hop);
|
||||||
tor_free(circ->n_conn_onionskin);
|
tor_free(circ->n_chan_onionskin);
|
||||||
|
|
||||||
/* Remove from map. */
|
/* Remove from map. */
|
||||||
circuit_set_n_circid_orconn(circ, 0, NULL);
|
circuit_set_n_circid_chan(circ, 0, NULL);
|
||||||
|
|
||||||
/* Clear cell queue _after_ removing it from the map. Otherwise our
|
/* Clear cell queue _after_ removing it from the map. Otherwise our
|
||||||
* "active" checks will be violated. */
|
* "active" checks will be violated. */
|
||||||
cell_queue_clear(&circ->n_conn_cells);
|
cell_queue_clear(&circ->n_chan_cells);
|
||||||
|
|
||||||
memset(mem, 0xAA, memlen); /* poison memory */
|
memset(mem, 0xAA, memlen); /* poison memory */
|
||||||
tor_free(mem);
|
tor_free(mem);
|
||||||
@ -702,10 +710,10 @@ circuit_free_all(void)
|
|||||||
global_circuitlist = next;
|
global_circuitlist = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
smartlist_free(circuits_pending_or_conns);
|
smartlist_free(circuits_pending_chans);
|
||||||
circuits_pending_or_conns = NULL;
|
circuits_pending_chans = NULL;
|
||||||
|
|
||||||
HT_CLEAR(orconn_circid_map, &orconn_circid_circuit_map);
|
HT_CLEAR(chan_circid_map, &chan_circid_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Deallocate space associated with the cpath node <b>victim</b>. */
|
/** Deallocate space associated with the cpath node <b>victim</b>. */
|
||||||
@ -742,8 +750,12 @@ cpath_ref_decref(crypt_path_reference_t *cpath_ref)
|
|||||||
* of information about circuit <b>circ</b>.
|
* of information about circuit <b>circ</b>.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
circuit_dump_details(int severity, circuit_t *circ, int conn_array_index,
|
circuit_dump_conn_details(int severity,
|
||||||
const char *type, int this_circid, int other_circid)
|
circuit_t *circ,
|
||||||
|
int conn_array_index,
|
||||||
|
const char *type,
|
||||||
|
int this_circid,
|
||||||
|
int other_circid)
|
||||||
{
|
{
|
||||||
log(severity, LD_CIRC, "Conn %d has %s circuit: circID %d (other side %d), "
|
log(severity, LD_CIRC, "Conn %d has %s circuit: circID %d (other side %d), "
|
||||||
"state %d (%s), born %ld:",
|
"state %d (%s), born %ld:",
|
||||||
@ -766,44 +778,96 @@ circuit_dump_by_conn(connection_t *conn, int severity)
|
|||||||
|
|
||||||
for (circ = global_circuitlist; circ; circ = circ->next) {
|
for (circ = global_circuitlist; circ; circ = circ->next) {
|
||||||
circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0;
|
circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0;
|
||||||
if (circ->marked_for_close)
|
|
||||||
|
if (circ->marked_for_close) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (! CIRCUIT_IS_ORIGIN(circ))
|
if (!CIRCUIT_IS_ORIGIN(circ)) {
|
||||||
p_circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
|
p_circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
|
||||||
|
}
|
||||||
|
|
||||||
if (! CIRCUIT_IS_ORIGIN(circ) && TO_OR_CIRCUIT(circ)->p_conn &&
|
|
||||||
TO_CONN(TO_OR_CIRCUIT(circ)->p_conn) == conn)
|
|
||||||
circuit_dump_details(severity, circ, conn->conn_array_index, "App-ward",
|
|
||||||
p_circ_id, n_circ_id);
|
|
||||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||||
for (tmpconn=TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn;
|
for (tmpconn=TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn;
|
||||||
tmpconn=tmpconn->next_stream) {
|
tmpconn=tmpconn->next_stream) {
|
||||||
if (TO_CONN(tmpconn) == conn) {
|
if (TO_CONN(tmpconn) == conn) {
|
||||||
circuit_dump_details(severity, circ, conn->conn_array_index,
|
circuit_dump_conn_details(severity, circ, conn->conn_array_index,
|
||||||
"App-ward", p_circ_id, n_circ_id);
|
"App-ward", p_circ_id, n_circ_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (circ->n_conn && TO_CONN(circ->n_conn) == conn)
|
|
||||||
circuit_dump_details(severity, circ, conn->conn_array_index, "Exit-ward",
|
|
||||||
n_circ_id, p_circ_id);
|
|
||||||
if (! CIRCUIT_IS_ORIGIN(circ)) {
|
if (! CIRCUIT_IS_ORIGIN(circ)) {
|
||||||
for (tmpconn=TO_OR_CIRCUIT(circ)->n_streams; tmpconn;
|
for (tmpconn=TO_OR_CIRCUIT(circ)->n_streams; tmpconn;
|
||||||
tmpconn=tmpconn->next_stream) {
|
tmpconn=tmpconn->next_stream) {
|
||||||
if (TO_CONN(tmpconn) == conn) {
|
if (TO_CONN(tmpconn) == conn) {
|
||||||
circuit_dump_details(severity, circ, conn->conn_array_index,
|
circuit_dump_conn_details(severity, circ, conn->conn_array_index,
|
||||||
"Exit-ward", n_circ_id, p_circ_id);
|
"Exit-ward", n_circ_id, p_circ_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!circ->n_conn && circ->n_hop &&
|
}
|
||||||
tor_addr_eq(&circ->n_hop->addr, &conn->addr) &&
|
}
|
||||||
circ->n_hop->port == conn->port &&
|
|
||||||
conn->type == CONN_TYPE_OR &&
|
/** A helper function for circuit_dump_by_chan() below. Log a bunch
|
||||||
tor_memeq(TO_OR_CONN(conn)->identity_digest,
|
* of information about circuit <b>circ</b>.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
circuit_dump_chan_details(int severity,
|
||||||
|
circuit_t *circ,
|
||||||
|
channel_t *chan,
|
||||||
|
const char *type,
|
||||||
|
int this_circid,
|
||||||
|
int other_circid)
|
||||||
|
{
|
||||||
|
log(severity, LD_CIRC, "Conn %p has %s circuit: circID %d (other side %d), "
|
||||||
|
"state %d (%s), born %ld:",
|
||||||
|
chan, type, this_circid, other_circid, circ->state,
|
||||||
|
circuit_state_to_string(circ->state),
|
||||||
|
(long)circ->timestamp_created.tv_sec);
|
||||||
|
if (CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */
|
||||||
|
circuit_log_path(severity, LD_CIRC, TO_ORIGIN_CIRCUIT(circ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Log, at severity <b>severity</b>, information about each circuit
|
||||||
|
* that is connected to <b>chan</b>.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
circuit_dump_by_chan(channel_t *chan, int severity)
|
||||||
|
{
|
||||||
|
circuit_t *circ;
|
||||||
|
|
||||||
|
tor_assert(chan);
|
||||||
|
tor_assert(!(chan->is_listener));
|
||||||
|
|
||||||
|
for (circ = global_circuitlist; circ; circ = circ->next) {
|
||||||
|
circid_t n_circ_id = circ->n_circ_id, p_circ_id = 0;
|
||||||
|
|
||||||
|
if (circ->marked_for_close) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CIRCUIT_IS_ORIGIN(circ)) {
|
||||||
|
p_circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! CIRCUIT_IS_ORIGIN(circ) && TO_OR_CIRCUIT(circ)->p_chan &&
|
||||||
|
TO_OR_CIRCUIT(circ)->p_chan == chan) {
|
||||||
|
circuit_dump_chan_details(severity, circ, chan, "App-ward",
|
||||||
|
p_circ_id, n_circ_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (circ->n_chan && circ->n_chan == chan) {
|
||||||
|
circuit_dump_chan_details(severity, circ, chan, "Exit-ward",
|
||||||
|
n_circ_id, p_circ_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!circ->n_chan && circ->n_hop &&
|
||||||
|
channel_matches_extend_info(chan, circ->n_hop) &&
|
||||||
|
tor_memeq(chan->u.cell_chan.identity_digest,
|
||||||
circ->n_hop->identity_digest, DIGEST_LEN)) {
|
circ->n_hop->identity_digest, DIGEST_LEN)) {
|
||||||
circuit_dump_details(severity, circ, conn->conn_array_index,
|
circuit_dump_chan_details(severity, circ, chan,
|
||||||
(circ->state == CIRCUIT_STATE_OPEN &&
|
(circ->state == CIRCUIT_STATE_OPEN &&
|
||||||
!CIRCUIT_IS_ORIGIN(circ)) ?
|
!CIRCUIT_IS_ORIGIN(circ)) ?
|
||||||
"Endpoint" : "Pending",
|
"Endpoint" : "Pending",
|
||||||
@ -832,27 +896,37 @@ circuit_get_by_global_id(uint32_t id)
|
|||||||
|
|
||||||
/** Return a circ such that:
|
/** Return a circ such that:
|
||||||
* - circ-\>n_circ_id or circ-\>p_circ_id is equal to <b>circ_id</b>, and
|
* - circ-\>n_circ_id or circ-\>p_circ_id is equal to <b>circ_id</b>, and
|
||||||
* - circ is attached to <b>conn</b>, either as p_conn or n_conn.
|
* - circ is attached to <b>chan</b>, either as p_chan or n_chan.
|
||||||
* Return NULL if no such circuit exists.
|
* Return NULL if no such circuit exists.
|
||||||
*/
|
*/
|
||||||
static INLINE circuit_t *
|
static INLINE circuit_t *
|
||||||
circuit_get_by_circid_orconn_impl(circid_t circ_id, or_connection_t *conn)
|
circuit_get_by_circid_channel_impl(circid_t circ_id, channel_t *chan)
|
||||||
{
|
{
|
||||||
orconn_circid_circuit_map_t search;
|
chan_circid_circuit_map_t search;
|
||||||
orconn_circid_circuit_map_t *found;
|
chan_circid_circuit_map_t *found;
|
||||||
|
|
||||||
if (_last_circid_orconn_ent &&
|
if (_last_circid_chan_ent &&
|
||||||
circ_id == _last_circid_orconn_ent->circ_id &&
|
circ_id == _last_circid_chan_ent->circ_id &&
|
||||||
conn == _last_circid_orconn_ent->or_conn) {
|
chan == _last_circid_chan_ent->chan) {
|
||||||
found = _last_circid_orconn_ent;
|
found = _last_circid_chan_ent;
|
||||||
} else {
|
} else {
|
||||||
search.circ_id = circ_id;
|
search.circ_id = circ_id;
|
||||||
search.or_conn = conn;
|
search.chan = chan;
|
||||||
found = HT_FIND(orconn_circid_map, &orconn_circid_circuit_map, &search);
|
found = HT_FIND(chan_circid_map, &chan_circid_map, &search);
|
||||||
_last_circid_orconn_ent = found;
|
_last_circid_chan_ent = found;
|
||||||
}
|
}
|
||||||
if (found && found->circuit)
|
if (found && found->circuit) {
|
||||||
|
log_debug(LD_CIRC,
|
||||||
|
"circuit_get_by_circid_channel_impl() returning circuit %p for"
|
||||||
|
" circ_id %d, channel ID %lu (%p)",
|
||||||
|
found->circuit, circ_id, chan->global_identifier, chan);
|
||||||
return found->circuit;
|
return found->circuit;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug(LD_CIRC,
|
||||||
|
"circuit_get_by_circid_channel_impl() found nothing for"
|
||||||
|
" circ_id %d, channel ID %lu (%p)",
|
||||||
|
circ_id, chan->global_identifier, chan);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
/* The rest of this checks for bugs. Disabled by default. */
|
/* The rest of this checks for bugs. Disabled by default. */
|
||||||
@ -862,15 +936,15 @@ circuit_get_by_circid_orconn_impl(circid_t circ_id, or_connection_t *conn)
|
|||||||
for (circ=global_circuitlist;circ;circ = circ->next) {
|
for (circ=global_circuitlist;circ;circ = circ->next) {
|
||||||
if (! CIRCUIT_IS_ORIGIN(circ)) {
|
if (! CIRCUIT_IS_ORIGIN(circ)) {
|
||||||
or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
|
or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
|
||||||
if (or_circ->p_conn == conn && or_circ->p_circ_id == circ_id) {
|
if (or_circ->p_chan == chan && or_circ->p_circ_id == circ_id) {
|
||||||
log_warn(LD_BUG,
|
log_warn(LD_BUG,
|
||||||
"circuit matches p_conn, but not in hash table (Bug!)");
|
"circuit matches p_chan, but not in hash table (Bug!)");
|
||||||
return circ;
|
return circ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (circ->n_conn == conn && circ->n_circ_id == circ_id) {
|
if (circ->n_chan == chan && circ->n_circ_id == circ_id) {
|
||||||
log_warn(LD_BUG,
|
log_warn(LD_BUG,
|
||||||
"circuit matches n_conn, but not in hash table (Bug!)");
|
"circuit matches n_chan, but not in hash table (Bug!)");
|
||||||
return circ;
|
return circ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -880,14 +954,14 @@ circuit_get_by_circid_orconn_impl(circid_t circ_id, or_connection_t *conn)
|
|||||||
|
|
||||||
/** Return a circ such that:
|
/** Return a circ such that:
|
||||||
* - circ-\>n_circ_id or circ-\>p_circ_id is equal to <b>circ_id</b>, and
|
* - circ-\>n_circ_id or circ-\>p_circ_id is equal to <b>circ_id</b>, and
|
||||||
* - circ is attached to <b>conn</b>, either as p_conn or n_conn.
|
* - circ is attached to <b>chan</b>, either as p_chan or n_chan.
|
||||||
* - circ is not marked for close.
|
* - circ is not marked for close.
|
||||||
* Return NULL if no such circuit exists.
|
* Return NULL if no such circuit exists.
|
||||||
*/
|
*/
|
||||||
circuit_t *
|
circuit_t *
|
||||||
circuit_get_by_circid_orconn(circid_t circ_id, or_connection_t *conn)
|
circuit_get_by_circid_channel(circid_t circ_id, channel_t *chan)
|
||||||
{
|
{
|
||||||
circuit_t *circ = circuit_get_by_circid_orconn_impl(circ_id, conn);
|
circuit_t *circ = circuit_get_by_circid_channel_impl(circ_id, chan);
|
||||||
if (!circ || circ->marked_for_close)
|
if (!circ || circ->marked_for_close)
|
||||||
return NULL;
|
return NULL;
|
||||||
else
|
else
|
||||||
@ -895,11 +969,11 @@ circuit_get_by_circid_orconn(circid_t circ_id, or_connection_t *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Return true iff the circuit ID <b>circ_id</b> is currently used by a
|
/** Return true iff the circuit ID <b>circ_id</b> is currently used by a
|
||||||
* circuit, marked or not, on <b>conn</b>. */
|
* circuit, marked or not, on <b>chan</b>. */
|
||||||
int
|
int
|
||||||
circuit_id_in_use_on_orconn(circid_t circ_id, or_connection_t *conn)
|
circuit_id_in_use_on_channel(circid_t circ_id, channel_t *chan)
|
||||||
{
|
{
|
||||||
return circuit_get_by_circid_orconn_impl(circ_id, conn) != NULL;
|
return circuit_get_by_circid_channel_impl(circ_id, chan) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the circuit that a given edge connection is using. */
|
/** Return the circuit that a given edge connection is using. */
|
||||||
@ -916,27 +990,27 @@ circuit_get_by_edge_conn(edge_connection_t *conn)
|
|||||||
return circ;
|
return circ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** For each circuit that has <b>conn</b> as n_conn or p_conn, unlink the
|
/** For each circuit that has <b>chan</b> as n_chan or p_chan, unlink the
|
||||||
* circuit from the orconn,circid map, and mark it for close if it hasn't
|
* circuit from the chan,circid map, and mark it for close if it hasn't
|
||||||
* been marked already.
|
* been marked already.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
circuit_unlink_all_from_or_conn(or_connection_t *conn, int reason)
|
circuit_unlink_all_from_channel(channel_t *chan, int reason)
|
||||||
{
|
{
|
||||||
circuit_t *circ;
|
circuit_t *circ;
|
||||||
|
|
||||||
connection_or_unlink_all_active_circs(conn);
|
channel_unlink_all_active_circs(chan);
|
||||||
|
|
||||||
for (circ = global_circuitlist; circ; circ = circ->next) {
|
for (circ = global_circuitlist; circ; circ = circ->next) {
|
||||||
int mark = 0;
|
int mark = 0;
|
||||||
if (circ->n_conn == conn) {
|
if (circ->n_chan == chan) {
|
||||||
circuit_set_n_circid_orconn(circ, 0, NULL);
|
circuit_set_n_circid_chan(circ, 0, NULL);
|
||||||
mark = 1;
|
mark = 1;
|
||||||
}
|
}
|
||||||
if (! CIRCUIT_IS_ORIGIN(circ)) {
|
if (! CIRCUIT_IS_ORIGIN(circ)) {
|
||||||
or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
|
or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
|
||||||
if (or_circ->p_conn == conn) {
|
if (or_circ->p_chan == chan) {
|
||||||
circuit_set_p_circid_orconn(or_circ, 0, NULL);
|
circuit_set_p_circid_chan(or_circ, 0, NULL);
|
||||||
mark = 1;
|
mark = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1267,9 +1341,9 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
|
|||||||
circuit_rep_hist_note_result(ocirc);
|
circuit_rep_hist_note_result(ocirc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (circ->state == CIRCUIT_STATE_OR_WAIT) {
|
if (circ->state == CIRCUIT_STATE_CHAN_WAIT) {
|
||||||
if (circuits_pending_or_conns)
|
if (circuits_pending_chans)
|
||||||
smartlist_remove(circuits_pending_or_conns, circ);
|
smartlist_remove(circuits_pending_chans, circ);
|
||||||
}
|
}
|
||||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||||
control_event_circuit_status(TO_ORIGIN_CIRCUIT(circ),
|
control_event_circuit_status(TO_ORIGIN_CIRCUIT(circ),
|
||||||
@ -1306,9 +1380,9 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
|
|||||||
INTRO_POINT_FAILURE_UNREACHABLE);
|
INTRO_POINT_FAILURE_UNREACHABLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (circ->n_conn) {
|
if (circ->n_chan) {
|
||||||
circuit_clear_cell_queue(circ, circ->n_conn);
|
circuit_clear_cell_queue(circ, circ->n_chan);
|
||||||
connection_or_send_destroy(circ->n_circ_id, circ->n_conn, reason);
|
channel_send_destroy(circ->n_circ_id, circ->n_chan, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! CIRCUIT_IS_ORIGIN(circ)) {
|
if (! CIRCUIT_IS_ORIGIN(circ)) {
|
||||||
@ -1333,9 +1407,9 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
|
|||||||
conn->on_circuit = NULL;
|
conn->on_circuit = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (or_circ->p_conn) {
|
if (or_circ->p_chan) {
|
||||||
circuit_clear_cell_queue(circ, or_circ->p_conn);
|
circuit_clear_cell_queue(circ, or_circ->p_chan);
|
||||||
connection_or_send_destroy(or_circ->p_circ_id, or_circ->p_conn, reason);
|
channel_send_destroy(or_circ->p_circ_id, or_circ->p_chan, reason);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
|
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
|
||||||
@ -1438,22 +1512,22 @@ assert_circuit_ok(const circuit_t *c)
|
|||||||
or_circ = TO_OR_CIRCUIT(nonconst_circ);
|
or_circ = TO_OR_CIRCUIT(nonconst_circ);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c->n_conn) {
|
if (c->n_chan) {
|
||||||
tor_assert(!c->n_hop);
|
tor_assert(!c->n_hop);
|
||||||
|
|
||||||
if (c->n_circ_id) {
|
if (c->n_circ_id) {
|
||||||
/* We use the _impl variant here to make sure we don't fail on marked
|
/* We use the _impl variant here to make sure we don't fail on marked
|
||||||
* circuits, which would not be returned by the regular function. */
|
* circuits, which would not be returned by the regular function. */
|
||||||
circuit_t *c2 = circuit_get_by_circid_orconn_impl(c->n_circ_id,
|
circuit_t *c2 = circuit_get_by_circid_channel_impl(c->n_circ_id,
|
||||||
c->n_conn);
|
c->n_chan);
|
||||||
tor_assert(c == c2);
|
tor_assert(c == c2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (or_circ && or_circ->p_conn) {
|
if (or_circ && or_circ->p_chan) {
|
||||||
if (or_circ->p_circ_id) {
|
if (or_circ->p_circ_id) {
|
||||||
/* ibid */
|
/* ibid */
|
||||||
circuit_t *c2 = circuit_get_by_circid_orconn_impl(or_circ->p_circ_id,
|
circuit_t *c2 = circuit_get_by_circid_channel_impl(or_circ->p_circ_id,
|
||||||
or_circ->p_conn);
|
or_circ->p_chan);
|
||||||
tor_assert(c == c2);
|
tor_assert(c == c2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1464,7 +1538,7 @@ assert_circuit_ok(const circuit_t *c)
|
|||||||
tor_assert(c->deliver_window >= 0);
|
tor_assert(c->deliver_window >= 0);
|
||||||
tor_assert(c->package_window >= 0);
|
tor_assert(c->package_window >= 0);
|
||||||
if (c->state == CIRCUIT_STATE_OPEN) {
|
if (c->state == CIRCUIT_STATE_OPEN) {
|
||||||
tor_assert(!c->n_conn_onionskin);
|
tor_assert(!c->n_chan_onionskin);
|
||||||
if (or_circ) {
|
if (or_circ) {
|
||||||
tor_assert(or_circ->n_crypto);
|
tor_assert(or_circ->n_crypto);
|
||||||
tor_assert(or_circ->p_crypto);
|
tor_assert(or_circ->p_crypto);
|
||||||
@ -1472,12 +1546,12 @@ assert_circuit_ok(const circuit_t *c)
|
|||||||
tor_assert(or_circ->p_digest);
|
tor_assert(or_circ->p_digest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (c->state == CIRCUIT_STATE_OR_WAIT && !c->marked_for_close) {
|
if (c->state == CIRCUIT_STATE_CHAN_WAIT && !c->marked_for_close) {
|
||||||
tor_assert(circuits_pending_or_conns &&
|
tor_assert(circuits_pending_chans &&
|
||||||
smartlist_isin(circuits_pending_or_conns, c));
|
smartlist_isin(circuits_pending_chans, c));
|
||||||
} else {
|
} else {
|
||||||
tor_assert(!circuits_pending_or_conns ||
|
tor_assert(!circuits_pending_chans ||
|
||||||
!smartlist_isin(circuits_pending_or_conns, c));
|
!smartlist_isin(circuits_pending_chans, c));
|
||||||
}
|
}
|
||||||
if (origin_circ && origin_circ->cpath) {
|
if (origin_circ && origin_circ->cpath) {
|
||||||
assert_cpath_ok(origin_circ->cpath);
|
assert_cpath_ok(origin_circ->cpath);
|
||||||
|
@ -18,20 +18,21 @@ const char *circuit_purpose_to_controller_string(uint8_t purpose);
|
|||||||
const char *circuit_purpose_to_controller_hs_state_string(uint8_t purpose);
|
const char *circuit_purpose_to_controller_hs_state_string(uint8_t purpose);
|
||||||
const char *circuit_purpose_to_string(uint8_t purpose);
|
const char *circuit_purpose_to_string(uint8_t purpose);
|
||||||
void circuit_dump_by_conn(connection_t *conn, int severity);
|
void circuit_dump_by_conn(connection_t *conn, int severity);
|
||||||
void circuit_set_p_circid_orconn(or_circuit_t *circ, circid_t id,
|
void circuit_dump_by_chan(channel_t *chan, int severity);
|
||||||
or_connection_t *conn);
|
void circuit_set_p_circid_chan(or_circuit_t *circ, circid_t id,
|
||||||
void circuit_set_n_circid_orconn(circuit_t *circ, circid_t id,
|
channel_t *chan);
|
||||||
or_connection_t *conn);
|
void circuit_set_n_circid_chan(circuit_t *circ, circid_t id,
|
||||||
|
channel_t *chan);
|
||||||
void circuit_set_state(circuit_t *circ, uint8_t state);
|
void circuit_set_state(circuit_t *circ, uint8_t state);
|
||||||
void circuit_close_all_marked(void);
|
void circuit_close_all_marked(void);
|
||||||
int32_t circuit_initial_package_window(void);
|
int32_t circuit_initial_package_window(void);
|
||||||
origin_circuit_t *origin_circuit_new(void);
|
origin_circuit_t *origin_circuit_new(void);
|
||||||
or_circuit_t *or_circuit_new(circid_t p_circ_id, or_connection_t *p_conn);
|
or_circuit_t *or_circuit_new(circid_t p_circ_id, channel_t *p_chan);
|
||||||
circuit_t *circuit_get_by_circid_orconn(circid_t circ_id,
|
circuit_t *circuit_get_by_circid_channel(circid_t circ_id,
|
||||||
or_connection_t *conn);
|
channel_t *chan);
|
||||||
int circuit_id_in_use_on_orconn(circid_t circ_id, or_connection_t *conn);
|
int circuit_id_in_use_on_channel(circid_t circ_id, channel_t *chan);
|
||||||
circuit_t *circuit_get_by_edge_conn(edge_connection_t *conn);
|
circuit_t *circuit_get_by_edge_conn(edge_connection_t *conn);
|
||||||
void circuit_unlink_all_from_or_conn(or_connection_t *conn, int reason);
|
void circuit_unlink_all_from_channel(channel_t *chan, int reason);
|
||||||
origin_circuit_t *circuit_get_by_global_id(uint32_t id);
|
origin_circuit_t *circuit_get_by_global_id(uint32_t id);
|
||||||
origin_circuit_t *circuit_get_ready_rend_circ_by_rend_data(
|
origin_circuit_t *circuit_get_ready_rend_circ_by_rend_data(
|
||||||
const rend_data_t *rend_data);
|
const rend_data_t *rend_data);
|
||||||
@ -47,9 +48,9 @@ void _circuit_mark_for_close(circuit_t *circ, int reason,
|
|||||||
int line, const char *file);
|
int line, const char *file);
|
||||||
int circuit_get_cpath_len(origin_circuit_t *circ);
|
int circuit_get_cpath_len(origin_circuit_t *circ);
|
||||||
crypt_path_t *circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum);
|
crypt_path_t *circuit_get_cpath_hop(origin_circuit_t *circ, int hopnum);
|
||||||
void circuit_get_all_pending_on_or_conn(smartlist_t *out,
|
void circuit_get_all_pending_on_channel(smartlist_t *out,
|
||||||
or_connection_t *or_conn);
|
channel_t *chan);
|
||||||
int circuit_count_pending_on_or_conn(or_connection_t *or_conn);
|
int circuit_count_pending_on_channel(channel_t *chan);
|
||||||
|
|
||||||
#define circuit_mark_for_close(c, reason) \
|
#define circuit_mark_for_close(c, reason) \
|
||||||
_circuit_mark_for_close((c), (reason), __LINE__, _SHORT_FILE_)
|
_circuit_mark_for_close((c), (reason), __LINE__, _SHORT_FILE_)
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
**/
|
**/
|
||||||
|
|
||||||
#include "or.h"
|
#include "or.h"
|
||||||
|
#include "channel.h"
|
||||||
#include "circuitbuild.h"
|
#include "circuitbuild.h"
|
||||||
#include "circuitlist.h"
|
#include "circuitlist.h"
|
||||||
#include "circuituse.h"
|
#include "circuituse.h"
|
||||||
@ -53,7 +54,7 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ,
|
|||||||
tor_assert(conn);
|
tor_assert(conn);
|
||||||
tor_assert(conn->socks_request);
|
tor_assert(conn->socks_request);
|
||||||
|
|
||||||
if (must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_conn))
|
if (must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_chan))
|
||||||
return 0; /* ignore non-open circs */
|
return 0; /* ignore non-open circs */
|
||||||
if (circ->marked_for_close)
|
if (circ->marked_for_close)
|
||||||
return 0;
|
return 0;
|
||||||
@ -565,9 +566,9 @@ circuit_expire_building(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (victim->n_conn)
|
if (victim->n_chan)
|
||||||
log_info(LD_CIRC,"Abandoning circ %s:%d:%d (state %d:%s, purpose %d)",
|
log_info(LD_CIRC,"Abandoning circ %s:%d (state %d:%s, purpose %d)",
|
||||||
victim->n_conn->_base.address, victim->n_conn->_base.port,
|
channel_get_canonical_remote_descr(victim->n_chan),
|
||||||
victim->n_circ_id,
|
victim->n_circ_id,
|
||||||
victim->state, circuit_state_to_string(victim->state),
|
victim->state, circuit_state_to_string(victim->state),
|
||||||
victim->purpose);
|
victim->purpose);
|
||||||
@ -977,13 +978,13 @@ circuit_expire_old_circuits_serverside(time_t now)
|
|||||||
/* If the circuit has been idle for too long, and there are no streams
|
/* If the circuit has been idle for too long, and there are no streams
|
||||||
* on it, and it ends here, and it used a create_fast, mark it for close.
|
* on it, and it ends here, and it used a create_fast, mark it for close.
|
||||||
*/
|
*/
|
||||||
if (or_circ->is_first_hop && !circ->n_conn &&
|
if (or_circ->is_first_hop && !circ->n_chan &&
|
||||||
!or_circ->n_streams && !or_circ->resolving_streams &&
|
!or_circ->n_streams && !or_circ->resolving_streams &&
|
||||||
or_circ->p_conn &&
|
or_circ->p_chan &&
|
||||||
or_circ->p_conn->timestamp_last_added_nonpadding <= cutoff) {
|
channel_when_last_xmit(or_circ->p_chan) <= cutoff) {
|
||||||
log_info(LD_CIRC, "Closing circ_id %d (empty %d secs ago)",
|
log_info(LD_CIRC, "Closing circ_id %d (empty %d secs ago)",
|
||||||
or_circ->p_circ_id,
|
or_circ->p_circ_id,
|
||||||
(int)(now - or_circ->p_conn->timestamp_last_added_nonpadding));
|
(int)(now - channel_when_last_xmit(or_circ->p_chan)));
|
||||||
circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
|
circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1163,6 +1164,7 @@ circuit_try_attaching_streams(origin_circuit_t *circ)
|
|||||||
void
|
void
|
||||||
circuit_build_failed(origin_circuit_t *circ)
|
circuit_build_failed(origin_circuit_t *circ)
|
||||||
{
|
{
|
||||||
|
channel_t *n_chan = NULL;
|
||||||
/* we should examine circ and see if it failed because of
|
/* we should examine circ and see if it failed because of
|
||||||
* the last hop or an earlier hop. then use this info below.
|
* the last hop or an earlier hop. then use this info below.
|
||||||
*/
|
*/
|
||||||
@ -1179,11 +1181,13 @@ circuit_build_failed(origin_circuit_t *circ)
|
|||||||
/* We failed at the first hop. If there's an OR connection
|
/* We failed at the first hop. If there's an OR connection
|
||||||
* to blame, blame it. Also, avoid this relay for a while, and
|
* to blame, blame it. Also, avoid this relay for a while, and
|
||||||
* fail any one-hop directory fetches destined for it. */
|
* fail any one-hop directory fetches destined for it. */
|
||||||
const char *n_conn_id = circ->cpath->extend_info->identity_digest;
|
const char *n_chan_id = circ->cpath->extend_info->identity_digest;
|
||||||
int already_marked = 0;
|
int already_marked = 0;
|
||||||
if (circ->_base.n_conn) {
|
if (circ->_base.n_chan) {
|
||||||
or_connection_t *n_conn = circ->_base.n_conn;
|
n_chan = circ->_base.n_chan;
|
||||||
if (n_conn->is_bad_for_new_circs) {
|
tor_assert(!(n_chan->is_listener));
|
||||||
|
|
||||||
|
if (n_chan->u.cell_chan.is_bad_for_new_circs) {
|
||||||
/* We only want to blame this router when a fresh healthy
|
/* We only want to blame this router when a fresh healthy
|
||||||
* connection fails. So don't mark this router as newly failed,
|
* connection fails. So don't mark this router as newly failed,
|
||||||
* since maybe this was just an old circuit attempt that's
|
* since maybe this was just an old circuit attempt that's
|
||||||
@ -1195,18 +1199,18 @@ circuit_build_failed(origin_circuit_t *circ)
|
|||||||
}
|
}
|
||||||
log_info(LD_OR,
|
log_info(LD_OR,
|
||||||
"Our circuit failed to get a response from the first hop "
|
"Our circuit failed to get a response from the first hop "
|
||||||
"(%s:%d). I'm going to try to rotate to a better connection.",
|
"(%s). I'm going to try to rotate to a better connection.",
|
||||||
n_conn->_base.address, n_conn->_base.port);
|
channel_get_canonical_remote_descr(n_chan));
|
||||||
n_conn->is_bad_for_new_circs = 1;
|
n_chan->u.cell_chan.is_bad_for_new_circs = 1;
|
||||||
} else {
|
} else {
|
||||||
log_info(LD_OR,
|
log_info(LD_OR,
|
||||||
"Our circuit died before the first hop with no connection");
|
"Our circuit died before the first hop with no connection");
|
||||||
}
|
}
|
||||||
if (n_conn_id && !already_marked) {
|
if (n_chan_id && !already_marked) {
|
||||||
entry_guard_register_connect_status(n_conn_id, 0, 1, time(NULL));
|
entry_guard_register_connect_status(n_chan_id, 0, 1, time(NULL));
|
||||||
/* if there are any one-hop streams waiting on this circuit, fail
|
/* if there are any one-hop streams waiting on this circuit, fail
|
||||||
* them now so they can retry elsewhere. */
|
* them now so they can retry elsewhere. */
|
||||||
connection_ap_fail_onehop(n_conn_id, circ->build_state);
|
connection_ap_fail_onehop(n_chan_id, circ->build_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2148,6 +2148,7 @@ dumpstats(int severity)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* TODO add dump for channels with circuit_dump_by_chan() */
|
||||||
circuit_dump_by_conn(conn, severity); /* dump info about all the circuits
|
circuit_dump_by_conn(conn, severity); /* dump info about all the circuits
|
||||||
* using this conn */
|
* using this conn */
|
||||||
} SMARTLIST_FOREACH_END(conn);
|
} SMARTLIST_FOREACH_END(conn);
|
||||||
|
44
src/or/or.h
44
src/or/or.h
@ -445,9 +445,9 @@ typedef enum {
|
|||||||
#define CIRCUIT_STATE_BUILDING 0
|
#define CIRCUIT_STATE_BUILDING 0
|
||||||
/** Circuit state: Waiting to process the onionskin. */
|
/** Circuit state: Waiting to process the onionskin. */
|
||||||
#define CIRCUIT_STATE_ONIONSKIN_PENDING 1
|
#define CIRCUIT_STATE_ONIONSKIN_PENDING 1
|
||||||
/** Circuit state: I'd like to deliver a create, but my n_conn is still
|
/** Circuit state: I'd like to deliver a create, but my n_chan is still
|
||||||
* connecting. */
|
* connecting. */
|
||||||
#define CIRCUIT_STATE_OR_WAIT 2
|
#define CIRCUIT_STATE_CHAN_WAIT 2
|
||||||
/** Circuit state: onionskin(s) processed, ready to send/receive cells. */
|
/** Circuit state: onionskin(s) processed, ready to send/receive cells. */
|
||||||
#define CIRCUIT_STATE_OPEN 3
|
#define CIRCUIT_STATE_OPEN 3
|
||||||
|
|
||||||
@ -674,7 +674,7 @@ typedef enum {
|
|||||||
#define END_CIRC_REASON_RESOURCELIMIT 5
|
#define END_CIRC_REASON_RESOURCELIMIT 5
|
||||||
#define END_CIRC_REASON_CONNECTFAILED 6
|
#define END_CIRC_REASON_CONNECTFAILED 6
|
||||||
#define END_CIRC_REASON_OR_IDENTITY 7
|
#define END_CIRC_REASON_OR_IDENTITY 7
|
||||||
#define END_CIRC_REASON_OR_CONN_CLOSED 8
|
#define END_CIRC_REASON_CHANNEL_CLOSED 8
|
||||||
#define END_CIRC_REASON_FINISHED 9
|
#define END_CIRC_REASON_FINISHED 9
|
||||||
#define END_CIRC_REASON_TIMEOUT 10
|
#define END_CIRC_REASON_TIMEOUT 10
|
||||||
#define END_CIRC_REASON_DESTROYED 11
|
#define END_CIRC_REASON_DESTROYED 11
|
||||||
@ -2590,9 +2590,9 @@ typedef struct circuit_t {
|
|||||||
* ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */
|
* ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */
|
||||||
|
|
||||||
/** Queue of cells waiting to be transmitted on n_conn. */
|
/** Queue of cells waiting to be transmitted on n_conn. */
|
||||||
cell_queue_t n_conn_cells;
|
cell_queue_t n_chan_cells;
|
||||||
/** The OR connection that is next in this circuit. */
|
/** The channel that is next in this circuit. */
|
||||||
or_connection_t *n_conn;
|
channel_t *n_chan;
|
||||||
/** The circuit_id used in the next (forward) hop of this circuit. */
|
/** The circuit_id used in the next (forward) hop of this circuit. */
|
||||||
circid_t n_circ_id;
|
circid_t n_circ_id;
|
||||||
|
|
||||||
@ -2600,12 +2600,12 @@ typedef struct circuit_t {
|
|||||||
* the circuit has attached to a connection. */
|
* the circuit has attached to a connection. */
|
||||||
extend_info_t *n_hop;
|
extend_info_t *n_hop;
|
||||||
|
|
||||||
/** True iff we are waiting for n_conn_cells to become less full before
|
/** True iff we are waiting for n_chan_cells to become less full before
|
||||||
* allowing p_streams to add any more cells. (Origin circuit only.) */
|
* allowing p_streams to add any more cells. (Origin circuit only.) */
|
||||||
unsigned int streams_blocked_on_n_conn : 1;
|
unsigned int streams_blocked_on_n_chan : 1;
|
||||||
/** True iff we are waiting for p_conn_cells to become less full before
|
/** True iff we are waiting for p_chan_cells to become less full before
|
||||||
* allowing n_streams to add any more cells. (OR circuit only.) */
|
* allowing n_streams to add any more cells. (OR circuit only.) */
|
||||||
unsigned int streams_blocked_on_p_conn : 1;
|
unsigned int streams_blocked_on_p_chan : 1;
|
||||||
|
|
||||||
uint8_t state; /**< Current status of this circuit. */
|
uint8_t state; /**< Current status of this circuit. */
|
||||||
uint8_t purpose; /**< Why are we creating this circuit? */
|
uint8_t purpose; /**< Why are we creating this circuit? */
|
||||||
@ -2620,10 +2620,10 @@ typedef struct circuit_t {
|
|||||||
* more. */
|
* more. */
|
||||||
int deliver_window;
|
int deliver_window;
|
||||||
|
|
||||||
/** For storage while n_conn is pending
|
/** For storage while n_chan is pending
|
||||||
* (state CIRCUIT_STATE_OR_WAIT). When defined, it is always
|
* (state CIRCUIT_STATE_CHAN_WAIT). When defined, it is always
|
||||||
* length ONIONSKIN_CHALLENGE_LEN. */
|
* length ONIONSKIN_CHALLENGE_LEN. */
|
||||||
char *n_conn_onionskin;
|
char *n_chan_onionskin;
|
||||||
|
|
||||||
/** When was this circuit created? We keep this timestamp with a higher
|
/** When was this circuit created? We keep this timestamp with a higher
|
||||||
* resolution than most so that the circuit-build-time tracking code can
|
* resolution than most so that the circuit-build-time tracking code can
|
||||||
@ -2652,11 +2652,11 @@ typedef struct circuit_t {
|
|||||||
/** Next circuit in the doubly-linked ring of circuits waiting to add
|
/** Next circuit in the doubly-linked ring of circuits waiting to add
|
||||||
* cells to n_conn. NULL if we have no cells pending, or if we're not
|
* cells to n_conn. NULL if we have no cells pending, or if we're not
|
||||||
* linked to an OR connection. */
|
* linked to an OR connection. */
|
||||||
struct circuit_t *next_active_on_n_conn;
|
struct circuit_t *next_active_on_n_chan;
|
||||||
/** Previous circuit in the doubly-linked ring of circuits waiting to add
|
/** Previous circuit in the doubly-linked ring of circuits waiting to add
|
||||||
* cells to n_conn. NULL if we have no cells pending, or if we're not
|
* cells to n_conn. NULL if we have no cells pending, or if we're not
|
||||||
* linked to an OR connection. */
|
* linked to an OR connection. */
|
||||||
struct circuit_t *prev_active_on_n_conn;
|
struct circuit_t *prev_active_on_n_chan;
|
||||||
struct circuit_t *next; /**< Next circuit in linked list of all circuits. */
|
struct circuit_t *next; /**< Next circuit in linked list of all circuits. */
|
||||||
|
|
||||||
/** Unique ID for measuring tunneled network status requests. */
|
/** Unique ID for measuring tunneled network status requests. */
|
||||||
@ -2828,20 +2828,20 @@ typedef struct or_circuit_t {
|
|||||||
circuit_t _base;
|
circuit_t _base;
|
||||||
|
|
||||||
/** Next circuit in the doubly-linked ring of circuits waiting to add
|
/** Next circuit in the doubly-linked ring of circuits waiting to add
|
||||||
* cells to p_conn. NULL if we have no cells pending, or if we're not
|
* cells to p_chan. NULL if we have no cells pending, or if we're not
|
||||||
* linked to an OR connection. */
|
* linked to an OR connection. */
|
||||||
struct circuit_t *next_active_on_p_conn;
|
struct circuit_t *next_active_on_p_chan;
|
||||||
/** Previous circuit in the doubly-linked ring of circuits waiting to add
|
/** Previous circuit in the doubly-linked ring of circuits waiting to add
|
||||||
* cells to p_conn. NULL if we have no cells pending, or if we're not
|
* cells to p_chan. NULL if we have no cells pending, or if we're not
|
||||||
* linked to an OR connection. */
|
* linked to an OR connection. */
|
||||||
struct circuit_t *prev_active_on_p_conn;
|
struct circuit_t *prev_active_on_p_chan;
|
||||||
|
|
||||||
/** The circuit_id used in the previous (backward) hop of this circuit. */
|
/** The circuit_id used in the previous (backward) hop of this circuit. */
|
||||||
circid_t p_circ_id;
|
circid_t p_circ_id;
|
||||||
/** Queue of cells waiting to be transmitted on p_conn. */
|
/** Queue of cells waiting to be transmitted on p_conn. */
|
||||||
cell_queue_t p_conn_cells;
|
cell_queue_t p_chan_cells;
|
||||||
/** The OR connection that is previous in this circuit. */
|
/** The channel that is previous in this circuit. */
|
||||||
or_connection_t *p_conn;
|
channel_t *p_chan;
|
||||||
/** Linked list of Exit streams associated with this circuit. */
|
/** Linked list of Exit streams associated with this circuit. */
|
||||||
edge_connection_t *n_streams;
|
edge_connection_t *n_streams;
|
||||||
/** Linked list of Exit streams associated with this circuit that are
|
/** Linked list of Exit streams associated with this circuit that are
|
||||||
|
@ -323,8 +323,8 @@ circuit_end_reason_to_control_string(int reason)
|
|||||||
return "CONNECTFAILED";
|
return "CONNECTFAILED";
|
||||||
case END_CIRC_REASON_OR_IDENTITY:
|
case END_CIRC_REASON_OR_IDENTITY:
|
||||||
return "OR_IDENTITY";
|
return "OR_IDENTITY";
|
||||||
case END_CIRC_REASON_OR_CONN_CLOSED:
|
case END_CIRC_REASON_CHANNEL_CLOSED:
|
||||||
return "OR_CONN_CLOSED";
|
return "CHANNEL_CLOSED";
|
||||||
case END_CIRC_REASON_FINISHED:
|
case END_CIRC_REASON_FINISHED:
|
||||||
return "FINISHED";
|
return "FINISHED";
|
||||||
case END_CIRC_REASON_TIMEOUT:
|
case END_CIRC_REASON_TIMEOUT:
|
||||||
|
@ -45,15 +45,15 @@ void cell_queue_clear(cell_queue_t *queue);
|
|||||||
void cell_queue_append(cell_queue_t *queue, packed_cell_t *cell);
|
void cell_queue_append(cell_queue_t *queue, packed_cell_t *cell);
|
||||||
void cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell);
|
void cell_queue_append_packed_copy(cell_queue_t *queue, const cell_t *cell);
|
||||||
|
|
||||||
void append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn,
|
void append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan,
|
||||||
cell_t *cell, cell_direction_t direction,
|
cell_t *cell, cell_direction_t direction,
|
||||||
streamid_t fromstream);
|
streamid_t fromstream);
|
||||||
void connection_or_unlink_all_active_circs(or_connection_t *conn);
|
void channel_unlink_all_active_circs(channel_t *chan);
|
||||||
int connection_or_flush_from_first_active_circuit(or_connection_t *conn,
|
int channel_flush_from_first_active_circuit(channel_t *conn,
|
||||||
int max, time_t now);
|
int max, time_t now);
|
||||||
void assert_active_circuits_ok(or_connection_t *orconn);
|
void assert_active_circuits_ok(or_connection_t *orconn);
|
||||||
void make_circuit_inactive_on_conn(circuit_t *circ, or_connection_t *conn);
|
void make_circuit_inactive_on_chan(circuit_t *circ, channel_t *chan);
|
||||||
void make_circuit_active_on_conn(circuit_t *circ, or_connection_t *conn);
|
void make_circuit_active_on_chan(circuit_t *circ, channel_t *chan);
|
||||||
|
|
||||||
int append_address_to_payload(uint8_t *payload_out, const tor_addr_t *addr);
|
int append_address_to_payload(uint8_t *payload_out, const tor_addr_t *addr);
|
||||||
const uint8_t *decode_address_from_payload(tor_addr_t *addr_out,
|
const uint8_t *decode_address_from_payload(tor_addr_t *addr_out,
|
||||||
@ -62,7 +62,7 @@ const uint8_t *decode_address_from_payload(tor_addr_t *addr_out,
|
|||||||
unsigned cell_ewma_get_tick(void);
|
unsigned cell_ewma_get_tick(void);
|
||||||
void cell_ewma_set_scale_factor(const or_options_t *options,
|
void cell_ewma_set_scale_factor(const or_options_t *options,
|
||||||
const networkstatus_t *consensus);
|
const networkstatus_t *consensus);
|
||||||
void circuit_clear_cell_queue(circuit_t *circ, or_connection_t *orconn);
|
void circuit_clear_cell_queue(circuit_t *circ, channel_t *chan);
|
||||||
|
|
||||||
#ifdef RELAY_PRIVATE
|
#ifdef RELAY_PRIVATE
|
||||||
int relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction,
|
int relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction,
|
||||||
|
Loading…
Reference in New Issue
Block a user