Remove descriptor_list and use routerlist instead. Make directories manage routerlist a little better.

svn:r4854
This commit is contained in:
Nick Mathewson 2005-08-26 20:59:04 +00:00
parent a47765a16d
commit 0e649ac60a
4 changed files with 174 additions and 212 deletions

View File

@ -235,22 +235,14 @@ dirserv_free_fingerprint_list()
* Descriptor list * Descriptor list
*/ */
/** List of routerinfo_t for all server descriptors that this dirserv static smartlist_t *
* is holding. get_descriptor_list(void)
* XXXX This should eventually get coalesced into routerlist.c
*/
static smartlist_t *descriptor_list = NULL;
/** Release all storage that the dirserv is holding for server
* descriptors. */
void
dirserv_free_descriptors()
{ {
if (!descriptor_list) routerlist_t *routerlist;
return; router_get_routerlist(&routerlist);
SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri, if (!routerlist)
routerinfo_free(ri)); return NULL;
smartlist_clear(descriptor_list); return routerlist->routers;
} }
/** Return -1 if <b>ri</b> has a private or otherwise bad address, /** Return -1 if <b>ri</b> has a private or otherwise bad address,
@ -274,6 +266,64 @@ dirserv_router_has_valid_address(routerinfo_t *ri)
return 0; return 0;
} }
int
dirserv_wants_to_reject_router(routerinfo_t *ri, int *verified,
const char **msg)
{
/* Okay. Now check whether the fingerprint is recognized. */
int r = dirserv_router_fingerprint_is_known(ri);
time_t now;
if (r==-1) {
log_fn(LOG_WARN, "Known nickname '%s', wrong fingerprint. Not adding (ContactInfo '%s', platform '%s').",
ri->nickname, ri->contact_info ? ri->contact_info : "",
ri->platform ? ri->platform : "");
*msg = "Rejected: There is already a verified server with this nickname and a different fingerprint.";
return -1;
} else if (r==0) {
char fp[FINGERPRINT_LEN+1];
log_fn(LOG_INFO, "Unknown nickname '%s' (%s:%d). Will try to add.",
ri->nickname, ri->address, ri->or_port);
if (crypto_pk_get_fingerprint(ri->identity_pkey, fp, 1) < 0) {
log_fn(LOG_WARN, "Error computing fingerprint for '%s'", ri->nickname);
} else {
log_fn(LOG_INFO, "Fingerprint line: %s %s", ri->nickname, fp);
}
*verified = 0;
} else {
*verified = 1;
}
/* Is there too much clock skew? */
now = time(NULL);
if (ri->published_on > now+ROUTER_ALLOW_SKEW) {
log_fn(LOG_NOTICE, "Publication time for nickname '%s' is too far (%d minutes) in the future; possible clock skew. Not adding (ContactInfo '%s', platform '%s').",
ri->nickname, (int)((ri->published_on-now)/60),
ri->contact_info ? ri->contact_info : "",
ri->platform ? ri->platform : "");
*msg = "Rejected: Your clock is set too far in the future, or your timezone is not correct.";
return -1;
}
if (ri->published_on < now-ROUTER_MAX_AGE) {
log_fn(LOG_NOTICE, "Publication time for router with nickname '%s' is too far (%d minutes) in the past. Not adding (ContactInfo '%s', platform '%s').",
ri->nickname, (int)((now-ri->published_on)/60),
ri->contact_info ? ri->contact_info : "",
ri->platform ? ri->platform : "");
*msg = "Rejected: Server is expired, or your clock is too far in the past, or your timezone is not correct.";
return -1;
}
if (dirserv_router_has_valid_address(ri) < 0) {
log_fn(LOG_NOTICE, "Router with nickname '%s' has invalid address '%s'. Not adding (ContactInfo '%s', platform '%s').",
ri->nickname, ri->address,
ri->contact_info ? ri->contact_info : "",
ri->platform ? ri->platform : "");
*msg = "Rejected: Address is not an IP, or IP is a private address.";
return -1;
}
return 0;
}
/** Parse the server descriptor at *desc and maybe insert it into the /** Parse the server descriptor at *desc and maybe insert it into the
* list of server descriptors, and (if the descriptor is well-formed) * list of server descriptors, and (if the descriptor is well-formed)
* advance *desc immediately past the descriptor's end. Set msg to a * advance *desc immediately past the descriptor's end. Set msg to a
@ -288,17 +338,12 @@ dirserv_router_has_valid_address(routerinfo_t *ri)
int int
dirserv_add_descriptor(const char **desc, const char **msg) dirserv_add_descriptor(const char **desc, const char **msg)
{ {
routerinfo_t *ri = NULL, *ri_old=NULL; routerinfo_t *ri = NULL;
int i, r, found=-1;
char *start, *end; char *start, *end;
char *desc_tmp = NULL; char *desc_tmp = NULL;
size_t desc_len; size_t desc_len;
time_t now;
int verified=1; /* whether we knew its fingerprint already */
tor_assert(msg); tor_assert(msg);
*msg = NULL; *msg = NULL;
if (!descriptor_list)
descriptor_list = smartlist_create();
start = strstr(*desc, "router "); start = strstr(*desc, "router ");
if (!start) { if (!start) {
@ -323,104 +368,11 @@ dirserv_add_descriptor(const char **desc, const char **msg)
*msg = "Rejected: Couldn't parse server descriptor."; *msg = "Rejected: Couldn't parse server descriptor.";
return -1; return -1;
} }
/* Okay. Now check whether the fingerprint is recognized. */ if (router_add_to_routerlist(ri, msg)) {
r = dirserv_router_fingerprint_is_known(ri);
if (r==-1) {
log_fn(LOG_WARN, "Known nickname '%s', wrong fingerprint. Not adding (ContactInfo '%s', platform '%s').",
ri->nickname, ri->contact_info ? ri->contact_info : "",
ri->platform ? ri->platform : "");
*msg = "Rejected: There is already a verified server with this nickname and a different fingerprint.";
routerinfo_free(ri);
*desc = end;
return -1; return -1;
} else if (r==0) {
char fp[FINGERPRINT_LEN+1];
log_fn(LOG_INFO, "Unknown nickname '%s' (%s:%d). Will try to add.",
ri->nickname, ri->address, ri->or_port);
if (crypto_pk_get_fingerprint(ri->identity_pkey, fp, 1) < 0) {
log_fn(LOG_WARN, "Error computing fingerprint for '%s'", ri->nickname);
} else { } else {
log_fn(LOG_INFO, "Fingerprint line: %s %s", ri->nickname, fp); return ri->is_verified ? 1 : 0;
} }
verified = 0;
}
/* Is there too much clock skew? */
now = time(NULL);
if (ri->published_on > now+ROUTER_ALLOW_SKEW) {
log_fn(LOG_NOTICE, "Publication time for nickname '%s' is too far (%d minutes) in the future; possible clock skew. Not adding (ContactInfo '%s', platform '%s').",
ri->nickname, (int)((ri->published_on-now)/60),
ri->contact_info ? ri->contact_info : "",
ri->platform ? ri->platform : "");
*msg = "Rejected: Your clock is set too far in the future, or your timezone is not correct.";
routerinfo_free(ri);
*desc = end;
return -1;
}
if (ri->published_on < now-ROUTER_MAX_AGE) {
log_fn(LOG_NOTICE, "Publication time for router with nickname '%s' is too far (%d minutes) in the past. Not adding (ContactInfo '%s', platform '%s').",
ri->nickname, (int)((now-ri->published_on)/60),
ri->contact_info ? ri->contact_info : "",
ri->platform ? ri->platform : "");
*msg = "Rejected: Server is expired, or your clock is too far in the past, or your timezone is not correct.";
routerinfo_free(ri);
*desc = end;
return -1;
}
if (dirserv_router_has_valid_address(ri) < 0) {
log_fn(LOG_NOTICE, "Router with nickname '%s' has invalid address '%s'. Not adding (ContactInfo '%s', platform '%s').",
ri->nickname, ri->address,
ri->contact_info ? ri->contact_info : "",
ri->platform ? ri->platform : "");
*msg = "Rejected: Address is not an IP, or IP is a private address.";
routerinfo_free(ri);
*desc = end;
return -1;
}
/* Do we already have an entry for this router? */
for (i = 0; i < smartlist_len(descriptor_list); ++i) {
ri_old = smartlist_get(descriptor_list, i);
if (!memcmp(ri->identity_digest, ri_old->identity_digest, DIGEST_LEN)) {
found = i;
break;
}
}
if (found >= 0) {
char hex_digest[HEX_DIGEST_LEN+1];
base16_encode(hex_digest, HEX_DIGEST_LEN+1, ri->identity_digest,DIGEST_LEN);
/* if so, decide whether to update it. */
if (ri_old->published_on >= ri->published_on) {
/* We already have a newer or equal-time descriptor */
log_fn(LOG_INFO,"We already have a new enough desc for server %s (nickname '%s'). Not adding.",hex_digest,ri->nickname);
*msg = "We already have a newer descriptor.";
/* This isn't really an error; return success. */
routerinfo_free(ri);
*desc = end;
return verified;
}
/* We don't already have a newer one; we'll update this one. */
log_fn(LOG_INFO,"Dirserv updating desc for server %s (nickname '%s')",hex_digest,ri->nickname);
if (ri->addr == ri_old->addr && ri->or_port == ri_old->or_port) {
ri->last_reachable = ri_old->last_reachable; /* these carry over */
ri->testing_since = ri_old->testing_since;
}
*msg = verified?"Verified server updated":"Unverified server updated. (Have you sent us your key fingerprint?)";
routerinfo_free(ri_old);
smartlist_del_keeporder(descriptor_list, found);
} else {
/* Add at the end. */
log_fn(LOG_INFO,"Dirserv adding desc for nickname '%s'",ri->nickname);
*msg = verified?"Verified server added":"Unverified server added. (Have you sent us your key fingerprint?)";
}
ri->is_verified = verified ||
tor_version_as_new_as(ri->platform,"0.1.0.2-rc");
smartlist_add(descriptor_list, ri);
*desc = end;
directory_set_dirty();
return verified;
} }
/** Remove all descriptors whose nicknames or fingerprints no longer /** Remove all descriptors whose nicknames or fingerprints no longer
@ -431,27 +383,33 @@ static void
directory_remove_invalid(void) directory_remove_invalid(void)
{ {
int i; int i;
int r; int changed = 0;
routerinfo_t *ent; smartlist_t *descriptor_list = get_descriptor_list();
if (!descriptor_list) if (!descriptor_list)
descriptor_list = smartlist_create(); return;
for (i = 0; i < smartlist_len(descriptor_list); ++i) { for (i = 0; i < smartlist_len(descriptor_list); ++i) {
ent = smartlist_get(descriptor_list, i); routerinfo_t *ent = smartlist_get(descriptor_list, i);
r = dirserv_router_fingerprint_is_known(ent); int r = dirserv_router_fingerprint_is_known(ent);
if (r<0) { if (r<0) {
log(LOG_INFO, "Router '%s' is now verified with a key; removing old router with same name and different key.", log(LOG_INFO, "Router '%s' is now verified with a key; removing old router with same name and different key.",
ent->nickname); ent->nickname);
routerinfo_free(ent); routerinfo_free(ent);
smartlist_del(descriptor_list, i--); smartlist_del(descriptor_list, i--);
changed = 1;
} else if (r>0 && !ent->is_verified) { } else if (r>0 && !ent->is_verified) {
log(LOG_INFO, "Router '%s' is now approved.", ent->nickname); log(LOG_INFO, "Router '%s' is now approved.", ent->nickname);
ent->is_verified = 1; ent->is_verified = 1;
changed = 1;
} else if (r==0 && ent->is_verified) { } else if (r==0 && ent->is_verified) {
log(LOG_INFO, "Router '%s' is no longer approved.", ent->nickname); log(LOG_INFO, "Router '%s' is no longer approved.", ent->nickname);
ent->is_verified = 0; ent->is_verified = 0;
changed = 1;
} }
} }
if (changed)
directory_set_dirty();
} }
/** Write a list of unregistered descriptors into a newly allocated /** Write a list of unregistered descriptors into a newly allocated
@ -467,6 +425,7 @@ dirserver_getinfo_unregistered(const char *question)
char *answer; char *answer;
routerinfo_t *ent; routerinfo_t *ent;
int min_bw = atoi(question); int min_bw = atoi(question);
smartlist_t *descriptor_list = get_descriptor_list();
if (!descriptor_list) if (!descriptor_list)
return tor_strdup(""); return tor_strdup("");
@ -608,7 +567,11 @@ list_server_status(smartlist_t *routers, char **router_status_out)
* been found unreachable for the past several testing periods. * been found unreachable for the past several testing periods.
*/ */
void void
dirserv_log_unreachable_servers(time_t now) { dirserv_log_unreachable_servers(time_t now)
{
smartlist_t *descriptor_list = get_descriptor_list();
if (!descriptor_list)
return;
SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri, SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
{ {
@ -631,7 +594,9 @@ dirserv_log_unreachable_servers(time_t now) {
* (This function can go away when we merge descriptor-list and router-list.) * (This function can go away when we merge descriptor-list and router-list.)
*/ */
void void
dirserv_router_has_begun_reachability_testing(char *digest, time_t now) { dirserv_router_has_begun_reachability_testing(char *digest, time_t now)
{
smartlist_t *descriptor_list = get_descriptor_list();
if (!descriptor_list) if (!descriptor_list)
return; return;
SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri, SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
@ -642,30 +607,6 @@ dirserv_router_has_begun_reachability_testing(char *digest, time_t now) {
}); });
} }
/** Remove any descriptors from the directory that are more than <b>age</b>
* seconds old.
*/
void
dirserv_remove_old_servers(int age)
{
int i;
time_t cutoff;
routerinfo_t *ent;
if (!descriptor_list)
descriptor_list = smartlist_create();
cutoff = time(NULL) - age;
for (i = 0; i < smartlist_len(descriptor_list); ++i) {
ent = smartlist_get(descriptor_list, i);
if (ent->published_on <= cutoff) {
/* descriptor_list[i] is too old. Remove it. */
routerinfo_free(ent);
smartlist_del(descriptor_list, i--);
directory_set_dirty();
}
}
}
/* Given a (possibly empty) list of config_line_t, each line of which contains /* Given a (possibly empty) list of config_line_t, each line of which contains
* a list of comma-separated version numbers surrounded by optional space, * a list of comma-separated version numbers surrounded by optional space,
* allocate and return a new string containing the version numbers, in order, * allocate and return a new string containing the version numbers, in order,
@ -704,12 +645,13 @@ dirserv_dump_directory_to_string(char **dir_out,
char *buf = NULL; char *buf = NULL;
size_t buf_len; size_t buf_len;
size_t identity_pkey_len; size_t identity_pkey_len;
smartlist_t *descriptor_list = get_descriptor_list();
tor_assert(dir_out); tor_assert(dir_out);
*dir_out = NULL; *dir_out = NULL;
if (!descriptor_list) if (!descriptor_list)
descriptor_list = smartlist_create(); return -1;
if (list_server_status(descriptor_list, &router_status)) if (list_server_status(descriptor_list, &router_status))
return -1; return -1;
@ -722,14 +664,13 @@ dirserv_dump_directory_to_string(char **dir_out,
recommended_versions = format_versions_list(get_options()->RecommendedVersions); recommended_versions = format_versions_list(get_options()->RecommendedVersions);
dirserv_remove_old_servers(ROUTER_MAX_AGE);
published_on = time(NULL); published_on = time(NULL);
format_iso_time(published, published_on); format_iso_time(published, published_on);
buf_len = 2048+strlen(recommended_versions)+ buf_len = 2048+strlen(recommended_versions)+
strlen(router_status); strlen(router_status);
SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri, SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
buf_len += strlen(ri->signed_descriptor)); buf_len += ri->signed_descriptor_len);
buf = tor_malloc(buf_len); buf = tor_malloc(buf_len);
/* We'll be comparing against buf_len throughout the rest of the /* We'll be comparing against buf_len throughout the rest of the
function, though strictly speaking we shouldn't be able to exceed function, though strictly speaking we shouldn't be able to exceed
@ -997,9 +938,7 @@ generate_runningrouters(void)
crypto_pk_env_t *private_key = get_identity_key(); crypto_pk_env_t *private_key = get_identity_key();
char *identity_pkey; /* Identity key, DER64-encoded. */ char *identity_pkey; /* Identity key, DER64-encoded. */
size_t identity_pkey_len; size_t identity_pkey_len;
smartlist_t *descriptor_list = get_descriptor_list();
if (!descriptor_list)
descriptor_list = smartlist_create();
if (list_server_status(descriptor_list, &router_status)) { if (list_server_status(descriptor_list, &router_status)) {
goto err; goto err;
@ -1113,6 +1052,12 @@ generate_v2_networkstatus(void)
struct in_addr in; struct in_addr in;
uint32_t addr; uint32_t addr;
crypto_pk_env_t *private_key = get_identity_key(); crypto_pk_env_t *private_key = get_identity_key();
smartlist_t *descriptor_list = get_descriptor_list();
if (!descriptor_list) {
log_fn(LOG_WARN, "Couldn't get router list.");
goto done;
}
if (resolve_my_address(options, &addr, &hostname)<0) { if (resolve_my_address(options, &addr, &hostname)<0) {
log_fn(LOG_WARN, "Couldn't resolve my hostname"); log_fn(LOG_WARN, "Couldn't resolve my hostname");
@ -1285,22 +1230,12 @@ dirserv_get_networkstatus_v2(const char **directory, const char *key,
void void
dirserv_get_routerdescs(smartlist_t *descs_out, const char *key) dirserv_get_routerdescs(smartlist_t *descs_out, const char *key)
{ {
smartlist_t *complete_list; smartlist_t *complete_list = get_descriptor_list();
/* This is annoying. Can we unify these? */
if (descriptor_list)
complete_list = descriptor_list;
else {
routerlist_t *rlst;
router_get_routerlist(&rlst);
complete_list = rlst->routers;
}
if (!complete_list) if (!complete_list)
return; return;
if (!strcmp(key, "/tor/server/all")) { if (!strcmp(key, "/tor/server/all")) {
smartlist_add_all(descs_out, descriptor_list); smartlist_add_all(descs_out, complete_list);
} else if (!strcmp(key, "/tor/server/authority")) { } else if (!strcmp(key, "/tor/server/authority")) {
routerinfo_t *ri = router_get_my_routerinfo(); routerinfo_t *ri = router_get_my_routerinfo();
if (ri) if (ri)
@ -1323,7 +1258,7 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key)
smartlist_free(hexdigests); smartlist_free(hexdigests);
/* XXXX should always return own descriptor. or special-case it. or /* XXXX should always return own descriptor. or special-case it. or
* something. */ * something. */
SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri, SMARTLIST_FOREACH(complete_list, routerinfo_t *, ri,
SMARTLIST_FOREACH(digests, const char *, d, SMARTLIST_FOREACH(digests, const char *, d,
if (!memcmp(d,ri->identity_digest,DIGEST_LEN)) { if (!memcmp(d,ri->identity_digest,DIGEST_LEN)) {
smartlist_add(descs_out,ri); smartlist_add(descs_out,ri);
@ -1352,6 +1287,7 @@ dirserv_orconn_tls_done(const char *address,
int as_advertised) int as_advertised)
{ {
int i; int i;
smartlist_t *descriptor_list = get_descriptor_list();
tor_assert(address); tor_assert(address);
tor_assert(digest_rcvd); tor_assert(digest_rcvd);
tor_assert(nickname_rcvd); tor_assert(nickname_rcvd);
@ -1359,6 +1295,8 @@ dirserv_orconn_tls_done(const char *address,
if (!descriptor_list) if (!descriptor_list)
return; return;
// XXXXNM We should really have a better solution here than dropping
// XXXXNM whole routers; otherwise, they come back way too easily.
for (i = 0; i < smartlist_len(descriptor_list); ++i) { for (i = 0; i < smartlist_len(descriptor_list); ++i) {
routerinfo_t *ri = smartlist_get(descriptor_list, i); routerinfo_t *ri = smartlist_get(descriptor_list, i);
int drop = 0; int drop = 0;
@ -1399,12 +1337,6 @@ dirserv_free_all(void)
smartlist_free(fingerprint_list); smartlist_free(fingerprint_list);
fingerprint_list = NULL; fingerprint_list = NULL;
} }
if (descriptor_list) {
SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
routerinfo_free(ri));
smartlist_free(descriptor_list);
descriptor_list = NULL;
}
clear_cached_dir(&the_directory); clear_cached_dir(&the_directory);
clear_cached_dir(&the_runningrouters); clear_cached_dir(&the_runningrouters);
clear_cached_dir(&cached_directory); clear_cached_dir(&cached_directory);

View File

@ -692,8 +692,6 @@ run_scheduled_events(time_t now)
routerlist_remove_old_routers(ROUTER_MAX_AGE); routerlist_remove_old_routers(ROUTER_MAX_AGE);
if (authdir_mode(options)) { if (authdir_mode(options)) {
/* Dump any old descriptors. */
dirserv_remove_old_servers(ROUTER_MAX_AGE);
dirserv_log_unreachable_servers(now); dirserv_log_unreachable_servers(now);
if (!we_are_hibernating()) { /* try to determine reachability */ if (!we_are_hibernating()) { /* try to determine reachability */
router_retry_connections(1); router_retry_connections(1);

View File

@ -736,15 +736,16 @@ typedef struct {
addr_policy_t *exit_policy; /**< What streams will this OR permit addr_policy_t *exit_policy; /**< What streams will this OR permit
* to exit? */ * to exit? */
long uptime; /**< How many seconds the router claims to have been up */ long uptime; /**< How many seconds the router claims to have been up */
smartlist_t *declared_family; /**< Nicknames of router which this router
* claims are its family. */
char *contact_info; /**< Declared contact info for this router. */
/* local info */ /* local info */
int is_running; /**< As far as we know, is this OR currently running? */ 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? */ time_t status_set_at; /**< When did we last update is_running? */
int is_verified; /**< Has a trusted dirserver validated this OR? */ int is_verified; /**< Has a trusted dirserver validated this OR?
* (For Authdir: Have we validated this OR?)
smartlist_t *declared_family; /**< Nicknames of router which this router */
* claims are its family. */
char *contact_info; /**< Declared contact info for this router. */
/* The below items are used only by authdirservers right now for /* The below items are used only by authdirservers right now for
* reachability testing. */ * reachability testing. */
@ -1636,7 +1637,6 @@ void dirserv_free_descriptors(void);
int list_server_status(smartlist_t *routers, char **router_status_out); int list_server_status(smartlist_t *routers, char **router_status_out);
void dirserv_log_unreachable_servers(time_t now); void dirserv_log_unreachable_servers(time_t now);
void dirserv_router_has_begun_reachability_testing(char *digest, time_t now); void dirserv_router_has_begun_reachability_testing(char *digest, time_t now);
void dirserv_remove_old_servers(int age);
int dirserv_dump_directory_to_string(char **dir_out, int dirserv_dump_directory_to_string(char **dir_out,
crypto_pk_env_t *private_key); crypto_pk_env_t *private_key);
void directory_set_dirty(void); void directory_set_dirty(void);
@ -1654,6 +1654,8 @@ void dirserv_orconn_tls_done(const char *address,
const char *digest_rcvd, const char *digest_rcvd,
const char *nickname, const char *nickname,
int as_advertised); int as_advertised);
int dirserv_wants_to_reject_router(routerinfo_t *ri, int *verified,
const char **msg);
void dirserv_free_all(void); void dirserv_free_all(void);
/********************************* dns.c ***************************/ /********************************* dns.c ***************************/
@ -1991,6 +1993,7 @@ void free_trusted_dir_servers(void);
routerinfo_t *routerinfo_copy(const routerinfo_t *router); routerinfo_t *routerinfo_copy(const routerinfo_t *router);
void router_mark_as_down(const char *digest); void router_mark_as_down(const char *digest);
void routerlist_remove_old_routers(int age); void routerlist_remove_old_routers(int age);
int router_add_to_routerlist(routerinfo_t *router, const char **msg);
int router_load_single_router(const char *s, const char **msg); int router_load_single_router(const char *s, const char **msg);
int router_load_routerlist_from_directory(const char *s,crypto_pk_env_t *pkey, int router_load_routerlist_from_directory(const char *s,crypto_pk_env_t *pkey,
int dir_is_recent, int dir_is_cached); int dir_is_recent, int dir_is_cached);

View File

@ -861,40 +861,59 @@ router_mark_as_down(const char *digest)
* *<b>msg</b> a static string describing the reason for refusing the * *<b>msg</b> a static string describing the reason for refusing the
* routerinfo. * routerinfo.
*/ */
static int int
router_add_to_routerlist(routerinfo_t *router, const char **msg) router_add_to_routerlist(routerinfo_t *router, const char **msg)
{ {
int i; int i;
routerinfo_t *r;
char id_digest[DIGEST_LEN]; char id_digest[DIGEST_LEN];
int authdir = get_options()->AuthoritativeDir;
int authdir_verified = 0;
tor_assert(routerlist); tor_assert(routerlist);
crypto_pk_get_digest(router->identity_pkey, id_digest); crypto_pk_get_digest(router->identity_pkey, id_digest);
if (authdir) {
if (dirserv_wants_to_reject_router(router, &authdir_verified, msg))
return -1;
router->is_verified = authdir_verified;
if (tor_version_as_new_as(router->platform,"0.1.0.2-rc"))
router->is_verified = 1;
}
/* If we have a router with this name, and the identity key is the same, /* If we have a router with this name, and the identity key is the same,
* choose the newer one. If the identity key has changed, drop the router. * choose the newer one. If the identity key has changed, drop the router.
*/ */
for (i = 0; i < smartlist_len(routerlist->routers); ++i) { for (i = 0; i < smartlist_len(routerlist->routers); ++i) {
r = smartlist_get(routerlist->routers, i); routerinfo_t *old_router = smartlist_get(routerlist->routers, i);
if (!crypto_pk_cmp_keys(router->identity_pkey,old_router->identity_pkey)) {
if (!crypto_pk_cmp_keys(router->identity_pkey, r->identity_pkey)) { if (router->published_on <= old_router->published_on) {
if (router->published_on > r->published_on) {
log_fn(LOG_DEBUG, "Replacing entry for router '%s/%s' [%s]",
router->nickname, r->nickname, hex_str(id_digest,DIGEST_LEN));
//XXXRD /* Remember whether we trust this router as a dirserver. */
routerinfo_free(r);
smartlist_set(routerlist->routers, i, router);
return 0;
} else {
log_fn(LOG_DEBUG, "Skipping not-new descriptor for router '%s'", log_fn(LOG_DEBUG, "Skipping not-new descriptor for router '%s'",
router->nickname); router->nickname);
if (!authdir)
/* Update the is_running status to whatever we were told. */ /* Update the is_running status to whatever we were told. */
r->is_running = router->is_running; old_router->is_running = router->is_running;
routerinfo_free(router); routerinfo_free(router);
if (msg) *msg = "Router descriptor was not new."; if (msg) *msg = "Router descriptor was not new.";
return -1; return -1;
} else {
log_fn(LOG_DEBUG, "Replacing entry for router '%s/%s' [%s]",
router->nickname, old_router->nickname,
hex_str(id_digest,DIGEST_LEN));
if (router->addr == old_router->addr &&
router->or_port == old_router->or_port) {
/* these carry over when the address and orport are unchanged.*/
router->last_reachable = old_router->last_reachable;
router->testing_since = old_router->testing_since;
} }
} else if (!strcasecmp(router->nickname, r->nickname)) { if (msg)
*msg = authdir_verified ? "Verified server updated":
"Unverified server updated. (Have you sent us your key finerprint?)";
routerinfo_free(old_router);
smartlist_set(routerlist->routers, i, router);
directory_set_dirty();
return 0;
}
} else if (!strcasecmp(router->nickname, old_router->nickname)) {
/* nicknames match, keys don't. */ /* nicknames match, keys don't. */
if (router->is_verified) { if (router->is_verified) {
/* The new verified router replaces the old one; remove the /* The new verified router replaces the old one; remove the
@ -905,14 +924,15 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg)
* make new ones with the new key. * make new ones with the new key.
*/ */
connection_t *conn; connection_t *conn;
while ((conn = connection_get_by_identity_digest(r->identity_digest, while ((conn = connection_get_by_identity_digest(
CONN_TYPE_OR))) { old_router->identity_digest, CONN_TYPE_OR))) {
log_fn(LOG_INFO,"Closing conn to obsolete router '%s'", r->nickname); log_fn(LOG_INFO,"Closing conn to obsolete router '%s'",
old_router->nickname);
connection_mark_for_close(conn); connection_mark_for_close(conn);
} }
routerinfo_free(r); routerinfo_free(old_router);
smartlist_del_keeporder(routerlist->routers, i--); smartlist_del_keeporder(routerlist->routers, i--);
} else if (r->is_verified) { } else if (old_router->is_verified) {
/* Can't replace a verified router with an unverified one. */ /* Can't replace a verified router with an unverified one. */
log_fn(LOG_DEBUG, "Skipping unverified entry for verified router '%s'", log_fn(LOG_DEBUG, "Skipping unverified entry for verified router '%s'",
router->nickname); router->nickname);
@ -925,16 +945,13 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg)
/* We haven't seen a router with this name before. Add it to the end of /* We haven't seen a router with this name before. Add it to the end of
* the list. */ * the list. */
smartlist_add(routerlist->routers, router); smartlist_add(routerlist->routers, router);
directory_set_dirty();
return 0; return 0;
} }
/** Remove any routers from the routerlist that are more than <b>age</b> /** Remove any routers from the routerlist that are more than <b>age</b>
* seconds old. * seconds old.
*
* (This function is just like dirserv_remove_old_servers. One day we should
* merge them.)
*/ */
//XXXRD
void void
routerlist_remove_old_routers(int age) routerlist_remove_old_routers(int age)
{ {
@ -956,7 +973,7 @@ routerlist_remove_old_routers(int age)
} }
} }
/* /**
* Code to parse a single router descriptor and insert it into the * Code to parse a single router descriptor and insert it into the
* routerlist. Return -1 if the descriptor was ill-formed; 0 if the * routerlist. Return -1 if the descriptor was ill-formed; 0 if the
* descriptor was well-formed but could not be added; and 1 if the * descriptor was well-formed but could not be added; and 1 if the
@ -965,6 +982,8 @@ routerlist_remove_old_routers(int age)
* If we don't add it and <b>msg</b> is not NULL, then assign to * If we don't add it and <b>msg</b> is not NULL, then assign to
* *<b>msg</b> a static string describing the reason for refusing the * *<b>msg</b> a static string describing the reason for refusing the
* descriptor. * descriptor.
*
* This is used only by the controller.
*/ */
int int
router_load_single_router(const char *s, const char **msg) router_load_single_router(const char *s, const char **msg)
@ -1350,6 +1369,7 @@ routers_update_status_from_entry(smartlist_t *routers,
time_t list_time, time_t list_time,
const char *s) const char *s)
{ {
int authdir = get_options()->AuthoritativeDir;
int is_running = 1; int is_running = 1;
int is_verified = 0; int is_verified = 0;
int hex_digest_set = 0; int hex_digest_set = 0;
@ -1421,12 +1441,21 @@ routers_update_status_from_entry(smartlist_t *routers,
{ {
int nickname_matches = is_verified && !strcasecmp(r->nickname, nickname); int nickname_matches = is_verified && !strcasecmp(r->nickname, nickname);
int digest_matches = !memcmp(digest, r->identity_digest, DIGEST_LEN); int digest_matches = !memcmp(digest, r->identity_digest, DIGEST_LEN);
if (!authdir) {
/* If we're not an authoritative directory, update verified status.
*/
if (nickname_matches && digest_matches) if (nickname_matches && digest_matches)
r->is_verified = 1; r->is_verified = 1;
else if (digest_matches) else if (digest_matches)
r->is_verified = 0; r->is_verified = 0;
}
if (digest_matches) if (digest_matches)
if (r->status_set_at < list_time) { if (r->status_set_at < list_time) {
if (!authdir || is_running)
/* If we're an authoritative directory, only believe that servers
* are down when we hear it ourselves. Otherwise, believe
* what we're told.
*/
r->is_running = is_running; r->is_running = is_running;
r->status_set_at = time(NULL); r->status_set_at = time(NULL);
} }