mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
break part of circuit.c into relay.c
svn:r1854
This commit is contained in:
@@ -7,7 +7,7 @@ bin_PROGRAMS = tor
|
||||
tor_SOURCES = buffers.c circuit.c command.c config.c \
|
||||
connection.c connection_edge.c connection_or.c \
|
||||
cpuworker.c directory.c dirserv.c dns.c main.c \
|
||||
onion.c rendcommon.c rendclient.c rendmid.c \
|
||||
onion.c relay.c rendcommon.c rendclient.c rendmid.c \
|
||||
rendservice.c rephist.c router.c routerlist.c routerparse.c \
|
||||
tor_main.c
|
||||
|
||||
@@ -16,7 +16,7 @@ tor_LDADD = ../common/libor.a
|
||||
test_SOURCES = buffers.c circuit.c command.c config.c \
|
||||
connection.c connection_edge.c connection_or.c \
|
||||
cpuworker.c directory.c dirserv.c dns.c main.c \
|
||||
onion.c rendcommon.c rendclient.c rendmid.c \
|
||||
onion.c relay.c rendcommon.c rendclient.c rendmid.c \
|
||||
rendservice.c rephist.c router.c routerlist.c routerparse.c \
|
||||
test.c
|
||||
|
||||
@@ -24,4 +24,3 @@ test_LDADD = ../common/libor.a
|
||||
|
||||
noinst_HEADERS = or.h tree.h
|
||||
|
||||
|
||||
|
||||
+1
-339
@@ -4,17 +4,13 @@
|
||||
|
||||
/**
|
||||
* \file circuit.c
|
||||
* \brief Manage circuits and the global circuit list. Also handle
|
||||
* relay cell encryption/decryption.
|
||||
* \brief Manage circuits and the global circuit list.
|
||||
**/
|
||||
|
||||
#include "or.h"
|
||||
|
||||
extern or_options_t options; /* command-line and config-file options */
|
||||
|
||||
static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
|
||||
crypt_path_t **layer_hint, char *recognized);
|
||||
static connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction);
|
||||
static int circuit_resume_edge_reading_helper(connection_t *conn,
|
||||
circuit_t *circ,
|
||||
crypt_path_t *layer_hint);
|
||||
@@ -27,15 +23,6 @@ static void circuit_is_open(circuit_t *circ);
|
||||
static void circuit_build_failed(circuit_t *circ);
|
||||
static circuit_t *circuit_establish_circuit(uint8_t purpose, const char *exit_nickname);
|
||||
|
||||
/** Stats: how many relay cells have originated at this hop, or have
|
||||
* been relayed onward (not recognized at this hop)?
|
||||
*/
|
||||
unsigned long stats_n_relay_cells_relayed = 0;
|
||||
/** Stats: how many relay cells have been delivered to streams at this
|
||||
* hop?
|
||||
*/
|
||||
unsigned long stats_n_relay_cells_delivered = 0;
|
||||
|
||||
/********* START VARIABLES **********/
|
||||
|
||||
/** A global (within this file) list of all circuits at this hop. */
|
||||
@@ -675,331 +662,6 @@ void circuit_build_needed_circs(time_t now) {
|
||||
/* XXX count idle rendezvous circs and build more */
|
||||
}
|
||||
|
||||
/** Update digest from the payload of cell. Assign integrity part to
|
||||
* cell.
|
||||
*/
|
||||
static void relay_set_digest(crypto_digest_env_t *digest, cell_t *cell) {
|
||||
char integrity[4];
|
||||
relay_header_t rh;
|
||||
|
||||
crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE);
|
||||
crypto_digest_get_digest(digest, integrity, 4);
|
||||
// log_fn(LOG_DEBUG,"Putting digest of %u %u %u %u into relay cell.",
|
||||
// integrity[0], integrity[1], integrity[2], integrity[3]);
|
||||
relay_header_unpack(&rh, cell->payload);
|
||||
memcpy(rh.integrity, integrity, 4);
|
||||
relay_header_pack(cell->payload, &rh);
|
||||
}
|
||||
|
||||
/** Does the digest for this circuit indicate that this cell is for us?
|
||||
*
|
||||
* Update digest from the payload of cell (with the integrity part set
|
||||
* to 0). If the integrity part is valid, return 1, else restore digest
|
||||
* and cell to their original state and return 0.
|
||||
*/
|
||||
static int relay_digest_matches(crypto_digest_env_t *digest, cell_t *cell) {
|
||||
char received_integrity[4], calculated_integrity[4];
|
||||
relay_header_t rh;
|
||||
crypto_digest_env_t *backup_digest=NULL;
|
||||
|
||||
backup_digest = crypto_digest_dup(digest);
|
||||
|
||||
relay_header_unpack(&rh, cell->payload);
|
||||
memcpy(received_integrity, rh.integrity, 4);
|
||||
memset(rh.integrity, 0, 4);
|
||||
relay_header_pack(cell->payload, &rh);
|
||||
|
||||
// log_fn(LOG_DEBUG,"Reading digest of %u %u %u %u from relay cell.",
|
||||
// received_integrity[0], received_integrity[1],
|
||||
// received_integrity[2], received_integrity[3]);
|
||||
|
||||
crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE);
|
||||
crypto_digest_get_digest(digest, calculated_integrity, 4);
|
||||
|
||||
if(memcmp(received_integrity, calculated_integrity, 4)) {
|
||||
// log_fn(LOG_INFO,"Recognized=0 but bad digest. Not recognizing.");
|
||||
// (%d vs %d).", received_integrity, calculated_integrity);
|
||||
/* restore digest to its old form */
|
||||
crypto_digest_assign(digest, backup_digest);
|
||||
/* restore the relay header */
|
||||
memcpy(rh.integrity, received_integrity, 4);
|
||||
relay_header_pack(cell->payload, &rh);
|
||||
crypto_free_digest_env(backup_digest);
|
||||
return 0;
|
||||
}
|
||||
crypto_free_digest_env(backup_digest);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Apply <b>cipher</b> to CELL_PAYLOAD_SIZE bytes of <b>in</b>
|
||||
* (in place).
|
||||
*
|
||||
* If <b>encrypt_mode</b> is 1 then encrypt, else decrypt.
|
||||
*
|
||||
* Return -1 if the crypto fails, else return 0.
|
||||
*/
|
||||
static int relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in,
|
||||
int encrypt_mode) {
|
||||
char out[CELL_PAYLOAD_SIZE]; /* 'in' must be this size too */
|
||||
relay_header_t rh;
|
||||
|
||||
relay_header_unpack(&rh, in);
|
||||
// log_fn(LOG_DEBUG,"before crypt: %d",rh.recognized);
|
||||
if(( encrypt_mode && crypto_cipher_encrypt(cipher, in, CELL_PAYLOAD_SIZE, out)) ||
|
||||
(!encrypt_mode && crypto_cipher_decrypt(cipher, in, CELL_PAYLOAD_SIZE, out))) {
|
||||
log_fn(LOG_WARN,"Error during relay encryption");
|
||||
return -1;
|
||||
}
|
||||
memcpy(in,out,CELL_PAYLOAD_SIZE);
|
||||
relay_header_unpack(&rh, in);
|
||||
// log_fn(LOG_DEBUG,"after crypt: %d",rh.recognized);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Receive a relay cell:
|
||||
* - Crypt it (encrypt APward, decrypt at AP, decrypt exitward).
|
||||
* - Check if recognized (if exitward).
|
||||
* - If recognized and the digest checks out, then find if there's
|
||||
* a conn that the cell is intended for, and deliver it to
|
||||
* connection_edge.
|
||||
* - Else connection_or_write_cell_to_buf to the conn on the other
|
||||
* side of the circuit.
|
||||
*/
|
||||
int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
int cell_direction) {
|
||||
connection_t *conn=NULL;
|
||||
crypt_path_t *layer_hint=NULL;
|
||||
char recognized=0;
|
||||
|
||||
tor_assert(cell && circ);
|
||||
tor_assert(cell_direction == CELL_DIRECTION_OUT || cell_direction == CELL_DIRECTION_IN);
|
||||
if (circ->marked_for_close)
|
||||
return 0;
|
||||
|
||||
if(relay_crypt(circ, cell, cell_direction, &layer_hint, &recognized) < 0) {
|
||||
log_fn(LOG_WARN,"relay crypt failed. Dropping connection.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(recognized) {
|
||||
conn = relay_lookup_conn(circ, cell, cell_direction);
|
||||
if(cell_direction == CELL_DIRECTION_OUT) {
|
||||
++stats_n_relay_cells_delivered;
|
||||
log_fn(LOG_DEBUG,"Sending away from origin.");
|
||||
if (connection_edge_process_relay_cell(cell, circ, conn, NULL) < 0) {
|
||||
log_fn(LOG_WARN,"connection_edge_process_relay_cell (away from origin) failed.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if(cell_direction == CELL_DIRECTION_IN) {
|
||||
++stats_n_relay_cells_delivered;
|
||||
log_fn(LOG_DEBUG,"Sending to origin.");
|
||||
if (connection_edge_process_relay_cell(cell, circ, conn, layer_hint) < 0) {
|
||||
log_fn(LOG_WARN,"connection_edge_process_relay_cell (at origin) failed.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* not recognized. pass it on. */
|
||||
if(cell_direction == CELL_DIRECTION_OUT) {
|
||||
cell->circ_id = circ->n_circ_id; /* switch it */
|
||||
conn = circ->n_conn;
|
||||
} else {
|
||||
cell->circ_id = circ->p_circ_id; /* switch it */
|
||||
conn = circ->p_conn;
|
||||
}
|
||||
|
||||
if(!conn) {
|
||||
if (circ->rend_splice && cell_direction == CELL_DIRECTION_OUT) {
|
||||
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 (circuit_receive_relay_cell(cell, circ->rend_splice, CELL_DIRECTION_IN)<0) {
|
||||
log_fn(LOG_WARN, "Error relaying cell across rendezvous; closing circuits");
|
||||
circuit_mark_for_close(circ); /* XXXX Do this here, or just return -1? */
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
log_fn(LOG_WARN,"Didn't recognize cell, but circ stops here! Closing circ.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_fn(LOG_DEBUG,"Passing on unrecognized cell.");
|
||||
++stats_n_relay_cells_relayed;
|
||||
connection_or_write_cell_to_buf(cell, conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Do the appropriate en/decryptions for <b>cell</b> arriving on
|
||||
* <b>circ</b> in direction <b>cell_direction</b>.
|
||||
*
|
||||
* If cell_direction == CELL_DIRECTION_IN:
|
||||
* - If we're at the origin (we're the OP), for hops 1..N,
|
||||
* decrypt cell. If recognized, stop.
|
||||
* - Else (we're not the OP), encrypt one hop. Cell is not recognized.
|
||||
*
|
||||
* If cell_direction == CELL_DIRECTION_OUT:
|
||||
* - decrypt one hop. Check if recognized.
|
||||
*
|
||||
* If cell is recognized, set *recognized to 1, and set
|
||||
* *layer_hint to the hop that recognized it.
|
||||
*
|
||||
* Return -1 to indicate that we should mark the circuit for close,
|
||||
* else return 0.
|
||||
*/
|
||||
/* wrap this into receive_relay_cell one day */
|
||||
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 && cell && recognized);
|
||||
tor_assert(cell_direction == CELL_DIRECTION_IN || cell_direction == CELL_DIRECTION_OUT);
|
||||
|
||||
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;
|
||||
if(thishop->state != CPATH_STATE_OPEN) {
|
||||
log_fn(LOG_WARN,"Relay cell before first created cell? Closing.");
|
||||
return -1;
|
||||
}
|
||||
do { /* Remember: cpath is in forward order, that is, first hop first. */
|
||||
tor_assert(thishop);
|
||||
|
||||
if(relay_crypt_one_payload(thishop->b_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(thishop->b_digest, cell)) {
|
||||
*recognized = 1;
|
||||
*layer_hint = thishop;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
thishop = thishop->next;
|
||||
} while(thishop != circ->cpath && thishop->state == CPATH_STATE_OPEN);
|
||||
log_fn(LOG_WARN,"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)
|
||||
return -1;
|
||||
// log_fn(LOG_DEBUG,"Skipping recognized check, because we're not the OP.");
|
||||
}
|
||||
} 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)
|
||||
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)) {
|
||||
*recognized = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Package a relay cell:
|
||||
* - Encrypt it to the right layer
|
||||
* - connection_or_write_cell_to_buf to the right conn
|
||||
*/
|
||||
int
|
||||
circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
int cell_direction,
|
||||
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) {
|
||||
conn = circ->n_conn;
|
||||
if(!conn) {
|
||||
log_fn(LOG_WARN,"outgoing relay cell has n_conn==NULL. Dropping.");
|
||||
return 0; /* just drop it */
|
||||
}
|
||||
relay_set_digest(layer_hint->f_digest, cell);
|
||||
|
||||
thishop = layer_hint;
|
||||
/* moving from farthest to nearest hop */
|
||||
do {
|
||||
tor_assert(thishop);
|
||||
|
||||
log_fn(LOG_DEBUG,"crypting a layer of the relay cell.");
|
||||
if(relay_crypt_one_payload(thishop->f_crypto, cell->payload, 1) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
thishop = thishop->prev;
|
||||
} while (thishop != circ->cpath->prev);
|
||||
|
||||
} else { /* incoming cell */
|
||||
conn = circ->p_conn;
|
||||
if(!conn) {
|
||||
log_fn(LOG_WARN,"incoming relay cell has p_conn==NULL. Dropping.");
|
||||
return 0; /* just drop it */
|
||||
}
|
||||
relay_set_digest(circ->p_digest, cell);
|
||||
if(relay_crypt_one_payload(circ->p_crypto, cell->payload, 1) < 0)
|
||||
return -1;
|
||||
}
|
||||
++stats_n_relay_cells_relayed;
|
||||
connection_or_write_cell_to_buf(cell, conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** If cell's stream_id matches the stream_id of any conn that's
|
||||
* attached to circ, return that conn, else return NULL.
|
||||
*/
|
||||
static connection_t *
|
||||
relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
|
||||
{
|
||||
connection_t *tmpconn;
|
||||
relay_header_t rh;
|
||||
|
||||
relay_header_unpack(&rh, cell->payload);
|
||||
|
||||
if(!rh.stream_id)
|
||||
return NULL;
|
||||
|
||||
/* IN or OUT cells could have come from either direction, now
|
||||
* that we allow rendezvous *to* an OP.
|
||||
*/
|
||||
|
||||
for(tmpconn = circ->n_streams; tmpconn; tmpconn=tmpconn->next_stream) {
|
||||
if(rh.stream_id == tmpconn->stream_id) {
|
||||
log_fn(LOG_DEBUG,"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->p_streams; tmpconn; tmpconn=tmpconn->next_stream) {
|
||||
if(rh.stream_id == tmpconn->stream_id) {
|
||||
log_fn(LOG_DEBUG,"found conn for stream %d.", rh.stream_id);
|
||||
return tmpconn;
|
||||
}
|
||||
}
|
||||
for(tmpconn = circ->resolving_streams; tmpconn; tmpconn=tmpconn->next_stream) {
|
||||
if(rh.stream_id == tmpconn->stream_id) {
|
||||
log_fn(LOG_DEBUG,"found conn for stream %d.", rh.stream_id);
|
||||
return tmpconn;
|
||||
}
|
||||
}
|
||||
return NULL; /* probably a begin relay cell */
|
||||
}
|
||||
|
||||
/** The circuit <b>circ</b> has received a circuit-level sendme
|
||||
* (on hop <b>layer_hint</b>, if we're the OP). Go through all the
|
||||
* attached streams and let them resume reading and packaging, if
|
||||
|
||||
@@ -852,11 +852,12 @@ int connection_handle_write(connection_t *conn) {
|
||||
}
|
||||
}
|
||||
|
||||
if(!connection_wants_to_flush(conn)) /* it's done flushing */
|
||||
if(connection_finished_flushing(conn) < 0) { /* ...and get handled here. */
|
||||
if(!connection_wants_to_flush(conn)) { /* it's done flushing */
|
||||
if(connection_finished_flushing(conn) < 0) {
|
||||
/* already marked */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1053,6 +1054,7 @@ int connection_state_is_open(connection_t *conn) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return 1 if conn is in 'connecting' state, else return 0. */
|
||||
int connection_state_is_connecting(connection_t *conn) {
|
||||
tor_assert(conn);
|
||||
|
||||
|
||||
@@ -527,7 +527,6 @@ static int directory_handle_command(connection_t *conn) {
|
||||
* appropriate.
|
||||
*/
|
||||
int connection_dir_finished_flushing(connection_t *conn) {
|
||||
int e, len=sizeof(e);
|
||||
|
||||
tor_assert(conn && conn->type == CONN_TYPE_DIR);
|
||||
|
||||
|
||||
+83
-82
@@ -897,11 +897,6 @@ int circuit_count_building(uint8_t purpose);
|
||||
int circuit_stream_is_being_handled(connection_t *conn);
|
||||
void circuit_build_needed_circs(time_t now);
|
||||
|
||||
int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
int cell_direction);
|
||||
int circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
int cell_direction, crypt_path_t *layer_hint);
|
||||
|
||||
void circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint);
|
||||
int circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint);
|
||||
void circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint);
|
||||
@@ -928,9 +923,6 @@ void assert_cpath_ok(const crypt_path_t *c);
|
||||
void assert_cpath_layer_ok(const crypt_path_t *c);
|
||||
void assert_circuit_ok(const circuit_t *c);
|
||||
|
||||
extern unsigned long stats_n_relay_cells_relayed;
|
||||
extern unsigned long stats_n_relay_cells_delivered;
|
||||
|
||||
/********************************* command.c ***************************/
|
||||
|
||||
void command_process_cell(cell_t *cell, connection_t *conn);
|
||||
@@ -1090,6 +1082,20 @@ int connection_dir_process_inbuf(connection_t *conn);
|
||||
int connection_dir_finished_flushing(connection_t *conn);
|
||||
int connection_dir_finished_connecting(connection_t *conn);
|
||||
|
||||
/********************************* dirserv.c ***************************/
|
||||
int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
|
||||
int dirserv_parse_fingerprint_file(const char *fname);
|
||||
int dirserv_router_fingerprint_is_known(const routerinfo_t *router);
|
||||
void dirserv_free_fingerprint_list();
|
||||
int dirserv_add_descriptor(const char **desc);
|
||||
int dirserv_init_from_directory_string(const char *dir);
|
||||
void dirserv_free_descriptors();
|
||||
int dirserv_dump_directory_to_string(char *s, unsigned int maxlen,
|
||||
crypto_pk_env_t *private_key);
|
||||
void directory_set_dirty(void);
|
||||
size_t dirserv_get_directory(const char **cp);
|
||||
void dirserv_remove_old_servers(void);
|
||||
|
||||
/********************************* dns.c ***************************/
|
||||
|
||||
void dns_init(void);
|
||||
@@ -1155,82 +1161,15 @@ int onion_skin_client_handshake(crypto_dh_env_t *handshake_state,
|
||||
cpath_build_state_t *onion_new_cpath_build_state(uint8_t purpose,
|
||||
const char *exit_nickname);
|
||||
|
||||
/********************************* router.c ***************************/
|
||||
/********************************* relay.c ***************************/
|
||||
|
||||
void set_onion_key(crypto_pk_env_t *k);
|
||||
crypto_pk_env_t *get_onion_key(void);
|
||||
crypto_pk_env_t *get_previous_onion_key(void);
|
||||
time_t get_onion_key_set_at(void);
|
||||
void set_identity_key(crypto_pk_env_t *k);
|
||||
crypto_pk_env_t *get_identity_key(void);
|
||||
int init_keys(void);
|
||||
crypto_pk_env_t *init_key_from_file(const char *fname);
|
||||
void rotate_onion_key(void);
|
||||
|
||||
void router_retry_connections(void);
|
||||
void router_upload_dir_desc_to_dirservers(void);
|
||||
void router_post_to_dirservers(uint8_t purpose, const char *payload, int payload_len);
|
||||
int router_compare_to_my_exit_policy(connection_t *conn);
|
||||
routerinfo_t *router_get_my_routerinfo(void);
|
||||
const char *router_get_my_descriptor(void);
|
||||
int router_is_me(routerinfo_t *router);
|
||||
int router_rebuild_descriptor(void);
|
||||
int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
|
||||
crypto_pk_env_t *ident_key);
|
||||
|
||||
/********************************* routerlist.c ***************************/
|
||||
|
||||
routerinfo_t *router_pick_directory_server(void);
|
||||
struct smartlist_t;
|
||||
routerinfo_t *router_choose_random_node(routerlist_t *dir,
|
||||
char *preferred, char *excluded,
|
||||
struct smartlist_t *excludedsmartlist);
|
||||
routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port);
|
||||
routerinfo_t *router_get_by_nickname(char *nickname);
|
||||
void router_get_routerlist(routerlist_t **prouterlist);
|
||||
void routerlist_free(routerlist_t *routerlist);
|
||||
void routerinfo_free(routerinfo_t *router);
|
||||
routerinfo_t *routerinfo_copy(const routerinfo_t *router);
|
||||
void router_mark_as_down(char *nickname);
|
||||
int router_set_routerlist_from_file(char *routerfile);
|
||||
int router_set_routerlist_from_string(const char *s);
|
||||
int router_set_routerlist_from_directory(const char *s, crypto_pk_env_t *pkey);
|
||||
int router_compare_addr_to_exit_policy(uint32_t addr, uint16_t port,
|
||||
struct exit_policy_t *policy);
|
||||
#define ADDR_POLICY_ACCEPTED 0
|
||||
#define ADDR_POLICY_REJECTED -1
|
||||
#define ADDR_POLICY_UNKNOWN 1
|
||||
int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port);
|
||||
int router_exit_policy_rejects_all(routerinfo_t *router);
|
||||
|
||||
/********************************* routerparse.c ************************/
|
||||
|
||||
int router_get_router_hash(const char *s, char *digest);
|
||||
int router_get_dir_hash(const char *s, char *digest);
|
||||
int router_parse_list_from_string(const char **s,
|
||||
routerlist_t **dest,
|
||||
int n_good_nicknames,
|
||||
const char **good_nickname_lst);
|
||||
int router_parse_routerlist_from_directory(const char *s,
|
||||
routerlist_t **dest,
|
||||
crypto_pk_env_t *pkey);
|
||||
routerinfo_t *router_parse_entry_from_string(const char *s, const char *end);
|
||||
int router_add_exit_policy_from_string(routerinfo_t *router, const char *s);
|
||||
|
||||
/********************************* dirserv.c ***************************/
|
||||
int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
|
||||
int dirserv_parse_fingerprint_file(const char *fname);
|
||||
int dirserv_router_fingerprint_is_known(const routerinfo_t *router);
|
||||
void dirserv_free_fingerprint_list();
|
||||
int dirserv_add_descriptor(const char **desc);
|
||||
int dirserv_init_from_directory_string(const char *dir);
|
||||
void dirserv_free_descriptors();
|
||||
int dirserv_dump_directory_to_string(char *s, unsigned int maxlen,
|
||||
crypto_pk_env_t *private_key);
|
||||
void directory_set_dirty(void);
|
||||
size_t dirserv_get_directory(const char **cp);
|
||||
void dirserv_remove_old_servers(void);
|
||||
extern unsigned long stats_n_relay_cells_relayed;
|
||||
extern unsigned long stats_n_relay_cells_delivered;
|
||||
|
||||
int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
int cell_direction);
|
||||
int circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
int cell_direction, crypt_path_t *layer_hint);
|
||||
|
||||
/********************************* rephist.c ***************************/
|
||||
|
||||
@@ -1318,6 +1257,68 @@ int rend_mid_introduce(circuit_t *circ, const char *request, int request_len);
|
||||
int rend_mid_establish_rendezvous(circuit_t *circ, const char *request, int request_len);
|
||||
int rend_mid_rendezvous(circuit_t *circ, const char *request, int request_len);
|
||||
|
||||
/********************************* router.c ***************************/
|
||||
|
||||
void set_onion_key(crypto_pk_env_t *k);
|
||||
crypto_pk_env_t *get_onion_key(void);
|
||||
crypto_pk_env_t *get_previous_onion_key(void);
|
||||
time_t get_onion_key_set_at(void);
|
||||
void set_identity_key(crypto_pk_env_t *k);
|
||||
crypto_pk_env_t *get_identity_key(void);
|
||||
int init_keys(void);
|
||||
crypto_pk_env_t *init_key_from_file(const char *fname);
|
||||
void rotate_onion_key(void);
|
||||
|
||||
void router_retry_connections(void);
|
||||
void router_upload_dir_desc_to_dirservers(void);
|
||||
void router_post_to_dirservers(uint8_t purpose, const char *payload, int payload_len);
|
||||
int router_compare_to_my_exit_policy(connection_t *conn);
|
||||
routerinfo_t *router_get_my_routerinfo(void);
|
||||
const char *router_get_my_descriptor(void);
|
||||
int router_is_me(routerinfo_t *router);
|
||||
int router_rebuild_descriptor(void);
|
||||
int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
|
||||
crypto_pk_env_t *ident_key);
|
||||
|
||||
/********************************* routerlist.c ***************************/
|
||||
|
||||
routerinfo_t *router_pick_directory_server(void);
|
||||
struct smartlist_t;
|
||||
routerinfo_t *router_choose_random_node(routerlist_t *dir,
|
||||
char *preferred, char *excluded,
|
||||
struct smartlist_t *excludedsmartlist);
|
||||
routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port);
|
||||
routerinfo_t *router_get_by_nickname(char *nickname);
|
||||
void router_get_routerlist(routerlist_t **prouterlist);
|
||||
void routerlist_free(routerlist_t *routerlist);
|
||||
void routerinfo_free(routerinfo_t *router);
|
||||
routerinfo_t *routerinfo_copy(const routerinfo_t *router);
|
||||
void router_mark_as_down(char *nickname);
|
||||
int router_set_routerlist_from_file(char *routerfile);
|
||||
int router_set_routerlist_from_string(const char *s);
|
||||
int router_set_routerlist_from_directory(const char *s, crypto_pk_env_t *pkey);
|
||||
int router_compare_addr_to_exit_policy(uint32_t addr, uint16_t port,
|
||||
struct exit_policy_t *policy);
|
||||
#define ADDR_POLICY_ACCEPTED 0
|
||||
#define ADDR_POLICY_REJECTED -1
|
||||
#define ADDR_POLICY_UNKNOWN 1
|
||||
int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port);
|
||||
int router_exit_policy_rejects_all(routerinfo_t *router);
|
||||
|
||||
/********************************* routerparse.c ************************/
|
||||
|
||||
int router_get_router_hash(const char *s, char *digest);
|
||||
int router_get_dir_hash(const char *s, char *digest);
|
||||
int router_parse_list_from_string(const char **s,
|
||||
routerlist_t **dest,
|
||||
int n_good_nicknames,
|
||||
const char **good_nickname_lst);
|
||||
int router_parse_routerlist_from_directory(const char *s,
|
||||
routerlist_t **dest,
|
||||
crypto_pk_env_t *pkey);
|
||||
routerinfo_t *router_parse_entry_from_string(const char *s, const char *end);
|
||||
int router_add_exit_policy_from_string(routerinfo_t *router, const char *s);
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,350 @@
|
||||
/* Copyright 2001 Matej Pfajfar, 2001-2004 Roger Dingledine. */
|
||||
/* See LICENSE for licensing information */
|
||||
/* $Id$ */
|
||||
|
||||
/**
|
||||
* \file relay.c
|
||||
* \brief Handle relay cell encryption/decryption.
|
||||
**/
|
||||
|
||||
#include "or.h"
|
||||
|
||||
static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction,
|
||||
crypt_path_t **layer_hint, char *recognized);
|
||||
static connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
|
||||
;
|
||||
|
||||
/** Stats: how many relay cells have originated at this hop, or have
|
||||
* been relayed onward (not recognized at this hop)?
|
||||
*/
|
||||
unsigned long stats_n_relay_cells_relayed = 0;
|
||||
/** Stats: how many relay cells have been delivered to streams at this
|
||||
* hop?
|
||||
*/
|
||||
unsigned long stats_n_relay_cells_delivered = 0;
|
||||
|
||||
/** Update digest from the payload of cell. Assign integrity part to
|
||||
* cell.
|
||||
*/
|
||||
static void relay_set_digest(crypto_digest_env_t *digest, cell_t *cell) {
|
||||
char integrity[4];
|
||||
relay_header_t rh;
|
||||
|
||||
crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE);
|
||||
crypto_digest_get_digest(digest, integrity, 4);
|
||||
// log_fn(LOG_DEBUG,"Putting digest of %u %u %u %u into relay cell.",
|
||||
// integrity[0], integrity[1], integrity[2], integrity[3]);
|
||||
relay_header_unpack(&rh, cell->payload);
|
||||
memcpy(rh.integrity, integrity, 4);
|
||||
relay_header_pack(cell->payload, &rh);
|
||||
}
|
||||
|
||||
/** Does the digest for this circuit indicate that this cell is for us?
|
||||
*
|
||||
* Update digest from the payload of cell (with the integrity part set
|
||||
* to 0). If the integrity part is valid, return 1, else restore digest
|
||||
* and cell to their original state and return 0.
|
||||
*/
|
||||
static int relay_digest_matches(crypto_digest_env_t *digest, cell_t *cell) {
|
||||
char received_integrity[4], calculated_integrity[4];
|
||||
relay_header_t rh;
|
||||
crypto_digest_env_t *backup_digest=NULL;
|
||||
|
||||
backup_digest = crypto_digest_dup(digest);
|
||||
|
||||
relay_header_unpack(&rh, cell->payload);
|
||||
memcpy(received_integrity, rh.integrity, 4);
|
||||
memset(rh.integrity, 0, 4);
|
||||
relay_header_pack(cell->payload, &rh);
|
||||
|
||||
// log_fn(LOG_DEBUG,"Reading digest of %u %u %u %u from relay cell.",
|
||||
// received_integrity[0], received_integrity[1],
|
||||
// received_integrity[2], received_integrity[3]);
|
||||
|
||||
crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE);
|
||||
crypto_digest_get_digest(digest, calculated_integrity, 4);
|
||||
|
||||
if(memcmp(received_integrity, calculated_integrity, 4)) {
|
||||
// log_fn(LOG_INFO,"Recognized=0 but bad digest. Not recognizing.");
|
||||
// (%d vs %d).", received_integrity, calculated_integrity);
|
||||
/* restore digest to its old form */
|
||||
crypto_digest_assign(digest, backup_digest);
|
||||
/* restore the relay header */
|
||||
memcpy(rh.integrity, received_integrity, 4);
|
||||
relay_header_pack(cell->payload, &rh);
|
||||
crypto_free_digest_env(backup_digest);
|
||||
return 0;
|
||||
}
|
||||
crypto_free_digest_env(backup_digest);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Apply <b>cipher</b> to CELL_PAYLOAD_SIZE bytes of <b>in</b>
|
||||
* (in place).
|
||||
*
|
||||
* If <b>encrypt_mode</b> is 1 then encrypt, else decrypt.
|
||||
*
|
||||
* Return -1 if the crypto fails, else return 0.
|
||||
*/
|
||||
static int relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in,
|
||||
int encrypt_mode) {
|
||||
char out[CELL_PAYLOAD_SIZE]; /* 'in' must be this size too */
|
||||
relay_header_t rh;
|
||||
|
||||
relay_header_unpack(&rh, in);
|
||||
// log_fn(LOG_DEBUG,"before crypt: %d",rh.recognized);
|
||||
if(( encrypt_mode && crypto_cipher_encrypt(cipher, in, CELL_PAYLOAD_SIZE, out)) ||
|
||||
(!encrypt_mode && crypto_cipher_decrypt(cipher, in, CELL_PAYLOAD_SIZE, out))) {
|
||||
log_fn(LOG_WARN,"Error during relay encryption");
|
||||
return -1;
|
||||
}
|
||||
memcpy(in,out,CELL_PAYLOAD_SIZE);
|
||||
relay_header_unpack(&rh, in);
|
||||
// log_fn(LOG_DEBUG,"after crypt: %d",rh.recognized);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Receive a relay cell:
|
||||
* - Crypt it (encrypt APward, decrypt at AP, decrypt exitward).
|
||||
* - Check if recognized (if exitward).
|
||||
* - If recognized and the digest checks out, then find if there's
|
||||
* a conn that the cell is intended for, and deliver it to·
|
||||
* connection_edge.
|
||||
* - Else connection_or_write_cell_to_buf to the conn on the other
|
||||
* side of the circuit.
|
||||
*/
|
||||
int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
int cell_direction) {
|
||||
connection_t *conn=NULL;
|
||||
crypt_path_t *layer_hint=NULL;
|
||||
char recognized=0;
|
||||
|
||||
tor_assert(cell && circ);
|
||||
tor_assert(cell_direction == CELL_DIRECTION_OUT || cell_direction == CELL_DIRECTION_IN);
|
||||
if (circ->marked_for_close)
|
||||
return 0;
|
||||
|
||||
if(relay_crypt(circ, cell, cell_direction, &layer_hint, &recognized) < 0) {
|
||||
log_fn(LOG_WARN,"relay crypt failed. Dropping connection.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(recognized) {
|
||||
conn = relay_lookup_conn(circ, cell, cell_direction);
|
||||
if(cell_direction == CELL_DIRECTION_OUT) {
|
||||
++stats_n_relay_cells_delivered;
|
||||
log_fn(LOG_DEBUG,"Sending away from origin.");
|
||||
if (connection_edge_process_relay_cell(cell, circ, conn, NULL) < 0) {
|
||||
log_fn(LOG_WARN,"connection_edge_process_relay_cell (away from origin) failed.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if(cell_direction == CELL_DIRECTION_IN) {
|
||||
++stats_n_relay_cells_delivered;
|
||||
log_fn(LOG_DEBUG,"Sending to origin.");
|
||||
if (connection_edge_process_relay_cell(cell, circ, conn, layer_hint) < 0) {
|
||||
log_fn(LOG_WARN,"connection_edge_process_relay_cell (at origin) failed.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* not recognized. pass it on. */
|
||||
if(cell_direction == CELL_DIRECTION_OUT) {
|
||||
cell->circ_id = circ->n_circ_id; /* switch it */
|
||||
conn = circ->n_conn;
|
||||
} else {
|
||||
cell->circ_id = circ->p_circ_id; /* switch it */
|
||||
conn = circ->p_conn;
|
||||
}
|
||||
|
||||
if(!conn) {
|
||||
if (circ->rend_splice && cell_direction == CELL_DIRECTION_OUT) {
|
||||
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 (circuit_receive_relay_cell(cell, circ->rend_splice, CELL_DIRECTION_IN)<0) {
|
||||
log_fn(LOG_WARN, "Error relaying cell across rendezvous; closing circuits");
|
||||
circuit_mark_for_close(circ); /* XXXX Do this here, or just return -1? */
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
log_fn(LOG_WARN,"Didn't recognize cell, but circ stops here! Closing circ.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_fn(LOG_DEBUG,"Passing on unrecognized cell.");
|
||||
++stats_n_relay_cells_relayed;
|
||||
connection_or_write_cell_to_buf(cell, conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Do the appropriate en/decryptions for <b>cell</b> arriving on
|
||||
* <b>circ</b> in direction <b>cell_direction</b>.
|
||||
*
|
||||
* If cell_direction == CELL_DIRECTION_IN:
|
||||
* - If we're at the origin (we're the OP), for hops 1..N,
|
||||
* decrypt cell. If recognized, stop.
|
||||
* - Else (we're not the OP), encrypt one hop. Cell is not recognized.
|
||||
*
|
||||
* If cell_direction == CELL_DIRECTION_OUT:
|
||||
* - decrypt one hop. Check if recognized.
|
||||
*
|
||||
* If cell is recognized, set *recognized to 1, and set
|
||||
* *layer_hint to the hop that recognized it.
|
||||
*
|
||||
* Return -1 to indicate that we should mark the circuit for close,
|
||||
* else return 0.
|
||||
*/
|
||||
/* wrap this into receive_relay_cell one day */
|
||||
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 && cell && recognized);
|
||||
tor_assert(cell_direction == CELL_DIRECTION_IN || cell_direction == CELL_DIRECTION_OUT);
|
||||
|
||||
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;
|
||||
if(thishop->state != CPATH_STATE_OPEN) {
|
||||
log_fn(LOG_WARN,"Relay cell before first created cell? Closing.");
|
||||
return -1;
|
||||
}
|
||||
do { /* Remember: cpath is in forward order, that is, first hop first. */
|
||||
tor_assert(thishop);
|
||||
|
||||
if(relay_crypt_one_payload(thishop->b_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(thishop->b_digest, cell)) {
|
||||
*recognized = 1;
|
||||
*layer_hint = thishop;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
thishop = thishop->next;
|
||||
} while(thishop != circ->cpath && thishop->state == CPATH_STATE_OPEN);
|
||||
log_fn(LOG_WARN,"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)
|
||||
return -1;
|
||||
// log_fn(LOG_DEBUG,"Skipping recognized check, because we're not the OP.");
|
||||
}
|
||||
} 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)
|
||||
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)) {
|
||||
*recognized = 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Package a relay cell:
|
||||
* - Encrypt it to the right layer
|
||||
* - connection_or_write_cell_to_buf to the right conn
|
||||
*/
|
||||
int
|
||||
circuit_package_relay_cell(cell_t *cell, circuit_t *circ,
|
||||
int cell_direction,
|
||||
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) {
|
||||
conn = circ->n_conn;
|
||||
if(!conn) {
|
||||
log_fn(LOG_WARN,"outgoing relay cell has n_conn==NULL. Dropping.");
|
||||
return 0; /* just drop it */
|
||||
}
|
||||
relay_set_digest(layer_hint->f_digest, cell);
|
||||
|
||||
thishop = layer_hint;
|
||||
/* moving from farthest to nearest hop */
|
||||
do {
|
||||
tor_assert(thishop);
|
||||
|
||||
log_fn(LOG_DEBUG,"crypting a layer of the relay cell.");
|
||||
if(relay_crypt_one_payload(thishop->f_crypto, cell->payload, 1) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
thishop = thishop->prev;
|
||||
} while (thishop != circ->cpath->prev);
|
||||
|
||||
} else { /* incoming cell */
|
||||
conn = circ->p_conn;
|
||||
if(!conn) {
|
||||
log_fn(LOG_WARN,"incoming relay cell has p_conn==NULL. Dropping.");
|
||||
return 0; /* just drop it */
|
||||
}
|
||||
relay_set_digest(circ->p_digest, cell);
|
||||
if(relay_crypt_one_payload(circ->p_crypto, cell->payload, 1) < 0)
|
||||
return -1;
|
||||
}
|
||||
++stats_n_relay_cells_relayed;
|
||||
connection_or_write_cell_to_buf(cell, conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** If cell's stream_id matches the stream_id of any conn that's
|
||||
* attached to circ, return that conn, else return NULL.
|
||||
*/
|
||||
static connection_t *
|
||||
relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction)
|
||||
{
|
||||
connection_t *tmpconn;
|
||||
relay_header_t rh;
|
||||
|
||||
relay_header_unpack(&rh, cell->payload);
|
||||
|
||||
if(!rh.stream_id)
|
||||
return NULL;
|
||||
|
||||
/* IN or OUT cells could have come from either direction, now
|
||||
* that we allow rendezvous *to* an OP.
|
||||
*/
|
||||
|
||||
for(tmpconn = circ->n_streams; tmpconn; tmpconn=tmpconn->next_stream) {
|
||||
if(rh.stream_id == tmpconn->stream_id) {
|
||||
log_fn(LOG_DEBUG,"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->p_streams; tmpconn; tmpconn=tmpconn->next_stream) {
|
||||
if(rh.stream_id == tmpconn->stream_id) {
|
||||
log_fn(LOG_DEBUG,"found conn for stream %d.", rh.stream_id);
|
||||
return tmpconn;
|
||||
}
|
||||
}
|
||||
for(tmpconn = circ->resolving_streams; tmpconn; tmpconn=tmpconn->next_stream) {
|
||||
if(rh.stream_id == tmpconn->stream_id) {
|
||||
log_fn(LOG_DEBUG,"found conn for stream %d.", rh.stream_id);
|
||||
return tmpconn;
|
||||
}
|
||||
}
|
||||
return NULL; /* probably a begin relay cell */
|
||||
}
|
||||
|
||||
@@ -211,6 +211,7 @@ routerinfo_t *router_get_by_nickname(char *nickname)
|
||||
int i;
|
||||
routerinfo_t *router;
|
||||
|
||||
tor_assert(nickname);
|
||||
tor_assert(routerlist);
|
||||
|
||||
for(i=0;i<smartlist_len(routerlist->routers);i++) {
|
||||
@@ -290,7 +291,9 @@ void routerlist_free(routerlist_t *rl)
|
||||
|
||||
/** Mark the router named <b>nickname</b> as non-running in our routerlist. */
|
||||
void router_mark_as_down(char *nickname) {
|
||||
routerinfo_t *router = router_get_by_nickname(nickname);
|
||||
routerinfo_t *router;
|
||||
tor_assert(nickname);
|
||||
router = router_get_by_nickname(nickname);
|
||||
if(!router) /* we don't seem to know about him in the first place */
|
||||
return;
|
||||
log_fn(LOG_DEBUG,"Marking %s as down.",router->nickname);
|
||||
|
||||
Reference in New Issue
Block a user