|
@@ -1677,6 +1677,49 @@ networkstatus_getinfo_helper_single(routerstatus_t *rs)
|
|
|
return tor_strdup(buf);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * recent info of each router we know about that is of purpose
|
|
|
+ * <b>purpose_string</b>. Return NULL if unrecognized purpose.
|
|
|
+ *
|
|
|
+ * Right now this function is oriented toward listing bridges (you
|
|
|
+ * shouldn't use this for general-purpose routers, since those
|
|
|
+ * should be listed from the consensus, not from the routers list). */
|
|
|
+char *
|
|
|
+networkstatus_getinfo_by_purpose(const char *purpose_string)
|
|
|
+{
|
|
|
+ time_t now = time(NULL);
|
|
|
+ time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
|
|
|
+ char *answer;
|
|
|
+ routerlist_t *rl = router_get_routerlist();
|
|
|
+ smartlist_t *statuses = smartlist_create();
|
|
|
+ uint8_t purpose = router_purpose_from_string(purpose_string);
|
|
|
+ routerstatus_t rs;
|
|
|
+ int bridge_auth = authdir_mode_bridge(get_options());
|
|
|
+
|
|
|
+ if (purpose == ROUTER_PURPOSE_UNKNOWN) {
|
|
|
+ log_info(LD_DIR, "Unrecognized purpose '%s' when listing router statuses.",
|
|
|
+ purpose_string);
|
|
|
+ return NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
|
|
|
+ if (ri->cache_info.published_on < cutoff)
|
|
|
+ continue;
|
|
|
+ if (ri->purpose != purpose)
|
|
|
+ continue;
|
|
|
+ if (bridge_auth && ri->purpose == ROUTER_PURPOSE_BRIDGE)
|
|
|
+ dirserv_set_router_is_running(ri, now);
|
|
|
+
|
|
|
+ set_routerstatus_from_routerinfo(&rs, ri, now, 0, 0, 0, 0);
|
|
|
+ smartlist_add(statuses, networkstatus_getinfo_helper_single(&rs));
|
|
|
+ });
|
|
|
+
|
|
|
+ answer = smartlist_join_strings(statuses, "", 0, NULL);
|
|
|
+ SMARTLIST_FOREACH(statuses, char *, cp, tor_free(cp));
|
|
|
+ smartlist_free(statuses);
|
|
|
+ return answer;
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
* control interface expects for a GETINFO question, set *<b>answer</b> to a
|
|
|
* newly-allocated string containing networkstatus lines for the appropriate
|
|
@@ -1712,13 +1755,15 @@ getinfo_helper_networkstatus(control_connection_t *conn,
|
|
|
status = router_get_consensus_status_by_id(d);
|
|
|
} else if (!strcmpstart(question, "ns/name/")) {
|
|
|
status = router_get_consensus_status_by_nickname(question+8, 0);
|
|
|
+ } else if (!strcmpstart(question, "ns/purpose/")) {
|
|
|
+ *answer = networkstatus_getinfo_by_purpose(question+11);
|
|
|
+ return *answer ? 0 : -1;
|
|
|
} else {
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
- if (status) {
|
|
|
+ if (status)
|
|
|
*answer = networkstatus_getinfo_helper_single(status);
|
|
|
- }
|
|
|
return 0;
|
|
|
}
|
|
|
|