hex) is <digest>. Only available if we're downloading extra-info
documents.
- "ns/id/<OR identity>" or "ns/name/<OR nickname>" -- the latest network
- status info for a given OR. Network status info is as given in
+ "ns/id/<OR identity>" or "ns/name/<OR nickname>" -- the latest router
+ status info (v2 directory style) for a given OR. Router status
+ info is as given in
dir-spec.txt, and reflects the current beliefs of this Tor about the
router in question. Like directory clients, controllers MUST
tolerate unrecognized flags and lines. The published date and
not necessarily those for a descriptor that Tor currently has.
[First implemented in 0.1.2.3-alpha.]
- "ns/all" -- Network status info (v2 directory style) for all ORs we
+ "ns/all" -- Router status info (v2 directory style) for all ORs we
have an opinion about, joined by newlines. [First implemented
in 0.1.2.3-alpha.]
+ "ns/purpose/<purpose>" -- Router status info (v2 directory style)
+ for all ORs of this purpose. Mostly designed for /ns/purpose/bridge
+ queries. [First implemented in 0.2.0.13-alpha.]
+
"desc/all-recent" -- the latest server descriptor for every router that
Tor knows about.
3 for details. (If VERBOSE_NAMES is enabled, the output will
not conform to dir-spec-v1.txt; instead, the result will be a
space-separated list of LongName, each preceded by a "!" if it is
- believed to be not running.)
+ believed to be not running.) This option is deprecated; use
+ "ns/all" instead.
"address-mappings/all"
"address-mappings/config"
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/")) {
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);
/** 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;
* If for_controller is >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. */
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);
* 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,
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
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;
}
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);
#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,
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);