summaryrefslogtreecommitdiff
path: root/src/or/dirvote.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/dirvote.c')
-rw-r--r--src/or/dirvote.c362
1 files changed, 173 insertions, 189 deletions
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index a557fc782e..144859ae04 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -1,6 +1,6 @@
/* Copyright (c) 2001-2004, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
- * Copyright (c) 2007-2011, The Tor Project, Inc. */
+ * Copyright (c) 2007-2012, The Tor Project, Inc. */
/* See LICENSE for licensing information */
#define DIRVOTE_PRIVATE
@@ -33,6 +33,7 @@ typedef struct pending_consensus_t {
networkstatus_t *consensus;
} pending_consensus_t;
+/* DOCDOC dirvote_add_signatures_to_all_pending_consensuses */
static int dirvote_add_signatures_to_all_pending_consensuses(
const char *detached_signatures_body,
const char *source,
@@ -53,7 +54,7 @@ static int dirvote_publish_consensus(void);
static char *make_consensus_method_list(int low, int high, const char *sep);
/** The highest consensus method that we currently support. */
-#define MAX_SUPPORTED_CONSENSUS_METHOD 11
+#define MAX_SUPPORTED_CONSENSUS_METHOD 13
/** Lowest consensus method that contains a 'directory-footer' marker */
#define MIN_METHOD_FOR_FOOTER 9
@@ -67,6 +68,14 @@ static char *make_consensus_method_list(int low, int high, const char *sep);
/** Lowest consensus method that generates microdescriptors */
#define MIN_METHOD_FOR_MICRODESC 8
+/** Lowest consensus method that ensures a majority of authorities voted
+ * for a param. */
+#define MIN_METHOD_FOR_MAJORITY_PARAMS 12
+
+/** Lowest consensus method where microdesc consensuses omit any entry
+ * with no microdesc. */
+#define MIN_METHOD_FOR_MANDATORY_MICRODESC 13
+
/* =====
* Voting
* =====*/
@@ -78,7 +87,7 @@ static char *make_consensus_method_list(int low, int high, const char *sep);
* <b>v3_ns</b>, signed with our v3 signing key <b>private_signing_key</b>.
* For v3 authorities. */
char *
-format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
+format_networkstatus_vote(crypto_pk_t *private_signing_key,
networkstatus_t *v3_ns)
{
size_t len;
@@ -86,9 +95,7 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
const char *client_versions = NULL, *server_versions = NULL;
char *outp, *endp;
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();
char *version_lines = NULL;
@@ -101,8 +108,6 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_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);
@@ -189,7 +194,8 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
flags,
params,
voter->nickname, fingerprint, voter->address,
- ipaddr, voter->dir_port, voter->or_port, voter->contact);
+ fmt_addr32(addr), voter->dir_port, voter->or_port,
+ voter->contact);
if (r < 0) {
log_err(LD_BUG, "Insufficient memory for network status line");
@@ -370,8 +376,7 @@ get_frequent_members(smartlist_t *out, smartlist_t *in, int min)
{
char *cur = NULL;
int count = 0;
- SMARTLIST_FOREACH(in, char *, cp,
- {
+ SMARTLIST_FOREACH_BEGIN(in, char *, cp) {
if (cur && !strcmp(cp, cur)) {
++count;
} else {
@@ -380,7 +385,7 @@ get_frequent_members(smartlist_t *out, smartlist_t *in, int min)
cur = cp;
count = 1;
}
- });
+ } SMARTLIST_FOREACH_END(cp);
if (count > min)
smartlist_add(out, cur);
}
@@ -443,8 +448,7 @@ compute_routerstatus_consensus(smartlist_t *votes, int consensus_method,
* date cannot tie, we use the descriptor with the smaller digest.
*/
smartlist_sort(votes, _compare_vote_rs);
- SMARTLIST_FOREACH(votes, vote_routerstatus_t *, rs,
- {
+ SMARTLIST_FOREACH_BEGIN(votes, vote_routerstatus_t *, rs) {
if (cur && !compare_vote_rs(cur, rs)) {
++cur_n;
} else {
@@ -458,7 +462,7 @@ compute_routerstatus_consensus(smartlist_t *votes, int consensus_method,
cur_n = 1;
cur = rs;
}
- });
+ } SMARTLIST_FOREACH_END(rs);
if (cur_n > most_n ||
(cur && cur_n == most_n && cur->status.published_on > most_published)) {
@@ -471,7 +475,7 @@ compute_routerstatus_consensus(smartlist_t *votes, int consensus_method,
if (consensus_method >= MIN_METHOD_FOR_MICRODESC &&
microdesc_digest256_out) {
- smartlist_t *digests = smartlist_create();
+ smartlist_t *digests = smartlist_new();
const char *best_microdesc_digest;
SMARTLIST_FOREACH_BEGIN(votes, vote_routerstatus_t *, rs) {
char d[DIGEST256_LEN];
@@ -499,15 +503,15 @@ static void
hash_list_members(char *digest_out, size_t len_out,
smartlist_t *lst, digest_algorithm_t alg)
{
- crypto_digest_env_t *d;
+ crypto_digest_t *d;
if (alg == DIGEST_SHA1)
- d = crypto_new_digest_env();
+ d = crypto_digest_new();
else
- d = crypto_new_digest256_env(alg);
+ d = crypto_digest256_new(alg);
SMARTLIST_FOREACH(lst, const char *, cp,
crypto_digest_add_bytes(d, cp, strlen(cp)));
crypto_digest_get_digest(d, digest_out, len_out);
- crypto_free_digest_env(d);
+ crypto_digest_free(d);
}
/** Sorting helper: compare two strings based on their values as base-ten
@@ -535,9 +539,9 @@ _cmp_int_strings(const void **_a, const void **_b)
static int
compute_consensus_method(smartlist_t *votes)
{
- smartlist_t *all_methods = smartlist_create();
- smartlist_t *acceptable_methods = smartlist_create();
- smartlist_t *tmp = smartlist_create();
+ smartlist_t *all_methods = smartlist_new();
+ smartlist_t *acceptable_methods = smartlist_new();
+ smartlist_t *tmp = smartlist_new();
int min = (smartlist_len(votes) * 2) / 3;
int n_ok;
int result;
@@ -580,15 +584,13 @@ make_consensus_method_list(int low, int high, const char *separator)
{
char *list;
- char b[32];
int i;
smartlist_t *lst;
- lst = smartlist_create();
+ lst = smartlist_new();
for (i = low; i <= high; ++i) {
if (!consensus_method_is_supported(i))
continue;
- tor_snprintf(b, sizeof(b), "%d", i);
- smartlist_add(lst, tor_strdup(b));
+ smartlist_add_asprintf(lst, "%d", i);
}
list = smartlist_join_strings(lst, separator, 0, NULL);
tor_assert(list);
@@ -605,7 +607,7 @@ static char *
compute_consensus_versions_list(smartlist_t *lst, int n_versioning)
{
int min = n_versioning / 2;
- smartlist_t *good = smartlist_create();
+ smartlist_t *good = smartlist_new();
char *result;
sort_version_list(lst, 0);
get_frequent_members(good, lst, min);
@@ -614,11 +616,16 @@ compute_consensus_versions_list(smartlist_t *lst, int n_versioning)
return result;
}
+/** Minimum number of directory authorities voting for a parameter to
+ * include it in the consensus, if consensus method 12 or later is to be
+ * used. See proposal 178 for details. */
+#define MIN_VOTES_FOR_PARAM 3
+
/** Helper: given a list of valid networkstatus_t, return a new string
* containing the contents of the consensus network parameter set.
*/
/* private */ char *
-dirvote_compute_params(smartlist_t *votes)
+dirvote_compute_params(smartlist_t *votes, int method, int total_authorities)
{
int i;
int32_t *vals;
@@ -630,7 +637,7 @@ dirvote_compute_params(smartlist_t *votes)
const int n_votes = smartlist_len(votes);
smartlist_t *output;
- smartlist_t *param_list = smartlist_create();
+ smartlist_t *param_list = smartlist_new();
/* We require that the parameter lists in the votes are well-formed: that
is, that their keywords are unique and sorted, and that their values are
@@ -658,16 +665,16 @@ dirvote_compute_params(smartlist_t *votes)
tor_assert(eq);
cur_param_len = (int)(eq+1 - cur_param);
- output = smartlist_create();
+ output = smartlist_new();
SMARTLIST_FOREACH_BEGIN(param_list, const char *, param) {
const char *next_param;
int ok=0;
eq = strchr(param, '=');
- tor_assert(i<n_votes);
+ tor_assert(i<n_votes); /* Make sure we prevented vote-stuffing. */
vals[i++] = (int32_t)
tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
- tor_assert(ok);
+ tor_assert(ok); /* Already checked these when parsing. */
if (param_sl_idx+1 == smartlist_len(param_list))
next_param = NULL;
@@ -675,11 +682,17 @@ dirvote_compute_params(smartlist_t *votes)
next_param = smartlist_get(param_list, param_sl_idx+1);
if (!next_param || strncmp(next_param, param, cur_param_len)) {
/* We've reached the end of a series. */
- int32_t median = median_int32(vals, i);
- char *out_string = tor_malloc(64+cur_param_len);
- memcpy(out_string, param, cur_param_len);
- tor_snprintf(out_string+cur_param_len,64, "%ld", (long)median);
- smartlist_add(output, out_string);
+ /* Make sure enough authorities voted on this param, unless the
+ * the consensus method we use is too old for that. */
+ if (method < MIN_METHOD_FOR_MAJORITY_PARAMS ||
+ i > total_authorities/2 ||
+ i >= MIN_VOTES_FOR_PARAM) {
+ int32_t median = median_int32(vals, i);
+ char *out_string = tor_malloc(64+cur_param_len);
+ memcpy(out_string, param, cur_param_len);
+ tor_snprintf(out_string+cur_param_len,64, "%ld", (long)median);
+ smartlist_add(output, out_string);
+ }
i = 0;
if (next_param) {
@@ -798,8 +811,6 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
int64_t Wmg = -1, Wme = -1, Wmd = -1;
int64_t Wed = -1, Wee = -1;
const char *casename;
- char buf[512];
- int r;
if (G <= 0 || M <= 0 || E <= 0 || D <= 0) {
log_warn(LD_DIR, "Consensus with empty bandwidth: "
@@ -997,7 +1008,7 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
/* We cast down the weights to 32 bit ints on the assumption that
* weight_scale is ~= 10000. We need to ensure a rogue authority
* doesn't break this assumption to rig our weights */
- tor_assert(0 < weight_scale && weight_scale < INT32_MAX);
+ tor_assert(0 < weight_scale && weight_scale <= INT32_MAX);
/*
* Provide Wgm=Wgg, Wmm=1, Wem=Wee, Weg=Wed. May later determine
@@ -1007,7 +1018,7 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
*
* NOTE: This list is sorted.
*/
- r = tor_snprintf(buf, sizeof(buf),
+ smartlist_add_asprintf(chunks,
"bandwidth-weights Wbd=%d Wbe=%d Wbg=%d Wbm=%d "
"Wdb=%d "
"Web=%d Wed=%d Wee=%d Weg=%d Wem=%d "
@@ -1018,13 +1029,6 @@ networkstatus_compute_bw_weights_v10(smartlist_t *chunks, int64_t G,
(int)weight_scale, (int)Wed, (int)Wee, (int)Wed, (int)Wee,
(int)weight_scale, (int)Wgd, (int)Wgg, (int)Wgg,
(int)weight_scale, (int)Wmd, (int)Wme, (int)Wmg, (int)weight_scale);
- if (r<0) {
- log_warn(LD_BUG,
- "Not enough space in buffer for bandwidth-weights line.");
- *buf = '\0';
- return 0;
- }
- smartlist_add(chunks, tor_strdup(buf));
log_notice(LD_CIRC, "Computed bandwidth weights for %s with v10: "
"G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
@@ -1048,8 +1052,6 @@ networkstatus_compute_bw_weights_v9(smartlist_t *chunks, int64_t G, int64_t M,
int64_t Wmg = -1, Wme = -1, Wmd = -1;
int64_t Wed = -1, Wee = -1;
const char *casename;
- char buf[512];
- int r;
if (G <= 0 || M <= 0 || E <= 0 || D <= 0) {
log_warn(LD_DIR, "Consensus with empty bandwidth: "
@@ -1234,7 +1236,7 @@ networkstatus_compute_bw_weights_v9(smartlist_t *chunks, int64_t G, int64_t M,
/* We cast down the weights to 32 bit ints on the assumption that
* weight_scale is ~= 10000. We need to ensure a rogue authority
* doesn't break this assumption to rig our weights */
- tor_assert(0 < weight_scale && weight_scale < INT32_MAX);
+ tor_assert(0 < weight_scale && weight_scale <= INT32_MAX);
if (Wgg < 0 || Wgg > weight_scale) {
log_warn(LD_DIR, "Bw %s: Wgg="I64_FORMAT"! G="I64_FORMAT
@@ -1311,7 +1313,7 @@ networkstatus_compute_bw_weights_v9(smartlist_t *chunks, int64_t G, int64_t M,
*
* NOTE: This list is sorted.
*/
- r = tor_snprintf(buf, sizeof(buf),
+ smartlist_add_asprintf(chunks,
"Wbd=%d Wbe=%d Wbg=%d Wbm=%d "
"Wdb=%d "
"Web=%d Wed=%d Wee=%d Weg=%d Wem=%d "
@@ -1322,12 +1324,7 @@ networkstatus_compute_bw_weights_v9(smartlist_t *chunks, int64_t G, int64_t M,
(int)weight_scale, (int)Wed, (int)Wee, (int)Wed, (int)Wee,
(int)weight_scale, (int)Wgd, (int)Wgg, (int)Wgg,
(int)weight_scale, (int)Wmd, (int)Wme, (int)Wmg, (int)weight_scale);
- if (r<0) {
- log_warn(LD_BUG,
- "Not enough space in buffer for bandwidth-weights line.");
- *buf = '\0';
- }
- smartlist_add(chunks, tor_strdup(buf));
+
log_notice(LD_CIRC, "Computed bandwidth weights for %s with v9: "
"G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
" T="I64_FORMAT,
@@ -1347,10 +1344,10 @@ networkstatus_compute_bw_weights_v9(smartlist_t *chunks, int64_t G, int64_t M,
char *
networkstatus_compute_consensus(smartlist_t *votes,
int total_authorities,
- crypto_pk_env_t *identity_key,
- crypto_pk_env_t *signing_key,
+ crypto_pk_t *identity_key,
+ crypto_pk_t *signing_key,
const char *legacy_id_key_digest,
- crypto_pk_env_t *legacy_signing_key,
+ crypto_pk_t *legacy_signing_key,
consensus_flavor_t flavor)
{
smartlist_t *chunks;
@@ -1375,7 +1372,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
log_warn(LD_DIR, "Can't compute a consensus from no votes.");
return NULL;
}
- flags = smartlist_create();
+ flags = smartlist_new();
consensus_method = compute_consensus_method(votes);
if (consensus_method_is_supported(consensus_method)) {
@@ -1398,8 +1395,8 @@ networkstatus_compute_consensus(smartlist_t *votes,
int *votesec_list = tor_malloc(n_votes * sizeof(int));
int *distsec_list = tor_malloc(n_votes * sizeof(int));
int n_versioning_clients = 0, n_versioning_servers = 0;
- smartlist_t *combined_client_versions = smartlist_create();
- smartlist_t *combined_server_versions = smartlist_create();
+ smartlist_t *combined_client_versions = smartlist_new();
+ smartlist_t *combined_server_versions = smartlist_new();
SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
tor_assert(v->type == NS_TYPE_VOTE);
@@ -1409,7 +1406,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
votesec_list[v_sl_idx] = v->vote_seconds;
distsec_list[v_sl_idx] = v->dist_seconds;
if (v->client_versions) {
- smartlist_t *cv = smartlist_create();
+ smartlist_t *cv = smartlist_new();
++n_versioning_clients;
smartlist_split_string(cv, v->client_versions, ",",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
@@ -1418,7 +1415,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_free(cv); /* elements get freed later. */
}
if (v->server_versions) {
- smartlist_t *sv = smartlist_create();
+ smartlist_t *sv = smartlist_new();
++n_versioning_servers;
smartlist_split_string(sv, v->server_versions, ",",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
@@ -1460,10 +1457,9 @@ networkstatus_compute_consensus(smartlist_t *votes,
tor_free(distsec_list);
}
- chunks = smartlist_create();
+ chunks = smartlist_new();
{
- char *buf=NULL;
char va_buf[ISO_TIME_LEN+1], fu_buf[ISO_TIME_LEN+1],
vu_buf[ISO_TIME_LEN+1];
char *flaglist;
@@ -1472,20 +1468,17 @@ networkstatus_compute_consensus(smartlist_t *votes,
format_iso_time(vu_buf, valid_until);
flaglist = smartlist_join_strings(flags, " ", 0, NULL);
- tor_asprintf(&buf, "network-status-version 3%s%s\n"
+ smartlist_add_asprintf(chunks, "network-status-version 3%s%s\n"
"vote-status consensus\n",
flavor == FLAV_NS ? "" : " ",
flavor == FLAV_NS ? "" : flavor_name);
- smartlist_add(chunks, buf);
-
if (consensus_method >= 2) {
- tor_asprintf(&buf, "consensus-method %d\n",
+ smartlist_add_asprintf(chunks, "consensus-method %d\n",
consensus_method);
- smartlist_add(chunks, buf);
}
- tor_asprintf(&buf,
+ smartlist_add_asprintf(chunks,
"valid-after %s\n"
"fresh-until %s\n"
"valid-until %s\n"
@@ -1496,13 +1489,13 @@ networkstatus_compute_consensus(smartlist_t *votes,
va_buf, fu_buf, vu_buf,
vote_seconds, dist_seconds,
client_versions, server_versions, flaglist);
- smartlist_add(chunks, buf);
tor_free(flaglist);
}
if (consensus_method >= MIN_METHOD_FOR_PARAMS) {
- params = dirvote_compute_params(votes);
+ params = dirvote_compute_params(votes, consensus_method,
+ total_authorities);
if (params) {
smartlist_add(chunks, tor_strdup("params "));
smartlist_add(chunks, params);
@@ -1514,7 +1507,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_sort(votes, _compare_votes_by_authority_id);
/* Add the authority sections. */
{
- smartlist_t *dir_sources = smartlist_create();
+ smartlist_t *dir_sources = smartlist_new();
SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
dir_src_ent_t *e = tor_malloc_zero(sizeof(dir_src_ent_t));
e->v = v;
@@ -1533,37 +1526,30 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_sort(dir_sources, _compare_dir_src_ents_by_authority_id);
SMARTLIST_FOREACH_BEGIN(dir_sources, const dir_src_ent_t *, e) {
- struct in_addr in;
- char ip[INET_NTOA_BUF_LEN];
char fingerprint[HEX_DIGEST_LEN+1];
char votedigest[HEX_DIGEST_LEN+1];
networkstatus_t *v = e->v;
networkstatus_voter_info_t *voter = get_voter(v);
- char *buf = NULL;
if (e->is_legacy)
tor_assert(consensus_method >= 2);
- in.s_addr = htonl(voter->addr);
- tor_inet_ntoa(&in, ip, sizeof(ip));
base16_encode(fingerprint, sizeof(fingerprint), e->digest, DIGEST_LEN);
base16_encode(votedigest, sizeof(votedigest), voter->vote_digest,
DIGEST_LEN);
- tor_asprintf(&buf,
+ smartlist_add_asprintf(chunks,
"dir-source %s%s %s %s %s %d %d\n",
voter->nickname, e->is_legacy ? "-legacy" : "",
- fingerprint, voter->address, ip,
+ fingerprint, voter->address, fmt_addr32(voter->addr),
voter->dir_port,
voter->or_port);
- smartlist_add(chunks, buf);
if (! e->is_legacy) {
- tor_asprintf(&buf,
+ smartlist_add_asprintf(chunks,
"contact %s\n"
"vote-digest %s\n",
voter->contact,
votedigest);
- smartlist_add(chunks, buf);
}
} SMARTLIST_FOREACH_END(e);
SMARTLIST_FOREACH(dir_sources, dir_src_ent_t *, e, tor_free(e));
@@ -1577,10 +1563,10 @@ networkstatus_compute_consensus(smartlist_t *votes,
int *flag_counts; /* The number of voters that list flag[j] for the
* currently considered router. */
int i;
- smartlist_t *matching_descs = smartlist_create();
- smartlist_t *chosen_flags = smartlist_create();
- smartlist_t *versions = smartlist_create();
- smartlist_t *exitsummaries = smartlist_create();
+ smartlist_t *matching_descs = smartlist_new();
+ smartlist_t *chosen_flags = smartlist_new();
+ smartlist_t *versions = smartlist_new();
+ smartlist_t *exitsummaries = smartlist_new();
uint32_t *bandwidths = tor_malloc(sizeof(uint32_t) * smartlist_len(votes));
uint32_t *measured_bws = tor_malloc(sizeof(uint32_t) *
smartlist_len(votes));
@@ -1615,12 +1601,10 @@ networkstatus_compute_consensus(smartlist_t *votes,
chosen_named_idx = smartlist_string_pos(flags, "Named");
/* Build the flag index. */
- SMARTLIST_FOREACH(votes, networkstatus_t *, v,
- {
+ SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
flag_map[v_sl_idx] = tor_malloc_zero(
sizeof(int)*smartlist_len(v->known_flags));
- SMARTLIST_FOREACH(v->known_flags, const char *, fl,
- {
+ SMARTLIST_FOREACH_BEGIN(v->known_flags, const char *, fl) {
int p = smartlist_string_pos(flags, fl);
tor_assert(p >= 0);
flag_map[v_sl_idx][fl_sl_idx] = p;
@@ -1629,21 +1613,21 @@ networkstatus_compute_consensus(smartlist_t *votes,
named_flag[v_sl_idx] = fl_sl_idx;
if (!strcmp(fl, "Unnamed"))
unnamed_flag[v_sl_idx] = fl_sl_idx;
- });
+ } SMARTLIST_FOREACH_END(fl);
n_voter_flags[v_sl_idx] = smartlist_len(v->known_flags);
size[v_sl_idx] = smartlist_len(v->routerstatus_list);
- });
+ } SMARTLIST_FOREACH_END(v);
/* Named and Unnamed get treated specially */
if (consensus_method >= 2) {
- SMARTLIST_FOREACH(votes, networkstatus_t *, v,
- {
+ SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
uint64_t nf;
if (named_flag[v_sl_idx]<0)
continue;
nf = U64_LITERAL(1) << named_flag[v_sl_idx];
- SMARTLIST_FOREACH(v->routerstatus_list, vote_routerstatus_t *, rs,
- {
+ SMARTLIST_FOREACH_BEGIN(v->routerstatus_list,
+ vote_routerstatus_t *, rs) {
+
if ((rs->flags & nf) != 0) {
const char *d = strmap_get_lc(name_to_id_map, rs->status.nickname);
if (!d) {
@@ -1658,16 +1642,16 @@ networkstatus_compute_consensus(smartlist_t *votes,
/* It's already a conflict, or it's already this ID. */
}
}
- });
- });
- SMARTLIST_FOREACH(votes, networkstatus_t *, v,
- {
+ } SMARTLIST_FOREACH_END(rs);
+ } SMARTLIST_FOREACH_END(v);
+
+ SMARTLIST_FOREACH_BEGIN(votes, networkstatus_t *, v) {
uint64_t uf;
if (unnamed_flag[v_sl_idx]<0)
continue;
uf = U64_LITERAL(1) << unnamed_flag[v_sl_idx];
- SMARTLIST_FOREACH(v->routerstatus_list, vote_routerstatus_t *, rs,
- {
+ SMARTLIST_FOREACH_BEGIN(v->routerstatus_list,
+ vote_routerstatus_t *, rs) {
if ((rs->flags & uf) != 0) {
const char *d = strmap_get_lc(name_to_id_map, rs->status.nickname);
if (d == conflict || d == unknown) {
@@ -1682,8 +1666,8 @@ networkstatus_compute_consensus(smartlist_t *votes,
/* It's mapped to a different name. */
}
}
- });
- });
+ } SMARTLIST_FOREACH_END(rs);
+ } SMARTLIST_FOREACH_END(v);
}
/* Now go through all the votes */
@@ -1700,7 +1684,6 @@ networkstatus_compute_consensus(smartlist_t *votes,
int naming_conflict = 0;
int n_listing = 0;
int i;
- char *buf=NULL;
char microdesc_digest[DIGEST256_LEN];
/* Of the next-to-be-considered digest in each voter, which is first? */
@@ -1773,6 +1756,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
rs = compute_routerstatus_consensus(matching_descs, consensus_method,
microdesc_digest);
/* Copy bits of that into rs_out. */
+ memset(&rs_out, 0, sizeof(rs_out));
tor_assert(fast_memeq(lowest_id, rs->status.identity_digest,DIGEST_LEN));
memcpy(rs_out.identity_digest, lowest_id, DIGEST_LEN);
memcpy(rs_out.descriptor_digest, rs->status.descriptor_digest,
@@ -1806,8 +1790,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
/* Set the flags. */
smartlist_add(chosen_flags, (char*)"s"); /* for the start of the line. */
- SMARTLIST_FOREACH(flags, const char *, fl,
- {
+ SMARTLIST_FOREACH_BEGIN(flags, const char *, fl) {
if (!strcmp(fl, "Named")) {
if (is_named)
smartlist_add(chosen_flags, (char*)fl);
@@ -1827,7 +1810,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
is_bad_exit = 1;
}
}
- });
+ } SMARTLIST_FOREACH_END(fl);
/* Starting with consensus method 4 we do not list servers
* that are not running in a consensus. See Proposal 138 */
@@ -1892,7 +1875,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
* that list previously */
const char *chosen_exitsummary = NULL;
smartlist_clear(exitsummaries);
- SMARTLIST_FOREACH(matching_descs, vote_routerstatus_t *, vsr, {
+ SMARTLIST_FOREACH_BEGIN(matching_descs, vote_routerstatus_t *, vsr) {
/* Check if the vote where this status comes from had the
* proper descriptor */
tor_assert(fast_memeq(rs_out.identity_digest,
@@ -1912,7 +1895,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
exitsummary_disagreement = 1;
}
}
- });
+ } SMARTLIST_FOREACH_END(vsr);
if (exitsummary_disagreement) {
char id[HEX_DIGEST_LEN+1];
@@ -1957,6 +1940,13 @@ networkstatus_compute_consensus(smartlist_t *votes,
}
}
+ if (flavor == FLAV_MICRODESC &&
+ consensus_method >= MIN_METHOD_FOR_MANDATORY_MICRODESC &&
+ tor_digest256_is_zero(microdesc_digest)) {
+ /* With no microdescriptor digest, we omit the entry entirely. */
+ continue;
+ }
+
{
char buf[4096];
/* Okay!! Now we can write the descriptor... */
@@ -1968,10 +1958,9 @@ networkstatus_compute_consensus(smartlist_t *votes,
/* Now an m line, if applicable. */
if (flavor == FLAV_MICRODESC &&
!tor_digest256_is_zero(microdesc_digest)) {
- char m[BASE64_DIGEST256_LEN+1], *cp;
+ char m[BASE64_DIGEST256_LEN+1];
digest256_to_base64(m, microdesc_digest);
- tor_asprintf(&cp, "m %s\n", m);
- smartlist_add(chunks, cp);
+ smartlist_add_asprintf(chunks, "m %s\n", m);
}
/* Next line is all flags. The "\n" is missing. */
smartlist_add(chunks,
@@ -1984,15 +1973,12 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_add(chunks, tor_strdup("\n"));
/* Now the weight line. */
if (rs_out.has_bandwidth) {
- char *cp=NULL;
- tor_asprintf(&cp, "w Bandwidth=%d\n", rs_out.bandwidth);
- smartlist_add(chunks, cp);
+ smartlist_add_asprintf(chunks, "w Bandwidth=%d\n", rs_out.bandwidth);
}
/* Now the exitpolicy summary line. */
if (rs_out.has_exitsummary && flavor == FLAV_NS) {
- tor_asprintf(&buf, "p %s\n", rs_out.exitsummary);
- smartlist_add(chunks, buf);
+ smartlist_add_asprintf(chunks, "p %s\n", rs_out.exitsummary);
}
/* And the loop is over and we move on to the next router */
@@ -2041,7 +2027,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
int ok=0;
char *eq = strchr(bw_weight_param, '=');
if (eq) {
- weight_scale = tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok,
+ weight_scale = tor_parse_long(eq+1, 10, 1, INT32_MAX, &ok,
NULL);
if (!ok) {
log_warn(LD_DIR, "Bad element '%s' in bw weight param",
@@ -2074,7 +2060,6 @@ networkstatus_compute_consensus(smartlist_t *votes,
size_t digest_len =
flavor == FLAV_NS ? DIGEST_LEN : DIGEST256_LEN;
const char *algname = crypto_digest_algorithm_get_name(digest_alg);
- char *buf = NULL;
char sigbuf[4096];
smartlist_add(chunks, tor_strdup("directory-signature "));
@@ -2088,14 +2073,13 @@ networkstatus_compute_consensus(smartlist_t *votes,
/* add the junk that will go at the end of the line. */
if (flavor == FLAV_NS) {
- tor_asprintf(&buf, "%s %s\n", fingerprint,
+ smartlist_add_asprintf(chunks, "%s %s\n", fingerprint,
signing_key_fingerprint);
} else {
- tor_asprintf(&buf, "%s %s %s\n",
+ smartlist_add_asprintf(chunks, "%s %s %s\n",
algname, fingerprint,
signing_key_fingerprint);
}
- smartlist_add(chunks, buf);
/* And the signature. */
sigbuf[0] = '\0';
if (router_append_dirobj_signature(sigbuf, sizeof(sigbuf),
@@ -2113,14 +2097,13 @@ networkstatus_compute_consensus(smartlist_t *votes,
crypto_pk_get_fingerprint(legacy_signing_key,
signing_key_fingerprint, 0);
if (flavor == FLAV_NS) {
- tor_asprintf(&buf, "%s %s\n", fingerprint,
+ smartlist_add_asprintf(chunks, "%s %s\n", fingerprint,
signing_key_fingerprint);
} else {
- tor_asprintf(&buf, "%s %s %s\n",
+ smartlist_add_asprintf(chunks, "%s %s %s\n",
algname, fingerprint,
signing_key_fingerprint);
}
- smartlist_add(chunks, buf);
sigbuf[0] = '\0';
if (router_append_dirobj_signature(sigbuf, sizeof(sigbuf),
digest, digest_len,
@@ -2313,7 +2296,7 @@ networkstatus_format_signatures(networkstatus_t *consensus,
else
keyword = "directory-signature";
- elements = smartlist_create();
+ elements = smartlist_new();
SMARTLIST_FOREACH_BEGIN(consensus->voters, networkstatus_voter_info_t *, v) {
SMARTLIST_FOREACH_BEGIN(v->sigs, document_signature_t *, sig) {
@@ -2325,20 +2308,19 @@ networkstatus_format_signatures(networkstatus_t *consensus,
base16_encode(sk, sizeof(sk), sig->signing_key_digest, DIGEST_LEN);
base16_encode(id, sizeof(id), sig->identity_digest, DIGEST_LEN);
if (flavor == FLAV_NS) {
- tor_snprintf(buf, sizeof(buf),
+ smartlist_add_asprintf(elements,
"%s %s %s\n-----BEGIN SIGNATURE-----\n",
keyword, id, sk);
} else {
const char *digest_name =
crypto_digest_algorithm_get_name(sig->alg);
- tor_snprintf(buf, sizeof(buf),
+ smartlist_add_asprintf(elements,
"%s%s%s %s %s %s\n-----BEGIN SIGNATURE-----\n",
keyword,
for_detached_signatures ? " " : "",
for_detached_signatures ? flavor_name : "",
digest_name, id, sk);
}
- smartlist_add(elements, tor_strdup(buf));
base64_encode(buf, sizeof(buf), sig->signature, sig->signature_len);
strlcat(buf, "-----END SIGNATURE-----\n", sizeof(buf));
smartlist_add(elements, tor_strdup(buf));
@@ -2361,7 +2343,6 @@ char *
networkstatus_get_detached_signatures(smartlist_t *consensuses)
{
smartlist_t *elements;
- char buf[4096];
char *result = NULL, *sigs = NULL;
networkstatus_t *consensus_ns = NULL;
tor_assert(consensuses);
@@ -2377,7 +2358,7 @@ networkstatus_get_detached_signatures(smartlist_t *consensuses)
return NULL;
}
- elements = smartlist_create();
+ elements = smartlist_new();
{
char va_buf[ISO_TIME_LEN+1], fu_buf[ISO_TIME_LEN+1],
@@ -2390,12 +2371,11 @@ networkstatus_get_detached_signatures(smartlist_t *consensuses)
format_iso_time(fu_buf, consensus_ns->fresh_until);
format_iso_time(vu_buf, consensus_ns->valid_until);
- tor_snprintf(buf, sizeof(buf),
+ smartlist_add_asprintf(elements,
"consensus-digest %s\n"
"valid-after %s\n"
"fresh-until %s\n"
"valid-until %s\n", d, va_buf, fu_buf, vu_buf);
- smartlist_add(elements, tor_strdup(buf));
}
/* Get all the digests for the non-FLAV_NS consensuses */
@@ -2414,9 +2394,8 @@ networkstatus_get_detached_signatures(smartlist_t *consensuses)
if (tor_mem_is_zero(ns->digests.d[alg], DIGEST256_LEN))
continue;
base16_encode(d, sizeof(d), ns->digests.d[alg], DIGEST256_LEN);
- tor_snprintf(buf, sizeof(buf), "additional-digest %s %s %s\n",
+ smartlist_add_asprintf(elements, "additional-digest %s %s %s\n",
flavor_name, alg_name, d);
- smartlist_add(elements, tor_strdup(buf));
}
} SMARTLIST_FOREACH_END(ns);
@@ -2455,7 +2434,7 @@ get_detached_signatures_from_pending_consensuses(pending_consensus_t *pending,
{
int flav;
char *signatures;
- smartlist_t *c = smartlist_create();
+ smartlist_t *c = smartlist_new();
for (flav = 0; flav < n_flavors; ++flav) {
if (pending[flav].consensus)
smartlist_add(c, pending[flav].consensus);
@@ -2518,7 +2497,7 @@ authority_cert_dup(authority_cert_t *cert)
void
dirvote_get_preferred_voting_intervals(vote_timing_t *timing_out)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert(timing_out);
@@ -2594,7 +2573,7 @@ static struct {
/** Set voting_schedule to hold the timing for the next vote we should be
* doing. */
void
-dirvote_recalculate_timing(or_options_t *options, time_t now)
+dirvote_recalculate_timing(const or_options_t *options, time_t now)
{
int interval, vote_delay, dist_delay;
time_t start;
@@ -2645,7 +2624,7 @@ dirvote_recalculate_timing(or_options_t *options, time_t now)
/** Entry point: Take whatever voting actions are pending as of <b>now</b>. */
void
-dirvote_act(or_options_t *options, time_t now)
+dirvote_act(const or_options_t *options, time_t now)
{
if (!authdir_mode_v3(options))
return;
@@ -2710,6 +2689,7 @@ static smartlist_t *pending_vote_list = NULL;
* build a consensus, the votes go here for the next period. */
static smartlist_t *previous_vote_list = NULL;
+/* DOCDOC pending_consensuses */
static pending_consensus_t pending_consensuses[N_CONSENSUS_FLAVORS];
/** The detached signatures for the consensus that we're currently
@@ -2725,7 +2705,7 @@ static smartlist_t *pending_consensus_signature_list = NULL;
static int
dirvote_perform_vote(void)
{
- crypto_pk_env_t *key = get_my_v3_authority_signing_key();
+ crypto_pk_t *key = get_my_v3_authority_signing_key();
authority_cert_t *cert = get_my_v3_authority_cert();
networkstatus_t *ns;
char *contents;
@@ -2760,7 +2740,7 @@ dirvote_perform_vote(void)
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_VOTE,
ROUTER_PURPOSE_GENERAL,
- V3_AUTHORITY,
+ V3_DIRINFO,
pending_vote->vote_body->dir,
pending_vote->vote_body->dir_len, 0);
log_notice(LD_DIR, "Vote posted.");
@@ -2773,13 +2753,12 @@ dirvote_perform_vote(void)
static void
dirvote_fetch_missing_votes(void)
{
- smartlist_t *missing_fps = smartlist_create();
+ smartlist_t *missing_fps = smartlist_new();
char *resource;
- SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
- trusted_dir_server_t *, ds,
- {
- if (!(ds->type & V3_AUTHORITY))
+ SMARTLIST_FOREACH_BEGIN(router_get_trusted_dir_servers(),
+ trusted_dir_server_t *, ds) {
+ if (!(ds->type & V3_DIRINFO))
continue;
if (!dirvote_get_vote(ds->v3_identity_digest,
DGV_BY_ID|DGV_INCLUDE_PENDING)) {
@@ -2788,14 +2767,19 @@ dirvote_fetch_missing_votes(void)
DIGEST_LEN);
smartlist_add(missing_fps, cp);
}
- });
+ } SMARTLIST_FOREACH_END(ds);
if (!smartlist_len(missing_fps)) {
smartlist_free(missing_fps);
return;
}
- log_notice(LOG_NOTICE, "We're missing votes from %d authorities. Asking "
- "every other authority for a copy.", smartlist_len(missing_fps));
+ {
+ char *tmp = smartlist_join_strings(missing_fps, " ", 0, NULL);
+ log_notice(LOG_NOTICE, "We're missing votes from %d authorities (%s). "
+ "Asking every other authority for a copy.",
+ smartlist_len(missing_fps), tmp);
+ tor_free(tmp);
+ }
resource = smartlist_join_strings(missing_fps, "+", 0, NULL);
directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE,
0, resource);
@@ -2847,9 +2831,9 @@ static void
dirvote_clear_votes(int all_votes)
{
if (!previous_vote_list)
- previous_vote_list = smartlist_create();
+ previous_vote_list = smartlist_new();
if (!pending_vote_list)
- pending_vote_list = smartlist_create();
+ pending_vote_list = smartlist_new();
/* All "previous" votes are now junk. */
SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, v, {
@@ -2888,11 +2872,11 @@ dirvote_clear_votes(int all_votes)
static char *
list_v3_auth_ids(void)
{
- smartlist_t *known_v3_keys = smartlist_create();
+ smartlist_t *known_v3_keys = smartlist_new();
char *keys;
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
- if ((ds->type & V3_AUTHORITY) &&
+ if ((ds->type & V3_DIRINFO) &&
!tor_digest_is_zero(ds->v3_identity_digest))
smartlist_add(known_v3_keys,
tor_strdup(hex_str(ds->v3_identity_digest, DIGEST_LEN))));
@@ -2921,7 +2905,7 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out)
tor_assert(status_out);
if (!pending_vote_list)
- pending_vote_list = smartlist_create();
+ pending_vote_list = smartlist_new();
*status_out = 0;
*msg_out = NULL;
@@ -2985,7 +2969,7 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out)
update_consensus_router_descriptor_downloads(time(NULL), 1, vote);
/* Now see whether we already have a vote from this authority. */
- SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, {
+ SMARTLIST_FOREACH_BEGIN(pending_vote_list, pending_vote_t *, v) {
if (fast_memeq(v->vote->cert->cache_info.identity_digest,
vote->cert->cache_info.identity_digest,
DIGEST_LEN)) {
@@ -3020,7 +3004,7 @@ dirvote_add_vote(const char *vote_body, const char **msg_out, int *status_out)
goto err;
}
}
- });
+ } SMARTLIST_FOREACH_END(v);
pending_vote = tor_malloc_zero(sizeof(pending_vote_t));
pending_vote->vote_body = new_cached_dir(tor_strndup(vote_body,
@@ -3085,9 +3069,9 @@ dirvote_compute_consensuses(void)
memset(pending, 0, sizeof(pending));
if (!pending_vote_list)
- pending_vote_list = smartlist_create();
+ pending_vote_list = smartlist_new();
- n_voters = get_n_authorities(V3_AUTHORITY);
+ n_voters = get_n_authorities(V3_DIRINFO);
n_votes = smartlist_len(pending_vote_list);
if (n_votes <= n_voters/2) {
log_warn(LD_DIR, "We don't have enough votes to generate a consensus: "
@@ -3113,8 +3097,8 @@ dirvote_compute_consensuses(void)
goto err;
}
- votes = smartlist_create();
- votestrings = smartlist_create();
+ votes = smartlist_new();
+ votestrings = smartlist_new();
SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v,
{
sized_chunk_t *c = tor_malloc(sizeof(sized_chunk_t));
@@ -3133,7 +3117,7 @@ dirvote_compute_consensuses(void)
{
char legacy_dbuf[DIGEST_LEN];
- crypto_pk_env_t *legacy_sign=NULL;
+ crypto_pk_t *legacy_sign=NULL;
char *legacy_id_digest = NULL;
int n_generated = 0;
if (get_options()->V3AuthUseLegacyKey) {
@@ -3204,8 +3188,7 @@ dirvote_compute_consensuses(void)
int n_sigs = 0;
/* we may have gotten signatures for this consensus before we built
* it ourself. Add them now. */
- SMARTLIST_FOREACH(pending_consensus_signature_list, char *, sig,
- {
+ SMARTLIST_FOREACH_BEGIN(pending_consensus_signature_list, char *, sig) {
const char *msg = NULL;
int r = dirvote_add_signatures_to_all_pending_consensuses(sig,
"pending", &msg);
@@ -3216,7 +3199,7 @@ dirvote_compute_consensuses(void)
"Could not add queued signature to new consensus: %s",
msg);
tor_free(sig);
- });
+ } SMARTLIST_FOREACH_END(sig);
if (n_sigs)
log_notice(LD_DIR, "Added %d pending signatures while building "
"consensus.", n_sigs);
@@ -3227,7 +3210,7 @@ dirvote_compute_consensuses(void)
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_SIGNATURES,
ROUTER_PURPOSE_GENERAL,
- V3_AUTHORITY,
+ V3_DIRINFO,
pending_consensus_signatures,
strlen(pending_consensus_signatures), 0);
log_notice(LD_DIR, "Signature(s) posted.");
@@ -3394,7 +3377,7 @@ dirvote_add_signatures(const char *detached_signatures_body,
log_notice(LD_DIR, "Got a signature from %s. "
"Queuing it for the next consensus.", source);
if (!pending_consensus_signature_list)
- pending_consensus_signature_list = smartlist_create();
+ pending_consensus_signature_list = smartlist_new();
smartlist_add(pending_consensus_signature_list,
tor_strdup(detached_signatures_body));
*msg = "Signature queued";
@@ -3533,9 +3516,9 @@ dirvote_create_microdescriptor(const routerinfo_t *ri)
{
microdesc_t *result = NULL;
char *key = NULL, *summary = NULL, *family = NULL;
- char buf[1024];
size_t keylen;
- char *out = buf, *end = buf+sizeof(buf);
+ smartlist_t *chunks = smartlist_new();
+ char *output = NULL;
if (crypto_pk_write_public_key_to_string(ri->onion_pkey, &key, &keylen)<0)
goto done;
@@ -3543,23 +3526,19 @@ dirvote_create_microdescriptor(const routerinfo_t *ri)
if (ri->declared_family)
family = smartlist_join_strings(ri->declared_family, " ", 0, NULL);
- if (tor_snprintf(out, end-out, "onion-key\n%s", key)<0)
- goto done;
- out += strlen(out);
- if (family) {
- if (tor_snprintf(out, end-out, "family %s\n", family)<0)
- goto done;
- out += strlen(out);
- }
- if (summary && strcmp(summary, "reject 1-65535")) {
- if (tor_snprintf(out, end-out, "p %s\n", summary)<0)
- goto done;
- out += strlen(out);
- }
- *out = '\0'; /* Make sure it's nul-terminated. This should be a no-op */
+ smartlist_add_asprintf(chunks, "onion-key\n%s", key);
+
+ if (family)
+ smartlist_add_asprintf(chunks, "family %s\n", family);
+
+ if (summary && strcmp(summary, "reject 1-65535"))
+ smartlist_add_asprintf(chunks, "p %s\n", summary);
+
+ output = smartlist_join_strings(chunks, "", 0, NULL);
{
- smartlist_t *lst = microdescs_parse_from_string(buf, out, 0, 1);
+ smartlist_t *lst = microdescs_parse_from_string(output,
+ output+strlen(output), 0, 1);
if (smartlist_len(lst) != 1) {
log_warn(LD_DIR, "We generated a microdescriptor we couldn't parse.");
SMARTLIST_FOREACH(lst, microdesc_t *, md, microdesc_free(md));
@@ -3571,9 +3550,14 @@ dirvote_create_microdescriptor(const routerinfo_t *ri)
}
done:
+ tor_free(output);
tor_free(key);
tor_free(summary);
tor_free(family);
+ if (chunks) {
+ SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
+ smartlist_free(chunks);
+ }
return result;
}