aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/or/directory.c9
-rw-r--r--src/or/directory.h3
-rw-r--r--src/or/dirserv.c12
-rw-r--r--src/or/or.h2
-rw-r--r--src/or/router.c99
-rw-r--r--src/or/router.h1
-rw-r--r--src/test/test_dir.c17
7 files changed, 101 insertions, 42 deletions
diff --git a/src/or/directory.c b/src/or/directory.c
index 8370095e92..31a7860ed9 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -943,6 +943,15 @@ directory_initiate_command_rend(const tor_addr_t *_addr,
log_debug(LD_DIR, "anonymized %d, use_begindir %d.",
anonymized_connection, use_begindir);
+ if (!dir_port && !use_begindir) {
+ char ipaddr[TOR_ADDR_BUF_LEN];
+ tor_addr_to_str(ipaddr, _addr, TOR_ADDR_BUF_LEN, 0);
+ log_warn(LD_BUG, "Cannot use directory server without dirport or "
+ "begindir! Address: %s, ORPort: %d, DirPort: %d",
+ escaped_safe_str_client(ipaddr), or_port, dir_port);
+ return;
+ }
+
log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
#ifndef NON_ANONYMOUS_MODE_ENABLED
diff --git a/src/or/directory.h b/src/or/directory.h
index 2644e5703e..28442b9d4d 100644
--- a/src/or/directory.h
+++ b/src/or/directory.h
@@ -101,7 +101,8 @@ time_t download_status_increment_attempt(download_status_t *dls,
* the optional status code <b>sc</b>. */
#define download_status_failed(dls, sc) \
download_status_increment_failure((dls), (sc), NULL, \
- get_options()->DirPort_set, time(NULL))
+ dir_server_mode(get_options()), \
+ time(NULL))
void download_status_reset(download_status_t *dls);
static int download_status_is_ready(download_status_t *dls, time_t now,
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 467c6e2d99..fc6899b3c8 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -1091,13 +1091,13 @@ directory_fetches_from_authorities(const or_options_t *options)
return 1; /* we don't know our IP address; ask an authority. */
refuseunknown = ! router_my_exit_policy_is_reject_star() &&
should_refuse_unknown_exits(options);
- if (!options->DirPort_set && !refuseunknown)
+ if (!dir_server_mode(options) && !refuseunknown)
return 0;
if (!server_mode(options) || !advertised_server_mode())
return 0;
me = router_get_my_routerinfo();
- if (!me || (!me->dir_port && !refuseunknown))
- return 0; /* if dirport not advertised, return 0 too */
+ if (!me || (!me->supports_tunnelled_dir_requests && !refuseunknown))
+ return 0; /* if we don't service directory requests, return 0 too */
return 1;
}
@@ -1128,7 +1128,7 @@ directory_fetches_dir_info_later(const or_options_t *options)
int
directory_caches_unknown_auth_certs(const or_options_t *options)
{
- return options->DirPort_set || options->BridgeRelay;
+ return dir_server_mode(options) || options->BridgeRelay;
}
/** Return 1 if we want to keep descriptors, networkstatuses, etc around
@@ -1137,7 +1137,7 @@ directory_caches_unknown_auth_certs(const or_options_t *options)
int
directory_caches_dir_info(const or_options_t *options)
{
- if (options->BridgeRelay || options->DirPort_set)
+ if (options->BridgeRelay || dir_server_mode(options))
return 1;
if (!server_mode(options) || !advertised_server_mode())
return 0;
@@ -1153,7 +1153,7 @@ directory_caches_dir_info(const or_options_t *options)
int
directory_permits_begindir_requests(const or_options_t *options)
{
- return options->BridgeRelay != 0 || options->DirPort_set;
+ return options->BridgeRelay != 0 || dir_server_mode(options);
}
/** Return 1 if we have no need to fetch new descriptors. This generally
diff --git a/src/or/or.h b/src/or/or.h
index fe59124440..3cb1e7d7ef 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2148,7 +2148,7 @@ typedef struct {
unsigned int needs_retest_if_added:1;
/** True iff this router included "tunnelled-dir-server" in its descriptor,
- * implies it accepts tunnelled directory requests, or it advertised
+ * implying it accepts tunnelled directory requests, or it advertised
* dir_port > 0. */
unsigned int supports_tunnelled_dir_requests:1;
diff --git a/src/or/router.c b/src/or/router.c
index 49e2e318f5..1927cfd38b 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -1099,39 +1099,25 @@ 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 directory
+ * services */
+/* XXX Should this be increased? */
+#define MIN_BW_TO_ADVERTISE_DIRSERVER 51200
+
+/** 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)) {
/* Don't spend bytes for directory traffic if we could end up hibernating,
* but allow DirPort otherwise. Some people set AccountingMax because
@@ -1158,10 +1144,9 @@ 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 ||
+ } else if (options->BandwidthRate < MIN_BW_TO_ADVERTISE_DIRSERVER ||
(options->RelayBandwidthRate > 0 &&
- options->RelayBandwidthRate < MIN_BW_TO_ADVERTISE_DIRPORT)) {
+ options->RelayBandwidthRate < MIN_BW_TO_ADVERTISE_DIRSERVER)) {
/* if we're advertising a small amount */
new_choice = 0;
reason = "BandwidthRate under 50KB";
@@ -1169,15 +1154,61 @@ 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)
+{
+ return (server_mode(options) || options->DirPort_set) &&
+ router_should_be_directory_server(options, 0);
+}
+
+/** 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
@@ -2642,6 +2673,10 @@ router_dump_router_to_string(routerinfo_t *router,
tor_free(p6);
}
+ if (dir_server_mode(options)) {
+ 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 "));
diff --git a/src/or/router.h b/src/or/router.h
index 85f43d804d..f176477d77 100644
--- a/src/or/router.h
+++ b/src/or/router.h
@@ -41,6 +41,7 @@ int init_keys_client(void);
int check_whether_orport_reachable(void);
int check_whether_dirport_reachable(void);
+int dir_server_mode(const or_options_t *options);
void consider_testing_reachability(int test_or, int test_dir);
void router_orport_found_reachable(void);
void router_dirport_found_reachable(void);
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index ab802dc2df..28ec90c163 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -174,8 +174,13 @@ test_dir_formats(void *arg)
/* XXXX025 router_dump_to_string should really take this from ri.*/
options->ContactInfo = tor_strdup("Magri White "
"<magri@elsewhere.example.com>");
+
+ options->ORPort_set = options->DirPort_set = options->AssumeReachable = 1;
buf = router_dump_router_to_string(r1, pk2, NULL, NULL, NULL);
+
tor_free(options->ContactInfo);
+ /* Reset for later */
+ options->ORPort_set = options->DirPort_set = options->AssumeReachable = 0;
tt_assert(buf);
strlcpy(buf2, "router Magri 192.168.0.1 9000 0 9003\n"
@@ -200,7 +205,8 @@ test_dir_formats(void *arg)
strlcat(buf2, "hidden-service-dir\n", sizeof(buf2));
strlcat(buf2, "contact Magri White <magri@elsewhere.example.com>\n",
sizeof(buf2));
- strlcat(buf2, "reject *:*\nrouter-signature\n", sizeof(buf2));
+ strlcat(buf2, "reject *:*\n", sizeof(buf2));
+ strlcat(buf2, "tunnelled-dir-server\nrouter-signature\n", sizeof(buf2));
buf[strlen(buf2)] = '\0'; /* Don't compare the sig; it's never the same
* twice */
@@ -214,12 +220,13 @@ test_dir_formats(void *arg)
tt_assert(rp1);
tt_int_op(rp1->addr,OP_EQ, r1->addr);
tt_int_op(rp1->or_port,OP_EQ, r1->or_port);
- //test_eq(rp1->dir_port, r1->dir_port);
+ tt_int_op(rp1->dir_port,OP_EQ, r1->dir_port);
tt_int_op(rp1->bandwidthrate,OP_EQ, r1->bandwidthrate);
tt_int_op(rp1->bandwidthburst,OP_EQ, r1->bandwidthburst);
tt_int_op(rp1->bandwidthcapacity,OP_EQ, r1->bandwidthcapacity);
tt_assert(crypto_pk_cmp_keys(rp1->onion_pkey, pk1) == 0);
tt_assert(crypto_pk_cmp_keys(rp1->identity_pkey, pk2) == 0);
+ tt_assert(rp1->supports_tunnelled_dir_requests);
//tt_assert(rp1->exit_policy == NULL);
tor_free(buf);
@@ -290,6 +297,7 @@ test_dir_formats(void *arg)
BASE64_ENCODE_MULTILINE);
strlcat(buf2, cert_buf, sizeof(buf2));
strlcat(buf2, "accept *:80\nreject 18.0.0.0/8:24\n", sizeof(buf2));
+ strlcat(buf2, "tunnelled-dir-server\n", sizeof(buf2));
strlcat(buf2, "router-sig-ed25519 ", sizeof(buf2));
buf = router_dump_router_to_string(r2, pk1, pk2, &r2_onion_keypair, &kp2);
@@ -301,6 +309,9 @@ test_dir_formats(void *arg)
tor_free(buf);
buf = router_dump_router_to_string(r2, pk1, NULL, NULL, NULL);
+
+ /* Reset for later */
+ options->ORPort_set = 0;
cp = buf;
rp2 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL,NULL);
tt_assert(rp2);
@@ -315,6 +326,7 @@ test_dir_formats(void *arg)
CURVE25519_PUBKEY_LEN);
tt_assert(crypto_pk_cmp_keys(rp2->onion_pkey, pk2) == 0);
tt_assert(crypto_pk_cmp_keys(rp2->identity_pkey, pk1) == 0);
+ tt_assert(rp2->supports_tunnelled_dir_requests);
tt_int_op(smartlist_len(rp2->exit_policy),OP_EQ, 2);
@@ -1821,6 +1833,7 @@ test_routerstatus_for_v3ns(routerstatus_t *rs, time_t now)
tt_assert(rs->is_flagged_running);
tt_assert(!rs->is_valid);
tt_assert(!rs->is_named);
+ tt_assert(rs->is_v2_dir);
/* XXXX check version */
} else if (tor_memeq(rs->identity_digest,
"\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5\x5"