summaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
authorAndrea Shepard <andrea@torproject.org>2016-06-28 02:21:39 +0000
committerAndrea Shepard <andrea@torproject.org>2016-06-29 05:55:42 +0000
commit8798ca4be299855a9a87a48df772081e06e9040c (patch)
treeec60d000b9012f0110ce2aa8cbe77ddacafa81b5 /src/or
parent18c6e139932630615bf3fee232dc5e08fac42449 (diff)
downloadtor-8798ca4be299855a9a87a48df772081e06e9040c.tar.gz
tor-8798ca4be299855a9a87a48df772081e06e9040c.zip
Add router descriptor download status queries to GETINFO
Diffstat (limited to 'src/or')
-rw-r--r--src/or/control.c56
-rw-r--r--src/or/networkstatus.c37
-rw-r--r--src/or/networkstatus.h1
3 files changed, 94 insertions, 0 deletions
diff --git a/src/or/control.c b/src/or/control.c
index a45b5f903d..7b8699d4ac 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -2307,6 +2307,52 @@ getinfo_helper_downloads_cert(const char *fp_sk_req,
}
}
+/** Handle the routerdesc download cases for getinfo_helper_downloads() */
+static void
+getinfo_helper_downloads_desc(const char *desc_req,
+ download_status_t **dl_to_emit,
+ smartlist_t **digest_list,
+ const char **errmsg)
+{
+ char desc_digest[DIGEST_LEN];
+ /*
+ * Two cases to handle here:
+ *
+ * Case 1: desc_req = "descs"
+ * - Emit a list of all router descriptor digests, which we get by
+ * calling router_get_descriptor_digests(); this can return NULL
+ * if we have no current ns-flavor consensus.
+ *
+ * Case 2: desc_req = <fp>
+ * - Check on the specified fingerprint and emit its download_status_t
+ * using router_get_dl_status_by_descriptor_digest().
+ */
+
+ if (strcmp(desc_req, "descs") == 0) {
+ *digest_list = router_get_descriptor_digests();
+ if (!(*digest_list)) {
+ *errmsg = "We don't seem to have a networkstatus-flavored consensus";
+ }
+ /*
+ * Microdescs don't use the download_status_t mechanism, so we don't
+ * answer queries about their downloads here; see microdesc.c.
+ */
+ } else if (strlen(desc_req) == HEX_DIGEST_LEN) {
+ if (base16_decode(desc_digest, DIGEST_LEN,
+ desc_req, strlen(desc_req)) == DIGEST_LEN) {
+ /* Okay we got a digest-shaped thing; try asking for it */
+ *dl_to_emit = router_get_dl_status_by_descriptor_digest(desc_digest);
+ if (!(*dl_to_emit)) {
+ *errmsg = "No such descriptor digest found";
+ }
+ } else {
+ *errmsg = "That didn't look like a digest";
+ }
+ } else {
+ *errmsg = "Unknown router descriptor download status query";
+ }
+}
+
/** Implementation helper for GETINFO: knows the answers for questions about
* download status information. */
static int
@@ -2335,6 +2381,10 @@ getinfo_helper_downloads(control_connection_t *control_conn,
getinfo_helper_downloads_cert(
question + strlen("downloads/cert/"),
&dl_to_emit, &digest_list, errmsg);
+ } else if (!strcmpstart(question, "downloads/desc/")) {
+ getinfo_helper_downloads_desc(
+ question + strlen("downloads/desc/"),
+ &dl_to_emit, &digest_list, errmsg);
} else {
*errmsg = "Unknown download status query";
}
@@ -2826,6 +2876,12 @@ static const getinfo_item_t getinfo_items[] = {
DOC("downloads/cert/fp/<fp>/<sk>",
"Download status for <fp> with signing key <sk>; corresponds "
"to /fp-sk/ URLs on directory server."),
+ PREFIX("downloads/desc/", downloads,
+ "Download statuses for router descriptors, by descriptor digest"),
+ DOC("downloads/desc/descs",
+ "Return a list of known router descriptor digests"),
+ DOC("downloads/desc/<desc>",
+ "Return a download status for a given descriptor digest"),
ITEM("info/names", misc,
"List of GETINFO options, types, and documentation."),
ITEM("events/names", misc,
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 45688b18f6..a582b852ae 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -659,6 +659,43 @@ router_get_consensus_status_by_descriptor_digest(networkstatus_t *consensus,
consensus, digest);
}
+/** Return a smartlist of all router descriptor digests in a consensus */
+static smartlist_t *
+router_get_descriptor_digests_in_consensus(networkstatus_t *consensus)
+{
+ smartlist_t *result = smartlist_new();
+ digestmap_iter_t *i;
+ const char *digest;
+ void *rs;
+ char *digest_tmp;
+
+ for (i = digestmap_iter_init(consensus->desc_digest_map);
+ !(digestmap_iter_done(i));
+ i = digestmap_iter_next(consensus->desc_digest_map, i)) {
+ digestmap_iter_get(i, &digest, &rs);
+ digest_tmp = tor_malloc(DIGEST_LEN);
+ memcpy(digest_tmp, digest, DIGEST_LEN);
+ smartlist_add(result, digest_tmp);
+ }
+
+ return result;
+}
+
+/** Return a smartlist of all router descriptor digests in the current
+ * consensus */
+smartlist_t *
+router_get_descriptor_digests(void)
+{
+ smartlist_t *result = NULL;
+
+ if (current_ns_consensus) {
+ result =
+ router_get_descriptor_digests_in_consensus(current_ns_consensus);
+ }
+
+ return result;
+}
+
/** Given the digest of a router descriptor, return its current download
* status, or NULL if the digest is unrecognized. */
MOCK_IMPL(download_status_t *,
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index 752ddf8e1e..6d5d05aefc 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -45,6 +45,7 @@ download_status_t * networkstatus_get_dl_status_by_flavor_bootstrap(
download_status_t * networkstatus_get_dl_status_by_flavor_running(
consensus_flavor_t flavor);
+smartlist_t * router_get_descriptor_digests(void);
MOCK_DECL(download_status_t *,router_get_dl_status_by_descriptor_digest,
(const char *d));