diff options
author | Karsten Loesing <karsten.loesing@gmx.net> | 2009-08-20 18:45:03 +0200 |
---|---|---|
committer | Roger Dingledine <arma@torproject.org> | 2009-08-26 20:15:47 -0400 |
commit | 889c07f1fc54b5bd60c7919f8a5fc784eed2d57a (patch) | |
tree | 92850567ed6d9fd7264912470cf5b20c7360681e /src/or/routerparse.c | |
parent | b2b25cf3a2d5db6c7c1da37923c34805dcd1dc21 (diff) | |
download | tor-889c07f1fc54b5bd60c7919f8a5fc784eed2d57a.tar.gz tor-889c07f1fc54b5bd60c7919f8a5fc784eed2d57a.zip |
When Tor fails to parse a descriptor of any kind, dump it to disk.
Diffstat (limited to 'src/or/routerparse.c')
-rw-r--r-- | src/or/routerparse.c | 50 |
1 files changed, 44 insertions, 6 deletions
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; |