diff options
author | Nick Mathewson <nickm@torproject.org> | 2004-05-17 20:31:01 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2004-05-17 20:31:01 +0000 |
commit | 50b7ebcf9e5b2c6f9fa1f8be470e34e0789c772f (patch) | |
tree | 29f8b52d6c44c4969f816ffcf52257bd5c02a866 | |
parent | d9bcb23f769b4f9137956eae9e4ccf240b3cb686 (diff) | |
download | tor-50b7ebcf9e5b2c6f9fa1f8be470e34e0789c772f.tar.gz tor-50b7ebcf9e5b2c6f9fa1f8be470e34e0789c772f.zip |
Make directory functions update routerlist, not replace it. Add notion of OR-is-trusted-to-be-a-dirserver. Arma, please review: does this handle being a dirserver right?
svn:r1880
-rw-r--r-- | src/or/config.c | 2 | ||||
-rw-r--r-- | src/or/directory.c | 2 | ||||
-rw-r--r-- | src/or/dirserv.c | 2 | ||||
-rw-r--r-- | src/or/main.c | 10 | ||||
-rw-r--r-- | src/or/or.h | 16 | ||||
-rw-r--r-- | src/or/routerlist.c | 115 |
6 files changed, 121 insertions, 26 deletions
diff --git a/src/or/config.c b/src/or/config.c index e8f644cc54..7f30416d3f 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -362,7 +362,7 @@ const char default_dirservers_string[] = ; int config_assign_default_dirservers(void) { - if(router_set_routerlist_from_string(default_dirservers_string) < 0) { + if(router_load_routerlist_from_string(default_dirservers_string, 1) < 0) { log_fn(LOG_WARN,"Bug: the default dirservers internal string is corrupt."); return -1; } diff --git a/src/or/directory.c b/src/or/directory.c index aa97c7c419..5d5a1fde58 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -336,7 +336,7 @@ int connection_dir_process_inbuf(connection_t *conn) { connection_mark_for_close(conn); return -1; } - if(router_set_routerlist_from_directory(body, conn->identity_pkey) < 0){ + if(router_load_routerlist_from_directory(body, conn->identity_pkey) < 0){ log_fn(LOG_INFO,"...but parsing failed. Ignoring."); } else { log_fn(LOG_INFO,"updated routers."); diff --git a/src/or/dirserv.c b/src/or/dirserv.c index ec5582a46e..c4b76406aa 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -566,7 +566,7 @@ size_t dirserv_get_directory(const char **directory) * necessary, but safe is better than sorry. */ new_directory = tor_strdup(the_directory); /* use a new copy of the dir, since get_dir_from_string scribbles on it */ - if (router_set_routerlist_from_directory(new_directory, get_identity_key())) { + if (router_load_routerlist_from_directory(new_directory, get_identity_key())) { log_fn(LOG_ERR, "We just generated a directory we can't parse. Dying."); exit(0); } diff --git a/src/or/main.c b/src/or/main.c index f2f74717e5..20da0c1a3f 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -668,10 +668,12 @@ static int do_main_loop(void) { } /* load the routers file */ - if(options.RouterFile && - router_set_routerlist_from_file(options.RouterFile) < 0) { - log_fn(LOG_ERR,"Error loading router list."); - return -1; + if(options.RouterFile) { + routerlist_clear_trusted_directories(); + if (router_load_routerlist_from_file(options.RouterFile, 1) < 0) { + log_fn(LOG_ERR,"Error loading router list."); + return -1; + } } if(options.DirPort) { /* the directory is already here, run startup things */ diff --git a/src/or/or.h b/src/or/or.h index 924131cf73..8cc42cd9f2 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -542,7 +542,6 @@ typedef struct { crypto_pk_env_t *onion_pkey; /**< Public RSA key for onions. */ crypto_pk_env_t *identity_pkey; /**< Public RSA key for signing. */ - int is_running; /**< As far as we know, is this OR currently running? */ char *platform; /**< What software/operating system is this OR using? */ @@ -552,6 +551,10 @@ typedef struct { uint32_t bandwidthburst; /**< How large is this OR's token bucket? */ struct exit_policy_t *exit_policy; /**< What streams will this OR permit * to exit? */ + /* local info */ + int is_running; /**< As far as we know, is this OR currently running? */ + int is_trusted_dir; /**< Do we trust this OR as a directory server? */ + } routerinfo_t; #define MAX_ROUTERS_IN_DIR 1024 @@ -561,7 +564,9 @@ typedef struct { smartlist_t *routers; /** Which versions of tor are recommended by this directory? */ char *software_versions; - /** When was this directory published? */ + /** When was the most recent directory that contributed to this list + * published? + */ time_t published_on; } routerlist_t; @@ -1284,12 +1289,13 @@ routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port); routerinfo_t *router_get_by_nickname(char *nickname); void router_get_routerlist(routerlist_t **prouterlist); void routerlist_free(routerlist_t *routerlist); +void routerlist_clear_trusted_directories(void); void routerinfo_free(routerinfo_t *router); routerinfo_t *routerinfo_copy(const routerinfo_t *router); void router_mark_as_down(char *nickname); -int router_set_routerlist_from_file(char *routerfile); -int router_set_routerlist_from_string(const char *s); -int router_set_routerlist_from_directory(const char *s, crypto_pk_env_t *pkey); +int router_load_routerlist_from_file(char *routerfile, int trusted); +int router_load_routerlist_from_string(const char *s, int trusted); +int router_load_routerlist_from_directory(const char *s,crypto_pk_env_t *pkey); int router_compare_addr_to_exit_policy(uint32_t addr, uint16_t port, struct exit_policy_t *policy); #define ADDR_POLICY_ACCEPTED 0 diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 63891540ea..a10c5ec7dd 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -44,8 +44,9 @@ routerinfo_t *router_pick_directory_server(void) { if(!choice) { log_fn(LOG_WARN,"No dirservers known. Reloading and trying again."); has_fetched_directory=0; /* reset it */ + routerlist_clear_trusted_directories(); if(options.RouterFile) { - if(router_set_routerlist_from_file(options.RouterFile) < 0) + if(router_load_routerlist_from_file(options.RouterFile, 1) < 0) return NULL; } else { if(config_assign_default_dirservers() < 0) @@ -71,7 +72,7 @@ static routerinfo_t *router_pick_directory_server_impl(void) { sl = smartlist_create(); for(i=0;i< smartlist_len(routerlist->routers); i++) { router = smartlist_get(routerlist->routers, i); - if(router->dir_port > 0 && router->is_running) + if(router->dir_port > 0 && router->is_running && router->is_trusted_dir) smartlist_add(sl, router); } @@ -86,7 +87,7 @@ static routerinfo_t *router_pick_directory_server_impl(void) { * so we cycle through the list again. */ for(i=0; i < smartlist_len(routerlist->routers); i++) { router = smartlist_get(routerlist->routers, i); - if(router->dir_port > 0) { + if(router->dir_port > 0 && router->is_trusted_dir) { router->is_running = 1; dirserver = router; } @@ -300,13 +301,68 @@ void router_mark_as_down(char *nickname) { router->is_running = 0; } +/** Add <b>router</b> to the routerlist, if we don't already have it. Replace + * older entries (if any) with the same name. Note: Callers should not hold + * their pointers to <b>router</b> after invoking this function; <b>router</b> + * will either be inserted into the routerlist or freed. Returns 0 if the + * router was added; -1 if it was not. + */ +int router_add_to_routerlist(routerinfo_t *router) { + int i; + routerinfo_t *r; + /* 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. + */ + for (i = 0; i < smartlist_len(routerlist->routers); ++i) { + r = smartlist_get(routerlist->routers, i); + if (!strcasecmp(router->nickname, r->nickname)) { + if (!crypto_pk_cmp_keys(router->identity_pkey, r->identity_pkey)) { + if (router->published_on > r->published_on) { + log_fn(LOG_DEBUG, "Replacing entry for router '%s'", + router->nickname); + /* Remember whether we trust this router as a dirserver. */ + if (r->is_trusted_dir) + router->is_trusted_dir = 1; + /* If the adress hasn't changed; no need to re-resolve. */ + if (!strcasecmp(r->address, router->address)) + router->addr = r->addr; + routerinfo_free(r); + smartlist_set(routerlist->routers, i, router); + return 0; + } else { + log_fn(LOG_DEBUG, "Skipping old entry for router '%s'", + router->nickname); + /* If we now trust 'router', then we trust the one in the routerlist + * too. */ + if (router->is_trusted_dir) + r->is_trusted_dir = 1; + /* Update the is_running status to whatever we were told. */ + r->is_running = router->is_running; + routerinfo_free(router); + return -1; + } + } else { + log_fn(LOG_WARN, "Identity key mismatch for router '%s'", + router->nickname); + routerinfo_free(router); + return -1; + } + } + } + /* We haven't seen a router with this name before. Add it to the end of + * the list. */ + smartlist_add(routerlist->routers, router); + return 0; +} + /* * Code to parse router descriptors and directories. */ -/** Replace the current router list with the one stored in - * <b>routerfile</b>. */ -int router_set_routerlist_from_file(char *routerfile) +/** Update the current router list with the one stored in + * <b>routerfile</b>. If <b>trusted</b> is true, then we'll use + * directory servers from the file. */ +int router_load_routerlist_from_file(char *routerfile, int trusted) { char *string; @@ -316,7 +372,7 @@ int router_set_routerlist_from_file(char *routerfile) return -1; } - if(router_set_routerlist_from_string(string) < 0) { + if(router_load_routerlist_from_string(string, trusted) < 0) { log_fn(LOG_WARN,"The routerfile itself was corrupt."); free(string); return -1; @@ -327,15 +383,35 @@ int router_set_routerlist_from_file(char *routerfile) return 0; } +/** Mark all directories in the routerlist as nontrusted. */ +void routerlist_clear_trusted_directories(void) +{ + if (!routerlist) return; + SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, r, + r->is_trusted_dir = 0); +} + /** Helper function: read routerinfo elements from s, and throw out the - * ones that don't parse and resolve. Replace the current - * routerlist. */ -int router_set_routerlist_from_string(const char *s) + * ones that don't parse and resolve. Add all remaining elements to the + * routerlist. If <b>trusted</b> is true, then we'll use + * directory servers from the string + */ +int router_load_routerlist_from_string(const char *s, int trusted) { - if (router_parse_list_from_string(&s, &routerlist, -1, NULL)) { + routerlist_t *new_list=NULL; + + if (router_parse_list_from_string(&s, &new_list, -1, NULL)) { log(LOG_WARN, "Error parsing router file"); return -1; } + if (trusted) { + SMARTLIST_FOREACH(new_list->routers, routerinfo_t *, r, + if (r->dir_port) r->is_trusted_dir = 1); + } + SMARTLIST_FOREACH(new_list->routers, routerinfo_t *, r, + router_add_to_routerlist(r)); + smartlist_clear(new_list->routers); + routerlist_free(new_list); if (router_resolve_routerlist(routerlist)) { log(LOG_WARN, "Error resolving routerlist"); return -1; @@ -370,16 +446,25 @@ int is_recommended_version(const char *myversion, /** Replace the current routerlist with the routers stored in the * signed directory <b>s</b>. If pkey is provided, make sure that <b>s</b> is * signed with pkey. */ -int router_set_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) { - if (router_parse_routerlist_from_directory(s, &routerlist, pkey)) { + routerlist_t *new_list = NULL; + if (router_parse_routerlist_from_directory(s, &new_list, pkey)) { log_fn(LOG_WARN, "Couldn't parse directory."); return -1; } + SMARTLIST_FOREACH(new_list->routers, routerinfo_t *, r, + router_add_to_routerlist(r)); + smartlist_clear(new_list->routers); if (router_resolve_routerlist(routerlist)) { log_fn(LOG_WARN, "Error resolving routerlist"); return -1; } + routerlist->published_on = new_list->published_on; + tor_free(routerlist->software_versions); + routerlist->software_versions = new_list->software_versions; + new_list->software_versions = NULL; + routerlist_free(new_list); if (!is_recommended_version(VERSION, routerlist->software_versions)) { log(options.IgnoreVersion ? LOG_WARN : LOG_ERR, "You are running Tor version %s, which will not work with this network.\n" @@ -432,7 +517,9 @@ router_resolve_routerlist(routerlist_t *rl) r = smartlist_get(rl->routers,i); if (router_is_me(r)) { remove = 1; - } else if (router_resolve(r)) { + } else if (r->addr) { + /* already resolved. */ + } else if (!router_resolve(r)) { log_fn(LOG_WARN, "Couldn't resolve router %s; not using", r->address); remove = 1; } |