aboutsummaryrefslogtreecommitdiff
path: root/src/or/control.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/control.c')
-rw-r--r--src/or/control.c527
1 files changed, 332 insertions, 195 deletions
diff --git a/src/or/control.c b/src/or/control.c
index 03d9fcee2a..3609210b95 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2016, The Tor Project, Inc. */
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
@@ -36,6 +36,7 @@
#include "or.h"
#include "addressmap.h"
+#include "bridges.h"
#include "buffers.h"
#include "channel.h"
#include "channeltls.h"
@@ -57,10 +58,14 @@
#include "entrynodes.h"
#include "geoip.h"
#include "hibernate.h"
+#include "hs_common.h"
#include "main.h"
+#include "microdesc.h"
#include "networkstatus.h"
#include "nodelist.h"
#include "policies.h"
+#include "proto_control0.h"
+#include "proto_http.h"
#include "reasons.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -69,6 +74,7 @@
#include "router.h"
#include "routerlist.h"
#include "routerparse.h"
+#include "shared_random.h"
#ifndef _WIN32
#include <pwd.h>
@@ -351,7 +357,7 @@ static inline void
connection_write_str_to_buf(const char *s, control_connection_t *conn)
{
size_t len = strlen(s);
- connection_write_to_buf(s, len, TO_CONN(conn));
+ connection_buf_add(s, len, TO_CONN(conn));
}
/** Given a <b>len</b>-character string in <b>data</b>, made of lines
@@ -364,16 +370,23 @@ connection_write_str_to_buf(const char *s, control_connection_t *conn)
STATIC size_t
write_escaped_data(const char *data, size_t len, char **out)
{
- size_t sz_out = len+8;
+ tor_assert(len < SIZE_MAX - 9);
+ size_t sz_out = len+8+1;
char *outp;
const char *start = data, *end;
- int i;
+ size_t i;
int start_of_line;
- for (i=0; i<(int)len; ++i) {
- if (data[i]== '\n')
+ for (i=0; i < len; ++i) {
+ if (data[i] == '\n') {
sz_out += 2; /* Maybe add a CR; maybe add a dot. */
+ if (sz_out >= SIZE_T_CEILING) {
+ log_warn(LD_BUG, "Input to write_escaped_data was too long");
+ *out = tor_strdup(".\r\n");
+ return 3;
+ }
+ }
}
- *out = outp = tor_malloc(sz_out+1);
+ *out = outp = tor_malloc(sz_out);
end = data+len;
start_of_line = 1;
while (data < end) {
@@ -399,7 +412,8 @@ write_escaped_data(const char *data, size_t len, char **out)
*outp++ = '\r';
*outp++ = '\n';
*outp = '\0'; /* NUL-terminate just in case. */
- tor_assert((outp - *out) <= (int)sz_out);
+ tor_assert(outp >= *out);
+ tor_assert((size_t)(outp - *out) <= sz_out);
return outp - *out;
}
@@ -553,7 +567,7 @@ connection_printf_to_buf(control_connection_t *conn, const char *format, ...)
tor_assert(0);
}
- connection_write_to_buf(buf, (size_t)len, TO_CONN(conn));
+ connection_buf_add(buf, (size_t)len, TO_CONN(conn));
tor_free(buf);
}
@@ -579,7 +593,7 @@ control_ports_write_to_file(void)
smartlist_add_asprintf(lines, "UNIX_PORT=%s\n", conn->address);
continue;
}
-#endif
+#endif /* defined(AF_UNIX) */
smartlist_add_asprintf(lines, "PORT=%s:%d\n", conn->address, conn->port);
} SMARTLIST_FOREACH_END(conn);
@@ -596,7 +610,7 @@ control_ports_write_to_file(void)
options->ControlPortWriteToFile);
}
}
-#endif
+#endif /* !defined(_WIN32) */
tor_free(joined);
SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
smartlist_free(lines);
@@ -778,7 +792,7 @@ queued_events_flush_all(int force)
SMARTLIST_FOREACH_BEGIN(controllers, control_connection_t *,
control_conn) {
if (control_conn->event_mask & bit) {
- connection_write_to_buf(ev->msg, msg_len, TO_CONN(control_conn));
+ connection_buf_add(ev->msg, msg_len, TO_CONN(control_conn));
}
} SMARTLIST_FOREACH_END(control_conn);
@@ -799,7 +813,7 @@ queued_events_flush_all(int force)
}
/** Libevent callback: Flushes pending events to controllers that are
- * interested in them */
+ * interested in them. */
static void
flush_queued_events_cb(evutil_socket_t fd, short what, void *arg)
{
@@ -942,7 +956,7 @@ control_setconf_helper(control_connection_t *conn, uint32_t len, char *body,
++body;
}
- smartlist_add(entries, tor_strdup(""));
+ smartlist_add_strdup(entries, "");
config = smartlist_join_strings(entries, "\n", 0, NULL);
SMARTLIST_FOREACH(entries, char *, cp, tor_free(cp));
smartlist_free(entries);
@@ -1060,7 +1074,7 @@ handle_control_getconf(control_connection_t *conn, uint32_t body_len,
tor_assert(strlen(tmp)>4);
tmp[3] = ' ';
msg = smartlist_join_strings(answers, "", 0, &msg_len);
- connection_write_to_buf(msg, msg_len, TO_CONN(conn));
+ connection_buf_add(msg, msg_len, TO_CONN(conn));
} else {
connection_write_str_to_buf("250 OK\r\n", conn);
}
@@ -1142,7 +1156,6 @@ static const struct control_event_t control_event_table[] = {
{ EVENT_ERR_MSG, "ERR" },
{ EVENT_NEW_DESC, "NEWDESC" },
{ EVENT_ADDRMAP, "ADDRMAP" },
- { EVENT_AUTHDIR_NEWDESCS, "AUTHDIR_NEWDESCS" },
{ EVENT_DESCCHANGED, "DESCCHANGED" },
{ EVENT_NS, "NS" },
{ EVENT_STATUS_GENERAL, "STATUS_GENERAL" },
@@ -1182,7 +1195,10 @@ handle_control_setevents(control_connection_t *conn, uint32_t len,
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
SMARTLIST_FOREACH_BEGIN(events, const char *, ev)
{
- if (!strcasecmp(ev, "EXTENDED")) {
+ if (!strcasecmp(ev, "EXTENDED") ||
+ !strcasecmp(ev, "AUTHDIR_NEWDESCS")) {
+ log_warn(LD_CONTROL, "The \"%s\" SETEVENTS argument is no longer "
+ "supported.", ev);
continue;
} else {
int i;
@@ -1459,8 +1475,10 @@ handle_control_saveconf(control_connection_t *conn, uint32_t len,
const char *body)
{
(void) len;
- (void) body;
- if (options_save_current()<0) {
+
+ int force = !strcmpstart(body, "FORCE");
+ const or_options_t *options = get_options();
+ if ((!force && options->IncludeUsed) || options_save_current() < 0) {
connection_write_str_to_buf(
"551 Unable to write configuration to disk.\r\n", conn);
} else {
@@ -1640,12 +1658,12 @@ handle_control_mapaddress(control_connection_t *conn, uint32_t len,
if (smartlist_len(reply)) {
((char*)smartlist_get(reply,smartlist_len(reply)-1))[3] = ' ';
r = smartlist_join_strings(reply, "\r\n", 1, &sz);
- connection_write_to_buf(r, sz, TO_CONN(conn));
+ connection_buf_add(r, sz, TO_CONN(conn));
tor_free(r);
} else {
const char *response =
"512 syntax error: not enough arguments to mapaddress.\r\n";
- connection_write_to_buf(response, strlen(response), TO_CONN(conn));
+ connection_buf_add(response, strlen(response), TO_CONN(conn));
}
SMARTLIST_FOREACH(reply, char *, cp, tor_free(cp));
@@ -1674,6 +1692,8 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
*answer = tor_strdup(a);
} else if (!strcmp(question, "config-text")) {
*answer = options_dump(get_options(), OPTIONS_DUMP_MINIMAL);
+ } else if (!strcmp(question, "config-can-saveconf")) {
+ *answer = tor_strdup(get_options()->IncludeUsed ? "0" : "1");
} else if (!strcmp(question, "info/names")) {
*answer = list_getinfo_options();
} else if (!strcmp(question, "dormant")) {
@@ -1729,7 +1749,7 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
#else
int myUid = geteuid();
tor_asprintf(answer, "%d", myUid);
- #endif
+#endif /* defined(_WIN32) */
} else if (!strcmp(question, "process/user")) {
#ifdef _WIN32
*answer = tor_strdup("");
@@ -1742,7 +1762,7 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
} else {
*answer = tor_strdup("");
}
- #endif
+#endif /* defined(_WIN32) */
} else if (!strcmp(question, "process/descriptor-limit")) {
int max_fds = get_max_sockets();
tor_asprintf(answer, "%d", max_fds);
@@ -1828,6 +1848,8 @@ getinfo_helper_listeners(control_connection_t *control_conn,
if (!strcmp(question, "net/listeners/or"))
type = CONN_TYPE_OR_LISTENER;
+ else if (!strcmp(question, "net/listeners/extor"))
+ type = CONN_TYPE_EXT_OR_LISTENER;
else if (!strcmp(question, "net/listeners/dir"))
type = CONN_TYPE_DIR_LISTENER;
else if (!strcmp(question, "net/listeners/socks"))
@@ -1836,6 +1858,8 @@ getinfo_helper_listeners(control_connection_t *control_conn,
type = CONN_TYPE_AP_TRANS_LISTENER;
else if (!strcmp(question, "net/listeners/natd"))
type = CONN_TYPE_AP_NATD_LISTENER;
+ else if (!strcmp(question, "net/listeners/httptunnel"))
+ type = CONN_TYPE_AP_HTTP_CONNECT_LISTENER;
else if (!strcmp(question, "net/listeners/dns"))
type = CONN_TYPE_AP_DNS_LISTENER;
else if (!strcmp(question, "net/listeners/control"))
@@ -1870,7 +1894,7 @@ getinfo_helper_listeners(control_connection_t *control_conn,
/** Implementation helper for GETINFO: knows the answers for questions about
* directory information. */
-static int
+STATIC int
getinfo_helper_dir(control_connection_t *control_conn,
const char *question, char **answer,
const char **errmsg)
@@ -1878,27 +1902,42 @@ getinfo_helper_dir(control_connection_t *control_conn,
(void) control_conn;
if (!strcmpstart(question, "desc/id/")) {
const routerinfo_t *ri = NULL;
- const node_t *node = node_get_by_hex_id(question+strlen("desc/id/"));
+ const node_t *node = node_get_by_hex_id(question+strlen("desc/id/"), 0);
if (node)
ri = node->ri;
if (ri) {
const char *body = signed_descriptor_get_body(&ri->cache_info);
if (body)
*answer = tor_strndup(body, ri->cache_info.signed_descriptor_len);
+ } else if (! we_fetch_router_descriptors(get_options())) {
+ /* Descriptors won't be available, provide proper error */
+ *errmsg = "We fetch microdescriptors, not router "
+ "descriptors. You'll need to use md/id/* "
+ "instead of desc/id/*.";
+ return 0;
}
} else if (!strcmpstart(question, "desc/name/")) {
const routerinfo_t *ri = NULL;
/* XXX Setting 'warn_if_unnamed' here is a bit silly -- the
* warning goes to the user, not to the controller. */
const node_t *node =
- node_get_by_nickname(question+strlen("desc/name/"), 1);
+ node_get_by_nickname(question+strlen("desc/name/"), 0);
if (node)
ri = node->ri;
if (ri) {
const char *body = signed_descriptor_get_body(&ri->cache_info);
if (body)
*answer = tor_strndup(body, ri->cache_info.signed_descriptor_len);
+ } else if (! we_fetch_router_descriptors(get_options())) {
+ /* Descriptors won't be available, provide proper error */
+ *errmsg = "We fetch microdescriptors, not router "
+ "descriptors. You'll need to use md/name/* "
+ "instead of desc/name/*.";
+ return 0;
}
+ } else if (!strcmp(question, "desc/download-enabled")) {
+ int r = we_fetch_router_descriptors(get_options());
+ tor_asprintf(answer, "%d", !!r);
} else if (!strcmp(question, "desc/all-recent")) {
routerlist_t *routerlist = router_get_routerlist();
smartlist_t *sl = smartlist_new();
@@ -1968,7 +2007,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
return -1;
}
} else if (!strcmpstart(question, "md/id/")) {
- const node_t *node = node_get_by_hex_id(question+strlen("md/id/"));
+ const node_t *node = node_get_by_hex_id(question+strlen("md/id/"), 0);
const microdesc_t *md = NULL;
if (node) md = node->md;
if (md && md->body) {
@@ -1977,17 +2016,20 @@ getinfo_helper_dir(control_connection_t *control_conn,
} else if (!strcmpstart(question, "md/name/")) {
/* XXX Setting 'warn_if_unnamed' here is a bit silly -- the
* warning goes to the user, not to the controller. */
- const node_t *node = node_get_by_nickname(question+strlen("md/name/"), 1);
+ const node_t *node = node_get_by_nickname(question+strlen("md/name/"), 0);
/* XXXX duplicated code */
const microdesc_t *md = NULL;
if (node) md = node->md;
if (md && md->body) {
*answer = tor_strndup(md->body, md->bodylen);
}
+ } else if (!strcmp(question, "md/download-enabled")) {
+ int r = we_fetch_microdescriptors(get_options());
+ tor_asprintf(answer, "%d", !!r);
} else if (!strcmpstart(question, "desc-annotations/id/")) {
const routerinfo_t *ri = NULL;
const node_t *node =
- node_get_by_hex_id(question+strlen("desc-annotations/id/"));
+ node_get_by_hex_id(question+strlen("desc-annotations/id/"), 0);
if (node)
ri = node->ri;
if (ri) {
@@ -2028,7 +2070,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
} else if (!strcmpstart(question, "dir/status/")) {
*answer = tor_strdup("");
} else if (!strcmp(question, "dir/status-vote/current/consensus")) { /* v3 */
- if (directory_caches_dir_info(get_options())) {
+ if (we_want_to_fetch_flavor(get_options(), FLAV_NS)) {
const cached_dir_t *consensus = dirserv_get_consensus("ns");
if (consensus)
*answer = tor_strdup(consensus->dir);
@@ -2044,6 +2086,12 @@ getinfo_helper_dir(control_connection_t *control_conn,
}
}
} else if (!strcmp(question, "network-status")) { /* v1 */
+ static int network_status_warned = 0;
+ if (!network_status_warned) {
+ log_warn(LD_CONTROL, "GETINFO network-status is deprecated; it will "
+ "go away in a future version of Tor.");
+ network_status_warned = 1;
+ }
routerlist_t *routerlist = router_get_routerlist();
if (!routerlist || !routerlist->routers ||
list_server_status_v1(routerlist->routers, answer, 1) < 0) {
@@ -2114,7 +2162,7 @@ download_status_to_string(const download_status_t *dl)
if (dl) {
/* Get some substrings of the eventual output ready */
- format_iso_time(tbuf, dl->next_attempt_at);
+ format_iso_time(tbuf, download_status_get_next_attempt_at(dl));
switch (dl->schedule) {
case DL_SCHED_GENERIC:
@@ -2539,7 +2587,7 @@ circuit_describe_status_for_controller(origin_circuit_t *circ)
if (circ->rend_data != NULL) {
smartlist_add_asprintf(descparts, "REND_QUERY=%s",
- circ->rend_data->onion_address);
+ rend_data_get_address(circ->rend_data));
}
{
@@ -2594,6 +2642,8 @@ getinfo_helper_events(control_connection_t *control_conn,
if (circ->base_.state == CIRCUIT_STATE_OPEN)
state = "BUILT";
+ else if (circ->base_.state == CIRCUIT_STATE_GUARD_WAIT)
+ state = "GUARD_WAIT";
else if (circ->cpath)
state = "EXTENDED";
else
@@ -2819,12 +2869,13 @@ getinfo_helper_events(control_connection_t *control_conn,
/** Implementation helper for GETINFO: knows how to enumerate hidden services
* created via the control port. */
-static int
+STATIC int
getinfo_helper_onions(control_connection_t *control_conn,
const char *question, char **answer,
const char **errmsg)
{
smartlist_t *onion_list = NULL;
+ (void) errmsg; /* no errors from this method */
if (control_conn && !strcmp(question, "onions/current")) {
onion_list = control_conn->ephemeral_onion_services;
@@ -2834,13 +2885,13 @@ getinfo_helper_onions(control_connection_t *control_conn,
return 0;
}
if (!onion_list || smartlist_len(onion_list) == 0) {
- if (errmsg) {
- *errmsg = "No onion services of the specified type.";
+ if (answer) {
+ *answer = tor_strdup("");
}
- return -1;
- }
- if (answer) {
+ } else {
+ if (answer) {
*answer = smartlist_join_strings(onion_list, "\r\n", 0, NULL);
+ }
}
return 0;
@@ -2866,12 +2917,33 @@ getinfo_helper_liveness(control_connection_t *control_conn,
return 0;
}
+/** Implementation helper for GETINFO: answers queries about shared random
+ * value. */
+static int
+getinfo_helper_sr(control_connection_t *control_conn,
+ const char *question, char **answer,
+ const char **errmsg)
+{
+ (void) control_conn;
+ (void) errmsg;
+
+ if (!strcmp(question, "sr/current")) {
+ *answer = sr_get_current_for_control();
+ } else if (!strcmp(question, "sr/previous")) {
+ *answer = sr_get_previous_for_control();
+ }
+ /* Else statement here is unrecognized key so do nothing. */
+
+ return 0;
+}
+
/** Callback function for GETINFO: on a given control connection, try to
* answer the question <b>q</b> and store the newly-allocated answer in
* *<b>a</b>. If an internal error occurs, return -1 and optionally set
* *<b>error_out</b> to point to an error message to be delivered to the
* controller. On success, _or if the key is not recognized_, return 0. Do not
- * set <b>a</b> if the key is not recognized.
+ * set <b>a</b> if the key is not recognized but you may set <b>error_out</b>
+ * to improve the error message.
*/
typedef int (*getinfo_helper_t)(control_connection_t *,
const char *q, char **a,
@@ -2899,6 +2971,8 @@ static const getinfo_item_t getinfo_items[] = {
ITEM("config-defaults-file", misc, "Current location of the defaults file."),
ITEM("config-text", misc,
"Return the string that would be written by a saveconf command."),
+ ITEM("config-can-saveconf", misc,
+ "Is it possible to save the configuration to the \"torrc\" file?"),
ITEM("accounting/bytes", accounting,
"Number of bytes read/written so far in the accounting interval."),
ITEM("accounting/bytes-left", accounting,
@@ -2974,9 +3048,13 @@ static const getinfo_item_t getinfo_items[] = {
PREFIX("desc/name/", dir, "Router descriptors by nickname."),
ITEM("desc/all-recent", dir,
"All non-expired, non-superseded router descriptors."),
+ ITEM("desc/download-enabled", dir,
+ "Do we try to download router descriptors?"),
ITEM("desc/all-recent-extrainfo-hack", dir, NULL), /* Hack. */
PREFIX("md/id/", dir, "Microdescriptors by ID"),
PREFIX("md/name/", dir, "Microdescriptors by name"),
+ ITEM("md/download-enabled", dir,
+ "Do we try to download microdescriptors?"),
PREFIX("extra-info/digest/", dir, "Extra-info documents by digest."),
PREFIX("hs/client/desc/id", dir,
"Hidden Service descriptor in client's cache by onion."),
@@ -3058,6 +3136,8 @@ static const getinfo_item_t getinfo_items[] = {
"Onion services owned by the current control connection."),
ITEM("onions/detached", onions,
"Onion services detached from the control connection."),
+ ITEM("sr/current", sr, "Get current shared random value."),
+ ITEM("sr/previous", sr, "Get previous shared random value."),
{ NULL, NULL, NULL, 0 }
};
@@ -3122,7 +3202,7 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len,
smartlist_t *questions = smartlist_new();
smartlist_t *answers = smartlist_new();
smartlist_t *unrecognized = smartlist_new();
- char *msg = NULL, *ans = NULL;
+ char *ans = NULL;
int i;
(void) len; /* body is NUL-terminated, so it's safe to ignore the length. */
@@ -3137,20 +3217,26 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len,
goto done;
}
if (!ans) {
- smartlist_add(unrecognized, (char*)q);
+ if (errmsg) /* use provided error message */
+ smartlist_add_strdup(unrecognized, errmsg);
+ else /* use default error message */
+ smartlist_add_asprintf(unrecognized, "Unrecognized key \"%s\"", q);
} else {
- smartlist_add(answers, tor_strdup(q));
+ smartlist_add_strdup(answers, q);
smartlist_add(answers, ans);
}
} SMARTLIST_FOREACH_END(q);
+
if (smartlist_len(unrecognized)) {
+ /* control-spec section 2.3, mid-reply '-' or end of reply ' ' */
for (i=0; i < smartlist_len(unrecognized)-1; ++i)
connection_printf_to_buf(conn,
- "552-Unrecognized key \"%s\"\r\n",
- (char*)smartlist_get(unrecognized, i));
+ "552-%s\r\n",
+ (char *)smartlist_get(unrecognized, i));
+
connection_printf_to_buf(conn,
- "552 Unrecognized key \"%s\"\r\n",
- (char*)smartlist_get(unrecognized, i));
+ "552 %s\r\n",
+ (char *)smartlist_get(unrecognized, i));
goto done;
}
@@ -3166,7 +3252,7 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len,
size_t esc_len;
esc_len = write_escaped_data(v, strlen(v), &esc);
connection_printf_to_buf(conn, "250+%s=\r\n", k);
- connection_write_to_buf(esc, esc_len, TO_CONN(conn));
+ connection_buf_add(esc, esc_len, TO_CONN(conn));
tor_free(esc);
}
}
@@ -3177,8 +3263,8 @@ handle_control_getinfo(control_connection_t *conn, uint32_t len,
smartlist_free(answers);
SMARTLIST_FOREACH(questions, char *, cp, tor_free(cp));
smartlist_free(questions);
+ SMARTLIST_FOREACH(unrecognized, char *, cp, tor_free(cp));
smartlist_free(unrecognized);
- tor_free(msg);
return 0;
}
@@ -3324,7 +3410,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
nodes = smartlist_new();
SMARTLIST_FOREACH_BEGIN(router_nicknames, const char *, n) {
- const node_t *node = node_get_by_nickname(n, 1);
+ const node_t *node = node_get_by_nickname(n, 0);
if (!node) {
connection_printf_to_buf(conn, "552 No such router \"%s\"\r\n", n);
goto done;
@@ -3350,7 +3436,8 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
SMARTLIST_FOREACH(nodes, const node_t *, node,
{
extend_info_t *info = extend_info_from_node(node, first_node);
- if (first_node && !info) {
+ if (!info) {
+ tor_assert_nonfatal(first_node);
log_warn(LD_CONTROL,
"controller tried to connect to a node that doesn't have any "
"addresses that are allowed by the firewall configuration; "
@@ -3358,10 +3445,6 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
circuit_mark_for_close(TO_CIRCUIT(circ), -END_CIRC_REASON_CONNECTFAILED);
connection_write_str_to_buf("551 Couldn't start circuit\r\n", conn);
goto done;
- } else {
- /* True, since node_has_descriptor(node) == true and we are extending
- * to the node's primary address */
- tor_assert(info);
}
circuit_append_new_exit(circ, info);
extend_info_free(info);
@@ -3377,7 +3460,8 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
goto done;
}
} else {
- if (circ->base_.state == CIRCUIT_STATE_OPEN) {
+ if (circ->base_.state == CIRCUIT_STATE_OPEN ||
+ circ->base_.state == CIRCUIT_STATE_GUARD_WAIT) {
int err_reason = 0;
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
if ((err_reason = circuit_send_next_onion_skin(circ)) < 0) {
@@ -3519,24 +3603,9 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
}
/* Is this a single hop circuit? */
if (circ && (circuit_get_cpath_len(circ)<2 || hop==1)) {
- const node_t *node = NULL;
- char *exit_digest = NULL;
- if (circ->build_state &&
- circ->build_state->chosen_exit &&
- !tor_digest_is_zero(circ->build_state->chosen_exit->identity_digest)) {
- exit_digest = circ->build_state->chosen_exit->identity_digest;
- node = node_get_by_id(exit_digest);
- }
- /* Do both the client and relay allow one-hop exit circuits? */
- if (!node ||
- !node_allows_single_hop_exits(node) ||
- !get_options()->AllowSingleHopCircuits) {
- connection_write_str_to_buf(
- "551 Can't attach stream to this one-hop circuit.\r\n", conn);
- return 0;
- }
- tor_assert(exit_digest);
- ap_conn->chosen_exit_name = tor_strdup(hex_str(exit_digest, DIGEST_LEN));
+ connection_write_str_to_buf(
+ "551 Can't attach stream to this one-hop circuit.\r\n", conn);
+ return 0;
}
if (circ && hop>0) {
@@ -4039,6 +4108,14 @@ handle_control_dropguards(control_connection_t *conn,
smartlist_split_string(args, body, " ",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ static int have_warned = 0;
+ if (! have_warned) {
+ log_warn(LD_CONTROL, "DROPGUARDS is dangerous; make sure you understand "
+ "the risks before using it. It may be removed in a future "
+ "version of Tor.");
+ have_warned = 1;
+ }
+
if (smartlist_len(args)) {
connection_printf_to_buf(conn, "512 Too many arguments to DROPGUARDS\r\n");
} else {
@@ -4074,7 +4151,7 @@ handle_control_hsfetch(control_connection_t *conn, uint32_t len,
/* Extract the first argument (either HSAddress or DescID). */
arg1 = smartlist_get(args, 0);
/* Test if it's an HS address without the .onion part. */
- if (rend_valid_service_id(arg1)) {
+ if (rend_valid_v2_service_id(arg1)) {
hsaddress = arg1;
} else if (strcmpstart(arg1, v2_str) == 0 &&
rend_valid_descriptor_id(arg1 + v2_str_len) &&
@@ -4084,7 +4161,7 @@ handle_control_hsfetch(control_connection_t *conn, uint32_t len,
* of the id. */
desc_id = digest;
} else {
- connection_printf_to_buf(conn, "513 Unrecognized \"%s\"\r\n",
+ connection_printf_to_buf(conn, "513 Invalid argument \"%s\"\r\n",
arg1);
goto done;
}
@@ -4100,7 +4177,7 @@ handle_control_hsfetch(control_connection_t *conn, uint32_t len,
const char *server;
server = arg + strlen(opt_server);
- node = node_get_by_hex_id(server);
+ node = node_get_by_hex_id(server, 0);
if (!node) {
connection_printf_to_buf(conn, "552 Server \"%s\" not found\r\n",
server);
@@ -4186,7 +4263,7 @@ handle_control_hspost(control_connection_t *conn,
SMARTLIST_FOREACH_BEGIN(args, const char *, arg) {
if (!strcasecmpstart(arg, opt_server)) {
const char *server = arg + strlen(opt_server);
- const node_t *node = node_get_by_hex_id(server);
+ const node_t *node = node_get_by_hex_id(server, 0);
if (!node || !node->rs) {
connection_printf_to_buf(conn, "552 Server \"%s\" not found\r\n",
@@ -4718,7 +4795,7 @@ handle_control_del_onion(control_connection_t *conn,
return 0;
const char *service_id = smartlist_get(args, 0);
- if (!rend_valid_service_id(service_id)) {
+ if (!rend_valid_v2_service_id(service_id)) {
connection_printf_to_buf(conn, "512 Malformed Onion Service id\r\n");
goto out;
}
@@ -4859,6 +4936,38 @@ peek_connection_has_control0_command(connection_t *conn)
return peek_buf_has_control0_command(conn->inbuf);
}
+static int
+peek_connection_has_http_command(connection_t *conn)
+{
+ return peek_buf_has_http_command(conn->inbuf);
+}
+
+static const char CONTROLPORT_IS_NOT_AN_HTTP_PROXY_MSG[] =
+ "HTTP/1.0 501 Tor ControlPort is not an HTTP proxy"
+ "\r\nContent-Type: text/html; charset=iso-8859-1\r\n\r\n"
+ "<html>\n"
+ "<head>\n"
+ "<title>Tor's ControlPort is not an HTTP proxy</title>\n"
+ "</head>\n"
+ "<body>\n"
+ "<h1>Tor's ControlPort is not an HTTP proxy</h1>\n"
+ "<p>\n"
+ "It appears you have configured your web browser to use Tor's control port"
+ " as an HTTP proxy.\n"
+ "This is not correct: Tor's default SOCKS proxy port is 9050.\n"
+ "Please configure your client accordingly.\n"
+ "</p>\n"
+ "<p>\n"
+ "See <a href=\"https://www.torproject.org/documentation.html\">"
+ "https://www.torproject.org/documentation.html</a> for more "
+ "information.\n"
+ "<!-- Plus this comment, to make the body response more than 512 bytes, so "
+ " IE will be willing to display it. Comment comment comment comment "
+ " comment comment comment comment comment comment comment comment.-->\n"
+ "</p>\n"
+ "</body>\n"
+ "</html>\n";
+
/** Called when data has arrived on a v1 control connection: Try to fetch
* commands from conn->inbuf, and execute them.
*/
@@ -4892,12 +5001,21 @@ connection_control_process_inbuf(control_connection_t *conn)
sizeof(buf)-6);
body_len = 2+strlen(buf+6)+2; /* code, msg, nul. */
set_uint16(buf+0, htons(body_len));
- connection_write_to_buf(buf, 4+body_len, TO_CONN(conn));
+ connection_buf_add(buf, 4+body_len, TO_CONN(conn));
connection_mark_and_flush(TO_CONN(conn));
return 0;
}
+ /* If the user has the HTTP proxy port and the control port confused. */
+ if (conn->base_.state == CONTROL_CONN_STATE_NEEDAUTH &&
+ peek_connection_has_http_command(TO_CONN(conn))) {
+ connection_write_str_to_buf(CONTROLPORT_IS_NOT_AN_HTTP_PROXY_MSG, conn);
+ log_notice(LD_CONTROL, "Received HTTP request on ControlPort");
+ connection_mark_and_flush(TO_CONN(conn));
+ return 0;
+ }
+
again:
while (1) {
size_t last_idx;
@@ -4905,7 +5023,7 @@ connection_control_process_inbuf(control_connection_t *conn)
/* First, fetch a line. */
do {
data_len = conn->incoming_cmd_len - conn->incoming_cmd_cur_len;
- r = connection_fetch_from_buf_line(TO_CONN(conn),
+ r = connection_buf_get_line(TO_CONN(conn),
conn->incoming_cmd+conn->incoming_cmd_cur_len,
&data_len);
if (r == 0)
@@ -5473,15 +5591,20 @@ control_event_stream_bandwidth(edge_connection_t *edge_conn)
{
circuit_t *circ;
origin_circuit_t *ocirc;
+ struct timeval now;
+ char tbuf[ISO_TIME_USEC_LEN+1];
if (EVENT_IS_INTERESTING(EVENT_STREAM_BANDWIDTH_USED)) {
if (!edge_conn->n_read && !edge_conn->n_written)
return 0;
+ tor_gettimeofday(&now);
+ format_iso_time_nospace_usec(tbuf, &now);
send_control_event(EVENT_STREAM_BANDWIDTH_USED,
- "650 STREAM_BW "U64_FORMAT" %lu %lu\r\n",
+ "650 STREAM_BW "U64_FORMAT" %lu %lu %s\r\n",
U64_PRINTF_ARG(edge_conn->base_.global_identifier),
(unsigned long)edge_conn->n_read,
- (unsigned long)edge_conn->n_written);
+ (unsigned long)edge_conn->n_written,
+ tbuf);
circ = circuit_get_by_edge_conn(edge_conn);
if (circ && CIRCUIT_IS_ORIGIN(circ)) {
@@ -5503,6 +5626,8 @@ control_event_stream_bandwidth_used(void)
if (EVENT_IS_INTERESTING(EVENT_STREAM_BANDWIDTH_USED)) {
smartlist_t *conns = get_connection_array();
edge_connection_t *edge_conn;
+ struct timeval now;
+ char tbuf[ISO_TIME_USEC_LEN+1];
SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn)
{
@@ -5512,11 +5637,14 @@ control_event_stream_bandwidth_used(void)
if (!edge_conn->n_read && !edge_conn->n_written)
continue;
+ tor_gettimeofday(&now);
+ format_iso_time_nospace_usec(tbuf, &now);
send_control_event(EVENT_STREAM_BANDWIDTH_USED,
- "650 STREAM_BW "U64_FORMAT" %lu %lu\r\n",
+ "650 STREAM_BW "U64_FORMAT" %lu %lu %s\r\n",
U64_PRINTF_ARG(edge_conn->base_.global_identifier),
(unsigned long)edge_conn->n_read,
- (unsigned long)edge_conn->n_written);
+ (unsigned long)edge_conn->n_written,
+ tbuf);
edge_conn->n_written = edge_conn->n_read = 0;
}
@@ -5532,6 +5660,8 @@ int
control_event_circ_bandwidth_used(void)
{
origin_circuit_t *ocirc;
+ struct timeval now;
+ char tbuf[ISO_TIME_USEC_LEN+1];
if (!EVENT_IS_INTERESTING(EVENT_CIRC_BANDWIDTH_USED))
return 0;
@@ -5541,11 +5671,15 @@ control_event_circ_bandwidth_used(void)
ocirc = TO_ORIGIN_CIRCUIT(circ);
if (!ocirc->n_read_circ_bw && !ocirc->n_written_circ_bw)
continue;
+ tor_gettimeofday(&now);
+ format_iso_time_nospace_usec(tbuf, &now);
send_control_event(EVENT_CIRC_BANDWIDTH_USED,
- "650 CIRC_BW ID=%d READ=%lu WRITTEN=%lu\r\n",
+ "650 CIRC_BW ID=%d READ=%lu WRITTEN=%lu "
+ "TIME=%s\r\n",
ocirc->global_identifier,
(unsigned long)ocirc->n_read_circ_bw,
- (unsigned long)ocirc->n_written_circ_bw);
+ (unsigned long)ocirc->n_written_circ_bw,
+ tbuf);
ocirc->n_written_circ_bw = ocirc->n_read_circ_bw = 0;
}
SMARTLIST_FOREACH_END(circ);
@@ -5716,7 +5850,7 @@ control_event_circuit_cell_stats(void)
if (!get_options()->TestingEnableCellStatsEvent ||
!EVENT_IS_INTERESTING(EVENT_CELL_STATS))
return 0;
- cell_stats = tor_malloc(sizeof(cell_stats_t));;
+ cell_stats = tor_malloc(sizeof(cell_stats_t));
SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ) {
if (!circ->testing_cell_stats)
continue;
@@ -5951,47 +6085,6 @@ control_event_address_mapped(const char *from, const char *to, time_t expires,
return 0;
}
-/** The authoritative dirserver has received a new descriptor that
- * has passed basic syntax checks and is properly self-signed.
- *
- * Notify any interested party of the new descriptor and what has
- * been done with it, and also optionally give an explanation/reason. */
-int
-control_event_or_authdir_new_descriptor(const char *action,
- const char *desc, size_t desclen,
- const char *msg)
-{
- char firstline[1024];
- char *buf;
- size_t totallen;
- char *esc = NULL;
- size_t esclen;
-
- if (!EVENT_IS_INTERESTING(EVENT_AUTHDIR_NEWDESCS))
- return 0;
-
- tor_snprintf(firstline, sizeof(firstline),
- "650+AUTHDIR_NEWDESC=\r\n%s\r\n%s\r\n",
- action,
- msg ? msg : "");
-
- /* Escape the server descriptor properly */
- esclen = write_escaped_data(desc, desclen, &esc);
-
- totallen = strlen(firstline) + esclen + 1;
- buf = tor_malloc(totallen);
- strlcpy(buf, firstline, totallen);
- strlcpy(buf+strlen(firstline), esc, totallen);
- send_control_event_string(EVENT_AUTHDIR_NEWDESCS,
- buf);
- send_control_event_string(EVENT_AUTHDIR_NEWDESCS,
- "650 OK\r\n");
- tor_free(esc);
- tor_free(buf);
-
- return 0;
-}
-
/** Cached liveness for network liveness events and GETINFO
*/
@@ -6053,9 +6146,9 @@ control_event_networkstatus_changed_helper(smartlist_t *statuses,
return 0;
strs = smartlist_new();
- smartlist_add(strs, tor_strdup("650+"));
- smartlist_add(strs, tor_strdup(event_string));
- smartlist_add(strs, tor_strdup("\r\n"));
+ smartlist_add_strdup(strs, "650+");
+ smartlist_add_strdup(strs, event_string);
+ smartlist_add_strdup(strs, "\r\n");
SMARTLIST_FOREACH(statuses, const routerstatus_t *, rs,
{
s = networkstatus_getinfo_helper_single(rs);
@@ -6483,7 +6576,7 @@ monitor_owning_controller_process(const char *process_spec)
msg);
owning_controller_process_spec = NULL;
tor_cleanup();
- exit(0);
+ exit(1);
}
}
@@ -6681,80 +6774,112 @@ control_event_bootstrap(bootstrap_status_t status, int progress)
}
/** Called when Tor has failed to make bootstrapping progress in a way
- * that indicates a problem. <b>warn</b> gives a hint as to why, and
- * <b>reason</b> provides an "or_conn_end_reason" tag. <b>or_conn</b>
- * is the connection that caused this problem.
+ * that indicates a problem. <b>warn</b> gives a human-readable hint
+ * as to why, and <b>reason</b> provides a controller-facing short
+ * tag. <b>conn</b> is the connection that caused this problem and
+ * can be NULL if a connection cannot be easily identified.
*/
-MOCK_IMPL(void,
- control_event_bootstrap_problem, (const char *warn, int reason,
- or_connection_t *or_conn))
+void
+control_event_bootstrap_problem(const char *warn, const char *reason,
+ const connection_t *conn, int dowarn)
{
int status = bootstrap_percent;
const char *tag = "", *summary = "";
char buf[BOOTSTRAP_MSG_LEN];
const char *recommendation = "ignore";
int severity;
+ char *or_id = NULL, *hostaddr = NULL;
+ or_connection_t *or_conn = NULL;
/* bootstrap_percent must not be in "undefined" state here. */
tor_assert(status >= 0);
- if (or_conn->have_noted_bootstrap_problem)
- return;
-
- or_conn->have_noted_bootstrap_problem = 1;
-
if (bootstrap_percent == 100)
return; /* already bootstrapped; nothing to be done here. */
bootstrap_problems++;
if (bootstrap_problems >= BOOTSTRAP_PROBLEM_THRESHOLD)
- recommendation = "warn";
-
- if (reason == END_OR_CONN_REASON_NO_ROUTE)
- recommendation = "warn";
-
- /* If we are using bridges and all our OR connections are now
- closed, it means that we totally failed to connect to our
- bridges. Throw a warning. */
- if (get_options()->UseBridges && !any_other_active_or_conns(or_conn))
- recommendation = "warn";
+ dowarn = 1;
if (we_are_hibernating())
- recommendation = "ignore";
+ dowarn = 0;
while (status>=0 && bootstrap_status_to_string(status, &tag, &summary) < 0)
status--; /* find a recognized status string based on current progress */
status = bootstrap_percent; /* set status back to the actual number */
- severity = !strcmp(recommendation, "warn") ? LOG_WARN : LOG_INFO;
+ severity = dowarn ? LOG_WARN : LOG_INFO;
+
+ if (dowarn)
+ recommendation = "warn";
+
+ if (conn && conn->type == CONN_TYPE_OR) {
+ /* XXX TO_OR_CONN can't deal with const */
+ or_conn = TO_OR_CONN((connection_t *)conn);
+ or_id = tor_strdup(hex_str(or_conn->identity_digest, DIGEST_LEN));
+ } else {
+ or_id = tor_strdup("?");
+ }
+
+ if (conn)
+ tor_asprintf(&hostaddr, "%s:%d", conn->address, (int)conn->port);
+ else
+ hostaddr = tor_strdup("?");
log_fn(severity,
LD_CONTROL, "Problem bootstrapping. Stuck at %d%%: %s. (%s; %s; "
- "count %d; recommendation %s; host %s at %s:%d)",
- status, summary, warn,
- orconn_end_reason_to_control_string(reason),
+ "count %d; recommendation %s; host %s at %s)",
+ status, summary, warn, reason,
bootstrap_problems, recommendation,
- hex_str(or_conn->identity_digest, DIGEST_LEN),
- or_conn->base_.address,
- or_conn->base_.port);
+ or_id, hostaddr);
connection_or_report_broken_states(severity, LD_HANDSHAKE);
tor_snprintf(buf, sizeof(buf),
"BOOTSTRAP PROGRESS=%d TAG=%s SUMMARY=\"%s\" WARNING=\"%s\" REASON=%s "
- "COUNT=%d RECOMMENDATION=%s HOSTID=\"%s\" HOSTADDR=\"%s:%d\"",
- bootstrap_percent, tag, summary, warn,
- orconn_end_reason_to_control_string(reason), bootstrap_problems,
+ "COUNT=%d RECOMMENDATION=%s HOSTID=\"%s\" HOSTADDR=\"%s\"",
+ bootstrap_percent, tag, summary, warn, reason, bootstrap_problems,
recommendation,
- hex_str(or_conn->identity_digest, DIGEST_LEN),
- or_conn->base_.address,
- (int)or_conn->base_.port);
+ or_id, hostaddr);
tor_snprintf(last_sent_bootstrap_message,
sizeof(last_sent_bootstrap_message),
"WARN %s", buf);
control_event_client_status(LOG_WARN, "%s", buf);
+
+ tor_free(hostaddr);
+ tor_free(or_id);
+}
+
+/** Called when Tor has failed to make bootstrapping progress in a way
+ * that indicates a problem. <b>warn</b> gives a hint as to why, and
+ * <b>reason</b> provides an "or_conn_end_reason" tag. <b>or_conn</b>
+ * is the connection that caused this problem.
+ */
+MOCK_IMPL(void,
+control_event_bootstrap_prob_or, (const char *warn, int reason,
+ or_connection_t *or_conn))
+{
+ int dowarn = 0;
+
+ if (or_conn->have_noted_bootstrap_problem)
+ return;
+
+ or_conn->have_noted_bootstrap_problem = 1;
+
+ if (reason == END_OR_CONN_REASON_NO_ROUTE)
+ dowarn = 1;
+
+ /* If we are using bridges and all our OR connections are now
+ closed, it means that we totally failed to connect to our
+ bridges. Throw a warning. */
+ if (get_options()->UseBridges && !any_other_active_or_conns(or_conn))
+ dowarn = 1;
+
+ control_event_bootstrap_problem(warn,
+ orconn_end_reason_to_control_string(reason),
+ TO_CONN(or_conn), dowarn);
}
/** We just generated a new summary of which countries we've seen clients
@@ -6864,8 +6989,10 @@ control_event_hs_descriptor_requested(const rend_data_t *rend_query,
send_control_event(EVENT_HS_DESC,
"650 HS_DESC REQUESTED %s %s %s %s\r\n",
- rend_hsaddress_str_or_unknown(rend_query->onion_address),
- rend_auth_type_to_string(rend_query->auth_type),
+ rend_hsaddress_str_or_unknown(
+ rend_data_get_address(rend_query)),
+ rend_auth_type_to_string(
+ TO_REND_DATA_V2(rend_query)->auth_type),
node_describe_longname_by_id(id_digest),
desc_id_base32);
}
@@ -6881,19 +7008,25 @@ get_desc_id_from_query(const rend_data_t *rend_data, const char *hsdir_fp)
{
int replica;
const char *desc_id = NULL;
+ const rend_data_v2_t *rend_data_v2 = TO_REND_DATA_V2(rend_data);
/* Possible if the fetch was done using a descriptor ID. This means that
* the HSFETCH command was used. */
- if (!tor_digest_is_zero(rend_data->desc_id_fetch)) {
- desc_id = rend_data->desc_id_fetch;
+ if (!tor_digest_is_zero(rend_data_v2->desc_id_fetch)) {
+ desc_id = rend_data_v2->desc_id_fetch;
goto end;
}
+ /* Without a directory fingerprint at this stage, we can't do much. */
+ if (hsdir_fp == NULL) {
+ goto end;
+ }
+
/* OK, we have an onion address so now let's find which descriptor ID
* is the one associated with the HSDir fingerprint. */
for (replica = 0; replica < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS;
replica++) {
- const char *digest = rend_data->descriptor_id[replica];
+ const char *digest = rend_data_get_desc_id(rend_data, replica, NULL);
SMARTLIST_FOREACH_BEGIN(rend_data->hsdirs_fp, char *, fingerprint) {
if (tor_memcmp(fingerprint, hsdir_fp, DIGEST_LEN) == 0) {
@@ -6978,10 +7111,9 @@ control_event_hs_descriptor_receive_end(const char *action,
char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
const char *desc_id = NULL;
- if (!action || !id_digest || !rend_data || !onion_address) {
- log_warn(LD_BUG, "Called with action==%p, id_digest==%p, "
- "rend_data==%p, onion_address==%p", action, id_digest,
- rend_data, onion_address);
+ if (!action || !rend_data || !onion_address) {
+ log_warn(LD_BUG, "Called with action==%p, rend_data==%p, "
+ "onion_address==%p", action, rend_data, onion_address);
return;
}
@@ -7002,8 +7134,10 @@ control_event_hs_descriptor_receive_end(const char *action,
"650 HS_DESC %s %s %s %s%s%s\r\n",
action,
rend_hsaddress_str_or_unknown(onion_address),
- rend_auth_type_to_string(rend_data->auth_type),
- node_describe_longname_by_id(id_digest),
+ rend_auth_type_to_string(
+ TO_REND_DATA_V2(rend_data)->auth_type),
+ id_digest ?
+ node_describe_longname_by_id(id_digest) : "UNKNOWN",
desc_id_field ? desc_id_field : "",
reason_field ? reason_field : "");
@@ -7083,28 +7217,30 @@ control_event_hs_descriptor_uploaded(const char *id_digest,
id_digest, NULL);
}
-/** Send HS_DESC event to inform controller that query <b>rend_query</b>
- * failed to retrieve hidden service descriptor identified by
- * <b>id_digest</b>. If <b>reason</b> is not NULL, add it to REASON=
- * field.
+/** Send HS_DESC event to inform controller that query <b>rend_data</b>
+ * failed to retrieve hidden service descriptor from directory identified by
+ * <b>id_digest</b>. If NULL, "UNKNOWN" is used. If <b>reason</b> is not NULL,
+ * add it to REASON= field.
*/
void
control_event_hs_descriptor_failed(const rend_data_t *rend_data,
const char *id_digest,
const char *reason)
{
- if (!rend_data || !id_digest) {
- log_warn(LD_BUG, "Called with rend_data==%p, id_digest==%p",
- rend_data, id_digest);
+ if (!rend_data) {
+ log_warn(LD_BUG, "Called with rend_data==%p", rend_data);
return;
}
control_event_hs_descriptor_receive_end("FAILED",
- rend_data->onion_address,
+ rend_data_get_address(rend_data),
rend_data, id_digest, reason);
}
-/** send HS_DESC_CONTENT event after completion of a successful fetch from
- * hs directory. */
+/** Send HS_DESC_CONTENT event after completion of a successful fetch from hs
+ * directory. If <b>hsdir_id_digest</b> is NULL, it is replaced by "UNKNOWN".
+ * If <b>content</b> is NULL, it is replaced by an empty string. The
+ * <b>onion_address</b> or <b>desc_id</b> set to NULL will no trigger the
+ * control event. */
void
control_event_hs_descriptor_content(const char *onion_address,
const char *desc_id,
@@ -7114,9 +7250,9 @@ control_event_hs_descriptor_content(const char *onion_address,
static const char *event_name = "HS_DESC_CONTENT";
char *esc_content = NULL;
- if (!onion_address || !desc_id || !hsdir_id_digest) {
- log_warn(LD_BUG, "Called with onion_address==%p, desc_id==%p, "
- "hsdir_id_digest==%p", onion_address, desc_id, hsdir_id_digest);
+ if (!onion_address || !desc_id) {
+ log_warn(LD_BUG, "Called with onion_address==%p, desc_id==%p, ",
+ onion_address, desc_id);
return;
}
@@ -7131,7 +7267,9 @@ control_event_hs_descriptor_content(const char *onion_address,
event_name,
rend_hsaddress_str_or_unknown(onion_address),
desc_id,
- node_describe_longname_by_id(hsdir_id_digest),
+ hsdir_id_digest ?
+ node_describe_longname_by_id(hsdir_id_digest) :
+ "UNKNOWN",
esc_content);
tor_free(esc_content);
}
@@ -7150,7 +7288,7 @@ control_event_hs_descriptor_upload_failed(const char *id_digest,
id_digest);
return;
}
- control_event_hs_descriptor_upload_end("UPLOAD_FAILED", onion_address,
+ control_event_hs_descriptor_upload_end("FAILED", onion_address,
id_digest, reason);
}
@@ -7183,5 +7321,4 @@ control_testing_set_global_event_mask(uint64_t mask)
{
global_event_mask = mask;
}
-#endif
-
+#endif /* defined(TOR_UNIT_TESTS) */