aboutsummaryrefslogtreecommitdiff
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
parent136ed3307140ff82ade78f21765e43c87902d240 (diff)
downloadtor-e5f064c983eba136e3d448914995e79f1f55959d.tar
tor-e5f064c983eba136e3d448914995e79f1f55959d.tar.gz
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
-rw-r--r--ChangeLog2
-rw-r--r--doc/TODO9
-rw-r--r--doc/control-spec.txt12
-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
7 files changed, 126 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index e77914696..c7a853a05 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -20,6 +20,8 @@ Changes in version 0.1.2.3-alpha - 2006-10-??
Perry)
- Add a REMOTE_REASON field to CIRC events to tell the controller about
why a remote OR told us to close a circuit.
+ - There's now a GETINFO ns/... field so that controllers can ask Tor
+ about the current state of a router.
o Security bugfixes:
- When the user sends a NEWNYM signal, clear the client-side DNS
diff --git a/doc/TODO b/doc/TODO
index d38d4da01..aee472e54 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -30,7 +30,7 @@ N - Test guard unreachable logic; make sure that we actually attempt to
connect to guards that we think are unreachable from time to time.
Make sure that we don't freak out when the network is down.
N - Stop recommending exits as guards?
-N - Clients stop dumping old descriptors if the network-statuses
+ o Clients stop dumping old descriptors if the network-statuses
claim they're still valid.
P - Figure out why dll's compiled in mingw don't work right in WinXP.
P - Figure out why openssl 0.9.8d "make test" fails at sha256t test.
@@ -76,7 +76,12 @@ N - Simplify authority operation
being a client.
. Reduce resource load
d - Tolerate clock skew on bridge relays.
-N - A way to examine router flags from controller.
+ o A way to examine router flags from controller.
+ o Specify: GETINFO ns/id/x, ns/name/x, ns/all.
+ o Implement
+N - A way to alert controller when router flags change.
+ - Specify: SETEVENTS NS
+ - Implement
d - A way to adjust router flags from the controller
d - a way to pick entries based wholly on extend_info equivalent;
a way to export extend_info equivalent.
diff --git a/doc/control-spec.txt b/doc/control-spec.txt
index 235c19a7c..b6638958d 100644
--- a/doc/control-spec.txt
+++ b/doc/control-spec.txt
@@ -349,6 +349,18 @@ $Id$
"desc/id/<OR identity>" or "desc/name/<OR nickname>" -- the latest
server descriptor for a given OR, NUL-terminated.
+ "ns/id/<OR identity>" or "desc/name/<OR nickname>" -- the latest network
+ status info for a given OR. Network status info is as given in
+ dir-spec.txt, and reflects the current beliefs of this Tor about the
+ router in question. [First implemented in 0.1.2.3-alpha] Like
+ directory clients, controllers MUST tolerate unrecognized flags and
+ lines. The published date and descriptor digest are those believed to
+ be best by this Tor, not necessarily those for a descriptor that Tor
+ currently has.
+
+ "ns/all" -- Network status info for all ORs we have an opinion about,
+ joined by newlines. [First implemented in 0.1.2.3-alpha.]
+
"desc/all-recent" -- the latest server descriptor for every router that
Tor knows about.
diff --git a/src/or/control.c b/src/or/control.c
index 167b0e7ba..84d4ee4d5 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 355dcef52..d4acc0cd4 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 f44f8a2a9..86c626a77 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 25e54dfef..3ec7d7ffe 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)
{