r9060@totoro: nickm | 2006-10-17 11:12:48 -0400

Apply patch from Mike Perry: add more reasons for circuit destroys. (Slightly tweaked to avoid allocating a number for an "internal" reason.)


svn:r8739
This commit is contained in:
Nick Mathewson 2006-10-17 15:20:00 +00:00
parent e3b1d059c7
commit b713b370bf
13 changed files with 42 additions and 29 deletions

View File

@ -6,7 +6,9 @@ Changes in version 0.1.2.3-alpha - 2006-10-??
o Minor features, controller: o Minor features, controller:
- Add a REASON field to CIRC events; for backward compatibility, this - Add a REASON field to CIRC events; for backward compatibility, this
field is sent only to controllers that have enabled the extended field is sent only to controllers that have enabled the extended
event format. (Patch from Mike Perry) event format. Also, add additional reason codes to explain why a
given circuit has been destroyed or truncated. (Patches from Mike
Perry)
o Security bugfixes: o Security bugfixes:
- When the user sends a NEWNYM signal, clear the client-side DNS - When the user sends a NEWNYM signal, clear the client-side DNS

View File

@ -777,16 +777,17 @@ $Id$
Reason = "NONE" / "TORPROTOCOL" / "INTERNAL" / "REQUESTED" / Reason = "NONE" / "TORPROTOCOL" / "INTERNAL" / "REQUESTED" /
"HIBERNATING" / "RESOURCELIMIT" / "CONNECTFAILED" / "HIBERNATING" / "RESOURCELIMIT" / "CONNECTFAILED" /
"OR_IDENTITY" / "OR_CONN_CLOSED" "OR_IDENTITY" / "OR_CONN_CLOSED" / "TIMEOUT" /
"FINISHED" / "DESTROYED" / "NOPATH" / "NOSUCHSERVICE"
The path is provided only when the circuit has been extended at least one The path is provided only when the circuit has been extended at least one
hop. hop.
The "REASON" field is provided only for FAILED and CLOSED events, and only The "REASON" field is provided only for FAILED and CLOSED events, and only
if extended events are enabled (see 3.19). Clients MUST accept reasons if extended events are enabled (see 3.19). Clients MUST accept reasons
not listed above. not listed above. Reasons are as given in tor-spec.txt, except for:
[XXXX Explain what the reasons mean.] NOPATH (Not enough nodes to make circuit)
4.1.2. Stream status changed 4.1.2. Stream status changed

View File

@ -228,7 +228,7 @@ TODO:
associated with. associated with.
The 'Command' field holds one of the following values: The 'Command' field holds one of the following values:
0 -- PADDING (Padding) (See Sec 7.2) 0 -- PADDING (Padding) (See Sec 7.2)
1 -- CREATE (Create a circuit) (See Sec 5.1) 1 -- CREATE (Create a circuit) (See Sec 5.1)
2 -- CREATED (Acknowledge create) (See Sec 5.1) 2 -- CREATED (Acknowledge create) (See Sec 5.1)
3 -- RELAY (End-to-end data) (See Sec 5.5 and 6) 3 -- RELAY (End-to-end data) (See Sec 5.5 and 6)
@ -563,6 +563,10 @@ TODO:
as expected.) as expected.)
8 -- OR_CONN_CLOSED (The OR connection that was carrying this circuit 8 -- OR_CONN_CLOSED (The OR connection that was carrying this circuit
died.) died.)
9 -- FINISHED (The circuit has expired for being dirty or old.)
10 -- TIMEOUT (Circuit construction took too long)
11 -- DESTROYED (The circuit was destroyed w/o client TRUNCATE)
12 -- NOSUCHSERVICE (Request for unknown hidden service)
[Versions of Tor prior to 0.1.0.11 didn't send reasons; implementations [Versions of Tor prior to 0.1.0.11 didn't send reasons; implementations
MUST accept empty TRUNCATED and DESTROY cells.] MUST accept empty TRUNCATED and DESTROY cells.]

View File

@ -305,8 +305,7 @@ circuit_establish_circuit(uint8_t purpose, extend_info_t *info,
if (onion_pick_cpath_exit(circ, info) < 0 || if (onion_pick_cpath_exit(circ, info) < 0 ||
onion_populate_cpath(circ) < 0) { onion_populate_cpath(circ) < 0) {
/* XXX should there be a 'couldn't build a path' reason? */ circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_NOPATH);
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return NULL; return NULL;
} }

View File

