summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2007-01-03 19:58:00 +0000
committerNick Mathewson <nickm@torproject.org>2007-01-03 19:58:00 +0000
commit2963d4acc267102e1b2927ed6bbcd0717fbae67e (patch)
tree25a7b9091ce8e207624c040a507ffbf835b0f97a
parent931e555ef9c3d1ec88d1f051cb01c4d09e608876 (diff)
downloadtor-2963d4acc267102e1b2927ed6bbcd0717fbae67e.tar.gz
tor-2963d4acc267102e1b2927ed6bbcd0717fbae67e.zip
r11820@Kushana: nickm | 2007-01-03 14:54:05 -0500
Add (and specify) a BadDirectory flag to networkstatuses, so authorities can tell clients that some caches are broken. Also, implement an as-yet-unused function to estimate how many bytes will be sent on a directory connection. svn:r9255
-rw-r--r--ChangeLog2
-rw-r--r--doc/TODO6
-rw-r--r--doc/dir-spec.txt6
-rw-r--r--src/or/dirserv.c29
-rw-r--r--src/or/or.h10
-rw-r--r--src/or/routerlist.c11
-rw-r--r--src/or/routerparse.c4
7 files changed, 62 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index 98ca8d9ef4..fa0ecbf8ef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/doc/TODO b/doc/TODO
index fc1b363520..7aa67bd39e 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -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;
}
}