From 7a6f3cd223a34b76b7bc183f0465fcfdddc405b2 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 8 Jun 2007 18:41:09 +0000 Subject: [PATCH] r13313@catbus: nickm | 2007-06-08 14:23:11 -0400 Refactor v3 vote generation code into "build a networkstatus_vote_t" and "format a networkstatus_vote_t". This should make testing possible. svn:r10533 --- src/or/dirserv.c | 580 +++++++++++++++++++++++++++++++------------ src/or/dirvote.c | 60 +++-- src/or/or.h | 6 +- src/or/routerparse.c | 33 +-- 4 files changed, 485 insertions(+), 194 deletions(-) diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 6852984c43..f2daa7890a 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1556,11 +1556,31 @@ dirserv_compute_performance_thresholds(routerlist_t *rl) smartlist_free(bandwidths_excluding_exits); } +/** DOCDOC */ +static char * +version_from_platform(const char *platform) +{ + if (platform && !strcmpstart(platform, "Tor ")) { + const char *eos = find_whitespace(platform+4); + if (eos && !strcmpstart(eos, " (r")) { + /* XXXX020 Unify this logic with the other version extraction + * logic */ + eos = find_whitespace(eos+1); + } + if (eos) { + return tor_strndup(platform, eos-platform); + } + } + return NULL; +} + + /** Helper: write the router-status information in rs into buf, * which has at least buf_len free characters. Do NUL-termination. * Use the same format as in network-status documents. If platform is * non-NULL, add a "v" line for the platform. Return 0 on success, -1 on - * failure. */ + * failure. + * DOCDOC new arguments */ int routerstatus_format_entry(char *buf, size_t buf_len, routerstatus_t *rs, const char *platform, @@ -1569,6 +1589,7 @@ routerstatus_format_entry(char *buf, size_t buf_len, int r; struct in_addr in; char *cp; + char *v; int f_authority; char published[ISO_TIME_LEN+1]; @@ -1617,25 +1638,14 @@ routerstatus_format_entry(char *buf, size_t buf_len, log_warn(LD_BUG, "Not enough space in buffer."); return -1; } - if (platform && !strcmpstart(platform, "Tor ")) { - const char *eos = find_whitespace(platform+4); - if (eos && !strcmpstart(eos, " (r")) { - /* XXXX020 Unify this logic with the other version extraction - * logic */ - eos = find_whitespace(eos+1); - } - if (eos) { - char *p = tor_strndup(platform, eos-platform); - size_t ln = strlen(buf); - buf += ln; - buf_len -= ln; - if (tor_snprintf(buf, buf_len, "opt v %s\n", p)<0) { - tor_free(p); - log_warn(LD_BUG, "Unable to print router version."); - return -1; - } - tor_free(p); + + if (platform && (v = version_from_platform(platform))) { + if (tor_snprintf(buf, buf_len, "opt v %s\n", v)<0) { + tor_free(v); + log_warn(LD_BUG, "Unable to print router version."); + return -1; } + tor_free(v); } return 0; @@ -1652,6 +1662,379 @@ _compare_routerinfo_by_id_digest(const void **a, const void **b) DIGEST_LEN); } +/** DOCDOC */ +static void +set_routerstatus_from_routerinfo(routerstatus_t *rs, + routerinfo_t *ri, time_t now, + int naming, int exits_can_be_guards, + int listbadexits) +{ + int unstable_version = + tor_version_as_new_as(ri->platform,"0.1.1.10-alpha") && + !tor_version_as_new_as(ri->platform,"0.1.1.16-rc-cvs"); + memset(rs, 0, sizeof(routerstatus_t)); + + /* Already set by compute_performance_thresholds. */ + rs->is_exit = ri->is_exit; + rs->is_stable = ri->is_stable = + router_is_active(ri, now) && + !dirserv_thinks_router_is_unreliable(now, ri, 1, 0) && + !unstable_version; + rs->is_fast = ri->is_fast = + router_is_active(ri, now) && + !dirserv_thinks_router_is_unreliable(now, ri, 0, 1); + rs->is_running = ri->is_running; /* computed above */ + /* + int f_authority = router_digest_is_trusted_dir( + ri->cache_info.identity_digest); + */ + rs->is_named = naming && ri->is_named; + rs->is_valid = ri->is_valid; + rs->is_possible_guard = rs->is_fast && rs->is_stable && + (!rs->is_exit || exits_can_be_guards) && + router_get_advertised_bandwidth(ri) >= + (exits_can_be_guards ? guard_bandwidth_including_exits : + guard_bandwidth_excluding_exits); + rs->is_bad_exit = listbadexits && ri->is_bad_exit; + /* 0.1.1.9-alpha is the first version to support fetch by descriptor + * hash. */ + rs->is_v2_dir = ri->dir_port && + tor_version_as_new_as(ri->platform,"0.1.1.9-alpha"); + + if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME)) + rs->is_named = 0; + + rs->published_on = ri->cache_info.published_on; + memcpy(rs->identity_digest, ri->cache_info.identity_digest, DIGEST_LEN); + memcpy(rs->descriptor_digest, ri->cache_info.signed_descriptor_digest, + DIGEST_LEN); + rs->addr = ri->addr; + strlcpy(rs->nickname, ri->nickname, sizeof(rs->nickname)); + rs->or_port = ri->or_port; + rs->dir_port = ri->dir_port; +} + +/** DOCDOC */ +static networkstatus_vote_t * +generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, + authority_cert_t *cert) +{ + or_options_t *options = get_options(); + networkstatus_vote_t *v3_out = NULL; + uint32_t addr; + char *hostname = NULL, *client_versions = NULL, *server_versions = NULL; + const char *contact; + smartlist_t *routers, *routerstatuses; + char identity_digest[DIGEST_LEN]; + char signing_key_digest[DIGEST_LEN]; + int naming = options->NamingAuthoritativeDir; + int listbadexits = options->AuthDirListBadExits; + int exits_can_be_guards; + routerlist_t *rl = router_get_routerlist(); + time_t now = time(NULL); + time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH; + networkstatus_voter_info_t *voter = NULL; + + /* check that everything is deallocated XXXX020 */ + + tor_assert(private_key); + tor_assert(cert); + + if (resolve_my_address(LOG_WARN, options, &addr, &hostname)<0) { + log_warn(LD_NET, "Couldn't resolve my hostname"); + return NULL; + } + if (crypto_pk_get_digest(private_key, signing_key_digest)<0) { + log_err(LD_BUG, "Error computing signing key digest"); + return NULL; + } + if (crypto_pk_get_digest(cert->identity_key, identity_digest)<0) { + log_err(LD_BUG, "Error computing identity key digest"); + return NULL; + } + + if (options->VersioningAuthoritativeDir) { + client_versions = format_versions_list(options->RecommendedClientVersions); + server_versions = format_versions_list(options->RecommendedServerVersions); + } + + contact = get_options()->ContactInfo; + if (!contact) + contact = "(none)"; + + /* precompute this part, since we need it to decide what "stable" + * means. */ + SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, { + ri->is_running = dirserv_thinks_router_is_reachable(ri, now); + }); + + dirserv_compute_performance_thresholds(rl); + + /* XXXX We should take steps to keep this from oscillating if + * total_exit_bandwidth is close to total_bandwidth/3. */ + exits_can_be_guards = total_exit_bandwidth >= (total_bandwidth / 3); + + routers = smartlist_create(); + smartlist_add_all(routers, rl->routers); + smartlist_sort(routers, _compare_routerinfo_by_id_digest); + + routerstatuses = smartlist_create(); + + SMARTLIST_FOREACH(routers, routerinfo_t *, ri, { + if (ri->cache_info.published_on >= cutoff) { + routerstatus_t *rs; + vote_routerstatus_t *vrs; + + vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); + rs = &vrs->status; + set_routerstatus_from_routerinfo(rs, ri, now, + naming, exits_can_be_guards, + listbadexits); + + vrs->version = version_from_platform(ri->platform); + smartlist_add(routerstatuses, vrs); + } + }); + smartlist_free(routers); + + tor_assert(v3_out); + memset(v3_out, 0, sizeof(networkstatus_vote_t)); + v3_out->is_vote = 1; + v3_out->published = time(NULL); + v3_out->valid_after = time(NULL); /* XXXX020 not right. */ + v3_out->fresh_until = time(NULL); /* XXXX020 not right. */ + v3_out->valid_until = time(NULL); /* XXXX020 not right. */ + v3_out->vote_seconds = 600; /* XXXX020 not right. */ + v3_out->dist_seconds = 600; /* XXXX020 not right. */ + + v3_out->client_versions = client_versions; + v3_out->server_versions = server_versions; + v3_out->known_flags = smartlist_create(); + smartlist_split_string(v3_out->known_flags, + "Authority Exit Fast Guard Running Stable Valid V2Dir", + 0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + if (listbadexits) + smartlist_add(v3_out->known_flags, tor_strdup("BadExit")); + if (naming) + smartlist_add(v3_out->known_flags, tor_strdup("Named")); + smartlist_sort_strings(v3_out->known_flags); + + voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t)); + voter->nickname = tor_strdup(options->Nickname); + memcpy(voter->identity_digest, identity_digest, DIGEST_LEN); + voter->address = hostname; + voter->addr = addr; + voter->dir_port = options->DirPort; + voter->or_port = options->ORPort; + voter->contact = tor_strdup(contact); + memcpy(voter->signing_key_digest, signing_key_digest, DIGEST_LEN); + v3_out->voters = smartlist_create(); + smartlist_add(v3_out->voters, voter); + v3_out->cert = authority_cert_dup(cert); + /* ????? networkstatus_digest is unset. */ + v3_out->routerstatus_list = routerstatuses; + + return v3_out; +} + +static char * +format_networkstatus_vote(crypto_pk_env_t *private_key, + networkstatus_vote_t *v3_ns) +{ +/** Longest status flag name that we generate. */ +#define LONGEST_STATUS_FLAG_NAME_LEN 9 +/** Maximum number of status flags we'll apply to one router. */ +#define N_STATUS_FLAGS 10 +/** Amount of space to allocate for each entry. (r line and s line.) */ +#define RS_ENTRY_LEN \ + ( /* first line */ \ + MAX_NICKNAME_LEN+BASE64_DIGEST_LEN*2+ISO_TIME_LEN+INET_NTOA_BUF_LEN+ \ + 5*2 /* ports */ + 10 /* punctuation */ + \ + /* second line */ \ + (LONGEST_STATUS_FLAG_NAME_LEN+1)*N_STATUS_FLAGS + 2) + + size_t len; + char *status = NULL, *client_versions = NULL, *server_versions = NULL; + char *outp, *endp; + // or_options_t *options = get_options(); + char fingerprint[FINGERPRINT_LEN+1]; + char ipaddr[INET_NTOA_BUF_LEN]; + char digest[DIGEST_LEN]; + struct in_addr in; + uint32_t addr; + routerlist_t *rl = router_get_routerlist(); + // time_t now = time(NULL); + // time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH; + /* + int naming = options->NamingAuthoritativeDir; + int listbadexits = options->AuthDirListBadExits; + int exits_can_be_guards; + */ + char *version_lines = NULL; + networkstatus_voter_info_t *voter; + /* XXX check that everything gets freed */ + + tor_assert(private_key); + + voter = smartlist_get(v3_ns->voters, 0); + + addr = voter->addr; + in.s_addr = htonl(addr); + tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr)); + + base16_encode(fingerprint, sizeof(fingerprint), + v3_ns->cert->cache_info.identity_digest, DIGEST_LEN); + client_versions = v3_ns->client_versions; + server_versions = v3_ns->server_versions; + + if (client_versions || server_versions) { + size_t v_len = 64; + char *cp; + if (client_versions) + v_len += strlen(client_versions); + if (client_versions) + v_len += strlen(server_versions); + version_lines = tor_malloc(v_len); + cp = version_lines; + if (client_versions) { + tor_snprintf(cp, v_len-(cp-version_lines), + "client-versions %s\n", client_versions); + cp += strlen(cp); + } + if (server_versions) + tor_snprintf(cp, v_len-(cp-version_lines), + "server-versions %s\n", server_versions); + } else { + version_lines = tor_strdup(""); + } + + len = 8192; + len += strlen(version_lines); + len += (RS_ENTRY_LEN)*smartlist_len(rl->routers); + len += v3_ns->cert->cache_info.signed_descriptor_len; + + status = tor_malloc(len); + { + char published[ISO_TIME_LEN+1]; + char va[ISO_TIME_LEN+1]; + char fu[ISO_TIME_LEN+1]; + char vu[ISO_TIME_LEN+1]; + char *flags = smartlist_join_strings(v3_ns->known_flags, " ", 0, NULL); + authority_cert_t *cert = v3_ns->cert; + format_iso_time(published, v3_ns->published); + format_iso_time(va, v3_ns->valid_after); + format_iso_time(fu, v3_ns->fresh_until); + format_iso_time(vu, v3_ns->valid_until); + + tor_assert(cert); + tor_snprintf(status, len, + "network-status-version 3\n" + "vote-status vote\n" + "published %s\n" + "valid-after %s\n" + "fresh-until %s\n" + "valid-until %s\n" + "%s" /* versions */ + "known-flags %s" + "dir-source %s %s %s %s %d %d\n" + "contact %s\n", + published, va, fu, vu, + version_lines, + flags, + voter->nickname, fingerprint, voter->address, + ipaddr, voter->dir_port, voter->or_port, voter->contact); + + tor_free(flags); + outp = status + strlen(status); + endp = status + len; + tor_assert(outp + cert->cache_info.signed_descriptor_len < endp); + memcpy(outp, cert->cache_info.signed_descriptor_body, + cert->cache_info.signed_descriptor_len); + + outp += cert->cache_info.signed_descriptor_len; + } + + SMARTLIST_FOREACH(v3_ns->routerstatus_list, vote_routerstatus_t *, vrs, + { + /* XXXX020 ri->platform!!!. Also, version-from-platform. */ + if (routerstatus_format_entry(outp, endp-outp, &vrs->status, + vrs->version, 0) < 0) { + log_warn(LD_BUG, "Unable to print router status."); + goto err; + } + outp += strlen(outp); + }); + + { + char signing_key_fingerprint[FINGERPRINT_LEN+1]; + if (tor_snprintf(outp, endp-outp, "directory-signature ")<0) { + log_warn(LD_BUG, "Unable to start signature line."); + goto err; + } + outp += strlen(outp); + + if (crypto_pk_get_fingerprint(private_key, signing_key_fingerprint, 0)<0) { + log_warn(LD_BUG, "Unable to get fingerprint for signing key"); + goto err; + } + if (tor_snprintf(outp, endp-outp, "%s %s\n", fingerprint, + signing_key_fingerprint)<0) { + log_warn(LD_BUG, "Unable to end signature line."); + goto err; + } + outp += strlen(outp); + } + + note_crypto_pk_op(SIGN_DIR); + if (router_append_dirobj_signature(outp,endp-outp,digest,private_key)<0) { + log_warn(LD_BUG, "Unable to sign router status."); + goto err; + } + + goto done; + + err: + tor_free(status); + done: + tor_free(version_lines); + return status; +} + +static cached_dir_t * +generate_v3_networkstatus(void) +{ + crypto_pk_env_t *key = get_my_v3_authority_signing_key(); + authority_cert_t *cert = get_my_v3_authority_cert(); + networkstatus_vote_t *ns; + char *status; + time_t now = time(NULL); + + if (!cert || !key) { + log_warn(LD_NET, "Didn't find key/certificate to generate v3 vote"); + return NULL; + } + + if (!(ns = generate_networkstatus_vote_obj(key, cert))) + return NULL; + + status = format_networkstatus_vote(key, ns); + networkstatus_vote_free(ns); + if (!status) + return NULL; + + { + cached_dir_t **ns_ptr = + &the_v3_networkstatus_vote; + if (*ns_ptr) + cached_dir_decref(*ns_ptr); + *ns_ptr = new_cached_dir(status, now); + status = NULL; /* So it doesn't get double-freed. */ + router_set_networkstatus((*ns_ptr)->dir, now, NS_GENERATED, NULL); + } + + return the_v3_networkstatus_vote; +} + /** For v2 and v3 authoritative directories only: If v2 is set, replace * the contents of the_v2_networkstatus with a newly generated network * status object. If v2 is zero, replace the contents of @@ -1693,20 +2076,13 @@ generate_networkstatus_opinion(int v2) int listbadexits = options->AuthDirListBadExits; int exits_can_be_guards; const char *contact; - authority_cert_t *cert = NULL; char *version_lines = NULL; smartlist_t *routers = NULL; - if (v2) { - private_key = get_identity_key(); - } else { - private_key = get_my_v3_authority_signing_key(); - cert = get_my_v3_authority_cert(); - if (!private_key || !cert) { - log_warn(LD_NET, "Didn't find key/certificate to generate v3 vote"); - goto done; - } - } + if (!v2) + return generate_v3_networkstatus(); + + private_key = get_identity_key(); if (resolve_my_address(LOG_WARN, options, &addr, &hostname)<0) { log_warn(LD_NET, "Couldn't resolve my hostname"); @@ -1726,14 +2102,9 @@ generate_networkstatus_opinion(int v2) goto done; } - if (v2) { - if (crypto_pk_get_fingerprint(private_key, fingerprint, 0)<0) { - log_err(LD_BUG, "Error computing fingerprint"); - goto done; - } - } else { - base16_encode(fingerprint, sizeof(fingerprint), - cert->cache_info.identity_digest, DIGEST_LEN); + if (crypto_pk_get_fingerprint(private_key, fingerprint, 0)<0) { + log_err(LD_BUG, "Error computing fingerprint"); + goto done; } contact = get_options()->ContactInfo; @@ -1753,13 +2124,9 @@ generate_networkstatus_opinion(int v2) len = 4096+strlen(client_versions)+strlen(server_versions); len += identity_pkey_len*2; len += (RS_ENTRY_LEN)*smartlist_len(rl->routers); - if (!v2) { - len += cert->cache_info.signed_descriptor_len; - } status = tor_malloc(len); - if (v2) { - tor_snprintf(status, len, + tor_snprintf(status, len, "network-status-version 2\n" "dir-source %s %s %d\n" "fingerprint %s\n" @@ -1777,38 +2144,8 @@ generate_networkstatus_opinion(int v2) versioning ? " Versions" : "", version_lines, identity_pkey); - outp = status + strlen(status); - endp = status + len; - } else { - tor_snprintf(status, len, - "network-status-version 3\n" - "vote-status vote\n" - "published %s\n" - "valid-after %s\n" - "fresh-until %s\n" - "valid-until %s\n" - "%s" /* versions */ - "known-flags Authority%s Exit Fast Guard%s Running Stable " - "Valid V2Dir\n" - "dir-source %s %s %s %s %d %d\n" - "contact %s\n", - published, - published, /* XXXX020 should be valid-after*/ - published, /* XXXX020 should be fresh-until*/ - published, /* XXXX020 should be valid-until*/ - version_lines, - listbadexits ? " BadExit" : "", - naming ? " Named" : "", - options->Nickname, fingerprint, options->Address, - ipaddr, (int)options->DirPort, (int)options->ORPort, - contact); - outp = status + strlen(status); - endp = status + len; - tor_assert(outp + cert->cache_info.signed_descriptor_len < endp); - memcpy(outp, cert->cache_info.signed_descriptor_body, - cert->cache_info.signed_descriptor_len); - outp += cert->cache_info.signed_descriptor_len; - } + outp = status + strlen(status); + endp = status + len; /* precompute this part, since we need it to decide what "stable" * means. */ @@ -1830,51 +2167,10 @@ generate_networkstatus_opinion(int v2) if (ri->cache_info.published_on >= cutoff) { routerstatus_t rs; - /* These versions dump connections with idle live circuits - sometimes. D'oh!*/ - int unstable_version = - tor_version_as_new_as(ri->platform,"0.1.1.10-alpha") && - !tor_version_as_new_as(ri->platform,"0.1.1.16-rc-cvs"); - memset(&rs, 0, sizeof(rs)); - - /* Already set by compute_performance_thresholds. */ - rs.is_exit = ri->is_exit; - rs.is_stable = ri->is_stable = - router_is_active(ri, now) && - !dirserv_thinks_router_is_unreliable(now, ri, 1, 0) && - !unstable_version; - rs.is_fast = ri->is_fast = - router_is_active(ri, now) && - !dirserv_thinks_router_is_unreliable(now, ri, 0, 1); - rs.is_running = ri->is_running; /* computed above */ - /* - int f_authority = router_digest_is_trusted_dir( - ri->cache_info.identity_digest); - */ - rs.is_named = naming && ri->is_named; - rs.is_valid = ri->is_valid; - rs.is_possible_guard = rs.is_fast && rs.is_stable && - (!rs.is_exit || exits_can_be_guards) && - router_get_advertised_bandwidth(ri) >= - (exits_can_be_guards ? guard_bandwidth_including_exits : - guard_bandwidth_excluding_exits); - rs.is_bad_exit = listbadexits && ri->is_bad_exit; - /* 0.1.1.9-alpha is the first version to support fetch by descriptor - * hash. */ - rs.is_v2_dir = ri->dir_port && - tor_version_as_new_as(ri->platform,"0.1.1.9-alpha"); - - if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME)) - rs.is_named = 0; - - rs.published_on = ri->cache_info.published_on; - memcpy(rs.identity_digest, ri->cache_info.identity_digest, DIGEST_LEN); - memcpy(rs.descriptor_digest, ri->cache_info.signed_descriptor_digest, - DIGEST_LEN); - rs.addr = ri->addr; - strlcpy(rs.nickname, ri->nickname, sizeof(rs.nickname)); - rs.or_port = ri->or_port; - rs.dir_port = ri->dir_port; + + set_routerstatus_from_routerinfo(&rs, ri, now, + naming, exits_can_be_guards, + listbadexits); if (routerstatus_format_entry(outp, endp-outp, &rs, ri->platform, 0) < 0) { @@ -1885,36 +2181,16 @@ generate_networkstatus_opinion(int v2) } }); - if (v2) { - if (tor_snprintf(outp, endp-outp, "directory-signature %s\n", - get_options()->Nickname)<0) { - log_warn(LD_BUG, "Unable to write signature line."); - goto done; - } - if (router_get_networkstatus_v2_hash(status, digest)<0) { - log_warn(LD_BUG, "Unable to hash network status"); - goto done; - } - outp += strlen(outp); - } else { - char signing_key_fingerprint[FINGERPRINT_LEN+1]; - if (tor_snprintf(outp, endp-outp, "directory-signature ")<0) { - log_warn(LD_BUG, "Unable to start signature line."); - goto done; - } - outp += strlen(outp); - - if (crypto_pk_get_fingerprint(private_key, signing_key_fingerprint, 0)<0) { - log_warn(LD_BUG, "Unable to get fingerprint for signing key"); - goto done; - } - if (tor_snprintf(outp, endp-outp, "%s %s\n", fingerprint, - signing_key_fingerprint)<0) { - log_warn(LD_BUG, "Unable to end signature line."); - goto done; - } - outp += strlen(outp); + if (tor_snprintf(outp, endp-outp, "directory-signature %s\n", + get_options()->Nickname)<0) { + log_warn(LD_BUG, "Unable to write signature line."); + goto done; + } + if (router_get_networkstatus_v2_hash(status, digest)<0) { + log_warn(LD_BUG, "Unable to hash network status"); + goto done; } + outp += strlen(outp); note_crypto_pk_op(SIGN_DIR); if (router_append_dirobj_signature(outp,endp-outp,digest,private_key)<0) { @@ -1923,14 +2199,12 @@ generate_networkstatus_opinion(int v2) } { - cached_dir_t **ns_ptr = - v2 ? &the_v2_networkstatus : &the_v3_networkstatus_vote; + cached_dir_t **ns_ptr = &the_v2_networkstatus; if (*ns_ptr) cached_dir_decref(*ns_ptr); *ns_ptr = new_cached_dir(status, now); status = NULL; /* So it doesn't get double-freed. */ - if (v2) - the_v2_networkstatus_is_dirty = 0; + the_v2_networkstatus_is_dirty = 0; router_set_networkstatus((*ns_ptr)->dir, now, NS_GENERATED, NULL); r = *ns_ptr; } diff --git a/src/or/dirvote.c b/src/or/dirvote.c index bfdafbd512..42e13a7d91 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -15,16 +15,14 @@ const char dirvote_c_id[] = void networkstatus_vote_free(networkstatus_vote_t *ns) { - int i; if (!ns) return; tor_free(ns->client_versions); tor_free(ns->server_versions); if (ns->known_flags) { - for (i=0; ns->known_flags[i]; ++i) - tor_free(ns->known_flags[i]); - tor_free(ns->known_flags); + SMARTLIST_FOREACH(ns->known_flags, char *, c, tor_free(c)); + smartlist_free(ns->known_flags); } if (ns->voters) { SMARTLIST_FOREACH(ns->voters, networkstatus_voter_info_t *, voter, @@ -317,8 +315,8 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_add_all(combined_server_versions, sv); smartlist_free(sv); /* elements get freed later. */ } - for (j=0; v->known_flags[j]; ++j) - smartlist_add(flags, tor_strdup(v->known_flags[j])); + SMARTLIST_FOREACH(v->known_flags, const char *, cp, + smartlist_add(flags, tor_strdup(cp))); }); valid_after = median_time(va_times); fresh_until = median_time(fu_times); @@ -444,18 +442,18 @@ networkstatus_compute_consensus(smartlist_t *votes, named_flag[i] = -1; SMARTLIST_FOREACH(votes, networkstatus_vote_t *, v, { - for (i = 0; v->known_flags[i]; ++i) { - int p = smartlist_string_pos(flags, v->known_flags[i]); + SMARTLIST_FOREACH(v->known_flags, const char *, fl, + { + int p = smartlist_string_pos(flags, fl); tor_assert(p >= 0); - flag_map[v_sl_idx][i] = p; + flag_map[v_sl_idx][fl_sl_idx] = p; ++n_flag_voters[p]; - if (!strcmp(v->known_flags[i], "Named")) - named_flag[v_sl_idx] = i; + if (!strcmp(fl, "Named")) + named_flag[v_sl_idx] = fl_sl_idx; /* XXXX020 somebody needs to make sure that there are no duplicate * entries in anybody's flag list. */ - } - tor_assert(!v->known_flags[i]); - n_voter_flags[v_sl_idx] = i; + }); + n_voter_flags[v_sl_idx] = smartlist_len(v->known_flags); size[v_sl_idx] = smartlist_len(v->routerstatus_list); }); @@ -691,3 +689,37 @@ networkstatus_check_consensus_signature(networkstatus_vote_t *consensus) return 0; } +/** Free storage held in cert. */ +void +authority_cert_free(authority_cert_t *cert) +{ + if (!cert) + return; + + tor_free(cert->cache_info.signed_descriptor_body); + if (cert->signing_key) + crypto_free_pk_env(cert->signing_key); + if (cert->identity_key) + crypto_free_pk_env(cert->identity_key); + + tor_free(cert); +} + +/** DOCDOC */ +authority_cert_t * +authority_cert_dup(authority_cert_t *cert) +{ + authority_cert_t *out = tor_malloc(sizeof(authority_cert_t)); + tor_assert(cert); + + memcpy(out, cert, sizeof(authority_cert_t)); + /* Now copy pointed-to things. */ + out->cache_info.signed_descriptor_body = + tor_strndup(cert->cache_info.signed_descriptor_body, + cert->cache_info.signed_descriptor_len); + out->cache_info.saved_location = SAVED_NOWHERE; + out->identity_key = crypto_pk_dup_key(cert->identity_key); + out->signing_key = crypto_pk_dup_key(cert->signing_key); + + return out; +} diff --git a/src/or/or.h b/src/or/or.h index 36bc9f21fd..be47e211d7 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1333,7 +1333,7 @@ typedef struct networkstatus_vote_t { char *client_versions; char *server_versions; - char **known_flags; /* NULL-terminated */ + smartlist_t *known_flags; smartlist_t *voters; /* list of networkstatus_voter_info_t */ @@ -2743,6 +2743,9 @@ networkstatus_voter_info_t *networkstatus_get_voter_by_id( const char *identity); int networkstatus_check_consensus_signature(networkstatus_vote_t *consensus); +void authority_cert_free(authority_cert_t *cert); +authority_cert_t *authority_cert_dup(authority_cert_t *cert); + /********************************* dns.c ***************************/ int dns_init(void); @@ -3410,7 +3413,6 @@ networkstatus_t *networkstatus_parse_from_string(const char *s); networkstatus_vote_t *networkstatus_parse_vote_from_string(const char *s, int is_vote); -void authority_cert_free(authority_cert_t *cert); authority_cert_t *authority_cert_parse_from_string(const char *s, const char **end_of_string); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index be984d2634..e5645787c1 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -1287,22 +1287,6 @@ extrainfo_parse_entry_from_string(const char *s, const char *end, return extrainfo; } -/** Free storage held in cert. */ -void -authority_cert_free(authority_cert_t *cert) -{ - if (!cert) - return; - - tor_free(cert->cache_info.signed_descriptor_body); - if (cert->signing_key) - crypto_free_pk_env(cert->signing_key); - if (cert->identity_key) - crypto_free_pk_env(cert->identity_key); - - tor_free(cert); -} - /** Parse a key certificate from s; point end-of-string to * the first character after the certificate. */ authority_cert_t * @@ -1515,14 +1499,13 @@ routerstatus_parse_entry_from_string(const char **s, smartlist_t *tokens, tok = find_first_by_keyword(tokens, K_S); if (tok && vote) { - int i, j; + int i; vote_rs->flags = 0; for (i=0; i < tok->n_args; ++i) { - for (j=0; vote->known_flags[j]; ++j) { - if (!strcmp(tok->args[i], vote->known_flags[j])) { - vote_rs->flags |= (1<known_flags, tok->args[i]); + if (p >= 0) { + vote_rs->flags |= (1<known_flags = tor_malloc(sizeof(char*)*(tok->n_args+1)); - memcpy(ns->known_flags, tok->args, sizeof(char*)*(tok->n_args)); - ns->known_flags[tok->n_args] = NULL; + ns->known_flags = smartlist_create(); + for (i = 0; i < tok->n_args; ++i) + smartlist_add(ns->known_flags, tok->args[i]); tok->n_args = 0; /* suppress free of args members, but not of args itself. */ ns->voters = smartlist_create(); -- 2.47.3