diff --git a/doc/TODO b/doc/TODO
index 9e7aa2a314..6372d50529 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -65,7 +65,7 @@ NICK - Possible to get autoconf to easily install things into ~/.tor?
o nickname defaults to first piece of hostname
o running-routers list refers to nickname if verified, else
hash-base64'ed.
- - Mark routers as verified or unverified based on whether
+ o Mark routers as verified or unverified based on whether
running-routers list includes nickname or id hash.
o put OR uptime in descriptor
o name the secret-key directory something to discourage people
@@ -95,6 +95,7 @@ NICK - Reputation info needs to give better weight to recent events than
- he can connect to you
- he has successfully extended to you
- he has sufficient mean-time-between-failures
+ - Don't accept ORs with nicknames same as verified ORs' nicknames.
- add new "Middleman 1" config variable?
o if torrc not found, exitpolicy reject *:*
NICK - change if(options.ORPort) to what we really mean.
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 3da343285f..98eeef55a9 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -469,8 +469,9 @@ list_running_servers(char **nicknames_out)
if (router_nickname_is_approved(conn->nickname, conn->identity_digest)) {
name = tor_strdup(conn->nickname);
} else {
- name = tor_malloc(HEX_DIGEST_LEN+1);
- base16_encode(name, HEX_DIGEST_LEN, conn->identity_digest, DIGEST_LEN);
+ name = tor_malloc(HEX_DIGEST_LEN+2);
+ *name = '$';
+ base16_encode(name+1, HEX_DIGEST_LEN, conn->identity_digest, DIGEST_LEN);
}
if(conn->state == OR_CONN_STATE_OPEN)
diff --git a/src/or/or.h b/src/or/or.h
index 8fb3b45dd1..d7d0fab49a 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -584,6 +584,8 @@ typedef struct {
* to exit? */
/* local info */
int is_running; /**< As far as we know, is this OR currently running? */
+ time_t status_set_at; /**< When did we last update is_running? */
+ int is_verified; /**< Has a trusted dirserver validated this OR? */
int is_trusted_dir; /**< Do we trust this OR as a directory server? */
} routerinfo_t;
@@ -1381,6 +1383,9 @@ 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);
+void router_update_status_from_smartlist(routerinfo_t *r,
+ time_t list_time,
+ smartlist_t *running_list);
/********************************* routerparse.c ************************/
@@ -1397,9 +1402,8 @@ int router_get_router_hash(const char *s, char *digest);
int router_get_dir_hash(const char *s, char *digest);
int router_get_runningrouters_hash(const char *s, char *digest);
int router_parse_list_from_string(const char **s,
- routerlist_t **dest,
- int n_good_nicknames,
- const char **good_nickname_lst);
+ routerlist_t **dest,
+ smartlist_t *good_nickname_list);
int router_parse_routerlist_from_directory(const char *s,
routerlist_t **dest,
crypto_pk_env_t *pkey);
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index b1455879da..3d648ae8a3 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -93,6 +93,7 @@ static routerinfo_t *router_pick_directory_server_impl(void) {
if(router->is_trusted_dir) {
tor_assert(router->dir_port > 0);
router->is_running = 1;
+ router->status_set_at = time(NULL);
smartlist_add(sl, router);
}
}
@@ -391,6 +392,7 @@ void router_mark_as_down(const char *digest) {
return;
log_fn(LOG_DEBUG,"Marking %s as down.",router->nickname);
router->is_running = 0;
+ router->status_set_at = time(NULL);
}
/** Add router to the routerlist, if we don't already have it. Replace
@@ -523,7 +525,7 @@ int router_load_routerlist_from_string(const char *s, int trusted)
{
routerlist_t *new_list=NULL;
- if (router_parse_list_from_string(&s, &new_list, -1, NULL)) {
+ if (router_parse_list_from_string(&s, &new_list, NULL)) {
log(LOG_WARN, "Error parsing router file");
return -1;
}
@@ -743,9 +745,8 @@ void running_routers_free(running_routers_t *rr)
void routerlist_update_from_runningrouters(routerlist_t *list,
running_routers_t *rr)
{
- int n_routers, n_names, i, j, running;
+ int n_routers, i;
routerinfo_t *router;
- const char *name;
if (!list)
return;
if (list->published_on >= rr->published_on)
@@ -754,26 +755,55 @@ void routerlist_update_from_runningrouters(routerlist_t *list,
return;
n_routers = smartlist_len(list->routers);
- n_names = smartlist_len(rr->running_routers);
for (i=0; irouters, i);
- for (j=0; jrunning_routers, j);
- if (*name != '!') {
- if (router_nickname_matches(router, name)) {
+ router_update_status_from_smartlist(router,
+ rr->published_on,
+ rr->running_routers);
+ }
+ list->running_routers_updated_on = rr->published_on;
+}
+
+/** Update the is_running and is_verified fields of the router router,
+ * based in its status in the list of strings stored in running_list.
+ * All entries in running_list follow one of these formats:
+ * - nickname -- router is running and verified.
+ *
- !nickname -- router is not-running and verified.
+ *
- $hexdigest -- router is running and unverified.
+ *
- !$hexdigest -- router is not-running and unverified.
+ *
+ */
+void router_update_status_from_smartlist(routerinfo_t *router,
+ time_t list_time,
+ smartlist_t *running_list)
+{
+ int n_names, i, running, approved;
+ const char *name;
+ running = approved = 0;
+
+ n_names = smartlist_len(running_list);
+ for (i=0; istatus_set_at < list_time) {
+ router->status_set_at = list_time;
router->is_running = 1;
- break;
}
- } else { /* *name == '!' */
- if (router_nickname_matches(router, name)) {
+ router->is_verified = (name[1] != '$');
+ return;
+ }
+ } else { /* *name == '!' */
+ if (router_nickname_matches(router, name)) {
+ if (router->status_set_at < list_time) {
+ router->status_set_at = list_time;
router->is_running = 0;
- break;
}
+ router->is_verified = (name[1] != '$');
+ return;
}
}
}
- list->running_routers_updated_on = rr->published_on;
}
/*
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 368de3c025..137db14b42 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -291,8 +291,7 @@ router_parse_routerlist_from_directory(const char *str,
char digest[DIGEST_LEN];
routerlist_t *new_dir = NULL;
char *versions = NULL;
- int n_good_nicknames = 0;
- char *good_nickname_lst[1024]; /* XXXX008 correct this limit. */
+ smartlist_t *good_nickname_list = NULL;
time_t published_on;
int i, r;
const char *end;
@@ -355,22 +354,21 @@ router_parse_routerlist_from_directory(const char *str,
goto err;
}
- n_good_nicknames = tok->n_args;
- memcpy(good_nickname_lst, tok->args, n_good_nicknames*sizeof(char *));
+ good_nickname_list = smartlist_create();
+ for (i=0; in_args; ++i) {
+ smartlist_add(good_nickname_list, tok->args[i]);
+ }
tok->n_args = 0; /* Don't free the strings in good_nickname_lst yet. */
/* Read the router list from s, advancing s up past the end of the last
* router. */
str = end;
if (router_parse_list_from_string(&str, &new_dir,
- n_good_nicknames,
- (const char**)good_nickname_lst)) {
+ good_nickname_list)) {
log_fn(LOG_WARN, "Error reading routers from directory");
goto err;
}
- for (i = 0; i < n_good_nicknames; ++i) {
- tor_free(good_nickname_lst[i]); /* now free them */
- }
+
new_dir->software_versions = versions; versions = NULL;
new_dir->published_on = published_on;
@@ -402,14 +400,15 @@ router_parse_routerlist_from_directory(const char *str,
if (new_dir)
routerlist_free(new_dir);
tor_free(versions);
- for (i = 0; i < n_good_nicknames; ++i) {
- tor_free(good_nickname_lst[i]);
- }
done:
if (tokens) {
SMARTLIST_FOREACH(tokens, directory_token_t *, tok, token_free(tok));
smartlist_free(tokens);
}
+ if (good_nickname_list) {
+ SMARTLIST_FOREACH(good_nickname_list, char *, n, tor_free(n));
+ smartlist_free(good_nickname_list);
+ }
return r;
}
@@ -531,22 +530,21 @@ static int check_directory_signature(const char *digest,
}
-/** Given a string *s containing a concatenated
- * sequence of router descriptors, parses them and stores the result
- * in *dest. If good_nickname_lst is provided, then routers whose
- * nicknames are not listed are marked as nonrunning. Advances *s to
- * a point immediately following the last router entry. Returns 0 on
+/** Given a string *s containing a concatenated sequence of router
+ * descriptors, parses them and stores the result in *dest. If
+ * good_nickname_list is provided, then routers are mared as
+ * running/nonrunning and verified/unverified based on their status in the
+ * list. Otherwise, all routers are marked running and verified. Advances
+ * *s to a point immediately following the last router entry. Returns 0 on
* success and -1 on failure.
*/
int
router_parse_list_from_string(const char **s, routerlist_t **dest,
- int n_good_nicknames,
- const char **good_nickname_list)
+ smartlist_t *good_nickname_list)
{
routerinfo_t *router;
smartlist_t *routers;
int rarray_len = 0;
- int i;
const char *end;
tor_assert(s && *s);
@@ -573,16 +571,13 @@ router_parse_list_from_string(const char **s, routerlist_t **dest,
continue;
}
- if (n_good_nicknames>=0) {
- router->is_running = 0;
- for (i = 0; i < n_good_nicknames; ++i) {
- if (router_nickname_matches(router, good_nickname_list[i])) {
- router->is_running = 1;
- break;
- }
- }
+ if (good_nickname_list) {
+ router_update_status_from_smartlist(router, time(NULL),
+ good_nickname_list);
} else {
router->is_running = 1; /* start out assuming all dirservers are up */
+ router->is_verified = 1;
+ router->status_set_at = time(NULL);
}
smartlist_add(routers, router);
log_fn(LOG_DEBUG,"just added router #%d.",rarray_len);