|
@@ -1780,6 +1780,88 @@ getinfo_helper_dir(control_connection_t *control_conn,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/** Allocate and return a description of <b>circ</b>'s current status,
|
|
|
|
+ * including its path (if any). */
|
|
|
|
+static char *
|
|
|
|
+circuit_describe_status_for_controller(origin_circuit_t *circ)
|
|
|
|
+{
|
|
|
|
+ char *rv;
|
|
|
|
+ smartlist_t *descparts = smartlist_create();
|
|
|
|
+
|
|
|
|
+ {
|
|
|
|
+ char *vpath = circuit_list_path_for_controller(circ);
|
|
|
|
+ if (*vpath) {
|
|
|
|
+ smartlist_add(descparts, vpath);
|
|
|
|
+ } else {
|
|
|
|
+ tor_free(vpath); /* empty path; don't put an extra space in the result */
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ {
|
|
|
|
+ char *buildflags = NULL;
|
|
|
|
+ cpath_build_state_t *build_state = circ->build_state;
|
|
|
|
+ smartlist_t *flaglist = smartlist_create();
|
|
|
|
+ char *flaglist_joined;
|
|
|
|
+
|
|
|
|
+ if (build_state->onehop_tunnel)
|
|
|
|
+ smartlist_add(flaglist, (void *)"ONEHOP_TUNNEL");
|
|
|
|
+ if (build_state->is_internal)
|
|
|
|
+ smartlist_add(flaglist, (void *)"IS_INTERNAL");
|
|
|
|
+ if (build_state->need_capacity)
|
|
|
|
+ smartlist_add(flaglist, (void *)"NEED_CAPACITY");
|
|
|
|
+ if (build_state->need_uptime)
|
|
|
|
+ smartlist_add(flaglist, (void *)"NEED_UPTIME");
|
|
|
|
+
|
|
|
|
+ /* Only emit a BUILD_FLAGS argument if it will have a non-empty value. */
|
|
|
|
+ if (smartlist_len(flaglist)) {
|
|
|
|
+ flaglist_joined = smartlist_join_strings(flaglist, ",", 0, NULL);
|
|
|
|
+
|
|
|
|
+ tor_asprintf(&buildflags, "BUILD_FLAGS=%s", flaglist_joined);
|
|
|
|
+ smartlist_add(descparts, buildflags);
|
|
|
|
+
|
|
|
|
+ tor_free(flaglist_joined);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ smartlist_free(flaglist);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ {
|
|
|
|
+ char *purpose = NULL;
|
|
|
|
+ tor_asprintf(&purpose, "PURPOSE=%s",
|
|
|
|
+ circuit_purpose_to_controller_string(circ->_base.purpose));
|
|
|
|
+ smartlist_add(descparts, purpose);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ {
|
|
|
|
+ char *hs_state_arg = NULL;
|
|
|
|
+ const char *hs_state =
|
|
|
|
+ circuit_purpose_to_controller_hs_state_string(circ->_base.purpose);
|
|
|
|
+
|
|
|
|
+ if (hs_state != NULL) {
|
|
|
|
+ tor_asprintf(&hs_state_arg, "HS_STATE=%s",
|
|
|
|
+ hs_state);
|
|
|
|
+
|
|
|
|
+ smartlist_add(descparts, hs_state_arg);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (circ->rend_data != NULL) {
|
|
|
|
+ char *rend_query_arg = NULL;
|
|
|
|
+
|
|
|
|
+ tor_asprintf(&rend_query_arg, "REND_QUERY=%s",
|
|
|
|
+ circ->rend_data->onion_address);
|
|
|
|
+
|
|
|
|
+ smartlist_add(descparts, rend_query_arg);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ rv = smartlist_join_strings(descparts, " ", 0, NULL);
|
|
|
|
+
|
|
|
|
+ SMARTLIST_FOREACH(descparts, char *, cp, tor_free(cp));
|
|
|
|
+ smartlist_free(descparts);
|
|
|
|
+
|
|
|
|
+ return rv;
|
|
|
|
+}
|
|
|
|
+
|
|
/** Implementation helper for GETINFO: knows how to generate summaries of the
|
|
/** Implementation helper for GETINFO: knows how to generate summaries of the
|
|
* current states of things we send events about. */
|
|
* current states of things we send events about. */
|
|
static int
|
|
static int
|
|
@@ -1789,33 +1871,33 @@ getinfo_helper_events(control_connection_t *control_conn,
|
|
{
|
|
{
|
|
(void) control_conn;
|
|
(void) control_conn;
|
|
if (!strcmp(question, "circuit-status")) {
|
|
if (!strcmp(question, "circuit-status")) {
|
|
- circuit_t *circ;
|
|
|
|
|
|
+ circuit_t *circ_;
|
|
smartlist_t *status = smartlist_create();
|
|
smartlist_t *status = smartlist_create();
|
|
- for (circ = _circuit_get_global_list(); circ; circ = circ->next) {
|
|
|
|
- char *s, *path;
|
|
|
|
|
|
+ for (circ_ = _circuit_get_global_list(); circ_; circ_ = circ_->next) {
|
|
|
|
+ origin_circuit_t *circ;
|
|
|
|
+ char *s, *circdesc;
|
|
size_t slen;
|
|
size_t slen;
|
|
const char *state;
|
|
const char *state;
|
|
- const char *purpose;
|
|
|
|
- if (! CIRCUIT_IS_ORIGIN(circ) || circ->marked_for_close)
|
|
|
|
|
|
+ if (! CIRCUIT_IS_ORIGIN(circ_) || circ_->marked_for_close)
|
|
continue;
|
|
continue;
|
|
|
|
+ circ = TO_ORIGIN_CIRCUIT(circ_);
|
|
|
|
|
|
- path = circuit_list_path_for_controller(TO_ORIGIN_CIRCUIT(circ));
|
|
|
|
-
|
|
|
|
- if (circ->state == CIRCUIT_STATE_OPEN)
|
|
|
|
|
|
+ if (circ->_base.state == CIRCUIT_STATE_OPEN)
|
|
state = "BUILT";
|
|
state = "BUILT";
|
|
- else if (strlen(path))
|
|
|
|
|
|
+ else if (circ->cpath)
|
|
state = "EXTENDED";
|
|
state = "EXTENDED";
|
|
else
|
|
else
|
|
state = "LAUNCHED";
|
|
state = "LAUNCHED";
|
|
|
|
|
|
- purpose = circuit_purpose_to_controller_string(circ->purpose);
|
|
|
|
- slen = strlen(path)+strlen(state)+strlen(purpose)+30;
|
|
|
|
|
|
+ circdesc = circuit_describe_status_for_controller(circ);
|
|
|
|
+
|
|
|
|
+ slen = strlen(circdesc)+strlen(state)+30;
|
|
s = tor_malloc(slen+1);
|
|
s = tor_malloc(slen+1);
|
|
- tor_snprintf(s, slen, "%lu %s%s%s PURPOSE=%s",
|
|
|
|
- (unsigned long)TO_ORIGIN_CIRCUIT(circ)->global_identifier,
|
|
|
|
- state, *path ? " " : "", path, purpose);
|
|
|
|
|
|
+ tor_snprintf(s, slen, "%lu %s%s%s",
|
|
|
|
+ (unsigned long)circ->global_identifier,
|
|
|
|
+ state, *circdesc ? " " : "", circdesc);
|
|
smartlist_add(status, s);
|
|
smartlist_add(status, s);
|
|
- tor_free(path);
|
|
|
|
|
|
+ tor_free(circdesc);
|
|
}
|
|
}
|
|
*answer = smartlist_join_strings(status, "\r\n", 0, NULL);
|
|
*answer = smartlist_join_strings(status, "\r\n", 0, NULL);
|
|
SMARTLIST_FOREACH(status, char *, cp, tor_free(cp));
|
|
SMARTLIST_FOREACH(status, char *, cp, tor_free(cp));
|
|
@@ -3237,7 +3319,7 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
|
|
int reason_code)
|
|
int reason_code)
|
|
{
|
|
{
|
|
const char *status;
|
|
const char *status;
|
|
- char extended_buf[96];
|
|
|
|
|
|
+ char reasons[64] = "";
|
|
if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS))
|
|
if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS))
|
|
return 0;
|
|
return 0;
|
|
tor_assert(circ);
|
|
tor_assert(circ);
|
|
@@ -3254,36 +3336,32 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
- tor_snprintf(extended_buf, sizeof(extended_buf), "PURPOSE=%s",
|
|
|
|
- circuit_purpose_to_controller_string(circ->_base.purpose));
|
|
|
|
-
|
|
|
|
if (tp == CIRC_EVENT_FAILED || tp == CIRC_EVENT_CLOSED) {
|
|
if (tp == CIRC_EVENT_FAILED || tp == CIRC_EVENT_CLOSED) {
|
|
const char *reason_str = circuit_end_reason_to_control_string(reason_code);
|
|
const char *reason_str = circuit_end_reason_to_control_string(reason_code);
|
|
- char *reason = NULL;
|
|
|
|
- size_t n=strlen(extended_buf);
|
|
|
|
|
|
+ char unk_reason_buf[16];
|
|
if (!reason_str) {
|
|
if (!reason_str) {
|
|
- reason = tor_malloc(16);
|
|
|
|
- tor_snprintf(reason, 16, "UNKNOWN_%d", reason_code);
|
|
|
|
- reason_str = reason;
|
|
|
|
|
|
+ tor_snprintf(unk_reason_buf, 16, "UNKNOWN_%d", reason_code);
|
|
|
|
+ reason_str = unk_reason_buf;
|
|
}
|
|
}
|
|
if (reason_code > 0 && reason_code & END_CIRC_REASON_FLAG_REMOTE) {
|
|
if (reason_code > 0 && reason_code & END_CIRC_REASON_FLAG_REMOTE) {
|
|
- tor_snprintf(extended_buf+n, sizeof(extended_buf)-n,
|
|
|
|
|
|
+ tor_snprintf(reasons, sizeof(reasons),
|
|
" REASON=DESTROYED REMOTE_REASON=%s", reason_str);
|
|
" REASON=DESTROYED REMOTE_REASON=%s", reason_str);
|
|
} else {
|
|
} else {
|
|
- tor_snprintf(extended_buf+n, sizeof(extended_buf)-n,
|
|
|
|
|
|
+ tor_snprintf(reasons, sizeof(reasons),
|
|
" REASON=%s", reason_str);
|
|
" REASON=%s", reason_str);
|
|
}
|
|
}
|
|
- tor_free(reason);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
{
|
|
{
|
|
- char *vpath = circuit_list_path_for_controller(circ);
|
|
|
|
- const char *sp = strlen(vpath) ? " " : "";
|
|
|
|
|
|
+ char *circdesc = circuit_describe_status_for_controller(circ);
|
|
|
|
+ const char *sp = strlen(circdesc) ? " " : "";
|
|
send_control_event(EVENT_CIRCUIT_STATUS, ALL_FORMATS,
|
|
send_control_event(EVENT_CIRCUIT_STATUS, ALL_FORMATS,
|
|
- "650 CIRC %lu %s%s%s %s\r\n",
|
|
|
|
|
|
+ "650 CIRC %lu %s%s%s%s\r\n",
|
|
(unsigned long)circ->global_identifier,
|
|
(unsigned long)circ->global_identifier,
|
|
- status, sp, vpath, extended_buf);
|
|
|
|
- tor_free(vpath);
|
|
|
|
|
|
+ status, sp,
|
|
|
|
+ circdesc,
|
|
|
|
+ reasons);
|
|
|
|
+ tor_free(circdesc);
|
|
}
|
|
}
|
|
|
|
|
|
return 0;
|
|
return 0;
|