@ -780,7 +780,7 @@ circuit_mark_all_unused_circs(void)
if (CIRCUIT_IS_ORIGIN(circ) && if (CIRCUIT_IS_ORIGIN(circ) &&
!circ->marked_for_close && !circ->marked_for_close &&
!circ->timestamp_dirty) !circ->timestamp_dirty)
circuit_mark_for_close(circ, END_CIRC_REASON_REQUESTED); circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
} }
} }
@ -843,7 +843,7 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
file, line, circ->purpose); file, line, circ->purpose);
} }
reason = END_CIRC_REASON_NONE; reason = END_CIRC_REASON_NONE;
} else if (CIRCUIT_IS_ORIGIN(circ) && reason != END_CIRC_REASON_NONE) { } else if (CIRCUIT_IS_ORIGIN(circ) && reason < _END_CIRC_REASON_MIN) {
/* We don't send reasons when closing circuits at the origin, but we want /* We don't send reasons when closing circuits at the origin, but we want
* to track them anyway so we can give them to the controller. */ * to track them anyway so we can give them to the controller. */
reason = END_CIRC_REASON_NONE; reason = END_CIRC_REASON_NONE;

View File

@ -265,8 +265,7 @@ circuit_expire_building(time_t now)
circuit_state_to_string(victim->state), victim->purpose); circuit_state_to_string(victim->state), victim->purpose);
circuit_log_path(LOG_INFO,LD_CIRC,TO_ORIGIN_CIRCUIT(victim)); circuit_log_path(LOG_INFO,LD_CIRC,TO_ORIGIN_CIRCUIT(victim));
/* XXXX Should there be a timeout reason? CONNECTFAILED isn't right. */ circuit_mark_for_close(victim, END_CIRC_REASON_TIMEOUT);
circuit_mark_for_close(victim, END_CIRC_REASON_CONNECTFAILED);
} }
} }
@ -584,8 +583,7 @@ circuit_expire_old_circuits(time_t now)
log_debug(LD_CIRC, "Closing n_circ_id %d (dirty %d secs ago, purp %d)", log_debug(LD_CIRC, "Closing n_circ_id %d (dirty %d secs ago, purp %d)",
circ->n_circ_id, (int)(now - circ->timestamp_dirty), circ->n_circ_id, (int)(now - circ->timestamp_dirty),
circ->purpose); circ->purpose);
/* XXXX Should there be a timeout reason? REQUESTED isn't right. */ circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
circuit_mark_for_close(circ, END_CIRC_REASON_REQUESTED);
} else if (!circ->timestamp_dirty && } else if (!circ->timestamp_dirty &&
circ->state == CIRCUIT_STATE_OPEN && circ->state == CIRCUIT_STATE_OPEN &&
circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) { circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) {
@ -593,8 +591,7 @@ circuit_expire_old_circuits(time_t now)
log_debug(LD_CIRC, log_debug(LD_CIRC,
"Closing circuit that has been unused for %d seconds.", "Closing circuit that has been unused for %d seconds.",
(int)(now - circ->timestamp_created)); (int)(now - circ->timestamp_created));
/* XXXX Should there be a timeout reason? REQUESTED isn't right. */ circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED);
circuit_mark_for_close(circ, END_CIRC_REASON_REQUESTED);
} }
} }
} }

View File

