|
@@ -21,9 +21,10 @@ static smartlist_t *trusted_dir_servers = NULL;
|
|
|
/* static function prototypes */
|
|
|
static routerinfo_t *
|
|
|
router_pick_directory_server_impl(int requireother, int fascistfirewall,
|
|
|
- int for_runningrouters);
|
|
|
+ int for_v2_directory);
|
|
|
static trusted_dir_server_t *
|
|
|
-router_pick_trusteddirserver_impl(int requireother, int fascistfirewall);
|
|
|
+router_pick_trusteddirserver_impl(int need_v1_support,
|
|
|
+ int requireother, int fascistfirewall);
|
|
|
static void mark_all_trusteddirservers_up(void);
|
|
|
static int router_nickname_is_in_list(routerinfo_t *router, const char *list);
|
|
|
static int router_nickname_matches(routerinfo_t *router, const char *nickname);
|
|
@@ -78,12 +79,13 @@ router_reload_router_list(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/** DOCDOC */
|
|
|
int
|
|
|
router_reload_networkstatus(void)
|
|
|
{
|
|
|
char filename[512];
|
|
|
struct stat st;
|
|
|
- smartlist_t *entries;
|
|
|
+ smartlist_t *entries, *bad_names;
|
|
|
char *s;
|
|
|
tor_assert(get_options()->DataDirectory);
|
|
|
if (!networkstatus_list)
|
|
@@ -92,17 +94,24 @@ router_reload_networkstatus(void)
|
|
|
tor_snprintf(filename,sizeof(filename),"%s/cached-status",
|
|
|
get_options()->DataDirectory);
|
|
|
entries = tor_listdir(filename);
|
|
|
+ bad_names = smartlist_create();
|
|
|
SMARTLIST_FOREACH(entries, const char *, fn, {
|
|
|
+ char buf[DIGEST_LEN];
|
|
|
+ if (strlen(fn) != HEX_DIGEST_LEN ||
|
|
|
+ base16_decode(buf, sizeof(buf), fn, strlen(fn))) {
|
|
|
+ log_fn(LOG_INFO,
|
|
|
+ "Skipping cached-status file with unexpected name \"%s\"",fn);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
tor_snprintf(filename,sizeof(filename),"%s/cached-status/%s",
|
|
|
get_options()->DataDirectory, fn);
|
|
|
s = read_file_to_str(filename, 0);
|
|
|
if (s) {
|
|
|
- networkstatus_t *ns;
|
|
|
stat(filename, &st);
|
|
|
- log_fn(LOG_INFO, "Loading cached network status from %s", filename);
|
|
|
- ns = networkstatus_parse_from_string(s);
|
|
|
- ns->received_on = st.st_mtime;
|
|
|
- smartlist_add(networkstatus_list, ns);
|
|
|
+ if (router_set_networkstatus(s, st.st_mtime, 1)<0) {
|
|
|
+ log_fn(LOG_WARN, "Couldn't load networkstatus from \"%s\"",filename);
|
|
|
+ }
|
|
|
+ tor_free(s);
|
|
|
}
|
|
|
});
|
|
|
return 0;
|
|
@@ -133,7 +142,7 @@ router_get_trusted_dir_servers(smartlist_t **outp)
|
|
|
routerinfo_t *
|
|
|
router_pick_directory_server(int requireother,
|
|
|
int fascistfirewall,
|
|
|
- int for_runningrouters,
|
|
|
+ int for_v2_directory,
|
|
|
int retry_if_no_servers)
|
|
|
{
|
|
|
routerinfo_t *choice;
|
|
@@ -142,7 +151,7 @@ router_pick_directory_server(int requireother,
|
|
|
return NULL;
|
|
|
|
|
|
choice = router_pick_directory_server_impl(requireother, fascistfirewall,
|
|
|
- for_runningrouters);
|
|
|
+ for_v2_directory);
|
|
|
if (choice || !retry_if_no_servers)
|
|
|
return choice;
|
|
|
|
|
@@ -151,7 +160,7 @@ router_pick_directory_server(int requireother,
|
|
|
mark_all_trusteddirservers_up();
|
|
|
/* try again */
|
|
|
choice = router_pick_directory_server_impl(requireother, fascistfirewall,
|
|
|
- for_runningrouters);
|
|
|
+ for_v2_directory);
|
|
|
if (choice)
|
|
|
return choice;
|
|
|
|
|
@@ -163,7 +172,7 @@ router_pick_directory_server(int requireother,
|
|
|
}
|
|
|
/* give it one last try */
|
|
|
choice = router_pick_directory_server_impl(requireother, 0,
|
|
|
- for_runningrouters);
|
|
|
+ for_v2_directory);
|
|
|
return choice;
|
|
|
}
|
|
|
|
|
@@ -171,21 +180,26 @@ router_pick_directory_server(int requireother,
|
|
|
* trusted dirservers and <b>retry_if_no_servers</b> is non-zero,
|
|
|
* set them all as running again, and try again.
|
|
|
* Other args are as in router_pick_trusteddirserver_impl().
|
|
|
+ *
|
|
|
+ * DOCDOC need_v1_support
|
|
|
*/
|
|
|
trusted_dir_server_t *
|
|
|
-router_pick_trusteddirserver(int requireother,
|
|
|
+router_pick_trusteddirserver(int need_v1_support,
|
|
|
+ int requireother,
|
|
|
int fascistfirewall,
|
|
|
int retry_if_no_servers)
|
|
|
{
|
|
|
trusted_dir_server_t *choice;
|
|
|
|
|
|
- choice = router_pick_trusteddirserver_impl(requireother, fascistfirewall);
|
|
|
+ choice = router_pick_trusteddirserver_impl(need_v1_support,
|
|
|
+ requireother, fascistfirewall);
|
|
|
if (choice || !retry_if_no_servers)
|
|
|
return choice;
|
|
|
|
|
|
log_fn(LOG_INFO,"No trusted dirservers are reachable. Trying them all again.");
|
|
|
mark_all_trusteddirservers_up();
|
|
|
- return router_pick_trusteddirserver_impl(requireother, fascistfirewall);
|
|
|
+ return router_pick_trusteddirserver_impl(need_v1_support,
|
|
|
+ requireother, fascistfirewall);
|
|
|
}
|
|
|
|
|
|
/** Pick a random running verified directory server/mirror from our
|
|
@@ -193,13 +207,12 @@ router_pick_trusteddirserver(int requireother,
|
|
|
* If <b>fascistfirewall</b> and we're not using a proxy,
|
|
|
* make sure the port we pick is allowed by options-\>firewallports.
|
|
|
* If <b>requireother</b>, it cannot be us.
|
|
|
- * If <b>for_runningrouters</b>, make sure we pick a dirserver that
|
|
|
- * can answer queries for running-routers (this option will become obsolete
|
|
|
- * once 0.0.9-rc5 is dead).
|
|
|
+ *
|
|
|
+ * DOCDOC need_v1_support, for_v2_directory
|
|
|
*/
|
|
|
static routerinfo_t *
|
|
|
router_pick_directory_server_impl(int requireother, int fascistfirewall,
|
|
|
- int for_runningrouters)
|
|
|
+ int for_v2_directory)
|
|
|
{
|
|
|
int i;
|
|
|
routerinfo_t *router;
|
|
@@ -223,9 +236,9 @@ router_pick_directory_server_impl(int requireother, int fascistfirewall,
|
|
|
if (!fascist_firewall_allows_address(router->addr, router->dir_port))
|
|
|
continue;
|
|
|
}
|
|
|
- /* before 0.0.9rc5-cvs, only trusted dirservers served status info. */
|
|
|
- if (for_runningrouters &&
|
|
|
- !(tor_version_as_new_as(router->platform,"0.0.9rc5-cvs") ||
|
|
|
+ /* before 0.1.1.6-alpha, only trusted dirservers served status info. */
|
|
|
+ if (for_v2_directory &&
|
|
|
+ !(tor_version_as_new_as(router->platform,"0.1.1.6-alpha") ||
|
|
|
router_digest_is_trusted_dir(router->identity_digest)))
|
|
|
continue;
|
|
|
smartlist_add(sl, router);
|
|
@@ -242,7 +255,8 @@ router_pick_directory_server_impl(int requireother, int fascistfirewall,
|
|
|
* If <b>requireother</b>, it cannot be us.
|
|
|
*/
|
|
|
static trusted_dir_server_t *
|
|
|
-router_pick_trusteddirserver_impl(int requireother, int fascistfirewall)
|
|
|
+router_pick_trusteddirserver_impl(int need_v1_support,
|
|
|
+ int requireother, int fascistfirewall)
|
|
|
{
|
|
|
smartlist_t *sl;
|
|
|
routerinfo_t *me;
|
|
@@ -259,6 +273,8 @@ router_pick_trusteddirserver_impl(int requireother, int fascistfirewall)
|
|
|
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d,
|
|
|
{
|
|
|
if (!d->is_running) continue;
|
|
|
+ if (need_v1_support && !d->supports_v1_protocol)
|
|
|
+ continue;
|
|
|
if (requireother && me &&
|
|
|
!memcmp(me->identity_digest, d->digest, DIGEST_LEN))
|
|
|
continue;
|
|
@@ -1166,6 +1182,79 @@ router_load_routerlist_from_directory(const char *s,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/** DOCDOC returns 0 on no problems, -1 on problems.
|
|
|
+ */
|
|
|
+int
|
|
|
+router_set_networkstatus(const char *s, time_t arrived_at, int is_cached)
|
|
|
+{
|
|
|
+ networkstatus_t *ns;
|
|
|
+ int i, found;
|
|
|
+ time_t now;
|
|
|
+ char fp[HEX_DIGEST_LEN+1];
|
|
|
+
|
|
|
+ ns = networkstatus_parse_from_string(s);
|
|
|
+ if (!ns) {
|
|
|
+ log_fn(LOG_WARN, "Couldn't parse network status.");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ if (!router_digest_is_trusted_dir(ns->identity_digest)) {
|
|
|
+ log_fn(LOG_INFO, "Network status was signed, but not by an authoritative directory we recognize.");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ now = time(NULL);
|
|
|
+ if (arrived_at > now)
|
|
|
+ arrived_at = now;
|
|
|
+
|
|
|
+ ns->received_on = arrived_at;
|
|
|
+
|
|
|
+ /*XXXX Check publishing skew. NM*/
|
|
|
+
|
|
|
+ if (!networkstatus_list)
|
|
|
+ networkstatus_list = smartlist_create();
|
|
|
+
|
|
|
+ found = 0;
|
|
|
+ for (i=0; i < smartlist_len(networkstatus_list); ++i) {
|
|
|
+ networkstatus_t *old_ns = smartlist_get(networkstatus_list, i);
|
|
|
+
|
|
|
+ if (!memcmp(old_ns->identity_digest, ns->identity_digest, DIGEST_LEN)) {
|
|
|
+ if (!memcmp(old_ns->networkstatus_digest,
|
|
|
+ ns->networkstatus_digest, DIGEST_LEN)) {
|
|
|
+ networkstatus_free(ns);
|
|
|
+ return 0;
|
|
|
+ } else if (old_ns->published_on >= ns->published_on) {
|
|
|
+ log_fn(LOG_INFO, "Dropping network-status; we have a newer one for this authority.");
|
|
|
+ networkstatus_free(ns);
|
|
|
+ return 0;
|
|
|
+ } else {
|
|
|
+ networkstatus_free(old_ns);
|
|
|
+ smartlist_set(networkstatus_list, i, ns);
|
|
|
+ found = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!found)
|
|
|
+ smartlist_add(networkstatus_list, ns);
|
|
|
+
|
|
|
+ base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN);
|
|
|
+
|
|
|
+ if (!is_cached) {
|
|
|
+ const char *datadir = get_options()->DataDirectory;
|
|
|
+ char fp[HEX_DIGEST_LEN+1];
|
|
|
+ size_t len = strlen(datadir)+64;
|
|
|
+ char *fn = tor_malloc(len+1);
|
|
|
+ tor_snprintf(fn, len, "%s/cached-directory/%s",datadir,fp);
|
|
|
+ if (write_str_to_file(fn, s, 0)<0) {
|
|
|
+ log_fn(LOG_NOTICE, "Couldn't write cached network status to \"%s\"", fn);
|
|
|
+ }
|
|
|
+ tor_free(fn);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (get_options()->DirPort)
|
|
|
+ dirserv_set_cached_networkstatus_v2(s, fp, ns->published_on);
|
|
|
+}
|
|
|
+
|
|
|
/** Ensure that our own routerinfo is at the front, and remove duplicates
|
|
|
* of our routerinfo.
|
|
|
*/
|
|
@@ -1571,7 +1660,8 @@ router_update_status_from_smartlist(routerinfo_t *router,
|
|
|
* <b>address</b>:<b>port</b>, with identity key <b>digest</b>. If
|
|
|
* <b>address</b> is NULL, add ourself. */
|
|
|
void
|
|
|
-add_trusted_dir_server(const char *address, uint16_t port, const char *digest)
|
|
|
+add_trusted_dir_server(const char *address, uint16_t port, const char *digest,
|
|
|
+ int supports_v1)
|
|
|
{
|
|
|
trusted_dir_server_t *ent;
|
|
|
uint32_t a;
|
|
@@ -1599,6 +1689,7 @@ add_trusted_dir_server(const char *address, uint16_t port, const char *digest)
|
|
|
ent->addr = a;
|
|
|
ent->dir_port = port;
|
|
|
ent->is_running = 1;
|
|
|
+ ent->supports_v1_protocol = supports_v1;
|
|
|
memcpy(ent->digest, digest, DIGEST_LEN);
|
|
|
smartlist_add(trusted_dir_servers, ent);
|
|
|
}
|