diff options
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | doc/TODO | 6 | ||||
-rw-r--r-- | doc/dir-spec.txt | 6 | ||||
-rw-r--r-- | src/or/dirserv.c | 29 | ||||
-rw-r--r-- | src/or/or.h | 10 | ||||
-rw-r--r-- | src/or/routerlist.c | 11 | ||||
-rw-r--r-- | src/or/routerparse.c | 4 |
7 files changed, 62 insertions, 6 deletions
@@ -76,6 +76,8 @@ Changes in version 0.1.2.5-alpha - 2007-01-03 - When we change nameservers or IP addresses, reset and re-launch our tests for DNS hijacking. - Block an obscure DoS attack from directory caches. + - Add a BadDirectory flag to network status docs so that authorities + can (eventually) tell clients about caches they believe to be broken. o Security bugfixes: - Stop sending the HttpProxyAuthenticator string to directory @@ -86,7 +86,7 @@ N - DNS improvements D But eventually, we give up after getting a lot of 503s. D Delay when we get a lot of 503s, rather than punting onto the servers that have given us 503s? -N - Add a 'BadDirectory' flag to statuses. + o Add a 'BadDirectory' flag to statuses. - authorities should *never* 503 a cache, and should never 503 network status requests. They can 503 client descriptor requests when they feel like it. @@ -136,8 +136,8 @@ R - "bandwidth classes", for incoming vs initiated-here conns, and to give dir conns lower priority. . Write limiting; separate token bucket for write o preemptively give a 503 to some v1 dir requests - - preemptively give a 503 to some v2 dir requests - - Write function to estimate bytes needed for N descriptors +R - preemptively give a 503 to some v2 dir requests + o Write function to estimate bytes needed for N descriptors statuses D per-conn write buckets D separate config options for read vs write limiting diff --git a/doc/dir-spec.txt b/doc/dir-spec.txt index 93d5d2dc06..1d4781dde7 100644 --- a/doc/dir-spec.txt +++ b/doc/dir-spec.txt @@ -347,6 +347,8 @@ $Id$ "Versions" if this directory authority recommends software versions. "BadExits" if the directory authority flags nodes that it believes are performing incorrectly as exit nodes. + "BadDirectories" if the directory authority flags nodes that it + believes are performing incorrectly as directory caches. The dir-options entry is optional. The "-versions" entries are required if the "Versions" flag is present. The other entries are required and must @@ -376,6 +378,10 @@ $Id$ "BadExit" if the router is believed to be useless as an exit node (because its ISP censors it, because it is behind a restrictive proxy, or for some similar reason). + "BadDirectory" if the router is believed to be useless as a + directory cache (because its directory port isn't working; + because its bandwidth is always throttled, or for some + similar reason). "Exit" if the router is useful for building general-purpose exit circuits. "Fast" if the router is suitable for high-bandwidth circuits. diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 9ba181572c..12efc03ff4 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1882,6 +1882,35 @@ dirserv_test_reachability(int try_all) ctr = (ctr + 1) % 128; } +/** Return an approximate estimate of the number of bytes that will be needed + * to transmit the server descriptors (if is_serverdescs) or networkstatus + * objects (if !is_serverdescs) listed in <b>fps</b>. If <b>compressed</b> is + * set, we guess how large the data will be after compression. + * + * The return value is an estimate; it might be larger or smaller. + **/ +size_t +dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs, + int compressed) +{ + size_t result; + if (is_serverdescs) { + int n = smartlist_len(fps); + routerinfo_t *me = router_get_my_routerinfo(); + result = (me?me->cache_info.signed_descriptor_len:2048) * n; + if (compressed) + result /= 2; /* observed compressability is between 35 and 55%. */ + } else { + result = 0; + SMARTLIST_FOREACH(fps, const char *, d, { + cached_dir_t *dir = digestmap_get(cached_v2_networkstatus, d); + if (dir) + result += compressed ? dir->dir_z_len : dir->dir_len; + }); + } + return result; +} + /** When we're spooling data onto our outbuf, add more whenever we dip * below this threshold. */ #define DIRSERV_BUFFER_MIN 16384 diff --git a/src/or/or.h b/src/or/or.h index 6292417c7c..08f7aed5bd 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1012,6 +1012,8 @@ typedef struct routerstatus_t { * choice as an entry guard. */ unsigned int is_bad_exit:1; /**< True iff this node is a bad choice for * an exit node. */ + unsigned int is_bad_directory:1; /**< Do we think this directory is junky, + * underpowered, or otherwise useless? */ /** True iff we know version info for this router. (i.e., a "v" entry was * included.) We'll replace all these with a big tor_version_t or a char[] @@ -1081,9 +1083,11 @@ typedef struct networkstatus_t { unsigned int recommends_versions:1; /**< True iff this directory server * recommends client and server software * versions. */ - unsigned int lists_bad_exits:1; /** True iff this directory server marks + unsigned int lists_bad_exits:1; /**< True iff this directory server marks * malfunctioning exits as bad. */ - + /** True iff this directory server marks malfunctioning directories as + * bad. */ + unsigned int lists_bad_directories:1; smartlist_t *entries; /**< List of routerstatus_t*. This list is kept * sorted by identity_digest. */ } networkstatus_t; @@ -2319,6 +2323,8 @@ void dirserv_test_reachability(int try_all); int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, int complain); int dirserv_would_reject_router(routerstatus_t *rs); +size_t dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs, + int compressed); void dirserv_free_all(void); void cached_dir_decref(cached_dir_t *d); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index feae0778e4..ebffadd839 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -546,6 +546,8 @@ router_pick_directory_server_impl(int requireother, int fascistfirewall, int is_overloaded = _local_status->last_dir_503_at + DIR_503_TIMEOUT > now; if (!status->is_running || !status->dir_port || !status->is_valid) continue; + if (status->is_bad_directory) + continue; if (requireother && router_digest_is_me(status->identity_digest)) continue; is_trusted = router_digest_is_trusted_dir(status->identity_digest); @@ -3212,7 +3214,7 @@ routerstatus_list_update_from_networkstatus(time_t now) { or_options_t *options = get_options(); int n_trusted, n_statuses, n_recent = 0, n_naming = 0; - int n_listing_bad_exits = 0; + int n_listing_bad_exits = 0, n_listing_bad_directories = 0; int i, j, warned; int *index, *size; networkstatus_t **networkstatus; @@ -3262,6 +3264,8 @@ routerstatus_list_update_from_networkstatus(time_t now) ++n_recent; if (networkstatus[i]->lists_bad_exits) ++n_listing_bad_exits; + if (networkstatus[i]->lists_bad_directories) + ++n_listing_bad_directories; } /** Iterate over all entries in all networkstatuses, and build @@ -3333,6 +3337,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, n_guard=0, n_bad_exit=0; + int n_bad_directory=0; int n_version_known=0, n_supports_begindir=0; int n_desc_digests=0, highest_count=0; const char *the_name = NULL; @@ -3421,6 +3426,8 @@ routerstatus_list_update_from_networkstatus(time_t now) ++n_v2_dir; if (rs->is_bad_exit) ++n_bad_exit; + if (rs->is_bad_directory) + ++n_bad_directory; if (rs->version_known) ++n_version_known; if (rs->version_supports_begindir) @@ -3475,6 +3482,8 @@ routerstatus_list_update_from_networkstatus(time_t now) rs_out->status.is_stable = n_stable > n_statuses/2; rs_out->status.is_v2_dir = n_v2_dir > n_statuses/2; rs_out->status.is_bad_exit = n_bad_exit > n_listing_bad_exits/2; + rs_out->status.is_bad_directory = + n_bad_directory > n_listing_bad_directories/2; rs_out->status.version_known = n_version_known > 0; rs_out->status.version_supports_begindir = n_supports_begindir > n_version_known/2; diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 611eab08c7..8cd08d6b12 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -1077,6 +1077,8 @@ routerstatus_parse_entry_from_string(const char **s, smartlist_t *tokens) rs->is_possible_guard = 1; else if (!strcmp(tok->args[i], "BadExit")) rs->is_bad_exit = 1; + else if (!strcmp(tok->args[i], "BadDirectory")) + rs->is_bad_directory = 1; } } if ((tok = find_first_by_keyword(tokens, K_V))) { @@ -1224,6 +1226,8 @@ networkstatus_parse_from_string(const char *s) ns->recommends_versions = 1; if (!strcmp(tok->args[i], "BadExits")) ns->lists_bad_exits = 1; + if (!strcmp(tok->args[i], "BadDirectories")) + ns->lists_bad_directories = 1; } } |