diff options
Diffstat (limited to 'src/or')
35 files changed, 742 insertions, 221 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c index 4696bec8f4..cdb499b8da 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -1945,7 +1945,7 @@ parse_socks(const char *data, size_t datalen, socks_request_t *req, log_warn(LD_PROTOCOL, "Your application (using socks4 to port %d) gave Tor " "a malformed hostname: %s. Rejecting the connection.", - req->port, escaped(req->address)); + req->port, escaped_safe_str_client(req->address)); return -1; } if (authend != authstart) { diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 4831f2be76..5ffd1f68c7 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -92,7 +92,7 @@ circuit_is_acceptable(const origin_circuit_t *origin_circ, /* decide if this circ is suitable for this conn */ /* for rend circs, circ->cpath->prev is not the last router in the - * circuit, it's the magical extra bob hop. so just check the nickname + * circuit, it's the magical extra service hop. so just check the nickname * of the one we meant to finish at. */ build_state = origin_circ->build_state; @@ -1493,11 +1493,11 @@ circuit_has_opened(origin_circuit_t *circ) circuit_try_attaching_streams(circ); break; case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO: - /* at Bob, waiting for introductions */ + /* at the service, waiting for introductions */ rend_service_intro_has_opened(circ); break; case CIRCUIT_PURPOSE_S_CONNECT_REND: - /* at Bob, connecting to rend point */ + /* at the service, connecting to rend point */ rend_service_rendezvous_has_opened(circ); break; case CIRCUIT_PURPOSE_TESTING: @@ -1617,32 +1617,32 @@ circuit_build_failed(origin_circuit_t *circ) circuit_testing_failed(circ, failed_at_last_hop); break; case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO: - /* at Bob, waiting for introductions */ + /* at the service, waiting for introductions */ if (circ->base_.state != CIRCUIT_STATE_OPEN) { circuit_increment_failure_count(); } - /* no need to care here, because bob will rebuild intro + /* no need to care here, because the service will rebuild intro * points periodically. */ break; case CIRCUIT_PURPOSE_C_INTRODUCING: - /* at Alice, connecting to intro point */ - /* Don't increment failure count, since Bob may have picked + /* at the client, connecting to intro point */ + /* Don't increment failure count, since the service may have picked * the introduction point maliciously */ - /* Alice will pick a new intro point when this one dies, if + /* The client will pick a new intro point when this one dies, if * the stream in question still cares. No need to act here. */ break; case CIRCUIT_PURPOSE_C_ESTABLISH_REND: - /* at Alice, waiting for Bob */ + /* at the client, waiting for the service */ circuit_increment_failure_count(); - /* Alice will pick a new rend point when this one dies, if + /* the client will pick a new rend point when this one dies, if * the stream in question still cares. No need to act here. */ break; case CIRCUIT_PURPOSE_S_CONNECT_REND: - /* at Bob, connecting to rend point */ - /* Don't increment failure count, since Alice may have picked + /* at the service, connecting to rend point */ + /* Don't increment failure count, since the client may have picked * the rendezvous point maliciously */ log_info(LD_REND, - "Couldn't connect to Alice's chosen rend point %s " + "Couldn't connect to the client's chosen rend point %s " "(%s hop failed).", escaped(build_state_get_exit_nickname(circ->build_state)), failed_at_last_hop?"last":"non-last"); @@ -2246,7 +2246,7 @@ consider_recording_trackhost(const entry_connection_t *conn, char fp[HEX_DIGEST_LEN+1]; /* Search the addressmap for this conn's destination. */ - /* If he's not in the address map.. */ + /* If they're not in the address map.. */ if (!options->TrackHostExits || addressmap_have_mapping(conn->socks_request->address, options->TrackHostExitsExpire)) diff --git a/src/or/config.c b/src/or/config.c index b9d9fb2d9a..d71cf6dec7 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -224,6 +224,7 @@ static config_var_t option_vars_[] = { V(DirPortFrontPage, FILENAME, NULL), VAR("DirReqStatistics", BOOL, DirReqStatistics_option, "1"), VAR("DirAuthority", LINELIST, DirAuthorities, NULL), + V(DirCache, BOOL, "1"), V(DirAuthorityFallbackRate, DOUBLE, "1.0"), V(DisableAllSwap, BOOL, "0"), V(DisableDebuggerAttachment, BOOL, "1"), @@ -591,7 +592,6 @@ static const config_var_t testing_tor_network_defaults[] = { static char *get_windows_conf_root(void); #endif static int options_act_reversible(const or_options_t *old_options, char **msg); -static int options_act(const or_options_t *old_options); static int options_transition_allowed(const or_options_t *old, const or_options_t *new, char **msg); @@ -672,9 +672,9 @@ get_dirportfrontpage, (void)) return global_dirfrontpagecontents; } -/** Return the currently configured options. */ -or_options_t * -get_options_mutable(void) +/** Returns the currently configured options. */ +MOCK_IMPL(or_options_t *, +get_options_mutable, (void)) { tor_assert(global_options); return global_options; @@ -834,7 +834,6 @@ config_free_all(void) tor_free(torrc_fname); tor_free(torrc_defaults_fname); - tor_free(the_tor_version); tor_free(global_dirfrontpagecontents); tor_free(the_short_tor_version); @@ -918,7 +917,7 @@ static const char *default_authorities[] = { "ipv6=[2001:638:a000:4140::ffff:189]:443 " "131.188.40.189:80 F204 4413 DAC2 E02E 3D6B CF47 35A1 9BCA 1DE9 7281", "dannenberg orport=443 " - "v3ident=585769C78764D58426B8B52B6651A5A71137189A " + "v3ident=0232AF901C31A04EE9848595AF9BB7620D4C5B2E " "193.23.244.244:80 7BE6 83E6 5D48 1413 21C5 ED92 F075 C553 64AC 7123", "urras orport=80 " "v3ident=80550987E1D626E3EBA5E5E75A458DE0626D088C " @@ -939,6 +938,14 @@ static const char *default_authorities[] = { NULL }; +/** List of fallback directory authorities. The list is generated by opt-in of + * relays that meet certain stability criteria. + */ +static const char *default_fallbacks[] = { +#include "fallback_dirs.inc" + NULL +}; + /** Add the default directory authorities directly into the trusted dir list, * but only add them insofar as they share bits with <b>type</b>. * Each authority's bits are restricted to the bits shared with <b>type</b>. @@ -961,14 +968,10 @@ MOCK_IMPL(void, add_default_fallback_dir_servers,(void)) { int i; - const char *fallback[] = { -#include "fallback_dirs.inc" - NULL - }; - for (i=0; fallback[i]; i++) { - if (parse_dir_fallback_line(fallback[i], 0)<0) { + for (i=0; default_fallbacks[i]; i++) { + if (parse_dir_fallback_line(default_fallbacks[i], 0)<0) { log_err(LD_BUG, "Couldn't parse internal FallbackDir line %s", - fallback[i]); + default_fallbacks[i]); } } } @@ -1443,7 +1446,7 @@ options_transition_requires_fresh_tls_context(const or_options_t *old_options, * Note: We haven't moved all the "act on new configuration" logic * here yet. Some is still in do_hup() and other places. */ -static int +STATIC int options_act(const or_options_t *old_options) { config_line_t *cl; @@ -1465,10 +1468,12 @@ options_act(const or_options_t *old_options) if (options->DisableDebuggerAttachment && !disabled_debugger_attach && running_tor) { int ok = tor_disable_debugger_attach(); + /* LCOV_EXCL_START the warned_debugger_attach is 0 can't reach inside. */ if (warned_debugger_attach && ok == 1) { log_notice(LD_CONFIG, "Disabled attaching debuggers for unprivileged " "users."); } + /* LCOV_EXCL_STOP */ disabled_debugger_attach = (ok == 1); } else if (!options->DisableDebuggerAttachment && !warned_debugger_attach) { @@ -1495,12 +1500,14 @@ options_act(const or_options_t *old_options) #endif #ifdef ENABLE_TOR2WEB_MODE +/* LCOV_EXCL_START */ if (!options->Tor2webMode) { log_err(LD_CONFIG, "This copy of Tor was compiled to run in " "'tor2web mode'. It can only be run with the Tor2webMode torrc " "option enabled."); return -1; } +/* LCOV_EXCL_STOP */ #else if (options->Tor2webMode) { log_err(LD_CONFIG, "This copy of Tor was not compiled to run in " @@ -1512,7 +1519,7 @@ options_act(const or_options_t *old_options) #endif /* If we are a bridge with a pluggable transport proxy but no - Extended ORPort, inform the user that she is missing out. */ + Extended ORPort, inform the user that they are missing out. */ if (server_mode(options) && options->ServerTransportPlugin && !options->ExtORPort_lines) { log_notice(LD_CONFIG, "We use pluggable transports but the Extended " @@ -1764,8 +1771,8 @@ options_act(const or_options_t *old_options) if (revise_trackexithosts) addressmap_clear_excluded_trackexithosts(options); - if (!options->AutomapHostsOnResolve) { - if (old_options->AutomapHostsOnResolve) + if (!options->AutomapHostsOnResolve && + old_options->AutomapHostsOnResolve) { revise_automap_entries = 1; } else { if (!smartlist_strings_eq(old_options->AutomapHostsSuffixes, @@ -1904,8 +1911,8 @@ options_act(const or_options_t *old_options) print_notice = 1; } if (print_notice) - log_notice(LD_CONFIG, "Configured to measure statistics. Look for " - "the *-stats files that will first be written to the " + log_notice(LD_CONFIG, "Configured to measure statistics. Look for " + "the *-stats files that will first be written to the " "data directory in 24 hours from now."); } @@ -3473,8 +3480,30 @@ options_validate(or_options_t *old_options, or_options_t *options, options->AccountingRule = ACCT_SUM; else if (!strcmp(options->AccountingRule_option, "max")) options->AccountingRule = ACCT_MAX; + else if (!strcmp(options->AccountingRule_option, "in")) + options->AccountingRule = ACCT_IN; + else if (!strcmp(options->AccountingRule_option, "out")) + options->AccountingRule = ACCT_OUT; else - REJECT("AccountingRule must be 'sum' or 'max'"); + REJECT("AccountingRule must be 'sum', 'max', 'in', or 'out'"); + } + + if (options->DirPort_set && !options->DirCache) { + REJECT("DirPort configured but DirCache disabled. DirPort requires " + "DirCache."); + } + + if (options->BridgeRelay && !options->DirCache) { + REJECT("We're a bridge but DirCache is disabled. BridgeRelay requires " + "DirCache."); + } + + if (server_mode(options)) { + char *msg = NULL; + if (have_enough_mem_for_dircache(options, 0, &msg)) { + log_warn(LD_CONFIG, "%s", msg); + tor_free(msg); + } } if (options->HTTPProxy) { /* parse it now */ @@ -4085,6 +4114,52 @@ compute_real_max_mem_in_queues(const uint64_t val, int log_guess) } } +/* If we have less than 300 MB suggest disabling dircache */ +#define DIRCACHE_MIN_MB_BANDWIDTH 300 +#define DIRCACHE_MIN_BANDWIDTH (DIRCACHE_MIN_MB_BANDWIDTH*ONE_MEGABYTE) +#define STRINGIFY(val) #val + +/** Create a warning message for emitting if we are a dircache but may not have + * enough system memory, or if we are not a dircache but probably should be. + * Return -1 when a message is returned in *msg*, else return 0. */ +STATIC int +have_enough_mem_for_dircache(const or_options_t *options, size_t total_mem, + char **msg) +{ + *msg = NULL; + /* XXX We should possibly be looking at MaxMemInQueues here + * unconditionally. Or we should believe total_mem unconditionally. */ + if (total_mem == 0) { + if (get_total_system_memory(&total_mem) < 0) { + total_mem = options->MaxMemInQueues >= SIZE_MAX ? + SIZE_MAX : (size_t)options->MaxMemInQueues; + } + } + if (options->DirCache) { + if (total_mem < DIRCACHE_MIN_BANDWIDTH) { + if (options->BridgeRelay) { + *msg = strdup("Running a Bridge with less than " + STRINGIFY(DIRCACHE_MIN_MB_BANDWIDTH) " MB of memory is " + "not recommended."); + } else { + *msg = strdup("Being a directory cache (default) with less than " + STRINGIFY(DIRCACHE_MIN_MB_BANDWIDTH) " MB of memory is " + "not recommended and may consume most of the available " + "resources, consider disabling this functionality by " + "setting the DirCache option to 0."); + } + } + } else { + if (total_mem >= DIRCACHE_MIN_BANDWIDTH) { + *msg = strdup("DirCache is disabled and we are configured as a " + "relay. This may disqualify us from becoming a guard in the " + "future."); + } + } + return *msg == NULL ? 0 : -1; +} +#undef STRINGIFY + /** Helper: return true iff s1 and s2 are both NULL, or both non-NULL * equal strings. */ static int @@ -4273,7 +4348,8 @@ options_transition_affects_descriptor(const or_options_t *old_options, !opt_streq(old_options->MyFamily, new_options->MyFamily) || !opt_streq(old_options->AccountingStart, new_options->AccountingStart) || old_options->AccountingMax != new_options->AccountingMax || - public_server_mode(old_options) != public_server_mode(new_options)) + public_server_mode(old_options) != public_server_mode(new_options) || + old_options->DirCache != new_options->DirCache) return 1; return 0; @@ -6018,15 +6094,6 @@ warn_nonlocal_controller_ports(smartlist_t *ports, unsigned forbid_nonlocal) } SMARTLIST_FOREACH_END(port); } -#define CL_PORT_NO_STREAM_OPTIONS (1u<<0) -#define CL_PORT_WARN_NONLOCAL (1u<<1) -#define CL_PORT_ALLOW_EXTRA_LISTENADDR (1u<<2) -#define CL_PORT_SERVER_OPTIONS (1u<<3) -#define CL_PORT_FORBID_NONLOCAL (1u<<4) -#define CL_PORT_TAKES_HOSTNAMES (1u<<5) -#define CL_PORT_IS_UNIXSOCKET (1u<<6) -#define CL_PORT_DFLT_GROUP_WRITABLE (1u<<7) - #ifdef HAVE_SYS_UN_H /** Parse the given <b>addrport</b> and set <b>path_out</b> if a Unix socket @@ -6114,7 +6181,7 @@ config_parse_unix_port(const char *addrport, char **path_out) * <b>out</b> for every port that the client should listen on. Return 0 * on success, -1 on failure. */ -static int +STATIC int parse_port_config(smartlist_t *out, const config_line_t *ports, const config_line_t *listenaddrs, @@ -6320,7 +6387,7 @@ parse_port_config(smartlist_t *out, } port = ptmp; } else { - log_warn(LD_CONFIG, "Couldn't parse address '%s' for %sPort", + log_warn(LD_CONFIG, "Couldn't parse address %s for %sPort", escaped(addrport), portname); goto err; } @@ -7344,7 +7411,7 @@ getinfo_helper_config(control_connection_t *conn, smartlist_free(sl); } else if (!strcmp(question, "config/defaults")) { smartlist_t *sl = smartlist_new(); - int i, dirauth_lines_seen = 0; + int i, dirauth_lines_seen = 0, fallback_lines_seen = 0; for (i = 0; option_vars_[i].name; ++i) { const config_var_t *var = &option_vars_[i]; if (var->initvalue != NULL) { @@ -7355,6 +7422,13 @@ getinfo_helper_config(control_connection_t *conn, */ ++dirauth_lines_seen; } + if (strcmp(option_vars_[i].name, "FallbackDir") == 0) { + /* + * Similarly count fallback lines, so that we can decided later + * to add the defaults manually. + */ + ++fallback_lines_seen; + } char *val = esc_for_log(var->initvalue); smartlist_add_asprintf(sl, "%s %s\n",var->name,val); tor_free(val); @@ -7380,6 +7454,24 @@ getinfo_helper_config(control_connection_t *conn, } } + if (fallback_lines_seen == 0 && + get_options()->UseDefaultFallbackDirs == 1) { + /* + * We didn't see any explicitly configured fallback mirrors, + * so add the defaults to the list manually. + * + * default_fallbacks is included earlier in this file and + * is a const char ** NULL-terminated array of fallback config lines. + */ + const char **i; + + for (i = default_fallbacks; *i != NULL; ++i) { + char *val = esc_for_log(*i); + smartlist_add_asprintf(sl, "FallbackDir %s\n", val); + tor_free(val); + } + } + *answer = smartlist_join_strings(sl, "", 0, NULL); SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); smartlist_free(sl); diff --git a/src/or/config.h b/src/or/config.h index bfdd1694eb..c7ce57d2aa 100644 --- a/src/or/config.h +++ b/src/or/config.h @@ -16,7 +16,7 @@ MOCK_DECL(const char*, get_dirportfrontpage, (void)); MOCK_DECL(const or_options_t *, get_options, (void)); -or_options_t *get_options_mutable(void); +MOCK_DECL(or_options_t *, get_options_mutable, (void)); int set_options(or_options_t *new_val, char **msg); void config_free_all(void); const char *safe_str_client(const char *address); @@ -136,6 +136,17 @@ smartlist_t *get_options_from_transport_options_line(const char *line, smartlist_t *get_options_for_server_transport(const char *transport); #ifdef CONFIG_PRIVATE + +#define CL_PORT_NO_STREAM_OPTIONS (1u<<0) +#define CL_PORT_WARN_NONLOCAL (1u<<1) +#define CL_PORT_ALLOW_EXTRA_LISTENADDR (1u<<2) +#define CL_PORT_SERVER_OPTIONS (1u<<3) +#define CL_PORT_FORBID_NONLOCAL (1u<<4) +#define CL_PORT_TAKES_HOSTNAMES (1u<<5) +#define CL_PORT_IS_UNIXSOCKET (1u<<6) +#define CL_PORT_DFLT_GROUP_WRITABLE (1u<<7) + +STATIC int options_act(const or_options_t *old_options); #ifdef TOR_UNIT_TESTS extern struct config_format_t options_format; #endif @@ -158,6 +169,16 @@ STATIC int parse_dir_authority_line(const char *line, dirinfo_type_t required_type, int validate_only); STATIC int parse_dir_fallback_line(const char *line, int validate_only); +STATIC int have_enough_mem_for_dircache(const or_options_t *options, + size_t total_mem, char **msg); +STATIC int parse_port_config(smartlist_t *out, + const config_line_t *ports, + const config_line_t *listenaddrs, + const char *portname, + int listener_type, + const char *defaultaddr, + int defaultport, + const unsigned flags); #endif #endif diff --git a/src/or/connection.c b/src/or/connection.c index 63bfb2e01e..a8ce220c60 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1138,11 +1138,12 @@ connection_listener_new(const struct sockaddr *listensockaddr, tor_socket_strerror(errno)); } -#if defined USE_TRANSPARENT && defined(IP_TRANSPARENT) +#if defined(USE_TRANSPARENT) && defined(IP_TRANSPARENT) if (options->TransProxyType_parsed == TPT_TPROXY && type == CONN_TYPE_AP_TRANS_LISTENER) { int one = 1; - if (setsockopt(s, SOL_IP, IP_TRANSPARENT, &one, sizeof(one)) < 0) { + if (setsockopt(s, SOL_IP, IP_TRANSPARENT, (void*)&one, + (socklen_t)sizeof(one)) < 0) { const char *extra = ""; int e = tor_socket_errno(s); if (e == EPERM) @@ -1156,16 +1157,11 @@ connection_listener_new(const struct sockaddr *listensockaddr, #ifdef IPV6_V6ONLY if (listensockaddr->sa_family == AF_INET6) { -#ifdef _WIN32 - /* In Redmond, this kind of thing passes for standards-conformance. */ - DWORD one = 1; -#else int one = 1; -#endif /* We need to set IPV6_V6ONLY so that this socket can't get used for * IPv4 connections. */ if (setsockopt(s,IPPROTO_IPV6, IPV6_V6ONLY, - (void*)&one, sizeof(one)) < 0) { + (void*)&one, (socklen_t)sizeof(one)) < 0) { int e = tor_socket_errno(s); log_warn(LD_NET, "Error setting IPV6_V6ONLY flag: %s", tor_socket_strerror(e)); @@ -1447,7 +1443,7 @@ connection_handle_listener_read(connection_t *conn, int new_type) if (!SOCKET_OK(news)) { /* accept() error */ int e = tor_socket_errno(conn->s); if (ERRNO_IS_ACCEPT_EAGAIN(e)) { - return 0; /* he hung up before we could accept(). that's fine. */ + return 0; /* they hung up before we could accept(). that's fine. */ } else if (ERRNO_IS_RESOURCE_LIMIT(e)) { warn_too_many_conns(); return 0; diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 8a3beb3ce9..758d583c39 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -800,20 +800,23 @@ connection_ap_attach_pending(int retry) if (untried_pending_connections == 0 && !retry) return; - SMARTLIST_FOREACH_BEGIN(pending_entry_connections, + /* Don't allow modifications to pending_entry_connections while we are + * iterating over it. */ + smartlist_t *pending = pending_entry_connections; + pending_entry_connections = smartlist_new(); + + SMARTLIST_FOREACH_BEGIN(pending, entry_connection_t *, entry_conn) { connection_t *conn = ENTRY_TO_CONN(entry_conn); tor_assert(conn && entry_conn); if (conn->marked_for_close) { UNMARK(); - SMARTLIST_DEL_CURRENT(pending_entry_connections, entry_conn); continue; } if (conn->magic != ENTRY_CONNECTION_MAGIC) { log_warn(LD_BUG, "%p has impossible magic value %u.", entry_conn, (unsigned)conn->magic); UNMARK(); - SMARTLIST_DEL_CURRENT(pending_entry_connections, entry_conn); continue; } if (conn->state != AP_CONN_STATE_CIRCUIT_WAIT) { @@ -822,7 +825,6 @@ connection_ap_attach_pending(int retry) entry_conn, conn_state_to_string(conn->type, conn->state)); UNMARK(); - SMARTLIST_DEL_CURRENT(pending_entry_connections, entry_conn); continue; } @@ -832,18 +834,19 @@ connection_ap_attach_pending(int retry) END_STREAM_REASON_CANT_ATTACH); } - if (conn->marked_for_close || - conn->type != CONN_TYPE_AP || - conn->state != AP_CONN_STATE_CIRCUIT_WAIT) { - UNMARK(); - SMARTLIST_DEL_CURRENT(pending_entry_connections, entry_conn); - continue; + if (! conn->marked_for_close && + conn->type == CONN_TYPE_AP && + conn->state == AP_CONN_STATE_CIRCUIT_WAIT) { + if (!smartlist_contains(pending_entry_connections, entry_conn)) { + smartlist_add(pending_entry_connections, entry_conn); + continue; + } } - tor_assert(conn->magic == ENTRY_CONNECTION_MAGIC); - + UNMARK(); } SMARTLIST_FOREACH_END(entry_conn); + smartlist_free(pending); untried_pending_connections = 0; } diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 73e4d19369..d778eb3b4f 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -1581,7 +1581,7 @@ connection_or_nonopen_was_started_here(or_connection_t *conn) } /** <b>Conn</b> just completed its handshake. Return 0 if all is well, and - * return -1 if he is lying, broken, or otherwise something is wrong. + * return -1 if they are lying, broken, or otherwise something is wrong. * * If we initiated this connection (<b>started_here</b> is true), make sure * the other side sent a correctly formed certificate. If I initiated the @@ -1754,7 +1754,7 @@ connection_or_client_used(or_connection_t *conn) * * Make sure we are happy with the person we just handshaked with. * - * If he initiated the connection, make sure he's not already connected, + * If they initiated the connection, make sure they're not already connected, * then initialize conn from the information in router. * * If all is successful, call circuit_n_conn_done() to handle events diff --git a/src/or/directory.c b/src/or/directory.c index b3a2f36f20..9419f2a590 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -144,7 +144,7 @@ purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose) /** Return a newly allocated string describing <b>auth</b>. Only describes * authority features. */ -static char * +STATIC char * authdir_type_to_string(dirinfo_type_t auth) { char *result; @@ -163,7 +163,7 @@ authdir_type_to_string(dirinfo_type_t auth) } /** Return a string describing a given directory connection purpose. */ -static const char * +STATIC const char * dir_conn_purpose_to_string(int purpose) { switch (purpose) @@ -371,7 +371,7 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, /** Return true iff, according to the values in <b>options</b>, we should be * using directory guards for direct downloads of directory information. */ -static int +STATIC int should_use_directory_guards(const or_options_t *options) { /* Public (non-bridge) servers never use directory guards. */ @@ -766,15 +766,15 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status, * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we * want to fetch. */ -void -directory_initiate_command_routerstatus(const routerstatus_t *status, - uint8_t dir_purpose, - uint8_t router_purpose, - dir_indirection_t indirection, - const char *resource, - const char *payload, - size_t payload_len, - time_t if_modified_since) +MOCK_IMPL(void, directory_initiate_command_routerstatus, + (const routerstatus_t *status, + uint8_t dir_purpose, + uint8_t router_purpose, + dir_indirection_t indirection, + const char *resource, + const char *payload, + size_t payload_len, + time_t if_modified_since)) { directory_initiate_command_routerstatus_rend(status, dir_purpose, router_purpose, @@ -812,7 +812,7 @@ connection_dir_request_failed(dir_connection_t *conn) return; /* this was a test fetch. don't retry. */ } if (!entry_list_is_constrained(get_options())) - router_set_status(conn->identity_digest, 0); /* don't try him again */ + router_set_status(conn->identity_digest, 0); /* don't try this one again */ if (conn->base_.purpose == DIR_PURPOSE_FETCH_SERVERDESC || conn->base_.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) { log_info(LD_DIR, "Giving up on serverdesc/extrainfo fetch from " @@ -2742,7 +2742,7 @@ client_likes_consensus(networkstatus_t *v, const char *want_url) /** Return the compression level we should use for sending a compressed * response of size <b>n_bytes</b>. */ -static zlib_compression_level_t +STATIC zlib_compression_level_t choose_compression_level(ssize_t n_bytes) { if (! have_been_under_memory_pressure()) { @@ -3811,11 +3811,10 @@ connection_dir_finished_connecting(dir_connection_t *conn) * Then return a list of int pointers defining download delays in seconds. * Helper function for download_status_increment_failure(), * download_status_reset(), and download_status_increment_attempt(). */ -static const smartlist_t * +STATIC const smartlist_t * find_dl_schedule(download_status_t *dls, const or_options_t *options) { - /* XX/teor Replace with dir_server_mode from #12538 */ - const int dir_server = options->DirPort_set; + const int dir_server = dir_server_mode(options); const int multi_d = networkstatus_consensus_can_use_multiple_directories( options); const int we_are_bootstrapping = networkstatus_consensus_is_boostrapping( diff --git a/src/or/directory.h b/src/or/directory.h index 61c29baf06..2630705fdb 100644 --- a/src/or/directory.h +++ b/src/or/directory.h @@ -39,14 +39,16 @@ typedef enum { DIRIND_ANON_DIRPORT, } dir_indirection_t; -void directory_initiate_command_routerstatus(const routerstatus_t *status, - uint8_t dir_purpose, - uint8_t router_purpose, - dir_indirection_t indirection, - const char *resource, - const char *payload, - size_t payload_len, - time_t if_modified_since); +MOCK_DECL(void, directory_initiate_command_routerstatus, + (const routerstatus_t *status, + uint8_t dir_purpose, + uint8_t router_purpose, + dir_indirection_t indirection, + const char *resource, + const char *payload, + size_t payload_len, + time_t if_modified_since)); + void directory_initiate_command_routerstatus_rend(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, @@ -101,7 +103,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, @@ -146,6 +149,13 @@ STATIC int connection_dir_would_close_consensus_conn_helper(void); STATIC int download_status_schedule_get_delay(download_status_t *dls, const smartlist_t *schedule, time_t now); + +STATIC char* authdir_type_to_string(dirinfo_type_t auth); +STATIC const char * dir_conn_purpose_to_string(int purpose); +STATIC int should_use_directory_guards(const or_options_t *options); +STATIC zlib_compression_level_t choose_compression_level(ssize_t n_bytes); +STATIC const smartlist_t *find_dl_schedule(download_status_t *dls, + const or_options_t *options); #endif #endif diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 39563c3932..620d324704 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 @@ -1350,8 +1350,9 @@ dirserv_thinks_router_is_unreliable(time_t now, } /** Return true iff <b>router</b> should be assigned the "HSDir" flag. + * * Right now this means it advertises support for it, it has a high uptime, - * it has a DirPort open, it has the Stable and Fast flag and it's currently + * it's a directory cache, it has the Stable and Fast flags, and it's currently * considered Running. * * This function needs to be called after router-\>is_running has @@ -1378,7 +1379,8 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router, else uptime = real_uptime(router, now); - return (router->wants_to_be_hs_dir && router->dir_port && + return (router->wants_to_be_hs_dir && + router->supports_tunnelled_dir_requests && node->is_stable && node->is_fast && uptime >= get_options()->MinUptimeHidServDirectoryV2 && router_is_active(router, node, now)); @@ -1921,7 +1923,7 @@ routerstatus_format_entry(const routerstatus_t *rs, const char *version, rs->is_hs_dir?" HSDir":"", rs->is_flagged_running?" Running":"", rs->is_stable?" Stable":"", - (rs->dir_port!=0)?" V2Dir":"", + rs->is_v2_dir?" V2Dir":"", rs->is_valid?" Valid":""); /* length of "opt v \n" */ @@ -2185,6 +2187,7 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, strlcpy(rs->nickname, ri->nickname, sizeof(rs->nickname)); rs->or_port = ri->or_port; rs->dir_port = ri->dir_port; + rs->is_v2_dir = ri->supports_tunnelled_dir_requests; if (options->AuthDirHasIPv6Connectivity == 1 && !tor_addr_is_null(&ri->ipv6_addr) && node->last_reachable6 >= now - REACHABLE_TIMEOUT) { diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 0449e9d8d9..b61b33af79 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -54,7 +54,6 @@ static int dirvote_perform_vote(void); static void dirvote_clear_votes(int all_votes); static int dirvote_compute_consensuses(void); static int dirvote_publish_consensus(void); -static char *make_consensus_method_list(int low, int high, const char *sep); /* ===== * Voting @@ -564,7 +563,7 @@ consensus_method_is_supported(int method) /** Return a newly allocated string holding the numbers between low and high * (inclusive) that are supported consensus methods. */ -static char * +STATIC char * make_consensus_method_list(int low, int high, const char *separator) { char *list; diff --git a/src/or/dirvote.h b/src/or/dirvote.h index 966d163088..cc526ea34e 100644 --- a/src/or/dirvote.h +++ b/src/or/dirvote.h @@ -177,6 +177,7 @@ STATIC char *format_networkstatus_vote(crypto_pk_t *private_key, STATIC char *dirvote_compute_params(smartlist_t *votes, int method, int total_authorities); STATIC char *compute_consensus_package_lines(smartlist_t *votes); +STATIC char *make_consensus_method_list(int low, int high, const char *sep); #endif #endif diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index 1ce44d1026..d6bef658ff 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -1156,7 +1156,7 @@ choose_random_entry_impl(cpath_build_state_t *state, int for_directory, } else { /* Try to have at least 2 choices available. This way we don't * get stuck with a single live-but-crummy entry and just keep - * using him. + * using it. * (We might get 2 live-but-crummy entry guards, but so be it.) */ preferred_min = 2; } diff --git a/src/or/ext_orport.c b/src/or/ext_orport.c index f159f7d0a6..810fa0d9aa 100644 --- a/src/or/ext_orport.c +++ b/src/or/ext_orport.c @@ -151,7 +151,7 @@ init_ext_or_cookie_authentication(int is_enabled) } /** Read data from <b>conn</b> and see if the client sent us the - * authentication type that she prefers to use in this session. + * authentication type that they prefer to use in this session. * * Return -1 if we received corrupted data or if we don't support the * authentication type. Return 0 if we need more data in diff --git a/src/or/fallback_dirs.inc b/src/or/fallback_dirs.inc index d9214cb884..d05f16f4ea 100644 --- a/src/or/fallback_dirs.inc +++ b/src/or/fallback_dirs.inc @@ -1 +1,206 @@ -/* This list will be empty until opt-ins are finalised. */ +/* Trial fallbacks for 0.2.8.1-alpha with ADDRESS_AND_PORT_STABLE_DAYS = 30 + * This works around an issue where relays post a descriptor without a DirPort + * when restarted. If these relays stay up, they will have been up for 120 days + * by the 0.2.8 stable release -- teor */ +/* Whitelist & blacklist excluded 1070 of 1091 candidates. */ +/* +Fallback Directory Summary +Final Count: 21 (Eligible 21, Usable 21, Target 290 (1454 * 0.200000), Clamped to 500) +*/ +/* Ignore low fallback numbers in alpha builds -- teor +#error Fallback Count 21 is too low. Must be at least 100 for diversity. Try adding entries to the whitelist, or setting INCLUDE_UNLISTED_ENTRIES = True. +*/ +/* +Final Weight: 491920 (Eligible 546000) +Max Weight: 43680 (8.879%) (Clamped to 10.000%) +Min Weight: 8080 (1.643%) (Clamped to 0.100%) +Clamped: 54080 (10.994%) Excess Weight, 4 High Weight Fallbacks (19.0%) +*/ +/* +Onionoo Source: details Date: 2016-01-18 00:00:00 Version: 3.0 +URL: https://onionoo.torproject.org/details?fields=fingerprint%2Cnickname%2Ccontact%2Clast_changed_address_or_port%2Cconsensus_weight%2Cor_addresses%2Cdir_address%2Crecommended_version%2Cflags&flag=V2Dir&type=relay&last_seen_days=-7&first_seen_days=30- +*/ +/* +Onionoo Source: uptime Date: 2016-01-18 00:00:00 Version: 3.0 +URL: https://onionoo.torproject.org/uptime?first_seen_days=30-&flag=V2Dir&type=relay&last_seen_days=-7 +*/ +/* +wagner +Flags: Fast Guard Running Stable V2Dir Valid +Fallback Weight: 43680 / 491920 (8.879%) +Consensus Weight: 62600 / 546000 (11.465%) +Rarely used email <trff914 AT gmail DOT com> +*/ +"5.175.233.86:80 orport=443 id=5525D0429BFE5DC4F1B0E9DE47A4CFA169661E33" +" weight=43680", +/* +kitten2 +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 43680 / 491920 (8.879%) +Consensus Weight: 59100 / 546000 (10.824%) +0xEFB74277ECE4E222 Aeris <aeris+tor AT imirhil DOT fr> - 1aerisnnLWPchhDSXpxWGYWwLiSFUVFnd +*/ +"62.210.124.124:9130 orport=9101 id=2EBD117806EE43C3CC885A8F1E4DC60F207E7D3E" +" ipv6=[2001:bc8:3f23:100::1]:9101" +" weight=43680", +/* +kitten1 +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 43680 / 491920 (8.879%) +Consensus Weight: 57600 / 546000 (10.549%) +0xEFB74277ECE4E222 Aeris <aeris+tor AT imirhil DOT fr> - 1aerisnnLWPchhDSXpxWGYWwLiSFUVFnd +*/ +"62.210.124.124:9030 orport=9001 id=86E78DD3720C78DA8673182EF96C54B162CD660C" +" ipv6=[2001:bc8:3f23:100::1]:9001" +" weight=43680", +/* +fluxe4 +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 43680 / 491920 (8.879%) +Consensus Weight: 49500 / 546000 (9.066%) +Sebastian <tor@sebastianhahn.net> - 12NbRAjAG5U3LLWETSF7fSTcdaz32Mu5CN +*/ +"131.188.40.188:443 orport=80 id=EBE718E1A49EE229071702964F8DB1F318075FF8" +" weight=43680", +/* +BabylonNetwork03 +Flags: Exit Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 38700 / 491920 (7.867%) +Babylon Network | noc <AT> babylon <DOT> network | PGP 0x2A540FA5 | 1HiSG8pia5DdDLUMyYNkF9sicGozojZLnH +*/ +"193.111.136.162:80 orport=443 id=C79552275DFCD486B942510EF663ED36ACA1A84B" +" ipv6=[2001:4ba0:cafe:10d0::1]:443" +" weight=38700", +/* +tornoderdednl +Flags: Fast Guard Running Stable V2Dir Valid +Fallback Weight: 33000 / 491920 (6.708%) +0x4871E82F Thom Wiggers <thom @AT@ RDED POINT NL> BTC 1DLyDFV13zhCWJYHMh5bk5C58yYvpxqxfQ +*/ +"178.62.199.226:80 orport=443 id=CBEFF7BA4A4062045133C053F2D70524D8BBE5BE" +" ipv6=[2a03:b0c0:2:d0::b7:5001]:443" +" weight=33000", +/* +fluxe3 +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 31500 / 491920 (6.403%) +Sebastian <tor@sebastianhahn.net> - 12NbRAjAG5U3LLWETSF7fSTcdaz32Mu5CN +*/ +"78.47.18.110:443 orport=80 id=F8D27B163B9247B232A2EEE68DD8B698695C28DE" +" weight=31500", +/* +BabylonNetwork02 +Flags: Exit Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 27300 / 491920 (5.550%) +Babylon Network | noc <AT> babylon <DOT> network | PGP 0x2A540FA5 | 1HiSG8pia5DdDLUMyYNkF9sicGozojZLnH +*/ +"149.202.98.161:80 orport=443 id=54660C671B47E6986B465B80444414BD19E5A34B" +" ipv6=[2001:41d0:8:4528::161]:443" +" weight=27300", +/* +coby +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 20400 / 491920 (4.147%) +c0by <coby AT 127001 dot ovh> +*/ +"51.255.33.237:9091 orport=9001 id=A360C21FA87FFA2046D92C17086A6B47E5C68109" +" weight=20400", +/* +kili +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 19300 / 491920 (3.923%) +0x49CBC553 Joost Rijneveld <joost AT joostrijneveld dot nl> +*/ +"178.62.173.203:9030 orport=9001 id=DD85503F2D1F52EF9EAD621E942298F46CD2FC10" +" ipv6=[2a03:b0c0:0:1010::a4:b001]:9001" +" weight=19300", +/* +Logforme +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 18600 / 491920 (3.781%) +Logforme <m7527 AT abc dot se> +*/ +"84.219.173.60:9030 orport=443 id=855BC2DABE24C861CD887DB9B2E950424B49FC34" +" weight=18600", +/* +eriador +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 17400 / 491920 (3.537%) +hwertiout695@safe-mail.net +*/ +"85.25.138.93:9030 orport=4029 id=6DE61A6F72C1E5418A66BFED80DFB63E4C77668F" +" weight=17400", +/* +Doedel24 +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 17000 / 491920 (3.456%) +Felix <zwiebel ta quantentunnel tod de> +*/ +"178.254.20.134:9030 orport=9001 id=2CE96A8A1DA032664C90F574AFFBECE18A6E8DFC" +" weight=17000", +/* +GrmmlLitavis +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 15500 / 491920 (3.151%) +<tor AT grmml DOT eu> +*/ +"5.39.88.19:9030 orport=9001 id=7CB8C31432A796731EA7B6BF4025548DFEB25E0C" +" ipv6=[2001:41d0:8:9a13::1]:9050" +" weight=15500", +/* +Doedel21 +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 13800 / 491920 (2.805%) +Felix <zwiebel ta quantentunnel tod de> +*/ +"178.254.44.135:80 orport=443 id=AE6A8C18E7499B586CD36246AC4BCAFFBBF93AB2" +" weight=13800", +/* +Unnamed +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 13400 / 491920 (2.724%) +monitor0penmailbox0rg +*/ +"217.12.199.208:80 orport=443 id=DF3AED4322B1824BF5539AE54B2D1B38E080FF05" +" weight=13400", +/* +Doedel26 +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 12800 / 491920 (2.602%) +Felix <zwiebel ta quantentunnel tod de> +*/ +"178.254.20.134:80 orport=443 id=9F5068310818ED7C70B0BC4087AB55CB12CB4377" +" weight=12800", +/* +Doedel22 +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 12000 / 491920 (2.439%) +Felix <zwiebel ta quantentunnel tod de> +*/ +"178.254.44.135:9030 orport=9001 id=8FA37B93397015B2BC5A525C908485260BE9F422" +" weight=12000", +/* +kitten4 +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 10100 / 491920 (2.053%) +0xEFB74277ECE4E222 Aeris <aeris+tor AT imirhil DOT fr> - 1aerisnnLWPchhDSXpxWGYWwLiSFUVFnd +*/ +"212.47.237.95:9130 orport=9101 id=6FB38EB22E57EF7ED5EF00238F6A48E553735D88" +" weight=10100", +/* +Binnacle +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 8320 / 491920 (1.691%) +starlight dot YYYYqQ at binnacle dot cx +*/ +"108.53.208.157:80 orport=443 id=4F0DB7E687FC7C0AE55C8F243DA8B0EB27FBF1F2" +" weight=8320", +/* +PedicaboMundi +Flags: Fast Guard HSDir Running Stable V2Dir Valid +Fallback Weight: 8080 / 491920 (1.643%) +0x43DE8191 - 12LiRiasTEL346ZFjgCh5e3nBexQuvDBTg +*/ +"144.76.14.145:110 orport=143 id=14419131033443AE6E21DA82B0D307F7CAE42BDB" +" ipv6=[2a01:4f8:190:9490::dead]:443" +" weight=8080", diff --git a/src/or/geoip.c b/src/or/geoip.c index 3ef1672f52..26030ae52a 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -1279,6 +1279,8 @@ geoip_dirreq_stats_write(time_t now) /* Generate history string .*/ str = geoip_format_dirreq_stats(now); + if (! str) + goto done; /* Write dirreq-stats string to disk. */ if (!check_or_create_data_subdir("stats")) { diff --git a/src/or/hibernate.c b/src/or/hibernate.c index 5f727e27d4..7f8530b221 100644 --- a/src/or/hibernate.c +++ b/src/or/hibernate.c @@ -412,11 +412,15 @@ configure_accounting(time_t now) /** Return the relevant number of bytes sent/received this interval * based on the set AccountingRule */ -static uint64_t +uint64_t get_accounting_bytes(void) { if (get_options()->AccountingRule == ACCT_SUM) return n_bytes_read_in_interval+n_bytes_written_in_interval; + else if (get_options()->AccountingRule == ACCT_IN) + return n_bytes_read_in_interval; + else if (get_options()->AccountingRule == ACCT_OUT) + return n_bytes_written_in_interval; else return MAX(n_bytes_read_in_interval, n_bytes_written_in_interval); } @@ -1010,7 +1014,7 @@ getinfo_helper_accounting(control_connection_t *conn, else *answer = tor_strdup("awake"); } else if (!strcmp(question, "accounting/bytes")) { - tor_asprintf(answer, U64_FORMAT" "U64_FORMAT, + tor_asprintf(answer, U64_FORMAT" "U64_FORMAT, U64_PRINTF_ARG(n_bytes_read_in_interval), U64_PRINTF_ARG(n_bytes_written_in_interval)); } else if (!strcmp(question, "accounting/bytes-left")) { @@ -1022,6 +1026,18 @@ getinfo_helper_accounting(control_connection_t *conn, total_left = limit - total_bytes; tor_asprintf(answer, U64_FORMAT" "U64_FORMAT, U64_PRINTF_ARG(total_left), U64_PRINTF_ARG(total_left)); + } else if (get_options()->AccountingRule == ACCT_IN) { + uint64_t read_left = 0; + if (n_bytes_read_in_interval < limit) + read_left = limit - n_bytes_read_in_interval; + tor_asprintf(answer, U64_FORMAT" "U64_FORMAT, + U64_PRINTF_ARG(read_left), U64_PRINTF_ARG(limit)); + } else if (get_options()->AccountingRule == ACCT_OUT) { + uint64_t write_left = 0; + if (n_bytes_written_in_interval < limit) + write_left = limit - n_bytes_written_in_interval; + tor_asprintf(answer, U64_FORMAT" "U64_FORMAT, + U64_PRINTF_ARG(limit), U64_PRINTF_ARG(write_left)); } else { uint64_t read_left = 0, write_left = 0; if (n_bytes_read_in_interval < limit) diff --git a/src/or/hibernate.h b/src/or/hibernate.h index b9e619c5ad..e0d0c29bdb 100644 --- a/src/or/hibernate.h +++ b/src/or/hibernate.h @@ -19,6 +19,7 @@ MOCK_DECL(int, accounting_is_enabled, (const or_options_t *options)); int accounting_get_interval_length(void); MOCK_DECL(time_t, accounting_get_end_time, (void)); void configure_accounting(time_t now); +uint64_t get_accounting_bytes(void); void accounting_run_housekeeping(time_t now); void accounting_add_bytes(size_t n_read, size_t n_written, int seconds); int accounting_record_bandwidth_usage(time_t now, or_state_t *state); diff --git a/src/or/include.am b/src/or/include.am index 5ec96e5a93..712ae18406 100644 --- a/src/or/include.am +++ b/src/or/include.am @@ -93,7 +93,8 @@ src_or_libtor_testing_a_SOURCES = $(LIBTOR_A_SOURCES) src_or_tor_SOURCES = src/or/tor_main.c AM_CPPFLAGS += -I$(srcdir)/src/or -Isrc/or -src/or/tor_main.o: micro-revision.i +src/or/tor_main.$(OBJEXT) \ + src/or/src_or_tor_cov-tor_main.$(OBJEXT): micro-revision.i AM_CPPFLAGS += -DSHARE_DATADIR="\"$(datadir)\"" \ -DLOCALSTATEDIR="\"$(localstatedir)\"" \ @@ -109,7 +110,7 @@ src_or_libtor_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) src_or_tor_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@ src_or_tor_LDADD = src/or/libtor.a src/common/libor.a \ - src/common/libor-crypto.a $(LIBDONNA) \ + src/common/libor-crypto.a $(LIBKECCAK_TINY) $(LIBDONNA) \ src/common/libor-event.a src/trunnel/libor-trunnel.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ @TOR_SYSTEMD_LIBS@ @@ -120,7 +121,7 @@ src_or_tor_cov_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_CPPFLAGS) src_or_tor_cov_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) src_or_tor_cov_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@ src_or_tor_cov_LDADD = src/or/libtor-testing.a src/common/libor-testing.a \ - src/common/libor-crypto-testing.a $(LIBDONNA) \ + src/common/libor-crypto-testing.a $(LIBKECCAK_TINY) $(LIBDONNA) \ src/common/libor-event-testing.a src/trunnel/libor-trunnel-testing.a \ @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ @TOR_SYSTEMD_LIBS@ diff --git a/src/or/main.c b/src/or/main.c index 455cba4513..bd4f7eaa71 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -225,11 +225,13 @@ set_buffer_lengths_to_zero(tor_socket_t s) { int zero = 0; int r = 0; - if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&zero, sizeof(zero))) { + if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&zero, + (socklen_t)sizeof(zero))) { log_warn(LD_NET, "Unable to clear SO_SNDBUF"); r = -1; } - if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&zero, sizeof(zero))) { + if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&zero, + (socklen_t)sizeof(zero))) { log_warn(LD_NET, "Unable to clear SO_RCVBUF"); r = -1; } @@ -1299,7 +1301,7 @@ static periodic_event_item_t periodic_events[] = { /* These are pointers to members of periodic_events[] that are used to * implement particular callbacks. We keep them separate here so that we * can access them by name. We also keep them inside periodic_events[] - * so that we can implement "reset all timers" in a reasaonable way. */ + * so that we can implement "reset all timers" in a reasonable way. */ static periodic_event_item_t *check_descriptor_event=NULL; static periodic_event_item_t *fetch_networkstatus_event=NULL; static periodic_event_item_t *launch_descriptor_fetches_event=NULL; @@ -2067,8 +2069,9 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg) if (me && !check_whether_orport_reachable()) { char *address = tor_dup_ip(me->addr); log_warn(LD_CONFIG,"Your server (%s:%d) has not managed to confirm that " - "its ORPort is reachable. Please check your firewalls, ports, " - "address, /etc/hosts file, etc.", + "its ORPort is reachable. Relays do not publish descriptors " + "until their ORPort and DirPort are reachable. Please check " + "your firewalls, ports, address, /etc/hosts file, etc.", address, me->or_port); control_event_server_status(LOG_WARN, "REACHABILITY_FAILED ORADDRESS=%s:%d", @@ -2080,8 +2083,9 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg) char *address = tor_dup_ip(me->addr); log_warn(LD_CONFIG, "Your server (%s:%d) has not managed to confirm that its " - "DirPort is reachable. Please check your firewalls, ports, " - "address, /etc/hosts file, etc.", + "DirPort is reachable. Relays do not publish descriptors " + "until their ORPort and DirPort are reachable. Please check " + "your firewalls, ports, address, /etc/hosts file, etc.", address, me->dir_port); control_event_server_status(LOG_WARN, "REACHABILITY_FAILED DIRADDRESS=%s:%d", @@ -3460,6 +3464,9 @@ sandbox_init_filter(void) ".tmp"); OPEN_DATADIR2_SUFFIX("keys", "ed25519_master_id_public_key", ".tmp"); OPEN_DATADIR2_SUFFIX("keys", "ed25519_signing_secret_key", ".tmp"); + OPEN_DATADIR2_SUFFIX("keys", "ed25519_signing_secret_key_encrypted", + ".tmp"); + OPEN_DATADIR2_SUFFIX("keys", "ed25519_signing_public_key", ".tmp"); OPEN_DATADIR2_SUFFIX("keys", "ed25519_signing_cert", ".tmp"); OPEN_DATADIR2_SUFFIX("stats", "bridge-stats", ".tmp"); diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 0cf8873f03..f3a8276689 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -1461,6 +1461,38 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c, } SMARTLIST_FOREACH_JOIN_END(rs_old, rs_new); } +#ifdef TOR_UNIT_TESTS +/**Accept a <b>flavor</b> consensus <b>c</b> without any additional + * validation. This is exclusively for unit tests. + * We copy any ancillary information from a pre-existing consensus + * and then free the current one and replace it with the newly + * provided instance. Returns -1 on unrecognized flavor, 0 otherwise. + */ +int +networkstatus_set_current_consensus_from_ns(networkstatus_t *c, + const char *flavor) +{ + int flav = networkstatus_parse_flavor_name(flavor); + switch (flav) { + case FLAV_NS: + if (current_ns_consensus) { + networkstatus_copy_old_consensus_info(c, current_ns_consensus); + networkstatus_vote_free(current_ns_consensus); + } + current_ns_consensus = c; + break; + case FLAV_MICRODESC: + if (current_md_consensus) { + networkstatus_copy_old_consensus_info(c, current_md_consensus); + networkstatus_vote_free(current_md_consensus); + } + current_md_consensus = c; + break; + } + return current_md_consensus ? 0 : -1; +} +#endif //TOR_UNIT_TESTS + /** Try to replace the current cached v3 networkstatus with the one in * <b>consensus</b>. If we don't have enough certificates to validate it, * store it in consensus_waiting_for_certs and launch a certificate fetch. diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h index 4cb33c3fc0..4eab4d83f8 100644 --- a/src/or/networkstatus.h +++ b/src/or/networkstatus.h @@ -114,6 +114,10 @@ int networkstatus_get_weight_scale_param(networkstatus_t *ns); #ifdef NETWORKSTATUS_PRIVATE STATIC void vote_routerstatus_free(vote_routerstatus_t *rs); +#ifdef TOR_UNIT_TESTS +STATIC int networkstatus_set_current_consensus_from_ns(networkstatus_t *c, + const char *flavor); +#endif // TOR_UNIT_TESTS #endif #endif diff --git a/src/or/nodelist.c b/src/or/nodelist.c index 28d874133c..d7cada94d3 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -643,12 +643,19 @@ node_is_named(const node_t *node) int node_is_dir(const node_t *node) { - if (node->rs) - return node->rs->dir_port != 0; - else if (node->ri) - return node->ri->dir_port != 0; - else + if (node->rs) { + routerstatus_t * rs = node->rs; + /* This is true if supports_tunnelled_dir_requests is true which + * indicates that we support directory request tunnelled or through the + * DirPort. */ + return rs->is_v2_dir; + } else if (node->ri) { + routerinfo_t * ri = node->ri; + /* Both tunnelled request is supported or DirPort is set. */ + return ri->supports_tunnelled_dir_requests; + } else { return 0; + } } /** Return true iff <b>node</b> has either kind of usable descriptor -- that diff --git a/src/or/or.h b/src/or/or.h index 79b1c95ff0..697c576873 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -458,9 +458,11 @@ typedef enum { #define CIRCUIT_PURPOSE_OR_MIN_ 1 /** OR-side circuit purpose: normal circuit, at OR. */ #define CIRCUIT_PURPOSE_OR 1 -/** OR-side circuit purpose: At OR, from Bob, waiting for intro from Alices. */ +/** OR-side circuit purpose: At OR, from the service, waiting for intro from + * clients. */ #define CIRCUIT_PURPOSE_INTRO_POINT 2 -/** OR-side circuit purpose: At OR, from Alice, waiting for Bob. */ +/** OR-side circuit purpose: At OR, from the client, waiting for the service. + */ #define CIRCUIT_PURPOSE_REND_POINT_WAITING 3 /** OR-side circuit purpose: At OR, both circuits have this purpose. */ #define CIRCUIT_PURPOSE_REND_ESTABLISHED 4 @@ -479,43 +481,47 @@ typedef enum { * to becoming open, or they are open and have sent the * establish_rendezvous cell but haven't received an ack. * circuits that are c_rend_ready are open and have received a - * rend ack, but haven't heard from bob yet. if they have a + * rend ack, but haven't heard from the service yet. if they have a * buildstate->pending_final_cpath then they're expecting a - * cell from bob, else they're not. + * cell from the service, else they're not. * circuits that are c_rend_ready_intro_acked are open, and * some intro circ has sent its intro and received an ack. * circuits that are c_rend_joined are open, have heard from - * bob, and are talking to him. + * the service, and are talking to it. */ /** Client-side circuit purpose: Normal circuit, with cpath. */ #define CIRCUIT_PURPOSE_C_GENERAL 5 -/** Client-side circuit purpose: at Alice, connecting to intro point. */ +/** Client-side circuit purpose: at the client, connecting to intro point. */ #define CIRCUIT_PURPOSE_C_INTRODUCING 6 -/** Client-side circuit purpose: at Alice, sent INTRODUCE1 to intro point, +/** Client-side circuit purpose: at the client, sent INTRODUCE1 to intro point, * waiting for ACK/NAK. */ #define CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT 7 -/** Client-side circuit purpose: at Alice, introduced and acked, closing. */ +/** Client-side circuit purpose: at the client, introduced and acked, closing. + */ #define CIRCUIT_PURPOSE_C_INTRODUCE_ACKED 8 -/** Client-side circuit purpose: at Alice, waiting for ack. */ +/** Client-side circuit purpose: at the client, waiting for ack. */ #define CIRCUIT_PURPOSE_C_ESTABLISH_REND 9 -/** Client-side circuit purpose: at Alice, waiting for Bob. */ +/** Client-side circuit purpose: at the client, waiting for the service. */ #define CIRCUIT_PURPOSE_C_REND_READY 10 -/** Client-side circuit purpose: at Alice, waiting for Bob, INTRODUCE - * has been acknowledged. */ +/** Client-side circuit purpose: at the client, waiting for the service, + * INTRODUCE has been acknowledged. */ #define CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED 11 -/** Client-side circuit purpose: at Alice, rendezvous established. */ +/** Client-side circuit purpose: at the client, rendezvous established. */ #define CIRCUIT_PURPOSE_C_REND_JOINED 12 /** This circuit is used for build time measurement only */ #define CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT 13 #define CIRCUIT_PURPOSE_C_MAX_ 13 -/** Hidden-service-side circuit purpose: at Bob, waiting for introductions. */ +/** Hidden-service-side circuit purpose: at the service, waiting for + * introductions. */ #define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO 14 -/** Hidden-service-side circuit purpose: at Bob, successfully established - * intro. */ +/** Hidden-service-side circuit purpose: at the service, successfully + * established intro. */ #define CIRCUIT_PURPOSE_S_INTRO 15 -/** Hidden-service-side circuit purpose: at Bob, connecting to rend point. */ +/** Hidden-service-side circuit purpose: at the service, connecting to rend + * point. */ #define CIRCUIT_PURPOSE_S_CONNECT_REND 16 -/** Hidden-service-side circuit purpose: at Bob, rendezvous established. */ +/** Hidden-service-side circuit purpose: at the service, rendezvous + * established. */ #define CIRCUIT_PURPOSE_S_REND_JOINED 17 /** A testing circuit; not meant to be used for actual traffic. */ #define CIRCUIT_PURPOSE_TESTING 18 @@ -2147,6 +2153,11 @@ typedef struct { * tests for it. */ unsigned int needs_retest_if_added:1; + /** True iff this router included "tunnelled-dir-server" in its descriptor, + * implying it accepts tunnelled directory requests, or it advertised + * dir_port > 0. */ + unsigned int supports_tunnelled_dir_requests:1; + /** Tor can use this router for general positions in circuits; we got it * from a directory server as usual, or we're an authority and a server * uploaded it. */ @@ -2224,6 +2235,9 @@ typedef struct routerstatus_t { * an exit node. */ unsigned int is_hs_dir:1; /**< True iff this router is a v2-or-later hidden * service directory. */ + unsigned int is_v2_dir:1; /** True iff this router publishes an open DirPort + * or it claims to accept tunnelled dir requests. + */ /** True iff we know version info for this router. (i.e., a "v" entry was * included.) We'll replace all these with a big tor_version_t or a char[] * if the number of traits we care about ever becomes incredibly big. */ @@ -2325,7 +2339,7 @@ typedef struct microdesc_t { curve25519_public_key_t *onion_curve25519_pkey; /** Ed25519 identity key, if included. */ ed25519_public_key_t *ed25519_identity_pkey; - /** As routerinfo_t.ipv6_add */ + /** As routerinfo_t.ipv6_addr */ tor_addr_t ipv6_addr; /** As routerinfo_t.ipv6_orport */ uint16_t ipv6_orport; @@ -2343,7 +2357,7 @@ typedef struct microdesc_t { * Specifically, a node_t is a Tor router as we are using it: a router that * we are considering for circuits, connections, and so on. A node_t is a * thin wrapper around the routerstatus, routerinfo, and microdesc for a - * single wrapper, and provides a consistent interface for all of them. + * single router, and provides a consistent interface for all of them. * * Also, a node_t has mutable state. While a routerinfo, a routerstatus, * and a microdesc have[*] only the information read from a router @@ -3886,9 +3900,11 @@ typedef struct { * hibernate." */ /** How do we determine when our AccountingMax has been reached? * "max" for when in or out reaches AccountingMax - * "sum" for when in plus out reaches AccountingMax */ + * "sum" for when in plus out reaches AccountingMax + * "in" for when in reaches AccountingMax + * "out" for when out reaches AccountingMax */ char *AccountingRule_option; - enum { ACCT_MAX, ACCT_SUM } AccountingRule; + enum { ACCT_MAX, ACCT_SUM, ACCT_IN, ACCT_OUT } AccountingRule; /** Base64-encoded hash of accepted passwords for the control system. */ config_line_t *HashedControlPassword; @@ -3962,6 +3978,10 @@ typedef struct { /** Should we fetch our dir info at the start of the consensus period? */ int FetchDirInfoExtraEarly; + int DirCache; /**< Cache all directory documents and accept requests via + * tunnelled dir conns from clients. If 1, enabled (default); + * If 0, disabled. */ + char *VirtualAddrNetworkIPv4; /**< Address and mask to hand out for virtual * MAPADDRESS requests for IPv4 addresses */ char *VirtualAddrNetworkIPv6; /**< Address and mask to hand out for virtual diff --git a/src/or/relay.c b/src/or/relay.c index ee2f041dbd..aea51a165b 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -833,7 +833,7 @@ connection_ap_process_end_not_open( } } } - /* check if he *ought* to have allowed it */ + /* check if the exit *ought* to have allowed it */ adjust_exit_policy_from_exitpolicy_failure(circ, conn, diff --git a/src/or/rendclient.c b/src/or/rendclient.c index dc05d6f2ed..b822295832 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -182,7 +182,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc, goto cleanup; } - /* first 20 bytes of payload are the hash of Bob's pk */ + /* first 20 bytes of payload are the hash of the service's pk */ intro_key = NULL; SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *, intro, { @@ -1096,9 +1096,9 @@ rend_client_rendezvous_acked(origin_circuit_t *circ, const uint8_t *request, circ->base_.timestamp_dirty = time(NULL); /* From a path bias point of view, this circuit is now successfully used. - * Waiting any longer opens us up to attacks from Bob. He could induce - * Alice to attempt to connect to his hidden service and never reply - * to her rend requests */ + * Waiting any longer opens us up to attacks from malicious hidden services. + * They could induce the client to attempt to connect to their hidden + * service and never reply to the client's rend requests */ pathbias_mark_use_success(circ); /* XXXX This is a pretty brute-force approach. It'd be better to @@ -1110,7 +1110,7 @@ rend_client_rendezvous_acked(origin_circuit_t *circ, const uint8_t *request, return 0; } -/** Bob sent us a rendezvous cell; join the circuits. */ +/** The service sent us a rendezvous cell; join the circuits. */ int rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, size_t request_len) @@ -1135,7 +1135,8 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, log_info(LD_REND,"Got RENDEZVOUS2 cell from hidden service."); - /* first DH_KEY_LEN bytes are g^y from bob. Finish the dh handshake...*/ + /* first DH_KEY_LEN bytes are g^y from the service. Finish the dh + * handshake...*/ tor_assert(circ->build_state); tor_assert(circ->build_state->pending_final_cpath); hop = circ->build_state->pending_final_cpath; @@ -1164,7 +1165,7 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_C_REND_JOINED); hop->state = CPATH_STATE_OPEN; /* set the windows to default. these are the windows - * that alice thinks bob has. + * that the client thinks the service has. */ hop->package_window = circuit_initial_package_window(); hop->deliver_window = CIRCWINDOW_START; diff --git a/src/or/rendmid.c b/src/or/rendmid.c index 2451acb514..cbfbcbe051 100644 --- a/src/or/rendmid.c +++ b/src/or/rendmid.c @@ -80,7 +80,7 @@ rend_mid_establish_intro(or_circuit_t *circ, const uint8_t *request, goto err; } - /* The request is valid. First, compute the hash of Bob's PK.*/ + /* The request is valid. First, compute the hash of the service's PK.*/ if (crypto_pk_get_digest(pk, pk_digest)<0) { log_warn(LD_BUG, "Internal error: couldn't hash public key."); goto err; @@ -178,7 +178,8 @@ rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1, (char*)request, REND_SERVICE_ID_LEN); - /* The first 20 bytes are all we look at: they have a hash of Bob's PK. */ + /* The first 20 bytes are all we look at: they have a hash of the service's + * PK. */ intro_circ = circuit_get_intro_point((const uint8_t*)request); if (!intro_circ) { log_info(LD_REND, @@ -202,7 +203,7 @@ rend_mid_introduce(or_circuit_t *circ, const uint8_t *request, "Unable to send INTRODUCE2 cell to Tor client."); goto err; } - /* And send an ack down Alice's circuit. Empty body means succeeded. */ + /* And send an ack down the client's circuit. Empty body means succeeded. */ if (relay_send_command_from_edge(0,TO_CIRCUIT(circ), RELAY_COMMAND_INTRODUCE_ACK, NULL,0,NULL)) { @@ -337,7 +338,7 @@ rend_mid_rendezvous(or_circuit_t *circ, const uint8_t *request, circ->circuit_carries_hs_traffic_stats = 1; } - /* Send the RENDEZVOUS2 cell to Alice. */ + /* Send the RENDEZVOUS2 cell to the client. */ if (relay_send_command_from_edge(0, TO_CIRCUIT(rend_circ), RELAY_COMMAND_RENDEZVOUS2, (char*)(request+REND_COOKIE_LEN), diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 15d98bfde5..7471c6252f 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -1676,7 +1676,7 @@ rend_service_receive_introduction(origin_circuit_t *circuit, /* help predict this next time */ rep_hist_note_used_internal(now, circ_needs_uptime, 1); - /* Launch a circuit to alice's chosen rendezvous point. + /* Launch a circuit to the client's chosen rendezvous point. */ for (i=0;i<MAX_REND_FAILURES;i++) { int flags = CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_IS_INTERNAL; @@ -2970,7 +2970,7 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit) /* Append the cpath entry. */ hop->state = CPATH_STATE_OPEN; /* set the windows to default. these are the windows - * that bob thinks alice has. + * that the service thinks the client has. */ hop->package_window = circuit_initial_package_window(); hop->deliver_window = CIRCWINDOW_START; 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 ")); diff --git a/src/or/router.h b/src/or/router.h index a4b3e9616c..ca590e3217 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/or/routerlist.c b/src/or/routerlist.c index 9b8885e9c9..f6662705dc 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -68,8 +68,6 @@ typedef struct cert_list_t cert_list_t; static int compute_weighted_bandwidths(const smartlist_t *sl, bandwidth_weight_rule_t rule, u64_dbl_t **bandwidths_out); -static const routerstatus_t *router_pick_directory_server_impl( - dirinfo_type_t auth, int flags, int *n_busy_out); static const routerstatus_t *router_pick_trusteddirserver_impl( const smartlist_t *sourcelist, dirinfo_type_t auth, int flags, int *n_busy_out); @@ -1654,7 +1652,7 @@ router_skip_dir_reachability(const or_options_t *options, int try_ip_pref) * directories that we excluded for no other reason than * PDS_NO_EXISTING_SERVERDESC_FETCH or PDS_NO_EXISTING_MICRODESC_FETCH. */ -static const routerstatus_t * +STATIC const routerstatus_t * router_pick_directory_server_impl(dirinfo_type_t type, int flags, int *n_busy_out) { @@ -1697,7 +1695,7 @@ router_pick_directory_server_impl(dirinfo_type_t type, int flags, if (!status) continue; - if (!node->is_running || !status->dir_port || !node->is_valid) + if (!node->is_running || !node_is_dir(node) || !node->is_valid) continue; if (requireother && router_digest_is_me(node->identity)) continue; @@ -3424,7 +3422,11 @@ routerlist_reparse_old(routerlist_t *rl, signed_descriptor_t *sd) return ri; } -/** Free all memory held by the routerlist module. */ +/** Free all memory held by the routerlist module. + * Note: Calling routerlist_free_all() should always be paired with + * a call to nodelist_free_all(). These should only be called during + * cleanup. + */ void routerlist_free_all(void) { @@ -4624,13 +4626,20 @@ static int max_dl_per_request(const or_options_t *options, int purpose) { /* Since squid does not like URLs >= 4096 bytes we limit it to 96. - * 4096 - strlen(http://255.255.255.255/tor/server/d/.z) == 4058 - * 4058/41 (40 for the hash and 1 for the + that separates them) => 98 + * 4096 - strlen(http://[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535 + * /tor/server/d/.z) == 4026 + * 4026/41 (40 for the hash and 1 for the + that separates them) => 98 * So use 96 because it's a nice number. + * + * For microdescriptors, the calculation is + * 4096 - strlen(http://[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535 + * /tor/micro/d/.z) == 4027 + * 4027/44 (43 for the hash and 1 for the - that separates them) => 91 + * So use 90 because it's a nice number. */ int max = 96; if (purpose == DIR_PURPOSE_FETCH_MICRODESC) { - max = 92; + max = 90; } /* If we're going to tunnel our connections, we can ask for a lot more * in a request. */ @@ -5088,7 +5097,9 @@ router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2) (r1->contact_info && r2->contact_info && strcasecmp(r1->contact_info, r2->contact_info)) || r1->is_hibernating != r2->is_hibernating || - cmp_addr_policies(r1->exit_policy, r2->exit_policy)) + cmp_addr_policies(r1->exit_policy, r2->exit_policy) || + (r1->supports_tunnelled_dir_requests != + r2->supports_tunnelled_dir_requests)) return 0; if ((r1->declared_family == NULL) != (r2->declared_family == NULL)) return 0; diff --git a/src/or/routerlist.h b/src/or/routerlist.h index ac286d904f..483dd06039 100644 --- a/src/or/routerlist.h +++ b/src/or/routerlist.h @@ -234,6 +234,9 @@ STATIC int choose_array_element_by_weight(const u64_dbl_t *entries, int n_entries); STATIC void scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries, uint64_t *total_out); +STATIC const routerstatus_t *router_pick_directory_server_impl( + dirinfo_type_t auth, int flags, + int *n_busy_out); MOCK_DECL(int, router_descriptor_is_older_than, (const routerinfo_t *router, int seconds)); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 3f794ad902..fafba96e95 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -35,8 +35,9 @@ /****************************************************************************/ /** Enumeration of possible token types. The ones starting with K_ correspond - * to directory 'keywords'. ERR_ is an error in the tokenizing process, EOF_ - * is an end-of-file marker, and NIL_ is used to encode not-a-token. + * to directory 'keywords'. A_ is for an annotation, R or C is related to + * hidden services, ERR_ is an error in the tokenizing process, EOF_ is an + * end-of-file marker, and NIL_ is used to encode not-a-token. */ typedef enum { K_ACCEPT = 0, @@ -125,6 +126,7 @@ typedef enum { K_DIR_KEY_CERTIFICATION, K_DIR_KEY_CROSSCERT, K_DIR_ADDRESS, + K_DIR_TUNNELLED, K_VOTE_STATUS, K_VALID_AFTER, @@ -318,6 +320,7 @@ static token_rule_t routerdesc_token_table[] = { T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ), T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ), A01("@purpose", A_PURPOSE, GE(1), NO_OBJ ), + T01("tunnelled-dir-server",K_DIR_TUNNELLED, NO_ARGS, NO_OBJ ), END_OF_TABLE }; @@ -1609,6 +1612,12 @@ router_parse_entry_from_string(const char *s, const char *end, router->wants_to_be_hs_dir = 1; } + /* This router accepts tunnelled directory requests via begindir if it has + * an open dirport or it included "tunnelled-dir-server". */ + if (find_opt_by_keyword(tokens, K_DIR_TUNNELLED) || router->dir_port > 0) { + router->supports_tunnelled_dir_requests = 1; + } + tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE); note_crypto_pk_op(VERIFY_RTR); #ifdef COUNT_DISTINCT_DIGESTS @@ -2294,6 +2303,8 @@ routerstatus_parse_entry_from_string(memarea_t *area, rs->is_unnamed = 1; } else if (!strcmp(tok->args[i], "HSDir")) { rs->is_hs_dir = 1; + } else if (!strcmp(tok->args[i], "V2Dir")) { + rs->is_v2_dir = 1; } } } diff --git a/src/or/status.c b/src/or/status.c index 8f7be0aa3c..69d10721d2 100644 --- a/src/or/status.c +++ b/src/or/status.c @@ -164,24 +164,38 @@ log_accounting(const time_t now, const or_options_t *options) or_state_t *state = get_or_state(); char *acc_rcvd = bytes_to_usage(state->AccountingBytesReadInInterval); char *acc_sent = bytes_to_usage(state->AccountingBytesWrittenInInterval); + char *acc_used = bytes_to_usage(get_accounting_bytes()); uint64_t acc_bytes = options->AccountingMax; char *acc_max; time_t interval_end = accounting_get_end_time(); char end_buf[ISO_TIME_LEN + 1]; char *remaining = NULL; - if (options->AccountingRule == ACCT_SUM) - acc_bytes *= 2; acc_max = bytes_to_usage(acc_bytes); format_local_iso_time(end_buf, interval_end); remaining = secs_to_uptime(interval_end - now); + const char *acc_rule; + switch (options->AccountingRule) { + case ACCT_MAX: acc_rule = "max"; + break; + case ACCT_SUM: acc_rule = "sum"; + break; + case ACCT_OUT: acc_rule = "out"; + break; + case ACCT_IN: acc_rule = "in"; + break; + default: acc_rule = "max"; + break; + } + log_notice(LD_HEARTBEAT, "Heartbeat: Accounting enabled. " - "Sent: %s / %s, Received: %s / %s. The " + "Sent: %s, Received: %s, Used: %s / %s, Rule: %s. The " "current accounting interval ends on %s, in %s.", - acc_sent, acc_max, acc_rcvd, acc_max, end_buf, remaining); + acc_sent, acc_rcvd, acc_used, acc_max, acc_rule, end_buf, remaining); tor_free(acc_rcvd); tor_free(acc_sent); + tor_free(acc_used); tor_free(acc_max); tor_free(remaining); } diff --git a/src/or/transports.c b/src/or/transports.c index 81b8db2508..5a3af85be8 100644 --- a/src/or/transports.c +++ b/src/or/transports.c @@ -1100,7 +1100,7 @@ parse_smethod_line(const char *line, managed_proxy_t *mp) smartlist_add(mp->transports, transport); - /* For now, notify the user so that he knows where the server + /* For now, notify the user so that they know where the server transport is listening. */ log_info(LD_CONFIG, "Server transport %s at %s:%d.", method_name, address, (int)port); |