mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 04:13:28 +01:00
Don't tell anybody, but we're going OO here. This patch splits
circuit_t into origin_circuit_t and or_circuit_t. I fixed some segaults; there may be more. We still need to move more rendezvous stuff into subtypes. This is a trial run for splitting up connection_t; if the approach is insane, please say so soon so we can do something smarter. Also, this discards the old HALF_OPEN code, which nobody seems to want. svn:r6817
This commit is contained in:
parent
6d2eb77555
commit
7239262f71
@ -43,7 +43,7 @@ static int entry_guards_dirty = 0;
|
||||
|
||||
static int circuit_deliver_create_cell(circuit_t *circ,
|
||||
uint8_t cell_type, char *payload);
|
||||
static int onion_pick_cpath_exit(circuit_t *circ, extend_info_t *exit);
|
||||
static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit);
|
||||
static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath);
|
||||
static int onion_extend_cpath(uint8_t purpose, crypt_path_t **head_ptr,
|
||||
cpath_build_state_t *state);
|
||||
@ -95,14 +95,13 @@ get_unique_circ_id_by_conn(connection_t *conn)
|
||||
* a more verbose format using spaces.
|
||||
*/
|
||||
char *
|
||||
circuit_list_path(circuit_t *circ, int verbose)
|
||||
circuit_list_path(origin_circuit_t *circ, int verbose)
|
||||
{
|
||||
crypt_path_t *hop;
|
||||
smartlist_t *elements;
|
||||
const char *states[] = {"closed", "waiting for keys", "open"};
|
||||
char buf[128];
|
||||
char *s;
|
||||
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
||||
|
||||
elements = smartlist_create();
|
||||
|
||||
@ -112,8 +111,8 @@ circuit_list_path(circuit_t *circ, int verbose)
|
||||
circ->build_state->is_internal ? "internal" : "exit",
|
||||
circ->build_state->need_uptime ? " (high-uptime)" : "",
|
||||
circ->build_state->desired_path_len,
|
||||
circ->state == CIRCUIT_STATE_OPEN ? "" : ", exit ",
|
||||
circ->state == CIRCUIT_STATE_OPEN ? "" :
|
||||
circ->_base.state == CIRCUIT_STATE_OPEN ? "" : ", exit ",
|
||||
circ->_base.state == CIRCUIT_STATE_OPEN ? "" :
|
||||
(nickname?nickname:"*unnamed*"));
|
||||
smartlist_add(elements, tor_strdup(buf));
|
||||
}
|
||||
@ -152,7 +151,7 @@ circuit_list_path(circuit_t *circ, int verbose)
|
||||
* exit point.
|
||||
*/
|
||||
void
|
||||
circuit_log_path(int severity, unsigned int domain, circuit_t *circ)
|
||||
circuit_log_path(int severity, unsigned int domain, origin_circuit_t *circ)
|
||||
{
|
||||
char *s = circuit_list_path(circ,1);
|
||||
log(severity,domain,"%s",s);
|
||||
@ -165,7 +164,7 @@ circuit_log_path(int severity, unsigned int domain, circuit_t *circ)
|
||||
* unable to extend.
|
||||
*/
|
||||
void
|
||||
circuit_rep_hist_note_result(circuit_t *circ)
|
||||
circuit_rep_hist_note_result(origin_circuit_t *circ)
|
||||
{
|
||||
crypt_path_t *hop;
|
||||
char *prev_digest = NULL;
|
||||
@ -206,74 +205,14 @@ circuit_rep_hist_note_result(circuit_t *circ)
|
||||
} while (hop!=circ->cpath);
|
||||
}
|
||||
|
||||
/** A helper function for circuit_dump_by_conn() below. Log a bunch
|
||||
* of information about circuit <b>circ</b>.
|
||||
*/
|
||||
static void
|
||||
circuit_dump_details(int severity, circuit_t *circ, int poll_index,
|
||||
const char *type, int this_circid, int other_circid)
|
||||
{
|
||||
log(severity, LD_CIRC, "Conn %d has %s circuit: circID %d (other side %d), "
|
||||
"state %d (%s), born %d:",
|
||||
poll_index, type, this_circid, other_circid, circ->state,
|
||||
circuit_state_to_string(circ->state), (int)circ->timestamp_created);
|
||||
if (CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */
|
||||
circuit_log_path(severity, LD_CIRC, circ);
|
||||
}
|
||||
}
|
||||
|
||||
/** Log, at severity <b>severity</b>, information about each circuit
|
||||
* that is connected to <b>conn</b>.
|
||||
*/
|
||||
void
|
||||
circuit_dump_by_conn(connection_t *conn, int severity)
|
||||
{
|
||||
circuit_t *circ;
|
||||
connection_t *tmpconn;
|
||||
|
||||
for (circ=global_circuitlist;circ;circ = circ->next) {
|
||||
if (circ->marked_for_close)
|
||||
continue;
|
||||
if (circ->p_conn == conn)
|
||||
circuit_dump_details(severity, circ, conn->poll_index, "App-ward",
|
||||
circ->p_circ_id, circ->n_circ_id);
|
||||
for (tmpconn=circ->p_streams; tmpconn; tmpconn=tmpconn->next_stream) {
|
||||
if (tmpconn == conn) {
|
||||
circuit_dump_details(severity, circ, conn->poll_index, "App-ward",
|
||||
circ->p_circ_id, circ->n_circ_id);
|
||||
}
|
||||
}
|
||||
if (circ->n_conn == conn)
|
||||
circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward",
|
||||
circ->n_circ_id, circ->p_circ_id);
|
||||
for (tmpconn=circ->n_streams; tmpconn; tmpconn=tmpconn->next_stream) {
|
||||
if (tmpconn == conn) {
|
||||
circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward",
|
||||
circ->n_circ_id, circ->p_circ_id);
|
||||
}
|
||||
}
|
||||
if (!circ->n_conn && circ->n_addr && circ->n_port &&
|
||||
circ->n_addr == conn->addr &&
|
||||
circ->n_port == conn->port &&
|
||||
!memcmp(conn->identity_digest, circ->n_conn_id_digest, DIGEST_LEN)) {
|
||||
circuit_dump_details(severity, circ, conn->poll_index,
|
||||
(circ->state == CIRCUIT_STATE_OPEN &&
|
||||
!CIRCUIT_IS_ORIGIN(circ)) ?
|
||||
"Endpoint" : "Pending",
|
||||
circ->n_circ_id, circ->p_circ_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Pick all the entries in our cpath. Stop and return 0 when we're
|
||||
* happy, or return -1 if an error occurs. */
|
||||
static int
|
||||
onion_populate_cpath(circuit_t *circ)
|
||||
onion_populate_cpath(origin_circuit_t *circ)
|
||||
{
|
||||
int r;
|
||||
again:
|
||||
r = onion_extend_cpath(circ->purpose, &circ->cpath, circ->build_state);
|
||||
// || !CIRCUIT_IS_ORIGIN(circ)) { // wtf? -rd
|
||||
r = onion_extend_cpath(circ->_base.purpose, &circ->cpath, circ->build_state);
|
||||
if (r < 0) {
|
||||
log_info(LD_CIRC,"Generating cpath hop failed.");
|
||||
return -1;
|
||||
@ -283,19 +222,20 @@ again:
|
||||
return 0; /* if r == 1 */
|
||||
}
|
||||
|
||||
/** Create and return a new circuit. Initialize its purpose and
|
||||
/** Create and return a new origin circuit. Initialize its purpose and
|
||||
* build-state based on our arguments. */
|
||||
circuit_t *
|
||||
circuit_init(uint8_t purpose, int need_uptime, int need_capacity, int internal)
|
||||
origin_circuit_t *
|
||||
origin_circuit_init(uint8_t purpose, int need_uptime, int need_capacity,
|
||||
int internal)
|
||||
{
|
||||
/* sets circ->p_circ_id and circ->p_conn */
|
||||
circuit_t *circ = circuit_new(0, NULL);
|
||||
circuit_set_state(circ, CIRCUIT_STATE_OR_WAIT);
|
||||
origin_circuit_t *circ = origin_circuit_new();
|
||||
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OR_WAIT);
|
||||
circ->build_state = tor_malloc_zero(sizeof(cpath_build_state_t));
|
||||
circ->build_state->need_uptime = need_uptime;
|
||||
circ->build_state->need_capacity = need_capacity;
|
||||
circ->build_state->is_internal = internal;
|
||||
circ->purpose = purpose;
|
||||
circ->_base.purpose = purpose;
|
||||
return circ;
|
||||
}
|
||||
|
||||
@ -306,24 +246,24 @@ circuit_init(uint8_t purpose, int need_uptime, int need_capacity, int internal)
|
||||
* Also launch a connection to the first OR in the chosen path, if
|
||||
* it's not open already.
|
||||
*/
|
||||
circuit_t *
|
||||
origin_circuit_t *
|
||||
circuit_establish_circuit(uint8_t purpose, extend_info_t *info,
|
||||
int need_uptime, int need_capacity, int internal)
|
||||
{
|
||||
circuit_t *circ;
|
||||
origin_circuit_t *circ;
|
||||
|
||||
circ = circuit_init(purpose, need_uptime, need_capacity, internal);
|
||||
circ = origin_circuit_init(purpose, need_uptime, need_capacity, internal);
|
||||
|
||||
if (onion_pick_cpath_exit(circ, info) < 0 ||
|
||||
onion_populate_cpath(circ) < 0) {
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
control_event_circuit_status(circ, CIRC_EVENT_LAUNCHED);
|
||||
|
||||
if (circuit_handle_first_hop(circ) < 0) {
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
|
||||
return NULL;
|
||||
}
|
||||
return circ;
|
||||
@ -334,7 +274,7 @@ circuit_establish_circuit(uint8_t purpose, extend_info_t *info,
|
||||
* it. If we're already connected, then send the 'create' cell.
|
||||
* Return 0 for ok, -1 if circ should be marked-for-close. */
|
||||
int
|
||||
circuit_handle_first_hop(circuit_t *circ)
|
||||
circuit_handle_first_hop(origin_circuit_t *circ)
|
||||
{
|
||||
crypt_path_t *firsthop;
|
||||
connection_t *n_conn;
|
||||
@ -351,7 +291,7 @@ circuit_handle_first_hop(circuit_t *circ)
|
||||
log_debug(LD_CIRC,"Looking for firsthop '%s:%u'",tmpbuf,
|
||||
firsthop->extend_info->port);
|
||||
/* imprint the circuit with its future n_conn->id */
|
||||
memcpy(circ->n_conn_id_digest, firsthop->extend_info->identity_digest,
|
||||
memcpy(circ->_base.n_conn_id_digest, firsthop->extend_info->identity_digest,
|
||||
DIGEST_LEN);
|
||||
n_conn = connection_or_get_by_identity_digest(
|
||||
firsthop->extend_info->identity_digest);
|
||||
@ -363,8 +303,8 @@ circuit_handle_first_hop(circuit_t *circ)
|
||||
router_digest_version_as_new_as(firsthop->extend_info->identity_digest,
|
||||
"0.1.1.9-alpha-cvs"))) {
|
||||
/* not currently connected */
|
||||
circ->n_addr = firsthop->extend_info->addr;
|
||||
circ->n_port = firsthop->extend_info->port;
|
||||
circ->_base.n_addr = firsthop->extend_info->addr;
|
||||
circ->_base.n_port = firsthop->extend_info->port;
|
||||
|
||||
if (!n_conn || n_conn->is_obsolete) { /* launch the connection */
|
||||
n_conn = connection_or_connect(firsthop->extend_info->addr,
|
||||
@ -383,9 +323,9 @@ circuit_handle_first_hop(circuit_t *circ)
|
||||
*/
|
||||
return 0;
|
||||
} else { /* it's already open. use it. */
|
||||
circ->n_addr = n_conn->addr;
|
||||
circ->n_port = n_conn->port;
|
||||
circ->n_conn = n_conn;
|
||||
circ->_base.n_addr = n_conn->addr;
|
||||
circ->_base.n_port = n_conn->port;
|
||||
circ->_base.n_conn = n_conn;
|
||||
log_debug(LD_CIRC,"Conn open. Delivering first onion skin.");
|
||||
if (circuit_send_next_onion_skin(circ) < 0) {
|
||||
log_info(LD_CIRC,"circuit_send_next_onion_skin failed.");
|
||||
@ -433,7 +373,7 @@ circuit_n_conn_done(connection_t *or_conn, int status)
|
||||
* set_circid_orconn here. */
|
||||
circ->n_conn = or_conn;
|
||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||
if (circuit_send_next_onion_skin(circ) < 0) {
|
||||
if (circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ)) < 0) {
|
||||
log_info(LD_CIRC,
|
||||
"send_next_onion_skin failed; circuit marked for closing.");
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
@ -471,7 +411,8 @@ circuit_n_conn_done(connection_t *or_conn, int status)
|
||||
* Return -1 if we failed to find a suitable circid, else return 0.
|
||||
*/
|
||||
static int
|
||||
circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type, char *payload)
|
||||
circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type,
|
||||
char *payload)
|
||||
{
|
||||
cell_t cell;
|
||||
uint16_t id;
|
||||
@ -488,7 +429,7 @@ circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type, char *payload)
|
||||
return -1;
|
||||
}
|
||||
log_debug(LD_CIRC,"Chosen circID %u.", id);
|
||||
circuit_set_circid_orconn(circ, id, circ->n_conn, N_CONN_CHANGED);
|
||||
circuit_set_n_circid_orconn(circ, id, circ->n_conn);
|
||||
|
||||
memset(&cell, 0, sizeof(cell_t));
|
||||
cell.command = cell_type;
|
||||
@ -552,7 +493,7 @@ extern int has_completed_circuit;
|
||||
* Return -reason if we want to tear down circ, else return 0.
|
||||
*/
|
||||
int
|
||||
circuit_send_next_onion_skin(circuit_t *circ)
|
||||
circuit_send_next_onion_skin(origin_circuit_t *circ)
|
||||
{
|
||||
crypt_path_t *hop;
|
||||
routerinfo_t *router;
|
||||
@ -561,14 +502,13 @@ circuit_send_next_onion_skin(circuit_t *circ)
|
||||
size_t payload_len;
|
||||
|
||||
tor_assert(circ);
|
||||
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
||||
|
||||
if (circ->cpath->state == CPATH_STATE_CLOSED) {
|
||||
int fast;
|
||||
uint8_t cell_type;
|
||||
log_debug(LD_CIRC,"First skin; sending create cell.");
|
||||
|
||||
router = router_get_by_digest(circ->n_conn->identity_digest);
|
||||
router = router_get_by_digest(circ->_base.n_conn->identity_digest);
|
||||
fast = should_use_create_fast_for_router(router);
|
||||
if (! fast) {
|
||||
/* We are an OR, or we are connecting to an old Tor: we should
|
||||
@ -593,22 +533,22 @@ circuit_send_next_onion_skin(circuit_t *circ)
|
||||
sizeof(circ->cpath->fast_handshake_state));
|
||||
}
|
||||
|
||||
if (circuit_deliver_create_cell(circ, cell_type, payload) < 0)
|
||||
if (circuit_deliver_create_cell(TO_CIRCUIT(circ), cell_type, payload) < 0)
|
||||
return - END_CIRC_REASON_RESOURCELIMIT;
|
||||
|
||||
circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
|
||||
circuit_set_state(circ, CIRCUIT_STATE_BUILDING);
|
||||
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
|
||||
log_info(LD_CIRC,"First hop: finished sending %s cell to '%s'",
|
||||
fast ? "CREATE_FAST" : "CREATE",
|
||||
router ? router->nickname : "<unnamed>");
|
||||
} else {
|
||||
tor_assert(circ->cpath->state == CPATH_STATE_OPEN);
|
||||
tor_assert(circ->state == CIRCUIT_STATE_BUILDING);
|
||||
tor_assert(circ->_base.state == CIRCUIT_STATE_BUILDING);
|
||||
log_debug(LD_CIRC,"starting to send subsequent skin.");
|
||||
hop = onion_next_hop_in_cpath(circ->cpath);
|
||||
if (!hop) {
|
||||
/* done building the circuit. whew. */
|
||||
circuit_set_state(circ, CIRCUIT_STATE_OPEN);
|
||||
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);
|
||||
log_info(LD_CIRC,"circuit built!");
|
||||
circuit_reset_failure_count(0);
|
||||
if (!has_completed_circuit) {
|
||||
@ -645,7 +585,8 @@ circuit_send_next_onion_skin(circuit_t *circ)
|
||||
log_debug(LD_CIRC,"Sending extend relay cell.");
|
||||
/* send it to hop->prev, because it will transfer
|
||||
* it to a create cell and then send to hop */
|
||||
if (connection_edge_send_command(NULL, circ, RELAY_COMMAND_EXTEND,
|
||||
if (connection_edge_send_command(NULL, TO_CIRCUIT(circ),
|
||||
RELAY_COMMAND_EXTEND,
|
||||
payload, payload_len, hop->prev) < 0)
|
||||
return 0; /* circuit is closed */
|
||||
|
||||
@ -820,12 +761,12 @@ circuit_init_cpath_crypto(crypt_path_t *cpath, char *key_data, int reverse)
|
||||
* Return - reason if we want to mark circ for close, else return 0.
|
||||
*/
|
||||
int
|
||||
circuit_finish_handshake(circuit_t *circ, uint8_t reply_type, char *reply)
|
||||
circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type,
|
||||
char *reply)
|
||||
{
|
||||
char keys[CPATH_KEY_MATERIAL_LEN];
|
||||
crypt_path_t *hop;
|
||||
|
||||
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
||||
if (circ->cpath->state == CPATH_STATE_AWAITING_KEYS)
|
||||
hop = circ->cpath;
|
||||
else {
|
||||
@ -883,20 +824,19 @@ circuit_finish_handshake(circuit_t *circ, uint8_t reply_type, char *reply)
|
||||
* just give up: for circ to close, and return 0.
|
||||
*/
|
||||
int
|
||||
circuit_truncated(circuit_t *circ, crypt_path_t *layer)
|
||||
circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer)
|
||||
{
|
||||
// crypt_path_t *victim;
|
||||
// connection_t *stream;
|
||||
|
||||
tor_assert(circ);
|
||||
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
||||
tor_assert(layer);
|
||||
|
||||
/* XXX Since we don't ask for truncates currently, getting a truncated
|
||||
* means that a connection broke or an extend failed. For now,
|
||||
* just give up.
|
||||
*/
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
@ -929,7 +869,8 @@ circuit_truncated(circuit_t *circ, crypt_path_t *layer)
|
||||
* cell back.
|
||||
*/
|
||||
int
|
||||
onionskin_answer(circuit_t *circ, uint8_t cell_type, char *payload, char *keys)
|
||||
onionskin_answer(or_circuit_t *circ, uint8_t cell_type, char *payload,
|
||||
char *keys)
|
||||
{
|
||||
cell_t cell;
|
||||
crypt_path_t *tmp_cpath;
|
||||
@ -941,7 +882,7 @@ onionskin_answer(circuit_t *circ, uint8_t cell_type, char *payload, char *keys)
|
||||
cell.command = cell_type;
|
||||
cell.circ_id = circ->p_circ_id;
|
||||
|
||||
circuit_set_state(circ, CIRCUIT_STATE_OPEN);
|
||||
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);
|
||||
|
||||
memcpy(cell.payload, payload,
|
||||
cell_type == CELL_CREATED ? ONIONSKIN_REPLY_LEN : DIGEST_LEN*2);
|
||||
@ -1338,13 +1279,13 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
|
||||
* router (or use <b>exit</b> if provided). Store these in the
|
||||
* cpath. Return 0 if ok, -1 if circuit should be closed. */
|
||||
static int
|
||||
onion_pick_cpath_exit(circuit_t *circ, extend_info_t *exit)
|
||||
onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
|
||||
{
|
||||
cpath_build_state_t *state = circ->build_state;
|
||||
routerlist_t *rl = router_get_routerlist();
|
||||
int r;
|
||||
|
||||
r = new_route_len(get_options()->PathlenCoinWeight, circ->purpose,
|
||||
r = new_route_len(get_options()->PathlenCoinWeight, circ->_base.purpose,
|
||||
exit, rl->routers);
|
||||
if (r < 1) /* must be at least 1 */
|
||||
return -1;
|
||||
@ -1355,8 +1296,8 @@ onion_pick_cpath_exit(circuit_t *circ, extend_info_t *exit)
|
||||
exit = extend_info_dup(exit);
|
||||
} else { /* we have to decide one */
|
||||
routerinfo_t *router =
|
||||
choose_good_exit_server(circ->purpose, rl, state->need_uptime,
|
||||
state->need_capacity, state->is_internal);
|
||||
choose_good_exit_server(circ->_base.purpose, rl, state->need_uptime,
|
||||
state->need_capacity, state->is_internal);
|
||||
if (!router) {
|
||||
log_warn(LD_CIRC,"failed to choose an exit server");
|
||||
return -1;
|
||||
@ -1372,11 +1313,11 @@ onion_pick_cpath_exit(circuit_t *circ, extend_info_t *exit)
|
||||
* the caller will do this if it wants to.
|
||||
*/
|
||||
int
|
||||
circuit_append_new_exit(circuit_t *circ, extend_info_t *info)
|
||||
circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info)
|
||||
{
|
||||
cpath_build_state_t *state;
|
||||
tor_assert(info);
|
||||
tor_assert(circ && CIRCUIT_IS_ORIGIN(circ));
|
||||
tor_assert(circ);
|
||||
|
||||
state = circ->build_state;
|
||||
tor_assert(state);
|
||||
@ -1394,15 +1335,14 @@ circuit_append_new_exit(circuit_t *circ, extend_info_t *info)
|
||||
* send the next extend cell to begin connecting to that hop.
|
||||
*/
|
||||
int
|
||||
circuit_extend_to_new_exit(circuit_t *circ, extend_info_t *info)
|
||||
circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info)
|
||||
{
|
||||
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
||||
circuit_append_new_exit(circ, info);
|
||||
circuit_set_state(circ, CIRCUIT_STATE_BUILDING);
|
||||
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
|
||||
if (circuit_send_next_onion_skin(circ)<0) {
|
||||
log_warn(LD_CIRC, "Couldn't extend circuit to new point '%s'.",
|
||||
info->nickname);
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -68,35 +68,14 @@ HT_GENERATE(orconn_circid_map, orconn_circid_circuit_map_t, node,
|
||||
*/
|
||||
orconn_circid_circuit_map_t *_last_circid_orconn_ent = NULL;
|
||||
|
||||
/** Set the p_conn or n_conn field of a circuit <b>circ</b>, along
|
||||
* with the corresponding circuit ID, and add the circuit as appropriate
|
||||
* to the (orconn,id)-\>circuit map. */
|
||||
void
|
||||
circuit_set_circid_orconn(circuit_t *circ, uint16_t id,
|
||||
connection_t *conn,
|
||||
enum which_conn_changed_t which)
|
||||
static void
|
||||
circuit_set_circid_orconn_helper(circuit_t *circ, uint16_t id,
|
||||
connection_t *conn,
|
||||
uint16_t old_id, connection_t *old_conn)
|
||||
{
|
||||
uint16_t old_id;
|
||||
connection_t *old_conn;
|
||||
orconn_circid_circuit_map_t search;
|
||||
orconn_circid_circuit_map_t *found;
|
||||
|
||||
tor_assert(!conn || conn->type == CONN_TYPE_OR);
|
||||
|
||||
if (which == P_CONN_CHANGED) {
|
||||
old_id = circ->p_circ_id;
|
||||
old_conn = circ->p_conn;
|
||||
circ->p_circ_id = id;
|
||||
circ->p_conn = conn;
|
||||
} else {
|
||||
old_id = circ->n_circ_id;
|
||||
old_conn = circ->n_conn;
|
||||
circ->n_circ_id = id;
|
||||
circ->n_conn = conn;
|
||||
}
|
||||
if (conn == old_conn && old_id == id)
|
||||
return;
|
||||
|
||||
if (_last_circid_orconn_ent &&
|
||||
((old_id == _last_circid_orconn_ent->circ_id &&
|
||||
old_conn == _last_circid_orconn_ent->or_conn) ||
|
||||
@ -135,6 +114,47 @@ circuit_set_circid_orconn(circuit_t *circ, uint16_t id,
|
||||
++conn->n_circuits;
|
||||
}
|
||||
|
||||
/** Set the p_conn field of a circuit <b>circ</b>, along
|
||||
* with the corresponding circuit ID, and add the circuit as appropriate
|
||||
* to the (orconn,id)-\>circuit map. */
|
||||
void
|
||||
circuit_set_p_circid_orconn(or_circuit_t *circ, uint16_t id,
|
||||
connection_t *conn)
|
||||
{
|
||||
uint16_t old_id;
|
||||
connection_t *old_conn;
|
||||
|
||||
old_id = circ->p_circ_id;
|
||||
old_conn = circ->p_conn;
|
||||
circ->p_circ_id = id;
|
||||
circ->p_conn = conn;
|
||||
|
||||
if (id == old_id && conn == old_conn)
|
||||
return;
|
||||
circuit_set_circid_orconn_helper(TO_CIRCUIT(circ), id, conn,
|
||||
old_id, old_conn);
|
||||
}
|
||||
|
||||
/** Set the n_conn field of a circuit <b>circ</b>, along
|
||||
* with the corresponding circuit ID, and add the circuit as appropriate
|
||||
* to the (orconn,id)-\>circuit map. */
|
||||
void
|
||||
circuit_set_n_circid_orconn(circuit_t *circ, uint16_t id,
|
||||
connection_t *conn)
|
||||
{
|
||||
uint16_t old_id;
|
||||
connection_t *old_conn;
|
||||
|
||||
old_id = circ->n_circ_id;
|
||||
old_conn = circ->n_conn;
|
||||
circ->n_circ_id = id;
|
||||
circ->n_conn = conn;
|
||||
|
||||
if (id == old_id && conn == old_conn)
|
||||
return;
|
||||
circuit_set_circid_orconn_helper(circ, id, conn, old_id, old_conn);
|
||||
}
|
||||
|
||||
/** Change the state of <b>circ</b> to <b>state</b>, adding it to or removing
|
||||
* it from lists as appropriate. */
|
||||
void
|
||||
@ -224,36 +244,53 @@ circuit_state_to_string(int state)
|
||||
}
|
||||
}
|
||||
|
||||
/** Allocate space for a new circuit, initializing with <b>p_circ_id</b>
|
||||
* and <b>p_conn</b>. Add it to the global circuit list.
|
||||
*/
|
||||
circuit_t *
|
||||
circuit_new(uint16_t p_circ_id, connection_t *p_conn)
|
||||
/* DOCDOC */
|
||||
static void
|
||||
init_circuit_base(circuit_t *circ)
|
||||
{
|
||||
circuit_t *circ;
|
||||
static uint32_t n_circuits_allocated = 1;
|
||||
/* never zero, since a global ID of 0 is treated specially by the
|
||||
* controller */
|
||||
|
||||
circ = tor_malloc_zero(sizeof(circuit_t));
|
||||
circ->magic = CIRCUIT_MAGIC;
|
||||
|
||||
circ->timestamp_created = time(NULL);
|
||||
|
||||
/* CircIDs */
|
||||
if (p_conn) {
|
||||
circuit_set_circid_orconn(circ, p_circ_id, p_conn, P_CONN_CHANGED);
|
||||
}
|
||||
/* circ->n_circ_id remains 0 because we haven't identified the next hop
|
||||
* yet */
|
||||
|
||||
circ->package_window = CIRCWINDOW_START;
|
||||
circ->deliver_window = CIRCWINDOW_START;
|
||||
|
||||
circ->next_stream_id = crypto_rand_int(1<<16);
|
||||
circ->global_identifier = n_circuits_allocated++;
|
||||
|
||||
circuit_add(circ);
|
||||
}
|
||||
|
||||
/** Allocate space for a new circuit, initializing with <b>p_circ_id</b>
|
||||
* and <b>p_conn</b>. Add it to the global circuit list.
|
||||
*/
|
||||
origin_circuit_t *
|
||||
origin_circuit_new(void)
|
||||
{
|
||||
origin_circuit_t *circ;
|
||||
|
||||
circ = tor_malloc_zero(sizeof(origin_circuit_t));
|
||||
circ->_base.magic = ORIGIN_CIRCUIT_MAGIC;
|
||||
|
||||
circ->next_stream_id = crypto_rand_int(1<<16);
|
||||
|
||||
init_circuit_base(TO_CIRCUIT(circ));
|
||||
|
||||
return circ;
|
||||
}
|
||||
|
||||
or_circuit_t *
|
||||
or_circuit_new(uint16_t p_circ_id, connection_t *p_conn)
|
||||
{
|
||||
/* CircIDs */
|
||||
or_circuit_t *circ;
|
||||
|
||||
circ = tor_malloc_zero(sizeof(or_circuit_t));
|
||||
circ->_base.magic = OR_CIRCUIT_MAGIC;
|
||||
|
||||
if (p_conn)
|
||||
circuit_set_p_circid_orconn(circ, p_circ_id, p_conn);
|
||||
|
||||
init_circuit_base(TO_CIRCUIT(circ));
|
||||
|
||||
return circ;
|
||||
}
|
||||
@ -263,35 +300,53 @@ circuit_new(uint16_t p_circ_id, connection_t *p_conn)
|
||||
static void
|
||||
circuit_free(circuit_t *circ)
|
||||
{
|
||||
void *mem;
|
||||
tor_assert(circ);
|
||||
tor_assert(circ->magic == CIRCUIT_MAGIC);
|
||||
if (circ->n_crypto)
|
||||
crypto_free_cipher_env(circ->n_crypto);
|
||||
if (circ->p_crypto)
|
||||
crypto_free_cipher_env(circ->p_crypto);
|
||||
if (circ->n_digest)
|
||||
crypto_free_digest_env(circ->n_digest);
|
||||
if (circ->p_digest)
|
||||
crypto_free_digest_env(circ->p_digest);
|
||||
if (circ->build_state) {
|
||||
if (circ->build_state->chosen_exit)
|
||||
extend_info_free(circ->build_state->chosen_exit);
|
||||
if (circ->build_state->pending_final_cpath)
|
||||
circuit_free_cpath_node(circ->build_state->pending_final_cpath);
|
||||
}
|
||||
tor_free(circ->build_state);
|
||||
tor_free(circ->onionskin);
|
||||
circuit_free_cpath(circ->cpath);
|
||||
if (circ->rend_splice) {
|
||||
tor_assert(circ->rend_splice->magic == CIRCUIT_MAGIC);
|
||||
circ->rend_splice->rend_splice = NULL;
|
||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
|
||||
mem = ocirc;
|
||||
tor_assert(circ->magic == ORIGIN_CIRCUIT_MAGIC);
|
||||
if (ocirc->build_state) {
|
||||
if (ocirc->build_state->chosen_exit)
|
||||
extend_info_free(ocirc->build_state->chosen_exit);
|
||||
if (ocirc->build_state->pending_final_cpath)
|
||||
circuit_free_cpath_node(ocirc->build_state->pending_final_cpath);
|
||||
}
|
||||
tor_free(ocirc->build_state);
|
||||
|
||||
circuit_free_cpath(ocirc->cpath);
|
||||
|
||||
} else {
|
||||
or_circuit_t *ocirc = TO_OR_CIRCUIT(circ);
|
||||
mem = ocirc;
|
||||
tor_assert(circ->magic == OR_CIRCUIT_MAGIC);
|
||||
|
||||
if (ocirc->p_crypto)
|
||||
crypto_free_cipher_env(ocirc->p_crypto);
|
||||
if (ocirc->p_digest)
|
||||
crypto_free_digest_env(ocirc->p_digest);
|
||||
if (ocirc->n_crypto)
|
||||
crypto_free_cipher_env(ocirc->n_crypto);
|
||||
if (ocirc->n_digest)
|
||||
crypto_free_digest_env(ocirc->n_digest);
|
||||
|
||||
if (ocirc->rend_splice) {
|
||||
or_circuit_t *other = ocirc->rend_splice;
|
||||
tor_assert(other->_base.magic == OR_CIRCUIT_MAGIC);
|
||||
other->rend_splice = NULL;
|
||||
}
|
||||
|
||||
tor_free(circ->onionskin);
|
||||
|
||||
/* remove from map. */
|
||||
circuit_set_p_circid_orconn(ocirc, 0, NULL);
|
||||
}
|
||||
|
||||
/* Remove from map. */
|
||||
circuit_set_circid_orconn(circ, 0, NULL, P_CONN_CHANGED);
|
||||
circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED);
|
||||
circuit_set_n_circid_orconn(circ, 0, NULL);
|
||||
|
||||
memset(circ, 0xAA, sizeof(circuit_t)); /* poison memory */
|
||||
tor_free(circ);
|
||||
tor_free(mem);
|
||||
}
|
||||
|
||||
/** Deallocate space associated with the linked list <b>cpath</b>. */
|
||||
@ -321,11 +376,14 @@ circuit_free_all(void)
|
||||
circuit_t *next;
|
||||
while (global_circuitlist) {
|
||||
next = global_circuitlist->next;
|
||||
while (global_circuitlist->resolving_streams) {
|
||||
connection_t *next;
|
||||
next = global_circuitlist->resolving_streams->next_stream;
|
||||
connection_free(global_circuitlist->resolving_streams);
|
||||
global_circuitlist->resolving_streams = next;
|
||||
if (! CIRCUIT_IS_ORIGIN(global_circuitlist)) {
|
||||
or_circuit_t *or_circ = TO_OR_CIRCUIT(global_circuitlist);
|
||||
while (or_circ->resolving_streams) {
|
||||
connection_t *next;
|
||||
next = or_circ->resolving_streams->next_stream;
|
||||
connection_free(or_circ->resolving_streams);
|
||||
or_circ->resolving_streams = next;
|
||||
}
|
||||
}
|
||||
circuit_free(global_circuitlist);
|
||||
global_circuitlist = next;
|
||||
@ -358,6 +416,76 @@ circuit_free_cpath_node(crypt_path_t *victim)
|
||||
tor_free(victim);
|
||||
}
|
||||
|
||||
/** A helper function for circuit_dump_by_conn() below. Log a bunch
|
||||
* of information about circuit <b>circ</b>.
|
||||
*/
|
||||
static void
|
||||
circuit_dump_details(int severity, circuit_t *circ, int poll_index,
|
||||
const char *type, int this_circid, int other_circid)
|
||||
{
|
||||
log(severity, LD_CIRC, "Conn %d has %s circuit: circID %d (other side %d), "
|
||||
"state %d (%s), born %d:",
|
||||
poll_index, type, this_circid, other_circid, circ->state,
|
||||
circuit_state_to_string(circ->state), (int)circ->timestamp_created);
|
||||
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>conn</b>.
|
||||
*/
|
||||
void
|
||||
circuit_dump_by_conn(connection_t *conn, int severity)
|
||||
{
|
||||
circuit_t *circ;
|
||||
connection_t *tmpconn;
|
||||
|
||||
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_conn == conn)
|
||||
circuit_dump_details(severity, circ, conn->poll_index, "App-ward",
|
||||
p_circ_id, n_circ_id);
|
||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||
for (tmpconn=TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn;
|
||||
tmpconn=tmpconn->next_stream) {
|
||||
if (tmpconn == conn) {
|
||||
circuit_dump_details(severity, circ, conn->poll_index, "App-ward",
|
||||
p_circ_id, n_circ_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (circ->n_conn == conn)
|
||||
circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward",
|
||||
n_circ_id, p_circ_id);
|
||||
if (! CIRCUIT_IS_ORIGIN(circ)) {
|
||||
for (tmpconn=TO_OR_CIRCUIT(circ)->n_streams; tmpconn;
|
||||
tmpconn=tmpconn->next_stream) {
|
||||
if (tmpconn == conn) {
|
||||
circuit_dump_details(severity, circ, conn->poll_index, "Exit-ward",
|
||||
n_circ_id, p_circ_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!circ->n_conn && circ->n_addr && circ->n_port &&
|
||||
circ->n_addr == conn->addr &&
|
||||
circ->n_port == conn->port &&
|
||||
!memcmp(conn->identity_digest, circ->n_conn_id_digest, DIGEST_LEN)) {
|
||||
circuit_dump_details(severity, circ, conn->poll_index,
|
||||
(circ->state == CIRCUIT_STATE_OPEN &&
|
||||
!CIRCUIT_IS_ORIGIN(circ)) ?
|
||||
"Endpoint" : "Pending",
|
||||
n_circ_id, p_circ_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Return the circuit whose global ID is <b>id</b>, or NULL if no
|
||||
* such circuit exists. */
|
||||
circuit_t *
|
||||
@ -407,10 +535,13 @@ circuit_get_by_circid_orconn_impl(uint16_t circ_id, connection_t *conn)
|
||||
{
|
||||
circuit_t *circ;
|
||||
for (circ=global_circuitlist;circ;circ = circ->next) {
|
||||
if (circ->p_conn == conn && circ->p_circ_id == circ_id) {
|
||||
log_warn(LD_BUG,
|
||||
"circuit matches p_conn, but not in hash table (Bug!)");
|
||||
return circ;
|
||||
if (! CIRCUIT_IS_ORIGIN(circ)) {
|
||||
or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
|
||||
if (or_circ->p_conn == conn && or_circ->p_circ_id == circ_id) {
|
||||
log_warn(LD_BUG,
|
||||
"circuit matches p_conn, but not in hash table (Bug!)");
|
||||
return circ;
|
||||
}
|
||||
}
|
||||
if (circ->n_conn == conn && circ->n_circ_id == circ_id) {
|
||||
log_warn(LD_BUG,
|
||||
@ -462,7 +593,9 @@ circuit_get_by_edge_conn(connection_t *conn)
|
||||
tor_assert(CONN_IS_EDGE(conn));
|
||||
|
||||
circ = conn->on_circuit;
|
||||
tor_assert(!circ || circ->magic == CIRCUIT_MAGIC);
|
||||
tor_assert(!circ ||
|
||||
(CIRCUIT_IS_ORIGIN(circ) ? circ->magic == ORIGIN_CIRCUIT_MAGIC
|
||||
: circ->magic == OR_CIRCUIT_MAGIC));
|
||||
|
||||
return circ;
|
||||
}
|
||||
@ -476,14 +609,20 @@ circuit_unlink_all_from_or_conn(connection_t *conn, int reason)
|
||||
{
|
||||
circuit_t *circ;
|
||||
for (circ = global_circuitlist; circ; circ = circ->next) {
|
||||
if (circ->n_conn == conn || circ->p_conn == conn) {
|
||||
if (circ->n_conn == conn)
|
||||
circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED);
|
||||
if (circ->p_conn == conn)
|
||||
circuit_set_circid_orconn(circ, 0, NULL, P_CONN_CHANGED);
|
||||
if (!circ->marked_for_close)
|
||||
circuit_mark_for_close(circ, reason);
|
||||
int mark = 0;
|
||||
if (circ->n_conn == conn) {
|
||||
circuit_set_n_circid_orconn(circ, 0, NULL);
|
||||
mark = 1;
|
||||
}
|
||||
if (! CIRCUIT_IS_ORIGIN(circ)) {
|
||||
or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
|
||||
if (or_circ->p_conn == conn) {
|
||||
circuit_set_p_circid_orconn(or_circ, 0, NULL);
|
||||
mark = 1;
|
||||
}
|
||||
}
|
||||
if (mark && !circ->marked_for_close)
|
||||
circuit_mark_for_close(circ, reason);
|
||||
}
|
||||
}
|
||||
|
||||
@ -536,7 +675,7 @@ circuit_get_next_by_pk_and_purpose(circuit_t *start,
|
||||
/** Return the circuit waiting for a rendezvous with the provided cookie.
|
||||
* Return NULL if no such circuit is found.
|
||||
*/
|
||||
circuit_t *
|
||||
or_circuit_t *
|
||||
circuit_get_rendezvous(const char *cookie)
|
||||
{
|
||||
circuit_t *circ;
|
||||
@ -544,7 +683,7 @@ circuit_get_rendezvous(const char *cookie)
|
||||
if (! circ->marked_for_close &&
|
||||
circ->purpose == CIRCUIT_PURPOSE_REND_POINT_WAITING &&
|
||||
! memcmp(circ->rend_cookie, cookie, REND_COOKIE_LEN) )
|
||||
return circ;
|
||||
return TO_OR_CIRCUIT(circ);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@ -559,41 +698,43 @@ circuit_get_rendezvous(const char *cookie)
|
||||
*
|
||||
* Only return internal circuits if that is requested.
|
||||
*/
|
||||
circuit_t *
|
||||
origin_circuit_t *
|
||||
circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
|
||||
int need_uptime,
|
||||
int need_capacity, int internal)
|
||||
{
|
||||
circuit_t *circ;
|
||||
circuit_t *best=NULL;
|
||||
circuit_t *_circ;
|
||||
origin_circuit_t *best=NULL;
|
||||
|
||||
log_debug(LD_CIRC,
|
||||
"Hunting for a circ to cannibalize: purpose %d, uptime %d, "
|
||||
"capacity %d, internal %d",
|
||||
purpose, need_uptime, need_capacity, internal);
|
||||
|
||||
for (circ=global_circuitlist; circ; circ = circ->next) {
|
||||
if (CIRCUIT_IS_ORIGIN(circ) &&
|
||||
circ->state == CIRCUIT_STATE_OPEN &&
|
||||
!circ->marked_for_close &&
|
||||
circ->purpose == purpose &&
|
||||
!circ->timestamp_dirty &&
|
||||
(!need_uptime || circ->build_state->need_uptime) &&
|
||||
(!need_capacity || circ->build_state->need_capacity) &&
|
||||
(internal == circ->build_state->is_internal)) {
|
||||
if (info) {
|
||||
/* need to make sure we don't duplicate hops */
|
||||
crypt_path_t *hop = circ->cpath;
|
||||
do {
|
||||
if (!memcmp(hop->extend_info->identity_digest,
|
||||
info->identity_digest, DIGEST_LEN))
|
||||
goto next;
|
||||
hop=hop->next;
|
||||
} while (hop!=circ->cpath);
|
||||
}
|
||||
if (!best || (best->build_state->need_uptime && !need_uptime))
|
||||
best = circ;
|
||||
for (_circ=global_circuitlist; _circ; _circ = _circ->next) {
|
||||
if (CIRCUIT_IS_ORIGIN(_circ) &&
|
||||
_circ->state == CIRCUIT_STATE_OPEN &&
|
||||
!_circ->marked_for_close &&
|
||||
_circ->purpose == purpose &&
|
||||
!_circ->timestamp_dirty) {
|
||||
origin_circuit_t *circ = TO_ORIGIN_CIRCUIT(_circ);
|
||||
if ((!need_uptime || circ->build_state->need_uptime) &&
|
||||
(!need_capacity || circ->build_state->need_capacity) &&
|
||||
(internal == circ->build_state->is_internal)) {
|
||||
if (info) {
|
||||
/* need to make sure we don't duplicate hops */
|
||||
crypt_path_t *hop = circ->cpath;
|
||||
do {
|
||||
if (!memcmp(hop->extend_info->identity_digest,
|
||||
info->identity_digest, DIGEST_LEN))
|
||||
goto next;
|
||||
hop=hop->next;
|
||||
} while (hop!=circ->cpath);
|
||||
}
|
||||
if (!best || (best->build_state->need_uptime && !need_uptime))
|
||||
best = circ;
|
||||
next: ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return best;
|
||||
@ -685,7 +826,7 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
|
||||
}
|
||||
|
||||
if (circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) {
|
||||
onion_pending_remove(circ);
|
||||
onion_pending_remove(TO_OR_CIRCUIT(circ));
|
||||
}
|
||||
/* If the circuit ever became OPEN, we sent it to the reputation history
|
||||
* module then. If it isn't OPEN, we send it there now to remember which
|
||||
@ -693,60 +834,72 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
|
||||
*/
|
||||
if (circ->state != CIRCUIT_STATE_OPEN) {
|
||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||
circuit_build_failed(circ); /* take actions if necessary */
|
||||
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
|
||||
circuit_build_failed(ocirc); /* take actions if necessary */
|
||||
circuit_rep_hist_note_result(ocirc);
|
||||
}
|
||||
circuit_rep_hist_note_result(circ);
|
||||
}
|
||||
if (circ->state == CIRCUIT_STATE_OR_WAIT) {
|
||||
if (circuits_pending_or_conns)
|
||||
smartlist_remove(circuits_pending_or_conns, circ);
|
||||
}
|
||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||
control_event_circuit_status(circ,
|
||||
control_event_circuit_status(TO_ORIGIN_CIRCUIT(circ),
|
||||
(circ->state == CIRCUIT_STATE_OPEN)?CIRC_EVENT_CLOSED:CIRC_EVENT_FAILED);
|
||||
}
|
||||
if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
|
||||
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
|
||||
tor_assert(circ->state == CIRCUIT_STATE_OPEN);
|
||||
tor_assert(circ->build_state->chosen_exit);
|
||||
tor_assert(ocirc->build_state->chosen_exit);
|
||||
/* treat this like getting a nack from it */
|
||||
log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). "
|
||||
"Removing from descriptor.",
|
||||
safe_str(circ->rend_query),
|
||||
safe_str(build_state_get_exit_nickname(circ->build_state)));
|
||||
rend_client_remove_intro_point(circ->build_state->chosen_exit,
|
||||
safe_str(build_state_get_exit_nickname(ocirc->build_state)));
|
||||
rend_client_remove_intro_point(ocirc->build_state->chosen_exit,
|
||||
circ->rend_query);
|
||||
}
|
||||
|
||||
if (circ->n_conn)
|
||||
connection_or_send_destroy(circ->n_circ_id, circ->n_conn, reason);
|
||||
for (conn=circ->n_streams; conn; conn=conn->next_stream)
|
||||
connection_edge_destroy(circ->n_circ_id, conn);
|
||||
while (circ->resolving_streams) {
|
||||
conn = circ->resolving_streams;
|
||||
circ->resolving_streams = conn->next_stream;
|
||||
if (!conn->marked_for_close) {
|
||||
/* The other side will see a DESTROY, and infer that the connections
|
||||
* are closing because the circuit is getting torn down. No need
|
||||
* to send an end cell. */
|
||||
conn->has_sent_end = 1;
|
||||
connection_mark_for_close(conn);
|
||||
|
||||
if (! CIRCUIT_IS_ORIGIN(circ)) {
|
||||
or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
|
||||
for (conn=or_circ->n_streams; conn; conn=conn->next_stream)
|
||||
connection_edge_destroy(or_circ->p_circ_id, conn);
|
||||
|
||||
while (or_circ->resolving_streams) {
|
||||
conn = or_circ->resolving_streams;
|
||||
or_circ->resolving_streams = conn->next_stream;
|
||||
if (!conn->marked_for_close) {
|
||||
/* The other side will see a DESTROY, and infer that the connections
|
||||
* are closing because the circuit is getting torn down. No need
|
||||
* to send an end cell. */
|
||||
conn->has_sent_end = 1;
|
||||
connection_mark_for_close(conn);
|
||||
}
|
||||
conn->on_circuit = NULL;
|
||||
}
|
||||
conn->on_circuit = NULL;
|
||||
|
||||
if (or_circ->p_conn)
|
||||
connection_or_send_destroy(or_circ->p_circ_id, or_circ->p_conn, reason);
|
||||
} else {
|
||||
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
|
||||
for (conn=ocirc->p_streams; conn; conn=conn->next_stream)
|
||||
connection_edge_destroy(circ->n_circ_id, conn);
|
||||
}
|
||||
if (circ->p_conn)
|
||||
connection_or_send_destroy(circ->p_circ_id, circ->p_conn, reason);
|
||||
for (conn=circ->p_streams; conn; conn=conn->next_stream)
|
||||
connection_edge_destroy(circ->p_circ_id, conn);
|
||||
|
||||
circ->marked_for_close = line;
|
||||
circ->marked_for_close_file = file;
|
||||
|
||||
if (circ->rend_splice) {
|
||||
if (!circ->rend_splice->marked_for_close) {
|
||||
/* do this after marking this circuit, to avoid infinite recursion. */
|
||||
circuit_mark_for_close(circ->rend_splice, reason);
|
||||
if (! CIRCUIT_IS_ORIGIN(circ)) {
|
||||
or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
|
||||
if (or_circ->rend_splice) {
|
||||
if (!or_circ->rend_splice->_base.marked_for_close) {
|
||||
/* do this after marking this circuit, to avoid infinite recursion. */
|
||||
circuit_mark_for_close(TO_CIRCUIT(or_circ->rend_splice), reason);
|
||||
}
|
||||
or_circ->rend_splice = NULL;
|
||||
}
|
||||
circ->rend_splice = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -810,12 +963,19 @@ void
|
||||
assert_circuit_ok(const circuit_t *c)
|
||||
{
|
||||
connection_t *conn;
|
||||
const or_circuit_t *or_circ = NULL;
|
||||
const origin_circuit_t *origin_circ = NULL;
|
||||
|
||||
tor_assert(c);
|
||||
tor_assert(c->magic == CIRCUIT_MAGIC);
|
||||
tor_assert(c->magic == ORIGIN_CIRCUIT_MAGIC || c->magic == OR_CIRCUIT_MAGIC);
|
||||
tor_assert(c->purpose >= _CIRCUIT_PURPOSE_MIN &&
|
||||
c->purpose <= _CIRCUIT_PURPOSE_MAX);
|
||||
|
||||
if (CIRCUIT_IS_ORIGIN(c))
|
||||
origin_circ = TO_ORIGIN_CIRCUIT((circuit_t*)c);
|
||||
else
|
||||
or_circ = TO_OR_CIRCUIT((circuit_t*)c);
|
||||
|
||||
if (c->n_conn) {
|
||||
tor_assert(c->n_conn->type == CONN_TYPE_OR);
|
||||
tor_assert(!memcmp(c->n_conn->identity_digest, c->n_conn_id_digest,
|
||||
@ -823,32 +983,28 @@ assert_circuit_ok(const circuit_t *c)
|
||||
if (c->n_circ_id)
|
||||
tor_assert(c == circuit_get_by_circid_orconn(c->n_circ_id, c->n_conn));
|
||||
}
|
||||
if (c->p_conn) {
|
||||
tor_assert(c->p_conn->type == CONN_TYPE_OR);
|
||||
if (c->p_circ_id)
|
||||
tor_assert(c == circuit_get_by_circid_orconn(c->p_circ_id, c->p_conn));
|
||||
if (or_circ && or_circ->p_conn) {
|
||||
tor_assert(or_circ->p_conn->type == CONN_TYPE_OR);
|
||||
if (or_circ->p_circ_id)
|
||||
tor_assert(c == circuit_get_by_circid_orconn(or_circ->p_circ_id,
|
||||
or_circ->p_conn));
|
||||
}
|
||||
for (conn = c->p_streams; conn; conn = conn->next_stream)
|
||||
tor_assert(conn->type == CONN_TYPE_AP);
|
||||
for (conn = c->n_streams; conn; conn = conn->next_stream)
|
||||
tor_assert(conn->type == CONN_TYPE_EXIT);
|
||||
if (origin_circ)
|
||||
for (conn = origin_circ->p_streams; conn; conn = conn->next_stream)
|
||||
tor_assert(conn->type == CONN_TYPE_AP);
|
||||
if (or_circ)
|
||||
for (conn = or_circ->n_streams; conn; conn = conn->next_stream)
|
||||
tor_assert(conn->type == CONN_TYPE_EXIT);
|
||||
|
||||
tor_assert(c->deliver_window >= 0);
|
||||
tor_assert(c->package_window >= 0);
|
||||
if (c->state == CIRCUIT_STATE_OPEN) {
|
||||
tor_assert(!c->onionskin);
|
||||
if (c->cpath) {
|
||||
tor_assert(CIRCUIT_IS_ORIGIN(c));
|
||||
tor_assert(!c->n_crypto);
|
||||
tor_assert(!c->p_crypto);
|
||||
tor_assert(!c->n_digest);
|
||||
tor_assert(!c->p_digest);
|
||||
} else {
|
||||
tor_assert(!CIRCUIT_IS_ORIGIN(c));
|
||||
tor_assert(c->n_crypto);
|
||||
tor_assert(c->p_crypto);
|
||||
tor_assert(c->n_digest);
|
||||
tor_assert(c->p_digest);
|
||||
if (or_circ) {
|
||||
tor_assert(or_circ->n_crypto);
|
||||
tor_assert(or_circ->p_crypto);
|
||||
tor_assert(or_circ->n_digest);
|
||||
tor_assert(or_circ->p_digest);
|
||||
}
|
||||
}
|
||||
if (c->state == CIRCUIT_STATE_OR_WAIT && !c->marked_for_close) {
|
||||
@ -858,17 +1014,18 @@ assert_circuit_ok(const circuit_t *c)
|
||||
tor_assert(!circuits_pending_or_conns ||
|
||||
!smartlist_isin(circuits_pending_or_conns, c));
|
||||
}
|
||||
if (c->cpath) {
|
||||
assert_cpath_ok(c->cpath);
|
||||
if (origin_circ->cpath) {
|
||||
assert_cpath_ok(origin_circ->cpath);
|
||||
}
|
||||
if (c->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED) {
|
||||
tor_assert(or_circ);
|
||||
if (!c->marked_for_close) {
|
||||
tor_assert(c->rend_splice);
|
||||
tor_assert(c->rend_splice->rend_splice == c);
|
||||
tor_assert(or_circ->rend_splice);
|
||||
tor_assert(or_circ->rend_splice->rend_splice == or_circ);
|
||||
}
|
||||
tor_assert(c->rend_splice != c);
|
||||
tor_assert(or_circ->rend_splice != or_circ);
|
||||
} else {
|
||||
tor_assert(!c->rend_splice);
|
||||
tor_assert(!or_circ || !or_circ->rend_splice);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ circuit_is_acceptable(circuit_t *circ, connection_t *conn,
|
||||
time_t now)
|
||||
{
|
||||
routerinfo_t *exitrouter;
|
||||
cpath_build_state_t *build_state;
|
||||
tor_assert(circ);
|
||||
tor_assert(conn);
|
||||
tor_assert(conn->socks_request);
|
||||
@ -71,11 +72,12 @@ circuit_is_acceptable(circuit_t *circ, connection_t *conn,
|
||||
* circuit, it's the magical extra bob hop. so just check the nickname
|
||||
* of the one we meant to finish at.
|
||||
*/
|
||||
exitrouter = build_state_get_exit_router(circ->build_state);
|
||||
build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
|
||||
exitrouter = build_state_get_exit_router(build_state);
|
||||
|
||||
if (need_uptime && !circ->build_state->need_uptime)
|
||||
if (need_uptime && !build_state->need_uptime)
|
||||
return 0;
|
||||
if (need_internal != circ->build_state->is_internal)
|
||||
if (need_internal != build_state->is_internal)
|
||||
return 0;
|
||||
|
||||
if (purpose == CIRCUIT_PURPOSE_C_GENERAL) {
|
||||
@ -114,9 +116,11 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
|
||||
return 1;
|
||||
} else {
|
||||
if (a->timestamp_dirty ||
|
||||
b->build_state->is_internal ||
|
||||
a->timestamp_created > b->timestamp_created)
|
||||
return 1;
|
||||
if (CIRCUIT_IS_ORIGIN(b) &&
|
||||
TO_ORIGIN_CIRCUIT(b)->build_state->is_internal)
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT:
|
||||
@ -149,7 +153,7 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
|
||||
* If it's INTRODUCE_ACK_WAIT and must_be_open==0, then return the
|
||||
* closest introduce-purposed circuit that you can find.
|
||||
*/
|
||||
static circuit_t *
|
||||
static origin_circuit_t *
|
||||
circuit_get_best(connection_t *conn, int must_be_open, uint8_t purpose,
|
||||
int need_uptime, int need_internal)
|
||||
{
|
||||
@ -163,6 +167,8 @@ circuit_get_best(connection_t *conn, int must_be_open, uint8_t purpose,
|
||||
purpose == CIRCUIT_PURPOSE_C_REND_JOINED);
|
||||
|
||||
for (circ=global_circuitlist;circ;circ = circ->next) {
|
||||
if (!CIRCUIT_IS_ORIGIN(circ))
|
||||
continue;
|
||||
if (!circuit_is_acceptable(circ,conn,must_be_open,purpose,
|
||||
need_uptime,need_internal,now))
|
||||
continue;
|
||||
@ -174,7 +180,7 @@ circuit_get_best(connection_t *conn, int must_be_open, uint8_t purpose,
|
||||
best = circ;
|
||||
}
|
||||
|
||||
return best;
|
||||
return best ? TO_ORIGIN_CIRCUIT(best) : NULL;
|
||||
}
|
||||
|
||||
/** Close all circuits that start at us, aren't open, and were born
|
||||
@ -255,7 +261,7 @@ circuit_expire_building(time_t now)
|
||||
victim->n_circ_id, victim->state,
|
||||
circuit_state_to_string(victim->state), victim->purpose);
|
||||
|
||||
circuit_log_path(LOG_INFO,LD_CIRC,victim);
|
||||
circuit_log_path(LOG_INFO,LD_CIRC,TO_ORIGIN_CIRCUIT(victim));
|
||||
circuit_mark_for_close(victim, END_CIRC_AT_ORIGIN);
|
||||
}
|
||||
}
|
||||
@ -301,12 +307,14 @@ circuit_stream_is_being_handled(connection_t *conn, uint16_t port, int min)
|
||||
if (CIRCUIT_IS_ORIGIN(circ) &&
|
||||
!circ->marked_for_close &&
|
||||
circ->purpose == CIRCUIT_PURPOSE_C_GENERAL &&
|
||||
!circ->build_state->is_internal &&
|
||||
(!circ->timestamp_dirty ||
|
||||
circ->timestamp_dirty + get_options()->MaxCircuitDirtiness > now)) {
|
||||
exitrouter = build_state_get_exit_router(circ->build_state);
|
||||
if (exitrouter &&
|
||||
(!need_uptime || circ->build_state->need_uptime)) {
|
||||
cpath_build_state_t *build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
|
||||
if (build_state->is_internal)
|
||||
continue;
|
||||
|
||||
exitrouter = build_state_get_exit_router(build_state);
|
||||
if (exitrouter && (!need_uptime || build_state->need_uptime)) {
|
||||
int ok;
|
||||
if (conn) {
|
||||
ok = connection_ap_can_use_exit(conn, exitrouter);
|
||||
@ -343,6 +351,7 @@ circuit_predict_and_launch_new(void)
|
||||
|
||||
/* First, count how many of each type of circuit we have already. */
|
||||
for (circ=global_circuitlist;circ;circ = circ->next) {
|
||||
cpath_build_state_t *build_state;
|
||||
if (!CIRCUIT_IS_ORIGIN(circ))
|
||||
continue;
|
||||
if (circ->marked_for_close)
|
||||
@ -352,9 +361,10 @@ circuit_predict_and_launch_new(void)
|
||||
if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL)
|
||||
continue; /* only pay attention to general-purpose circs */
|
||||
num++;
|
||||
if (circ->build_state->is_internal)
|
||||
build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
|
||||
if (build_state->is_internal)
|
||||
num_internal++;
|
||||
if (circ->build_state->need_uptime && circ->build_state->is_internal)
|
||||
if (build_state->need_uptime && build_state->is_internal)
|
||||
num_uptime_internal++;
|
||||
}
|
||||
|
||||
@ -455,44 +465,49 @@ circuit_detach_stream(circuit_t *circ, connection_t *conn)
|
||||
conn->cpath_layer = NULL; /* make sure we don't keep a stale pointer */
|
||||
conn->on_circuit = NULL;
|
||||
|
||||
if (conn == circ->p_streams) {
|
||||
circ->p_streams = conn->next_stream;
|
||||
return;
|
||||
}
|
||||
if (conn == circ->n_streams) {
|
||||
circ->n_streams = conn->next_stream;
|
||||
return;
|
||||
}
|
||||
if (conn == circ->resolving_streams) {
|
||||
circ->resolving_streams = conn->next_stream;
|
||||
return;
|
||||
}
|
||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||
origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
|
||||
if (conn == origin_circ->p_streams) {
|
||||
origin_circ->p_streams = conn->next_stream;
|
||||
return;
|
||||
}
|
||||
|
||||
for (prevconn = circ->p_streams;
|
||||
prevconn && prevconn->next_stream && prevconn->next_stream != conn;
|
||||
prevconn = prevconn->next_stream)
|
||||
;
|
||||
if (prevconn && prevconn->next_stream) {
|
||||
prevconn->next_stream = conn->next_stream;
|
||||
return;
|
||||
}
|
||||
for (prevconn = origin_circ->p_streams;
|
||||
prevconn && prevconn->next_stream && prevconn->next_stream != conn;
|
||||
prevconn = prevconn->next_stream)
|
||||
;
|
||||
if (prevconn && prevconn->next_stream) {
|
||||
prevconn->next_stream = conn->next_stream;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
|
||||
if (conn == or_circ->n_streams) {
|
||||
or_circ->n_streams = conn->next_stream;
|
||||
return;
|
||||
}
|
||||
if (conn == or_circ->resolving_streams) {
|
||||
or_circ->resolving_streams = conn->next_stream;
|
||||
return;
|
||||
}
|
||||
|
||||
for (prevconn = circ->n_streams;
|
||||
prevconn && prevconn->next_stream && prevconn->next_stream != conn;
|
||||
prevconn = prevconn->next_stream)
|
||||
;
|
||||
if (prevconn && prevconn->next_stream) {
|
||||
prevconn->next_stream = conn->next_stream;
|
||||
return;
|
||||
}
|
||||
for (prevconn = or_circ->n_streams;
|
||||
prevconn && prevconn->next_stream && prevconn->next_stream != conn;
|
||||
prevconn = prevconn->next_stream)
|
||||
;
|
||||
if (prevconn && prevconn->next_stream) {
|
||||
prevconn->next_stream = conn->next_stream;
|
||||
return;
|
||||
}
|
||||
|
||||
for (prevconn = circ->resolving_streams;
|
||||
prevconn && prevconn->next_stream && prevconn->next_stream != conn;
|
||||
prevconn = prevconn->next_stream)
|
||||
;
|
||||
if (prevconn && prevconn->next_stream) {
|
||||
prevconn->next_stream = conn->next_stream;
|
||||
return;
|
||||
for (prevconn = or_circ->resolving_streams;
|
||||
prevconn && prevconn->next_stream && prevconn->next_stream != conn;
|
||||
prevconn = prevconn->next_stream)
|
||||
;
|
||||
if (prevconn && prevconn->next_stream) {
|
||||
prevconn->next_stream = conn->next_stream;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
log_err(LD_BUG,"edge conn not in circuit's list?");
|
||||
@ -543,7 +558,7 @@ circuit_about_to_close_connection(connection_t *conn)
|
||||
}
|
||||
|
||||
/** Find each circuit that has been unused for too long, or dirty
|
||||
* for too long and has no streams on it: mark it for close.
|
||||
* for too long and has no streax=ms on it: mark it for close.
|
||||
*/
|
||||
static void
|
||||
circuit_expire_old_circuits(time_t now)
|
||||
@ -552,23 +567,21 @@ circuit_expire_old_circuits(time_t now)
|
||||
time_t cutoff = now - get_options()->CircuitIdleTimeout;
|
||||
|
||||
for (circ = global_circuitlist; circ; circ = circ->next) {
|
||||
if (circ->marked_for_close)
|
||||
if (circ->marked_for_close || ! CIRCUIT_IS_ORIGIN(circ))
|
||||
continue;
|
||||
/* If the circuit has been dirty for too long, and there are no streams
|
||||
* on it, mark it for close.
|
||||
*/
|
||||
if (circ->timestamp_dirty &&
|
||||
circ->timestamp_dirty + get_options()->MaxCircuitDirtiness < now &&
|
||||
CIRCUIT_IS_ORIGIN(circ) &&
|
||||
!circ->p_streams /* nothing attached */ ) {
|
||||
!TO_ORIGIN_CIRCUIT(circ)->p_streams /* nothing attached */ ) {
|
||||
log_debug(LD_CIRC, "Closing n_circ_id %d (dirty %d secs ago, purp %d)",
|
||||
circ->n_circ_id, (int)(now - circ->timestamp_dirty),
|
||||
circ->purpose);
|
||||
/* (only general and purpose_c circs can get dirty) */
|
||||
tor_assert(!circ->n_streams);
|
||||
tor_assert(circ->purpose <= CIRCUIT_PURPOSE_C_REND_JOINED);
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
} else if (!circ->timestamp_dirty && CIRCUIT_IS_ORIGIN(circ) &&
|
||||
} else if (!circ->timestamp_dirty &&
|
||||
circ->state == CIRCUIT_STATE_OPEN &&
|
||||
circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) {
|
||||
if (circ->timestamp_created < cutoff) {
|
||||
@ -583,17 +596,17 @@ circuit_expire_old_circuits(time_t now)
|
||||
|
||||
/** A testing circuit has completed. Take whatever stats we want. */
|
||||
static void
|
||||
circuit_testing_opened(circuit_t *circ)
|
||||
circuit_testing_opened(origin_circuit_t *circ)
|
||||
{
|
||||
/* For now, we only use testing circuits to see if our ORPort is
|
||||
reachable. But we remember reachability in onionskin_answer(),
|
||||
so there's no need to record anything here. Just close the circ. */
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
|
||||
}
|
||||
|
||||
/** A testing circuit has failed to build. Take whatever stats we want. */
|
||||
static void
|
||||
circuit_testing_failed(circuit_t *circ, int at_last_hop)
|
||||
circuit_testing_failed(origin_circuit_t *circ, int at_last_hop)
|
||||
{
|
||||
if (server_mode(get_options()) && check_whether_orport_reachable())
|
||||
return;
|
||||
@ -614,11 +627,11 @@ circuit_testing_failed(circuit_t *circ, int at_last_hop)
|
||||
* that could use circ.
|
||||
*/
|
||||
void
|
||||
circuit_has_opened(circuit_t *circ)
|
||||
circuit_has_opened(origin_circuit_t *circ)
|
||||
{
|
||||
control_event_circuit_status(circ, CIRC_EVENT_BUILT);
|
||||
|
||||
switch (circ->purpose) {
|
||||
switch (TO_CIRCUIT(circ)->purpose) {
|
||||
case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
|
||||
rend_client_rendcirc_has_opened(circ);
|
||||
connection_ap_attach_pending();
|
||||
@ -643,7 +656,7 @@ circuit_has_opened(circuit_t *circ)
|
||||
circuit_testing_opened(circ);
|
||||
break;
|
||||
default:
|
||||
log_err(LD_BUG,"unhandled purpose %d",circ->purpose);
|
||||
log_err(LD_BUG,"unhandled purpose %d",circ->_base.purpose);
|
||||
tor_assert(0);
|
||||
}
|
||||
}
|
||||
@ -651,7 +664,7 @@ circuit_has_opened(circuit_t *circ)
|
||||
/** Called whenever a circuit could not be successfully built.
|
||||
*/
|
||||
void
|
||||
circuit_build_failed(circuit_t *circ)
|
||||
circuit_build_failed(origin_circuit_t *circ)
|
||||
{
|
||||
/* we should examine circ and see if it failed because of
|
||||
* the last hop or an earlier hop. then use this info below.
|
||||
@ -669,11 +682,12 @@ circuit_build_failed(circuit_t *circ)
|
||||
/* We failed at the first hop. If there's an OR connection
|
||||
to blame, blame it. */
|
||||
connection_t *n_conn = NULL;
|
||||
if (circ->n_conn) {
|
||||
n_conn = circ->n_conn;
|
||||
} else if (circ->state == CIRCUIT_STATE_OR_WAIT) {
|
||||
if (circ->_base.n_conn) {
|
||||
n_conn = circ->_base.n_conn;
|
||||
} else if (circ->_base.state == CIRCUIT_STATE_OR_WAIT) {
|
||||
/* we have to hunt for it */
|
||||
n_conn = connection_or_get_by_identity_digest(circ->n_conn_id_digest);
|
||||
n_conn = connection_or_get_by_identity_digest(
|
||||
circ->_base.n_conn_id_digest);
|
||||
}
|
||||
if (n_conn) {
|
||||
log_info(LD_OR,
|
||||
@ -685,7 +699,7 @@ circuit_build_failed(circuit_t *circ)
|
||||
}
|
||||
}
|
||||
|
||||
switch (circ->purpose) {
|
||||
switch (circ->_base.purpose) {
|
||||
case CIRCUIT_PURPOSE_C_GENERAL:
|
||||
/* If we never built the circuit, note it as a failure. */
|
||||
circuit_increment_failure_count();
|
||||
@ -695,7 +709,7 @@ circuit_build_failed(circuit_t *circ)
|
||||
break;
|
||||
case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
|
||||
/* at Bob, waiting for introductions */
|
||||
if (circ->state != CIRCUIT_STATE_OPEN) {
|
||||
if (circ->_base.state != CIRCUIT_STATE_OPEN) {
|
||||
circuit_increment_failure_count();
|
||||
}
|
||||
/* no need to care here, because bob will rebuild intro
|
||||
@ -744,11 +758,11 @@ static int did_circs_fail_last_period = 0;
|
||||
|
||||
/** Launch a new circuit; see circuit_launch_by_extend_info() for
|
||||
* details on arguments. */
|
||||
circuit_t *
|
||||
origin_circuit_t *
|
||||
circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
|
||||
int need_uptime, int need_capacity, int internal)
|
||||
{
|
||||
circuit_t *circ;
|
||||
origin_circuit_t *circ;
|
||||
extend_info_t *info = NULL;
|
||||
if (exit)
|
||||
info = extend_info_from_router(exit);
|
||||
@ -765,11 +779,11 @@ circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
|
||||
* choose among routers with high bandwidth. If <b>internal</b> is true, the
|
||||
* last hop need not be an exit node. Return the newly allocated circuit on
|
||||
* success, or NULL on failure. */
|
||||
circuit_t *
|
||||
origin_circuit_t *
|
||||
circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *extend_info,
|
||||
int need_uptime, int need_capacity, int internal)
|
||||
{
|
||||
circuit_t *circ;
|
||||
origin_circuit_t *circ;
|
||||
|
||||
if (!router_have_minimum_dir_info()) {
|
||||
log_debug(LD_CIRC,"Haven't fetched enough directory info yet; canceling "
|
||||
@ -785,11 +799,11 @@ circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *extend_info,
|
||||
if (circ) {
|
||||
log_info(LD_CIRC,"Cannibalizing circ '%s' for purpose %d",
|
||||
build_state_get_exit_nickname(circ->build_state), purpose);
|
||||
circ->purpose = purpose;
|
||||
circ->_base.purpose = purpose;
|
||||
/* reset the birth date of this circ, else expire_building
|
||||
* will see it and think it's been trying to build since it
|
||||
* began. */
|
||||
circ->timestamp_created = time(NULL);
|
||||
circ->_base.timestamp_created = time(NULL);
|
||||
switch (purpose) {
|
||||
case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
|
||||
case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
|
||||
@ -829,7 +843,7 @@ circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *extend_info,
|
||||
|
||||
/** Launch a new circuit; see circuit_launch_by_extend_info() for
|
||||
* details on arguments. */
|
||||
circuit_t *
|
||||
origin_circuit_t *
|
||||
circuit_launch_by_nickname(uint8_t purpose, const char *exit_nickname,
|
||||
int need_uptime, int need_capacity, int internal)
|
||||
{
|
||||
@ -879,9 +893,9 @@ circuit_reset_failure_count(int timeout)
|
||||
static int
|
||||
circuit_get_open_circ_or_launch(connection_t *conn,
|
||||
uint8_t desired_circuit_purpose,
|
||||
circuit_t **circp)
|
||||
origin_circuit_t **circp)
|
||||
{
|
||||
circuit_t *circ;
|
||||
origin_circuit_t *circ;
|
||||
int is_resolve;
|
||||
int need_uptime, need_internal;
|
||||
|
||||
@ -996,9 +1010,10 @@ circuit_get_open_circ_or_launch(connection_t *conn,
|
||||
rep_hist_note_used_internal(time(NULL), need_uptime, 1);
|
||||
if (circ) {
|
||||
/* write the service_id into circ */
|
||||
strlcpy(circ->rend_query, conn->rend_query, sizeof(circ->rend_query));
|
||||
if (circ->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
|
||||
circ->state == CIRCUIT_STATE_OPEN)
|
||||
strlcpy(circ->_base.rend_query, conn->rend_query,
|
||||
sizeof(circ->_base.rend_query));
|
||||
if (circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
|
||||
circ->_base.state == CIRCUIT_STATE_OPEN)
|
||||
rend_client_rendcirc_has_opened(circ);
|
||||
}
|
||||
}
|
||||
@ -1017,19 +1032,18 @@ circuit_get_open_circ_or_launch(connection_t *conn,
|
||||
* circ's cpath.
|
||||
*/
|
||||
static void
|
||||
link_apconn_to_circ(connection_t *apconn, circuit_t *circ)
|
||||
link_apconn_to_circ(connection_t *apconn, origin_circuit_t *circ)
|
||||
{
|
||||
/* add it into the linked list of streams on this circuit */
|
||||
log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %d.",
|
||||
circ->n_circ_id);
|
||||
circ->_base.n_circ_id);
|
||||
/* reset it, so we can measure circ timeouts */
|
||||
apconn->timestamp_lastread = time(NULL);
|
||||
apconn->next_stream = circ->p_streams;
|
||||
apconn->on_circuit = circ;
|
||||
apconn->on_circuit = TO_CIRCUIT(circ);
|
||||
/* assert_connection_ok(conn, time(NULL)); */
|
||||
circ->p_streams = apconn;
|
||||
|
||||
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
||||
tor_assert(circ->cpath);
|
||||
tor_assert(circ->cpath->prev);
|
||||
tor_assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
|
||||
@ -1039,7 +1053,7 @@ link_apconn_to_circ(connection_t *apconn, circuit_t *circ)
|
||||
/** If an exit wasn't specifically chosen, save the history for future
|
||||
* use. */
|
||||
static void
|
||||
consider_recording_trackhost(connection_t *conn, circuit_t *circ)
|
||||
consider_recording_trackhost(connection_t *conn, origin_circuit_t *circ)
|
||||
{
|
||||
int found_needle = 0;
|
||||
char *str;
|
||||
@ -1094,7 +1108,7 @@ consider_recording_trackhost(connection_t *conn, circuit_t *circ)
|
||||
* for connection_ap_handshake_attach_circuit. */
|
||||
int
|
||||
connection_ap_handshake_attach_chosen_circuit(connection_t *conn,
|
||||
circuit_t *circ)
|
||||
origin_circuit_t *circ)
|
||||
{
|
||||
tor_assert(conn);
|
||||
tor_assert(conn->type == CONN_TYPE_AP);
|
||||
@ -1102,12 +1116,12 @@ connection_ap_handshake_attach_chosen_circuit(connection_t *conn,
|
||||
conn->state == AP_CONN_STATE_CONTROLLER_WAIT);
|
||||
tor_assert(conn->socks_request);
|
||||
tor_assert(circ);
|
||||
tor_assert(circ->state == CIRCUIT_STATE_OPEN);
|
||||
tor_assert(circ->_base.state == CIRCUIT_STATE_OPEN);
|
||||
|
||||
conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
|
||||
|
||||
if (!circ->timestamp_dirty)
|
||||
circ->timestamp_dirty = time(NULL);
|
||||
if (!circ->_base.timestamp_dirty)
|
||||
circ->_base.timestamp_dirty = time(NULL);
|
||||
|
||||
link_apconn_to_circ(conn, circ);
|
||||
tor_assert(conn->socks_request);
|
||||
@ -1153,7 +1167,7 @@ connection_ap_handshake_attach_circuit(connection_t *conn)
|
||||
}
|
||||
|
||||
if (!connection_edge_is_rendezvous_stream(conn)) { /* we're a general conn */
|
||||
circuit_t *circ=NULL;
|
||||
origin_circuit_t *circ=NULL;
|
||||
|
||||
if (conn->chosen_exit_name) {
|
||||
routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1);
|
||||
@ -1190,7 +1204,7 @@ connection_ap_handshake_attach_circuit(connection_t *conn)
|
||||
|
||||
log_debug(LD_APP|LD_CIRC,
|
||||
"Attaching apconn to circ %d (stream %d sec old).",
|
||||
circ->n_circ_id, conn_age);
|
||||
circ->_base.n_circ_id, conn_age);
|
||||
/* here, print the circ's path. so people can figure out which circs are
|
||||
* sucking. */
|
||||
circuit_log_path(LOG_INFO,LD_APP|LD_CIRC,circ);
|
||||
@ -1199,7 +1213,7 @@ connection_ap_handshake_attach_circuit(connection_t *conn)
|
||||
return connection_ap_handshake_attach_chosen_circuit(conn, circ);
|
||||
|
||||
} else { /* we're a rendezvous conn */
|
||||
circuit_t *rendcirc=NULL, *introcirc=NULL;
|
||||
origin_circuit_t *rendcirc=NULL, *introcirc=NULL;
|
||||
|
||||
tor_assert(!conn->cpath_layer);
|
||||
|
||||
@ -1215,25 +1229,25 @@ connection_ap_handshake_attach_circuit(connection_t *conn)
|
||||
log_info(LD_REND,
|
||||
"rend joined circ %d already here. attaching. "
|
||||
"(stream %d sec old)",
|
||||
rendcirc->n_circ_id, conn_age);
|
||||
rendcirc->_base.n_circ_id, conn_age);
|
||||
/* Mark rendezvous circuits as 'newly dirty' every time you use
|
||||
* them, since the process of rebuilding a rendezvous circ is so
|
||||
* expensive. There is a tradeoffs between linkability and
|
||||
* feasibility, at this point.
|
||||
*/
|
||||
rendcirc->timestamp_dirty = time(NULL);
|
||||
rendcirc->_base.timestamp_dirty = time(NULL);
|
||||
link_apconn_to_circ(conn, rendcirc);
|
||||
if (connection_ap_handshake_send_begin(conn, rendcirc) < 0)
|
||||
return 0; /* already marked, let them fade away */
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (rendcirc && (rendcirc->purpose ==
|
||||
if (rendcirc && (rendcirc->_base.purpose ==
|
||||
CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED)) {
|
||||
log_info(LD_REND,
|
||||
"pending-join circ %d already here, with intro ack. "
|
||||
"Stalling. (stream %d sec old)",
|
||||
rendcirc->n_circ_id, conn_age);
|
||||
rendcirc->_base.n_circ_id, conn_age);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1247,7 +1261,8 @@ connection_ap_handshake_attach_circuit(connection_t *conn)
|
||||
tor_assert(introcirc);
|
||||
log_info(LD_REND, "Intro circ %d present and awaiting ack (rend %d). "
|
||||
"Stalling. (stream %d sec old)",
|
||||
introcirc->n_circ_id, rendcirc ? rendcirc->n_circ_id : 0,
|
||||
introcirc->_base.n_circ_id,
|
||||
rendcirc ? rendcirc->_base.n_circ_id : 0,
|
||||
conn_age);
|
||||
return 0;
|
||||
}
|
||||
@ -1255,32 +1270,34 @@ connection_ap_handshake_attach_circuit(connection_t *conn)
|
||||
/* now rendcirc and introcirc are each either undefined or not finished */
|
||||
|
||||
if (rendcirc && introcirc &&
|
||||
rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY) {
|
||||
rendcirc->_base.purpose == CIRCUIT_PURPOSE_C_REND_READY) {
|
||||
log_info(LD_REND,
|
||||
"ready rend circ %d already here (no intro-ack yet on "
|
||||
"intro %d). (stream %d sec old)",
|
||||
rendcirc->n_circ_id, introcirc->n_circ_id, conn_age);
|
||||
rendcirc->_base.n_circ_id,
|
||||
introcirc->_base.n_circ_id, conn_age);
|
||||
|
||||
tor_assert(introcirc->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
|
||||
if (introcirc->state == CIRCUIT_STATE_OPEN) {
|
||||
tor_assert(introcirc->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
|
||||
if (introcirc->_base.state == CIRCUIT_STATE_OPEN) {
|
||||
log_info(LD_REND,"found open intro circ %d (rend %d); sending "
|
||||
"introduction. (stream %d sec old)",
|
||||
introcirc->n_circ_id, rendcirc->n_circ_id, conn_age);
|
||||
introcirc->_base.n_circ_id, rendcirc->_base.n_circ_id,
|
||||
conn_age);
|
||||
if (rend_client_send_introduction(introcirc, rendcirc) < 0) {
|
||||
return -1;
|
||||
}
|
||||
rendcirc->timestamp_dirty = time(NULL);
|
||||
introcirc->timestamp_dirty = time(NULL);
|
||||
assert_circuit_ok(rendcirc);
|
||||
assert_circuit_ok(introcirc);
|
||||
rendcirc->_base.timestamp_dirty = time(NULL);
|
||||
introcirc->_base.timestamp_dirty = time(NULL);
|
||||
assert_circuit_ok(TO_CIRCUIT(rendcirc));
|
||||
assert_circuit_ok(TO_CIRCUIT(introcirc));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
log_info(LD_REND, "Intro (%d) and rend (%d) circs are not both ready. "
|
||||
"Stalling conn. (%d sec old)",
|
||||
introcirc ? introcirc->n_circ_id : 0,
|
||||
rendcirc ? rendcirc->n_circ_id : 0, conn_age);
|
||||
introcirc ? introcirc->_base.n_circ_id : 0,
|
||||
rendcirc ? rendcirc->_base.n_circ_id : 0, conn_age);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ command_process_cell(cell_t *cell, connection_t *conn)
|
||||
static void
|
||||
command_process_create_cell(cell_t *cell, connection_t *conn)
|
||||
{
|
||||
circuit_t *circ;
|
||||
or_circuit_t *circ;
|
||||
int id_is_high;
|
||||
|
||||
if (we_are_hibernating()) {
|
||||
@ -186,9 +186,7 @@ command_process_create_cell(cell_t *cell, connection_t *conn)
|
||||
return;
|
||||
}
|
||||
|
||||
circ = circuit_get_by_circid_orconn(cell->circ_id, conn);
|
||||
|
||||
if (circ) {
|
||||
if (circuit_get_by_circid_orconn(cell->circ_id, conn)) {
|
||||
routerinfo_t *router = router_get_by_digest(conn->identity_digest);
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Received CREATE cell (circID %d) for known circ. "
|
||||
@ -201,17 +199,17 @@ command_process_create_cell(cell_t *cell, connection_t *conn)
|
||||
return;
|
||||
}
|
||||
|
||||
circ = circuit_new(cell->circ_id, conn);
|
||||
circ->purpose = CIRCUIT_PURPOSE_OR;
|
||||
circuit_set_state(circ, CIRCUIT_STATE_ONIONSKIN_PENDING);
|
||||
circ = or_circuit_new(cell->circ_id, conn);
|
||||
circ->_base.purpose = CIRCUIT_PURPOSE_OR;
|
||||
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_ONIONSKIN_PENDING);
|
||||
if (cell->command == CELL_CREATE) {
|
||||
circ->onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
|
||||
memcpy(circ->onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN);
|
||||
circ->_base.onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
|
||||
memcpy(circ->_base.onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN);
|
||||
|
||||
/* hand it off to the cpuworkers, and then return. */
|
||||
if (assign_to_cpuworker(NULL, CPUWORKER_TASK_ONION, circ) < 0) {
|
||||
log_warn(LD_GENERAL,"Failed to hand off onionskin. Closing.");
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
|
||||
return;
|
||||
}
|
||||
log_debug(LD_OR,"success: handed off onionskin.");
|
||||
@ -223,12 +221,12 @@ command_process_create_cell(cell_t *cell, connection_t *conn)
|
||||
tor_assert(cell->command == CELL_CREATE_FAST);
|
||||
if (fast_server_handshake(cell->payload, reply, keys, sizeof(keys))<0) {
|
||||
log_warn(LD_OR,"Failed to generate key material. Closing.");
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
|
||||
return;
|
||||
}
|
||||
if (onionskin_answer(circ, CELL_CREATED_FAST, reply, keys)<0) {
|
||||
log_warn(LD_OR,"Failed to reply to CREATE_FAST cell. Closing.");
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -264,14 +262,16 @@ command_process_created_cell(cell_t *cell, connection_t *conn)
|
||||
}
|
||||
|
||||
if (CIRCUIT_IS_ORIGIN(circ)) { /* we're the OP. Handshake this. */
|
||||
origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
|
||||
log_debug(LD_OR,"at OP. Finishing handshake.");
|
||||
if (circuit_finish_handshake(circ, cell->command, cell->payload) < 0) {
|
||||
if (circuit_finish_handshake(origin_circ, cell->command,
|
||||
cell->payload) < 0) {
|
||||
log_warn(LD_OR,"circuit_finish_handshake failed.");
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
return;
|
||||
}
|
||||
log_debug(LD_OR,"Moving to next skin.");
|
||||
if (circuit_send_next_onion_skin(circ) < 0) {
|
||||
if (circuit_send_next_onion_skin(origin_circ) < 0) {
|
||||
log_info(LD_OR,"circuit_send_next_onion_skin failed.");
|
||||
/* XXX push this circuit_close lower */
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
@ -310,7 +310,9 @@ command_process_relay_cell(cell_t *cell, connection_t *conn)
|
||||
return;
|
||||
}
|
||||
|
||||
if (cell->circ_id == circ->p_circ_id) { /* it's an outgoing cell */
|
||||
if (!CIRCUIT_IS_ORIGIN(circ) &&
|
||||
cell->circ_id == TO_OR_CIRCUIT(circ)->p_circ_id) {
|
||||
/* it's an outgoing cell */
|
||||
if ((reason = circuit_receive_relay_cell(cell, circ,
|
||||
CELL_DIRECTION_OUT)) < 0) {
|
||||
log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,"circuit_receive_relay_cell "
|
||||
@ -357,12 +359,13 @@ command_process_destroy_cell(cell_t *cell, connection_t *conn)
|
||||
}
|
||||
log_debug(LD_OR,"Received for circID %d.",cell->circ_id);
|
||||
|
||||
if (cell->circ_id == circ->p_circ_id) {
|
||||
if (!CIRCUIT_IS_ORIGIN(circ) &&
|
||||
cell->circ_id == TO_OR_CIRCUIT(circ)->p_circ_id) {
|
||||
/* the destroy came from behind */
|
||||
circuit_set_circid_orconn(circ, 0, NULL, P_CONN_CHANGED);
|
||||
circuit_set_p_circid_orconn(TO_OR_CIRCUIT(circ), 0, NULL);
|
||||
circuit_mark_for_close(circ, reason);
|
||||
} else { /* the destroy came from ahead */
|
||||
circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED);
|
||||
circuit_set_n_circid_orconn(circ, 0, NULL);
|
||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||
circuit_mark_for_close(circ, reason);
|
||||
} else {
|
||||
|
@ -60,20 +60,6 @@ _connection_mark_unattached_ap(connection_t *conn, int endreason,
|
||||
int
|
||||
connection_edge_reached_eof(connection_t *conn)
|
||||
{
|
||||
#ifdef HALF_OPEN
|
||||
/* eof reached; we're done reading, but we might want to write more. */
|
||||
conn->done_receiving = 1;
|
||||
shutdown(conn->s, 0); /* XXX check return, refactor NM */
|
||||
if (conn->done_sending) {
|
||||
connection_edge_end(conn, END_STREAM_REASON_DONE, conn->cpath_layer);
|
||||
connection_mark_for_close(conn);
|
||||
} else {
|
||||
connection_edge_send_command(conn, circuit_get_by_edge_conn(conn),
|
||||
RELAY_COMMAND_END,
|
||||
NULL, 0, conn->cpath_layer);
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
if (buf_datalen(conn->inbuf) && connection_state_is_open(conn)) {
|
||||
/* it still has stuff to process. don't let it die yet. */
|
||||
return 0;
|
||||
@ -88,7 +74,6 @@ connection_edge_reached_eof(connection_t *conn)
|
||||
connection_mark_for_close(conn);
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Handle new bytes on conn->inbuf based on state:
|
||||
@ -386,7 +371,8 @@ connection_ap_expire_beginning(void)
|
||||
continue;
|
||||
}
|
||||
tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_GENERAL);
|
||||
nickname = build_state_get_exit_nickname(circ->build_state);
|
||||
nickname = build_state_get_exit_nickname(
|
||||
TO_ORIGIN_CIRCUIT(circ)->build_state);
|
||||
log_fn(cutoff < 15 ? LOG_INFO : severity, LD_APP,
|
||||
"We tried for %d seconds to connect to '%s' using exit '%s'."
|
||||
" Retrying on a new circuit.",
|
||||
@ -406,7 +392,7 @@ connection_ap_expire_beginning(void)
|
||||
conn->timestamp_lastread += cutoff;
|
||||
conn->num_socks_retries++;
|
||||
/* move it back into 'pending' state, and try to attach. */
|
||||
if (connection_ap_detach_retriable(conn, circ)<0) {
|
||||
if (connection_ap_detach_retriable(conn, TO_ORIGIN_CIRCUIT(circ))<0) {
|
||||
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
|
||||
}
|
||||
} /* end for */
|
||||
@ -444,17 +430,17 @@ connection_ap_attach_pending(void)
|
||||
* Returns -1 on err, 1 on success, 0 on not-yet-sure.
|
||||
*/
|
||||
int
|
||||
connection_ap_detach_retriable(connection_t *conn, circuit_t *circ)
|
||||
connection_ap_detach_retriable(connection_t *conn, origin_circuit_t *circ)
|
||||
{
|
||||
control_event_stream_status(conn, STREAM_EVENT_FAILED_RETRIABLE);
|
||||
conn->timestamp_lastread = time(NULL);
|
||||
if (! get_options()->LeaveStreamsUnattached) {
|
||||
conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
|
||||
circuit_detach_stream(circ,conn);
|
||||
circuit_detach_stream(TO_CIRCUIT(circ),conn);
|
||||
return connection_ap_handshake_attach_circuit(conn);
|
||||
} else {
|
||||
conn->state = AP_CONN_STATE_CONTROLLER_WAIT;
|
||||
circuit_detach_stream(circ,conn);
|
||||
circuit_detach_stream(TO_CIRCUIT(circ),conn);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -1026,7 +1012,7 @@ addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
|
||||
*/
|
||||
int
|
||||
connection_ap_handshake_rewrite_and_attach(connection_t *conn,
|
||||
circuit_t *circ)
|
||||
origin_circuit_t *circ)
|
||||
{
|
||||
socks_request_t *socks = conn->socks_request;
|
||||
hostname_type_t addresstype;
|
||||
@ -1287,7 +1273,7 @@ connection_ap_handshake_process_socks(connection_t *conn)
|
||||
* already in use; return it. Return 0 if can't get a unique stream_id.
|
||||
*/
|
||||
static uint16_t
|
||||
get_unique_stream_id_by_circ(circuit_t *circ)
|
||||
get_unique_stream_id_by_circ(origin_circuit_t *circ)
|
||||
{
|
||||
connection_t *tmpconn;
|
||||
uint16_t test_stream_id;
|
||||
@ -1314,7 +1300,8 @@ again:
|
||||
* If ap_conn is broken, mark it for close and return -1. Else return 0.
|
||||
*/
|
||||
int
|
||||
connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ)
|
||||
connection_ap_handshake_send_begin(connection_t *ap_conn,
|
||||
origin_circuit_t *circ)
|
||||
{
|
||||
char payload[CELL_PAYLOAD_SIZE];
|
||||
int payload_len;
|
||||
@ -1326,12 +1313,12 @@ connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ)
|
||||
ap_conn->stream_id = get_unique_stream_id_by_circ(circ);
|
||||
if (ap_conn->stream_id==0) {
|
||||
connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_RESOURCELIMIT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tor_snprintf(payload,RELAY_PAYLOAD_SIZE, "%s:%d",
|
||||
(circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) ?
|
||||
(circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL) ?
|
||||
ap_conn->socks_request->address : "",
|
||||
ap_conn->socks_request->port);
|
||||
payload_len = strlen(payload)+1;
|
||||
@ -1339,7 +1326,8 @@ connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ)
|
||||
log_debug(LD_APP,
|
||||
"Sending relay cell to begin stream %d.", ap_conn->stream_id);
|
||||
|
||||
if (connection_edge_send_command(ap_conn, circ, RELAY_COMMAND_BEGIN,
|
||||
if (connection_edge_send_command(ap_conn, TO_CIRCUIT(circ),
|
||||
RELAY_COMMAND_BEGIN,
|
||||
payload, payload_len,
|
||||
ap_conn->cpath_layer) < 0)
|
||||
return -1; /* circuit is closed, don't continue */
|
||||
@ -1348,7 +1336,7 @@ connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ)
|
||||
ap_conn->deliver_window = STREAMWINDOW_START;
|
||||
ap_conn->state = AP_CONN_STATE_CONNECT_WAIT;
|
||||
log_info(LD_APP,"Address/port sent, ap socket %d, n_circ_id %d",
|
||||
ap_conn->s, circ->n_circ_id);
|
||||
ap_conn->s, circ->_base.n_circ_id);
|
||||
control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT);
|
||||
return 0;
|
||||
}
|
||||
@ -1359,7 +1347,8 @@ connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ)
|
||||
* If ap_conn is broken, mark it for close and return -1. Else return 0.
|
||||
*/
|
||||
int
|
||||
connection_ap_handshake_send_resolve(connection_t *ap_conn, circuit_t *circ)
|
||||
connection_ap_handshake_send_resolve(connection_t *ap_conn,
|
||||
origin_circuit_t *circ)
|
||||
{
|
||||
int payload_len;
|
||||
const char *string_addr;
|
||||
@ -1368,12 +1357,12 @@ connection_ap_handshake_send_resolve(connection_t *ap_conn, circuit_t *circ)
|
||||
tor_assert(ap_conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
|
||||
tor_assert(ap_conn->socks_request);
|
||||
tor_assert(ap_conn->socks_request->command == SOCKS_COMMAND_RESOLVE);
|
||||
tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_GENERAL);
|
||||
tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL);
|
||||
|
||||
ap_conn->stream_id = get_unique_stream_id_by_circ(circ);
|
||||
if (ap_conn->stream_id==0) {
|
||||
connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_RESOURCELIMIT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1384,13 +1373,14 @@ connection_ap_handshake_send_resolve(connection_t *ap_conn, circuit_t *circ)
|
||||
log_debug(LD_APP,
|
||||
"Sending relay cell to begin stream %d.", ap_conn->stream_id);
|
||||
|
||||
if (connection_edge_send_command(ap_conn, circ, RELAY_COMMAND_RESOLVE,
|
||||
if (connection_edge_send_command(ap_conn, TO_CIRCUIT(circ),
|
||||
RELAY_COMMAND_RESOLVE,
|
||||
string_addr, payload_len, ap_conn->cpath_layer) < 0)
|
||||
return -1; /* circuit is closed, don't continue */
|
||||
|
||||
ap_conn->state = AP_CONN_STATE_RESOLVE_WAIT;
|
||||
log_info(LD_APP,"Address sent for resolve, ap socket %d, n_circ_id %d",
|
||||
ap_conn->s, circ->n_circ_id);
|
||||
ap_conn->s, circ->_base.n_circ_id);
|
||||
control_event_stream_status(ap_conn, STREAM_EVENT_SENT_RESOLVE);
|
||||
return 0;
|
||||
}
|
||||
@ -1643,6 +1633,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
|
||||
n_stream->deliver_window = STREAMWINDOW_START;
|
||||
|
||||
if (circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED) {
|
||||
origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
|
||||
log_debug(LD_REND,"begin is for rendezvous. configuring stream.");
|
||||
n_stream->address = tor_strdup("(rendezvous)");
|
||||
n_stream->state = EXIT_CONN_STATE_CONNECTING;
|
||||
@ -1650,7 +1641,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
|
||||
sizeof(n_stream->rend_query));
|
||||
tor_assert(connection_edge_is_rendezvous_stream(n_stream));
|
||||
assert_circuit_ok(circ);
|
||||
if (rend_service_set_connection_addr_port(n_stream, circ) < 0) {
|
||||
if (rend_service_set_connection_addr_port(n_stream, origin_circ) < 0) {
|
||||
log_info(LD_REND,"Didn't find rendezvous service (port %d)",
|
||||
n_stream->port);
|
||||
connection_edge_end(n_stream, END_STREAM_REASON_EXITPOLICY,
|
||||
@ -1663,12 +1654,12 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
|
||||
}
|
||||
assert_circuit_ok(circ);
|
||||
log_debug(LD_REND,"Finished assigning addr/port");
|
||||
n_stream->cpath_layer = circ->cpath->prev; /* link it */
|
||||
n_stream->cpath_layer = origin_circ->cpath->prev; /* link it */
|
||||
|
||||
/* add it into the linked list of n_streams on this circuit */
|
||||
n_stream->next_stream = circ->n_streams;
|
||||
n_stream->next_stream = origin_circ->p_streams;
|
||||
n_stream->on_circuit = circ;
|
||||
circ->n_streams = n_stream;
|
||||
origin_circ->p_streams = n_stream;
|
||||
assert_circuit_ok(circ);
|
||||
|
||||
connection_exit_connect(n_stream);
|
||||
@ -1693,9 +1684,9 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
|
||||
case 1: /* resolve worked */
|
||||
|
||||
/* add it into the linked list of n_streams on this circuit */
|
||||
n_stream->next_stream = circ->n_streams;
|
||||
n_stream->next_stream = TO_OR_CIRCUIT(circ)->n_streams;
|
||||
n_stream->on_circuit = circ;
|
||||
circ->n_streams = n_stream;
|
||||
TO_OR_CIRCUIT(circ)->n_streams = n_stream;
|
||||
assert_circuit_ok(circ);
|
||||
|
||||
log_debug(LD_EXIT,"about to call connection_exit_connect().");
|
||||
@ -1706,9 +1697,9 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
|
||||
break;
|
||||
case 0: /* resolve added to pending list */
|
||||
/* add it into the linked list of resolving_streams on this circuit */
|
||||
n_stream->next_stream = circ->resolving_streams;
|
||||
n_stream->next_stream = TO_OR_CIRCUIT(circ)->resolving_streams;
|
||||
n_stream->on_circuit = circ;
|
||||
circ->resolving_streams = n_stream;
|
||||
TO_OR_CIRCUIT(circ)->resolving_streams = n_stream;
|
||||
assert_circuit_ok(circ);
|
||||
;
|
||||
}
|
||||
@ -1720,12 +1711,12 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
|
||||
* begin resolving the hostname, and (eventually) reply with a RESOLVED cell.
|
||||
*/
|
||||
int
|
||||
connection_exit_begin_resolve(cell_t *cell, circuit_t *circ)
|
||||
connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ)
|
||||
{
|
||||
connection_t *dummy_conn;
|
||||
relay_header_t rh;
|
||||
|
||||
assert_circuit_ok(circ);
|
||||
assert_circuit_ok(TO_CIRCUIT(circ));
|
||||
relay_header_unpack(&rh, cell->payload);
|
||||
|
||||
/* This 'dummy_conn' only exists to remember the stream ID
|
||||
@ -1754,9 +1745,9 @@ connection_exit_begin_resolve(cell_t *cell, circuit_t *circ)
|
||||
return 0;
|
||||
case 0: /* resolve added to pending list */
|
||||
dummy_conn->next_stream = circ->resolving_streams;
|
||||
dummy_conn->on_circuit = circ;
|
||||
dummy_conn->on_circuit = TO_CIRCUIT(circ);
|
||||
circ->resolving_streams = dummy_conn;
|
||||
assert_circuit_ok(circ);
|
||||
assert_circuit_ok(TO_CIRCUIT(circ));
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1372,7 +1372,7 @@ handle_getinfo_helper(const char *question, char **answer)
|
||||
const char *state;
|
||||
if (! CIRCUIT_IS_ORIGIN(circ) || circ->marked_for_close)
|
||||
continue;
|
||||
path = circuit_list_path(circ,0);
|
||||
path = circuit_list_path(TO_ORIGIN_CIRCUIT(circ),0);
|
||||
if (circ->state == CIRCUIT_STATE_OPEN)
|
||||
state = "BUILT";
|
||||
else if (strlen(path))
|
||||
@ -1728,6 +1728,15 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
|
||||
}
|
||||
}
|
||||
|
||||
if (circ && ! CIRCUIT_IS_ORIGIN(circ)) {
|
||||
if (v0)
|
||||
send_control0_error(conn, ERR_NO_CIRC,"Circuit does not originate here");
|
||||
else
|
||||
connection_printf_to_buf(conn,
|
||||
"555 Circuit does not originate here\r\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
routers = smartlist_create();
|
||||
SMARTLIST_FOREACH(router_nicknames, const char *, n,
|
||||
{
|
||||
@ -1751,20 +1760,20 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
|
||||
|
||||
if (zero_circ) {
|
||||
/* start a new circuit */
|
||||
circ = circuit_init(intended_purpose, 0, 0, 0);
|
||||
circ = TO_CIRCUIT( origin_circuit_init(intended_purpose, 0, 0, 0) );
|
||||
}
|
||||
|
||||
/* now circ refers to something that is ready to be extended */
|
||||
SMARTLIST_FOREACH(routers, routerinfo_t *, r,
|
||||
{
|
||||
extend_info_t *info = extend_info_from_router(r);
|
||||
circuit_append_new_exit(circ, info);
|
||||
circuit_append_new_exit(TO_ORIGIN_CIRCUIT(circ), info);
|
||||
extend_info_free(info);
|
||||
});
|
||||
|
||||
/* now that we've populated the cpath, start extending */
|
||||
if (zero_circ) {
|
||||
if (circuit_handle_first_hop(circ) < 0) {
|
||||
if (circuit_handle_first_hop(TO_ORIGIN_CIRCUIT(circ)) < 0) {
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
if (v0)
|
||||
send_control0_error(conn, ERR_INTERNAL, "couldn't start circuit");
|
||||
@ -1775,7 +1784,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
|
||||
} else {
|
||||
if (circ->state == CIRCUIT_STATE_OPEN) {
|
||||
circuit_set_state(circ, CIRCUIT_STATE_BUILDING);
|
||||
if (circuit_send_next_onion_skin(circ) < 0) {
|
||||
if (circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ)) < 0) {
|
||||
log_info(LD_CONTROL,
|
||||
"send_next_onion_skin failed; circuit marked for closing.");
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
@ -1940,17 +1949,19 @@ handle_control_attachstream(connection_t *conn, uint32_t len,
|
||||
ap_conn->state = AP_CONN_STATE_CONTROLLER_WAIT;
|
||||
}
|
||||
|
||||
if (circ && circ->state != CIRCUIT_STATE_OPEN) {
|
||||
if (circ &&
|
||||
(circ->state != CIRCUIT_STATE_OPEN || ! CIRCUIT_IS_ORIGIN(circ))) {
|
||||
if (STATE_IS_V0(conn->state))
|
||||
send_control0_error(conn, ERR_INTERNAL,
|
||||
"Refuse to attach stream to non-open circ.");
|
||||
"Refuse to attach stream to non-open, origin circ.");
|
||||
else
|
||||
connection_write_str_to_buf(
|
||||
"551 Can't attach stream to non-open circuit\r\n",
|
||||
conn);
|
||||
"551 Can't attach stream to non-open, origin circuit\r\n",
|
||||
conn);
|
||||
return 0;
|
||||
}
|
||||
if (connection_ap_handshake_rewrite_and_attach(ap_conn, circ) < 0) {
|
||||
if (connection_ap_handshake_rewrite_and_attach(ap_conn,
|
||||
circ ? TO_ORIGIN_CIRCUIT(circ) : NULL) < 0) {
|
||||
if (STATE_IS_V0(conn->state))
|
||||
send_control0_error(conn, ERR_INTERNAL, "Unable to attach stream.");
|
||||
else
|
||||
@ -2195,7 +2206,8 @@ handle_control_closecircuit(connection_t *conn, uint32_t len,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!safe || !circ->p_streams) {
|
||||
if (!safe || !CIRCUIT_IS_ORIGIN(circ) ||
|
||||
!TO_ORIGIN_CIRCUIT(circ)->p_streams) {
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_NONE);
|
||||
}
|
||||
|
||||
@ -2586,20 +2598,19 @@ connection_control_process_inbuf(connection_t *conn)
|
||||
/** Something has happened to circuit <b>circ</b>: tell any interested
|
||||
* control connections. */
|
||||
int
|
||||
control_event_circuit_status(circuit_t *circ, circuit_status_event_t tp)
|
||||
control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp)
|
||||
{
|
||||
char *path, *msg;
|
||||
if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS))
|
||||
return 0;
|
||||
tor_assert(circ);
|
||||
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
||||
|
||||
path = circuit_list_path(circ,0);
|
||||
if (EVENT_IS_INTERESTING0(EVENT_CIRCUIT_STATUS)) {
|
||||
size_t path_len = strlen(path);
|
||||
msg = tor_malloc(1+4+path_len+1); /* event, circid, path, NUL. */
|
||||
msg[0] = (uint8_t) tp;
|
||||
set_uint32(msg+1, htonl(circ->global_identifier));
|
||||
set_uint32(msg+1, htonl(circ->_base.global_identifier));
|
||||
strlcpy(msg+5,path,path_len+1);
|
||||
|
||||
send_control0_event(EVENT_CIRCUIT_STATUS, (uint32_t)(path_len+6), msg);
|
||||
@ -2620,7 +2631,7 @@ control_event_circuit_status(circuit_t *circ, circuit_status_event_t tp)
|
||||
}
|
||||
send_control1_event(EVENT_CIRCUIT_STATUS,
|
||||
"650 CIRC %lu %s %s\r\n",
|
||||
(unsigned long)circ->global_identifier,
|
||||
(unsigned long)circ->_base.global_identifier,
|
||||
status, path);
|
||||
}
|
||||
tor_free(path);
|
||||
|
@ -181,8 +181,8 @@ connection_cpu_process_inbuf(connection_t *conn)
|
||||
log_debug(LD_OR,"processed onion for a circ that's gone. Dropping.");
|
||||
goto done_processing;
|
||||
}
|
||||
tor_assert(circ->p_conn);
|
||||
if (onionskin_answer(circ, CELL_CREATED, buf+TAG_LEN,
|
||||
tor_assert(! CIRCUIT_IS_ORIGIN(circ));
|
||||
if (onionskin_answer(TO_OR_CIRCUIT(circ), CELL_CREATED, buf+TAG_LEN,
|
||||
buf+TAG_LEN+ONIONSKIN_REPLY_LEN) < 0) {
|
||||
log_warn(LD_OR,"onionskin_answer failed. Closing.");
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
|
||||
@ -386,7 +386,7 @@ spawn_enough_cpuworkers(void)
|
||||
static void
|
||||
process_pending_task(connection_t *cpuworker)
|
||||
{
|
||||
circuit_t *circ;
|
||||
or_circuit_t *circ;
|
||||
|
||||
tor_assert(cpuworker);
|
||||
|
||||
@ -444,7 +444,7 @@ int
|
||||
assign_to_cpuworker(connection_t *cpuworker, uint8_t question_type,
|
||||
void *task)
|
||||
{
|
||||
circuit_t *circ;
|
||||
or_circuit_t *circ;
|
||||
char tag[TAG_LEN];
|
||||
|
||||
tor_assert(question_type == CPUWORKER_TASK_ONION);
|
||||
@ -454,7 +454,7 @@ assign_to_cpuworker(connection_t *cpuworker, uint8_t question_type,
|
||||
|
||||
if (question_type == CPUWORKER_TASK_ONION) {
|
||||
circ = task;
|
||||
tor_assert(circ->onionskin);
|
||||
tor_assert(circ->_base.onionskin);
|
||||
|
||||
if (num_cpuworkers_busy == num_cpuworkers) {
|
||||
log_debug(LD_OR,"No idle cpuworkers. Queuing.");
|
||||
@ -484,9 +484,9 @@ assign_to_cpuworker(connection_t *cpuworker, uint8_t question_type,
|
||||
|
||||
connection_write_to_buf((char*)&question_type, 1, cpuworker);
|
||||
connection_write_to_buf(tag, sizeof(tag), cpuworker);
|
||||
connection_write_to_buf(circ->onionskin, ONIONSKIN_CHALLENGE_LEN,
|
||||
connection_write_to_buf(circ->_base.onionskin, ONIONSKIN_CHALLENGE_LEN,
|
||||
cpuworker);
|
||||
tor_free(circ->onionskin);
|
||||
tor_free(circ->_base.onionskin);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -686,12 +686,13 @@ dns_found_answer(const char *address, uint32_t addr, char outcome,
|
||||
|
||||
circ = circuit_get_by_edge_conn(pend->conn);
|
||||
tor_assert(circ);
|
||||
tor_assert(!CIRCUIT_IS_ORIGIN(circ));
|
||||
/* unlink pend->conn from resolving_streams, */
|
||||
circuit_detach_stream(circ, pend->conn);
|
||||
/* and link it to n_streams */
|
||||
pend->conn->next_stream = circ->n_streams;
|
||||
pend->conn->next_stream = TO_OR_CIRCUIT(circ)->n_streams;
|
||||
pend->conn->on_circuit = circ;
|
||||
circ->n_streams = pend->conn;
|
||||
TO_OR_CIRCUIT(circ)->n_streams = pend->conn;
|
||||
|
||||
connection_exit_connect(pend->conn);
|
||||
} else {
|
||||
|
@ -17,7 +17,7 @@ const char onion_c_id[] =
|
||||
/** Type for a linked list of circuits that are waiting for a free CPU worker
|
||||
* to process a waiting onion handshake. */
|
||||
typedef struct onion_queue_t {
|
||||
circuit_t *circ;
|
||||
or_circuit_t *circ;
|
||||
time_t when_added;
|
||||
struct onion_queue_t *next;
|
||||
} onion_queue_t;
|
||||
@ -35,7 +35,7 @@ static int ol_length=0;
|
||||
* if ol_list is too long, in which case do nothing and return -1.
|
||||
*/
|
||||
int
|
||||
onion_pending_add(circuit_t *circ)
|
||||
onion_pending_add(or_circuit_t *circ)
|
||||
{
|
||||
onion_queue_t *tmp;
|
||||
time_t now = time(NULL);
|
||||
@ -75,7 +75,7 @@ onion_pending_add(circuit_t *circ)
|
||||
onion_pending_remove(ol_list->circ);
|
||||
log_info(LD_CIRC,
|
||||
"Circuit create request is too old; cancelling due to overload.");
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_RESOURCELIMIT);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -83,10 +83,10 @@ onion_pending_add(circuit_t *circ)
|
||||
/** Remove the first item from ol_list and return it, or return
|
||||
* NULL if the list is empty.
|
||||
*/
|
||||
circuit_t *
|
||||
or_circuit_t *
|
||||
onion_next_task(void)
|
||||
{
|
||||
circuit_t *circ;
|
||||
or_circuit_t *circ;
|
||||
|
||||
if (!ol_list)
|
||||
return NULL; /* no onions pending, we're done */
|
||||
@ -103,7 +103,7 @@ onion_next_task(void)
|
||||
* circ, remove and free that element. Leave circ itself alone.
|
||||
*/
|
||||
void
|
||||
onion_pending_remove(circuit_t *circ)
|
||||
onion_pending_remove(or_circuit_t *circ)
|
||||
{
|
||||
onion_queue_t *tmpo, *victim;
|
||||
|
||||
|
253
src/or/or.h
253
src/or/or.h
@ -1040,7 +1040,10 @@ typedef struct {
|
||||
time_t expiry_time;
|
||||
} cpath_build_state_t;
|
||||
|
||||
#define CIRCUIT_MAGIC 0x35315243u
|
||||
#define ORIGIN_CIRCUIT_MAGIC 0x35315243u
|
||||
#define OR_CIRCUIT_MAGIC 0x98ABC04Fu
|
||||
|
||||
typedef uint16_t circid_t;
|
||||
|
||||
/**
|
||||
* A circuit is a path over the onion routing
|
||||
@ -1064,29 +1067,20 @@ typedef struct {
|
||||
* "backward" (towards the OP). At the OR, a circuit has only two stream
|
||||
* ciphers: one for data going forward, and one for data going backward.
|
||||
*/
|
||||
struct circuit_t {
|
||||
uint32_t magic; /**< For memory debugging: must equal CIRCUIT_MAGIC. */
|
||||
typedef struct circuit_t {
|
||||
uint32_t magic; /**< For memory and type debugging: must equal
|
||||
* ORIGIN_CIRCUIT_MAGIC or OR_CIRCUIT_MAGIC. */
|
||||
|
||||
/** The OR connection that is previous in this circuit. */
|
||||
connection_t *p_conn;
|
||||
/** The OR connection that is next in this circuit. */
|
||||
connection_t *n_conn;
|
||||
/** The identity hash of n_conn. */
|
||||
char n_conn_id_digest[DIGEST_LEN];
|
||||
/** Linked list of AP streams associated with this circuit. */
|
||||
connection_t *p_streams;
|
||||
/** Linked list of Exit streams associated with this circuit. */
|
||||
connection_t *n_streams;
|
||||
/** Linked list of Exit streams associated with this circuit that are
|
||||
* still being resolved. */
|
||||
connection_t *resolving_streams;
|
||||
/** The circuit_id used in the next (forward) hop of this circuit. */
|
||||
uint16_t n_circ_id;
|
||||
/** The IPv4 address of the OR that is next in this circuit. */
|
||||
uint32_t n_addr;
|
||||
/** The port for the OR that is next in this circuit. */
|
||||
uint16_t n_port;
|
||||
/** The next stream_id that will be tried when we're attempting to
|
||||
* construct a new AP stream originating at this circuit. */
|
||||
uint16_t next_stream_id;
|
||||
/** How many relay data cells can we package (read from edge streams)
|
||||
* on this circuit before we receive a circuit-level sendme cell asking
|
||||
* for more? */
|
||||
@ -1097,48 +1091,12 @@ struct circuit_t {
|
||||
* more. */
|
||||
int deliver_window;
|
||||
|
||||
/** The circuit_id used in the previous (backward) hop of this circuit. */
|
||||
uint16_t p_circ_id;
|
||||
/** The circuit_id used in the next (forward) hop of this circuit. */
|
||||
uint16_t n_circ_id;
|
||||
|
||||
/** The cipher used by intermediate hops for cells heading toward the
|
||||
* OP. */
|
||||
crypto_cipher_env_t *p_crypto;
|
||||
/** The cipher used by intermediate hops for cells heading away from
|
||||
* the OP. */
|
||||
crypto_cipher_env_t *n_crypto;
|
||||
|
||||
/** The integrity-checking digest used by intermediate hops, for
|
||||
* cells packaged here and heading towards the OP.
|
||||
*/
|
||||
crypto_digest_env_t *p_digest;
|
||||
/** The integrity-checking digest used by intermediate hops, for
|
||||
* cells packaged at the OP and arriving here.
|
||||
*/
|
||||
crypto_digest_env_t *n_digest;
|
||||
|
||||
/** Build state for this circuit. It includes the intended path
|
||||
* length, the chosen exit router, rendezvous information, etc.
|
||||
*/
|
||||
cpath_build_state_t *build_state;
|
||||
/** The doubly-linked list of crypt_path_t entries, one per hop,
|
||||
* for this circuit. This includes ciphers for each hop,
|
||||
* integrity-checking digests for each hop, and package/delivery
|
||||
* windows for each hop.
|
||||
*
|
||||
* The cpath field is defined only when we are the circuit's origin.
|
||||
*/
|
||||
crypt_path_t *cpath;
|
||||
|
||||
/** For storage while passing to cpuworker (state
|
||||
* CIRCUIT_STATE_ONIONSKIN_PENDING), or while n_conn is pending
|
||||
* (state CIRCUIT_STATE_OR_WAIT). When defined, it is always
|
||||
* length ONIONSKIN_CHALLENGE_LEN. */
|
||||
char *onionskin;
|
||||
|
||||
char handshake_digest[DIGEST_LEN]; /**< Stores KH for intermediate hops. */
|
||||
|
||||
time_t timestamp_created; /**< When was this circuit created? */
|
||||
time_t timestamp_dirty; /**< When the circuit was first used, or 0 if the
|
||||
* circuit is clean. */
|
||||
@ -1169,18 +1127,85 @@ struct circuit_t {
|
||||
*/
|
||||
char rend_cookie[REND_COOKIE_LEN];
|
||||
|
||||
/** Points to spliced circuit if purpose is REND_ESTABLISHED, and circuit
|
||||
* is not marked for close. */
|
||||
struct circuit_t *rend_splice;
|
||||
|
||||
/** Quasi-global identifier for this circuit; used for control.c */
|
||||
/* XXXX NM This can get re-used after 2**32 circuits. */
|
||||
uint32_t global_identifier;
|
||||
|
||||
struct circuit_t *next; /**< Next circuit in linked list. */
|
||||
};
|
||||
} circuit_t;
|
||||
|
||||
typedef struct circuit_t circuit_t;
|
||||
typedef struct origin_circuit_t {
|
||||
circuit_t _base;
|
||||
|
||||
/** Linked list of AP streams associated with this circuit. */
|
||||
connection_t *p_streams;
|
||||
/** The next stream_id that will be tried when we're attempting to
|
||||
* construct a new AP stream originating at this circuit. */
|
||||
uint16_t next_stream_id;
|
||||
/** Build state for this circuit. It includes the intended path
|
||||
* length, the chosen exit router, rendezvous information, etc.
|
||||
*/
|
||||
cpath_build_state_t *build_state;
|
||||
/** The doubly-linked list of crypt_path_t entries, one per hop,
|
||||
* for this circuit. This includes ciphers for each hop,
|
||||
* integrity-checking digests for each hop, and package/delivery
|
||||
* windows for each hop.
|
||||
*
|
||||
* The cpath field is defined only when we are the circuit's origin.
|
||||
*/
|
||||
crypt_path_t *cpath;
|
||||
|
||||
} origin_circuit_t;
|
||||
|
||||
typedef struct or_circuit_t {
|
||||
circuit_t _base;
|
||||
|
||||
/** The circuit_id used in the previous (backward) hop of this circuit. */
|
||||
circid_t p_circ_id;
|
||||
/** The OR connection that is previous in this circuit. */
|
||||
connection_t *p_conn;
|
||||
/** Linked list of Exit streams associated with this circuit. */
|
||||
connection_t *n_streams;
|
||||
/** Linked list of Exit streams associated with this circuit that are
|
||||
* still being resolved. */
|
||||
connection_t *resolving_streams;
|
||||
/** The cipher used by intermediate hops for cells heading toward the
|
||||
* OP. */
|
||||
crypto_cipher_env_t *p_crypto;
|
||||
/** The cipher used by intermediate hops for cells heading away from
|
||||
* the OP. */
|
||||
crypto_cipher_env_t *n_crypto;
|
||||
|
||||
/** The integrity-checking digest used by intermediate hops, for
|
||||
* cells packaged here and heading towards the OP.
|
||||
*/
|
||||
crypto_digest_env_t *p_digest;
|
||||
/** The integrity-checking digest used by intermediate hops, for
|
||||
* cells packaged at the OP and arriving here.
|
||||
*/
|
||||
crypto_digest_env_t *n_digest;
|
||||
|
||||
/** Points to spliced circuit if purpose is REND_ESTABLISHED, and circuit
|
||||
* is not marked for close. */
|
||||
struct or_circuit_t *rend_splice;
|
||||
|
||||
char handshake_digest[DIGEST_LEN]; /**< Stores KH for intermediate hops. */
|
||||
} or_circuit_t;
|
||||
|
||||
#define TO_CIRCUIT(x) (&((x)->_base))
|
||||
or_circuit_t *TO_OR_CIRCUIT(circuit_t *x);
|
||||
extern INLINE or_circuit_t *TO_OR_CIRCUIT(circuit_t *x)
|
||||
{
|
||||
tor_assert(x->magic == OR_CIRCUIT_MAGIC);
|
||||
return (or_circuit_t*) (((char*)x) - STRUCT_OFFSET(or_circuit_t, _base));
|
||||
}
|
||||
origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *x);
|
||||
extern INLINE origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *x)
|
||||
{
|
||||
tor_assert(x->magic == ORIGIN_CIRCUIT_MAGIC);
|
||||
return (origin_circuit_t*)
|
||||
(((char*)x) - STRUCT_OFFSET(origin_circuit_t, _base));
|
||||
}
|
||||
|
||||
#define ALLOW_INVALID_ENTRY 1
|
||||
#define ALLOW_INVALID_EXIT 2
|
||||
@ -1505,32 +1530,34 @@ void assert_buf_ok(buf_t *buf);
|
||||
|
||||
/********************************* circuitbuild.c **********************/
|
||||
|
||||
char *circuit_list_path(circuit_t *circ, int verbose);
|
||||
void circuit_log_path(int severity, unsigned int domain, circuit_t *circ);
|
||||
void circuit_rep_hist_note_result(circuit_t *circ);
|
||||
void circuit_dump_by_conn(connection_t *conn, int severity);
|
||||
circuit_t *circuit_init(uint8_t purpose, int need_uptime,
|
||||
int need_capacity, int internal);
|
||||
circuit_t *circuit_establish_circuit(uint8_t purpose, extend_info_t *exit,
|
||||
char *circuit_list_path(origin_circuit_t *circ, int verbose);
|
||||
void circuit_log_path(int severity, unsigned int domain,
|
||||
origin_circuit_t *circ);
|
||||
void circuit_rep_hist_note_result(origin_circuit_t *circ);
|
||||
origin_circuit_t *origin_circuit_init(uint8_t purpose, int need_uptime,
|
||||
int need_capacity, int internal);
|
||||
origin_circuit_t *circuit_establish_circuit(uint8_t purpose,
|
||||
extend_info_t *exit,
|
||||
int need_uptime, int need_capacity,
|
||||
int internal);
|
||||
int circuit_handle_first_hop(circuit_t *circ);
|
||||
int circuit_handle_first_hop(origin_circuit_t *circ);
|
||||
void circuit_n_conn_done(connection_t *or_conn, int status);
|
||||
int inform_testing_reachability(void);
|
||||
int circuit_send_next_onion_skin(circuit_t *circ);
|
||||
int circuit_send_next_onion_skin(origin_circuit_t *circ);
|
||||
void circuit_note_clock_jumped(int seconds_elapsed);
|
||||
int circuit_extend(cell_t *cell, circuit_t *circ);
|
||||
int circuit_init_cpath_crypto(crypt_path_t *cpath, char *key_data,
|
||||
int reverse);
|
||||
int circuit_finish_handshake(circuit_t *circ, uint8_t cell_type, char *reply);
|
||||
int circuit_truncated(circuit_t *circ, crypt_path_t *layer);
|
||||
int onionskin_answer(circuit_t *circ, uint8_t cell_type, char *payload,
|
||||
int circuit_finish_handshake(origin_circuit_t *circ, uint8_t cell_type,
|
||||
char *reply);
|
||||
int circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer);
|
||||
int onionskin_answer(or_circuit_t *circ, uint8_t cell_type, char *payload,
|
||||
char *keys);
|
||||
int circuit_all_predicted_ports_handled(time_t now, int *need_uptime,
|
||||
int *need_capacity);
|
||||
|
||||
int circuit_append_new_exit(circuit_t *circ, extend_info_t *info);
|
||||
int circuit_extend_to_new_exit(circuit_t *circ, extend_info_t *info);
|
||||
int circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info);
|
||||
int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info);
|
||||
void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop);
|
||||
extend_info_t *extend_info_from_router(routerinfo_t *r);
|
||||
extend_info_t *extend_info_dup(extend_info_t *info);
|
||||
@ -1551,13 +1578,15 @@ void entry_guards_free_all(void);
|
||||
|
||||
circuit_t * _circuit_get_global_list(void);
|
||||
const char *circuit_state_to_string(int state);
|
||||
enum which_conn_changed_t { P_CONN_CHANGED=1, N_CONN_CHANGED=0 };
|
||||
void circuit_set_circid_orconn(circuit_t *circ, uint16_t id,
|
||||
connection_t *conn,
|
||||
enum which_conn_changed_t which);
|
||||
void circuit_dump_by_conn(connection_t *conn, int severity);
|
||||
void circuit_set_p_circid_orconn(or_circuit_t *circ, uint16_t id,
|
||||
connection_t *conn);
|
||||
void circuit_set_n_circid_orconn(circuit_t *circ, uint16_t id,
|
||||
connection_t *conn);
|
||||
void circuit_set_state(circuit_t *circ, int state);
|
||||
void circuit_close_all_marked(void);
|
||||
circuit_t *circuit_new(uint16_t p_circ_id, connection_t *p_conn);
|
||||
origin_circuit_t *origin_circuit_new(void);
|
||||
or_circuit_t *or_circuit_new(uint16_t p_circ_id, connection_t *p_conn);
|
||||
circuit_t *circuit_get_by_circid_orconn(uint16_t circ_id, connection_t *conn);
|
||||
int circuit_id_used_on_conn(uint16_t circ_id, connection_t *conn);
|
||||
circuit_t *circuit_get_by_edge_conn(connection_t *conn);
|
||||
@ -1567,8 +1596,9 @@ circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query,
|
||||
uint8_t purpose);
|
||||
circuit_t *circuit_get_next_by_pk_and_purpose(circuit_t *start,
|
||||
const char *digest, uint8_t purpose);
|
||||
circuit_t *circuit_get_rendezvous(const char *cookie);
|
||||
circuit_t *circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
|
||||
or_circuit_t *circuit_get_rendezvous(const char *cookie);
|
||||
origin_circuit_t *circuit_find_to_cannibalize(uint8_t purpose,
|
||||
extend_info_t *info,
|
||||
int need_uptime,
|
||||
int need_capacity, int internal);
|
||||
void circuit_mark_all_unused_circs(void);
|
||||
@ -1592,22 +1622,22 @@ int circuit_stream_is_being_handled(connection_t *conn, uint16_t port,
|
||||
void circuit_build_needed_circs(time_t now);
|
||||
void circuit_detach_stream(circuit_t *circ, connection_t *conn);
|
||||
void circuit_about_to_close_connection(connection_t *conn);
|
||||
void circuit_has_opened(circuit_t *circ);
|
||||
void circuit_build_failed(circuit_t *circ);
|
||||
circuit_t *circuit_launch_by_nickname(uint8_t purpose,
|
||||
void circuit_has_opened(origin_circuit_t *circ);
|
||||
void circuit_build_failed(origin_circuit_t *circ);
|
||||
origin_circuit_t *circuit_launch_by_nickname(uint8_t purpose,
|
||||
const char *exit_nickname,
|
||||
int need_uptime, int need_capacity,
|
||||
int is_internal);
|
||||
circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
|
||||
origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
|
||||
extend_info_t *info,
|
||||
int need_uptime, int need_capacity,
|
||||
int is_internal);
|
||||
circuit_t *circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
|
||||
origin_circuit_t *circuit_launch_by_router(uint8_t purpose, routerinfo_t *exit,
|
||||
int need_uptime, int need_capacity,
|
||||
int is_internal);
|
||||
void circuit_reset_failure_count(int timeout);
|
||||
int connection_ap_handshake_attach_chosen_circuit(connection_t *conn,
|
||||
circuit_t *circ);
|
||||
origin_circuit_t *circ);
|
||||
int connection_ap_handshake_attach_circuit(connection_t *conn);
|
||||
|
||||
/********************************* command.c ***************************/
|
||||
@ -1733,9 +1763,10 @@ int connection_edge_end_errno(connection_t *conn, crypt_path_t *cpath_layer);
|
||||
int connection_edge_finished_flushing(connection_t *conn);
|
||||
int connection_edge_finished_connecting(connection_t *conn);
|
||||
|
||||
int connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ);
|
||||
int connection_ap_handshake_send_begin(connection_t *ap_conn,
|
||||
origin_circuit_t *circ);
|
||||
int connection_ap_handshake_send_resolve(connection_t *ap_conn,
|
||||
circuit_t *circ);
|
||||
origin_circuit_t *circ);
|
||||
|
||||
int connection_ap_make_bridge(char *address, uint16_t port);
|
||||
void connection_ap_handshake_socks_reply(connection_t *conn, char *reply,
|
||||
@ -1748,13 +1779,13 @@ void connection_ap_handshake_socks_resolved(connection_t *conn,
|
||||
int ttl);
|
||||
|
||||
int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
|
||||
int connection_exit_begin_resolve(cell_t *cell, circuit_t *circ);
|
||||
int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ);
|
||||
void connection_exit_connect(connection_t *conn);
|
||||
int connection_edge_is_rendezvous_stream(connection_t *conn);
|
||||
int connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit);
|
||||
void connection_ap_expire_beginning(void);
|
||||
void connection_ap_attach_pending(void);
|
||||
int connection_ap_detach_retriable(connection_t *conn, circuit_t *circ);
|
||||
int connection_ap_detach_retriable(connection_t *conn, origin_circuit_t *circ);
|
||||
|
||||
void addressmap_init(void);
|
||||
void addressmap_clean(time_t now);
|
||||
@ -1776,7 +1807,7 @@ const char *addressmap_register_virtual_address(int type, char *new_address);
|
||||
void addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
|
||||
time_t max_expires);
|
||||
int connection_ap_handshake_rewrite_and_attach(connection_t *conn,
|
||||
circuit_t *circ);
|
||||
origin_circuit_t *circ);
|
||||
|
||||
void set_exit_redirects(smartlist_t *lst);
|
||||
typedef enum hostname_type_t {
|
||||
@ -1865,7 +1896,8 @@ int connection_control_finished_flushing(connection_t *conn);
|
||||
int connection_control_reached_eof(connection_t *conn);
|
||||
int connection_control_process_inbuf(connection_t *conn);
|
||||
|
||||
int control_event_circuit_status(circuit_t *circ, circuit_status_event_t e);
|
||||
int control_event_circuit_status(origin_circuit_t *circ,
|
||||
circuit_status_event_t e);
|
||||
int control_event_stream_status(connection_t *conn, stream_status_event_t e);
|
||||
int control_event_or_conn_status(connection_t *conn, or_conn_status_event_t e);
|
||||
int control_event_bandwidth_used(uint32_t n_read, uint32_t n_written);
|
||||
@ -2026,9 +2058,9 @@ int tor_main(int argc, char *argv[]);
|
||||
|
||||
/********************************* onion.c ***************************/
|
||||
|
||||
int onion_pending_add(circuit_t *circ);
|
||||
circuit_t *onion_next_task(void);
|
||||
void onion_pending_remove(circuit_t *circ);
|
||||
int onion_pending_add(or_circuit_t *circ);
|
||||
or_circuit_t *onion_next_task(void);
|
||||
void onion_pending_remove(or_circuit_t *circ);
|
||||
|
||||
int onion_skin_create(crypto_pk_env_t *router_key,
|
||||
crypto_dh_env_t **handshake_state_out,
|
||||
@ -2148,22 +2180,23 @@ void rep_hist_free_all(void);
|
||||
|
||||
/********************************* rendclient.c ***************************/
|
||||
|
||||
void rend_client_introcirc_has_opened(circuit_t *circ);
|
||||
void rend_client_rendcirc_has_opened(circuit_t *circ);
|
||||
int rend_client_introduction_acked(circuit_t *circ, const char *request,
|
||||
void rend_client_introcirc_has_opened(origin_circuit_t *circ);
|
||||
void rend_client_rendcirc_has_opened(origin_circuit_t *circ);
|
||||
int rend_client_introduction_acked(origin_circuit_t *circ, const char *request,
|
||||
size_t request_len);
|
||||
void rend_client_refetch_renddesc(const char *query);
|
||||
int rend_client_remove_intro_point(extend_info_t *failed_intro,
|
||||
const char *query);
|
||||
int rend_client_rendezvous_acked(circuit_t *circ, const char *request,
|
||||
int rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request,
|
||||
size_t request_len);
|
||||
int rend_client_receive_rendezvous(circuit_t *circ, const char *request,
|
||||
int rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,
|
||||
size_t request_len);
|
||||
void rend_client_desc_here(const char *query);
|
||||
|
||||
extend_info_t *rend_client_get_random_intro(const char *query);
|
||||
|
||||
int rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc);
|
||||
int rend_client_send_introduction(origin_circuit_t *introcirc,
|
||||
origin_circuit_t *rendcirc);
|
||||
|
||||
/********************************* rendcommon.c ***************************/
|
||||
|
||||
@ -2228,25 +2261,27 @@ void rend_services_init(void);
|
||||
void rend_services_introduce(void);
|
||||
void rend_consider_services_upload(time_t now);
|
||||
|
||||
void rend_service_intro_has_opened(circuit_t *circuit);
|
||||
int rend_service_intro_established(circuit_t *circuit, const char *request,
|
||||
void rend_service_intro_has_opened(origin_circuit_t *circuit);
|
||||
int rend_service_intro_established(origin_circuit_t *circuit,
|
||||
const char *request,
|
||||
size_t request_len);
|
||||
void rend_service_rendezvous_has_opened(circuit_t *circuit);
|
||||
int rend_service_introduce(circuit_t *circuit, const char *request,
|
||||
void rend_service_rendezvous_has_opened(origin_circuit_t *circuit);
|
||||
int rend_service_introduce(origin_circuit_t *circuit, const char *request,
|
||||
size_t request_len);
|
||||
void rend_service_relaunch_rendezvous(circuit_t *oldcirc);
|
||||
int rend_service_set_connection_addr_port(connection_t *conn, circuit_t *circ);
|
||||
void rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc);
|
||||
int rend_service_set_connection_addr_port(connection_t *conn,
|
||||
origin_circuit_t *circ);
|
||||
void rend_service_dump_stats(int severity);
|
||||
void rend_service_free_all(void);
|
||||
|
||||
/********************************* rendmid.c *******************************/
|
||||
int rend_mid_establish_intro(circuit_t *circ, const char *request,
|
||||
int rend_mid_establish_intro(or_circuit_t *circ, const char *request,
|
||||
size_t request_len);
|
||||
int rend_mid_introduce(circuit_t *circ, const char *request,
|
||||
int rend_mid_introduce(or_circuit_t *circ, const char *request,
|
||||
size_t request_len);
|
||||
int rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
|
||||
int rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
|
||||
size_t request_len);
|
||||
int rend_mid_rendezvous(circuit_t *circ, const char *request,
|
||||
int rend_mid_rendezvous(or_circuit_t *circ, const char *request,
|
||||
size_t request_len);
|
||||
|
||||
/********************************* router.c ***************************/
|
||||
|
160
src/or/relay.c
160
src/or/relay.c
@ -191,18 +191,24 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
|
||||
if (cell_direction == CELL_DIRECTION_OUT) {
|
||||
cell->circ_id = circ->n_circ_id; /* switch it */
|
||||
conn = circ->n_conn;
|
||||
} else if (! CIRCUIT_IS_ORIGIN(circ)) {
|
||||
cell->circ_id = TO_OR_CIRCUIT(circ)->p_circ_id; /* switch it */
|
||||
conn = TO_OR_CIRCUIT(circ)->p_conn;
|
||||
} else {
|
||||
cell->circ_id = circ->p_circ_id; /* switch it */
|
||||
conn = circ->p_conn;
|
||||
// XXXX NM WARN.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!conn) {
|
||||
if (circ->rend_splice && cell_direction == CELL_DIRECTION_OUT) {
|
||||
// XXXX Can this splice stuff be done more cleanly?
|
||||
if (! CIRCUIT_IS_ORIGIN(circ) &&
|
||||
TO_OR_CIRCUIT(circ)->rend_splice &&
|
||||
cell_direction == CELL_DIRECTION_OUT) {
|
||||
or_circuit_t *splice = TO_OR_CIRCUIT(circ)->rend_splice;
|
||||
tor_assert(circ->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED);
|
||||
tor_assert(circ->rend_splice->purpose ==
|
||||
CIRCUIT_PURPOSE_REND_ESTABLISHED);
|
||||
cell->circ_id = circ->rend_splice->p_circ_id;
|
||||
if ((reason = circuit_receive_relay_cell(cell, circ->rend_splice,
|
||||
tor_assert(splice->_base.purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED);
|
||||
cell->circ_id = splice->p_circ_id;
|
||||
if ((reason = circuit_receive_relay_cell(cell, TO_CIRCUIT(splice),
|
||||
CELL_DIRECTION_IN)) < 0) {
|
||||
log_warn(LD_REND, "Error relaying cell across rendezvous; closing "
|
||||
"circuits");
|
||||
@ -244,7 +250,6 @@ static int
|
||||
relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
|
||||
crypt_path_t **layer_hint, char *recognized)
|
||||
{
|
||||
crypt_path_t *thishop;
|
||||
relay_header_t rh;
|
||||
|
||||
tor_assert(circ);
|
||||
@ -256,8 +261,8 @@ relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
|
||||
if (cell_direction == CELL_DIRECTION_IN) {
|
||||
if (CIRCUIT_IS_ORIGIN(circ)) { /* We're at the beginning of the circuit.
|
||||
* We'll want to do layered decrypts. */
|
||||
tor_assert(circ->cpath);
|
||||
thishop = circ->cpath;
|
||||
crypt_path_t *thishop, *cpath = TO_ORIGIN_CIRCUIT(circ)->cpath;
|
||||
thishop = cpath;
|
||||
if (thishop->state != CPATH_STATE_OPEN) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Relay cell before first created cell? Closing.");
|
||||
@ -280,11 +285,12 @@ relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
|
||||
}
|
||||
|
||||
thishop = thishop->next;
|
||||
} while (thishop != circ->cpath && thishop->state == CPATH_STATE_OPEN);
|
||||
} while (thishop != cpath && thishop->state == CPATH_STATE_OPEN);
|
||||
log_warn(LD_OR,"in-cell at OP not recognized. Closing.");
|
||||
return -1;
|
||||
} else { /* we're in the middle. Just one crypt. */
|
||||
if (relay_crypt_one_payload(circ->p_crypto, cell->payload, 1) < 0)
|
||||
if (relay_crypt_one_payload(TO_OR_CIRCUIT(circ)->p_crypto,
|
||||
cell->payload, 1) < 0)
|
||||
return -1;
|
||||
// log_fn(LOG_DEBUG,"Skipping recognized check, because we're not "
|
||||
// "the OP.");
|
||||
@ -292,13 +298,14 @@ relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
|
||||
} else /* cell_direction == CELL_DIRECTION_OUT */ {
|
||||
/* we're in the middle. Just one crypt. */
|
||||
|
||||
if (relay_crypt_one_payload(circ->n_crypto, cell->payload, 0) < 0)
|
||||
if (relay_crypt_one_payload(TO_OR_CIRCUIT(circ)->n_crypto,
|
||||
cell->payload, 0) < 0)
|
||||
return -1;
|
||||
|
||||
relay_header_unpack(&rh, cell->payload);
|
||||
if (rh.recognized == 0) {
|
||||
/* it's possibly recognized. have to check digest to be sure. */
|
||||
if (relay_digest_matches(circ->n_digest, cell)) {
|
||||
if (relay_digest_matches(TO_OR_CIRCUIT(circ)->n_digest, cell)) {
|
||||
*recognized = 1;
|
||||
return 0;
|
||||
}
|
||||
@ -307,7 +314,7 @@ relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Package a relay cell:
|
||||
/** Package a relay cell from an edge:
|
||||
* - Encrypt it to the right layer
|
||||
* - connection_or_write_cell_to_buf to the right conn
|
||||
*/
|
||||
@ -317,11 +324,11 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
crypt_path_t *layer_hint)
|
||||
{
|
||||
connection_t *conn; /* where to send the cell */
|
||||
crypt_path_t *thishop; /* counter for repeated crypts */
|
||||
|
||||
if (cell_direction == CELL_DIRECTION_OUT) {
|
||||
crypt_path_t *thishop; /* counter for repeated crypts */
|
||||
conn = circ->n_conn;
|
||||
if (!conn) {
|
||||
if (!CIRCUIT_IS_ORIGIN(circ) || !conn) {
|
||||
log_warn(LD_BUG,"outgoing relay cell has n_conn==NULL. Dropping.");
|
||||
return 0; /* just drop it */
|
||||
}
|
||||
@ -338,18 +345,20 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
}
|
||||
|
||||
thishop = thishop->prev;
|
||||
} while (thishop != circ->cpath->prev);
|
||||
} while (thishop != TO_ORIGIN_CIRCUIT(circ)->cpath->prev);
|
||||
|
||||
} else { /* incoming cell */
|
||||
conn = circ->p_conn;
|
||||
if (!conn) {
|
||||
or_circuit_t *or_circ;
|
||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||
/* XXXX RD This is a bug, right? */
|
||||
log_warn(LD_BUG,"incoming relay cell has p_conn==NULL. Dropping.");
|
||||
log_warn(LD_BUG,"incoming relay cell at origin circuit. Dropping.");
|
||||
assert_circuit_ok(circ);
|
||||
return 0; /* just drop it */
|
||||
}
|
||||
relay_set_digest(circ->p_digest, cell);
|
||||
if (relay_crypt_one_payload(circ->p_crypto, cell->payload, 1) < 0)
|
||||
or_circ = TO_OR_CIRCUIT(circ);
|
||||
conn = or_circ->p_conn;
|
||||
relay_set_digest(or_circ->p_digest, cell);
|
||||
if (relay_crypt_one_payload(or_circ->p_crypto, cell->payload, 1) < 0)
|
||||
return -1;
|
||||
}
|
||||
++stats_n_relay_cells_relayed;
|
||||
@ -375,25 +384,30 @@ relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
|
||||
* that we allow rendezvous *to* an OP.
|
||||
*/
|
||||
|
||||
for (tmpconn = circ->n_streams; tmpconn; tmpconn=tmpconn->next_stream) {
|
||||
if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) {
|
||||
log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
|
||||
if (cell_direction == CELL_DIRECTION_OUT ||
|
||||
connection_edge_is_rendezvous_stream(tmpconn))
|
||||
if (CIRCUIT_IS_ORIGIN(circ)) {
|
||||
for (tmpconn = TO_ORIGIN_CIRCUIT(circ)->p_streams; tmpconn;
|
||||
tmpconn=tmpconn->next_stream) {
|
||||
if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) {
|
||||
log_debug(LD_APP,"found conn for stream %d.", rh.stream_id);
|
||||
return tmpconn;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (tmpconn = circ->p_streams; tmpconn; tmpconn=tmpconn->next_stream) {
|
||||
if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) {
|
||||
log_debug(LD_APP,"found conn for stream %d.", rh.stream_id);
|
||||
return tmpconn;
|
||||
} else {
|
||||
for (tmpconn = TO_OR_CIRCUIT(circ)->n_streams; tmpconn;
|
||||
tmpconn=tmpconn->next_stream) {
|
||||
if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) {
|
||||
log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
|
||||
if (cell_direction == CELL_DIRECTION_OUT ||
|
||||
connection_edge_is_rendezvous_stream(tmpconn))
|
||||
return tmpconn;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (tmpconn = circ->resolving_streams; tmpconn;
|
||||
tmpconn=tmpconn->next_stream) {
|
||||
if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) {
|
||||
log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
|
||||
return tmpconn;
|
||||
for (tmpconn = TO_OR_CIRCUIT(circ)->resolving_streams; tmpconn;
|
||||
tmpconn=tmpconn->next_stream) {
|
||||
if (rh.stream_id == tmpconn->stream_id && !tmpconn->marked_for_close) {
|
||||
log_debug(LD_EXIT,"found conn for stream %d.", rh.stream_id);
|
||||
return tmpconn;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL; /* probably a begin relay cell */
|
||||
@ -445,6 +459,7 @@ connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
|
||||
cell_t cell;
|
||||
relay_header_t rh;
|
||||
int cell_direction;
|
||||
/* XXXX NM Split this function into a separate versions per circuit type? */
|
||||
|
||||
if (fromconn && fromconn->marked_for_close) {
|
||||
log_warn(LD_BUG,
|
||||
@ -471,9 +486,11 @@ connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
|
||||
if (cpath_layer) {
|
||||
cell.circ_id = circ->n_circ_id;
|
||||
cell_direction = CELL_DIRECTION_OUT;
|
||||
} else {
|
||||
cell.circ_id = circ->p_circ_id;
|
||||
} else if (! CIRCUIT_IS_ORIGIN(circ)) {
|
||||
cell.circ_id = TO_OR_CIRCUIT(circ)->p_circ_id;
|
||||
cell_direction = CELL_DIRECTION_IN;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&rh, 0, sizeof(rh));
|
||||
@ -647,7 +664,7 @@ edge_reason_is_retriable(int reason)
|
||||
*/
|
||||
static int
|
||||
connection_edge_process_end_not_open(
|
||||
relay_header_t *rh, cell_t *cell, circuit_t *circ,
|
||||
relay_header_t *rh, cell_t *cell, origin_circuit_t *circ,
|
||||
connection_t *conn, crypt_path_t *layer_hint)
|
||||
{
|
||||
struct in_addr in;
|
||||
@ -716,8 +733,8 @@ connection_edge_process_end_not_open(
|
||||
< MAX_RESOLVE_FAILURES) {
|
||||
/* We haven't retried too many times; reattach the connection. */
|
||||
circuit_log_path(LOG_INFO,LD_APP,circ);
|
||||
tor_assert(circ->timestamp_dirty);
|
||||
circ->timestamp_dirty -= get_options()->MaxCircuitDirtiness;
|
||||
tor_assert(circ->_base.timestamp_dirty);
|
||||
circ->_base.timestamp_dirty -= get_options()->MaxCircuitDirtiness;
|
||||
|
||||
if (conn->chosen_exit_optional) { /* stop wanting a specific exit */
|
||||
conn->chosen_exit_optional = 0;
|
||||
@ -780,11 +797,17 @@ connection_edge_process_relay_cell_not_open(
|
||||
relay_header_t *rh, cell_t *cell, circuit_t *circ,
|
||||
connection_t *conn, crypt_path_t *layer_hint)
|
||||
{
|
||||
if (rh->command == RELAY_COMMAND_END)
|
||||
return connection_edge_process_end_not_open(rh, cell, circ, conn,
|
||||
layer_hint);
|
||||
if (rh->command == RELAY_COMMAND_END) {
|
||||
if (CIRCUIT_IS_ORIGIN(circ))
|
||||
return connection_edge_process_end_not_open(rh, cell,
|
||||
TO_ORIGIN_CIRCUIT(circ), conn,
|
||||
layer_hint);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (conn->type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_CONNECTED) {
|
||||
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
||||
if (conn->state != AP_CONN_STATE_CONNECT_WAIT) {
|
||||
log_warn(LD_APP,"Got 'connected' while not in state connect_wait. "
|
||||
"Dropping.");
|
||||
@ -812,7 +835,7 @@ connection_edge_process_relay_cell_not_open(
|
||||
client_dns_set_addressmap(conn->socks_request->address, addr,
|
||||
conn->chosen_exit_name, ttl);
|
||||
}
|
||||
circuit_log_path(LOG_INFO,LD_APP,circ);
|
||||
circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ));
|
||||
connection_ap_handshake_socks_reply(conn, NULL, 0, SOCKS5_SUCCEEDED);
|
||||
/* handle anything that might have queued */
|
||||
if (connection_edge_package_raw_inbuf(conn, 1) < 0) {
|
||||
@ -967,16 +990,6 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
if (conn->socks_request && !conn->socks_request->has_finished)
|
||||
log_warn(LD_BUG,
|
||||
"Bug: open stream hasn't sent socks answer yet? Closing.");
|
||||
#ifdef HALF_OPEN
|
||||
conn->done_sending = 1;
|
||||
shutdown(conn->s, 1); /* XXX check return; refactor NM */
|
||||
if (conn->done_receiving) {
|
||||
/* We just *got* an end; no reason to send one. */
|
||||
conn->has_sent_end = 1;
|
||||
connection_mark_for_close(conn);
|
||||
conn->hold_open_until_flushed = 1;
|
||||
}
|
||||
#else
|
||||
/* We just *got* an end; no reason to send one. */
|
||||
conn->has_sent_end = 1;
|
||||
if (!conn->marked_for_close) {
|
||||
@ -985,7 +998,6 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
connection_mark_for_close(conn);
|
||||
conn->hold_open_until_flushed = 1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
case RELAY_COMMAND_EXTEND:
|
||||
if (conn) {
|
||||
@ -1000,12 +1012,13 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
return 0;
|
||||
}
|
||||
log_debug(domain,"Got an extended cell! Yay.");
|
||||
if ((reason = circuit_finish_handshake(circ, CELL_CREATED,
|
||||
if ((reason = circuit_finish_handshake(TO_ORIGIN_CIRCUIT(circ),
|
||||
CELL_CREATED,
|
||||
cell->payload+RELAY_HEADER_SIZE)) < 0) {
|
||||
log_warn(domain,"circuit_finish_handshake failed.");
|
||||
return reason;
|
||||
}
|
||||
if ((reason=circuit_send_next_onion_skin(circ))<0) {
|
||||
if ((reason=circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ)))<0) {
|
||||
log_info(domain,"circuit_send_next_onion_skin() failed.");
|
||||
return reason;
|
||||
}
|
||||
@ -1018,7 +1031,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
if (circ->n_conn) {
|
||||
uint8_t reason = *(uint8_t*)(cell->payload + RELAY_HEADER_SIZE);
|
||||
connection_or_send_destroy(circ->n_circ_id, circ->n_conn, reason);
|
||||
circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED);
|
||||
circuit_set_n_circid_orconn(circ, 0, NULL);
|
||||
}
|
||||
log_debug(LD_EXIT, "Processed 'truncate', replying.");
|
||||
{
|
||||
@ -1033,7 +1046,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
log_warn(LD_EXIT,"'truncated' unsupported at non-origin. Dropping.");
|
||||
return 0;
|
||||
}
|
||||
circuit_truncated(circ, layer_hint);
|
||||
circuit_truncated(TO_ORIGIN_CIRCUIT(circ), layer_hint);
|
||||
return 0;
|
||||
case RELAY_COMMAND_CONNECTED:
|
||||
if (conn) {
|
||||
@ -1083,7 +1096,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
circ->purpose);
|
||||
return 0;
|
||||
}
|
||||
connection_exit_begin_resolve(cell, circ);
|
||||
connection_exit_begin_resolve(cell, TO_OR_CIRCUIT(circ));
|
||||
return 0;
|
||||
case RELAY_COMMAND_RESOLVED:
|
||||
if (conn) {
|
||||
@ -1252,10 +1265,12 @@ circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
|
||||
|
||||
log_debug(layer_hint?LD_APP:LD_EXIT,"resuming");
|
||||
|
||||
/* have to check both n_streams and p_streams, to handle rendezvous */
|
||||
if (circuit_resume_edge_reading_helper(circ->n_streams, circ, layer_hint)
|
||||
>= 0)
|
||||
circuit_resume_edge_reading_helper(circ->p_streams, circ, layer_hint);
|
||||
if (CIRCUIT_IS_ORIGIN(circ))
|
||||
circuit_resume_edge_reading_helper(TO_ORIGIN_CIRCUIT(circ)->p_streams,
|
||||
circ, layer_hint);
|
||||
else
|
||||
circuit_resume_edge_reading_helper(TO_OR_CIRCUIT(circ)->n_streams,
|
||||
circ, layer_hint);
|
||||
}
|
||||
|
||||
/** A helper function for circuit_resume_edge_reading() above.
|
||||
@ -1304,11 +1319,12 @@ circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
|
||||
unsigned domain = layer_hint ? LD_APP : LD_EXIT;
|
||||
|
||||
if (!layer_hint) {
|
||||
or_circuit_t *or_circ = TO_OR_CIRCUIT(circ);
|
||||
log_debug(domain,"considering circ->package_window %d",
|
||||
circ->package_window);
|
||||
if (circ->package_window <= 0) {
|
||||
log_debug(domain,"yes, not-at-origin. stopped.");
|
||||
for (conn = circ->n_streams; conn; conn=conn->next_stream)
|
||||
for (conn = or_circ->n_streams; conn; conn=conn->next_stream)
|
||||
connection_stop_reading(conn);
|
||||
return 1;
|
||||
}
|
||||
@ -1319,10 +1335,14 @@ circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
|
||||
layer_hint->package_window);
|
||||
if (layer_hint->package_window <= 0) {
|
||||
log_debug(domain,"yes, at-origin. stopped.");
|
||||
#if 0
|
||||
// XXXX NM DEAD CODE.
|
||||
for (conn = circ->n_streams; conn; conn=conn->next_stream)
|
||||
if (conn->cpath_layer == layer_hint)
|
||||
connection_stop_reading(conn);
|
||||
for (conn = circ->p_streams; conn; conn=conn->next_stream)
|
||||
#endif
|
||||
for (conn = TO_ORIGIN_CIRCUIT(circ)->p_streams; conn;
|
||||
conn=conn->next_stream)
|
||||
if (conn->cpath_layer == layer_hint)
|
||||
connection_stop_reading(conn);
|
||||
return 1;
|
||||
|
@ -14,10 +14,9 @@ const char rendclient_c_id[] =
|
||||
/** Called when we've established a circuit to an introduction point:
|
||||
* send the introduction request. */
|
||||
void
|
||||
rend_client_introcirc_has_opened(circuit_t *circ)
|
||||
rend_client_introcirc_has_opened(origin_circuit_t *circ)
|
||||
{
|
||||
tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
|
||||
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
||||
tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
|
||||
tor_assert(circ->cpath);
|
||||
|
||||
log_info(LD_REND,"introcirc is open");
|
||||
@ -28,19 +27,19 @@ rend_client_introcirc_has_opened(circuit_t *circ)
|
||||
* it fails, mark the circ for close and return -1. else return 0.
|
||||
*/
|
||||
static int
|
||||
rend_client_send_establish_rendezvous(circuit_t *circ)
|
||||
rend_client_send_establish_rendezvous(origin_circuit_t *circ)
|
||||
{
|
||||
tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
|
||||
tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
|
||||
log_info(LD_REND, "Sending an ESTABLISH_RENDEZVOUS cell");
|
||||
|
||||
if (crypto_rand(circ->rend_cookie, REND_COOKIE_LEN) < 0) {
|
||||
if (crypto_rand(circ->_base.rend_cookie, REND_COOKIE_LEN) < 0) {
|
||||
log_warn(LD_BUG, "Internal error: Couldn't produce random cookie.");
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
|
||||
return -1;
|
||||
}
|
||||
if (connection_edge_send_command(NULL,circ,
|
||||
if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
|
||||
RELAY_COMMAND_ESTABLISH_RENDEZVOUS,
|
||||
circ->rend_cookie, REND_COOKIE_LEN,
|
||||
circ->_base.rend_cookie, REND_COOKIE_LEN,
|
||||
circ->cpath->prev)<0) {
|
||||
/* circ is already marked for close */
|
||||
log_warn(LD_GENERAL, "Couldn't send ESTABLISH_RENDEZVOUS cell");
|
||||
@ -54,7 +53,8 @@ rend_client_send_establish_rendezvous(circuit_t *circ)
|
||||
* down introcirc if possible.
|
||||
*/
|
||||
int
|
||||
rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc)
|
||||
rend_client_send_introduction(origin_circuit_t *introcirc,
|
||||
origin_circuit_t *rendcirc)
|
||||
{
|
||||
size_t payload_len;
|
||||
int r;
|
||||
@ -64,15 +64,15 @@ rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc)
|
||||
crypt_path_t *cpath;
|
||||
off_t dh_offset;
|
||||
|
||||
tor_assert(introcirc->purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
|
||||
tor_assert(rendcirc->purpose == CIRCUIT_PURPOSE_C_REND_READY);
|
||||
tor_assert(!rend_cmp_service_ids(introcirc->rend_query,
|
||||
rendcirc->rend_query));
|
||||
tor_assert(introcirc->_base.purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
|
||||
tor_assert(rendcirc->_base.purpose == CIRCUIT_PURPOSE_C_REND_READY);
|
||||
tor_assert(!rend_cmp_service_ids(introcirc->_base.rend_query,
|
||||
rendcirc->_base.rend_query));
|
||||
|
||||
if (rend_cache_lookup_entry(introcirc->rend_query, -1, &entry) < 1) {
|
||||
if (rend_cache_lookup_entry(introcirc->_base.rend_query, -1, &entry) < 1) {
|
||||
log_warn(LD_REND,
|
||||
"query %s didn't have valid rend desc in cache. Failing.",
|
||||
escaped_safe_str(introcirc->rend_query));
|
||||
escaped_safe_str(introcirc->_base.rend_query));
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -111,13 +111,15 @@ rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc)
|
||||
klen = crypto_pk_asn1_encode(extend_info->onion_key, tmp+7+DIGEST_LEN+2,
|
||||
sizeof(tmp)-(7+DIGEST_LEN+2));
|
||||
set_uint16(tmp+7+DIGEST_LEN, htons(klen));
|
||||
memcpy(tmp+7+DIGEST_LEN+2+klen, rendcirc->rend_cookie, REND_COOKIE_LEN);
|
||||
memcpy(tmp+7+DIGEST_LEN+2+klen, rendcirc->_base.rend_cookie,
|
||||
REND_COOKIE_LEN);
|
||||
dh_offset = 7+DIGEST_LEN+2+klen+REND_COOKIE_LEN;
|
||||
} else {
|
||||
/* Version 0. */
|
||||
strncpy(tmp, rendcirc->build_state->chosen_exit->nickname,
|
||||
(MAX_NICKNAME_LEN+1)); /* nul pads */
|
||||
memcpy(tmp+MAX_NICKNAME_LEN+1, rendcirc->rend_cookie, REND_COOKIE_LEN);
|
||||
memcpy(tmp+MAX_NICKNAME_LEN+1, rendcirc->_base.rend_cookie,
|
||||
REND_COOKIE_LEN);
|
||||
dh_offset = MAX_NICKNAME_LEN+1+REND_COOKIE_LEN;
|
||||
}
|
||||
|
||||
@ -141,7 +143,7 @@ rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc)
|
||||
tor_assert(DIGEST_LEN + r <= RELAY_PAYLOAD_SIZE); /* we overran something */
|
||||
payload_len = DIGEST_LEN + r;
|
||||
|
||||
if (connection_edge_send_command(NULL, introcirc,
|
||||
if (connection_edge_send_command(NULL, TO_CIRCUIT(introcirc),
|
||||
RELAY_COMMAND_INTRODUCE1,
|
||||
payload, payload_len,
|
||||
introcirc->cpath->prev)<0) {
|
||||
@ -151,22 +153,21 @@ rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc)
|
||||
}
|
||||
|
||||
/* Now, we wait for an ACK or NAK on this circuit. */
|
||||
introcirc->purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
|
||||
introcirc->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
circuit_mark_for_close(introcirc, END_CIRC_AT_ORIGIN);
|
||||
circuit_mark_for_close(rendcirc, END_CIRC_AT_ORIGIN);
|
||||
circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_AT_ORIGIN);
|
||||
circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_AT_ORIGIN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Called when a rendezvous circuit is open; sends a establish
|
||||
* rendezvous circuit as appropriate. */
|
||||
void
|
||||
rend_client_rendcirc_has_opened(circuit_t *circ)
|
||||
rend_client_rendcirc_has_opened(origin_circuit_t *circ)
|
||||
{
|
||||
tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
|
||||
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
||||
tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND);
|
||||
|
||||
log_info(LD_REND,"rendcirc is open");
|
||||
|
||||
@ -179,17 +180,17 @@ rend_client_rendcirc_has_opened(circuit_t *circ)
|
||||
/** Called when get an ACK or a NAK for a REND_INTRODUCE1 cell.
|
||||
*/
|
||||
int
|
||||
rend_client_introduction_acked(circuit_t *circ,
|
||||
rend_client_introduction_acked(origin_circuit_t *circ,
|
||||
const char *request, size_t request_len)
|
||||
{
|
||||
circuit_t *rendcirc;
|
||||
(void) request; // XXXX Use this.
|
||||
|
||||
if (circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
|
||||
if (circ->_base.purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
|
||||
log_warn(LD_PROTOCOL,
|
||||
"Received REND_INTRODUCE_ACK on unexpected circuit %d.",
|
||||
circ->n_circ_id);
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
circ->_base.n_circ_id);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -203,40 +204,40 @@ rend_client_introduction_acked(circuit_t *circ,
|
||||
*/
|
||||
log_info(LD_REND,"Received ack. Telling rend circ...");
|
||||
rendcirc = circuit_get_by_rend_query_and_purpose(
|
||||
circ->rend_query, CIRCUIT_PURPOSE_C_REND_READY);
|
||||
circ->_base.rend_query, CIRCUIT_PURPOSE_C_REND_READY);
|
||||
if (rendcirc) { /* remember the ack */
|
||||
rendcirc->purpose = CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED;
|
||||
} else {
|
||||
log_info(LD_REND,"...Found no rend circ. Dropping on the floor.");
|
||||
}
|
||||
/* close the circuit: we won't need it anymore. */
|
||||
circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACKED;
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
circ->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACKED;
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
|
||||
} else {
|
||||
/* It's a NAK; the introduction point didn't relay our request. */
|
||||
circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
|
||||
circ->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
|
||||
/* Remove this intro point from the set of viable introduction
|
||||
* points. If any remain, extend to a new one and try again.
|
||||
* If none remain, refetch the service descriptor.
|
||||
*/
|
||||
if (rend_client_remove_intro_point(circ->build_state->chosen_exit,
|
||||
circ->rend_query) > 0) {
|
||||
circ->_base.rend_query) > 0) {
|
||||
/* There are introduction points left. Re-extend the circuit to
|
||||
* another intro point and try again. */
|
||||
extend_info_t *extend_info;
|
||||
int result;
|
||||
extend_info = rend_client_get_random_intro(circ->rend_query);
|
||||
extend_info = rend_client_get_random_intro(circ->_base.rend_query);
|
||||
if (!extend_info) {
|
||||
log_warn(LD_REND, "No introduction points left for %s. Closing.",
|
||||
escaped_safe_str(circ->rend_query));
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
escaped_safe_str(circ->_base.rend_query));
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
|
||||
return -1;
|
||||
}
|
||||
log_info(LD_REND,
|
||||
"Got nack for %s from %s. Re-extending circ %d, "
|
||||
"this time to %s.",
|
||||
escaped_safe_str(circ->rend_query),
|
||||
circ->build_state->chosen_exit->nickname, circ->n_circ_id,
|
||||
escaped_safe_str(circ->_base.rend_query),
|
||||
circ->build_state->chosen_exit->nickname, circ->_base.n_circ_id,
|
||||
extend_info->nickname);
|
||||
result = circuit_extend_to_new_exit(circ, extend_info);
|
||||
extend_info_free(extend_info);
|
||||
@ -340,38 +341,38 @@ rend_client_remove_intro_point(extend_info_t *failed_intro, const char *query)
|
||||
* the circuit to C_REND_READY.
|
||||
*/
|
||||
int
|
||||
rend_client_rendezvous_acked(circuit_t *circ, const char *request,
|
||||
rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request,
|
||||
size_t request_len)
|
||||
{
|
||||
(void) request;
|
||||
(void) request_len;
|
||||
/* we just got an ack for our establish-rendezvous. switch purposes. */
|
||||
if (circ->purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND) {
|
||||
if (circ->_base.purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND) {
|
||||
log_warn(LD_PROTOCOL,"Got a rendezvous ack when we weren't expecting one. "
|
||||
"Closing circ.");
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
|
||||
return -1;
|
||||
}
|
||||
log_info(LD_REND,"Got rendezvous ack. This circuit is now ready for "
|
||||
"rendezvous.");
|
||||
circ->purpose = CIRCUIT_PURPOSE_C_REND_READY;
|
||||
circ->_base.purpose = CIRCUIT_PURPOSE_C_REND_READY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Bob sent us a rendezvous cell; join the circuits. */
|
||||
int
|
||||
rend_client_receive_rendezvous(circuit_t *circ, const char *request,
|
||||
rend_client_receive_rendezvous(origin_circuit_t *circ, const char *request,
|
||||
size_t request_len)
|
||||
{
|
||||
crypt_path_t *hop;
|
||||
char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN];
|
||||
|
||||
if ((circ->purpose != CIRCUIT_PURPOSE_C_REND_READY &&
|
||||
circ->purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED)
|
||||
if ((circ->_base.purpose != CIRCUIT_PURPOSE_C_REND_READY &&
|
||||
circ->_base.purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED)
|
||||
|| !circ->build_state->pending_final_cpath) {
|
||||
log_warn(LD_PROTOCOL,"Got rendezvous2 cell from hidden service, but not "
|
||||
"expecting it. Closing.");
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -405,7 +406,7 @@ rend_client_receive_rendezvous(circuit_t *circ, const char *request,
|
||||
hop->dh_handshake_state = NULL;
|
||||
|
||||
/* All is well. Extend the circuit. */
|
||||
circ->purpose = CIRCUIT_PURPOSE_C_REND_JOINED;
|
||||
circ->_base.purpose = CIRCUIT_PURPOSE_C_REND_JOINED;
|
||||
hop->state = CPATH_STATE_OPEN;
|
||||
/* set the windows to default. these are the windows
|
||||
* that alice thinks bob has.
|
||||
@ -417,7 +418,7 @@ rend_client_receive_rendezvous(circuit_t *circ, const char *request,
|
||||
circ->build_state->pending_final_cpath = NULL; /* prevent double-free */
|
||||
return 0;
|
||||
err:
|
||||
circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -432,34 +432,41 @@ void
|
||||
rend_process_relay_cell(circuit_t *circ, int command, size_t length,
|
||||
const char *payload)
|
||||
{
|
||||
or_circuit_t *or_circ = NULL;
|
||||
origin_circuit_t *origin_circ = NULL;
|
||||
int r;
|
||||
if (CIRCUIT_IS_ORIGIN(circ))
|
||||
origin_circ = TO_ORIGIN_CIRCUIT(circ);
|
||||
else
|
||||
or_circ = TO_OR_CIRCUIT(circ);
|
||||
|
||||
switch (command) {
|
||||
case RELAY_COMMAND_ESTABLISH_INTRO:
|
||||
r = rend_mid_establish_intro(circ,payload,length);
|
||||
r = rend_mid_establish_intro(or_circ,payload,length);
|
||||
break;
|
||||
case RELAY_COMMAND_ESTABLISH_RENDEZVOUS:
|
||||
r = rend_mid_establish_rendezvous(circ,payload,length);
|
||||
r = rend_mid_establish_rendezvous(or_circ,payload,length);
|
||||
break;
|
||||
case RELAY_COMMAND_INTRODUCE1:
|
||||
r = rend_mid_introduce(circ,payload,length);
|
||||
r = rend_mid_introduce(or_circ,payload,length);
|
||||
break;
|
||||
case RELAY_COMMAND_INTRODUCE2:
|
||||
r = rend_service_introduce(circ,payload,length);
|
||||
r = rend_service_introduce(origin_circ,payload,length);
|
||||
break;
|
||||
case RELAY_COMMAND_INTRODUCE_ACK:
|
||||
r = rend_client_introduction_acked(circ,payload,length);
|
||||
r = rend_client_introduction_acked(origin_circ,payload,length);
|
||||
break;
|
||||
case RELAY_COMMAND_RENDEZVOUS1:
|
||||
r = rend_mid_rendezvous(circ,payload,length);
|
||||
r = rend_mid_rendezvous(or_circ,payload,length);
|
||||
break;
|
||||
case RELAY_COMMAND_RENDEZVOUS2:
|
||||
r = rend_client_receive_rendezvous(circ,payload,length);
|
||||
r = rend_client_receive_rendezvous(origin_circ,payload,length);
|
||||
break;
|
||||
case RELAY_COMMAND_INTRO_ESTABLISHED:
|
||||
r = rend_service_intro_established(circ,payload,length);
|
||||
r = rend_service_intro_established(origin_circ,payload,length);
|
||||
break;
|
||||
case RELAY_COMMAND_RENDEZVOUS_ESTABLISHED:
|
||||
r = rend_client_rendezvous_acked(circ,payload,length);
|
||||
r = rend_client_rendezvous_acked(origin_circ,payload,length);
|
||||
break;
|
||||
default:
|
||||
tor_assert(0);
|
||||
|
@ -15,7 +15,7 @@ const char rendmid_c_id[] =
|
||||
* setting the circuit's purpose and service pk digest.
|
||||
*/
|
||||
int
|
||||
rend_mid_establish_intro(circuit_t *circ, const char *request,
|
||||
rend_mid_establish_intro(or_circuit_t *circ, const char *request,
|
||||
size_t request_len)
|
||||
{
|
||||
crypto_pk_env_t *pk = NULL;
|
||||
@ -31,7 +31,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
|
||||
"Received an ESTABLISH_INTRO request on circuit %d",
|
||||
circ->p_circ_id);
|
||||
|
||||
if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) {
|
||||
if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
|
||||
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
|
||||
"Rejecting ESTABLISH_INTRO on non-OR or non-edge circuit.");
|
||||
reason = END_CIRC_REASON_TORPROTOCOL;
|
||||
@ -89,13 +89,13 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
|
||||
c = NULL;
|
||||
while ((c = circuit_get_next_by_pk_and_purpose(
|
||||
c,pk_digest,CIRCUIT_PURPOSE_INTRO_POINT))) {
|
||||
log_info(LD_REND, "Replacing old circuit %d for service %s",
|
||||
c->p_circ_id, safe_str(serviceid));
|
||||
log_info(LD_REND, "Replacing old circuit for service %s",
|
||||
safe_str(serviceid));
|
||||
circuit_mark_for_close(c, END_CIRC_REASON_REQUESTED);
|
||||
}
|
||||
|
||||
/* Acknowledge the request. */
|
||||
if (connection_edge_send_command(NULL,circ,
|
||||
if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
|
||||
RELAY_COMMAND_INTRO_ESTABLISHED,
|
||||
"", 0, NULL)<0) {
|
||||
log_info(LD_GENERAL, "Couldn't send INTRO_ESTABLISHED cell.");
|
||||
@ -103,8 +103,8 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
|
||||
}
|
||||
|
||||
/* Now, set up this circuit. */
|
||||
circ->purpose = CIRCUIT_PURPOSE_INTRO_POINT;
|
||||
memcpy(circ->rend_pk_digest, pk_digest, DIGEST_LEN);
|
||||
circ->_base.purpose = CIRCUIT_PURPOSE_INTRO_POINT;
|
||||
memcpy(circ->_base.rend_pk_digest, pk_digest, DIGEST_LEN);
|
||||
|
||||
log_info(LD_REND,
|
||||
"Established introduction point on circuit %d for service %s",
|
||||
@ -116,7 +116,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
|
||||
reason = END_CIRC_REASON_TORPROTOCOL;
|
||||
err:
|
||||
if (pk) crypto_free_pk_env(pk);
|
||||
circuit_mark_for_close(circ, reason);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), reason);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -125,20 +125,23 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
|
||||
* INTRODUCE2 cell.
|
||||
*/
|
||||
int
|
||||
rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len)
|
||||
rend_mid_introduce(or_circuit_t *circ, const char *request, size_t request_len)
|
||||
{
|
||||
circuit_t *intro_circ;
|
||||
char serviceid[REND_SERVICE_ID_LEN+1];
|
||||
char nak_body[1];
|
||||
|
||||
if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) {
|
||||
if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
|
||||
log_warn(LD_PROTOCOL,
|
||||
"Rejecting INTRODUCE1 on non-OR or non-edge circuit %d.",
|
||||
circ->p_circ_id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* change to MAX_HEX_NICKNAME_LEN once 0.0.9.x is obsolete */
|
||||
/* We could change this to MAX_HEX_NICKNAME_LEN now that 0.0.9.x is
|
||||
* obsolete; however, there isn't much reason to do so, and we're going
|
||||
* to revise this protocol anyway.
|
||||
*/
|
||||
if (request_len < (DIGEST_LEN+(MAX_NICKNAME_LEN+1)+REND_COOKIE_LEN+
|
||||
DH_KEY_LEN+CIPHER_KEY_LEN+PKCS1_OAEP_PADDING_OVERHEAD)) {
|
||||
log_warn(LD_PROTOCOL, "Impossibly short INTRODUCE1 cell on circuit %d; "
|
||||
@ -152,7 +155,7 @@ rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len)
|
||||
/* The first 20 bytes are all we look at: they have a hash of Bob's PK. */
|
||||
intro_circ = circuit_get_next_by_pk_and_purpose(
|
||||
NULL, request, CIRCUIT_PURPOSE_INTRO_POINT);
|
||||
if (!intro_circ) {
|
||||
if (!intro_circ || CIRCUIT_IS_ORIGIN(intro_circ)) {
|
||||
log_info(LD_REND,
|
||||
"No intro circ found for INTRODUCE1 cell (%s) from circuit %d; "
|
||||
"responding with nack.",
|
||||
@ -163,7 +166,8 @@ rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len)
|
||||
log_info(LD_REND,
|
||||
"Sending introduction request for service %s "
|
||||
"from circ %d to circ %d",
|
||||
safe_str(serviceid), circ->p_circ_id, intro_circ->p_circ_id);
|
||||
safe_str(serviceid), circ->p_circ_id,
|
||||
TO_OR_CIRCUIT(intro_circ)->p_circ_id);
|
||||
|
||||
/* Great. Now we just relay the cell down the circuit. */
|
||||
if (connection_edge_send_command(NULL, intro_circ,
|
||||
@ -174,10 +178,11 @@ rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len)
|
||||
goto err;
|
||||
}
|
||||
/* And sent an ack down Alice's circuit. Empty body means succeeded. */
|
||||
if (connection_edge_send_command(NULL,circ,RELAY_COMMAND_INTRODUCE_ACK,
|
||||
if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
|
||||
RELAY_COMMAND_INTRODUCE_ACK,
|
||||
NULL,0,NULL)) {
|
||||
log_warn(LD_GENERAL, "Unable to send INTRODUCE_ACK cell to Tor client.");
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -185,11 +190,12 @@ rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len)
|
||||
err:
|
||||
/* Send the client an NACK */
|
||||
nak_body[0] = 1;
|
||||
if (connection_edge_send_command(NULL,circ,RELAY_COMMAND_INTRODUCE_ACK,
|
||||
if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
|
||||
RELAY_COMMAND_INTRODUCE_ACK,
|
||||
nak_body, 1, NULL)) {
|
||||
log_warn(LD_GENERAL, "Unable to send NAK to Tor client.");
|
||||
/* Is this right? */
|
||||
circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -198,13 +204,13 @@ rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len)
|
||||
* rendezvous cookie.
|
||||
*/
|
||||
int
|
||||
rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
|
||||
rend_mid_establish_rendezvous(or_circuit_t *circ, const char *request,
|
||||
size_t request_len)
|
||||
{
|
||||
char hexid[9];
|
||||
int reason = END_CIRC_REASON_TORPROTOCOL;
|
||||
|
||||
if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) {
|
||||
if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
|
||||
log_warn(LD_PROTOCOL,
|
||||
"Tried to establish rendezvous on non-OR or non-edge circuit.");
|
||||
goto err;
|
||||
@ -222,7 +228,7 @@ rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
|
||||
}
|
||||
|
||||
/* Acknowledge the request. */
|
||||
if (connection_edge_send_command(NULL,circ,
|
||||
if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
|
||||
RELAY_COMMAND_RENDEZVOUS_ESTABLISHED,
|
||||
"", 0, NULL)<0) {
|
||||
log_warn(LD_PROTOCOL, "Couldn't send RENDEZVOUS_ESTABLISHED cell.");
|
||||
@ -230,8 +236,8 @@ rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
|
||||
goto err;
|
||||
}
|
||||
|
||||
circ->purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
|
||||
memcpy(circ->rend_cookie, request, REND_COOKIE_LEN);
|
||||
circ->_base.purpose = CIRCUIT_PURPOSE_REND_POINT_WAITING;
|
||||
memcpy(circ->_base.rend_cookie, request, REND_COOKIE_LEN);
|
||||
|
||||
base16_encode(hexid,9,request,4);
|
||||
|
||||
@ -241,7 +247,7 @@ rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
|
||||
|
||||
return 0;
|
||||
err:
|
||||
circuit_mark_for_close(circ, reason);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), reason);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -250,9 +256,10 @@ rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
|
||||
* connecting the two circuits.
|
||||
*/
|
||||
int
|
||||
rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len)
|
||||
rend_mid_rendezvous(or_circuit_t *circ, const char *request,
|
||||
size_t request_len)
|
||||
{
|
||||
circuit_t *rend_circ;
|
||||
or_circuit_t *rend_circ;
|
||||
char hexid[9];
|
||||
int reason = END_CIRC_REASON_INTERNAL;
|
||||
base16_encode(hexid,9,request,request_len<4?request_len:4);
|
||||
@ -263,7 +270,7 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len)
|
||||
circ->p_circ_id, hexid);
|
||||
}
|
||||
|
||||
if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) {
|
||||
if (circ->_base.purpose != CIRCUIT_PURPOSE_OR || circ->_base.n_conn) {
|
||||
log_info(LD_REND,
|
||||
"Tried to complete rendezvous on non-OR or non-edge circuit %d.",
|
||||
circ->p_circ_id);
|
||||
@ -289,7 +296,7 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len)
|
||||
}
|
||||
|
||||
/* Send the RENDEZVOUS2 cell to Alice. */
|
||||
if (connection_edge_send_command(NULL, rend_circ,
|
||||
if (connection_edge_send_command(NULL, TO_CIRCUIT(rend_circ),
|
||||
RELAY_COMMAND_RENDEZVOUS2,
|
||||
request+REND_COOKIE_LEN,
|
||||
request_len-REND_COOKIE_LEN, NULL)) {
|
||||
@ -304,16 +311,16 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len)
|
||||
"Completing rendezvous: circuit %d joins circuit %d (cookie %s)",
|
||||
circ->p_circ_id, rend_circ->p_circ_id, hexid);
|
||||
|
||||
circ->purpose = CIRCUIT_PURPOSE_REND_ESTABLISHED;
|
||||
rend_circ->purpose = CIRCUIT_PURPOSE_REND_ESTABLISHED;
|
||||
memset(circ->rend_cookie, 0, REND_COOKIE_LEN);
|
||||
circ->_base.purpose = CIRCUIT_PURPOSE_REND_ESTABLISHED;
|
||||
rend_circ->_base.purpose = CIRCUIT_PURPOSE_REND_ESTABLISHED;
|
||||
memset(circ->_base.rend_cookie, 0, REND_COOKIE_LEN);
|
||||
|
||||
rend_circ->rend_splice = circ;
|
||||
circ->rend_splice = rend_circ;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
circuit_mark_for_close(circ, reason);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circ), reason);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,8 @@ const char rendservice_c_id[] =
|
||||
|
||||
#include "or.h"
|
||||
|
||||
static circuit_t *find_intro_circuit(routerinfo_t *router,
|
||||
const char *pk_digest);
|
||||
static origin_circuit_t *find_intro_circuit(routerinfo_t *router,
|
||||
const char *pk_digest);
|
||||
|
||||
/** Represents the mapping from a virtual port of a rendezvous service to
|
||||
* a real port on some IP.
|
||||
@ -285,7 +285,7 @@ static void
|
||||
rend_service_update_descriptor(rend_service_t *service)
|
||||
{
|
||||
rend_service_descriptor_t *d;
|
||||
circuit_t *circ;
|
||||
origin_circuit_t *circ;
|
||||
int i,n;
|
||||
routerinfo_t *router;
|
||||
|
||||
@ -310,7 +310,7 @@ rend_service_update_descriptor(rend_service_t *service)
|
||||
continue;
|
||||
}
|
||||
circ = find_intro_circuit(router, service->pk_digest);
|
||||
if (circ && circ->purpose == CIRCUIT_PURPOSE_S_INTRO) {
|
||||
if (circ && circ->_base.purpose == CIRCUIT_PURPOSE_S_INTRO) {
|
||||
/* We have an entirely established intro circuit. */
|
||||
d->intro_points[d->n_intro_points] = tor_strdup(router->nickname);
|
||||
d->intro_point_extend_info[d->n_intro_points] =
|
||||
@ -410,7 +410,7 @@ rend_service_requires_uptime(rend_service_t *service)
|
||||
* rendezvous point.
|
||||
*/
|
||||
int
|
||||
rend_service_introduce(circuit_t *circuit, const char *request,
|
||||
rend_service_introduce(origin_circuit_t *circuit, const char *request,
|
||||
size_t request_len)
|
||||
{
|
||||
char *ptr, *r_cookie;
|
||||
@ -421,21 +421,21 @@ rend_service_introduce(circuit_t *circuit, const char *request,
|
||||
int r, i;
|
||||
size_t len, keylen;
|
||||
crypto_dh_env_t *dh = NULL;
|
||||
circuit_t *launched = NULL;
|
||||
origin_circuit_t *launched = NULL;
|
||||
crypt_path_t *cpath = NULL;
|
||||
char serviceid[REND_SERVICE_ID_LEN+1];
|
||||
char hexcookie[9];
|
||||
int circ_needs_uptime;
|
||||
|
||||
base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
|
||||
circuit->rend_pk_digest,10);
|
||||
circuit->_base.rend_pk_digest,10);
|
||||
log_info(LD_REND, "Received INTRODUCE2 cell for service %s on circ %d.",
|
||||
escaped(serviceid), circuit->n_circ_id);
|
||||
escaped(serviceid), circuit->_base.n_circ_id);
|
||||
|
||||
if (circuit->purpose != CIRCUIT_PURPOSE_S_INTRO) {
|
||||
if (circuit->_base.purpose != CIRCUIT_PURPOSE_S_INTRO) {
|
||||
log_warn(LD_PROTOCOL,
|
||||
"Got an INTRODUCE2 over a non-introduction circuit %d.",
|
||||
circuit->n_circ_id);
|
||||
circuit->_base.n_circ_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -443,7 +443,7 @@ rend_service_introduce(circuit_t *circuit, const char *request,
|
||||
if (request_len < DIGEST_LEN+REND_COOKIE_LEN+(MAX_NICKNAME_LEN+1)+
|
||||
DH_KEY_LEN+42) {
|
||||
log_warn(LD_PROTOCOL, "Got a truncated INTRODUCE2 cell on circ %d.",
|
||||
circuit->n_circ_id);
|
||||
circuit->_base.n_circ_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -454,7 +454,7 @@ rend_service_introduce(circuit_t *circuit, const char *request,
|
||||
escaped(serviceid));
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(circuit->rend_pk_digest, request, DIGEST_LEN)) {
|
||||
if (memcmp(circuit->_base.rend_pk_digest, request, DIGEST_LEN)) {
|
||||
base32_encode(serviceid, REND_SERVICE_ID_LEN+1, request, 10);
|
||||
log_warn(LD_REND, "Got an INTRODUCE2 cell for the wrong service (%s).",
|
||||
escaped(serviceid));
|
||||
@ -589,11 +589,11 @@ rend_service_introduce(circuit_t *circuit, const char *request,
|
||||
extend_info->nickname, hexcookie, serviceid);
|
||||
tor_assert(launched->build_state);
|
||||
/* Fill in the circuit's state. */
|
||||
memcpy(launched->rend_pk_digest, circuit->rend_pk_digest,
|
||||
memcpy(launched->_base.rend_pk_digest, circuit->_base.rend_pk_digest,
|
||||
DIGEST_LEN);
|
||||
memcpy(launched->rend_cookie, r_cookie, REND_COOKIE_LEN);
|
||||
strlcpy(launched->rend_query, service->service_id,
|
||||
sizeof(launched->rend_query));
|
||||
memcpy(launched->_base.rend_cookie, r_cookie, REND_COOKIE_LEN);
|
||||
strlcpy(launched->_base.rend_query, service->service_id,
|
||||
sizeof(launched->_base.rend_query));
|
||||
launched->build_state->pending_final_cpath = cpath =
|
||||
tor_malloc_zero(sizeof(crypt_path_t));
|
||||
cpath->magic = CRYPT_PATH_MAGIC;
|
||||
@ -609,7 +609,8 @@ rend_service_introduce(circuit_t *circuit, const char *request,
|
||||
return 0;
|
||||
err:
|
||||
if (dh) crypto_dh_free(dh);
|
||||
if (launched) circuit_mark_for_close(launched, END_CIRC_AT_ORIGIN);
|
||||
if (launched)
|
||||
circuit_mark_for_close(TO_CIRCUIT(launched), END_CIRC_AT_ORIGIN);
|
||||
if (extend_info) extend_info_free(extend_info);
|
||||
return -1;
|
||||
}
|
||||
@ -618,12 +619,12 @@ rend_service_introduce(circuit_t *circuit, const char *request,
|
||||
* than the last hop: launches a new circuit to the same rendezvous point.
|
||||
*/
|
||||
void
|
||||
rend_service_relaunch_rendezvous(circuit_t *oldcirc)
|
||||
rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
|
||||
{
|
||||
circuit_t *newcirc;
|
||||
origin_circuit_t *newcirc;
|
||||
cpath_build_state_t *newstate, *oldstate;
|
||||
|
||||
tor_assert(oldcirc->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
|
||||
tor_assert(oldcirc->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
|
||||
|
||||
if (!oldcirc->build_state ||
|
||||
oldcirc->build_state->failure_count > MAX_REND_FAILURES ||
|
||||
@ -662,9 +663,12 @@ rend_service_relaunch_rendezvous(circuit_t *oldcirc)
|
||||
newstate->pending_final_cpath = oldstate->pending_final_cpath;
|
||||
oldstate->pending_final_cpath = NULL;
|
||||
|
||||
memcpy(newcirc->rend_query, oldcirc->rend_query, REND_SERVICE_ID_LEN+1);
|
||||
memcpy(newcirc->rend_pk_digest, oldcirc->rend_pk_digest, DIGEST_LEN);
|
||||
memcpy(newcirc->rend_cookie, oldcirc->rend_cookie, REND_COOKIE_LEN);
|
||||
memcpy(newcirc->_base.rend_query, oldcirc->_base.rend_query,
|
||||
REND_SERVICE_ID_LEN+1);
|
||||
memcpy(newcirc->_base.rend_pk_digest, oldcirc->_base.rend_pk_digest,
|
||||
DIGEST_LEN);
|
||||
memcpy(newcirc->_base.rend_cookie, oldcirc->_base.rend_cookie,
|
||||
REND_COOKIE_LEN);
|
||||
}
|
||||
|
||||
/** Launch a circuit to serve as an introduction point for the service
|
||||
@ -674,7 +678,7 @@ static int
|
||||
rend_service_launch_establish_intro(rend_service_t *service,
|
||||
const char *nickname)
|
||||
{
|
||||
circuit_t *launched;
|
||||
origin_circuit_t *launched;
|
||||
|
||||
log_info(LD_REND,
|
||||
"Launching circuit to introduction point %s for service %s",
|
||||
@ -691,11 +695,11 @@ rend_service_launch_establish_intro(rend_service_t *service,
|
||||
nickname);
|
||||
return -1;
|
||||
}
|
||||
strlcpy(launched->rend_query, service->service_id,
|
||||
sizeof(launched->rend_query));
|
||||
memcpy(launched->rend_pk_digest, service->pk_digest, DIGEST_LEN);
|
||||
strlcpy(launched->_base.rend_query, service->service_id,
|
||||
sizeof(launched->_base.rend_query));
|
||||
memcpy(launched->_base.rend_pk_digest, service->pk_digest, DIGEST_LEN);
|
||||
|
||||
if (launched->state == CIRCUIT_STATE_OPEN)
|
||||
if (launched->_base.state == CIRCUIT_STATE_OPEN)
|
||||
rend_service_intro_has_opened(launched);
|
||||
return 0;
|
||||
}
|
||||
@ -704,7 +708,7 @@ rend_service_launch_establish_intro(rend_service_t *service,
|
||||
* sends a RELAY_ESTABLISH_INTRO cell.
|
||||
*/
|
||||
void
|
||||
rend_service_intro_has_opened(circuit_t *circuit)
|
||||
rend_service_intro_has_opened(origin_circuit_t *circuit)
|
||||
{
|
||||
rend_service_t *service;
|
||||
size_t len;
|
||||
@ -713,23 +717,22 @@ rend_service_intro_has_opened(circuit_t *circuit)
|
||||
char auth[DIGEST_LEN + 9];
|
||||
char serviceid[REND_SERVICE_ID_LEN+1];
|
||||
|
||||
tor_assert(circuit->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
|
||||
tor_assert(CIRCUIT_IS_ORIGIN(circuit));
|
||||
tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
|
||||
tor_assert(circuit->cpath);
|
||||
|
||||
base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
|
||||
circuit->rend_pk_digest,10);
|
||||
circuit->_base.rend_pk_digest,10);
|
||||
|
||||
service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
|
||||
service = rend_service_get_by_pk_digest(circuit->_base.rend_pk_digest);
|
||||
if (!service) {
|
||||
log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %d.",
|
||||
serviceid, circuit->n_circ_id);
|
||||
serviceid, circuit->_base.n_circ_id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
log_info(LD_REND,
|
||||
"Established circuit %d as introduction point for service %s",
|
||||
circuit->n_circ_id, serviceid);
|
||||
circuit->_base.n_circ_id, serviceid);
|
||||
|
||||
/* Build the payload for a RELAY_ESTABLISH_INTRO cell. */
|
||||
len = crypto_pk_asn1_encode(service->private_key, buf+2,
|
||||
@ -748,47 +751,48 @@ rend_service_intro_has_opened(circuit_t *circuit)
|
||||
}
|
||||
len += r;
|
||||
|
||||
if (connection_edge_send_command(NULL, circuit,RELAY_COMMAND_ESTABLISH_INTRO,
|
||||
if (connection_edge_send_command(NULL, TO_CIRCUIT(circuit),
|
||||
RELAY_COMMAND_ESTABLISH_INTRO,
|
||||
buf, len, circuit->cpath->prev)<0) {
|
||||
log_info(LD_GENERAL,
|
||||
"Couldn't send introduction request for service %s on circuit %d",
|
||||
serviceid, circuit->n_circ_id);
|
||||
serviceid, circuit->_base.n_circ_id);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return;
|
||||
err:
|
||||
circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_AT_ORIGIN);
|
||||
}
|
||||
|
||||
/** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a
|
||||
* live introduction point, and note that the service descriptor is
|
||||
* now out-of-date.*/
|
||||
int
|
||||
rend_service_intro_established(circuit_t *circuit, const char *request,
|
||||
rend_service_intro_established(origin_circuit_t *circuit, const char *request,
|
||||
size_t request_len)
|
||||
{
|
||||
rend_service_t *service;
|
||||
(void) request;
|
||||
(void) request_len;
|
||||
|
||||
if (circuit->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
|
||||
if (circuit->_base.purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) {
|
||||
log_warn(LD_PROTOCOL,
|
||||
"received INTRO_ESTABLISHED cell on non-intro circuit.");
|
||||
goto err;
|
||||
}
|
||||
service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
|
||||
service = rend_service_get_by_pk_digest(circuit->_base.rend_pk_digest);
|
||||
if (!service) {
|
||||
log_warn(LD_REND, "Unknown service on introduction circuit %d.",
|
||||
circuit->n_circ_id);
|
||||
circuit->_base.n_circ_id);
|
||||
goto err;
|
||||
}
|
||||
service->desc_is_dirty = time(NULL);
|
||||
circuit->purpose = CIRCUIT_PURPOSE_S_INTRO;
|
||||
circuit->_base.purpose = CIRCUIT_PURPOSE_S_INTRO;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_AT_ORIGIN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -796,7 +800,7 @@ rend_service_intro_established(circuit_t *circuit, const char *request,
|
||||
* RELAY_COMMAND_RENDEZVOUS1 cell.
|
||||
*/
|
||||
void
|
||||
rend_service_rendezvous_has_opened(circuit_t *circuit)
|
||||
rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
|
||||
{
|
||||
rend_service_t *service;
|
||||
char buf[RELAY_PAYLOAD_SIZE];
|
||||
@ -804,22 +808,22 @@ rend_service_rendezvous_has_opened(circuit_t *circuit)
|
||||
char serviceid[REND_SERVICE_ID_LEN+1];
|
||||
char hexcookie[9];
|
||||
|
||||
tor_assert(circuit->purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
|
||||
tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
|
||||
tor_assert(circuit->cpath);
|
||||
tor_assert(circuit->build_state);
|
||||
hop = circuit->build_state->pending_final_cpath;
|
||||
tor_assert(hop);
|
||||
|
||||
base16_encode(hexcookie,9,circuit->rend_cookie,4);
|
||||
base16_encode(hexcookie,9,circuit->_base.rend_cookie,4);
|
||||
base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
|
||||
circuit->rend_pk_digest,10);
|
||||
circuit->_base.rend_pk_digest,10);
|
||||
|
||||
log_info(LD_REND,
|
||||
"Done building circuit %d to rendezvous with "
|
||||
"cookie %s for service %s",
|
||||
circuit->n_circ_id, hexcookie, serviceid);
|
||||
circuit->_base.n_circ_id, hexcookie, serviceid);
|
||||
|
||||
service = rend_service_get_by_pk_digest(circuit->rend_pk_digest);
|
||||
service = rend_service_get_by_pk_digest(circuit->_base.rend_pk_digest);
|
||||
if (!service) {
|
||||
log_warn(LD_GENERAL, "Internal error: unrecognized service ID on "
|
||||
"introduction circuit.");
|
||||
@ -827,7 +831,7 @@ rend_service_rendezvous_has_opened(circuit_t *circuit)
|
||||
}
|
||||
|
||||
/* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
|
||||
memcpy(buf, circuit->rend_cookie, REND_COOKIE_LEN);
|
||||
memcpy(buf, circuit->_base.rend_cookie, REND_COOKIE_LEN);
|
||||
if (crypto_dh_get_public(hop->dh_handshake_state,
|
||||
buf+REND_COOKIE_LEN, DH_KEY_LEN)<0) {
|
||||
log_warn(LD_GENERAL,"Couldn't get DH public key.");
|
||||
@ -837,7 +841,8 @@ rend_service_rendezvous_has_opened(circuit_t *circuit)
|
||||
DIGEST_LEN);
|
||||
|
||||
/* Send the cell */
|
||||
if (connection_edge_send_command(NULL, circuit, RELAY_COMMAND_RENDEZVOUS1,
|
||||
if (connection_edge_send_command(NULL, TO_CIRCUIT(circuit),
|
||||
RELAY_COMMAND_RENDEZVOUS1,
|
||||
buf, REND_COOKIE_LEN+DH_KEY_LEN+DIGEST_LEN,
|
||||
circuit->cpath->prev)<0) {
|
||||
log_warn(LD_GENERAL, "Couldn't send RENDEZVOUS1 cell.");
|
||||
@ -859,11 +864,11 @@ rend_service_rendezvous_has_opened(circuit_t *circuit)
|
||||
circuit->build_state->pending_final_cpath = NULL; /* prevent double-free */
|
||||
|
||||
/* Change the circuit purpose. */
|
||||
circuit->purpose = CIRCUIT_PURPOSE_S_REND_JOINED;
|
||||
circuit->_base.purpose = CIRCUIT_PURPOSE_S_REND_JOINED;
|
||||
|
||||
return;
|
||||
err:
|
||||
circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN);
|
||||
circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_AT_ORIGIN);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -874,28 +879,31 @@ rend_service_rendezvous_has_opened(circuit_t *circuit)
|
||||
* <b>router</b> for the service whose public key is <b>pk_digest</b>. Return
|
||||
* NULL if no such service is found.
|
||||
*/
|
||||
static circuit_t *
|
||||
static origin_circuit_t *
|
||||
find_intro_circuit(routerinfo_t *router, const char *pk_digest)
|
||||
{
|
||||
circuit_t *circ = NULL;
|
||||
cpath_build_state_t *build_state = NULL;
|
||||
|
||||
tor_assert(router);
|
||||
while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
|
||||
CIRCUIT_PURPOSE_S_INTRO))) {
|
||||
tor_assert(circ->cpath);
|
||||
if (!strcasecmp(circ->build_state->chosen_exit->nickname,
|
||||
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
||||
build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
|
||||
if (!strcasecmp(build_state->chosen_exit->nickname,
|
||||
router->nickname)) {
|
||||
return circ;
|
||||
return TO_ORIGIN_CIRCUIT(circ);
|
||||
}
|
||||
}
|
||||
|
||||
circ = NULL;
|
||||
while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
|
||||
CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
|
||||
tor_assert(circ->cpath);
|
||||
if (!strcasecmp(circ->build_state->chosen_exit->nickname,
|
||||
tor_assert(CIRCUIT_IS_ORIGIN(circ));
|
||||
build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
|
||||
if (!strcasecmp(build_state->chosen_exit->nickname,
|
||||
router->nickname)) {
|
||||
return circ;
|
||||
return TO_ORIGIN_CIRCUIT(circ);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@ -1088,7 +1096,7 @@ rend_service_dump_stats(int severity)
|
||||
routerinfo_t *router;
|
||||
rend_service_t *service;
|
||||
char *nickname;
|
||||
circuit_t *circ;
|
||||
origin_circuit_t *circ;
|
||||
|
||||
for (i=0; i < smartlist_len(rend_service_list); ++i) {
|
||||
service = smartlist_get(rend_service_list, i);
|
||||
@ -1108,7 +1116,7 @@ rend_service_dump_stats(int severity)
|
||||
continue;
|
||||
}
|
||||
log(severity, LD_GENERAL, " Intro point at %s: circuit is %s",nickname,
|
||||
circuit_state_to_string(circ->state));
|
||||
circuit_state_to_string(circ->_base.state));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1119,22 +1127,23 @@ rend_service_dump_stats(int severity)
|
||||
* or 0 for success.
|
||||
*/
|
||||
int
|
||||
rend_service_set_connection_addr_port(connection_t *conn, circuit_t *circ)
|
||||
rend_service_set_connection_addr_port(connection_t *conn,
|
||||
origin_circuit_t *circ)
|
||||
{
|
||||
rend_service_t *service;
|
||||
int i;
|
||||
rend_service_port_config_t *p;
|
||||
char serviceid[REND_SERVICE_ID_LEN+1];
|
||||
|
||||
tor_assert(circ->purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
|
||||
tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
|
||||
log_debug(LD_REND,"beginning to hunt for addr/port");
|
||||
base32_encode(serviceid, REND_SERVICE_ID_LEN+1,
|
||||
circ->rend_pk_digest,10);
|
||||
service = rend_service_get_by_pk_digest(circ->rend_pk_digest);
|
||||
circ->_base.rend_pk_digest,10);
|
||||
service = rend_service_get_by_pk_digest(circ->_base.rend_pk_digest);
|
||||
if (!service) {
|
||||
log_warn(LD_REND, "Couldn't find any service associated with pk %s on "
|
||||
"rendezvous circuit %d; closing.",
|
||||
serviceid, circ->n_circ_id);
|
||||
serviceid, circ->_base.n_circ_id);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < smartlist_len(service->ports); ++i) {
|
||||
|
Loading…
Reference in New Issue
Block a user