@ -379,18 +379,12 @@ command_process_destroy_cell(cell_t *cell, or_connection_t *conn)
circuit_set_n_circid_orconn(circ, 0, NULL); circuit_set_n_circid_orconn(circ, 0, NULL);
if (CIRCUIT_IS_ORIGIN(circ)) { if (CIRCUIT_IS_ORIGIN(circ)) {
/* Prevent arbitrary destroys from going unnoticed by controller */ /* Prevent arbitrary destroys from going unnoticed by controller */
/* XXXX Not quite right; what we want is to tell the controller the
* exact reason that we were asked to close, but tell it that we
* closed because we were asked. Anything else is not accurate.
* OR_CONN_CLOSED is certainly wrong, since a destroy doesn't mean
* that the underlying OR connection got closed. -NM */
#if 0
if (reason == END_CIRC_AT_ORIGIN || if (reason == END_CIRC_AT_ORIGIN ||
reason == END_CIRC_REASON_NONE || reason == END_CIRC_REASON_NONE ||
reason == END_CIRC_REASON_FINISHED ||
reason == END_CIRC_REASON_REQUESTED) { reason == END_CIRC_REASON_REQUESTED) {
reason = END_CIRC_REASON_OR_CONN_CLOSED; reason = END_CIRC_REASON_DESTROYED;
} }
#endif
circuit_mark_for_close(circ, reason); circuit_mark_for_close(circ, reason);
} else { } else {
char payload[1]; char payload[1];

View File

@ -3666,6 +3666,7 @@ static const struct {
{ "1.1", LE_11 }, { "1.1", LE_11 },
{ "1.1a", LE_11A }, { "1.1a", LE_11A },
{ "1.1b", LE_11B }, { "1.1b", LE_11B },
{ "1.2", LE_12 },
{ NULL, 0 } { NULL, 0 }
}; };

View File

@ -2825,6 +2825,16 @@ circuit_end_reason_to_string(int reason)
return "REASON=OR_IDENTITY"; return "REASON=OR_IDENTITY";
case END_CIRC_REASON_OR_CONN_CLOSED: case END_CIRC_REASON_OR_CONN_CLOSED:
return "REASON=OR_CONN_CLOSED"; return "REASON=OR_CONN_CLOSED";
case END_CIRC_REASON_FINISHED:
return "REASON=FINISHED";
case END_CIRC_REASON_TIMEOUT:
return "REASON=TIMEOUT";
case END_CIRC_REASON_DESTROYED:
return "REASON=DESTROYED";
case END_CIRC_REASON_NOPATH:
return "REASON=NOPATH";
case END_CIRC_REASON_NOSUCHSERVICE:
return "REASON=NOSUCHSERVICE";
default: default:
log_warn(LD_BUG, "Unrecognized reason code %d", (int)reason); log_warn(LD_BUG, "Unrecognized reason code %d", (int)reason);
return NULL; return NULL;

View File

@ -494,7 +494,9 @@ typedef enum {
#define RESOLVED_TYPE_ERROR 0xF1 #define RESOLVED_TYPE_ERROR 0xF1
/* DOCDOC We should document the meaning of these. */ /* DOCDOC We should document the meaning of these. */
#define END_CIRC_AT_ORIGIN -1 /* Negative reasons are internal */
#define END_CIRC_REASON_NOPATH -2
#define END_CIRC_AT_ORIGIN -1
#define _END_CIRC_REASON_MIN 0 #define _END_CIRC_REASON_MIN 0
#define END_CIRC_REASON_NONE 0 #define END_CIRC_REASON_NONE 0
#define END_CIRC_REASON_TORPROTOCOL 1 #define END_CIRC_REASON_TORPROTOCOL 1
@ -505,7 +507,11 @@ typedef enum {
#define END_CIRC_REASON_CONNECTFAILED 6 #define END_CIRC_REASON_CONNECTFAILED 6
#define END_CIRC_REASON_OR_IDENTITY 7 #define END_CIRC_REASON_OR_IDENTITY 7
#define END_CIRC_REASON_OR_CONN_CLOSED 8 #define END_CIRC_REASON_OR_CONN_CLOSED 8
#define _END_CIRC_REASON_MAX 8 #define END_CIRC_REASON_FINISHED 9
#define END_CIRC_REASON_TIMEOUT 10
#define END_CIRC_REASON_DESTROYED 11
#define END_CIRC_REASON_NOSUCHSERVICE 12
#define _END_CIRC_REASON_MAX 12
/** Length of 'y' portion of 'y.onion' URL. */ /** Length of 'y' portion of 'y.onion' URL. */
#define REND_SERVICE_ID_LEN 16 #define REND_SERVICE_ID_LEN 16

View File

@ -211,7 +211,7 @@ rend_client_introduction_acked(origin_circuit_t *circ,
} }
/* close the circuit: we won't need it anymore. */ /* close the circuit: we won't need it anymore. */
circ->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACKED; circ->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACKED;
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_AT_ORIGIN); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED);
} else { } else {
/* It's a NAK; the introduction point didn't relay our request. */ /* It's a NAK; the introduction point didn't relay our request. */
circ->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCING; circ->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCING;

View File

@ -90,7 +90,7 @@ rend_mid_establish_intro(or_circuit_t *circ, const char *request,
while ((c = circuit_get_intro_point(pk_digest))) { while ((c = circuit_get_intro_point(pk_digest))) {
log_info(LD_REND, "Replacing old circuit for service %s", log_info(LD_REND, "Replacing old circuit for service %s",
safe_str(serviceid)); safe_str(serviceid));
circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_REASON_REQUESTED); circuit_mark_for_close(TO_CIRCUIT(c), END_CIRC_REASON_FINISHED);
/* Now it's marked, and it won't be returned next time. */ /* Now it's marked, and it won't be returned next time. */
} }

View File

@ -738,8 +738,7 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
if (!service) { if (!service) {
log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %d.", log_warn(LD_REND, "Unrecognized service ID %s on introduction circuit %d.",
serviceid, circuit->_base.n_circ_id); serviceid, circuit->_base.n_circ_id);
/* XXXX Add a no-such-servicer reason? */ reason = END_CIRC_REASON_NOSUCHSERVICE;
reason = END_CIRC_REASON_CONNECTFAILED;
goto err; goto err;
} }