aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2006-10-20 14:58:29 +0000
committerNick Mathewson <nickm@torproject.org>2006-10-20 14:58:29 +0000
commite5f064c983eba136e3d448914995e79f1f55959d (patch)
tree2efab188a013149c6f8977539c3c63daa4c1e761 /src
parent136ed3307140ff82ade78f21765e43c87902d240 (diff)
downloadtor-e5f064c983eba136e3d448914995e79f1f55959d.tar.gz
tor-e5f064c983eba136e3d448914995e79f1f55959d.zip
r9290@31-35-219: nickm | 2006-10-20 10:32:33 -0400
Add a GETINFO target so controllers can ask Tor for the current state of a router. (Results given in networkstatus format.) svn:r8772
Diffstat (limited to 'src')
-rw-r--r--src/or/control.c3
-rw-r--r--src/or/dirserv.c4
-rw-r--r--src/or/or.h2
-rw-r--r--src/or/routerlist.c98
4 files changed, 105 insertions, 2 deletions
diff --git a/src/or/control.c b/src/or/control.c
index 167b0e7ba5..84d4ee4d56 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -1437,6 +1437,7 @@ list_getinfo_options(void)
"orconn-status Status of each current OR connection.\n"
"stream-status Status of each current application stream.\n"
"version The current version of Tor.\n");
+ // XXXX Uptodate!
}
/** Lookup the 'getinfo' entry <b>question</b>, and return
@@ -1493,6 +1494,8 @@ handle_getinfo_helper(control_connection_t *control_conn,
*answer = smartlist_join_strings(sl, "", 0, NULL);
SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
smartlist_free(sl);
+ } else if (!strcmpstart(question, "ns/")) {
+ return networkstatus_getinfo_helper(question, answer);
} else if (!strcmpstart(question, "unregistered-servers-")) {
*answer = dirserver_getinfo_unregistered(question +
strlen("unregistered-servers-"));
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 355dcef52b..d4acc0cd4a 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -1334,8 +1334,8 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
static cached_dir_t *
generate_v2_networkstatus(void)
{
-#define LONGEST_STATUS_FLAG_NAME_LEN 7
-#define N_STATUS_FLAGS 6
+#define LONGEST_STATUS_FLAG_NAME_LEN 9
+#define N_STATUS_FLAGS 9
#define RS_ENTRY_LEN \
( /* first line */ \
MAX_NICKNAME_LEN+BASE64_DIGEST_LEN*2+ISO_TIME_LEN+INET_NTOA_BUF_LEN+ \
diff --git a/src/or/or.h b/src/or/or.h
index f44f8a2a90..86c626a779 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2668,6 +2668,8 @@ void router_reset_status_download_failures(void);
int router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2);
const char *esc_router_info(routerinfo_t *router);
+int networkstatus_getinfo_helper(const char *question, char **answer);
+
/********************************* routerparse.c ************************/
#define MAX_STATUS_TAG_LEN 32
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 25e54dfef7..3ec7d7ffeb 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -4109,6 +4109,104 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
return 1;
}
+/** Generate networkstatus lines for a single routerstatus_t object, and
+ * return the result in a newly allocated string. Used only by controller
+ * interface (for now.) */
+/* XXXX This should eventually merge into generate_v2_networkstatus() */
+static char *
+networkstatus_getinfo_helper_single(routerstatus_t *rs)
+{
+ char buf[192];
+ int r;
+ struct in_addr in;
+
+ int f_authority;
+ char published[ISO_TIME_LEN+1];
+ char ipaddr[INET_NTOA_BUF_LEN];
+ char identity64[BASE64_DIGEST_LEN+1];
+ char digest64[BASE64_DIGEST_LEN+1];
+
+ format_iso_time(published, rs->published_on);
+ digest_to_base64(identity64, rs->identity_digest);
+ digest_to_base64(digest64, rs->descriptor_digest);
+ in.s_addr = htonl(rs->addr);
+ tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
+
+ f_authority = router_digest_is_trusted_dir(rs->identity_digest);
+
+ r = tor_snprintf(buf, sizeof(buf),
+ "r %s %s %s %s %s %d %d\n"
+ "s%s%s%s%s%s%s%s%s%s%s\n",
+ rs->nickname,
+ identity64,
+ digest64,
+ published,
+ ipaddr,
+ (int)rs->or_port,
+ (int)rs->dir_port,
+
+ f_authority?" Authority":"",
+ rs->is_bad_exit?" BadExit":"",
+ rs->is_exit?" Exit":"",
+ rs->is_fast?" Fast":"",
+ rs->is_possible_guard?" Guard":"",
+ rs->is_named?" Named":"",
+ rs->is_stable?" Stable":"",
+ rs->is_running?" Running":"",
+ rs->is_valid?" Valid":"",
+ rs->is_v2_dir?" V2Dir":"");
+ if (r<0)
+ log_warn(LD_BUG, "Not enough space in buffer.");
+
+ return tor_strdup(buf);
+}
+
+/** 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
+ * ORs. Return 0 on success, -1 on failure. */
+int
+networkstatus_getinfo_helper(const char *question, char **answer)
+{
+ local_routerstatus_t *status;
+
+ if (!routerstatus_list) {
+ *answer = tor_strdup("");
+ return 0;
+ }
+
+ if (!strcmpstart(question, "ns/all")) {
+ smartlist_t *statuses = smartlist_create();
+ SMARTLIST_FOREACH(routerstatus_list, local_routerstatus_t *, lrs,
+ {
+ routerstatus_t *rs = &(lrs->status);
+ 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 0;
+ } else if (!strcmpstart(question, "ns/id/")) {
+ char d[DIGEST_LEN];
+
+ if (base16_decode(d, DIGEST_LEN, question+6, strlen(question+6)))
+ return -1;
+ status = router_get_combined_status_by_digest(d);
+ } else if (!strcmpstart(question, "ns/name/")) {
+ status = router_get_combined_status_by_nickname(question+8, 0);
+ } else {
+ return -1;
+ }
+
+ if (status) {
+ *answer = networkstatus_getinfo_helper_single(&status->status);
+ } else {
+ *answer = tor_strdup("");
+ }
+ return 0;
+}
+
+/*DOCDOC*/
static void
routerlist_assert_ok(routerlist_t *rl)
{