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
This commit is contained in:
Nick Mathewson 2007-06-08 18:41:09 +00:00
parent e766814903
commit 7a6f3cd223
4 changed files with 484 additions and 193 deletions

View File

@ -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 <b>rs</b> into <b>buf</b>,
* which has at least <b>buf_len</b> free characters. Do NUL-termination.
* Use the same format as in network-status documents. If <b>platform</b> 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 <b>v2</b> is set, replace
* the contents of <b>the_v2_networkstatus</b> with a newly generated network
* status object. If <b>v2</b> 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;
}

View File

@ -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 <b>cert</b>. */
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;
}

View File

@ -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);

View File

@ -1287,22 +1287,6 @@ extrainfo_parse_entry_from_string(const char *s, const char *end,
return extrainfo;
}
/** Free storage held in <b>cert</b>. */
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 <b>s</b>; point <b>end-of-string</b> 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<<j);
break;
}
int p = smartlist_string_pos(vote->known_flags, tok->args[i]);
if (p >= 0) {
vote_rs->flags |= (1<<p);
break;
}
}
} else if (tok) {
@ -1869,9 +1852,9 @@ networkstatus_parse_vote_from_string(const char *s, int is_vote)
}
tok = find_first_by_keyword(tokens, K_KNOWN_FLAGS);
ns->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();