diff --git a/ChangeLog b/ChangeLog index e779146968..c7a853a054 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 d38d4da015..aee472e547 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 235c19a7cb..b6638958d8 100644 --- a/doc/control-spec.txt +++ b/doc/control-spec.txt @@ -349,6 +349,18 @@ $Id$ "desc/id/" or "desc/name/" -- the latest server descriptor for a given OR, NUL-terminated. + "ns/id/" or "desc/name/" -- 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 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 question, 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 question is a string beginning with "ns/" in a format the + * control interface expects for a GETINFO question, set *answer 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) {