[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[PATCH]: Export END_CIRC_REASON_* to controler
Attached is a patch to export circuit failure reasons to the
controller. I had to convert several END_CIRC_AT_ORIGIN reason
codes to the real reason codes for calls to circuit_mark_for_close().
As far as I can tell, this shouldn't break anything because
circuit_mark_for_close() actually does an expicit check and
if the circuit is an origin circuit, it resets the reason code
to NONE.
Note that I did not do anything with the conn->use_extended_events
setting since that requires some pretty substantial infrastructure
changes..
The patch to the spec file is included in the diff. I've been testing
it for a while with a new version of my scanner and it seems to be OK.
--
Mike Perry
Mad Computer Scientist
fscked.org evil labs
Index: src/or/circuitlist.c
===================================================================
--- src/or/circuitlist.c (revision 8642)
+++ src/or/circuitlist.c (working copy)
@@ -796,7 +796,7 @@
if (CIRCUIT_IS_ORIGIN(circ) &&
!circ->marked_for_close &&
!circ->timestamp_dirty)
- circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circ, END_CIRC_REASON_REQUESTED);
}
}
@@ -840,6 +840,7 @@
_circuit_mark_for_close(circuit_t *circ, int reason, int line,
const char *file)
{
+ int orig_reason = reason;
assert_circuit_ok(circ);
tor_assert(line);
tor_assert(file);
@@ -861,11 +862,13 @@
} 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-agnostic. */
+ /* In fact, due to the desire to export reason information to the
+ * controller, it has been made even more "origin-agnostic" than before */
reason = END_CIRC_REASON_NONE;
}
if (reason < _END_CIRC_REASON_MIN || reason > _END_CIRC_REASON_MAX) {
log_warn(LD_BUG, "Reason %d out of range at %s:%d", reason, file, line);
- reason = END_CIRC_REASON_NONE;
+ orig_reason = reason = END_CIRC_REASON_NONE;
}
if (circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) {
@@ -888,7 +891,8 @@
}
if (CIRCUIT_IS_ORIGIN(circ)) {
control_event_circuit_status(TO_ORIGIN_CIRCUIT(circ),
- (circ->state == CIRCUIT_STATE_OPEN)?CIRC_EVENT_CLOSED:CIRC_EVENT_FAILED);
+ (circ->state == CIRCUIT_STATE_OPEN)?CIRC_EVENT_CLOSED:CIRC_EVENT_FAILED,
+ orig_reason);
}
if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
Index: src/or/rendservice.c
===================================================================
--- src/or/rendservice.c (revision 8642)
+++ src/or/rendservice.c (working copy)
@@ -612,7 +612,7 @@
err:
if (dh) crypto_dh_free(dh);
if (launched)
- circuit_mark_for_close(TO_CIRCUIT(launched), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(launched), END_CIRC_REASON_TORPROTOCOL);
if (extend_info) extend_info_free(extend_info);
return -1;
}
@@ -763,7 +763,7 @@
return;
err:
- circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_REASON_TORPROTOCOL);
}
/** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a
@@ -793,7 +793,7 @@
return 0;
err:
- circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_REASON_TORPROTOCOL);
return -1;
}
@@ -869,7 +869,7 @@
return;
err:
- circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circuit), END_CIRC_REASON_TORPROTOCOL);
}
/*
Index: src/or/control.c
===================================================================
--- src/or/control.c (revision 8642)
+++ src/or/control.c (working copy)
@@ -1859,8 +1859,9 @@
/* now that we've populated the cpath, start extending */
if (zero_circ) {
- if (circuit_handle_first_hop(circ) < 0) {
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ int err_reason = 0;
+ if ((err_reason = circuit_handle_first_hop(circ)) < 0) {
+ circuit_mark_for_close(TO_CIRCUIT(circ), err_reason);
if (v0)
send_control0_error(conn, ERR_INTERNAL, "couldn't start circuit");
else
@@ -1869,11 +1870,12 @@
}
} else {
if (circ->_base.state == CIRCUIT_STATE_OPEN) {
+ int err_reason = 0;
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
- if (circuit_send_next_onion_skin(circ) < 0) {
+ if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) {
log_info(LD_CONTROL,
"send_next_onion_skin failed; circuit marked for closing.");
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), err_reason);
if (v0)
send_control0_error(conn, ERR_INTERNAL, "couldn't send onion skin");
else
@@ -2737,7 +2739,8 @@
/** Something has happened to circuit <b>circ</b>: tell any interested
* control connections. */
int
-control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp)
+control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
+ int rsn)
{
char *path=NULL, *msg;
if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS))
@@ -2759,7 +2762,8 @@
}
if (EVENT_IS_INTERESTING1(EVENT_CIRCUIT_STATUS)) {
const char *status;
- switch (tp)
+ const char *reason = "";
+ switch (tp)
{
case CIRC_EVENT_LAUNCHED: status = "LAUNCHED"; break;
case CIRC_EVENT_BUILT: status = "BUILT"; break;
@@ -2770,18 +2774,37 @@
log_warn(LD_BUG, "Unrecognized status code %d", (int)tp);
return 0;
}
+
+ if(tp == CIRC_EVENT_FAILED || tp == CIRC_EVENT_CLOSED) {
+ switch (rsn)
+ {
+ case END_CIRC_AT_ORIGIN: reason = " REASON=ORIGIN"; break;
+ case END_CIRC_REASON_NONE: reason = " REASON=NONE"; break;
+ case END_CIRC_REASON_TORPROTOCOL: reason = " REASON=TORPROTOCOL"; break;
+ case END_CIRC_REASON_INTERNAL: reason = " REASON=INTERNAL"; break;
+ case END_CIRC_REASON_REQUESTED: reason = " REASON=REQUESTED"; break;
+ case END_CIRC_REASON_HIBERNATING: reason = " REASON=HIBERNATING"; break;
+ case END_CIRC_REASON_RESOURCELIMIT: reason = " REASON=RESOURCELIMIT"; break;
+ case END_CIRC_REASON_CONNECTFAILED: reason = " REASON=CONNECTFAILED"; break;
+ case END_CIRC_REASON_OR_IDENTITY: reason = " REASON=OR_IDENTITY"; break;
+ case END_CIRC_REASON_OR_CONN_CLOSED: reason = " REASON=OR_CONN_CLOSED"; break;
+ default:
+ log_warn(LD_BUG, "Unrecognized reason code %d", (int)rsn);
+ }
+ }
+
if (EVENT_IS_INTERESTING1S(EVENT_CIRCUIT_STATUS)) {
send_control1_event(EVENT_CIRCUIT_STATUS, SHORT_NAMES,
- "650 CIRC %lu %s %s\r\n",
+ "650 CIRC %lu %s %s%s\r\n",
(unsigned long)circ->global_identifier,
- status, path);
+ status, path, reason);
}
if (EVENT_IS_INTERESTING1L(EVENT_CIRCUIT_STATUS)) {
char *vpath = circuit_list_path_for_controller(circ);
send_control1_event(EVENT_CIRCUIT_STATUS, LONG_NAMES,
- "650 CIRC %lu %s %s\r\n",
+ "650 CIRC %lu %s %s%s\r\n",
(unsigned long)circ->global_identifier,
- status, vpath);
+ status, vpath, reason);
tor_free(vpath);
}
}
Index: src/or/or.h
===================================================================
--- src/or/or.h (revision 8642)
+++ src/or/or.h (working copy)
@@ -2070,7 +2070,7 @@
int connection_control_process_inbuf(control_connection_t *conn);
int control_event_circuit_status(origin_circuit_t *circ,
- circuit_status_event_t e);
+ circuit_status_event_t e, int rsn);
int control_event_stream_status(edge_connection_t *conn,
stream_status_event_t e);
int control_event_or_conn_status(or_connection_t *conn,
Index: src/or/command.c
===================================================================
--- src/or/command.c (revision 8642)
+++ src/or/command.c (working copy)
@@ -273,18 +273,19 @@
if (CIRCUIT_IS_ORIGIN(circ)) { /* we're the OP. Handshake this. */
origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
+ int err_reason = 0;
log_debug(LD_OR,"at OP. Finishing handshake.");
- if (circuit_finish_handshake(origin_circ, cell->command,
- cell->payload) < 0) {
+ if ((err_reason = 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);
+ circuit_mark_for_close(circ, err_reason);
return;
}
log_debug(LD_OR,"Moving to next skin.");
- if (circuit_send_next_onion_skin(origin_circ) < 0) {
+ if ((err_reason = 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);
+ circuit_mark_for_close(circ, err_reason);
return;
}
} else { /* pack it into an extended relay cell, and send it. */
Index: src/or/circuituse.c
===================================================================
--- src/or/circuituse.c (revision 8642)
+++ src/or/circuituse.c (working copy)
@@ -265,7 +265,7 @@
circuit_state_to_string(victim->state), victim->purpose);
circuit_log_path(LOG_INFO,LD_CIRC,TO_ORIGIN_CIRCUIT(victim));
- circuit_mark_for_close(victim, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(victim, END_CIRC_REASON_CONNECTFAILED);
}
}
@@ -591,7 +591,7 @@
log_debug(LD_CIRC,
"Closing circuit that has been unused for %d seconds.",
(int)(now - circ->timestamp_created));
- circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(circ, END_CIRC_REASON_REQUESTED);
}
}
}
@@ -674,7 +674,7 @@
void
circuit_has_opened(origin_circuit_t *circ)
{
- control_event_circuit_status(circ, CIRC_EVENT_BUILT);
+ control_event_circuit_status(circ, CIRC_EVENT_BUILT, 0);
switch (TO_CIRCUIT(circ)->purpose) {
case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
Index: src/or/rendmid.c
===================================================================
--- src/or/rendmid.c (revision 8642)
+++ src/or/rendmid.c (working copy)
@@ -90,7 +90,7 @@
while ((c = circuit_get_intro_point(pk_digest))) {
log_info(LD_REND, "Replacing old circuit for service %s",
safe_str(serviceid));
- circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_REASON_REQUESTED);
+ circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_AT_ORIGIN);
/* Now it's marked, and it won't be returned next time. */
}
Index: src/or/circuitbuild.c
===================================================================
--- src/or/circuitbuild.c (revision 8642)
+++ src/or/circuitbuild.c (working copy)
@@ -298,19 +298,20 @@
int need_uptime, int need_capacity, int internal)
{
origin_circuit_t *circ;
+ int err_reason = 0;
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(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return NULL;
}
- control_event_circuit_status(circ, CIRC_EVENT_LAUNCHED);
+ control_event_circuit_status(circ, CIRC_EVENT_LAUNCHED, 0);
- if (circuit_handle_first_hop(circ) < 0) {
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ if ((err_reason = circuit_handle_first_hop(circ)) < 0) {
+ circuit_mark_for_close(TO_CIRCUIT(circ), err_reason);
return NULL;
}
return circ;
@@ -327,6 +328,7 @@
or_connection_t *n_conn;
char tmpbuf[INET_NTOA_BUF_LEN];
struct in_addr in;
+ int err_reason = 0;
firsthop = onion_next_hop_in_cpath(circ->cpath);
tor_assert(firsthop);
@@ -359,7 +361,7 @@
firsthop->extend_info->identity_digest);
if (!n_conn) { /* connect failed, forget the whole thing */
log_info(LD_CIRC,"connect to firsthop failed. Closing.");
- return -1;
+ return -END_CIRC_REASON_CONNECTFAILED;
}
}
@@ -374,9 +376,9 @@
circ->_base.n_port = n_conn->_base.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) {
+ if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) {
log_info(LD_CIRC,"circuit_send_next_onion_skin failed.");
- return -1;
+ return err_reason;
}
}
return 0;
@@ -393,6 +395,7 @@
circuit_n_conn_done(or_connection_t *or_conn, int status)
{
smartlist_t *changed_circs;
+ int err_reason = 0;
log_debug(LD_CIRC,"or_conn to %s, status=%d",
or_conn->nickname ? or_conn->nickname : "NULL", status);
@@ -421,10 +424,10 @@
* set_circid_orconn here. */
circ->n_conn = or_conn;
if (CIRCUIT_IS_ORIGIN(circ)) {
- if (circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ)) < 0) {
+ if ((err_reason = 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);
+ circuit_mark_for_close(circ, err_reason);
continue;
/* XXX could this be bad, eg if next_onion_skin failed because conn
* died? */
@@ -864,7 +867,7 @@
log_info(LD_CIRC,"Finished building %scircuit hop:",
(reply_type == CELL_CREATED_FAST) ? "fast " : "");
circuit_log_path(LOG_INFO,LD_CIRC,circ);
- control_event_circuit_status(circ, CIRC_EVENT_EXTENDED);
+ control_event_circuit_status(circ, CIRC_EVENT_EXTENDED, 0);
return 0;
}
@@ -888,7 +891,7 @@
* means that a connection broke or an extend failed. For now,
* just give up.
*/
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
return 0;
#if 0
@@ -1392,12 +1395,13 @@
int
circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info)
{
+ int err_reason = 0;
circuit_append_new_exit(circ, info);
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
- if (circuit_send_next_onion_skin(circ)<0) {
+ if ((err_reason = 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(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), err_reason);
return -1;
}
return 0;
Index: src/or/rendclient.c
===================================================================
--- src/or/rendclient.c (revision 8642)
+++ src/or/rendclient.c (working copy)
@@ -34,7 +34,7 @@
if (crypto_rand(circ->rend_cookie, REND_COOKIE_LEN) < 0) {
log_warn(LD_BUG, "Internal error: Couldn't produce random cookie.");
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return -1;
}
if (connection_edge_send_command(NULL,TO_CIRCUIT(circ),
@@ -157,8 +157,8 @@
return 0;
err:
- circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_AT_ORIGIN);
- circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_REASON_INTERNAL);
+ circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_REASON_INTERNAL);
return -1;
}
@@ -190,7 +190,7 @@
log_warn(LD_PROTOCOL,
"Received REND_INTRODUCE_ACK on unexpected circuit %d.",
circ->_base.n_circ_id);
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
return -1;
}
@@ -229,7 +229,7 @@
if (!extend_info) {
log_warn(LD_REND, "No introduction points left for %s. Closing.",
escaped_safe_str(circ->rend_query));
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return -1;
}
log_info(LD_REND,
@@ -349,7 +349,7 @@
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(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
return -1;
}
log_info(LD_REND,"Got rendezvous ack. This circuit is now ready for "
@@ -371,7 +371,7 @@
|| !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(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
return -1;
}
@@ -417,7 +417,7 @@
circ->build_state->pending_final_cpath = NULL; /* prevent double-free */
return 0;
err:
- circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN);
+ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
return -1;
}
Index: doc/control-spec.txt
===================================================================
--- doc/control-spec.txt (revision 8642)
+++ doc/control-spec.txt (working copy)
@@ -751,7 +751,8 @@
The syntax is:
- "650" SP "CIRC" SP CircuitID SP CircStatus [SP Path]
+ "650" SP "CIRC" SP CircuitID SP CircStatus [SP Path]
+ [SP "REASON=" Reason] CRLF
CircStatus =
"LAUNCHED" / ; circuit ID assigned to new circuit
@@ -762,9 +763,15 @@
Path = ServerID *("," ServerID)
+ Reason = "NONE" / "TORPROTOCOL" / "INTERNAL" / "REQUESTED" /
+ "HIBERNATING" / "RESOURCELIMIT" / "CONNECTFAILED" /
+ "OR_IDENTITY" / "OR_CONN_CLOSED"
+
The path is provided only when the circuit has been extended at least one
hop.
+ Reason is provided only for FAILED and CLOSED events.
+
4.1.2. Stream status changed
The syntax is: