aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2004-10-27 00:48:51 +0000
committerNick Mathewson <nickm@torproject.org>2004-10-27 00:48:51 +0000
commitb90b2bb848cbbfbc7babda6498e014b687704c29 (patch)
tree7d94fe9a64882b242064d40e990d4d82a5874497
parent26f3cb865202160fe6b8ecfb20a0e41fea3a4a6a (diff)
downloadtor-b90b2bb848cbbfbc7babda6498e014b687704c29.tar
tor-b90b2bb848cbbfbc7babda6498e014b687704c29.tar.gz
Add and document router-status line using new unified liveness/verifiedness format; continue to generate running-routers; continue to parse running-routers when no router-status line is found
svn:r2592
-rw-r--r--doc/tor-spec.txt30
-rw-r--r--src/or/dirserv.c155
-rw-r--r--src/or/or.h9
-rw-r--r--src/or/routerlist.c183
-rw-r--r--src/or/routerparse.c56
5 files changed, 278 insertions, 155 deletions
diff --git a/doc/tor-spec.txt b/doc/tor-spec.txt
index 1718eab8e..19e94af84 100644
--- a/doc/tor-spec.txt
+++ b/doc/tor-spec.txt
@@ -706,7 +706,7 @@ line, they must appear in the "ports" lines.
A Directory begins with a "signed-directory" item, followed by one each of
the following, in any order: "recommended-software", "published",
-"running-routers". It may include any number of "opt" items. After these
+"router-status". It may include any number of "opt" items. After these
items, a directory includes any number of router descriptors, and a single
"directory-signature" item.
@@ -723,7 +723,7 @@ items, a directory includes any number of router descriptors, and a single
A list of which versions of which implementations are currently
believed to be secure and compatible with the network.
- "running-routers" comma-separated-list
+ "running-routers" space-separated-list
A description of which routers are currently believed to be up or
down. Every entry consists of an optional "!", followed by either an
@@ -733,8 +733,30 @@ items, a directory includes any number of router descriptors, and a single
If a router's nickname is given, exactly one router of that nickname
will appear in the directory, and that router is "approved" by the
directory server. If a hashed identity key is given, that OR is not
- "approved".
+ "approved". [XXXX The 'running-routers' line is only provided for
+ backward compatibility. New code should parse 'router-status'
+ instead.]
+ "router-status" space-separated-list
+
+ A description of which routers are currently believed to be up or
+ down, and which are verified or unverified. Contains one entry for
+ every router that the directory server knows. Each entry is of the
+ format:
+
+ !name=$digest [Verified router, currently not live.]
+ name=$digest [Verified router, currently live.]
+ !$digest [Unverified router, currently not live.]
+ or $digest [Unverified router, currently live.]
+
+ (where 'name' is the router's nickname and 'digest' is a hexadecimal
+ encoding of the hash of the routers' identity key).
+
+ When parsing this line, clients should only mark a router as
+ 'verified' if its nickname AND digest match the one provided.
+ [XXXX 'router-status' was added in 0.0.9pre5; older directory code
+ uses 'running-routers' instead.]
+
"directory-signature" nickname-of-dirserver NL Signature
Note: The router descriptor for the directory server MUST appear first.
@@ -763,7 +785,7 @@ entries.
(see 7.2 above)
- "running-routers" list
+ "router-status" list
(see 7.2 above)
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index f414350bd..74409fe52 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -20,7 +20,8 @@ extern or_options_t options; /**< command-line and config-file options */
static int the_directory_is_dirty = 1;
static int runningrouters_is_dirty = 1;
-static int list_running_servers(char **nicknames_out);
+static int list_server_status(char **running_routers_out,
+ char **router_status_out);
static void directory_remove_unrecognized(void);
static int dirserv_regenerate_directory(void);
@@ -456,71 +457,80 @@ dirserv_load_from_directory_string(const char *dir)
return 0;
}
-/** Set *<b>nicknames_out</b> to a comma-separated list of all the ORs that we
- * believe are currently running (because we have open connections to
- * them). Return 0 on success; -1 on error.
+/**
+ * Allocate and return a description of the status of the server <b>desc</b>,
+ * for use in a running-routers line (if <b>rr_format</b> is true), or in a
+ * router-status line (if <b>rr_format</b> is false. The server is listed
+ * as running iff <b>is_live</b> is true.
*/
-static int
-list_running_servers(char **nicknames_out)
+static char *
+list_single_server_status(descriptor_entry_t *desc, int is_live,
+ int rr_format)
{
- connection_t **connection_array;
- int n_conns;
- connection_t *conn;
+ char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
char *cp;
- int i;
- size_t length;
- smartlist_t *nicknames_up, *nicknames_down;
- char *name;
- const char *s;
-
- *nicknames_out = NULL;
- nicknames_up = smartlist_create();
- nicknames_down = smartlist_create();
- smartlist_add(nicknames_up, tor_strdup(options.Nickname));
-
- get_connection_array(&connection_array, &n_conns);
- for (i = 0; i<n_conns; ++i) {
- conn = connection_array[i];
- if (conn->type != CONN_TYPE_OR || !conn->nickname)
- continue; /* only list connections to ORs with certificates. */
- s = dirserv_get_nickname_by_digest(conn->identity_digest);
- if (s) {
- name = tor_strdup(s);
- } else {
- name = tor_malloc(HEX_DIGEST_LEN+2);
- *name = '$';
- base16_encode(name+1, HEX_DIGEST_LEN+1, conn->identity_digest, DIGEST_LEN);
- }
- if(conn->state == OR_CONN_STATE_OPEN)
- smartlist_add(nicknames_up, name);
- else
- smartlist_add(nicknames_down, name);
- }
- length = smartlist_len(nicknames_up) +
- 2*smartlist_len(nicknames_down) + 1;
- /* spaces + EOS + !'s + 1. */
- SMARTLIST_FOREACH(nicknames_up, char *, c, length += strlen(c));
- SMARTLIST_FOREACH(nicknames_down, char *, c, length += strlen(c));
- *nicknames_out = tor_malloc_zero(length);
- cp = *nicknames_out;
- for (i = 0; i<smartlist_len(nicknames_up); ++i) {
- if (i)
- strcat(cp, " ");
- strcat(cp, (char*)smartlist_get(nicknames_up,i)); /* can't overflow */
- while (*cp)
- ++cp;
- }
- for (i = 0; i<smartlist_len(nicknames_down); ++i) {
- strcat(cp, " !");
- strcat(cp, (char*)smartlist_get(nicknames_down,i)); /* can't overflow */
- while (*cp)
- ++cp;
- }
- SMARTLIST_FOREACH(nicknames_up, char *, victim, tor_free(victim));
- SMARTLIST_FOREACH(nicknames_down, char *, victim, tor_free(victim));
- smartlist_free(nicknames_up);
- smartlist_free(nicknames_down);
+ tor_assert(desc);
+ tor_assert(desc->router);
+
+ cp = buf;
+ if (!is_live) {
+ *cp++ = '!';
+ }
+ if (desc->verified) {
+ strcpy(cp, desc->nickname);
+ cp += strlen(cp);
+ if (!rr_format)
+ *cp++ = '=';
+ }
+ if (!desc->verified || !rr_format) {
+ *cp++ = '$';
+ base16_encode(cp, HEX_DIGEST_LEN+1, desc->router->identity_digest,
+ DIGEST_LEN);
+ }
+ return tor_strdup(buf);
+}
+
+/** Allocate the contents of a running-routers line and a router-status line,
+ * and store them in *<b>running_routers_out</b> and *<b>router_status_out</b>
+ * respectively. Return 0 on success, -1 on failure.
+ */
+static int
+list_server_status(char **running_routers_out, char **router_status_out)
+{
+ /* List of entries in running-routers style: An optional !, then either
+ * a nickname or a dollar-prefixed hexdigest. */
+ smartlist_t *rr_entries;
+ /* List of entries in a router-status style: An optional !, then an optional
+ * equals-suffixed nickname, then a dollar-prefixed hexdigest. */
+ smartlist_t *rs_entries;
+
+ tor_assert(running_routers_out || router_status_out);
+
+ rr_entries = smartlist_create();
+ rs_entries = smartlist_create();
+
+ SMARTLIST_FOREACH(descriptor_list, descriptor_entry_t *, d,
+ {
+ int is_live;
+ tor_assert(d->router);
+ connection_t *conn = connection_get_by_identity_digest(
+ d->router->identity_digest, CONN_TYPE_OR);
+ is_live = (conn && conn->state == OR_CONN_STATE_OPEN);
+ smartlist_add(rr_entries, list_single_server_status(d, is_live, 1));
+ smartlist_add(rs_entries, list_single_server_status(d, is_live, 0));
+ });
+
+ if (running_routers_out)
+ *running_routers_out = smartlist_join_strings(rr_entries, " ", 0);
+ if (router_status_out)
+ *router_status_out = smartlist_join_strings(rs_entries, " ", 0);
+
+ SMARTLIST_FOREACH(rr_entries, char *, cp, tor_free(cp));
+ SMARTLIST_FOREACH(rs_entries, char *, cp, tor_free(cp));
+ smartlist_free(rr_entries);
+ smartlist_free(rs_entries);
+
return 0;
}
@@ -557,7 +567,8 @@ int
dirserv_dump_directory_to_string(char *s, size_t maxlen,
crypto_pk_env_t *private_key)
{
- char *cp, *eos;
+ char *eos, *cp;
+ char *running_routers, *router_status;
char *identity_pkey; /* Identity key, DER64-encoded. */
char *recommended_versions;
char digest[20];
@@ -570,7 +581,7 @@ dirserv_dump_directory_to_string(char *s, size_t maxlen,
if (!descriptor_list)
descriptor_list = smartlist_create();
- if (list_running_servers(&cp))
+ if (list_server_status(&running_routers, &router_status))
return -1;
/* ASN.1-encode the public key. This is a temporary measure; once
@@ -612,10 +623,13 @@ dirserv_dump_directory_to_string(char *s, size_t maxlen,
"published %s\n"
"recommended-software %s\n"
"running-routers %s\n"
+ "opt router-status %s\n"
"opt dir-signing-key %s\n\n",
- published, recommended_versions, cp, identity_pkey);
+ published, recommended_versions, running_routers, router_status,
+ identity_pkey);
- tor_free(cp);
+ tor_free(running_routers);
+ tor_free(router_status);
tor_free(identity_pkey);
i = strlen(s);
cp = s+i;
@@ -788,6 +802,7 @@ static size_t runningrouters_len=0;
static int generate_runningrouters(crypto_pk_env_t *private_key)
{
char *s, *cp;
+ char *router_status;
char digest[DIGEST_LEN];
char signature[PK_BYTES];
int i;
@@ -798,7 +813,7 @@ static int generate_runningrouters(crypto_pk_env_t *private_key)
len = 1024+(MAX_HEX_NICKNAME_LEN+2)*smartlist_len(descriptor_list);
s = tor_malloc_zero(len);
- if (list_running_servers(&cp))
+ if (list_server_status(NULL, &router_status))
return -1;
/* ASN.1-encode the public key. This is a temporary measure; once
* everyone is running 0.0.9pre3 or later, we can shift to using a
@@ -822,12 +837,12 @@ static int generate_runningrouters(crypto_pk_env_t *private_key)
format_iso_time(published, published_on);
sprintf(s, "network-status\n"
"published %s\n"
- "running-routers %s\n"
+ "router-status %s\n"
"opt dir-signing-key %s\n"
"directory-signature %s\n"
"-----BEGIN SIGNATURE-----\n",
- published, cp, identity_pkey, options.Nickname);
- tor_free(cp);
+ published, router_status, identity_pkey, options.Nickname);
+ tor_free(router_status);
tor_free(identity_pkey);
if (router_get_runningrouters_hash(s,digest)) {
log_fn(LOG_WARN,"couldn't compute digest");
diff --git a/src/or/or.h b/src/or/or.h
index 4db838ac9..780cff32f 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -621,6 +621,7 @@ typedef struct running_routers_t {
time_t published_on; /**< When was the list marked as published? */
/** Which ORs are on the list? Entries may be prefixed with ! and $. */
smartlist_t *running_routers;
+ int is_running_routers_format; /**< Are we using the old entry format? */
} running_routers_t;
/** Holds accounting information for a single step in the layered encryption
@@ -1469,9 +1470,14 @@ int router_exit_policy_rejects_all(routerinfo_t *router);
void running_routers_free(running_routers_t *rr);
void routerlist_update_from_runningrouters(routerlist_t *list,
running_routers_t *rr);
+int routers_update_status_from_entry(smartlist_t *routers,
+ time_t list_time,
+ const char *s,
+ int rr_format);
int router_update_status_from_smartlist(routerinfo_t *r,
time_t list_time,
- smartlist_t *running_list);
+ smartlist_t *running_list,
+ int rr_format);
void add_trusted_dir_server(const char *addr, uint16_t port,const char *digest);
void clear_trusted_dir_servers(void);
@@ -1493,6 +1499,7 @@ int router_get_runningrouters_hash(const char *s, char *digest);
int router_parse_list_from_string(const char **s,
routerlist_t **dest,
smartlist_t *good_nickname_list,
+ int rr_format,
time_t published);
int router_parse_routerlist_from_directory(const char *s,
routerlist_t **dest,
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 0aca4028c..598a3412a 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -1018,8 +1018,8 @@ void running_routers_free(running_routers_t *rr)
void routerlist_update_from_runningrouters(routerlist_t *list,
running_routers_t *rr)
{
- int n_routers, i;
- routerinfo_t *router, *me = router_get_my_routerinfo();
+ routerinfo_t *me = router_get_my_routerinfo();
+ smartlist_t *all_routers;
if (!list)
return;
if (list->published_on >= rr->published_on)
@@ -1027,18 +1027,15 @@ void routerlist_update_from_runningrouters(routerlist_t *list,
if (list->running_routers_updated_on >= rr->published_on)
return;
- if(me) { /* learn if the dirservers think I'm verified */
- router_update_status_from_smartlist(me,
- rr->published_on,
- rr->running_routers);
- }
- n_routers = smartlist_len(list->routers);
- for (i=0; i<n_routers; ++i) {
- router = smartlist_get(list->routers, i);
- router_update_status_from_smartlist(router,
- rr->published_on,
- rr->running_routers);
- }
+ all_routers = smartlist_create();
+ if(me) /* learn if the dirservers think I'm verified */
+ smartlist_add(all_routers, me);
+
+ smartlist_add_all(all_routers,list->routers);
+ SMARTLIST_FOREACH(rr->running_routers, const char *, cp,
+ routers_update_status_from_entry(all_routers, rr->published_on,
+ cp, rr->is_running_routers_format));
+ smartlist_free(all_routers);
list->running_routers_updated_on = rr->published_on;
}
@@ -1046,6 +1043,14 @@ void routerlist_update_from_runningrouters(routerlist_t *list,
* based in its status in the list of strings stored in <b>running_list</b>.
* All entries in <b>running_list</b> follow one of these formats:
* <ol><li> <b>nickname</b> -- router is running and verified.
+ * (running-routers format)
+ * <li> !<b>nickname</b> -- router is not-running and verified.
+ * (running-routers format)
+ * <li> <b>nickname</b>=$<b>hexdigest</b> -- router is running and
+ * verified. (router-status format)
+ * (router-status format)
+ * <li> !<b>nickname</b>=$<b>hexdigest</b> -- router is running and
+ * verified. (router-status format)
* <li> !<b>nickname</b> -- router is not-running and verified.
* <li> $<b>hexdigest</b> -- router is running and unverified.
* <li> !$<b>hexdigest</b> -- router is not-running and unverified.
@@ -1053,57 +1058,115 @@ void routerlist_update_from_runningrouters(routerlist_t *list,
*
* Return 1 if we found router in running_list, else return 0.
*/
-int router_update_status_from_smartlist(routerinfo_t *router,
- time_t list_time,
- smartlist_t *running_list)
+int routers_update_status_from_entry(smartlist_t *routers,
+ time_t list_time,
+ const char *s,
+ int rr_format)
{
- int n_names, i, running, approved;
- const char *name;
-#if 1
- char *cp;
- size_t n;
- n = 0;
- for (i=0; i<smartlist_len(running_list); ++i) {
- name = smartlist_get(running_list, i);
- n += strlen(name) + 1;
+ int is_running = 1;
+ int is_verified = 0;
+ int hex_digest_set = 0;
+ char nickname[MAX_NICKNAME_LEN+1];
+ char hexdigest[HEX_DIGEST_LEN+1];
+ char digest[DIGEST_LEN];
+ const char *cp, *end;
+
+ /* First, parse the entry. */
+ cp = s;
+ if (*cp == '!') {
+ is_running = 0;
+ ++cp;
}
- cp = tor_malloc(n+2);
- cp[0] = '\0';
- for (i=0; i<smartlist_len(running_list); ++i) {
- name = smartlist_get(running_list, i);
- strlcat(cp, name, n);
- strlcat(cp, " ", n);
+
+ if (*cp != '$') {
+ /* It starts with a non-dollar character; that's a nickname. The nickname
+ * entry will either extend to a NUL (old running-routers format) or to an
+ * equals sign (new router-status format). */
+ is_verified = 1;
+ end = strchr(cp, '=');
+ if (!end)
+ end = strchr(cp,'\0');
+ tor_assert(end);
+ /* 'end' now points on character beyond the end of the nickname */
+ if (end == cp || end-cp > MAX_NICKNAME_LEN) {
+ log_fn(LOG_WARN, "Bad nickname length (%d) in router status entry (%s)",
+ end-cp, s);
+ return -1;
+ }
+ memcpy(nickname, cp, end-cp);
+ nickname[end-cp]='\0';
+ if (!is_legal_nickname(nickname)) {
+ log_fn(LOG_WARN, "Bad nickname (%s) in router status entry (%s)",
+ nickname, s);
+ return -1;
+ }
+ cp = end;
+ if (*cp == '=')
+ ++cp;
}
- log_fn(LOG_DEBUG, "Updating status of %s from list \"%s\"",
- router->nickname, cp);
- tor_free(cp);
-#endif
-
- running = approved = 0;
- n_names = smartlist_len(running_list);
- for (i=0; i<n_names; ++i) {
- name = smartlist_get(running_list, i);
- if (*name != '!') {
- if (router_nickname_matches(router, name)) {
- if (router->status_set_at < list_time) {
- router->status_set_at = list_time;
- router->is_running = 1;
- }
- router->is_verified = (name[0] != '$');
- return 1;
- }
- } else { /* *name == '!' */
- name++;
- if (router_nickname_matches(router, name)) {
- if (router->status_set_at < list_time) {
- router->status_set_at = list_time;
- router->is_running = 0;
- }
- router->is_verified = (name[0] != '$');
- return 1;
- }
+ /* 'end' now points to the start of a hex digest, or EOS. */
+
+ /* Parse the hexdigest portion of the status. */
+ if (*cp == '$') {
+ hex_digest_set = 1;
+ ++cp;
+ if (strlen(cp) != HEX_DIGEST_LEN) {
+ log_fn(LOG_WARN, "Bad length (%d) on digest in router status entry (%s)",
+ strlen(cp), s);
+ return -1;
+ }
+ strcpy(hexdigest, cp);
+ if (base16_decode(digest, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0) {
+ log_fn(LOG_WARN, "Invalid digest in router status entry (%s)", s);
+ return -1;
}
}
+
+ /* Make sure that the entry was in the right format. */
+ if (rr_format) {
+ if (is_verified == hex_digest_set) {
+ log_fn(LOG_WARN, "Invalid syntax for running-routers member (%s)", s);
+ return -1;
+ }
+ } else {
+ if (!hex_digest_set) {
+ log_fn(LOG_WARN, "Invalid syntax for router-status member (%s)", s);
+ return -1;
+ }
+ }
+
+ /* Okay, we're done parsing. For all routers that match, update their status.
+ */
+ SMARTLIST_FOREACH(routers, routerinfo_t *, r,
+ {
+ int nickname_matches = is_verified && !strcasecmp(r->nickname, nickname);
+ int digest_matches = !memcmp(digest, r->identity_digest, DIGEST_LEN);
+ if (nickname_matches && (digest_matches||rr_format))
+ r->is_verified = 1;
+ else if (digest_matches)
+ r->is_verified = 0;
+ if (digest_matches || (nickname_matches&&rr_format))
+ if (r->status_set_at < list_time) {
+ r->is_running = is_running;
+ r->status_set_at = time(NULL);
+ }
+ });
+
+ return 0;
+}
+
+int router_update_status_from_smartlist(routerinfo_t *router,
+ time_t list_time,
+ smartlist_t *running_list,
+ int rr_format)
+{
+ smartlist_t *rl;
+ rl = smartlist_create();
+ smartlist_add(rl,router);
+ SMARTLIST_FOREACH(running_list, const char *, cp,
+ routers_update_status_from_entry(rl,list_time,cp,rr_format));
+
+ smartlist_free(rl);
return 0;
}
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 476c8af98..6d3ad6650 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -32,6 +32,7 @@ typedef enum {
K_ROUTER_SIGNATURE,
K_PUBLISHED,
K_RUNNING_ROUTERS,
+ K_ROUTER_STATUS,
K_PLATFORM,
K_OPT,
K_BANDWIDTH,
@@ -106,6 +107,7 @@ static struct {
{ "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY,RTR_ONLY },
{ "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ,RTR_ONLY },
{ "running-routers", K_RUNNING_ROUTERS, ARGS, NO_OBJ, DIR_ONLY },
+ { "router-status", K_ROUTER_STATUS, ARGS, NO_OBJ, DIR_ONLY },
{ "ports", K_PORTS, ARGS, NO_OBJ, RTR_ONLY },
{ "bandwidth", K_BANDWIDTH, ARGS, NO_OBJ, RTR_ONLY },
{ "platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ, RTR_ONLY },
@@ -393,9 +395,13 @@ router_parse_routerlist_from_directory(const char *str,
}
versions = tok->n_args ? tor_strdup(tok->args[0]) : tor_strdup("");
- if (!(tok = find_first_by_keyword(tokens, K_RUNNING_ROUTERS))) {
- log_fn(LOG_WARN, "Missing running-routers line from directory.");
- goto err;
+ /* Prefer router-status, then running-routers. */
+ if (!(tok = find_first_by_keyword(tokens, K_ROUTER_STATUS))) {
+ if (!(tok = find_first_by_keyword(tokens, K_RUNNING_ROUTERS))) {
+ log_fn(LOG_WARN,
+ "Missing running-routers/router-status line from directory.");
+ goto err;
+ }
}
good_nickname_list = smartlist_create();
@@ -408,25 +414,21 @@ router_parse_routerlist_from_directory(const char *str,
* router. */
str = end;
if (router_parse_list_from_string(&str, &new_dir,
- good_nickname_list, published_on)) {
+ good_nickname_list,
+ tok->tp==K_RUNNING_ROUTERS,
+ published_on)) {
log_fn(LOG_WARN, "Error reading routers from directory");
goto err;
}
- new_dir->software_versions = versions; versions = NULL;
- new_dir->published_on = published_on;
-
- SMARTLIST_FOREACH(tokens, directory_token_t *, tok, token_free(tok));
- smartlist_free(tokens);
- tokens = NULL;
-
/* Determine if my routerinfo is considered verified. */
{
static int have_warned_about_unverified_status = 0;
routerinfo_t *me = router_get_my_routerinfo();
if(me) {
if(router_update_status_from_smartlist(me, published_on,
- good_nickname_list)==1 &&
+ good_nickname_list,
+ tok->tp==K_RUNNING_ROUTERS)==1 &&
me->is_verified == 0 && !have_warned_about_unverified_status) {
log_fn(LOG_WARN,"Dirserver %s lists your server as unverified. Please consider sending your identity fingerprint to the tor-ops.", dirnickname);
have_warned_about_unverified_status = 1;
@@ -434,6 +436,13 @@ router_parse_routerlist_from_directory(const char *str,
}
}
+ new_dir->software_versions = versions; versions = NULL;
+ new_dir->published_on = published_on;
+
+ SMARTLIST_FOREACH(tokens, directory_token_t *, tok, token_free(tok));
+ smartlist_free(tokens);
+ tokens = NULL;
+
if (*dest)
routerlist_free(*dest);
*dest = new_dir;
@@ -497,14 +506,18 @@ router_parse_runningrouters(const char *str)
goto err;
}
- if (!(tok = find_first_by_keyword(tokens, K_RUNNING_ROUTERS))) {
- log_fn(LOG_WARN, "Missing running-routers line from directory.");
- goto err;
+ if (!(tok = find_first_by_keyword(tokens, K_ROUTER_STATUS))) {
+ if (!(tok = find_first_by_keyword(tokens, K_RUNNING_ROUTERS))) {
+ log_fn(LOG_WARN,
+ "Missing running-routers/router-status line from directory.");
+ goto err;
+ }
}
new_list = tor_malloc_zero(sizeof(running_routers_t));
new_list->published_on = published_on;
new_list->running_routers = smartlist_create();
+ new_list->is_running_routers_format = (tok->tp == K_RUNNING_ROUTERS);
for (i=0;i<tok->n_args;++i) {
smartlist_add(new_list->running_routers, tok->args[i]);
}
@@ -661,7 +674,7 @@ static int check_directory_signature(const char *digest,
int
router_parse_list_from_string(const char **s, routerlist_t **dest,
smartlist_t *good_nickname_list,
- time_t published_on)
+ int rr_format, time_t published_on)
{
routerinfo_t *router;
smartlist_t *routers;
@@ -692,10 +705,7 @@ router_parse_list_from_string(const char **s, routerlist_t **dest,
continue;
}
- if (good_nickname_list) {
- router_update_status_from_smartlist(router, published_on,
- good_nickname_list);
- } else {
+ if (!good_nickname_list) {
router->is_running = 1; /* start out assuming all dirservers are up */
router->is_verified = 1;
router->status_set_at = time(NULL);
@@ -704,6 +714,12 @@ router_parse_list_from_string(const char **s, routerlist_t **dest,
log_fn(LOG_DEBUG,"just added router #%d.",smartlist_len(routers));
}
+ if (good_nickname_list) {
+ SMARTLIST_FOREACH(good_nickname_list, const char *, cp,
+ routers_update_status_from_entry(routers, published_on,
+ cp, rr_format));
+ }
+
if (*dest)
routerlist_free(*dest);
*dest = tor_malloc_zero(sizeof(routerlist_t));