summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/or/control.c3
-rw-r--r--src/or/dirserv.c13
-rw-r--r--src/or/networkstatus.c49
-rw-r--r--src/or/or.h10
4 files changed, 63 insertions, 12 deletions
diff --git a/src/or/control.c b/src/or/control.c
index e404a4beb7..af1bb42f60 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -1453,7 +1453,8 @@ getinfo_helper_dir(control_connection_t *control_conn,
routerlist_t *routerlist = router_get_routerlist();
int verbose = control_conn->use_long_names;
if (!routerlist || !routerlist->routers ||
- list_server_status(routerlist->routers, answer, verbose ? 2 : 1) < 0) {
+ list_server_status_v1(routerlist->routers, answer,
+ verbose ? 2 : 1) < 0) {
return -1;
}
} else if (!strcmpstart(question, "extra-info/digest/")) {
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 5f19d15515..e45a6ea8f7 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -56,8 +56,6 @@ dirserv_get_status_impl(const char *fp, const char *nickname,
uint32_t addr, uint16_t or_port,
const char *platform, const char *contact,
const char **msg, int should_log);
-static void dirserv_set_router_is_running(routerinfo_t *router,
- time_t now);
static void clear_cached_dir(cached_dir_t *d);
static int dirserv_add_extrainfo(extrainfo_t *ei, const char **msg);
@@ -915,7 +913,7 @@ list_single_server_status(routerinfo_t *desc, int is_live)
/** Treat a router as alive if
* - It's me, and I'm not hibernating.
* or - We've found it reachable recently. */
-static void
+void
dirserv_set_router_is_running(routerinfo_t *router, time_t now)
{
int answer;
@@ -942,8 +940,8 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
* If for_controller is &gt;1, use the verbose nickname format.
*/
int
-list_server_status(smartlist_t *routers, char **router_status_out,
- int for_controller)
+list_server_status_v1(smartlist_t *routers, char **router_status_out,
+ int for_controller)
{
/* List of entries in a router-status style: An optional !, then an optional
* equals-suffixed nickname, then a dollar-prefixed hexdigest. */
@@ -952,7 +950,8 @@ list_server_status(smartlist_t *routers, char **router_status_out,
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
or_options_t *options = get_options();
/* We include v2 dir auths here too, because they need to answer
- * controllers. Eventually we'll deprecate this whole function. */
+ * controllers. Eventually we'll deprecate this whole function;
+ * see also networkstatus_getinfo_by_purpose(). */
int authdir = authdir_mode_publishes_statuses(options);
tor_assert(router_status_out);
@@ -1996,7 +1995,7 @@ get_possible_sybil_list(const smartlist_t *routers)
* We assume that ri-\>is_running has already been set, e.g. by
* dirserv_set_router_is_running(ri, now);
*/
-static void
+void
set_routerstatus_from_routerinfo(routerstatus_t *rs,
routerinfo_t *ri, time_t now,
int naming, int exits_can_be_guards,
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 3300c81b51..884bc0a3a6 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -1677,6 +1677,49 @@ networkstatus_getinfo_helper_single(routerstatus_t *rs)
return tor_strdup(buf);
}
+/** Alloc and return a string describing routerstatuses for the most
+ * 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);
+ /* then generate and write out status lines for each of them */
+ 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;
+}
+
/** If <b>question</b> is a string beginning with "ns/" in a format the
* 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;
}
diff --git a/src/or/or.h b/src/or/or.h
index b324b2e162..a59e7459b2 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3051,8 +3051,9 @@ int dirserv_add_descriptor(routerinfo_t *ri, const char **msg);
int getinfo_helper_dirserv_unregistered(control_connection_t *conn,
const char *question, char **answer);
void dirserv_free_descriptors(void);
-int list_server_status(smartlist_t *routers, char **router_status_out,
- int for_controller);
+void dirserv_set_router_is_running(routerinfo_t *router, time_t now);
+int list_server_status_v1(smartlist_t *routers, char **router_status_out,
+ int for_controller);
int dirserv_dump_directory_to_string(char **dir_out,
crypto_pk_env_t *private_key);
@@ -3158,6 +3159,10 @@ const char *dirvote_get_pending_detached_signatures(void);
#define DGV_INCLUDE_PENDING 2
#define DGV_INCLUDE_PREVIOUS 4
const cached_dir_t *dirvote_get_vote(const char *fp, int flags);
+void set_routerstatus_from_routerinfo(routerstatus_t *rs,
+ routerinfo_t *ri, time_t now,
+ int naming, int exits_can_be_guards,
+ int listbadexits, int listbaddirs);
void router_clear_status_flags(routerinfo_t *ri);
networkstatus_vote_t *
dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
@@ -3348,6 +3353,7 @@ void signed_descs_update_status_from_consensus_networkstatus(
smartlist_t *descs);
char *networkstatus_getinfo_helper_single(routerstatus_t *rs);
+char *networkstatus_getinfo_by_purpose(const char *purpose_string);
int getinfo_helper_networkstatus(control_connection_t *conn,
const char *question, char **answer);
void networkstatus_free_all(void);