diff options
45 files changed, 303 insertions, 317 deletions
diff --git a/.travis.yml b/.travis.yml index 27534e4cfe..3d61f5a61a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -100,6 +100,8 @@ matrix: env: RUST_OPTIONS="--enable-rust" TOR_RUST_DEPENDENCIES=true - compiler: gcc env: RUST_OPTIONS="" + - compiler: gcc + env: COVERAGE_OPTIONS="--enable-coverage" ## The "sudo: required" forces non-containerized builds, working ## around a Travis CI environment issue: clang LeakAnalyzer fails ## because it requires ptrace and the containerized environment no @@ -118,6 +120,7 @@ before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi ## Download rustup - if [[ "$RUST_OPTIONS" != "" ]]; then curl -Ssf -o rustup.sh https://sh.rustup.rs; fi + - if [[ "$COVERAGE_OPTIONS" != "" ]]; then pip install --user cpp-coveralls; fi install: ## If we're on OSX use brew to install required dependencies (for Linux, see the "apt:" section above) @@ -143,10 +146,14 @@ install: script: - ./autogen.sh - - ./configure $RUST_OPTIONS --disable-asciidoc --enable-fatal-warnings --disable-silent-rules --enable-fragile-hardening + - ./configure $RUST_OPTIONS $COVERAGE_OPTIONS --disable-asciidoc --enable-fatal-warnings --disable-silent-rules --enable-fragile-hardening ## We run `make check` because that's what https://jenkins.torproject.org does. - make check after_failure: ## `make check` will leave a log file with more details of test failures. - cat test-suite.log + +after_success: + ## If this build was one that produced coverage, upload it. + - if [[ "$COVERAGE_OPTIONS" != "" ]]; then coveralls -b . --exclude src/test --exclude src/trunnel --gcov-options '\-p'; fi @@ -964,7 +964,7 @@ Changes in version 0.3.3.2-alpha - 2018-02-10 would call the Rust implementation of protover_get_supported_protocols(). This was due to the C version returning a static string, whereas the Rust version newly allocated - a CString to pass accross the FFI boundary. Consequently, the C + a CString to pass across the FFI boundary. Consequently, the C code was not expecting to need to free() what it was given. Fixes bug 25127; bugfix on 0.3.2.1-alpha. diff --git a/Makefile.am b/Makefile.am index 04ca88a236..cccad6c5ed 100644 --- a/Makefile.am +++ b/Makefile.am @@ -217,6 +217,26 @@ check-logs: $(top_srcdir)/scripts/maint/checkLogs.pl \ $(top_srcdir)/src/*/*.[ch] | sort -n +.PHONY: check-typos +check-typos: + @if test -x "`which misspell 2>&1;true`"; then \ + echo "Checking for Typos ..."; \ + (misspell \ + $(top_srcdir)/src/[^e]*/*.[ch] \ + $(top_srcdir)/doc \ + $(top_srcdir)/contrib \ + $(top_srcdir)/scripts \ + $(top_srcdir)/README \ + $(top_srcdir)/ChangeLog \ + $(top_srcdir)/INSTALL \ + $(top_srcdir)/ReleaseNotes \ + $(top_srcdir)/LICENSE); \ + else \ + echo "Tor can use misspell to check for typos."; \ + echo "It seems that you don't have misspell installed."; \ + echo "You can install the latest version of misspell here: https://github.com/client9/misspell#install"; \ + fi + .PHONY: check-changes check-changes: if USEPYTHON diff --git a/changes/24378 b/changes/24378 new file mode 100644 index 0000000000..663d27e969 --- /dev/null +++ b/changes/24378 @@ -0,0 +1,8 @@ + o Removed features: + + - Directory authorities will no longer support voting according to any + consensus method before consensus method 25. This keeps authorities + compatible with all authorities running 0.2.9.8 and later, and does + not break any clients or relays. Implements ticket 24378 and + proposal 290. + diff --git a/changes/25857 b/changes/25857 new file mode 100644 index 0000000000..e457af2f82 --- /dev/null +++ b/changes/25857 @@ -0,0 +1,3 @@ + o Documentation: + - Correct an IPv6 error in the documentation for ExitPolicy. + Closes ticket 25857. Patch from "CTassisF". diff --git a/changes/bug24688 b/changes/bug24688 new file mode 100644 index 0000000000..c376fe6a03 --- /dev/null +++ b/changes/bug24688 @@ -0,0 +1,3 @@ + o Minor features (performance, 32-bit): + - Make our timing-wheel code run a tiny bit faster on 32-bit platforms, + by preferring 32-bit math to 64-bit. Closes ticket 24688. diff --git a/changes/bug25400 b/changes/bug25400 new file mode 100644 index 0000000000..cee7ea83b0 --- /dev/null +++ b/changes/bug25400 @@ -0,0 +1,5 @@ + o Minor bugfix (controler): + - Make CIRC_BW event reflect the total of all data sent on a circuit, + including padding and dropped cells. Also fix a mis-counting bug + when STREAM_BW events were enabled. Fixes bug 25400; bugfix on + 0.2.5.2-alpha. diff --git a/changes/bug25691_again b/changes/bug25691_again new file mode 100644 index 0000000000..3d0d91bfd3 --- /dev/null +++ b/changes/bug25691_again @@ -0,0 +1,6 @@ + o Minor bugfixes (path selection): + - Only select relays when they have the descriptors we prefer to + use for them. This change fixes a bug where we could select + a relay because it had _some_ descriptor, but reject it later with + a nonfatal assertion error because it didn't have the exact one we + wanted. Fixes bugs 25691 and 25692; bugfix on 0.3.3.4-alpha. diff --git a/changes/coveralls b/changes/coveralls new file mode 100644 index 0000000000..7fa69bb2b4 --- /dev/null +++ b/changes/coveralls @@ -0,0 +1,3 @@ + o Minor features (continuous integration): + - Our Travis CI configuration now integrates with the Coveralls coverage + analysis tool. Closes ticket 25818. diff --git a/changes/ticket25024 b/changes/ticket25024 new file mode 100644 index 0000000000..0e5069cf81 --- /dev/null +++ b/changes/ticket25024 @@ -0,0 +1,4 @@ + o Minor features (code quality): + - Add optional spell-checking for the Tor codebase, using the "misspell" + program. To use this feature, run "make check-typos". + Closes ticket 25024. diff --git a/doc/tor.1.txt b/doc/tor.1.txt index 95620a3344..594dedf397 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -368,7 +368,8 @@ GENERAL OPTIONS [[ControlSocket]] **ControlSocket** __Path__:: Like ControlPort, but listens on a Unix domain socket, rather than a TCP - socket. '0' disables ControlSocket (Unix and Unix-like systems only.) + socket. '0' disables ControlSocket. (Unix and Unix-like systems only.) + (Default: 0) [[ControlSocketsGroupWritable]] **ControlSocketsGroupWritable** **0**|**1**:: If this option is set to 0, don't allow the filesystem group to read and @@ -1834,8 +1835,8 @@ is non-zero): "**accept[6]**|**reject[6]** __ADDR__[/__MASK__][:__PORT__]". If /__MASK__ is omitted then this policy just applies to the host given. Instead of giving a host or network you can also use "\*" to denote the universe (0.0.0.0/0 - and ::/128), or \*4 to denote all IPv4 addresses, and \*6 to denote all - IPv6 addresses. + and ::/0), or \*4 to denote all IPv4 addresses, and \*6 to denote all IPv6 + addresses. __PORT__ can be a single port number, an interval of ports "__FROM_PORT__-__TO_PORT__", or "\*". If __PORT__ is omitted, that means "\*". + diff --git a/src/common/crypto_rsa.h b/src/common/crypto_rsa.h index 2f5442a5d2..e952089318 100644 --- a/src/common/crypto_rsa.h +++ b/src/common/crypto_rsa.h @@ -35,7 +35,7 @@ /** A public key, or a public/private key-pair. */ typedef struct crypto_pk_t crypto_pk_t; -/* RSA enviroment setup */ +/* RSA environment setup */ MOCK_DECL(crypto_pk_t *,crypto_pk_new,(void)); void crypto_pk_free_(crypto_pk_t *env); #define crypto_pk_free(pk) FREE_AND_NULL(crypto_pk_t, crypto_pk_free_, (pk)) diff --git a/src/common/timers.c b/src/common/timers.c index a90817da1c..6f6236ed3b 100644 --- a/src/common/timers.c +++ b/src/common/timers.c @@ -64,6 +64,11 @@ struct timeout_cb { * above TIMEOUT_MAX can also be super-inefficient. Choosing 5 here sets * timeout_max to 2^30 ticks, or 29 hours with our value for USEC_PER_TICK */ #define WHEEL_NUM 5 +#if SIZEOF_VOID_P == 4 +/* On 32-bit platforms, we want to override wheel_bit, so that timeout.c will + * use 32-bit math. */ +#define WHEEL_BIT 5 +#endif #include "src/ext/timeouts/timeout.c" static struct timeouts *global_timeouts = NULL; diff --git a/src/common/token_bucket.c b/src/common/token_bucket.c index d18731b0e3..747189e751 100644 --- a/src/common/token_bucket.c +++ b/src/common/token_bucket.c @@ -119,7 +119,7 @@ rate_per_sec_to_rate_per_step(uint32_t rate) */ uint64_t units = (uint64_t) rate * TICKS_PER_STEP; uint32_t val = (uint32_t) - monotime_coarse_stamp_units_to_approx_msec(units) / 1000; + (monotime_coarse_stamp_units_to_approx_msec(units) / 1000); return val ? val : 1; } diff --git a/src/common/util.c b/src/common/util.c index b7516b8b64..53e4507f1f 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -572,6 +572,19 @@ add_laplace_noise(int64_t signal_, double random_, double delta_f, return signal_ + noise; } +/* Helper: safely add two uint32_t's, capping at UINT32_MAX rather + * than overflow */ +uint32_t +tor_add_u32_nowrap(uint32_t a, uint32_t b) +{ + /* a+b > UINT32_MAX check, without overflow */ + if (PREDICT_UNLIKELY(a > UINT32_MAX - b)) { + return UINT32_MAX; + } else { + return a+b; + } +} + /* Helper: return greatest common divisor of a,b */ static uint64_t gcd64(uint64_t a, uint64_t b) diff --git a/src/common/util.h b/src/common/util.h index 5708b7fd86..7172b7da08 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -176,6 +176,8 @@ int n_bits_set_u8(uint8_t v); int64_t clamp_double_to_int64(double number); void simplify_fraction64(uint64_t *numer, uint64_t *denom); +uint32_t tor_add_u32_nowrap(uint32_t a, uint32_t b); + /* Compute the CEIL of <b>a</b> divided by <b>b</b>, for nonnegative <b>a</b> * and positive <b>b</b>. Works on integer types only. Not defined if a+(b-1) * can overflow. */ diff --git a/src/ext/timeouts/timeout.c b/src/ext/timeouts/timeout.c index 713ec219ce..d4b514d2c5 100644 --- a/src/ext/timeouts/timeout.c +++ b/src/ext/timeouts/timeout.c @@ -150,7 +150,7 @@ #else #define ctz(n) ctz32(n) #define clz(n) clz32(n) -#define fls(n) ((int)(32 - clz32(n))) +#define fls(n) ((int)(32 - clz32((uint32_t)n))) #endif #if WHEEL_BIT == 6 @@ -432,7 +432,7 @@ TIMEOUT_PUBLIC void timeouts_update(struct timeouts *T, abstime_t curtime) { * or can be replaced with a simpler operation. */ oslot = WHEEL_MASK & (T->curtime >> (wheel * WHEEL_BIT)); - pending = rotl(((UINT64_C(1) << _elapsed) - 1), oslot); + pending = rotl(((WHEEL_C(1) << _elapsed) - 1), oslot); nslot = WHEEL_MASK & (curtime >> (wheel * WHEEL_BIT)); pending |= rotr(rotl(((WHEEL_C(1) << _elapsed) - 1), nslot), (int)_elapsed); diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 54446bb01d..c33dbbeb2d 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -418,7 +418,7 @@ onion_populate_cpath(origin_circuit_t *circ) circ->cpath->extend_info->identity_digest); /* If we don't know the node and its descriptor, we must be bootstrapping. */ - if (!node || !node_has_descriptor(node)) { + if (!node || !node_has_preferred_descriptor(node, 1)) { return 0; } } @@ -1758,7 +1758,7 @@ ap_stream_wants_exit_attention(connection_t *conn) * Return NULL if we can't find any suitable routers. */ static const node_t * -choose_good_exit_server_general(int need_uptime, int need_capacity) +choose_good_exit_server_general(router_crn_flags_t flags) { int *n_supported; int n_pending_connections = 0; @@ -1768,6 +1768,9 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) const or_options_t *options = get_options(); const smartlist_t *the_nodes; const node_t *selected_node=NULL; + const int need_uptime = (flags & CRN_NEED_UPTIME) != 0; + const int need_capacity = (flags & CRN_NEED_CAPACITY) != 0; + const int direct_conn = (flags & CRN_DIRECT_CONN) != 0; connections = get_connection_array(); @@ -1800,7 +1803,7 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) */ continue; } - if (!node_has_descriptor(node)) { + if (!node_has_preferred_descriptor(node, direct_conn)) { n_supported[i] = -1; continue; } @@ -1913,7 +1916,8 @@ choose_good_exit_server_general(int need_uptime, int need_capacity) need_capacity?", fast":"", need_uptime?", stable":""); tor_free(n_supported); - return choose_good_exit_server_general(0, 0); + flags &= ~(CRN_NEED_UPTIME|CRN_NEED_CAPACITY); + return choose_good_exit_server_general(flags); } log_notice(LD_CIRC, "All routers are down or won't exit%s -- " "choosing a doomed exit at random.", @@ -2160,17 +2164,11 @@ pick_restricted_middle_node(router_crn_flags_t flags, * toward the preferences in 'options'. */ static const node_t * -choose_good_exit_server(origin_circuit_t *circ, int need_uptime, - int need_capacity, int is_internal, int need_hs_v3) +choose_good_exit_server(origin_circuit_t *circ, + router_crn_flags_t flags, int is_internal) { const or_options_t *options = get_options(); - router_crn_flags_t flags = CRN_NEED_DESC; - if (need_uptime) - flags |= CRN_NEED_UPTIME; - if (need_capacity) - flags |= CRN_NEED_CAPACITY; - if (need_hs_v3) - flags |= CRN_RENDEZVOUS_V3; + flags |= CRN_NEED_DESC; switch (TO_CIRCUIT(circ)->purpose) { case CIRCUIT_PURPOSE_C_HSDIR_GET: @@ -2184,7 +2182,7 @@ choose_good_exit_server(origin_circuit_t *circ, int need_uptime, if (is_internal) /* pick it like a middle hop */ return router_choose_random_node(NULL, options->ExcludeNodes, flags); else - return choose_good_exit_server_general(need_uptime,need_capacity); + return choose_good_exit_server_general(flags); case CIRCUIT_PURPOSE_C_ESTABLISH_REND: { /* Pick a new RP */ @@ -2309,15 +2307,22 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit_ei, extend_info_describe(exit_ei)); exit_ei = extend_info_dup(exit_ei); } else { /* we have to decide one */ + router_crn_flags_t flags = CRN_NEED_DESC; + if (state->need_uptime) + flags |= CRN_NEED_UPTIME; + if (state->need_capacity) + flags |= CRN_NEED_CAPACITY; + if (is_hs_v3_rp_circuit) + flags |= CRN_RENDEZVOUS_V3; + if (state->onehop_tunnel) + flags |= CRN_DIRECT_CONN; const node_t *node = - choose_good_exit_server(circ, state->need_uptime, - state->need_capacity, state->is_internal, - is_hs_v3_rp_circuit); + choose_good_exit_server(circ, flags, state->is_internal); if (!node) { log_warn(LD_CIRC,"Failed to choose an exit server"); return -1; } - exit_ei = extend_info_from_node(node, 0); + exit_ei = extend_info_from_node(node, state->onehop_tunnel); if (BUG(exit_ei == NULL)) return -1; } @@ -2374,6 +2379,10 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit_ei) /** Return the number of routers in <b>routers</b> that are currently up * and available for building circuits through. + * + * (Note that this function may overcount or undercount, if we have + * descriptors that are not the type we would prefer to use for some + * particular router. See bug #25885.) */ MOCK_IMPL(STATIC int, count_acceptable_nodes, (smartlist_t *nodes)) @@ -2390,7 +2399,7 @@ count_acceptable_nodes, (smartlist_t *nodes)) if (! node->is_valid) // log_debug(LD_CIRC,"Nope, the directory says %d is not valid.",i); continue; - if (! node_has_descriptor(node)) + if (! node_has_any_descriptor(node)) continue; /* The node has a descriptor, so we can just check the ntor key directly */ if (!node_has_curve25519_onion_key(node)) @@ -2778,9 +2787,10 @@ extend_info_new(const char *nickname, * of the node (i.e. its IPv4 address) unless * <b>for_direct_connect</b> is true, in which case the preferred * address is used instead. May return NULL if there is not enough - * info about <b>node</b> to extend to it--for example, if there is no - * routerinfo_t or microdesc_t, or if for_direct_connect is true and none of - * the node's addresses are allowed by tor's firewall and IP version config. + * info about <b>node</b> to extend to it--for example, if the preferred + * routerinfo_t or microdesc_t is missing, or if for_direct_connect is + * true and none of the node's addresses is allowed by tor's firewall + * and IP version config. **/ extend_info_t * extend_info_from_node(const node_t *node, int for_direct_connect) @@ -2788,17 +2798,8 @@ extend_info_from_node(const node_t *node, int for_direct_connect) tor_addr_port_t ap; int valid_addr = 0; - const int is_bridge = node_is_a_configured_bridge(node); - const int we_use_mds = we_use_microdescriptors_for_circuits(get_options()); - - if ((is_bridge && for_direct_connect) || !we_use_mds) { - /* We need an ri in this case. */ - if (!node->ri) - return NULL; - } else { - /* Otherwise we need an md. */ - if (node->rs == NULL || node->md == NULL) - return NULL; + if (!node_has_preferred_descriptor(node, for_direct_connect)) { + return NULL; } /* Choose a preferred address first, but fall back to an allowed address. diff --git a/src/or/circuituse.c b/src/or/circuituse.c index fe28dd9a1a..47e29c28dd 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -2383,7 +2383,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn, const node_t *r; int opt = conn->chosen_exit_optional; r = node_get_by_nickname(conn->chosen_exit_name, 0); - if (r && node_has_descriptor(r)) { + if (r && node_has_preferred_descriptor(r, conn->want_onehop ? 1 : 0)) { /* We might want to connect to an IPv6 bridge for loading descriptors so we use the preferred address rather than the primary. */ @@ -2393,7 +2393,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn, "Discarding this circuit.", conn->chosen_exit_name); return -1; } - } else { /* ! (r && node_has_descriptor(r)) */ + } else { /* ! (r && node_has_preferred_descriptor(...)) */ log_debug(LD_DIR, "considering %d, %s", want_onehop, conn->chosen_exit_name); if (want_onehop && conn->chosen_exit_name[0] == '$') { diff --git a/src/or/command.c b/src/or/command.c index 4f99462f38..4fa05a18b4 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -495,6 +495,17 @@ command_process_relay_cell(cell_t *cell, channel_t *chan) /* if we're a relay and treating connections with recent local * traffic better, then this is one of them. */ channel_timestamp_client(chan); + + /* Count all circuit bytes here for control port accuracy. We want + * to count even invalid/dropped relay cells, hence counting + * before the recognized check and the connection_edge_process_relay + * cell checks. + */ + origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); + + /* Count the payload bytes only. We don't care about cell headers */ + ocirc->n_read_circ_bw = tor_add_u32_nowrap(ocirc->n_read_circ_bw, + CELL_PAYLOAD_SIZE); } if (!CIRCUIT_IS_ORIGIN(circ) && diff --git a/src/or/config.c b/src/or/config.c index 206274cd38..9c0b321b56 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -2190,7 +2190,7 @@ options_act(const or_options_t *old_options) if (options->BandwidthRate != old_options->BandwidthRate || options->BandwidthBurst != old_options->BandwidthBurst || - options->BandwidthRate != old_options->BandwidthRate || + options->RelayBandwidthRate != old_options->RelayBandwidthRate || options->RelayBandwidthBurst != old_options->RelayBandwidthBurst) connection_bucket_adjust(options); diff --git a/src/or/connection.c b/src/or/connection.c index 9573989854..e8ecf0db9f 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -3479,25 +3479,15 @@ connection_buf_read_from_socket(connection_t *conn, ssize_t *max_to_read, /* change *max_to_read */ *max_to_read = at_most - n_read; - /* Update edge_conn->n_read and ocirc->n_read_circ_bw */ + /* Update edge_conn->n_read */ if (conn->type == CONN_TYPE_AP) { edge_connection_t *edge_conn = TO_EDGE_CONN(conn); - circuit_t *circ = circuit_get_by_edge_conn(edge_conn); - origin_circuit_t *ocirc; /* Check for overflow: */ if (PREDICT_LIKELY(UINT32_MAX - edge_conn->n_read > n_read)) edge_conn->n_read += (int)n_read; else edge_conn->n_read = UINT32_MAX; - - if (circ && CIRCUIT_IS_ORIGIN(circ)) { - ocirc = TO_ORIGIN_CIRCUIT(circ); - if (PREDICT_LIKELY(UINT32_MAX - ocirc->n_read_circ_bw > n_read)) - ocirc->n_read_circ_bw += (int)n_read; - else - ocirc->n_read_circ_bw = UINT32_MAX; - } } /* If CONN_BW events are enabled, update conn->n_read_conn_bw for @@ -3815,22 +3805,12 @@ connection_handle_write_impl(connection_t *conn, int force) if (n_written && conn->type == CONN_TYPE_AP) { edge_connection_t *edge_conn = TO_EDGE_CONN(conn); - circuit_t *circ = circuit_get_by_edge_conn(edge_conn); - origin_circuit_t *ocirc; /* Check for overflow: */ if (PREDICT_LIKELY(UINT32_MAX - edge_conn->n_written > n_written)) edge_conn->n_written += (int)n_written; else edge_conn->n_written = UINT32_MAX; - - if (circ && CIRCUIT_IS_ORIGIN(circ)) { - ocirc = TO_ORIGIN_CIRCUIT(circ); - if (PREDICT_LIKELY(UINT32_MAX - ocirc->n_written_circ_bw > n_written)) - ocirc->n_written_circ_bw += (int)n_written; - else - ocirc->n_written_circ_bw = UINT32_MAX; - } } /* If CONN_BW events are enabled, update conn->n_written_conn_bw for diff --git a/src/or/control.c b/src/or/control.c index 72122eaafb..dda8872182 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -3515,17 +3515,19 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len, smartlist_free(args); nodes = smartlist_new(); + int first_node = zero_circ; SMARTLIST_FOREACH_BEGIN(router_nicknames, const char *, n) { const node_t *node = node_get_by_nickname(n, 0); if (!node) { connection_printf_to_buf(conn, "552 No such router \"%s\"\r\n", n); goto done; } - if (!node_has_descriptor(node)) { + if (!node_has_preferred_descriptor(node, first_node)) { connection_printf_to_buf(conn, "552 No descriptor for \"%s\"\r\n", n); goto done; } smartlist_add(nodes, (void*)node); + first_node = 0; } SMARTLIST_FOREACH_END(n); if (!smartlist_len(nodes)) { connection_write_str_to_buf("512 No router names provided\r\n", conn); @@ -3538,14 +3540,15 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len, } /* now circ refers to something that is ready to be extended */ - int first_node = zero_circ; + first_node = zero_circ; SMARTLIST_FOREACH(nodes, const node_t *, node, { extend_info_t *info = extend_info_from_node(node, first_node); if (!info) { tor_assert_nonfatal(first_node); log_warn(LD_CONTROL, - "controller tried to connect to a node that doesn't have any " + "controller tried to connect to a node that lacks a suitable " + "descriptor, or which doesn't have any " "addresses that are allowed by the firewall configuration; " "circuit marked for closing."); circuit_mark_for_close(TO_CIRCUIT(circ), -END_CIRC_REASON_CONNECTFAILED); @@ -5828,8 +5831,6 @@ control_event_or_conn_status(or_connection_t *conn, or_conn_status_event_t tp, int control_event_stream_bandwidth(edge_connection_t *edge_conn) { - circuit_t *circ; - origin_circuit_t *ocirc; struct timeval now; char tbuf[ISO_TIME_USEC_LEN+1]; if (EVENT_IS_INTERESTING(EVENT_STREAM_BANDWIDTH_USED)) { @@ -5845,12 +5846,6 @@ control_event_stream_bandwidth(edge_connection_t *edge_conn) (unsigned long)edge_conn->n_written, tbuf); - circ = circuit_get_by_edge_conn(edge_conn); - if (circ && CIRCUIT_IS_ORIGIN(circ)) { - ocirc = TO_ORIGIN_CIRCUIT(circ); - ocirc->n_read_circ_bw += edge_conn->n_read; - ocirc->n_written_circ_bw += edge_conn->n_written; - } edge_conn->n_written = edge_conn->n_read = 0; } diff --git a/src/or/dircollate.c b/src/or/dircollate.c index ce4534ff6c..dec6f75154 100644 --- a/src/or/dircollate.c +++ b/src/or/dircollate.c @@ -25,7 +25,6 @@ #include "dircollate.h" #include "dirvote.h" -static void dircollator_collate_by_rsa(dircollator_t *dc); static void dircollator_collate_by_ed25519(dircollator_t *dc); /** Hashtable entry mapping a pair of digests (actually an ed25519 key and an @@ -208,49 +207,18 @@ dircollator_add_vote(dircollator_t *dc, networkstatus_t *v) void dircollator_collate(dircollator_t *dc, int consensus_method) { + (void) consensus_method; + tor_assert(!dc->is_collated); dc->all_rsa_sha1_lst = smartlist_new(); - if (consensus_method < MIN_METHOD_FOR_ED25519_ID_VOTING) - dircollator_collate_by_rsa(dc); - else - dircollator_collate_by_ed25519(dc); + dircollator_collate_by_ed25519(dc); smartlist_sort_digests(dc->all_rsa_sha1_lst); dc->is_collated = 1; } /** - * Collation function for RSA-only consensuses: collate the votes for each - * entry in <b>dc</b> by their RSA keys. - * - * The rule is: - * If an RSA identity key is listed by more than half of the authorities, - * include that identity, and treat all descriptors with that RSA identity - * as describing the same router. - */ -static void -dircollator_collate_by_rsa(dircollator_t *dc) -{ - const int total_authorities = dc->n_authorities; - - DIGESTMAP_FOREACH(dc->by_rsa_sha1, k, vote_routerstatus_t **, vrs_lst) { - int n = 0, i; - for (i = 0; i < dc->n_votes; ++i) { - if (vrs_lst[i] != NULL) - ++n; - } - - if (n <= total_authorities / 2) - continue; - - smartlist_add(dc->all_rsa_sha1_lst, (char *)k); - } DIGESTMAP_FOREACH_END; - - dc->by_collated_rsa_sha1 = dc->by_rsa_sha1; -} - -/** * Collation function for ed25519 consensuses: collate the votes for each * entry in <b>dc</b> by ed25519 key and by RSA key. * diff --git a/src/or/dirvote.c b/src/or/dirvote.c index c3cd0d3cd1..f3b8a19f00 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -549,12 +549,12 @@ compute_routerstatus_consensus(smartlist_t *votes, int consensus_method, tor_assert(most); - /* If we're producing "a" lines, vote on potential alternative (sets - * of) OR port(s) in the winning routerstatuses. + /* Vote on potential alternative (sets of) OR port(s) in the winning + * routerstatuses. * * XXX prop186 There's at most one alternative OR port (_the_ IPv6 * port) for now. */ - if (consensus_method >= MIN_METHOD_FOR_A_LINES && best_alt_orport_out) { + if (best_alt_orport_out) { smartlist_t *alt_orports = smartlist_new(); const tor_addr_port_t *most_alt_orport = NULL; @@ -664,13 +664,6 @@ compute_consensus_method(smartlist_t *votes) static int consensus_method_is_supported(int method) { - if (method == MIN_METHOD_FOR_ED25519_ID_IN_MD) { - /* This method was broken due to buggy code accidentally left in - * dircollate.c; do not actually use it. - */ - return 0; - } - return (method >= MIN_SUPPORTED_CONSENSUS_METHOD) && (method <= MAX_SUPPORTED_CONSENSUS_METHOD); } @@ -1455,19 +1448,14 @@ networkstatus_compute_consensus(smartlist_t *votes, n_versioning_servers); client_versions = compute_consensus_versions_list(combined_client_versions, n_versioning_clients); - if (consensus_method >= MIN_METHOD_FOR_PACKAGE_LINES) { - packages = compute_consensus_package_lines(votes); - } else { - packages = tor_strdup(""); - } + packages = compute_consensus_package_lines(votes); SMARTLIST_FOREACH(combined_server_versions, char *, cp, tor_free(cp)); SMARTLIST_FOREACH(combined_client_versions, char *, cp, tor_free(cp)); smartlist_free(combined_server_versions); smartlist_free(combined_client_versions); - if (consensus_method >= MIN_METHOD_FOR_ED25519_ID_VOTING) - smartlist_add_strdup(flags, "NoEdConsensus"); + smartlist_add_strdup(flags, "NoEdConsensus"); smartlist_sort_strings(flags); smartlist_uniq_strings(flags); @@ -1516,7 +1504,7 @@ networkstatus_compute_consensus(smartlist_t *votes, tor_free(flaglist); } - if (consensus_method >= MIN_METHOD_FOR_RECOMMENDED_PROTOCOLS) { + { int num_dirauth = get_n_authorities(V3_DIRINFO); int idx; for (idx = 0; idx < 4; ++idx) { @@ -1536,7 +1524,7 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_add_strdup(chunks, "\n"); } - if (consensus_method >= MIN_METHOD_FOR_SHARED_RANDOM) { + { int num_dirauth = get_n_authorities(V3_DIRINFO); /* Default value of this is 2/3 of the total number of authorities. For * instance, if we have 9 dirauth, the default value is 6. The following @@ -1601,7 +1589,7 @@ networkstatus_compute_consensus(smartlist_t *votes, smartlist_free(dir_sources); } - if (consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW) { + { char *max_unmeasured_param = NULL; /* XXXX Extract this code into a common function. Or don't! see #19011 */ if (params) { @@ -1863,7 +1851,6 @@ networkstatus_compute_consensus(smartlist_t *votes, continue; if (ed_consensus > 0) { - tor_assert(consensus_method >= MIN_METHOD_FOR_ED25519_ID_VOTING); if (ed_consensus <= total_authorities / 2) { log_warn(LD_BUG, "Not enough entries had ed_consensus set; how " "can we have a consensus of %d?", ed_consensus); @@ -1890,10 +1877,8 @@ networkstatus_compute_consensus(smartlist_t *votes, rs_out.published_on = rs->status.published_on; rs_out.dir_port = rs->status.dir_port; rs_out.or_port = rs->status.or_port; - if (consensus_method >= MIN_METHOD_FOR_A_LINES) { - tor_addr_copy(&rs_out.ipv6_addr, &alt_orport.addr); - rs_out.ipv6_orport = alt_orport.port; - } + tor_addr_copy(&rs_out.ipv6_addr, &alt_orport.addr); + rs_out.ipv6_orport = alt_orport.port; rs_out.has_bandwidth = 0; rs_out.has_exitsummary = 0; @@ -1923,8 +1908,7 @@ networkstatus_compute_consensus(smartlist_t *votes, } else if (!strcmp(fl, "Unnamed")) { if (is_unnamed) smartlist_add(chosen_flags, (char*)fl); - } else if (!strcmp(fl, "NoEdConsensus") && - consensus_method >= MIN_METHOD_FOR_ED25519_ID_VOTING) { + } else if (!strcmp(fl, "NoEdConsensus")) { if (ed_consensus <= total_authorities/2) smartlist_add(chosen_flags, (char*)fl); } else { @@ -1951,8 +1935,7 @@ networkstatus_compute_consensus(smartlist_t *votes, /* Starting with consensus method 24, we don't list servers * that are not valid in a consensus. See Proposal 272 */ - if (!is_valid && - consensus_method >= MIN_METHOD_FOR_EXCLUDING_INVALID_NODES) + if (!is_valid) continue; /* Pick the version. */ @@ -1973,8 +1956,7 @@ networkstatus_compute_consensus(smartlist_t *votes, /* If it's a guard and we have enough guardfraction votes, calculate its consensus guardfraction value. */ - if (is_guard && num_guardfraction_inputs > 2 && - consensus_method >= MIN_METHOD_FOR_GUARDFRACTION) { + if (is_guard && num_guardfraction_inputs > 2) { rs_out.has_guardfraction = 1; rs_out.guardfraction_percentage = median_uint32(measured_guardfraction, num_guardfraction_inputs); @@ -1991,8 +1973,7 @@ networkstatus_compute_consensus(smartlist_t *votes, rs_out.has_bandwidth = 1; rs_out.bw_is_unmeasured = 1; rs_out.bandwidth_kb = median_uint32(bandwidths_kb, num_bandwidths); - if (consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW && - n_authorities_measuring_bandwidth > 2) { + if (n_authorities_measuring_bandwidth > 2) { /* Cap non-measured bandwidths. */ if (rs_out.bandwidth_kb > max_unmeasured_bw_kb) { rs_out.bandwidth_kb = max_unmeasured_bw_kb; @@ -2132,8 +2113,7 @@ networkstatus_compute_consensus(smartlist_t *votes, /* Now the weight line. */ if (rs_out.has_bandwidth) { char *guardfraction_str = NULL; - int unmeasured = rs_out.bw_is_unmeasured && - consensus_method >= MIN_METHOD_TO_CLIP_UNMEASURED_BW; + int unmeasured = rs_out.bw_is_unmeasured; /* If we have guardfraction info, include it in the 'w' line. */ if (rs_out.has_guardfraction) { @@ -3835,8 +3815,7 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method) smartlist_add_asprintf(chunks, "onion-key\n%s", key); - if (consensus_method >= MIN_METHOD_FOR_NTOR_KEY && - ri->onion_curve25519_pkey) { + if (ri->onion_curve25519_pkey) { char kbuf[128]; base64_encode(kbuf, sizeof(kbuf), (const char*)ri->onion_curve25519_pkey->public_key, @@ -3846,8 +3825,7 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method) /* We originally put a lines in the micrdescriptors, but then we worked out * that we needed them in the microdesc consensus. See #20916. */ - if (consensus_method >= MIN_METHOD_FOR_A_LINES && - consensus_method < MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC && + if (consensus_method < MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC && !tor_addr_is_null(&ri->ipv6_addr) && ri->ipv6_orport) smartlist_add_asprintf(chunks, "a %s\n", fmt_addrport(&ri->ipv6_addr, ri->ipv6_orport)); @@ -3858,8 +3836,7 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method) if (summary && strcmp(summary, "reject 1-65535")) smartlist_add_asprintf(chunks, "p %s\n", summary); - if (consensus_method >= MIN_METHOD_FOR_P6_LINES && - ri->ipv6_exit_policy) { + if (ri->ipv6_exit_policy) { /* XXXX+++ This doesn't match proposal 208, which says these should * be taken unchanged from the routerinfo. That's bogosity, IMO: * the proposal should have said to do this instead.*/ @@ -3869,11 +3846,10 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method) tor_free(p6); } - if (consensus_method >= MIN_METHOD_FOR_ID_HASH_IN_MD) { + { char idbuf[ED25519_BASE64_LEN+1]; const char *keytype; - if (consensus_method >= MIN_METHOD_FOR_ED25519_ID_IN_MD && - ri->cache_info.signing_key_cert && + if (ri->cache_info.signing_key_cert && ri->cache_info.signing_key_cert->signing_key_included) { keytype = "ed25519"; ed25519_public_to_base64(idbuf, @@ -3951,13 +3927,7 @@ static const struct consensus_method_range_t { int low; int high; } microdesc_consensus_methods[] = { - {MIN_SUPPORTED_CONSENSUS_METHOD, MIN_METHOD_FOR_A_LINES - 1}, - {MIN_METHOD_FOR_A_LINES, MIN_METHOD_FOR_P6_LINES - 1}, - {MIN_METHOD_FOR_P6_LINES, MIN_METHOD_FOR_NTOR_KEY - 1}, - {MIN_METHOD_FOR_NTOR_KEY, MIN_METHOD_FOR_ID_HASH_IN_MD - 1}, - {MIN_METHOD_FOR_ID_HASH_IN_MD, MIN_METHOD_FOR_ED25519_ID_IN_MD - 1}, - {MIN_METHOD_FOR_ED25519_ID_IN_MD, - MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC - 1}, + {MIN_SUPPORTED_CONSENSUS_METHOD, MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC - 1}, {MIN_METHOD_FOR_NO_A_LINES_IN_MICRODESC, MAX_SUPPORTED_CONSENSUS_METHOD}, {-1, -1} }; diff --git a/src/or/dirvote.h b/src/or/dirvote.h index deeb27bfe1..8a317deb47 100644 --- a/src/or/dirvote.h +++ b/src/or/dirvote.h @@ -56,57 +56,11 @@ #define ROUTERSTATUS_FORMAT_NO_CONSENSUS_METHOD 0 /** The lowest consensus method that we currently support. */ -#define MIN_SUPPORTED_CONSENSUS_METHOD 13 +#define MIN_SUPPORTED_CONSENSUS_METHOD 25 /** The highest consensus method that we currently support. */ #define MAX_SUPPORTED_CONSENSUS_METHOD 28 -/** Lowest consensus method where microdesc consensuses omit any entry - * with no microdesc. */ -#define MIN_METHOD_FOR_MANDATORY_MICRODESC 13 - -/** Lowest consensus method that contains "a" lines. */ -#define MIN_METHOD_FOR_A_LINES 14 - -/** Lowest consensus method where microdescs may include a "p6" line. */ -#define MIN_METHOD_FOR_P6_LINES 15 - -/** Lowest consensus method where microdescs may include an onion-key-ntor - * line */ -#define MIN_METHOD_FOR_NTOR_KEY 16 - -/** Lowest consensus method that ensures that authorities output an - * Unmeasured=1 flag for unmeasured bandwidths */ -#define MIN_METHOD_TO_CLIP_UNMEASURED_BW 17 - -/** Lowest consensus method where authorities may include an "id" line in - * microdescriptors. */ -#define MIN_METHOD_FOR_ID_HASH_IN_MD 18 - -/** Lowest consensus method where we include "package" lines*/ -#define MIN_METHOD_FOR_PACKAGE_LINES 19 - -/** Lowest consensus method where authorities may include - * GuardFraction information in microdescriptors. */ -#define MIN_METHOD_FOR_GUARDFRACTION 20 - -/** Lowest consensus method where authorities may include an "id" line for - * ed25519 identities in microdescriptors. (Broken; see - * consensus_method_is_supported() for more info.) */ -#define MIN_METHOD_FOR_ED25519_ID_IN_MD 21 - -/** Lowest consensus method where authorities vote on ed25519 ids and ensure - * ed25519 id consistency. */ -#define MIN_METHOD_FOR_ED25519_ID_VOTING 22 - -/** Lowest consensus method where authorities may include a shared random - * value(s). */ -#define MIN_METHOD_FOR_SHARED_RANDOM 23 - -/** Lowest consensus method where authorities drop all nodes that don't get - * the Valid flag. */ -#define MIN_METHOD_FOR_EXCLUDING_INVALID_NODES 24 - /** Lowest consensus method where authorities vote on required/recommended * protocols. */ #define MIN_METHOD_FOR_RECOMMENDED_PROTOCOLS 25 diff --git a/src/or/dos.c b/src/or/dos.c index 4d1797eece..2cb3470582 100644 --- a/src/or/dos.c +++ b/src/or/dos.c @@ -15,6 +15,7 @@ #include "main.h" #include "networkstatus.h" #include "nodelist.h" +#include "relay.h" #include "router.h" #include "dos.h" @@ -622,10 +623,12 @@ dos_log_heartbeat(void) char *conn_msg = NULL; char *cc_msg = NULL; char *single_hop_client_msg = NULL; + char *circ_stats_msg = NULL; - if (!dos_is_enabled()) { - goto end; - } + /* Stats number coming from relay.c append_cell_to_circuit_queue(). */ + tor_asprintf(&circ_stats_msg, + " %" PRIu64 " circuits killed with too many cells.", + stats_n_circ_max_cell_reached); if (dos_cc_enabled) { tor_asprintf(&cc_msg, @@ -647,7 +650,8 @@ dos_log_heartbeat(void) } log_notice(LD_HEARTBEAT, - "DoS mitigation since startup:%s%s%s", + "DoS mitigation since startup:%s%s%s%s", + circ_stats_msg, (cc_msg != NULL) ? cc_msg : " [cc not enabled]", (conn_msg != NULL) ? conn_msg : " [conn not enabled]", (single_hop_client_msg != NULL) ? single_hop_client_msg : ""); @@ -655,8 +659,7 @@ dos_log_heartbeat(void) tor_free(conn_msg); tor_free(cc_msg); tor_free(single_hop_client_msg); - - end: + tor_free(circ_stats_msg); return; } diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c index 88d1b94deb..96e6ccaace 100644 --- a/src/or/entrynodes.c +++ b/src/or/entrynodes.c @@ -185,14 +185,14 @@ should_apply_guardfraction(const networkstatus_t *ns) return options->UseGuardFraction; } -/** Return true iff we know a descriptor for <b>guard</b> */ +/** Return true iff we know a preferred descriptor for <b>guard</b> */ static int guard_has_descriptor(const entry_guard_t *guard) { const node_t *node = node_get_by_id(guard->identity); if (!node) return 0; - return node_has_descriptor(node); + return node_has_preferred_descriptor(node, 1); } /** @@ -2269,7 +2269,8 @@ entry_guard_pick_for_circuit(guard_selection_t *gs, // XXXX #20827 check Ed ID. if (! node) goto fail; - if (BUG(usage != GUARD_USAGE_DIRGUARD && !node_has_descriptor(node))) + if (BUG(usage != GUARD_USAGE_DIRGUARD && + !node_has_preferred_descriptor(node, 1))) goto fail; *chosen_node_out = node; diff --git a/src/or/hs_common.c b/src/or/hs_common.c index aa34b0e8fb..24eb7a104a 100644 --- a/src/or/hs_common.c +++ b/src/or/hs_common.c @@ -1279,8 +1279,10 @@ node_has_hsdir_index(const node_t *node) tor_assert(node_supports_v3_hsdir(node)); /* A node can't have an HSDir index without a descriptor since we need desc - * to get its ed25519 key */ - if (!node_has_descriptor(node)) { + * to get its ed25519 key. for_direct_connect should be zero, since we + * always use the consensus-indexed node's keys to build the hash ring, even + * if some of the consensus-indexed nodes are also bridges. */ + if (!node_has_preferred_descriptor(node, 0)) { return 0; } @@ -1611,12 +1613,17 @@ hs_pick_hsdir(smartlist_t *responsible_dirs, const char *req_key_str) hs_clean_last_hid_serv_requests(now); /* Only select those hidden service directories to which we did not send a - * request recently and for which we have a router descriptor here. */ + * request recently and for which we have a router descriptor here. + * + * Use for_direct_connect==0 even if we will be connecting to the node + * directly, since we always use the key information in the + * consensus-indexed node descriptors for building the index. + **/ SMARTLIST_FOREACH_BEGIN(responsible_dirs, routerstatus_t *, dir) { time_t last = hs_lookup_last_hid_serv_request(dir, req_key_str, 0, 0); const node_t *node = node_get_by_id(dir->identity_digest); if (last + hs_hsdir_requery_period(options) >= now || - !node || !node_has_descriptor(node)) { + !node || !node_has_preferred_descriptor(node, 0)) { SMARTLIST_DEL_CURRENT(responsible_dirs, dir); continue; } diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index e03d9e6fe5..5f19792c7d 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -1528,7 +1528,7 @@ networkstatus_consensus_has_ipv6(const or_options_t* options) return cons->consensus_method >= MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS; } else { - return cons->consensus_method >= MIN_METHOD_FOR_A_LINES; + return 1; } } diff --git a/src/or/nodelist.c b/src/or/nodelist.c index 71eee3fa21..e7342f9799 100644 --- a/src/or/nodelist.c +++ b/src/or/nodelist.c @@ -43,6 +43,7 @@ #include "or.h" #include "address.h" #include "address_set.h" +#include "bridges.h" #include "config.h" #include "control.h" #include "dirserv.h" @@ -1130,15 +1131,44 @@ node_is_dir(const node_t *node) } } -/** Return true iff <b>node</b> has either kind of usable descriptor -- that - * is, a routerdescriptor or a microdescriptor. */ +/** Return true iff <b>node</b> has either kind of descriptor -- that + * is, a routerdescriptor or a microdescriptor. + * + * You should probably use node_has_preferred_descriptor() instead. + **/ int -node_has_descriptor(const node_t *node) +node_has_any_descriptor(const node_t *node) { return (node->ri || (node->rs && node->md)); } +/** Return true iff <b>node</b> has the kind of descriptor we would prefer to + * use for it, given our configuration and how we intend to use the node. + * + * If <b>for_direct_connect</b> is true, we intend to connect to the node + * directly, as the first hop of a circuit; otherwise, we intend to connect to + * it indirectly, or use it as if we were connecting to it indirectly. */ +int +node_has_preferred_descriptor(const node_t *node, + int for_direct_connect) +{ + const int is_bridge = node_is_a_configured_bridge(node); + const int we_use_mds = we_use_microdescriptors_for_circuits(get_options()); + + if ((is_bridge && for_direct_connect) || !we_use_mds) { + /* We need an ri in this case. */ + if (!node->ri) + return 0; + } else { + /* Otherwise we need an rs and an md. */ + if (node->rs == NULL || node->md == NULL) + return 0; + } + + return 1; +} + /** Return the router_purpose of <b>node</b>. */ int node_get_purpose(const node_t *node) @@ -1517,6 +1547,7 @@ node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out) { node_assert_ok(node); tor_assert(ap_out); + memset(ap_out, 0, sizeof(*ap_out)); /* Check ri first, because rewrite_node_address_for_bridge() updates * node->ri with the configured bridge address. @@ -1582,6 +1613,11 @@ node_get_prim_dirport(const node_t *node, tor_addr_port_t *ap_out) node_assert_ok(node); tor_assert(ap_out); + /* Clear the address, as a safety precaution if calling functions ignore the + * return value */ + tor_addr_make_null(&ap_out->addr, AF_INET); + ap_out->port = 0; + /* Check ri first, because rewrite_node_address_for_bridge() updates * node->ri with the configured bridge address. */ @@ -2217,7 +2253,8 @@ compute_frac_paths_available(const networkstatus_t *consensus, nu); SMARTLIST_FOREACH_BEGIN(myexits_unflagged, const node_t *, node) { - if (node_has_descriptor(node) && node_exit_policy_rejects_all(node)) { + if (node_has_preferred_descriptor(node, 0) && + node_exit_policy_rejects_all(node)) { SMARTLIST_DEL_CURRENT(myexits_unflagged, node); /* this node is not actually an exit */ np--; diff --git a/src/or/nodelist.h b/src/or/nodelist.h index 53b18ab48a..1ffba2e8df 100644 --- a/src/or/nodelist.h +++ b/src/or/nodelist.h @@ -46,7 +46,9 @@ void node_get_verbose_nickname(const node_t *node, void node_get_verbose_nickname_by_id(const char *id_digest, char *verbose_name_out); int node_is_dir(const node_t *node); -int node_has_descriptor(const node_t *node); +int node_has_any_descriptor(const node_t *node); +int node_has_preferred_descriptor(const node_t *node, + int for_direct_connect); int node_get_purpose(const node_t *node); #define node_is_bridge(node) \ (node_get_purpose((node)) == ROUTER_PURPOSE_BRIDGE) diff --git a/src/or/protover.c b/src/or/protover.c index 6532f09c2f..18382ba7c9 100644 --- a/src/or/protover.c +++ b/src/or/protover.c @@ -715,7 +715,7 @@ protover_all_supported(const char *s, char **missing_out) versions->high = i; } /* If the last one to be unsupported is one less than the current - * one, we're in a continous range, so set the high field. */ + * one, we're in a continuous range, so set the high field. */ if ((versions->high && versions->high == i - 1) || /* Similarly, if the last high wasn't set and we're currently * one higher than the low, add current index as the highest diff --git a/src/or/relay.c b/src/or/relay.c index 72a902d8b4..8c248e6d98 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -116,6 +116,9 @@ uint64_t stats_n_relay_cells_relayed = 0; * hop? */ uint64_t stats_n_relay_cells_delivered = 0; +/** Stats: how many circuits have we closed due to the cell queue limit being + * reached (see append_cell_to_circuit_queue()) */ +uint64_t stats_n_circ_max_cell_reached = 0; /** Used to tell which stream to read from first on a circuit. */ static tor_weak_rng_t stream_choice_rng = TOR_WEAK_RNG_INIT; @@ -371,6 +374,12 @@ circuit_package_relay_cell(cell_t *cell, circuit_t *circ, } relay_encrypt_cell_outbound(cell, TO_ORIGIN_CIRCUIT(circ), layer_hint); + + /* Update circ written totals for control port */ + origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); + ocirc->n_written_circ_bw = tor_add_u32_nowrap(ocirc->n_written_circ_bw, + CELL_PAYLOAD_SIZE); + } else { /* incoming cell */ if (CIRCUIT_IS_ORIGIN(circ)) { /* We should never package an _incoming_ cell from the circuit @@ -2862,6 +2871,7 @@ append_cell_to_circuit_queue(circuit_t *circ, channel_t *chan, (exitward) ? "Outbound" : "Inbound", queue->n, max_circuit_cell_queue_size); circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT); + stats_n_circ_max_cell_reached++; return; } diff --git a/src/or/relay.h b/src/or/relay.h index b4c0bff055..f304af684a 100644 --- a/src/or/relay.h +++ b/src/or/relay.h @@ -14,6 +14,7 @@ extern uint64_t stats_n_relay_cells_relayed; extern uint64_t stats_n_relay_cells_delivered; +extern uint64_t stats_n_circ_max_cell_reached; void relay_consensus_has_changed(const networkstatus_t *ns); int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, diff --git a/src/or/rendservice.c b/src/or/rendservice.c index cc22429777..1a93c36433 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -3596,7 +3596,7 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc, /* Don't upload descriptor if we succeeded in doing so last time. */ continue; node = node_get_by_id(hs_dir->identity_digest); - if (!node || !node_has_descriptor(node)) { + if (!node || !node_has_preferred_descriptor(node,0)) { log_info(LD_REND, "Not launching upload for for v2 descriptor to " "hidden service directory %s; we don't have its " "router descriptor. Queuing for later upload.", diff --git a/src/or/routerlist.c b/src/or/routerlist.c index bc3abb236f..1bfbd9f670 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -2335,7 +2335,7 @@ router_add_running_nodes_to_smartlist(smartlist_t *sl, int need_uptime, SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) { if (!node->is_running || !node->is_valid) continue; - if (need_desc && !(node->ri || (node->rs && node->md))) + if (need_desc && !node_has_preferred_descriptor(node, direct_conn)) continue; if (node->ri && node->ri->purpose != ROUTER_PURPOSE_GENERAL) continue; @@ -2758,7 +2758,7 @@ frac_nodes_with_descriptors(const smartlist_t *sl, total <= 0.0) { int n_with_descs = 0; SMARTLIST_FOREACH(sl, const node_t *, node, { - if (node_has_descriptor(node)) + if (node_has_any_descriptor(node)) n_with_descs++; }); return ((double)n_with_descs) / (double)smartlist_len(sl); @@ -2766,7 +2766,7 @@ frac_nodes_with_descriptors(const smartlist_t *sl, present = 0.0; SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) { - if (node_has_descriptor(node)) + if (node_has_any_descriptor(node)) present += bandwidths[node_sl_idx]; } SMARTLIST_FOREACH_END(node); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 79499f2e6f..1834cfad24 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -2743,8 +2743,7 @@ routerstatus_parse_entry_from_string(memarea_t *area, /* These are implied true by having been included in a consensus made * with a given method */ rs->is_flagged_running = 1; /* Starting with consensus method 4. */ - if (consensus_method >= MIN_METHOD_FOR_EXCLUDING_INVALID_NODES) - rs->is_valid = 1; + rs->is_valid = 1; /* Starting with consensus method 24. */ } { const char *protocols = NULL, *version = NULL; diff --git a/src/test/test_bridges.c b/src/test/test_bridges.c index b5bd27e098..c4a4cacd98 100644 --- a/src/test/test_bridges.c +++ b/src/test/test_bridges.c @@ -234,7 +234,7 @@ test_bridges_get_configured_bridge_by_orports_digest(void *arg) ret = get_configured_bridge_by_orports_digest(digest, orports); tt_ptr_op(ret, OP_NE, NULL); - tt_mem_op(addrport1, OP_EQ, bridge_get_addr_port(ret), sizeof(ret)); + tt_assert(tor_addr_port_eq(addrport1, bridge_get_addr_port(ret))); done: smartlist_free(orports); diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 5fac045b26..df5ae2d594 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -2917,8 +2917,9 @@ gen_routerstatus_for_umbw(int idx, time_t now) rs->addr = 0x99008801; rs->or_port = 443; rs->dir_port = 8000; - /* all flags but running cleared */ + /* all flags but running and valid cleared */ rs->is_flagged_running = 1; + rs->is_valid = 1; /* * This one has measured bandwidth below the clip cutoff, and * so shouldn't be clipped; we'll have to test that it isn't @@ -2991,8 +2992,9 @@ gen_routerstatus_for_umbw(int idx, time_t now) rs->addr = 0xC0000203; rs->or_port = 500; rs->dir_port = 1999; - /* all flags but running cleared */ + /* all flags but running and valid cleared */ rs->is_flagged_running = 1; + rs->is_valid = 1; /* * This one has unmeasured bandwidth below the clip cutoff, and * so shouldn't be clipped; we'll have to test that it isn't @@ -3014,7 +3016,7 @@ gen_routerstatus_for_umbw(int idx, time_t now) if (vrs) { vrs->microdesc = tor_malloc_zero(sizeof(vote_microdesc_hash_t)); tor_asprintf(&vrs->microdesc->microdesc_hash_line, - "m 9,10,11,12,13,14,15,16,17 " + "m 25,26,27,28 " "sha256=xyzajkldsdsajdadlsdjaslsdksdjlsdjsdaskdaaa%d\n", idx); } @@ -3040,7 +3042,7 @@ vote_tweaks_for_umbw(networkstatus_t *v, int voter, time_t now) smartlist_clear(v->supported_methods); /* Method 17 is MIN_METHOD_TO_CLIP_UNMEASURED_BW_KB */ smartlist_split_string(v->supported_methods, - "1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17", + "25 26 27 28", NULL, 0, -1); /* If we're using a non-default clip bandwidth, add it to net_params */ if (alternate_clip_bw > 0) { @@ -3202,9 +3204,9 @@ test_routerstatus_for_umbw(routerstatus_t *rs, time_t now) tt_assert(!rs->is_fast); tt_assert(!rs->is_possible_guard); tt_assert(!rs->is_stable); - /* (If it wasn't running it wouldn't be here) */ + /* (If it wasn't running and valid it wouldn't be here) */ tt_assert(rs->is_flagged_running); - tt_assert(!rs->is_valid); + tt_assert(rs->is_valid); tt_assert(!rs->is_named); /* This one should have measured bandwidth below the clip cutoff */ tt_assert(rs->has_bandwidth); @@ -5615,9 +5617,8 @@ test_dir_assumed_flags(void *arg) memarea_t *area = memarea_new(); routerstatus_t *rs = NULL; - /* First, we should always assume that the Running flag is set, even - * when it isn't listed, since the consensus method is always - * higher than 4. */ + /* We can assume that consensus method is higher than 24, so Running and + * Valid are always implicitly set */ const char *str1 = "r example hereiswhereyouridentitygoes 2015-08-30 12:00:00 " "192.168.0.1 9001 0\n" @@ -5626,17 +5627,6 @@ test_dir_assumed_flags(void *arg) const char *cp = str1; rs = routerstatus_parse_entry_from_string(area, &cp, tokens, NULL, NULL, - 23, FLAV_MICRODESC); - tt_assert(rs); - tt_assert(rs->is_flagged_running); - tt_assert(! rs->is_valid); - tt_assert(! rs->is_exit); - tt_assert(rs->is_fast); - routerstatus_free(rs); - - /* With method 24 or later, we can assume "valid" is set. */ - cp = str1; - rs = routerstatus_parse_entry_from_string(area, &cp, tokens, NULL, NULL, 24, FLAV_MICRODESC); tt_assert(rs); tt_assert(rs->is_flagged_running); @@ -5769,22 +5759,10 @@ test_dir_networkstatus_consensus_has_ipv6(void *arg) /* Test the bounds for A lines in the NS consensus */ mock_options->UseMicrodescriptors = 0; - mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES; + mock_networkstatus->consensus_method = MIN_SUPPORTED_CONSENSUS_METHOD; has_ipv6 = networkstatus_consensus_has_ipv6(get_options()); tt_assert(has_ipv6); - mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES + 1; - has_ipv6 = networkstatus_consensus_has_ipv6(get_options()); - tt_assert(has_ipv6); - - mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES + 20; - has_ipv6 = networkstatus_consensus_has_ipv6(get_options()); - tt_assert(has_ipv6); - - mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES - 1; - has_ipv6 = networkstatus_consensus_has_ipv6(get_options()); - tt_assert(!has_ipv6); - /* Test the bounds for A lines in the microdesc consensus */ mock_options->UseMicrodescriptors = 1; @@ -5793,6 +5771,10 @@ test_dir_networkstatus_consensus_has_ipv6(void *arg) has_ipv6 = networkstatus_consensus_has_ipv6(get_options()); tt_assert(has_ipv6); + mock_networkstatus->consensus_method = MAX_SUPPORTED_CONSENSUS_METHOD + 20; + has_ipv6 = networkstatus_consensus_has_ipv6(get_options()); + tt_assert(has_ipv6); + mock_networkstatus->consensus_method = MIN_METHOD_FOR_A_LINES_IN_MICRODESC_CONSENSUS + 1; has_ipv6 = networkstatus_consensus_has_ipv6(get_options()); diff --git a/src/test/test_hs.c b/src/test/test_hs.c index 9189bb65be..64448de510 100644 --- a/src/test/test_hs.c +++ b/src/test/test_hs.c @@ -361,6 +361,7 @@ test_pick_tor2web_rendezvous_node(void *arg) /* Parse Tor2webRendezvousPoints as a routerset. */ options->Tor2webRendezvousPoints = routerset_new(); + options->UseMicrodescriptors = 0; retval = routerset_parse(options->Tor2webRendezvousPoints, tor2web_rendezvous_str, "test_tor2web_rp"); diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c index 8c273c9639..17ba11ca7d 100644 --- a/src/test/test_hs_common.c +++ b/src/test/test_hs_common.c @@ -305,7 +305,8 @@ helper_add_hsdir_to_networkstatus(networkstatus_t *ns, node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest); tt_assert(node); node->rs = rs; - /* We need this to exist for node_has_descriptor() to return true. */ + /* We need this to exist for node_has_preferred_descriptor() to return + * true. */ node->md = tor_malloc_zero(sizeof(microdesc_t)); /* Do this now the nodelist_set_routerinfo() function needs a "rs" to set * the indexes which it doesn't have when it is called. */ diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c index 59b28f7580..3d02fc1a59 100644 --- a/src/test/test_microdesc.c +++ b/src/test/test_microdesc.c @@ -385,25 +385,6 @@ static const char test_ri2[] = "cf34GXHv61XReJF3AlzNHFpbrPOYmowmhrTULKyMqow=\n" "-----END SIGNATURE-----\n"; -static const char test_md_8[] = - "onion-key\n" - "-----BEGIN RSA PUBLIC KEY-----\n" - "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n" - "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n" - "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n" - "-----END RSA PUBLIC KEY-----\n" - "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"; - -static const char test_md_16[] = - "onion-key\n" - "-----BEGIN RSA PUBLIC KEY-----\n" - "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n" - "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n" - "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n" - "-----END RSA PUBLIC KEY-----\n" - "ntor-onion-key Gg73xH7+kTfT6bi1uNVx9gwQdQas9pROIfmc4NpAdC4=\n" - "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"; - static const char test_md_18[] = "onion-key\n" "-----BEGIN RSA PUBLIC KEY-----\n" @@ -415,16 +396,6 @@ static const char test_md_18[] = "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n" "id rsa1024 Cd47okjCHD83YGzThGBDptXs9Z4\n"; -static const char test_md2_18[] = - "onion-key\n" - "-----BEGIN RSA PUBLIC KEY-----\n" - "MIGJAoGBAL2R8EfubUcahxha4u02P4VAR0llQIMwFAmrHPjzcK7apcQgDOf2ovOA\n" - "+YQnJFxlpBmCoCZC6ssCi+9G0mqo650lFuTMP5I90BdtjotfzESfTykHLiChyvhd\n" - "l0dlqclb2SU/GKem/fLRXH16aNi72CdSUu/1slKs/70ILi34QixRAgMBAAE=\n" - "-----END RSA PUBLIC KEY-----\n" - "ntor-onion-key hbxdRnfVUJJY7+KcT4E3Rs7/zuClbN3hJrjSBiEGMgI=\n" - "id rsa1024 t+J/EEITw28T5+mCkYKEXklZl6A\n"; - static const char test_md2_21[] = "onion-key\n" "-----BEGIN RSA PUBLIC KEY-----\n" @@ -444,17 +415,6 @@ test_md_generate(void *arg) ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL, NULL); tt_assert(ri); - md = dirvote_create_microdescriptor(ri, 8); - tt_str_op(md->body, OP_EQ, test_md_8); - - /* XXXX test family lines. */ - /* XXXX test method 14 for A lines. */ - /* XXXX test method 15 for P6 lines. */ - - microdesc_free(md); - md = NULL; - md = dirvote_create_microdescriptor(ri, 16); - tt_str_op(md->body, OP_EQ, test_md_16); microdesc_free(md); md = NULL; @@ -471,11 +431,6 @@ test_md_generate(void *arg) microdesc_free(md); md = NULL; - md = dirvote_create_microdescriptor(ri, 18); - tt_str_op(md->body, OP_EQ, test_md2_18); - - microdesc_free(md); - md = NULL; md = dirvote_create_microdescriptor(ri, 21); tt_str_op(md->body, OP_EQ, test_md2_21); tt_assert(ed25519_pubkey_eq(md->ed25519_identity_pkey, diff --git a/src/test/test_status.c b/src/test/test_status.c index 50ea203e4d..b4ca17891b 100644 --- a/src/test/test_status.c +++ b/src/test/test_status.c @@ -340,7 +340,7 @@ NS(test_main)(void *arg) actual = log_heartbeat(0); tt_int_op(actual, OP_EQ, expected); - tt_int_op(CALLED(logv), OP_EQ, 5); + tt_int_op(CALLED(logv), OP_EQ, 6); done: NS_UNMOCK(tls_get_write_overhead_ratio); @@ -439,6 +439,16 @@ NS(logv)(int severity, log_domain_mask_t domain, tt_ptr_op(strstr(funcname, "rep_hist_log_link_protocol_counts"), OP_NE, NULL); break; + case 5: + tt_int_op(severity, OP_EQ, LOG_NOTICE); + tt_int_op(domain, OP_EQ, LD_HEARTBEAT); + tt_str_op(format, OP_EQ, "DoS mitigation since startup:%s%s%s%s"); + tt_str_op(va_arg(ap, char *), OP_EQ, + " 0 circuits killed with too many cells."); + tt_str_op(va_arg(ap, char *), OP_EQ, " [cc not enabled]"); + tt_str_op(va_arg(ap, char *), OP_EQ, " [conn not enabled]"); + tt_str_op(va_arg(ap, char *), OP_EQ, ""); + break; default: tt_abort_msg("unexpected call to logv()"); // TODO: prettyprint args break; diff --git a/src/test/test_util.c b/src/test/test_util.c index 24b43c899b..350273bf4c 100644 --- a/src/test/test_util.c +++ b/src/test/test_util.c @@ -6050,6 +6050,23 @@ test_util_monotonic_time_add_msec(void *arg) } static void +test_util_nowrap_math(void *arg) +{ + (void)arg; + + tt_u64_op(0, OP_EQ, tor_add_u32_nowrap(0, 0)); + tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(0, 1)); + tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(1, 0)); + tt_u64_op(4, OP_EQ, tor_add_u32_nowrap(2, 2)); + tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX-1, 2)); + tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(2, UINT32_MAX-1)); + tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX, UINT32_MAX)); + + done: + ; +} + +static void test_util_htonll(void *arg) { (void)arg; @@ -6243,6 +6260,7 @@ struct testcase_t util_tests[] = { UTIL_TEST(listdir, 0), UTIL_TEST(parent_dir, 0), UTIL_TEST(ftruncate, 0), + UTIL_TEST(nowrap_math, 0), UTIL_TEST(num_cpus, 0), UTIL_TEST_WIN_ONLY(load_win_lib, 0), UTIL_TEST_NO_WIN(exit_status, 0), |