aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2006-01-05 21:23:03 +0000
committerNick Mathewson <nickm@torproject.org>2006-01-05 21:23:03 +0000
commit878962bee11eb47042d49ebd7df0d18d403c98c0 (patch)
tree04b1c7ef50ea43a81b1b2b3536fb5b00584d88ed
parentd8e3bc02884cfb85f113e44c9f61a1035789f0bc (diff)
downloadtor-878962bee11eb47042d49ebd7df0d18d403c98c0.tar
tor-878962bee11eb47042d49ebd7df0d18d403c98c0.tar.gz
Add reasons to DESTROY and RELAY_TRUNCATED cells.
svn:r5734
-rw-r--r--doc/TODO13
-rw-r--r--doc/tor-spec.txt25
-rw-r--r--src/or/circuitbuild.c39
-rw-r--r--src/or/circuitlist.c31
-rw-r--r--src/or/circuituse.c10
-rw-r--r--src/or/command.c40
-rw-r--r--src/or/connection.c35
-rw-r--r--src/or/connection_edge.c8
-rw-r--r--src/or/connection_or.c23
-rw-r--r--src/or/control.c6
-rw-r--r--src/or/cpuworker.c4
-rw-r--r--src/or/onion.c2
-rw-r--r--src/or/or.h25
-rw-r--r--src/or/relay.c62
-rw-r--r--src/or/rendclient.c18
-rw-r--r--src/or/rendmid.c26
-rw-r--r--src/or/rendservice.c8
17 files changed, 234 insertions, 141 deletions
diff --git a/doc/TODO b/doc/TODO
index 9836a3cbb..21f5d603b 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -43,9 +43,10 @@ N - if they're trying to be a tor server and they're running
other nodes *are* reachable.
o Make EntryNodes and StrictEntrynodes do what we want.
-N - Destroy and truncated cells should have reasons.
- - Specify
- - Implement
+N . Destroy and truncated cells should have reasons.
+ o Specify
+ o Implement
+ - Display the reasons under some circumstances?
N . Only use a routerdesc if you recognize its hash.
o (Must defer till dirservers are upgraded to latest code, which
@@ -85,9 +86,6 @@ N . Only use a routerdesc if you recognize its hash.
- Test.
- Non-directories don't need to keep descriptors in memory.
-N - Should router info have a pointer to routerstatus?
- - We should at least do something about the duplicated fields.
-
R - Christian Grothoff's attack of infinite-length circuit.
the solution is to have a separate 'extend-data' cell type
which is used for the first N data cells, and only
@@ -115,6 +113,9 @@ Deferred from 0.1.1.x:
those, if circuits aren't working and it's a pattern we recognize
("port 443 worked once and port 9001 keeps not working").
+N - Should router info have a pointer to routerstatus?
+ - We should at least do something about the duplicated fields.
+
N . Additional controller features
o Find a way to make event info more extensible
- change circuit status events to give more details, like purpose,
diff --git a/doc/tor-spec.txt b/doc/tor-spec.txt
index 5bd449dcf..4b0931cdb 100644
--- a/doc/tor-spec.txt
+++ b/doc/tor-spec.txt
@@ -136,7 +136,8 @@ when do we rotate which keys (tls, link, etc)?
CREATE: Payload contains the handshake challenge.
CREATED: Payload contains the handshake response.
RELAY: Payload contains the relay header and relay body.
- DESTROY: Payload is unused.
+ DESTROY: Payload contains a reason for closing the circuit.
+ (see 4.4)
Upon receiving any other value for the command field, an OR must
drop the cell.
@@ -376,6 +377,28 @@ when do we rotate which keys (tls, link, etc)?
RELAY_TRUNCATED cell towards the OP; the node farther from the OP
should send a DESTROY cell down the circuit.
+ The payload of a RELAY_TRUNCATED or DESTROY cell contains a single octet,
+ describing why the circuit is being closed or truncated. When sending a
+ TRUNCATED or DESTROY cell because of another TRUNCATED or DESTROY cell,
+ the error code should be propagated. The origin of a circuit always sets
+ this error code to 0, to avoid leaking its version.
+
+ The error codes are:
+ 0 -- NONE (No reason given.)
+ 1 -- PROTOCOL (Tor protocol violation.)
+ 2 -- INTERNAL (Internal error.)
+ 3 -- REQUESTED (A client sent a TRUNCATE command.)
+ 4 -- HIBERNATING (Not currently operating; trying to save bandwidth.)
+ 5 -- RESOURCELIMIT (Out of memory, sockets, or circuit IDs.)
+ 6 -- CONNECTFAILED (Unable to reach server.)
+ 7 -- OR_IDENTITY (Connected to server, but its OR identity was not
+ as expected.)
+ 8 -- OR_CONN_CLOSED (The OR connection that was carrying this circuit
+ died.)
+
+ [Versions of Tor prior to 0.1.0.11 didn't sent versions; implementations
+ MUST accept empty TRUNCATED and DESTROY cells.]
+
4.5. Routing relay cells
When an OR receives a RELAY cell, it checks the cell's circID and
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index bfe61ff87..e371e269e 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -313,14 +313,14 @@ circuit_establish_circuit(uint8_t purpose, extend_info_t *info,
if (onion_pick_cpath_exit(circ, info) < 0 ||
onion_populate_cpath(circ) < 0) {
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(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);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return NULL;
}
return circ;
@@ -420,7 +420,7 @@ circuit_n_conn_done(connection_t *or_conn, int status)
DIGEST_LEN)) {
if (!status) { /* or_conn failed; close circ */
info(LD_CIRC,"or_conn failed. Closing circ.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_REASON_OR_IDENTITY);
continue;
}
debug(LD_CIRC,"Found circ %d, sending create cell.", circ->n_circ_id);
@@ -432,7 +432,7 @@ circuit_n_conn_done(connection_t *or_conn, int status)
if (circuit_send_next_onion_skin(circ) < 0) {
info(LD_CIRC,
"send_next_onion_skin failed; circuit marked for closing.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
continue;
/* XXX could this be bad, eg if next_onion_skin failed because conn
* died? */
@@ -441,7 +441,7 @@ circuit_n_conn_done(connection_t *or_conn, int status)
/* pull the create cell out of circ->onionskin, and send it */
tor_assert(circ->onionskin);
if (circuit_deliver_create_cell(circ,CELL_CREATE,circ->onionskin)<0) {
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
continue;
}
tor_free(circ->onionskin);
@@ -537,7 +537,7 @@ extern int has_completed_circuit;
* Otherwise, we need to build a relay extend cell and send it
* forward.
*
- * Return -1 if we want to tear down circ, else return 0.
+ * Return -reason if we want to tear down circ, else return 0.
*/
int
circuit_send_next_onion_skin(circuit_t *circ)
@@ -567,7 +567,7 @@ circuit_send_next_onion_skin(circuit_t *circ)
&(circ->cpath->dh_handshake_state),
payload) < 0) {
warn(LD_CIRC,"onion_skin_create (first hop) failed.");
- return -1;
+ return - END_CIRC_REASON_INTERNAL;
}
} else {
/* We are not an OR, and we're building the first hop of a circuit to a
@@ -582,7 +582,7 @@ circuit_send_next_onion_skin(circuit_t *circ)
}
if (circuit_deliver_create_cell(circ, cell_type, payload) < 0)
- return -1;
+ return - END_CIRC_REASON_RESOURCELIMIT;
circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
circuit_set_state(circ, CIRCUIT_STATE_BUILDING);
@@ -625,7 +625,7 @@ circuit_send_next_onion_skin(circuit_t *circ)
if (onion_skin_create(hop->extend_info->onion_key,
&(hop->dh_handshake_state), onionskin) < 0) {
warn(LD_CIRC,"onion_skin_create failed.");
- return -1;
+ return - END_CIRC_REASON_INTERNAL;
}
debug(LD_CIRC,"Sending extend relay cell.");
@@ -719,7 +719,7 @@ circuit_extend(cell_t *cell, circuit_t *circ)
n_conn = connection_or_connect(circ->n_addr, circ->n_port, id_digest);
if (!n_conn) {
info(LD_CIRC,"Launching n_conn failed. Closing circuit.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED);
return 0;
}
debug(LD_CIRC,"connecting in progress (or finished). Good.");
@@ -801,7 +801,7 @@ circuit_init_cpath_crypto(crypt_path_t *cpath, char *key_data, int reverse)
* Calculate the appropriate keys and digests, make sure KH is
* correct, and initialize this hop of the cpath.
*
- * Return -1 if we want to mark circ for close, else return 0.
+ * 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)
@@ -816,7 +816,7 @@ circuit_finish_handshake(circuit_t *circ, uint8_t reply_type, char *reply)
hop = onion_next_hop_in_cpath(circ->cpath);
if (!hop) { /* got an extended when we're all done? */
warn(LD_PROTOCOL,"got extended when circ already built? Closing.");
- return -1;
+ return - END_CIRC_REASON_TORPROTOCOL;
}
}
tor_assert(hop->state == CPATH_STATE_AWAITING_KEYS);
@@ -825,7 +825,7 @@ circuit_finish_handshake(circuit_t *circ, uint8_t reply_type, char *reply)
if (onion_skin_client_handshake(hop->dh_handshake_state, reply, keys,
DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) {
warn(LD_CIRC,"onion_skin_client_handshake failed.");
- return -1;
+ return -END_CIRC_REASON_TORPROTOCOL;
}
/* Remember hash of g^xy */
memcpy(hop->handshake_digest, reply+DH_KEY_LEN, DIGEST_LEN);
@@ -833,12 +833,12 @@ circuit_finish_handshake(circuit_t *circ, uint8_t reply_type, char *reply)
if (fast_client_handshake(hop->fast_handshake_state, reply, keys,
DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) {
warn(LD_CIRC,"fast_client_handshake failed.");
- return -1;
+ return -END_CIRC_REASON_TORPROTOCOL;
}
memcpy(hop->handshake_digest, reply+DIGEST_LEN, DIGEST_LEN);
} else {
warn(LD_PROTOCOL,"CREATED cell type did not match CREATE cell type.");
- return -1;
+ return -END_CIRC_REASON_TORPROTOCOL;
}
if (hop->dh_handshake_state) {
@@ -848,7 +848,7 @@ circuit_finish_handshake(circuit_t *circ, uint8_t reply_type, char *reply)
memset(hop->fast_handshake_state, 0, sizeof(hop->fast_handshake_state));
if (circuit_init_cpath_crypto(hop, keys, 0)<0) {
- return -1;
+ return -END_CIRC_REASON_TORPROTOCOL;
}
hop->state = CPATH_STATE_OPEN;
@@ -880,7 +880,7 @@ circuit_truncated(circuit_t *circ, crypt_path_t *layer)
* means that a connection broke or an extend failed. For now,
* just give up.
*/
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return 0;
#if 0
@@ -1375,12 +1375,13 @@ circuit_append_new_exit(circuit_t *circ, extend_info_t *info)
int
circuit_extend_to_new_exit(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);
if (circuit_send_next_onion_skin(circ)<0) {
warn(LD_CIRC, "Couldn't extend circuit to new point '%s'.",
info->nickname);
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return -1;
}
return 0;
@@ -1731,7 +1732,7 @@ static INLINE int
is_an_entry_node(char *digest)
{
SMARTLIST_FOREACH(entry_nodes, entry_node_t *, entry,
- if(!memcmp(digest, entry->identity, DIGEST_LEN))
+ if (!memcmp(digest, entry->identity, DIGEST_LEN))
return 1;
);
return 0;
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index a90af469b..ab60327a2 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -470,7 +470,7 @@ circuit_get_by_edge_conn(connection_t *conn)
* been marked already.
*/
void
-circuit_unlink_all_from_or_conn(connection_t *conn)
+circuit_unlink_all_from_or_conn(connection_t *conn, int reason)
{
circuit_t *circ;
for (circ = global_circuitlist; circ; circ = circ->next) {
@@ -480,7 +480,7 @@ circuit_unlink_all_from_or_conn(connection_t *conn)
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);
+ circuit_mark_for_close(circ, reason);
}
}
}
@@ -607,7 +607,7 @@ circuit_mark_all_unused_circs(void)
if (CIRCUIT_IS_ORIGIN(circ) &&
!circ->marked_for_close &&
!circ->timestamp_dirty)
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
}
}
@@ -648,7 +648,8 @@ circuit_expire_all_dirty_circs(void)
* rendezvous stream), then mark the other circuit to close as well.
*/
void
-_circuit_mark_for_close(circuit_t *circ, int line, const char *file)
+_circuit_mark_for_close(circuit_t *circ, int reason, int line,
+ const char *file)
{
connection_t *conn;
@@ -663,6 +664,22 @@ _circuit_mark_for_close(circuit_t *circ, int line, const char *file)
circ->marked_for_close_file, circ->marked_for_close);
return;
}
+ if (reason == END_CIRC_AT_ORIGIN) {
+ if (!CIRCUIT_IS_ORIGIN(circ)) {
+ warn(LD_BUG, "Specified 'at-origin' non-reason for ending circuit, "
+ "but circuit was not at origin. (called %s:%d, purpose=%d)",
+ file, line, circ->purpose);
+ }
+ reason = END_CIRC_REASON_NONE;
+ } else if (CIRCUIT_IS_ORIGIN(circ) && reason != END_CIRC_REASON_NONE) {
+ /* Don't warn about this; there are plenty of places where our code
+ * is origin-agnosic. */
+ reason = END_CIRC_REASON_NONE;
+ }
+ if (reason < _END_CIRC_REASON_MIN || reason > _END_CIRC_REASON_MAX) {
+ warn(LD_BUG, "Reason %d out of range at %s:%d", reason, file, line);
+ reason = END_CIRC_REASON_NONE;
+ }
if (circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) {
onion_pending_remove(circ);
@@ -698,7 +715,7 @@ _circuit_mark_for_close(circuit_t *circ, int line, const char *file)
}
if (circ->n_conn)
- connection_send_destroy(circ->n_circ_id, 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) {
@@ -714,7 +731,7 @@ _circuit_mark_for_close(circuit_t *circ, int line, const char *file)
conn->on_circuit = NULL;
}
if (circ->p_conn)
- connection_send_destroy(circ->p_circ_id, 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);
@@ -724,7 +741,7 @@ _circuit_mark_for_close(circuit_t *circ, int line, const char *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);
+ circuit_mark_for_close(circ->rend_splice, reason);
}
circ->rend_splice = NULL;
}
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index cf15b3ce9..1f5238782 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -264,7 +264,7 @@ circuit_expire_building(time_t now)
circuit_state_to_string(victim->state), victim->purpose);
circuit_log_path(LOG_INFO,LD_CIRC,victim);
- circuit_mark_for_close(victim);
+ circuit_mark_for_close(victim, END_CIRC_AT_ORIGIN);
}
}
@@ -523,7 +523,7 @@ circuit_about_to_close_connection(connection_t *conn)
/* Inform any pending (not attached) circs that they should give up. */
circuit_n_conn_done(conn, 0);
/* Now close all the attached circuits on it. */
- circuit_unlink_all_from_or_conn(conn);
+ circuit_unlink_all_from_or_conn(conn, END_CIRC_REASON_OR_CONN_CLOSED);
return;
}
case CONN_TYPE_AP:
@@ -568,7 +568,7 @@ circuit_expire_old_circuits(void)
/* (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);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
} else if (!circ->timestamp_dirty && CIRCUIT_IS_ORIGIN(circ) &&
circ->state == CIRCUIT_STATE_OPEN &&
circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) {
@@ -576,7 +576,7 @@ circuit_expire_old_circuits(void)
if (circ->timestamp_created + CIRCUIT_UNUSED_CIRC_TIMEOUT < now) {
debug(LD_CIRC,"Closing circuit that has been unused for %d seconds.",
(int)(now - circ->timestamp_created));
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
}
}
}
@@ -589,7 +589,7 @@ circuit_testing_opened(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);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
}
/** A testing circuit has failed to build. Take whatever stats we want. */
diff --git a/src/or/command.c b/src/or/command.c
index 4e7e103d7..49a9a8f6a 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -166,7 +166,8 @@ command_process_create_cell(cell_t *cell, connection_t *conn)
if (we_are_hibernating()) {
info(LD_OR,"Received create cell but we're shutting down. Sending back "
"destroy.");
- connection_send_destroy(cell->circ_id, conn);
+ connection_or_send_destroy(cell->circ_id, conn,
+ END_CIRC_REASON_HIBERNATING);
return;
}
@@ -214,7 +215,7 @@ command_process_create_cell(cell_t *cell, connection_t *conn)
/* hand it off to the cpuworkers, and then return */
if (assign_to_cpuworker(NULL, CPUWORKER_TASK_ONION, circ) < 0) {
warn(LD_GENERAL,"Failed to hand off onionskin. Closing.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
return;
}
debug(LD_OR,"success: handed off onionskin.");
@@ -226,12 +227,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) {
warn(LD_OR,"Failed to generate key material. Closing.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
return;
}
if (onionskin_answer(circ, CELL_CREATED_FAST, reply, keys)<0) {
warn(LD_OR,"Failed to reply to CREATE_FAST cell. Closing.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
return;
}
}
@@ -261,7 +262,7 @@ command_process_created_cell(cell_t *cell, connection_t *conn)
if (circ->n_circ_id != cell->circ_id) {
log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,
"got created cell from OPward? Closing.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
return;
}
@@ -269,13 +270,14 @@ command_process_created_cell(cell_t *cell, connection_t *conn)
debug(LD_OR,"at OP. Finishing handshake.");
if (circuit_finish_handshake(circ, cell->command, cell->payload) < 0) {
warn(LD_OR,"circuit_finish_handshake failed.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return;
}
debug(LD_OR,"Moving to next skin.");
if (circuit_send_next_onion_skin(circ) < 0) {
info(LD_OR,"circuit_send_next_onion_skin failed.");
- circuit_mark_for_close(circ); /* XXX push this circuit_close lower */
+ /* XXX push this circuit_close lower */
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return;
}
} else { /* pack it into an extended relay cell, and send it. */
@@ -293,6 +295,7 @@ static void
command_process_relay_cell(cell_t *cell, connection_t *conn)
{
circuit_t *circ;
+ int reason;
circ = circuit_get_by_circid_orconn(cell->circ_id, conn);
@@ -304,22 +307,24 @@ command_process_relay_cell(cell_t *cell, connection_t *conn)
if (circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) {
log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,"circuit in create_wait. Closing.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
return;
}
if (cell->circ_id == circ->p_circ_id) { /* it's an outgoing cell */
- if (circuit_receive_relay_cell(cell, circ, CELL_DIRECTION_OUT) < 0) {
+ if ((reason = circuit_receive_relay_cell(cell, circ,
+ CELL_DIRECTION_OUT)) < 0) {
log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,"circuit_receive_relay_cell "
"(forward) failed. Closing.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, -reason);
return;
}
} else { /* it's an ingoing cell */
- if (circuit_receive_relay_cell(cell, circ, CELL_DIRECTION_IN) < 0) {
+ if ((reason = circuit_receive_relay_cell(cell, circ,
+ CELL_DIRECTION_IN)) < 0) {
log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,"circuit_receive_relay_cell "
"(backward) failed. Closing.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, -reason);
return;
}
}
@@ -342,9 +347,10 @@ static void
command_process_destroy_cell(cell_t *cell, connection_t *conn)
{
circuit_t *circ;
+ uint8_t reason;
circ = circuit_get_by_circid_orconn(cell->circ_id, conn);
-
+ reason = (uint8_t)cell->payload[0];
if (!circ) {
info(LD_OR,"unknown circuit %d on connection from %s:%d. Dropping.",
cell->circ_id, conn->address, conn->port);
@@ -355,15 +361,17 @@ command_process_destroy_cell(cell_t *cell, connection_t *conn)
if (cell->circ_id == circ->p_circ_id) {
/* the destroy came from behind */
circuit_set_circid_orconn(circ, 0, NULL, P_CONN_CHANGED);
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, reason);
} else { /* the destroy came from ahead */
circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED);
if (CIRCUIT_IS_ORIGIN(circ)) {
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, reason);
} else {
+ char payload[1];
debug(LD_OR, "Delivering 'truncated' back.");
+ payload[0] = (char)reason;
connection_edge_send_command(NULL, circ, RELAY_COMMAND_TRUNCATED,
- NULL, 0, NULL);
+ payload, sizeof(payload), NULL);
}
}
}
diff --git a/src/or/connection.c b/src/or/connection.c
index 64a8679dd..ef94b60c3 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -1038,7 +1038,8 @@ connection_read_bucket_decrement(connection_t *conn, int num_read)
}
}
-/** DOCDOC */
+/** If we have exhaused our global read bucket, or the read bucket for conn,
+ * stop reading. */
static void
connection_consider_empty_buckets(connection_t *conn)
{
@@ -1546,7 +1547,8 @@ connection_write_to_buf(const char *string, size_t len, connection_t *conn)
/* if it failed, it means we have our package/delivery windows set
wrong compared to our max outbuf size. close the whole circuit. */
warn(LD_NET,"write_to_buf failed. Closing circuit (fd %d).", conn->s);
- circuit_mark_for_close(circuit_get_by_edge_conn(conn));
+ circuit_mark_for_close(circuit_get_by_edge_conn(conn),
+ END_CIRC_REASON_INTERNAL);
} else {
warn(LD_NET,"write_to_buf failed. Closing connection (fd %d).", conn->s);
connection_mark_for_close(conn);
@@ -1784,28 +1786,6 @@ connection_state_is_connecting(connection_t *conn)
return 0;
}
-/** Write a destroy cell with circ ID <b>circ_id</b> onto OR connection
- * <b>conn</b>.
- *
- * Return 0.
- */
-/*XXXX Why isn't this in connection_or.c?*/
-int
-connection_send_destroy(uint16_t circ_id, connection_t *conn)
-{
- cell_t cell;
-
- tor_assert(conn);
- tor_assert(connection_speaks_cells(conn));
-
- memset(&cell, 0, sizeof(cell_t));
- cell.circ_id = circ_id;
- cell.command = CELL_DESTROY;
- debug(LD_OR,"Sending destroy (circID %d).", circ_id);
- connection_or_write_cell_to_buf(&cell, conn);
- return 0;
-}
-
/** Alloocates a base64'ed authenticator for use in http or https
* auth, based on the input string <b>authenticator</b>. Returns it
* if success, else returns NULL. */
@@ -1829,9 +1809,12 @@ alloc_http_authenticator(const char *authenticator)
return base64_authenticator;
}
-/** DOCDOC
- * XXXX ipv6 NM
+/** Given a socket handle, check whether the local address (sockname) of the
+ * socket is one that we've connected from before. If so, double-check
+ * whether our address has changed and we need to generate keys. If we do,
+ * call init_keys().
*/
+/* XXXX Handle IPv6, eventually. */
static void
client_check_address_changed(int sock)
{
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index 0954bc4e1..93d6e884a 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -1208,7 +1208,7 @@ 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);
+ circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
return -1;
}
@@ -1254,7 +1254,7 @@ connection_ap_handshake_send_resolve(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);
+ circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
return -1;
}
@@ -1519,8 +1519,8 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
connection_edge_end(n_stream, END_STREAM_REASON_EXITPOLICY,
n_stream->cpath_layer);
connection_free(n_stream);
- circuit_mark_for_close(circ); /* knock the whole thing down, somebody
- * screwed up */
+ /* knock the whole thing down, somebody screwed up */
+ circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED);
tor_free(address);
return 0;
}
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index a5e837cd8..e714a65dd 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -779,3 +779,26 @@ loop:
goto loop; /* process the remainder of the buffer */
}
+/** Write a destroy cell with circ ID <b>circ_id</b> and reason <b>reason</b>
+ * onto OR connection <b>conn</b>. Don't perform range-checking on reason:
+ * we may want to propagate reasons from other cells.
+ *
+ * Return 0.
+ */
+int
+connection_or_send_destroy(uint16_t circ_id, connection_t *conn, int reason)
+{
+ cell_t cell;
+
+ tor_assert(conn);
+ tor_assert(connection_speaks_cells(conn));
+
+ memset(&cell, 0, sizeof(cell_t));
+ cell.circ_id = circ_id;
+ cell.command = CELL_DESTROY;
+ cell.payload[0] = (uint8_t) reason;
+ debug(LD_OR,"Sending destroy (circID %d).", circ_id);
+ connection_or_write_cell_to_buf(&cell, conn);
+ return 0;
+}
+
diff --git a/src/or/control.c b/src/or/control.c
index b5efb84f6..d557fab85 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -1611,7 +1611,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
/* now that we've populated the cpath, start extending */
if (zero_circ) {
if (circuit_handle_first_hop(circ) < 0) {
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
if (v0)
send_control0_error(conn, ERR_INTERNAL, "couldn't start circuit");
else
@@ -1624,7 +1624,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
if (circuit_send_next_onion_skin(circ) < 0) {
info(LD_CONTROL,
"send_next_onion_skin failed; circuit marked for closing.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
if (v0)
send_control0_error(conn, ERR_INTERNAL, "couldn't send onion skin");
else
@@ -1967,7 +1967,7 @@ handle_control_closecircuit(connection_t *conn, uint32_t len,
}
if (!safe || !circ->p_streams) {
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_REASON_NONE);
}
send_control_done(conn);
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index de5b33a4d..ad0785253 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -169,7 +169,7 @@ connection_cpu_process_inbuf(connection_t *conn)
debug(LD_OR,
"decoding onionskin failed. (Old key or bad software.) Closing.");
if (circ)
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL);
goto done_processing;
}
if (!circ) {
@@ -185,7 +185,7 @@ connection_cpu_process_inbuf(connection_t *conn)
if (onionskin_answer(circ, CELL_CREATED, buf+TAG_LEN,
buf+TAG_LEN+ONIONSKIN_REPLY_LEN) < 0) {
warn(LD_OR,"onionskin_answer failed. Closing.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
goto done_processing;
}
debug(LD_OR,"onionskin_answer succeeded. Yay.");
diff --git a/src/or/onion.c b/src/or/onion.c
index 7aaf5ddeb..cbe7bd673 100644
--- a/src/or/onion.c
+++ b/src/or/onion.c
@@ -71,7 +71,7 @@ onion_pending_add(circuit_t *circ)
onion_pending_remove(ol_list->circ);
info(LD_CIRC,
"Circuit create request is too old; cancelling due to overload.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
}
return 0;
}
diff --git a/src/or/or.h b/src/or/or.h
index fe7838242..06043f9e3 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -481,6 +481,19 @@ typedef enum {
#define RESOLVED_TYPE_ERROR_TRANSIENT 0xF0
#define RESOLVED_TYPE_ERROR 0xF1
+#define END_CIRC_AT_ORIGIN -1
+#define _END_CIRC_REASON_MIN 0
+#define END_CIRC_REASON_NONE 0
+#define END_CIRC_REASON_TORPROTOCOL 1
+#define END_CIRC_REASON_INTERNAL 2
+#define END_CIRC_REASON_REQUESTED 3
+#define END_CIRC_REASON_HIBERNATING 4
+#define END_CIRC_REASON_RESOURCELIMIT 5
+#define END_CIRC_REASON_CONNECTFAILED 6
+#define END_CIRC_REASON_OR_IDENTITY 7
+#define END_CIRC_REASON_OR_CONN_CLOSED 8
+#define _END_CIRC_REASON_MAX 8
+
/** Length of 'y' portion of 'y.onion' URL. */
#define REND_SERVICE_ID_LEN 16
@@ -1494,7 +1507,7 @@ circuit_t *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);
-void circuit_unlink_all_from_or_conn(connection_t *conn);
+void circuit_unlink_all_from_or_conn(connection_t *conn, int reason);
circuit_t *circuit_get_by_global_id(uint32_t id);
circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query,
uint8_t purpose);
@@ -1506,10 +1519,11 @@ circuit_t *circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
int need_capacity, int internal);
void circuit_mark_all_unused_circs(void);
void circuit_expire_all_dirty_circs(void);
-void _circuit_mark_for_close(circuit_t *circ, int line, const char *file);
+void _circuit_mark_for_close(circuit_t *circ, int reason,
+ int line, const char *file);
-#define circuit_mark_for_close(c) \
- _circuit_mark_for_close((c), __LINE__, _SHORT_FILE_)
+#define circuit_mark_for_close(c, reason) \
+ _circuit_mark_for_close((c), (reason), __LINE__, _SHORT_FILE_)
void assert_cpath_layer_ok(const crypt_path_t *cp);
void assert_circuit_ok(const circuit_t *c);
@@ -1651,7 +1665,6 @@ int connection_is_listener(connection_t *conn);
int connection_state_is_open(connection_t *conn);
int connection_state_is_connecting(connection_t *conn);
-int connection_send_destroy(uint16_t circ_id, connection_t *conn);
char *alloc_http_authenticator(const char *authenticator);
void assert_connection_ok(connection_t *conn, time_t now);
@@ -1742,6 +1755,8 @@ int connection_tls_start_handshake(connection_t *conn, int receiving);
int connection_tls_continue_handshake(connection_t *conn);
void connection_or_write_cell_to_buf(const cell_t *cell, connection_t *conn);
+int connection_or_send_destroy(uint16_t circ_id, connection_t *conn,
+ int reason);
/********************************* control.c ***************************/
diff --git a/src/or/relay.c b/src/or/relay.c
index f923ae59a..8ec5142e7 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -138,6 +138,8 @@ relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in,
* connection_edge.
* - Else connection_or_write_cell_to_buf to the conn on the other
* side of the circuit.
+ *
+ * Return -reason on failure.
*/
int
circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
@@ -145,6 +147,7 @@ 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;
+ int reason;
tor_assert(cell);
tor_assert(circ);
@@ -163,20 +166,21 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
if (cell_direction == CELL_DIRECTION_OUT) {
++stats_n_relay_cells_delivered;
debug(LD_OR,"Sending away from origin.");
- if (connection_edge_process_relay_cell(cell, circ, conn, NULL) < 0) {
+ if ((reason=connection_edge_process_relay_cell(cell, circ, conn, NULL))
+ < 0) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"connection_edge_process_relay_cell (away from origin) "
"failed.");
- return -1;
+ return reason;
}
}
if (cell_direction == CELL_DIRECTION_IN) {
++stats_n_relay_cells_delivered;
debug(LD_OR,"Sending to origin.");
- if (connection_edge_process_relay_cell(cell, circ, conn,
- layer_hint) < 0) {
+ if ((reason = connection_edge_process_relay_cell(cell, circ, conn,
+ layer_hint)) < 0) {
warn(LD_OR,"connection_edge_process_relay_cell (at origin) failed.");
- return -1;
+ return reason;
}
}
return 0;
@@ -197,19 +201,19 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction)
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) {
+ if ((reason = circuit_receive_relay_cell(cell, circ->rend_splice,
+ CELL_DIRECTION_IN)) < 0) {
warn(LD_REND, "Error relaying cell across rendezvous; closing "
"circuits");
/* XXXX Do this here, or just return -1? */
- circuit_mark_for_close(circ);
- return -1;
+ circuit_mark_for_close(circ, -reason);
+ return reason;
}
return 0;
}
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Didn't recognize cell, but circ stops here! Closing circ.");
- return -1;
+ return -END_CIRC_REASON_TORPROTOCOL;
}
debug(LD_OR,"Passing on unrecognized cell.");
@@ -489,7 +493,7 @@ connection_edge_send_command(connection_t *fromconn, circuit_t *circ,
if (circuit_package_relay_cell(&cell, circ, cell_direction, cpath_layer)
< 0) {
warn(LD_BUG,"circuit_package_relay_cell failed. Closing.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
return -1;
}
return 0;
@@ -655,7 +659,7 @@ connection_edge_process_end_not_open(
warn(LD_PROTOCOL,
"Got an end because of %s, but we're not an AP. Closing.",
connection_edge_end_reason_str(reason));
- return -1;
+ return - END_CIRC_REASON_TORPROTOCOL;
}
info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.",
safe_str(conn->socks_request->address),
@@ -848,7 +852,7 @@ connection_edge_process_relay_cell_not_open(
* If <b>layer_hint</b> is defined, then we're the origin of the
* circuit, and it specifies the hop that packaged <b>cell</b>.
*
- * Return -1 if you want to warn and tear down the circuit, else 0.
+ * Return -reason if you want to warn and tear down the circuit, else 0.
*/
static int
connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
@@ -858,6 +862,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
static int num_seen=0;
relay_header_t rh;
unsigned domain = layer_hint?LD_APP:LD_EXIT;
+ int reason;
tor_assert(cell);
tor_assert(circ);
@@ -869,7 +874,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
if (rh.length > RELAY_PAYLOAD_SIZE) {
warn(LD_PROTOCOL, "Relay cell length field too long. Closing circuit.");
- return -1;
+ return - END_CIRC_REASON_TORPROTOCOL;
}
/* either conn is NULL, in which case we've got a control cell, or else
@@ -904,7 +909,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL,
conn->cpath_layer);
connection_mark_for_close(conn);
- return -1;
+ return -END_CIRC_REASON_TORPROTOCOL;
}
debug(domain,"circ deliver_window now %d.", layer_hint ?
layer_hint->deliver_window : circ->deliver_window);
@@ -919,7 +924,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
if (--conn->deliver_window < 0) { /* is it below 0 after decrement? */
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"(relay data) conn deliver_window below 0. Killing.");
- return -1; /* somebody's breaking protocol. kill the whole circuit. */
+ return -END_CIRC_REASON_TORPROTOCOL;
}
stats_n_data_bytes_received += rh.length;
@@ -974,14 +979,14 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
return 0;
}
debug(domain,"Got an extended cell! Yay.");
- if (circuit_finish_handshake(circ, CELL_CREATED,
- cell->payload+RELAY_HEADER_SIZE) < 0) {
+ if ((reason = circuit_finish_handshake(circ, CELL_CREATED,
+ cell->payload+RELAY_HEADER_SIZE)) < 0) {
warn(domain,"circuit_finish_handshake failed.");
- return -1;
+ return reason;
}
- if (circuit_send_next_onion_skin(circ)<0) {
+ if ((reason=circuit_send_next_onion_skin(circ))<0) {
info(domain,"circuit_send_next_onion_skin() failed.");
- return -1;
+ return reason;
}
return 0;
case RELAY_COMMAND_TRUNCATE:
@@ -990,12 +995,17 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
return 0;
}
if (circ->n_conn) {
- connection_send_destroy(circ->n_circ_id, 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);
}
debug(LD_EXIT, "Processed 'truncate', replying.");
- connection_edge_send_command(NULL, circ, RELAY_COMMAND_TRUNCATED,
- NULL, 0, NULL);
+ {
+ char payload[1];
+ payload[0] = (char)END_CIRC_REASON_REQUESTED;
+ connection_edge_send_command(NULL, circ, RELAY_COMMAND_TRUNCATED,
+ payload, sizeof(payload), NULL);
+ }
return 0;
case RELAY_COMMAND_TRUNCATED:
if (!layer_hint) {
@@ -1008,7 +1018,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
if (conn) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"'connected' unsupported while open. Closing circ.");
- return -1;
+ return -END_CIRC_REASON_TORPROTOCOL;
}
info(domain,"'connected' received, no conn attached anymore. Ignoring.");
return 0;
@@ -1055,7 +1065,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
case RELAY_COMMAND_RESOLVED:
if (conn) {
warn(domain,"'resolved' unsupported while open. Closing circ.");
- return -1;
+ return -END_CIRC_REASON_TORPROTOCOL;
}
info(domain,"'resolved' received, no conn attached anymore. Ignoring.");
return 0;
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index f80c86a2c..3e89d8fa9 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -35,7 +35,7 @@ rend_client_send_establish_rendezvous(circuit_t *circ)
if (crypto_rand(circ->rend_cookie, REND_COOKIE_LEN) < 0) {
warn(LD_BUG, "Internal error: Couldn't produce random cookie.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return -1;
}
if (connection_edge_send_command(NULL,circ,
@@ -154,8 +154,8 @@ rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc)
return 0;
err:
- circuit_mark_for_close(introcirc);
- circuit_mark_for_close(rendcirc);
+ circuit_mark_for_close(introcirc, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(rendcirc, END_CIRC_AT_ORIGIN);
return -1;
}
@@ -186,7 +186,7 @@ rend_client_introduction_acked(circuit_t *circ,
if (circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
warn(LD_PROTOCOL, "Received REND_INTRODUCE_ACK on unexpected circuit %d.",
circ->n_circ_id);
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return -1;
}
@@ -208,7 +208,7 @@ rend_client_introduction_acked(circuit_t *circ,
}
/* close the circuit: we won't need it anymore. */
circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACKED;
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
} else {
/* It's a NAK; the introduction point didn't relay our request. */
circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
@@ -226,7 +226,7 @@ rend_client_introduction_acked(circuit_t *circ,
if (!extend_info) {
warn(LD_REND, "No introduction points left for %s. Closing.",
safe_str(circ->rend_query));
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return -1;
}
info(LD_REND,
@@ -340,7 +340,7 @@ rend_client_rendezvous_acked(circuit_t *circ, const char *request,
if (circ->purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND) {
warn(LD_PROTOCOL,"Got a rendezvous ack when we weren't expecting one. "
"Closing circ.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return -1;
}
info(LD_REND,"Got rendezvous ack. This circuit is now ready for "
@@ -362,7 +362,7 @@ rend_client_receive_rendezvous(circuit_t *circ, const char *request,
|| !circ->build_state->pending_final_cpath) {
warn(LD_PROTOCOL,"Got rendezvous2 cell from hidden service, but not "
"expecting it. Closing.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return -1;
}
@@ -408,7 +408,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);
+ circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
return -1;
}
diff --git a/src/or/rendmid.c b/src/or/rendmid.c
index 4059d3e69..cf0ec0baa 100644
--- a/src/or/rendmid.c
+++ b/src/or/rendmid.c
@@ -25,6 +25,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
size_t asn1len;
circuit_t *c;
char serviceid[REND_SERVICE_ID_LEN+1];
+ int reason = END_CIRC_REASON_INTERNAL;
info(LD_REND,
"Received an ESTABLISH_INTRO request on circuit %d", circ->p_circ_id);
@@ -32,6 +33,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) {
warn(LD_PROTOCOL,
"Rejecting ESTABLISH_INTRO on non-OR or non-edge circuit.");
+ reason = END_CIRC_REASON_TORPROTOCOL;
goto err;
}
if (request_len < 2+DIGEST_LEN)
@@ -44,6 +46,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
goto truncated;
pk = crypto_pk_asn1_decode(request+2, asn1len);
if (!pk) {
+ reason = END_CIRC_REASON_TORPROTOCOL;
warn(LD_PROTOCOL, "Couldn't decode public key.");
goto err;
}
@@ -57,6 +60,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
}
if (memcmp(expected_digest, request+2+asn1len, DIGEST_LEN)) {
warn(LD_PROTOCOL, "Hash of session info was not as expected.");
+ reason = END_CIRC_REASON_TORPROTOCOL;
goto err;
}
/* Rest of body: signature of previous data */
@@ -65,6 +69,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
request_len-(2+DIGEST_LEN+asn1len))<0) {
warn(LD_PROTOCOL,
"Incorrect signature on ESTABLISH_INTRO cell; rejecting.");
+ reason = END_CIRC_REASON_TORPROTOCOL;
goto err;
}
@@ -85,7 +90,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
c,pk_digest,CIRCUIT_PURPOSE_INTRO_POINT))) {
info(LD_REND, "Replacing old circuit %d for service %s",
c->p_circ_id, safe_str(serviceid));
- circuit_mark_for_close(c);
+ circuit_mark_for_close(c, END_CIRC_REASON_REQUESTED);
}
/* Acknowledge the request. */
@@ -107,9 +112,10 @@ rend_mid_establish_intro(circuit_t *circ, const char *request,
return 0;
truncated:
warn(LD_PROTOCOL, "Rejecting truncated ESTABLISH_INTRO cell.");
+ reason = END_CIRC_REASON_TORPROTOCOL;
err:
if (pk) crypto_free_pk_env(pk);
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, reason);
return -1;
}
@@ -168,7 +174,7 @@ rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len)
if (connection_edge_send_command(NULL,circ,RELAY_COMMAND_INTRODUCE_ACK,
NULL,0,NULL)) {
warn(LD_GENERAL, "Unable to send INTRODUCE_ACK cell to Tor client.");
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
return -1;
}
@@ -179,7 +185,8 @@ rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len)
if (connection_edge_send_command(NULL,circ,RELAY_COMMAND_INTRODUCE_ACK,
nak_body, 1, NULL)) {
warn(LD_GENERAL, "Unable to send NAK to Tor client.");
- circuit_mark_for_close(circ); /* Is this right? */
+ /* Is this right? */
+ circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
}
return -1;
}
@@ -192,6 +199,7 @@ rend_mid_establish_rendezvous(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) {
warn(LD_PROTOCOL,
@@ -214,6 +222,7 @@ rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
RELAY_COMMAND_RENDEZVOUS_ESTABLISHED,
"", 0, NULL)<0) {
warn(LD_PROTOCOL, "Couldn't send RENDEZVOUS_ESTABLISHED cell.");
+ reason = END_CIRC_REASON_INTERNAL;
goto err;
}
@@ -227,7 +236,7 @@ rend_mid_establish_rendezvous(circuit_t *circ, const char *request,
return 0;
err:
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, reason);
return -1;
}
@@ -240,7 +249,7 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len)
{
circuit_t *rend_circ;
char hexid[9];
-
+ int reason = END_CIRC_REASON_INTERNAL;
base16_encode(hexid,9,request,request_len<4?request_len:4);
if (request_len>=4) {
@@ -252,6 +261,7 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len)
info(LD_REND,
"Tried to complete rendezvous on non-OR or non-edge circuit %d.",
circ->p_circ_id);
+ reason = END_CIRC_REASON_TORPROTOCOL;
goto err;
}
@@ -259,6 +269,7 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len)
warn(LD_PROTOCOL,
"Rejecting RENDEZVOUS1 cell with bad length (%d) on circuit %d.",
(int)request_len, circ->p_circ_id);
+ reason = END_CIRC_REASON_TORPROTOCOL;
goto err;
}
@@ -267,6 +278,7 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len)
warn(LD_PROTOCOL,
"Rejecting RENDEZVOUS1 cell with unrecognized rendezvous cookie %s.",
hexid);
+ reason = END_CIRC_REASON_TORPROTOCOL;
goto err;
}
@@ -295,7 +307,7 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len)
return 0;
err:
- circuit_mark_for_close(circ);
+ circuit_mark_for_close(circ, reason);
return -1;
}
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 81762c43a..85da11603 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -605,7 +605,7 @@ 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);
+ if (launched) circuit_mark_for_close(launched, END_CIRC_AT_ORIGIN);
if (extend_info) extend_info_free(extend_info);
return -1;
}
@@ -751,7 +751,7 @@ rend_service_intro_has_opened(circuit_t *circuit)
return;
err:
- circuit_mark_for_close(circuit);
+ circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN);
}
/** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a
@@ -778,7 +778,7 @@ rend_service_intro_established(circuit_t *circuit, const char *request,
return 0;
err:
- circuit_mark_for_close(circuit);
+ circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN);
return -1;
}
@@ -852,7 +852,7 @@ rend_service_rendezvous_has_opened(circuit_t *circuit)
return;
err:
- circuit_mark_for_close(circuit);
+ circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN);
}
/*