summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarsten Loesing <karsten.loesing@gmx.net>2009-08-20 18:45:03 +0200
committerRoger Dingledine <arma@torproject.org>2009-08-26 20:15:47 -0400
commit889c07f1fc54b5bd60c7919f8a5fc784eed2d57a (patch)
tree92850567ed6d9fd7264912470cf5b20c7360681e
parentb2b25cf3a2d5db6c7c1da37923c34805dcd1dc21 (diff)
downloadtor-889c07f1fc54b5bd60c7919f8a5fc784eed2d57a.tar.gz
tor-889c07f1fc54b5bd60c7919f8a5fc784eed2d57a.zip
When Tor fails to parse a descriptor of any kind, dump it to disk.
-rw-r--r--ChangeLog2
-rw-r--r--src/or/routerparse.c50
2 files changed, 46 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index a3d76ca4ce..0182faa581 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -103,6 +103,8 @@ Changes in version 0.2.1.20 - 2009-??-??
- Fix a signed/unsigned compile warning in 0.2.1.19.
- Fix possible segmentation fault on directory authorities. Bugfix on
0.2.1.14-rc.
+ - When Tor fails to parse a descriptor of any kind, dump it to disk.
+ Might help diagnosing bug 1051.
Changes in version 0.2.1.19 - 2009-07-28
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 8fecd9ab47..9e5f37b4bd 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -545,6 +545,34 @@ static int tor_version_same_series(tor_version_t *a, tor_version_t *b);
#define DUMP_AREA(a,name) STMT_NIL
#endif
+/** Last time we dumped a descriptor to disk. */
+static time_t last_desc_dumped = 0;
+
+/** For debugging purposes, dump unparseable descriptor *<b>desc</b> of
+ * type *<b>type</b> to file $DATADIR/unparseable-desc. Do not write more
+ * than one descriptor to disk per minute. If there is already such a
+ * file in the data directory, overwrite it. */
+static void
+dump_desc(const char *desc, const char *type)
+{
+ time_t now = time(NULL);
+ tor_assert(desc);
+ tor_assert(type);
+ if (!last_desc_dumped || last_desc_dumped + 60 < now) {
+ char *debugfile = get_datadir_fname("unparseable-desc");
+ size_t filelen = 50 + strlen(type) + strlen(desc);
+ char *content = tor_malloc_zero(filelen);
+ tor_snprintf(content, filelen, "Unable to parse descriptor of type "
+ "%s:\n%s", type, desc);
+ write_str_to_file(debugfile, content, 0);
+ log_info(LD_DIR, "Unable to parse descriptor of type %s. See file "
+ "unparseable-desc in data directory for details.", type);
+ tor_free(content);
+ tor_free(debugfile);
+ last_desc_dumped = now;
+ }
+}
+
/** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
* <b>s</b>. Return 0 on success, -1 on failure.
*/
@@ -734,7 +762,7 @@ router_parse_directory(const char *str)
char digest[DIGEST_LEN];
time_t published_on;
int r;
- const char *end, *cp;
+ const char *end, *cp, *str_dup = str;
smartlist_t *tokens = NULL;
crypto_pk_env_t *declared_key = NULL;
memarea_t *area = memarea_new();
@@ -807,6 +835,7 @@ router_parse_directory(const char *str)
r = 0;
goto done;
err:
+ dump_desc(str_dup, "v1 directory");
r = -1;
done:
if (declared_key) crypto_free_pk_env(declared_key);
@@ -833,7 +862,7 @@ router_parse_runningrouters(const char *str)
int r = -1;
crypto_pk_env_t *declared_key = NULL;
smartlist_t *tokens = NULL;
- const char *eos = str + strlen(str);
+ const char *eos = str + strlen(str), *str_dup = str;
memarea_t *area = NULL;
if (router_get_runningrouters_hash(str, digest)) {
@@ -874,6 +903,7 @@ router_parse_runningrouters(const char *str)
r = 0;
err:
+ dump_desc(str_dup, "v1 running-routers");
if (declared_key) crypto_free_pk_env(declared_key);
if (tokens) {
SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
@@ -1183,7 +1213,7 @@ router_parse_entry_from_string(const char *s, const char *end,
smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
directory_token_t *tok;
struct in_addr in;
- const char *start_of_annotations, *cp;
+ const char *start_of_annotations, *cp, *s_dup = s;
size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
int ok = 1;
memarea_t *area = NULL;
@@ -1473,6 +1503,7 @@ router_parse_entry_from_string(const char *s, const char *end,
goto done;
err:
+ dump_desc(s_dup, "router descriptor");
routerinfo_free(router);
router = NULL;
done:
@@ -1507,6 +1538,7 @@ extrainfo_parse_entry_from_string(const char *s, const char *end,
crypto_pk_env_t *key = NULL;
routerinfo_t *router = NULL;
memarea_t *area = NULL;
+ const char *s_dup = s;
if (!end) {
end = s + strlen(s);
@@ -1595,6 +1627,7 @@ extrainfo_parse_entry_from_string(const char *s, const char *end,
goto done;
err:
+ dump_desc(s_dup, "extra-info descriptor");
if (extrainfo)
extrainfo_free(extrainfo);
extrainfo = NULL;
@@ -1624,6 +1657,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string)
size_t len;
int found;
memarea_t *area = NULL;
+ const char *s_dup = s;
s = eat_whitespace(s);
eos = strstr(s, "\ndir-key-certification");
@@ -1777,6 +1811,7 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string)
}
return cert;
err:
+ dump_desc(s_dup, "authority cert");
authority_cert_free(cert);
SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
smartlist_free(tokens);
@@ -1827,7 +1862,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
vote_routerstatus_t *vote_rs,
int consensus_method)
{
- const char *eos;
+ const char *eos, *s_dup = *s;
routerstatus_t *rs = NULL;
directory_token_t *tok;
char timebuf[ISO_TIME_LEN+1];
@@ -2010,6 +2045,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
goto done;
err:
+ dump_desc(s_dup, "routerstatus entry");
if (rs && !vote_rs)
routerstatus_free(rs);
rs = NULL;
@@ -2051,7 +2087,7 @@ _free_duplicate_routerstatus_entry(void *e)
networkstatus_v2_t *
networkstatus_v2_parse_from_string(const char *s)
{
- const char *eos;
+ const char *eos, *s_dup = s;
smartlist_t *tokens = smartlist_create();
smartlist_t *footer_tokens = smartlist_create();
networkstatus_v2_t *ns = NULL;
@@ -2200,6 +2236,7 @@ networkstatus_v2_parse_from_string(const char *s)
goto done;
err:
+ dump_desc(s_dup, "v2 networkstatus");
if (ns)
networkstatus_v2_free(ns);
ns = NULL;
@@ -2226,7 +2263,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
networkstatus_voter_info_t *voter = NULL;
networkstatus_t *ns = NULL;
char ns_digest[DIGEST_LEN];
- const char *cert, *end_of_header, *end_of_footer;
+ const char *cert, *end_of_header, *end_of_footer, *s_dup = s;
directory_token_t *tok;
int ok;
struct in_addr in;
@@ -2584,6 +2621,7 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
goto done;
err:
+ dump_desc(s_dup, "v3 networkstatus");
if (ns)
networkstatus_vote_free(ns);
ns = NULL;