summaryrefslogtreecommitdiff
path: root/src/or/router.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/router.c')
-rw-r--r--src/or/router.c140
1 files changed, 100 insertions, 40 deletions
diff --git a/src/or/router.c b/src/or/router.c
index d4131992aa..c4a805ff39 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -1099,43 +1099,47 @@ check_whether_dirport_reachable(void)
can_reach_dir_port;
}
-/** Look at a variety of factors, and return 0 if we don't want to
- * advertise the fact that we have a DirPort open. Else return the
- * DirPort we want to advertise.
- *
- * Log a helpful message if we change our mind about whether to publish
- * a DirPort.
+/** The lower threshold of remaining bandwidth required to advertise (or
+ * automatically provide) directory services */
+/* XXX Should this be increased? */
+#define MIN_BW_TO_ADVERTISE_DIRSERVER 51200
+
+/** Return true iff we have enough configured bandwidth to cache directory
+ * information. */
+static int
+router_has_bandwidth_to_be_dirserver(const or_options_t *options)
+{
+ if (options->BandwidthRate < MIN_BW_TO_ADVERTISE_DIRSERVER) {
+ return 0;
+ }
+ if (options->RelayBandwidthRate > 0 &&
+ options->RelayBandwidthRate < MIN_BW_TO_ADVERTISE_DIRSERVER) {
+ return 0;
+ }
+ return 1;
+}
+
+/** Helper: Return 1 if we have sufficient resources for serving directory
+ * requests, return 0 otherwise.
+ * dir_port is either 0 or the configured DirPort number.
+ * If AccountingMax is set less than our advertised bandwidth, then don't
+ * serve requests. Likewise, if our advertised bandwidth is less than
+ * MIN_BW_TO_ADVERTISE_DIRSERVER, don't bother trying to serve requests.
*/
static int
-decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port)
+router_should_be_directory_server(const or_options_t *options, int dir_port)
{
static int advertising=1; /* start out assuming we will advertise */
int new_choice=1;
const char *reason = NULL;
- /* Section one: reasons to publish or not publish that aren't
- * worth mentioning to the user, either because they're obvious
- * or because they're normal behavior. */
-
- if (!dir_port) /* short circuit the rest of the function */
- return 0;
- if (authdir_mode(options)) /* always publish */
- return dir_port;
- if (net_is_disabled())
- return 0;
- if (!check_whether_dirport_reachable())
- return 0;
- if (!router_get_advertised_dir_port(options, dir_port))
- return 0;
-
- /* Section two: reasons to publish or not publish that the user
- * might find surprising. These are generally config options that
- * make us choose not to publish. */
-
- if (accounting_is_enabled(options)) {
+ if (accounting_is_enabled(options) &&
+ get_options()->AccountingRule != ACCT_IN) {
/* Don't spend bytes for directory traffic if we could end up hibernating,
* but allow DirPort otherwise. Some people set AccountingMax because
- * they're confused or to get statistics. */
+ * they're confused or to get statistics. Directory traffic has a much
+ * larger effect on output than input so there is no reason to turn it
+ * off if using AccountingRule in. */
int interval_length = accounting_get_interval_length();
uint32_t effective_bw = get_effective_bwrate(options);
uint64_t acc_bytes;
@@ -1158,10 +1162,7 @@ decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port)
new_choice = 0;
reason = "AccountingMax enabled";
}
-#define MIN_BW_TO_ADVERTISE_DIRPORT 51200
- } else if (options->BandwidthRate < MIN_BW_TO_ADVERTISE_DIRPORT ||
- (options->RelayBandwidthRate > 0 &&
- options->RelayBandwidthRate < MIN_BW_TO_ADVERTISE_DIRPORT)) {
+ } else if (! router_has_bandwidth_to_be_dirserver(options)) {
/* if we're advertising a small amount */
new_choice = 0;
reason = "BandwidthRate under 50KB";
@@ -1169,15 +1170,63 @@ decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port)
if (advertising != new_choice) {
if (new_choice == 1) {
- log_notice(LD_DIR, "Advertising DirPort as %d", dir_port);
+ if (dir_port > 0)
+ log_notice(LD_DIR, "Advertising DirPort as %d", dir_port);
+ else
+ log_notice(LD_DIR, "Advertising directory service support");
} else {
tor_assert(reason);
- log_notice(LD_DIR, "Not advertising DirPort (Reason: %s)", reason);
+ log_notice(LD_DIR, "Not advertising Dir%s (Reason: %s)",
+ dir_port ? "Port" : "ectory Service support", reason);
}
advertising = new_choice;
}
- return advertising ? dir_port : 0;
+ return advertising;
+}
+
+/** Return 1 if we are configured to accept either relay or directory requests
+ * from clients and we aren't at risk of exceeding our bandwidth limits, thus
+ * we should be a directory server. If not, return 0.
+ */
+int
+dir_server_mode(const or_options_t *options)
+{
+ if (!options->DirCache)
+ return 0;
+ return options->DirPort_set ||
+ (server_mode(options) && router_has_bandwidth_to_be_dirserver(options));
+}
+
+/** Look at a variety of factors, and return 0 if we don't want to
+ * advertise the fact that we have a DirPort open, else return the
+ * DirPort we want to advertise.
+ *
+ * Log a helpful message if we change our mind about whether to publish
+ * a DirPort.
+ */
+static int
+decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port)
+{
+ /* Part one: reasons to publish or not publish that aren't
+ * worth mentioning to the user, either because they're obvious
+ * or because they're normal behavior. */
+
+ if (!dir_port) /* short circuit the rest of the function */
+ return 0;
+ if (authdir_mode(options)) /* always publish */
+ return dir_port;
+ if (net_is_disabled())
+ return 0;
+ if (!check_whether_dirport_reachable())
+ return 0;
+ if (!router_get_advertised_dir_port(options, dir_port))
+ return 0;
+
+ /* Part two: reasons to publish or not publish that the user
+ * might find surprising. router_should_be_directory_server()
+ * considers config options that make us choose not to publish. */
+ return router_should_be_directory_server(options, dir_port) ? dir_port : 0;
}
/** Allocate and return a new extend_info_t that can be used to build
@@ -1269,7 +1318,8 @@ router_orport_found_reachable(void)
char *address = tor_dup_ip(me->addr);
log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from "
"the outside. Excellent.%s",
- get_options()->PublishServerDescriptor_ != NO_DIRINFO ?
+ get_options()->PublishServerDescriptor_ != NO_DIRINFO
+ && check_whether_dirport_reachable() ?
" Publishing server descriptor." : "");
can_reach_or_port = 1;
mark_my_descriptor_dirty("ORPort found reachable");
@@ -1293,7 +1343,10 @@ router_dirport_found_reachable(void)
if (!can_reach_dir_port && me) {
char *address = tor_dup_ip(me->addr);
log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable "
- "from the outside. Excellent.");
+ "from the outside. Excellent.%s",
+ get_options()->PublishServerDescriptor_ != NO_DIRINFO
+ && check_whether_orport_reachable() ?
+ " Publishing server descriptor." : "");
can_reach_dir_port = 1;
if (decide_to_advertise_dirport(get_options(), me->dir_port)) {
mark_my_descriptor_dirty("DirPort found reachable");
@@ -1496,7 +1549,8 @@ proxy_mode(const or_options_t *options)
* and
* - We have ORPort set
* and
- * - We believe we are reachable from the outside; or
+ * - We believe both our ORPort and DirPort (if present) are reachable from
+ * the outside; or
* - We are an authoritative directory server.
*/
static int
@@ -1515,7 +1569,7 @@ decide_if_publishable_server(void)
if (!router_get_advertised_or_port(options))
return 0;
- return check_whether_orport_reachable();
+ return check_whether_orport_reachable() && check_whether_dirport_reachable();
}
/** Initiate server descriptor upload as reasonable (if server is publishable,
@@ -1867,6 +1921,8 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e)
ri->addr = addr;
ri->or_port = router_get_advertised_or_port(options);
ri->dir_port = router_get_advertised_dir_port(options, 0);
+ ri->supports_tunnelled_dir_requests = dir_server_mode(options) &&
+ router_should_be_directory_server(options, ri->dir_port);
ri->cache_info.published_on = time(NULL);
ri->onion_pkey = crypto_pk_dup_key(get_onion_key()); /* must invoke from
* main thread */
@@ -2320,7 +2376,7 @@ router_new_address_suggestion(const char *suggestion,
if (tor_addr_eq(&d_conn->base_.addr, &addr)) {
/* Don't believe anybody who says our IP is their IP. */
log_debug(LD_DIR, "A directory server told us our IP address is %s, "
- "but he's just reporting his own IP address. Ignoring.",
+ "but they are just reporting their own IP address. Ignoring.",
suggestion);
return;
}
@@ -2643,6 +2699,10 @@ router_dump_router_to_string(routerinfo_t *router,
tor_free(p6);
}
+ if (router->supports_tunnelled_dir_requests) {
+ smartlist_add(chunks, tor_strdup("tunnelled-dir-server\n"));
+ }
+
/* Sign the descriptor with Ed25519 */
if (emit_ed_sigs) {
smartlist_add(chunks, tor_strdup("router-sig-ed25519 "));