aboutsummaryrefslogtreecommitdiff
path: root/src/feature/dirauth
diff options
context:
space:
mode:
Diffstat (limited to 'src/feature/dirauth')
-rw-r--r--src/feature/dirauth/dirauth_options.inc7
-rw-r--r--src/feature/dirauth/dirvote.c55
-rw-r--r--src/feature/dirauth/dirvote.h6
-rw-r--r--src/feature/dirauth/process_descs.c23
-rw-r--r--src/feature/dirauth/process_descs.h3
-rw-r--r--src/feature/dirauth/voteflags.c11
-rw-r--r--src/feature/dirauth/voteflags.h3
7 files changed, 94 insertions, 14 deletions
diff --git a/src/feature/dirauth/dirauth_options.inc b/src/feature/dirauth/dirauth_options.inc
index 05726b8c2f..4fd07a8859 100644
--- a/src/feature/dirauth/dirauth_options.inc
+++ b/src/feature/dirauth/dirauth_options.inc
@@ -27,6 +27,10 @@ CONF_VAR(AuthDirHasIPv6Connectivity, BOOL, 0, "0")
* good. */
CONF_VAR(AuthDirListBadExits, BOOL, 0, "0")
+/** True iff we should list middle-only relays, and vote for all other
+ * relays as possibly suitable for other positions. */
+CONF_VAR(AuthDirListMiddleOnly, BOOL, 0, "0")
+
/** Do not permit more than this number of servers per IP address. */
CONF_VAR(AuthDirMaxServersPerAddr, POSINT, 0, "2")
@@ -109,4 +113,7 @@ CONF_VAR(VersioningAuthoritativeDirectory, BOOL, 0, "0")
* pressure or not. */
CONF_VAR(AuthDirRejectRequestsUnderLoad, BOOL, 0, "1")
+/** Boolean: Should we not give bandwidth weight measurements to dirauths? */
+CONF_VAR(AuthDirDontVoteOnDirAuthBandwidth, BOOL, 0, "1")
+
END_CONF_STRUCT(dirauth_options_t)
diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c
index fa906c0c3c..cdd2c132ef 100644
--- a/src/feature/dirauth/dirvote.c
+++ b/src/feature/dirauth/dirvote.c
@@ -1479,6 +1479,21 @@ compute_nth_protocol_set(int n, int n_voters, const smartlist_t *votes)
return result;
}
+/** Helper: Takes a smartlist of `const char *` flags, and a flag to remove.
+ *
+ * Removes that flag if it is present in the list. Doesn't free it.
+ */
+static void
+remove_flag(smartlist_t *sl, const char *flag)
+{
+ /* We can't use smartlist_string_remove() here, since that doesn't preserve
+ * order, and since it frees elements from the string. */
+
+ int idx = smartlist_string_pos(sl, flag);
+ if (idx >= 0)
+ smartlist_del_keeporder(sl, idx);
+}
+
/** Given a list of vote networkstatus_t in <b>votes</b>, our public
* authority <b>identity_key</b>, our private authority <b>signing_key</b>,
* and the number of <b>total_authorities</b> that we believe exist in our
@@ -1633,6 +1648,9 @@ networkstatus_compute_consensus(smartlist_t *votes,
tor_free(votesec_list);
tor_free(distsec_list);
}
+ // True if anybody is voting on the BadExit flag.
+ const bool badexit_flag_is_listed =
+ smartlist_contains_string(flags, "BadExit");
chunks = smartlist_new();
@@ -1924,7 +1942,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
const char *chosen_name = NULL;
int exitsummary_disagreement = 0;
int is_named = 0, is_unnamed = 0, is_running = 0, is_valid = 0;
- int is_guard = 0, is_exit = 0, is_bad_exit = 0;
+ int is_guard = 0, is_exit = 0, is_bad_exit = 0, is_middle_only = 0;
int naming_conflict = 0;
int n_listing = 0;
char microdesc_digest[DIGEST256_LEN];
@@ -2055,7 +2073,6 @@ networkstatus_compute_consensus(smartlist_t *votes,
}
/* Set the flags. */
- smartlist_add(chosen_flags, (char*)"s"); /* for the start of the line. */
SMARTLIST_FOREACH_BEGIN(flags, const char *, fl) {
if (!strcmp(fl, "Named")) {
if (is_named)
@@ -2077,6 +2094,8 @@ networkstatus_compute_consensus(smartlist_t *votes,
is_running = 1;
else if (!strcmp(fl, "BadExit"))
is_bad_exit = 1;
+ else if (!strcmp(fl, "MiddleOnly"))
+ is_middle_only = 1;
else if (!strcmp(fl, "Valid"))
is_valid = 1;
}
@@ -2093,6 +2112,22 @@ networkstatus_compute_consensus(smartlist_t *votes,
if (!is_valid)
continue;
+ /* Starting with consensus method 32, we handle the middle-only
+ * flag specially: when it is present, we clear some flags, and
+ * set others. */
+ if (is_middle_only && consensus_method >= MIN_METHOD_FOR_MIDDLEONLY) {
+ remove_flag(chosen_flags, "Exit");
+ remove_flag(chosen_flags, "V2Dir");
+ remove_flag(chosen_flags, "Guard");
+ remove_flag(chosen_flags, "HSDir");
+ is_exit = is_guard = 0;
+ if (! is_bad_exit && badexit_flag_is_listed) {
+ is_bad_exit = 1;
+ smartlist_add(chosen_flags, (char *)"BadExit");
+ smartlist_sort_strings(chosen_flags); // restore order.
+ }
+ }
+
/* Pick the version. */
if (smartlist_len(versions)) {
sort_version_list(versions, 0);
@@ -2253,6 +2288,8 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_add_asprintf(chunks, "m %s\n", m);
}
/* Next line is all flags. The "\n" is missing. */
+ smartlist_add_asprintf(chunks, "s%s",
+ smartlist_len(chosen_flags)?" ":"");
smartlist_add(chunks,
smartlist_join_strings(chosen_flags, " ", 0, NULL));
/* Now the version line. */
@@ -2265,7 +2302,8 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_add_asprintf(chunks, "pr %s\n", chosen_protocol_list);
}
/* Now the weight line. */
- if (rs_out.has_bandwidth) {
+ if (rs_out.has_bandwidth && (!rs_out.is_authority ||
+ !dirauth_get_options()->AuthDirDontVoteOnDirAuthBandwidth)) {
char *guardfraction_str = NULL;
int unmeasured = rs_out.bw_is_unmeasured;
@@ -4581,6 +4619,7 @@ const char DIRVOTE_UNIVERSAL_FLAGS[] =
* depending on our configuration. */
const char DIRVOTE_OPTIONAL_FLAGS[] =
"BadExit "
+ "MiddleOnly "
"Running";
/** Return a new networkstatus_t* containing our current opinion. (For v3
@@ -4598,7 +4637,8 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
smartlist_t *routers, *routerstatuses;
char identity_digest[DIGEST_LEN];
char signing_key_digest[DIGEST_LEN];
- const int listbadexits = d_options->AuthDirListBadExits;
+ const int list_bad_exits = d_options->AuthDirListBadExits;
+ const int list_middle_only = d_options->AuthDirListMiddleOnly;
routerlist_t *rl = router_get_routerlist();
time_t now = time(NULL);
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
@@ -4703,7 +4743,8 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
dirauth_set_routerstatus_from_routerinfo(rs, node, ri, now,
- listbadexits);
+ list_bad_exits,
+ list_middle_only);
if (ri->cache_info.signing_key_cert) {
memcpy(vrs->ed25519_id,
@@ -4825,8 +4866,10 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
if (vote_on_reachability)
smartlist_add_strdup(v3_out->known_flags, "Running");
- if (listbadexits)
+ if (list_bad_exits)
smartlist_add_strdup(v3_out->known_flags, "BadExit");
+ if (list_middle_only)
+ smartlist_add_strdup(v3_out->known_flags, "MiddleOnly");
smartlist_sort_strings(v3_out->known_flags);
if (d_options->ConsensusParams) {
diff --git a/src/feature/dirauth/dirvote.h b/src/feature/dirauth/dirvote.h
index 3420098315..64aaec116e 100644
--- a/src/feature/dirauth/dirvote.h
+++ b/src/feature/dirauth/dirvote.h
@@ -53,7 +53,7 @@
#define MIN_SUPPORTED_CONSENSUS_METHOD 28
/** The highest consensus method that we currently support. */
-#define MAX_SUPPORTED_CONSENSUS_METHOD 31
+#define MAX_SUPPORTED_CONSENSUS_METHOD 32
/**
* Lowest consensus method where microdescriptor lines are put in canonical
@@ -70,6 +70,10 @@
*/
#define MIN_METHOD_FOR_CORRECT_BWWEIGHTSCALE 31
+/** Lowest consensus method for which we handle the MiddleOnly flag specially.
+ */
+#define MIN_METHOD_FOR_MIDDLEONLY 32
+
/** Default bandwidth to clip unmeasured bandwidths to using method >=
* MIN_METHOD_TO_CLIP_UNMEASURED_BW. (This is not a consensus method; do not
* get confused with the above macros.) */
diff --git a/src/feature/dirauth/process_descs.c b/src/feature/dirauth/process_descs.c
index eca987b8b5..a75f516dca 100644
--- a/src/feature/dirauth/process_descs.c
+++ b/src/feature/dirauth/process_descs.c
@@ -226,6 +226,8 @@ dirserv_load_fingerprint_file(void)
add_status = RTR_BADEXIT;
} else if (!strcasecmp(nickname, "!invalid")) {
add_status = RTR_INVALID;
+ } else if (!strcasecmp(nickname, "!middleonly")) {
+ add_status = RTR_MIDDLEONLY;
}
/* Check if fingerprint is RSA or ed25519 by verifying it. */
@@ -412,11 +414,11 @@ dirserv_rejects_tor_version(const char *platform,
return true;
}
- /* Series between Tor 0.3.6 and 0.4.1 inclusive are unsupported. Reject
- * them. 0.3.6.0-alpha-dev only existed for a short time, before it was
- * renamed to 0.4.0.0-alpha-dev. */
+ /* Series between Tor 0.3.6.x and 0.4.5.5-rc inclusive are unsupported.
+ * Reject them. 0.3.6.0-alpha-dev only existed for a short time, before it
+ * was renamed to 0.4.0.0-alpha-dev. */
if (tor_version_as_new_as(platform,"0.3.6.0-alpha-dev") &&
- !tor_version_as_new_as(platform,"0.4.2.1-alpha")) {
+ !tor_version_as_new_as(platform,"0.4.5.6")) {
if (msg) {
*msg = please_upgrade_string;
}
@@ -496,6 +498,13 @@ dirserv_get_status_impl(const char *id_digest,
result |= RTR_BADEXIT;
}
+ if (authdir_policy_middleonly_address(ipv4_addr, ipv4_orport)) {
+ log_fn(severity, LD_DIRSERV,
+ "Marking '%s' as middle-only because of address '%s'",
+ nickname, fmt_addr(ipv4_addr));
+ result |= RTR_MIDDLEONLY;
+ }
+
if (!authdir_policy_permits_address(ipv4_addr, ipv4_orport)) {
log_fn(severity, LD_DIRSERV, "Rejecting '%s' because of address '%s'",
nickname, fmt_addr(ipv4_addr));
@@ -630,6 +639,7 @@ dirserv_set_node_flags_from_authoritative_status(node_t *node,
{
node->is_valid = (authstatus & RTR_INVALID) ? 0 : 1;
node->is_bad_exit = (authstatus & RTR_BADEXIT) ? 1 : 0;
+ node->is_middle_only = (authstatus & RTR_MIDDLEONLY) ? 1 : 0;
}
/** True iff <b>a</b> is more severe than <b>b</b>. */
@@ -963,6 +973,11 @@ directory_remove_invalid(void)
(r & RTR_BADEXIT) ? "bad" : "good");
node->is_bad_exit = (r&RTR_BADEXIT) ? 1: 0;
}
+ if (bool_neq((r & RTR_MIDDLEONLY), node->is_middle_only)) {
+ log_info(LD_DIRSERV, "Router '%s' is now %smiddle-only", description,
+ (r & RTR_MIDDLEONLY) ? "" : "not");
+ node->is_middle_only = (r&RTR_MIDDLEONLY) ? 1: 0;
+ }
} SMARTLIST_FOREACH_END(node);
routerlist_assert_ok(rl);
diff --git a/src/feature/dirauth/process_descs.h b/src/feature/dirauth/process_descs.h
index 6c056d11dd..a509eb1fbe 100644
--- a/src/feature/dirauth/process_descs.h
+++ b/src/feature/dirauth/process_descs.h
@@ -45,7 +45,8 @@ typedef struct authdir_config_t {
#define RTR_REJECT 4 /**< We will not publish this router. */
/* 8 Historically used to avoid using this as a dir. */
#define RTR_BADEXIT 16 /**< We'll tell clients not to use this as an exit. */
-/* 32 Historically used to indicade Unnamed */
+/** We'll vote to only use this router as a midpoint. */
+#define RTR_MIDDLEONLY 32
#endif /* defined(PROCESS_DESCS_PRIVATE) || defined(TOR_UNIT_TESTS) */
diff --git a/src/feature/dirauth/voteflags.c b/src/feature/dirauth/voteflags.c
index d755a270be..05c19ff501 100644
--- a/src/feature/dirauth/voteflags.c
+++ b/src/feature/dirauth/voteflags.c
@@ -565,7 +565,8 @@ dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs,
node_t *node,
const routerinfo_t *ri,
time_t now,
- int listbadexits)
+ int listbadexits,
+ int listmiddleonly)
{
const or_options_t *options = get_options();
uint32_t routerbw_kb = dirserv_get_credible_bandwidth_kb(ri);
@@ -597,6 +598,14 @@ dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs,
/* Override rs->is_bad_exit */
rs->is_bad_exit = listbadexits && node->is_bad_exit;
+ /* Override rs->is_middle_only and related flags. */
+ rs->is_middle_only = listmiddleonly && node->is_middle_only;
+ if (rs->is_middle_only) {
+ if (listbadexits)
+ rs->is_bad_exit = 1;
+ rs->is_exit = rs->is_possible_guard = rs->is_hs_dir = rs->is_v2_dir = 0;
+ }
+
/* Set rs->is_staledesc. */
rs->is_staledesc =
(ri->cache_info.published_on + DESC_IS_STALE_INTERVAL) < now;
diff --git a/src/feature/dirauth/voteflags.h b/src/feature/dirauth/voteflags.h
index 818a0bafd2..8371f1c315 100644
--- a/src/feature/dirauth/voteflags.h
+++ b/src/feature/dirauth/voteflags.h
@@ -22,7 +22,8 @@ void dirauth_set_routerstatus_from_routerinfo(routerstatus_t *rs,
node_t *node,
const routerinfo_t *ri,
time_t now,
- int listbadexits);
+ int listbadexits,
+ int listmiddleonly);
void dirserv_compute_performance_thresholds(digestmap_t *omit_as_sybil);
#endif /* defined(HAVE_MODULE_DIRAUTH) */