diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/or/circuitstats.c | 63 | ||||
-rw-r--r-- | src/core/or/circuitstats.h | 4 | ||||
-rw-r--r-- | src/feature/control/control_cmd.c | 33 | ||||
-rw-r--r-- | src/feature/control/control_events.c | 59 | ||||
-rw-r--r-- | src/feature/control/control_events.h | 2 | ||||
-rw-r--r-- | src/feature/control/control_hs.c | 3 | ||||
-rw-r--r-- | src/feature/dirauth/dirvote.c | 4 | ||||
-rw-r--r-- | src/feature/dirauth/dirvote.h | 12 | ||||
-rw-r--r-- | src/feature/relay/circuitbuild_relay.c | 58 | ||||
-rw-r--r-- | src/feature/relay/circuitbuild_relay.h | 2 | ||||
-rw-r--r-- | src/feature/relay/relay_periodic.c | 46 | ||||
-rw-r--r-- | src/feature/relay/selftest.c | 147 | ||||
-rw-r--r-- | src/feature/relay/selftest.h | 13 | ||||
-rw-r--r-- | src/lib/sandbox/sandbox.c | 31 | ||||
-rw-r--r-- | src/test/test_circuitbuild.c | 73 | ||||
-rw-r--r-- | src/test/test_hs_control.c | 2 | ||||
-rw-r--r-- | src/test/test_protover.c | 4 |
17 files changed, 430 insertions, 126 deletions
diff --git a/src/core/or/circuitstats.c b/src/core/or/circuitstats.c index 822e5bd308..6a9d84df99 100644 --- a/src/core/or/circuitstats.c +++ b/src/core/or/circuitstats.c @@ -53,9 +53,6 @@ #undef log #include <math.h> -static void cbt_control_event_buildtimeout_set( - const circuit_build_times_t *cbt, - buildtimeout_set_event_t type); static void circuit_build_times_scale_circ_counts(circuit_build_times_t *cbt); #define CBT_BIN_TO_MS(bin) ((bin)*CBT_BIN_WIDTH + (CBT_BIN_WIDTH/2)) @@ -545,7 +542,7 @@ circuit_build_times_get_initial_timeout(void) * Leave estimated parameters, timeout and network liveness intact * for future use. */ -STATIC void +void circuit_build_times_reset(circuit_build_times_t *cbt) { memset(cbt->circuit_build_times, 0, sizeof(cbt->circuit_build_times)); @@ -1893,61 +1890,3 @@ circuit_build_times_update_last_circ(circuit_build_times_t *cbt) { cbt->last_circ_at = approx_time(); } - -static void -cbt_control_event_buildtimeout_set(const circuit_build_times_t *cbt, - buildtimeout_set_event_t type) -{ - char *args = NULL; - double qnt; - double timeout_rate = 0.0; - double close_rate = 0.0; - - switch (type) { - case BUILDTIMEOUT_SET_EVENT_RESET: - case BUILDTIMEOUT_SET_EVENT_SUSPENDED: - case BUILDTIMEOUT_SET_EVENT_DISCARD: - qnt = 1.0; - break; - case BUILDTIMEOUT_SET_EVENT_COMPUTED: - case BUILDTIMEOUT_SET_EVENT_RESUME: - default: - qnt = circuit_build_times_quantile_cutoff(); - break; - } - - /* The timeout rate is the ratio of the timeout count over - * the total number of circuits attempted. The total number of - * circuits is (timeouts+succeeded), since every circuit - * either succeeds, or times out. "Closed" circuits are - * MEASURE_TIMEOUT circuits whose measurement period expired. - * All MEASURE_TIMEOUT circuits are counted in the timeouts stat - * before transitioning to MEASURE_TIMEOUT (in - * circuit_build_times_mark_circ_as_measurement_only()). - * MEASURE_TIMEOUT circuits that succeed are *not* counted as - * "succeeded". See circuit_build_times_handle_completed_hop(). - * - * We cast the denominator - * to promote it to double before the addition, to avoid int32 - * overflow. */ - const double total_circuits = - ((double)cbt->num_circ_timeouts) + cbt->num_circ_succeeded; - if (total_circuits >= 1.0) { - timeout_rate = cbt->num_circ_timeouts / total_circuits; - close_rate = cbt->num_circ_closed / total_circuits; - } - - tor_asprintf(&args, "TOTAL_TIMES=%lu " - "TIMEOUT_MS=%lu XM=%lu ALPHA=%f CUTOFF_QUANTILE=%f " - "TIMEOUT_RATE=%f CLOSE_MS=%lu CLOSE_RATE=%f", - (unsigned long)cbt->total_build_times, - (unsigned long)cbt->timeout_ms, - (unsigned long)cbt->Xm, cbt->alpha, qnt, - timeout_rate, - (unsigned long)cbt->close_ms, - close_rate); - - control_event_buildtimeout_set(type, args); - - tor_free(args); -} diff --git a/src/core/or/circuitstats.h b/src/core/or/circuitstats.h index 52c9100f53..317eeac202 100644 --- a/src/core/or/circuitstats.h +++ b/src/core/or/circuitstats.h @@ -49,6 +49,7 @@ double circuit_build_times_close_rate(const circuit_build_times_t *cbt); void circuit_build_times_update_last_circ(circuit_build_times_t *cbt); void circuit_build_times_mark_circ_as_measurement_only(origin_circuit_t *circ); +void circuit_build_times_reset(circuit_build_times_t *cbt); /** Total size of the circuit timeout history to accumulate. * 1000 is approx 2.5 days worth of continual-use circuits. */ @@ -137,7 +138,6 @@ int32_t circuit_build_times_initial_timeout(void); STATIC double circuit_build_times_calculate_timeout(circuit_build_times_t *cbt, double quantile); STATIC int circuit_build_times_update_alpha(circuit_build_times_t *cbt); -STATIC void circuit_build_times_reset(circuit_build_times_t *cbt); /* Network liveness functions */ STATIC int circuit_build_times_network_check_changed( @@ -158,7 +158,6 @@ void circuit_build_times_network_is_live(circuit_build_times_t *cbt); int circuit_build_times_network_check_live(const circuit_build_times_t *cbt); void circuit_build_times_network_circ_success(circuit_build_times_t *cbt); -#ifdef CIRCUITSTATS_PRIVATE /** Information about the state of our local network connection */ typedef struct { /** The timestamp we last completed a TLS handshake or received a cell */ @@ -208,6 +207,5 @@ struct circuit_build_times_t { uint32_t num_circ_closed; }; -#endif /* defined(CIRCUITSTATS_PRIVATE) */ #endif /* !defined(TOR_CIRCUITSTATS_H) */ diff --git a/src/feature/control/control_cmd.c b/src/feature/control/control_cmd.c index d9a38011de..ff1014632d 100644 --- a/src/feature/control/control_cmd.c +++ b/src/feature/control/control_cmd.c @@ -20,9 +20,11 @@ #include "core/or/circuitlist.h" #include "core/or/circuituse.h" #include "core/or/connection_edge.h" +#include "core/or/circuitstats.h" #include "feature/client/addressmap.h" #include "feature/client/dnsserv.h" #include "feature/client/entrynodes.h" +#include "feature/control/control_events.h" #include "feature/control/control.h" #include "feature/control/control_auth.h" #include "feature/control/control_cmd.h" @@ -55,6 +57,8 @@ #include "feature/rend/rend_encoded_v2_service_descriptor_st.h" #include "feature/rend/rend_service_descriptor_st.h" +#include "src/app/config/statefile.h" + static int control_setconf_helper(control_connection_t *conn, const control_cmd_args_t *args, int use_defaults); @@ -1396,6 +1400,34 @@ handle_control_dropguards(control_connection_t *conn, return 0; } +static const control_cmd_syntax_t droptimeouts_syntax = { + .max_args = 0, +}; + +/** Implementation for the DROPTIMEOUTS command. */ +static int +handle_control_droptimeouts(control_connection_t *conn, + const control_cmd_args_t *args) +{ + (void) args; /* We don't take arguments. */ + + static int have_warned = 0; + if (! have_warned) { + log_warn(LD_CONTROL, "DROPTIMEOUTS is dangerous; make sure you understand " + "the risks before using it. It may be removed in a future " + "version of Tor."); + have_warned = 1; + } + + circuit_build_times_reset(get_circuit_build_times_mutable()); + send_control_done(conn); + or_state_mark_dirty(get_or_state(), 0); + cbt_control_event_buildtimeout_set(get_circuit_build_times(), + BUILDTIMEOUT_SET_EVENT_RESET); + + return 0; +} + static const char *hsfetch_keywords[] = { "SERVER", NULL, }; @@ -2331,6 +2363,7 @@ static const control_cmd_def_t CONTROL_COMMANDS[] = ONE_LINE(protocolinfo, 0), ONE_LINE(authchallenge, CMD_FL_WIPE), ONE_LINE(dropguards, 0), + ONE_LINE(droptimeouts, 0), ONE_LINE(hsfetch, 0), MULTLINE(hspost, 0), ONE_LINE(add_onion, CMD_FL_WIPE), diff --git a/src/feature/control/control_events.c b/src/feature/control/control_events.c index 916ccea875..8e69c772f6 100644 --- a/src/feature/control/control_events.c +++ b/src/feature/control/control_events.c @@ -17,6 +17,7 @@ #include "core/mainloop/mainloop.h" #include "core/or/channeltls.h" #include "core/or/circuitlist.h" +#include "core/or/circuitstats.h" #include "core/or/command.h" #include "core/or/connection_edge.h" #include "core/or/connection_or.h" @@ -141,6 +142,64 @@ clear_circ_bw_fields(void) SMARTLIST_FOREACH_END(circ); } +/* Helper to emit the BUILDTIMEOUT_SET circuit build time event */ +void +cbt_control_event_buildtimeout_set(const circuit_build_times_t *cbt, + buildtimeout_set_event_t type) +{ + char *args = NULL; + double qnt; + double timeout_rate = 0.0; + double close_rate = 0.0; + + switch (type) { + case BUILDTIMEOUT_SET_EVENT_RESET: + case BUILDTIMEOUT_SET_EVENT_SUSPENDED: + case BUILDTIMEOUT_SET_EVENT_DISCARD: + qnt = 1.0; + break; + case BUILDTIMEOUT_SET_EVENT_COMPUTED: + case BUILDTIMEOUT_SET_EVENT_RESUME: + default: + qnt = circuit_build_times_quantile_cutoff(); + break; + } + + /* The timeout rate is the ratio of the timeout count over + * the total number of circuits attempted. The total number of + * circuits is (timeouts+succeeded), since every circuit + * either succeeds, or times out. "Closed" circuits are + * MEASURE_TIMEOUT circuits whose measurement period expired. + * All MEASURE_TIMEOUT circuits are counted in the timeouts stat + * before transitioning to MEASURE_TIMEOUT (in + * circuit_build_times_mark_circ_as_measurement_only()). + * MEASURE_TIMEOUT circuits that succeed are *not* counted as + * "succeeded". See circuit_build_times_handle_completed_hop(). + * + * We cast the denominator + * to promote it to double before the addition, to avoid int32 + * overflow. */ + const double total_circuits = + ((double)cbt->num_circ_timeouts) + cbt->num_circ_succeeded; + if (total_circuits >= 1.0) { + timeout_rate = cbt->num_circ_timeouts / total_circuits; + close_rate = cbt->num_circ_closed / total_circuits; + } + + tor_asprintf(&args, "TOTAL_TIMES=%lu " + "TIMEOUT_MS=%lu XM=%lu ALPHA=%f CUTOFF_QUANTILE=%f " + "TIMEOUT_RATE=%f CLOSE_MS=%lu CLOSE_RATE=%f", + (unsigned long)cbt->total_build_times, + (unsigned long)cbt->timeout_ms, + (unsigned long)cbt->Xm, cbt->alpha, qnt, + timeout_rate, + (unsigned long)cbt->close_ms, + close_rate); + + control_event_buildtimeout_set(type, args); + + tor_free(args); +} /** Set <b>global_event_mask*</b> to the bitwise OR of each live control * connection's event_mask field. */ void diff --git a/src/feature/control/control_events.h b/src/feature/control/control_events.h index 4a5492b510..0c8448e0f8 100644 --- a/src/feature/control/control_events.h +++ b/src/feature/control/control_events.h @@ -223,6 +223,8 @@ void control_event_hs_descriptor_content(const char *onion_address, const char *desc_id, const char *hsdir_fp, const char *content); +void cbt_control_event_buildtimeout_set(const circuit_build_times_t *cbt, + buildtimeout_set_event_t type); void control_events_free_all(void); diff --git a/src/feature/control/control_hs.c b/src/feature/control/control_hs.c index f5b331de9a..c8de03b318 100644 --- a/src/feature/control/control_hs.c +++ b/src/feature/control/control_hs.c @@ -291,7 +291,8 @@ handle_control_onion_client_auth_view(control_connection_t *conn, if (argc >= 1) { hsaddress = smartlist_get(args->args, 0); if (!hs_address_is_valid(hsaddress)) { - control_printf_endreply(conn, 512, "Invalid v3 addr \"%s\"", hsaddress); + control_printf_endreply(conn, 512, "Invalid v3 address \"%s\"", + hsaddress); goto err; } } diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c index 85a23a12f6..79651563b4 100644 --- a/src/feature/dirauth/dirvote.c +++ b/src/feature/dirauth/dirvote.c @@ -4679,9 +4679,9 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key, /* These are hardwired, to avoid disaster. */ v3_out->recommended_relay_protocols = - tor_strdup(DIRVOTE_RECCOMEND_RELAY_PROTO); + tor_strdup(DIRVOTE_RECOMMEND_RELAY_PROTO); v3_out->recommended_client_protocols = - tor_strdup(DIRVOTE_RECCOMEND_CLIENT_PROTO); + tor_strdup(DIRVOTE_RECOMMEND_CLIENT_PROTO); v3_out->required_relay_protocols = tor_strdup(DIRVOTE_REQUIRE_RELAY_PROTO); diff --git a/src/feature/dirauth/dirvote.h b/src/feature/dirauth/dirvote.h index fa7b1da4ab..1b1c9f2cc7 100644 --- a/src/feature/dirauth/dirvote.h +++ b/src/feature/dirauth/dirvote.h @@ -238,15 +238,15 @@ STATIC microdesc_t *dirvote_create_microdescriptor(const routerinfo_t *ri, /** The recommended relay protocols for this authority's votes. * Recommending a new protocol causes old tor versions to log a warning. */ -#define DIRVOTE_RECCOMEND_RELAY_PROTO \ - "Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 " \ - "Link=4 Microdesc=1-2 Relay=2" +#define DIRVOTE_RECOMMEND_RELAY_PROTO \ + "Cons=1-2 Desc=1-2 DirCache=2 HSDir=2 HSIntro=4 HSRend=2 " \ + "Link=5 LinkAuth=3 Microdesc=1-2 Relay=2" /** The recommended client protocols for this authority's votes. * Recommending a new protocol causes old tor versions to log a warning. */ -#define DIRVOTE_RECCOMEND_CLIENT_PROTO \ - "Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 " \ - "Link=4 Microdesc=1-2 Relay=2" +#define DIRVOTE_RECOMMEND_CLIENT_PROTO \ + "Cons=1-2 Desc=1-2 DirCache=2 HSDir=2 HSIntro=4 HSRend=2 " \ + "Link=5 LinkAuth=3 Microdesc=1-2 Relay=2" /** The required relay protocols for this authority's votes. * WARNING: Requiring a new protocol causes old tor versions to shut down. diff --git a/src/feature/relay/circuitbuild_relay.c b/src/feature/relay/circuitbuild_relay.c index b89866b477..470e639aa7 100644 --- a/src/feature/relay/circuitbuild_relay.c +++ b/src/feature/relay/circuitbuild_relay.c @@ -122,6 +122,52 @@ circuit_extend_add_ed25519_helper(struct extend_cell_t *ec) return 0; } +/* Make sure the extend cell <b>ec</b> has an IPv4 address if the relay + * supports in, and if not, fill it in. */ +STATIC int +circuit_extend_add_ipv4_helper(struct extend_cell_t *ec) +{ + IF_BUG_ONCE(!ec) { + return -1; + } + + const node_t *node = node_get_by_id((const char *) ec->node_id); + if (node) { + tor_addr_port_t node_ipv4; + node_get_prim_orport(node, &node_ipv4); + if (tor_addr_is_null(&ec->orport_ipv4.addr) && + !tor_addr_is_null(&node_ipv4.addr)) { + tor_addr_copy(&ec->orport_ipv4.addr, &node_ipv4.addr); + ec->orport_ipv4.port = node_ipv4.port; + } + } + + return 0; +} + +/* Make sure the extend cell <b>ec</b> has an IPv6 address if the relay + * supports in, and if not, fill it in. */ +STATIC int +circuit_extend_add_ipv6_helper(struct extend_cell_t *ec) +{ + IF_BUG_ONCE(!ec) { + return -1; + } + + const node_t *node = node_get_by_id((const char *) ec->node_id); + if (node) { + tor_addr_port_t node_ipv6; + node_get_pref_ipv6_orport(node, &node_ipv6); + if (tor_addr_is_null(&ec->orport_ipv6.addr) && + !tor_addr_is_null(&node_ipv6.addr)) { + tor_addr_copy(&ec->orport_ipv6.addr, &node_ipv6.addr); + ec->orport_ipv6.port = node_ipv6.port; + } + } + + return 0; +} + /* Check if the address and port in the tor_addr_port_t <b>ap</b> are valid, * and are allowed by the current ExtendAllowPrivateAddresses config. * @@ -412,6 +458,12 @@ circuit_extend(struct cell_t *cell, struct circuit_t *circ) if (circuit_extend_lspec_valid_helper(&ec, circ) < 0) return -1; + if (circuit_extend_add_ipv4_helper(&ec) < 0) + return -1; + + if (circuit_extend_add_ipv6_helper(&ec) < 0) + return -1; + /* Check the addresses, without logging */ const int ipv4_valid = circuit_extend_addr_port_is_valid(&ec.orport_ipv4, false, false, 0); @@ -542,7 +594,11 @@ onionskin_answer(struct or_circuit_t *circ, /* record that we could process create cells from a non-local conn * that we didn't initiate; presumably this means that create cells * can reach us too. */ - router_orport_found_reachable(); + tor_addr_t remote_addr; + if (channel_get_addr_if_possible(circ->p_chan, &remote_addr)) { + int family = tor_addr_family(&remote_addr); + router_orport_found_reachable(family); + } } return 0; diff --git a/src/feature/relay/circuitbuild_relay.h b/src/feature/relay/circuitbuild_relay.h index 0783161538..dc0b886a34 100644 --- a/src/feature/relay/circuitbuild_relay.h +++ b/src/feature/relay/circuitbuild_relay.h @@ -73,6 +73,8 @@ onionskin_answer(struct or_circuit_t *circ, STATIC int circuit_extend_state_valid_helper(const struct circuit_t *circ); STATIC int circuit_extend_add_ed25519_helper(struct extend_cell_t *ec); +STATIC int circuit_extend_add_ipv4_helper(struct extend_cell_t *ec); +STATIC int circuit_extend_add_ipv6_helper(struct extend_cell_t *ec); STATIC int circuit_extend_lspec_valid_helper(const struct extend_cell_t *ec, const struct circuit_t *circ); STATIC const tor_addr_port_t * circuit_choose_ip_ap_for_extend( diff --git a/src/feature/relay/relay_periodic.c b/src/feature/relay/relay_periodic.c index 6a92f49d2e..4e915f5e9f 100644 --- a/src/feature/relay/relay_periodic.c +++ b/src/feature/relay/relay_periodic.c @@ -201,20 +201,46 @@ reachability_warnings_callback(time_t now, const or_options_t *options) have_completed_a_circuit()) { /* every 20 minutes, check and complain if necessary */ const routerinfo_t *me = router_get_my_routerinfo(); - if (me && !router_should_skip_orport_reachability_check(options)) { - char *address = tor_dup_ip(me->addr); - if (address) { + bool v4_ok = + router_should_skip_orport_reachability_check_family(options,AF_INET); + bool v6_ok = + router_should_skip_orport_reachability_check_family(options,AF_INET6); + if (me && !(v4_ok && v6_ok)) { + /* We need to warn that one or more of our ORPorts isn't reachable. + * Determine which, and give a reasonable warning. */ + char *address4 = tor_dup_ip(me->addr); + char *address6 = tor_addr_to_str_dup(&me->ipv6_addr); + if (address4 || address6) { + char *where4=NULL, *where6=NULL; + if (!v4_ok) + tor_asprintf(&where4, "%s:%d", address4, me->or_port); + if (!v6_ok) + tor_asprintf(&where6, "[%s]:%d", address6, me->or_port); + const char *opt_and = (!v4_ok && !v6_ok) ? "and" : ""; + log_warn(LD_CONFIG, - "Your server (%s:%d) has not managed to confirm that " - "its ORPort is reachable. Relays do not publish descriptors " + "Your server has not managed to confirm reachability for " + "its ORPort(s) at %s%s%s. 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", - address, me->or_port); - tor_free(address); + where4?where4:"", + opt_and, + where6?where6:""); + tor_free(where4); + tor_free(where6); + if (!v4_ok) { + control_event_server_status(LOG_WARN, + "REACHABILITY_FAILED ORADDRESS=%s:%d", + address4, me->or_port); + } + if (!v6_ok) { + control_event_server_status(LOG_WARN, + "REACHABILITY_FAILED ORADDRESS=[%s]:%d", + address6, me->ipv6_orport); + } } + tor_free(address4); + tor_free(address6); } if (me && !router_should_skip_dirport_reachability_check(options)) { diff --git a/src/feature/relay/selftest.c b/src/feature/relay/selftest.c index 2b0fc951b7..12ce8e8bfd 100644 --- a/src/feature/relay/selftest.c +++ b/src/feature/relay/selftest.c @@ -44,16 +44,20 @@ #include "feature/relay/router.h" #include "feature/relay/selftest.h" -/** Whether we can reach our ORPort from the outside. */ -static int can_reach_or_port = 0; +static bool have_orport_for_family(int family); + +/** Whether we can reach our IPv4 ORPort from the outside. */ +static bool can_reach_or_port_ipv4 = false; +/** Whether we can reach our IPv6 ORPort from the outside. */ +static bool can_reach_or_port_ipv6 = false; /** Whether we can reach our DirPort from the outside. */ -static int can_reach_dir_port = 0; +static bool can_reach_dir_port = false; /** Forget what we have learned about our reachability status. */ void router_reset_reachability(void) { - can_reach_or_port = can_reach_dir_port = 0; + can_reach_or_port_ipv4 = can_reach_or_port_ipv6 = can_reach_dir_port = false; } /** Return 1 if we won't do reachability checks, because: @@ -75,13 +79,39 @@ router_reachability_checks_disabled(const or_options_t *options) * - we've seen a successful reachability check, or * - AssumeReachable is set, or * - the network is disabled. + + * If `family'`is AF_INET or AF_INET6, return true only when we should skip + * the given family's orport check (Because it's been checked, or because we + * aren't checking it.) If `family` is 0, return true if we can skip _all_ + * orport checks. */ int -router_should_skip_orport_reachability_check(const or_options_t *options) +router_should_skip_orport_reachability_check_family( + const or_options_t *options, + int family) { + tor_assert_nonfatal(family == AF_INET || family == AF_INET6 || family == 0); int reach_checks_disabled = router_reachability_checks_disabled(options); - return reach_checks_disabled || - can_reach_or_port; + if (reach_checks_disabled) { + return true; + } + + // Which reachability flags should we look at? + const bool checking_ipv4 = (family == AF_INET || family == 0); + const bool checking_ipv6 = (family == AF_INET6 || family == 0); + + if (checking_ipv4) { + if (have_orport_for_family(AF_INET) && !can_reach_or_port_ipv4) { + return false; + } + } + if (checking_ipv6) { + if (have_orport_for_family(AF_INET6) && !can_reach_or_port_ipv6) { + return false; + } + } + + return true; } /** Return 0 if we need to do a DirPort reachability check, because: @@ -133,6 +163,28 @@ router_should_check_reachability(int test_or, int test_dir) return 1; } +/** + * Return true if we have configured an ORPort for the given family that + * we would like to advertise. + * + * Like other self-testing functions, this function looks at our most + * recently built descriptor. + **/ +static bool +have_orport_for_family(int family) +{ + const routerinfo_t *me = router_get_my_routerinfo(); + + if (!me) + return false; + + tor_addr_port_t ap; + if (router_get_orport(me, &ap, family) < 0) { + return false; + } + return true; +} + /** Allocate and return a new extend_info_t that can be used to build * a circuit to or through the router <b>r</b>, using an address from * <b>family</b> (if available). @@ -255,16 +307,22 @@ router_do_reachability_checks(int test_or, int test_dir) { const routerinfo_t *me = router_get_my_routerinfo(); const or_options_t *options = get_options(); - int orport_reachable = router_should_skip_orport_reachability_check(options); + int orport_reachable_v4 = + router_should_skip_orport_reachability_check_family(options, AF_INET); + int orport_reachable_v6 = + router_should_skip_orport_reachability_check_family(options, AF_INET6); if (router_should_check_reachability(test_or, test_dir)) { - if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) { - /* At the moment, tor relays believe that they are reachable when they - * receive any create cell on an inbound connection. We'll do separate - * IPv4 and IPv6 reachability checks in #34067, and make them more - * precise. */ - router_do_orport_reachability_checks(me, AF_INET, orport_reachable); - router_do_orport_reachability_checks(me, AF_INET6, orport_reachable); + bool need_testing = !circuit_enough_testing_circs(); + /* At the moment, tor relays believe that they are reachable when they + * receive any create cell on an inbound connection, if the address + * family is correct. + */ + if (test_or && (!orport_reachable_v4 || need_testing)) { + router_do_orport_reachability_checks(me, AF_INET, orport_reachable_v4); + } + if (test_or && (!orport_reachable_v6 || need_testing)) { + router_do_orport_reachability_checks(me, AF_INET6, orport_reachable_v6); } if (test_dir && !router_should_skip_dirport_reachability_check(options)) { @@ -341,34 +399,58 @@ inform_testing_reachability(void) return 1; } -/** Annotate that we found our ORPort reachable. */ +/** + * Return true if this module knows of no reason why we shouldn't publish + * a server descriptor. + **/ +static bool +ready_to_publish(const or_options_t *options) +{ + return options->PublishServerDescriptor_ != NO_DIRINFO && + router_should_skip_dirport_reachability_check(options) && + router_should_skip_orport_reachability_check(options); +} + +/** Annotate that we found our ORPort reachable with a given address + * family. */ void -router_orport_found_reachable(void) +router_orport_found_reachable(int family) { const routerinfo_t *me = router_get_my_routerinfo(); const or_options_t *options = get_options(); - if (!can_reach_or_port && me) { - char *address = tor_dup_ip(me->addr); - - if (!address) + bool *can_reach_ptr; + if (family == AF_INET) { + can_reach_ptr = &can_reach_or_port_ipv4; + } else if (family == AF_INET6) { + can_reach_ptr = &can_reach_or_port_ipv6; + } else { + tor_assert_nonfatal_unreached(); + return; + } + if (!*can_reach_ptr && me) { + tor_addr_port_t ap; + if (router_get_orport(me, &ap, family) < 0) { return; + } + char *address = tor_strdup(fmt_addrport_ap(&ap)); + + *can_reach_ptr = true; - log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from " + log_notice(LD_OR,"Self-testing indicates your ORPort %s is reachable from " "the outside. Excellent.%s", - options->PublishServerDescriptor_ != NO_DIRINFO - && router_should_skip_dirport_reachability_check(options) ? - " Publishing server descriptor." : ""); - can_reach_or_port = 1; + address, + ready_to_publish(options) ? + " Publishing server descriptor." : ""); + mark_my_descriptor_dirty("ORPort found reachable"); /* This is a significant enough change to upload immediately, * at least in a test network */ if (options->TestingTorNetwork == 1) { reschedule_descriptor_update_check(); } - /* We'll add an IPv6 event in #34068. */ control_event_server_status(LOG_NOTICE, - "REACHABILITY_SUCCEEDED ORADDRESS=%s:%d", - address, me->or_port); + "REACHABILITY_SUCCEEDED ORADDRESS=%s", + address); tor_free(address); } } @@ -379,18 +461,19 @@ router_dirport_found_reachable(void) { const routerinfo_t *me = router_get_my_routerinfo(); const or_options_t *options = get_options(); + if (!can_reach_dir_port && me) { char *address = tor_dup_ip(me->addr); if (!address) return; + can_reach_dir_port = true; log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable " "from the outside. Excellent.%s", - options->PublishServerDescriptor_ != NO_DIRINFO - && router_should_skip_orport_reachability_check(options) ? + ready_to_publish(options) ? " Publishing server descriptor." : ""); - can_reach_dir_port = 1; + if (router_should_advertise_dirport(options, me->dir_port)) { mark_my_descriptor_dirty("DirPort found reachable"); /* This is a significant enough change to upload immediately, diff --git a/src/feature/relay/selftest.h b/src/feature/relay/selftest.h index 5799a6ca33..d65edf56ff 100644 --- a/src/feature/relay/selftest.h +++ b/src/feature/relay/selftest.h @@ -15,8 +15,11 @@ #ifdef HAVE_MODULE_RELAY struct or_options_t; -int router_should_skip_orport_reachability_check( - const struct or_options_t *options); +#define router_should_skip_orport_reachability_check(opts) \ + router_should_skip_orport_reachability_check_family((opts),0) +int router_should_skip_orport_reachability_check_family( + const struct or_options_t *options, + int family); int router_should_skip_dirport_reachability_check( const struct or_options_t *options); @@ -24,15 +27,17 @@ void router_do_reachability_checks(int test_or, int test_dir); void router_perform_bandwidth_test(int num_circs, time_t now); int inform_testing_reachability(void); -void router_orport_found_reachable(void); +void router_orport_found_reachable(int family); void router_dirport_found_reachable(void); void router_reset_reachability(void); #else /* !defined(HAVE_MODULE_RELAY) */ -#define router_should_skip_orport_reachability_check(opts) \ +#define router_should_skip_orport_reachability_check(opts) \ ((void)(opts), 0) +#define router_should_skip_orport_reachability_check_family(opts, fam) \ + ((void)(opts), (void)(fam), 0) #define router_should_skip_dirport_reachability_check(opts) \ ((void)(opts), 0) diff --git a/src/lib/sandbox/sandbox.c b/src/lib/sandbox/sandbox.c index b917912f4d..903d48449a 100644 --- a/src/lib/sandbox/sandbox.c +++ b/src/lib/sandbox/sandbox.c @@ -117,6 +117,10 @@ #endif /* defined(__i386__) || ... */ +#ifdef M_SYSCALL +#define SYSCALL_NAME_DEBUGGING +#endif + /**Determines if at least one sandbox is active.*/ static int sandbox_active = 0; /** Holds the parameter list configuration for the sandbox.*/ @@ -1545,8 +1549,10 @@ install_syscall_filter(sandbox_cfg_t* cfg) return (rc < 0 ? -rc : rc); } +#ifdef SYSCALL_NAME_DEBUGGING #include "lib/sandbox/linux_syscalls.inc" +/** Return a string containing the name of a given syscall (if we know it) */ static const char * get_syscall_name(int syscall_num) { @@ -1564,6 +1570,28 @@ get_syscall_name(int syscall_num) } } +/** Return the syscall number from a ucontext_t that we got in a signal + * handler (if we know how to do that). */ +static int +get_syscall_from_ucontext(const ucontext_t *ctx) +{ + return (int) ctx->uc_mcontext.M_SYSCALL; +} +#else +static const char * +get_syscall_name(int syscall_num) +{ + (void) syscall_num; + return "unknown"; +} +static int +get_syscall_from_ucontext(const ucontext_t *ctx) +{ + (void) ctx; + return -1; +} +#endif + #ifdef USE_BACKTRACE #define MAX_DEPTH 256 static void *syscall_cb_buf[MAX_DEPTH]; @@ -1579,7 +1607,6 @@ sigsys_debugging(int nr, siginfo_t *info, void *void_context) { ucontext_t *ctx = (ucontext_t *) (void_context); const char *syscall_name; - int syscall; #ifdef USE_BACKTRACE size_t depth; int n_fds, i; @@ -1594,7 +1621,7 @@ sigsys_debugging(int nr, siginfo_t *info, void *void_context) if (!ctx) return; - syscall = (int) ctx->uc_mcontext.M_SYSCALL; + int syscall = get_syscall_from_ucontext(ctx); #ifdef USE_BACKTRACE depth = backtrace(syscall_cb_buf, MAX_DEPTH); diff --git a/src/test/test_circuitbuild.c b/src/test/test_circuitbuild.c index 88e46af136..e1fbd333d7 100644 --- a/src/test/test_circuitbuild.c +++ b/src/test/test_circuitbuild.c @@ -36,6 +36,7 @@ #include "feature/relay/routermode.h" #include "feature/nodelist/node_st.h" +#include "feature/nodelist/routerinfo_st.h" /* Dummy nodes smartlist for testing */ static smartlist_t dummy_nodes; @@ -823,6 +824,77 @@ test_circuit_extend_lspec_valid(void *arg) tor_free(p_chan); } +#define NODE_SET_IPV4(node, ipv4_addr, ipv4_port) { \ + tor_addr_t addr; \ + tor_addr_parse(&addr, ipv4_addr); \ + node->ri->addr = tor_addr_to_ipv4h(&addr); \ + node->ri->or_port = ipv4_port; \ + } + +#define NODE_CLEAR_IPV4(node) { \ + node->ri->addr = 0; \ + node->ri->or_port = 0; \ + } + +#define NODE_SET_IPV6(node, ipv6_addr_str, ipv6_port) { \ + tor_addr_parse(&node->ri->ipv6_addr, ipv6_addr_str); \ + node->ri->ipv6_orport = ipv6_port; \ + } + +/* Test the different cases in circuit_extend_add_ed25519_helper(). */ +static void +test_circuit_extend_add_ip(void *arg) +{ + (void) arg; + tor_addr_t ipv4_tmp; + extend_cell_t *ec = tor_malloc_zero(sizeof(extend_cell_t)); + extend_cell_t *old_ec = tor_malloc_zero(sizeof(extend_cell_t)); + + node_t *fake_node = tor_malloc_zero(sizeof(node_t)); + routerinfo_t *ri = tor_malloc_zero(sizeof(routerinfo_t)); + + MOCK(node_get_by_id, mock_node_get_by_id); + + /* Set up the fake variables for the IPv4 test */ + fake_node->ri = ri; + mocked_node = fake_node; + memset(ec->node_id, 0xAA, sizeof(ec->node_id)); + memcpy(old_ec, ec, sizeof(extend_cell_t)); + NODE_SET_IPV4(fake_node, PUBLIC_IPV4, VALID_PORT); + + /* Do the IPv4 test */ + tt_int_op(circuit_extend_add_ipv4_helper(ec), OP_EQ, 0); + tor_addr_from_ipv4h(&ipv4_tmp, fake_node->ri->addr); + /* The IPv4 should match */ + tt_int_op(tor_addr_compare(&ec->orport_ipv4.addr, &ipv4_tmp, CMP_SEMANTIC), + OP_EQ, 0); + tt_int_op(ec->orport_ipv4.port, OP_EQ, VALID_PORT); + + /* Set up the fake variables for the IPv6 test */ + memcpy(ec, old_ec, sizeof(extend_cell_t)); + NODE_CLEAR_IPV4(fake_node); + NODE_SET_IPV6(fake_node, PUBLIC_IPV6, VALID_PORT); + + /* Do the IPv6 test */ + tt_int_op(circuit_extend_add_ipv6_helper(ec), OP_EQ, 0); + /* The IPv6 should match */ + tt_int_op(tor_addr_compare(&ec->orport_ipv6.addr, &fake_node->ri->ipv6_addr, + CMP_SEMANTIC), OP_EQ, 0); + tt_int_op(ec->orport_ipv6.port, OP_EQ, VALID_PORT); + + /* Cleanup */ + mocked_node = NULL; + + done: + UNMOCK(node_get_by_id); + + tor_free(ec); + tor_free(old_ec); + + tor_free(ri); + tor_free(fake_node); +} + static bool can_extend_over_ipv6_result = false; static int mock_router_can_extend_over_ipv6_calls = 0; static bool @@ -1902,6 +1974,7 @@ struct testcase_t circuitbuild_tests[] = { TEST_CIRCUIT(extend_state_valid, TT_FORK), TEST_CIRCUIT(extend_add_ed25519, TT_FORK), TEST_CIRCUIT(extend_lspec_valid, TT_FORK), + TEST_CIRCUIT(extend_add_ip, TT_FORK), TEST_CIRCUIT(choose_ip_ap_for_extend, 0), TEST_CIRCUIT_PASSTHROUGH(open_connection_for_extend, TT_FORK, "4"), diff --git a/src/test/test_hs_control.c b/src/test/test_hs_control.c index 8ba9f1173c..1f574179e9 100644 --- a/src/test/test_hs_control.c +++ b/src/test/test_hs_control.c @@ -393,7 +393,7 @@ test_hs_control_good_onion_client_auth_add(void *arg) retval = handle_control_command(&conn, (uint32_t) strlen(args), args); tt_int_op(retval, OP_EQ, 0); cp1 = buf_get_contents(TO_CONN(&conn)->outbuf, &sz); - tt_str_op(cp1, OP_EQ, "512 Invalid v3 addr \"house\"\r\n"); + tt_str_op(cp1, OP_EQ, "512 Invalid v3 address \"house\"\r\n"); done: tor_free(args); diff --git a/src/test/test_protover.c b/src/test/test_protover.c index 0880274811..5e74265550 100644 --- a/src/test/test_protover.c +++ b/src/test/test_protover.c @@ -680,8 +680,8 @@ test_protover_vote_roundtrip_ours(void *args) (void) args; const char *examples[] = { protover_get_supported_protocols(), - DIRVOTE_RECCOMEND_RELAY_PROTO, - DIRVOTE_RECCOMEND_CLIENT_PROTO, + DIRVOTE_RECOMMEND_RELAY_PROTO, + DIRVOTE_RECOMMEND_CLIENT_PROTO, DIRVOTE_REQUIRE_RELAY_PROTO, DIRVOTE_REQUIRE_CLIENT_PROTO, }; |