diff options
-rw-r--r-- | src/or/directory.c | 9 | ||||
-rw-r--r-- | src/or/directory.h | 3 | ||||
-rw-r--r-- | src/or/dirserv.c | 12 | ||||
-rw-r--r-- | src/or/or.h | 2 | ||||
-rw-r--r-- | src/or/router.c | 99 | ||||
-rw-r--r-- | src/or/router.h | 1 | ||||
-rw-r--r-- | src/test/test_dir.c | 17 |
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" |