diff --git a/changes/bug22042 b/changes/bug22042
new file mode 100644
index 0000000000..c1188df478
--- /dev/null
+++ b/changes/bug22042
@@ -0,0 +1,5 @@
+ o Minor bugfixes (control, hidden service client):
+ - Trigger HS descriptor events on the control port when the client is
+ unable to pick a suitable hidden service directory. This can happen if
+ they are all in the ExcludeNodes list or they all have been queried
+ inside the allowed 15 minutes. Fixes bug 22042.
diff --git a/src/or/control.c b/src/or/control.c
index 56f1329029..9b0d7c0007 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -7013,10 +7013,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;
}
@@ -7039,7 +7038,8 @@ control_event_hs_descriptor_receive_end(const char *action,
rend_hsaddress_str_or_unknown(onion_address),
rend_auth_type_to_string(
TO_REND_DATA_V2(rend_data)->auth_type),
- node_describe_longname_by_id(id_digest),
+ id_digest ?
+ node_describe_longname_by_id(id_digest) : "UNKNOWN",
desc_id_field ? desc_id_field : "",
reason_field ? reason_field : "");
@@ -7119,19 +7119,18 @@ control_event_hs_descriptor_uploaded(const char *id_digest,
id_digest, NULL);
}
-/** Send HS_DESC event to inform controller that query rend_query
- * failed to retrieve hidden service descriptor identified by
- * id_digest. If reason is not NULL, add it to REASON=
- * field.
+/** Send HS_DESC event to inform controller that query rend_data
+ * failed to retrieve hidden service descriptor from directory identified by
+ * id_digest. If NULL, "UNKNOWN" is used. If reason 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",
@@ -7139,8 +7138,11 @@ control_event_hs_descriptor_failed(const rend_data_t *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 hsdir_id_digest is NULL, it is replaced by "UNKNOWN".
+ * If content is NULL, it is replaced by an empty string. The
+ * onion_address or desc_id set to NULL will no trigger the
+ * control event. */
void
control_event_hs_descriptor_content(const char *onion_address,
const char *desc_id,
@@ -7150,9 +7152,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;
}
@@ -7167,7 +7169,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);
}
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 1ae03ed408..9bc2d6289d 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -724,6 +724,9 @@ directory_get_from_hs_dir(const char *desc_id,
hs_dir = pick_hsdir(desc_id, desc_id_base32);
if (!hs_dir) {
/* No suitable hs dir can be found, stop right now. */
+ control_event_hs_descriptor_failed(rend_query, NULL, "QUERY_NO_HSDIR");
+ control_event_hs_descriptor_content(rend_data_get_address(rend_query),
+ desc_id_base32, NULL, NULL);
return 0;
}
}
@@ -744,6 +747,9 @@ directory_get_from_hs_dir(const char *desc_id,
REND_DESC_COOKIE_LEN,
0)<0) {
log_warn(LD_BUG, "Could not base64-encode descriptor cookie.");
+ control_event_hs_descriptor_failed(rend_query, hsdir_fp, "BAD_DESC");
+ control_event_hs_descriptor_content(rend_data_get_address(rend_query),
+ desc_id_base32, hsdir_fp, NULL);
return 0;
}
/* Remove == signs. */