diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/ht.h | 2 | ||||
-rw-r--r-- | src/or/directory.c | 109 | ||||
-rw-r--r-- | src/or/or.h | 30 | ||||
-rw-r--r-- | src/or/relay.c | 3 | ||||
-rw-r--r-- | src/or/routerlist.c | 103 |
5 files changed, 152 insertions, 95 deletions
diff --git a/src/common/ht.h b/src/common/ht.h index e50ada29c5..d2be68322c 100644 --- a/src/common/ht.h +++ b/src/common/ht.h @@ -24,7 +24,7 @@ } #define HT_INITIALIZER() \ - { 0, NULL, 0, 0, -1 } + { NULL, 0, 0, 0, -1 } #define HT_INIT(root) do { \ (root)->hth_table_length = 0; \ diff --git a/src/or/directory.c b/src/or/directory.c index 4fbad1583e..b2244e53f7 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -31,11 +31,6 @@ const char directory_c_id[] = * connection_finished_connecting() in connection.c */ static void -directory_initiate_command_trusted_dir(trusted_dir_server_t *dirserv, - uint8_t purpose, int private_connection, - const char *resource, - const char *payload, size_t payload_len); -static void directory_initiate_command(const char *address, uint32_t addr, uint16_t port, const char *platform, const char *digest, uint8_t purpose, @@ -143,10 +138,11 @@ directory_post_to_dirservers(uint8_t purpose, const char *payload, */ SMARTLIST_FOREACH(dirservers, trusted_dir_server_t *, ds, { + routerstatus_t *rs = &(ds->fake_status); post_via_tor = purpose_is_private(purpose) || !fascist_firewall_allows_address(ds->addr,ds->dir_port); - directory_initiate_command_trusted_dir(ds, purpose, post_via_tor, - NULL, payload, payload_len); + directory_initiate_command_routerstatus(rs, purpose, post_via_tor, + NULL, payload, payload_len); }); } @@ -159,8 +155,7 @@ void directory_get_from_dirserver(uint8_t purpose, const char *resource, int retry_if_no_servers) { - routerinfo_t *r = NULL; - trusted_dir_server_t *ds = NULL; + routerstatus_t *rs = NULL; or_options_t *options = get_options(); int fetch_fresh_first = server_mode(options) && options->DirPort != 0; int directconn = !purpose_is_private(purpose); @@ -175,19 +170,21 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource, !strcmpstart(resource,"fp/") && strlen(resource) == HEX_DIGEST_LEN+3) { /* Try to ask the actual dirserver its opinion. */ char digest[DIGEST_LEN]; + trusted_dir_server_t *ds; base16_decode(digest, DIGEST_LEN, resource+3, HEX_DIGEST_LEN); ds = router_get_trusteddirserver_by_digest(digest); + rs = &(ds->fake_status); } - if (!ds && fetch_fresh_first) { + if (!rs && fetch_fresh_first) { /* only ask authdirservers, and don't ask myself */ - ds = router_pick_trusteddirserver(need_v1_support, 1, 1, + rs = router_pick_trusteddirserver(need_v1_support, 1, 1, retry_if_no_servers); } - if (!ds) { + if (!rs) { /* anybody with a non-zero dirport will do */ - r = router_pick_directory_server(1, 1, need_v2_support, - retry_if_no_servers); - if (!r) { + rs = router_pick_directory_server(1, 1, need_v2_support, + retry_if_no_servers); + if (!rs) { const char *which; if (purpose == DIR_PURPOSE_FETCH_DIR) which = "directory"; @@ -199,9 +196,9 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource, which = "server descriptors"; info(LD_DIR, "No router found for %s; falling back to dirserver list", which); - ds = router_pick_trusteddirserver(1, 1, 1, + rs = router_pick_trusteddirserver(1, 1, 1, retry_if_no_servers); - if (!ds) + if (!rs) directconn = 0; /* last resort: try routing it via Tor */ } } @@ -210,20 +207,18 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource, /* Never use fascistfirewall; we're going via Tor. */ if (purpose == DIR_PURPOSE_FETCH_RENDDESC) { /* only ask authdirservers, any of them will do */ - ds = router_pick_trusteddirserver(0, 0, 0, retry_if_no_servers); + rs = router_pick_trusteddirserver(0, 0, 0, retry_if_no_servers); } else { /* anybody with a non-zero dirport will do. Disregard firewalls. */ - r = router_pick_directory_server(1, 0, need_v2_support, - retry_if_no_servers); + rs = router_pick_directory_server(1, 0, need_v2_support, + retry_if_no_servers); + /* XXXX If no rs, fall back to trusted dir servers? -NM */ } } - if (r) - directory_initiate_command_router(r, purpose, !directconn, - resource, NULL, 0); - else if (ds) - directory_initiate_command_trusted_dir(ds, purpose, !directconn, - resource, NULL, 0); + if (rs) + directory_initiate_command_routerstatus(rs, purpose, !directconn, + resource, NULL, 0); else { notice(LD_DIR, "No running dirservers known. Will try again later. (purpose %d)", @@ -247,28 +242,56 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource, * want to fetch. */ void -directory_initiate_command_router(routerinfo_t *router, uint8_t purpose, - int private_connection, const char *resource, - const char *payload, size_t payload_len) +directory_initiate_command_router(routerinfo_t *router, + uint8_t purpose, + int private_connection, + const char *resource, + const char *payload, + size_t payload_len) { directory_initiate_command(router->address, router->addr, router->dir_port, - router->platform, router->cache_info.identity_digest, - purpose, private_connection, resource, - payload, payload_len); + router->platform, + router->cache_info.identity_digest, + purpose, private_connection, resource, + payload, payload_len); } -/** As directory_initiate_command_router, but send the command to a trusted - * directory server <b>dirserv</b>. **/ -static void -directory_initiate_command_trusted_dir(trusted_dir_server_t *dirserv, - uint8_t purpose, int private_connection, - const char *resource, - const char *payload, size_t payload_len) +/** Launch a new connection to the directory server <b>status</b> to upload or + * download a service or rendezvous descriptor. <b>purpose</b> determines what + * kind of directory connection we're launching, and must be one of + * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}. + * + * When uploading, <b>payload</b> and <b>payload_len</b> determine the content + * of the HTTP post. Otherwise, <b>payload</b> should be NULL. + * + * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we + * want to fetch. + */ +void +directory_initiate_command_routerstatus(routerstatus_t *status, + uint8_t purpose, + int private_connection, + const char *resource, + const char *payload, + size_t payload_len) { - directory_initiate_command(dirserv->address, dirserv->addr, - dirserv->dir_port, NULL, dirserv->digest, purpose, - private_connection, resource, - payload, payload_len); + const char *platform = NULL; + routerinfo_t *router; + char address_buf[INET_NTOA_BUF_LEN]; + struct in_addr in; + const char *address; + if ((router = router_get_by_digest(status->identity_digest))) { + platform = router->platform; + address = router->address; + } else { + in.s_addr = htonl(status->addr); + tor_inet_ntoa(&in, address_buf, sizeof(address_buf)); + address = address_buf; + } + directory_initiate_command(address, status->addr, status->dir_port, + platform, status->identity_digest, + purpose, private_connection, resource, + payload, payload_len); } /** Called when we are unable to complete the client's request to a diff --git a/src/or/or.h b/src/or/or.h index 128abf5e0a..e716c209b0 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1822,6 +1822,12 @@ void directory_initiate_command_router(routerinfo_t *router, uint8_t purpose, const char *resource, const char *payload, size_t payload_len); +void directory_initiate_command_routerstatus(routerstatus_t *status, + uint8_t purpose, + int private_connection, + const char *resource, + const char *payload, + size_t payload_len); int parse_http_response(const char *headers, int *code, time_t *date, int *compression, char **response); @@ -2183,24 +2189,26 @@ typedef struct trusted_dir_server_t { uint16_t dir_port; /**< Directory port */ char digest[DIGEST_LEN]; /**< Digest of identity key */ unsigned int is_running:1; /**< True iff we think this server is running. */ - unsigned int supports_v1_protocol:1; /**< True iff this server is an - * authority for the older ("v1") - * directory protocol.*/ + unsigned int is_v1_authority:1; /**< True iff this server is an + * authority for the older ("v1") + * directory protocol.*/ int n_networkstatus_failures; /**< How many times have we asked for this * server's network-status unsuccessfully? */ + routerstatus_t fake_status; /**< Used when we need to pass this trusted + * dir_server_t as a routerstatus_t. */ } trusted_dir_server_t; int router_reload_router_list(void); int router_reload_networkstatus(void); void router_get_trusted_dir_servers(smartlist_t **outp); -routerinfo_t *router_pick_directory_server(int requireother, - int fascistfirewall, - int for_v2_directory, - int retry_if_no_servers); -trusted_dir_server_t *router_pick_trusteddirserver(int need_v1_support, - int requireother, - int fascistfirewall, - int retry_if_no_servers); +routerstatus_t *router_pick_directory_server(int requireother, + int fascistfirewall, + int for_v2_directory, + int retry_if_no_servers); +routerstatus_t *router_pick_trusteddirserver(int need_v1_authority, + int requireother, + int fascistfirewall, + int retry_if_no_servers); trusted_dir_server_t *router_get_trusteddirserver_by_digest( const char *digest); int all_trusted_directory_servers_down(void); diff --git a/src/or/relay.c b/src/or/relay.c index 529c149715..028261078f 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -3,7 +3,8 @@ * Copyright 2004-2005 Roger Dingledine, Nick Mathewson. */ /* See LICENSE for licensing information */ /* $Id$ */ -const char relay_c_id[] = "$Id$"; +const char relay_c_id[] = + "$Id$"; /** * \file relay.c diff --git a/src/or/routerlist.c b/src/or/routerlist.c index b90e790cb3..c2c835c76a 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -18,11 +18,11 @@ const char routerlist_c_id[] = /****************************************************************************/ /* static function prototypes */ -static routerinfo_t *router_pick_directory_server_impl(int requireother, - int fascistfirewall, - int for_v2_directory); -static trusted_dir_server_t *router_pick_trusteddirserver_impl( - int need_v1_support, int requireother, int fascistfirewall); +static routerstatus_t *router_pick_directory_server_impl(int requireother, + int fascistfirewall, + int for_v2_directory); +static routerstatus_t *router_pick_trusteddirserver_impl( + int need_v1_authority, 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); @@ -321,13 +321,13 @@ router_get_trusted_dir_servers(smartlist_t **outp) * (that is, a trusted dirserver, or one running 0.0.9rc5-cvs or later). * Other args are as in router_pick_directory_server_impl(). */ -routerinfo_t * +routerstatus_t * router_pick_directory_server(int requireother, int fascistfirewall, int for_v2_directory, int retry_if_no_servers) { - routerinfo_t *choice; + routerstatus_t *choice; if (!routerlist) return NULL; @@ -358,6 +358,9 @@ router_pick_directory_server(int requireother, return choice; } +/** Return the trusted_dir_server_t for the directory authority whose identity + * key hashes to <b>digest</b>, or NULL if no such authority is known. + */ trusted_dir_server_t * router_get_trusteddirserver_by_digest(const char *digest) { @@ -376,24 +379,26 @@ router_get_trusteddirserver_by_digest(const char *digest) /** Try to find a running trusted dirserver. If there are no running * trusted dirservers and <b>retry_if_no_servers</b> is non-zero, * set them all as running again, and try again. + * If <b>need_v1_authority</b> is set, return only trusted servers + * that are authorities for the V1 directory protocol. * Other args are as in router_pick_trusteddirserver_impl(). */ -trusted_dir_server_t * -router_pick_trusteddirserver(int need_v1_support, +routerstatus_t * +router_pick_trusteddirserver(int need_v1_authority, int requireother, int fascistfirewall, int retry_if_no_servers) { - trusted_dir_server_t *choice; + routerstatus_t *choice; - choice = router_pick_trusteddirserver_impl(need_v1_support, + choice = router_pick_trusteddirserver_impl(need_v1_authority, requireother, fascistfirewall); if (choice || !retry_if_no_servers) return choice; info(LD_DIR,"No trusted dirservers are reachable. Trying them all again."); mark_all_trusteddirservers_up(); - return router_pick_trusteddirserver_impl(need_v1_support, + return router_pick_trusteddirserver_impl(need_v1_authority, requireother, fascistfirewall); } @@ -405,37 +410,34 @@ router_pick_trusteddirserver(int need_v1_support, * choose a directory server new enough to support the v2 directory * functionality. */ -static routerinfo_t * +static routerstatus_t * router_pick_directory_server_impl(int requireother, int fascistfirewall, int for_v2_directory) { - routerinfo_t *result; + routerstatus_t *result; smartlist_t *sl; - if (!routerlist) + if (!routerstatus_list) return NULL; /* Find all the running dirservers we know about. */ sl = smartlist_create(); - SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router, + SMARTLIST_FOREACH(routerstatus_list, local_routerstatus_t *, _local_status, { - if (!router->is_running || !router->dir_port || !router->is_verified) + routerstatus_t *status = &(_local_status->status); + if (!status->is_running || !status->dir_port || !status->is_valid) continue; - if (requireother && router_is_me(router)) + if (requireother && router_digest_is_me(status->identity_digest)) continue; if (fascistfirewall) { - if (!fascist_firewall_allows_address(router->addr, router->dir_port)) + if (!fascist_firewall_allows_address(status->addr, status->dir_port)) continue; } - /* Before 0.1.1.6-alpha, only trusted dirservers served status info. - * Before 0.1.1.7-alpha, retrieving nonexistent server IDs could bork - * the directory server. - */ if (for_v2_directory && - !(tor_version_as_new_as(router->platform,"0.1.1.7-alpha") || - router_digest_is_trusted_dir(router->cache_info.identity_digest))) + !(status->is_v2_dir || + router_digest_is_trusted_dir(status->identity_digest))) continue; - smartlist_add(sl, router); + smartlist_add(sl, status); }); result = smartlist_choose(sl); @@ -443,19 +445,19 @@ router_pick_directory_server_impl(int requireother, int fascistfirewall, return result; } -/** Choose randomly from among the trusted dirservers that are up. - * If <b>fascistfirewall</b>, - * make sure the port we pick is allowed by our firewall options. - * If <b>requireother</b>, it cannot be us. If <b>need_v1_support</b>, choose - * a trusted authority for the v1 directory system. +/** Choose randomly from among the trusted dirservers that are up. If + * <b>fascistfirewall</b>, make sure the port we pick is allowed by our + * firewall options. If <b>requireother</b>, it cannot be us. If + * <b>need_v1_authority</b>, choose a trusted authority for the v1 directory + * system. */ -static trusted_dir_server_t * -router_pick_trusteddirserver_impl(int need_v1_support, +static routerstatus_t * +router_pick_trusteddirserver_impl(int need_v1_authority, int requireother, int fascistfirewall) { smartlist_t *sl; routerinfo_t *me; - trusted_dir_server_t *ds; + routerstatus_t *rs; sl = smartlist_create(); me = router_get_my_routerinfo(); @@ -465,7 +467,7 @@ router_pick_trusteddirserver_impl(int need_v1_support, SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d, { if (!d->is_running) continue; - if (need_v1_support && !d->supports_v1_protocol) + if (need_v1_authority && !d->is_v1_authority) continue; if (requireother && me && router_digest_is_me(d->digest)) continue; @@ -473,12 +475,12 @@ router_pick_trusteddirserver_impl(int need_v1_support, if (!fascist_firewall_allows_address(d->addr, d->dir_port)) continue; } - smartlist_add(sl, d); + smartlist_add(sl, &d->fake_status); }); - ds = smartlist_choose(sl); + rs = smartlist_choose(sl); smartlist_free(sl); - return ds; + return rs; } /** Go through and mark the authoritative dirservers as up. */ @@ -2526,7 +2528,7 @@ add_trusted_dir_server(const char *nickname, const char *address, ent->addr = a; ent->dir_port = port; ent->is_running = 1; - ent->supports_v1_protocol = supports_v1; + ent->is_v1_authority = supports_v1; memcpy(ent->digest, digest, DIGEST_LEN); dlen = 64 + strlen(hostname) + (nickname?strlen(nickname):0); @@ -2538,6 +2540,16 @@ add_trusted_dir_server(const char *nickname, const char *address, tor_snprintf(ent->description, dlen, "directory server at %s:%d", hostname, (int)port); + ent->fake_status.addr = ent->addr; + memcpy(ent->fake_status.identity_digest, digest, DIGEST_LEN); + strlcpy(ent->fake_status.nickname, nickname, + sizeof(ent->fake_status.nickname)); + ent->fake_status.dir_port = ent->dir_port; + ent->fake_status.is_running = 1; + ent->fake_status.is_named = 1; + ent->fake_status.is_valid = 1; + ent->fake_status.is_v2_dir = 1; + smartlist_add(trusted_dir_servers, ent); } @@ -2848,6 +2860,7 @@ routerstatus_list_update_from_networkstatus(time_t now) */ while (1) { int n_running=0, n_named=0, n_valid=0, n_listing=0; + int n_v2_dir=0, n_fast=0, n_stable=0, n_exit=0; const char *the_name = NULL; local_routerstatus_t *rs_out, *rs_old; routerstatus_t *rs, *most_recent; @@ -2902,6 +2915,14 @@ routerstatus_list_update_from_networkstatus(time_t now) ++n_valid; if (rs->is_running && ns->is_recent) ++n_running; + if (rs->is_exit) + ++n_exit; + if (rs->is_fast) + ++n_fast; + if (rs->is_stable) + ++n_stable; + if (rs->is_v2_dir) + ++n_v2_dir; } rs_out = tor_malloc_zero(sizeof(local_routerstatus_t)); memcpy(&rs_out->status, most_recent, sizeof(routerstatus_t)); @@ -2930,6 +2951,10 @@ routerstatus_list_update_from_networkstatus(time_t now) sizeof(rs_out->status.nickname)); rs_out->status.is_valid = n_valid > n_statuses/2; rs_out->status.is_running = n_running > n_recent/2; + rs_out->status.is_exit = n_exit > n_statuses/2; + rs_out->status.is_fast = n_fast > n_statuses/2; + rs_out->status.is_stable = n_stable > n_statuses/2; + rs_out->status.is_v2_dir = n_v2_dir > n_statuses/2; } SMARTLIST_FOREACH(routerstatus_list, local_routerstatus_t *, rs, local_routerstatus_free(rs)); |