diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/compat.c | 14 | ||||
-rw-r--r-- | src/common/compat.h | 3 | ||||
-rw-r--r-- | src/common/compat_libevent.c | 3 | ||||
-rw-r--r-- | src/or/command.c | 6 | ||||
-rw-r--r-- | src/or/config.c | 2 | ||||
-rw-r--r-- | src/or/connection.c | 42 | ||||
-rw-r--r-- | src/or/connection_or.c | 6 | ||||
-rw-r--r-- | src/or/consdiff.c | 5 | ||||
-rw-r--r-- | src/or/hs_circuit.c | 9 | ||||
-rw-r--r-- | src/or/hs_common.c | 17 | ||||
-rw-r--r-- | src/or/hs_common.h | 2 | ||||
-rw-r--r-- | src/or/main.c | 111 | ||||
-rw-r--r-- | src/or/main.h | 2 | ||||
-rw-r--r-- | src/or/networkstatus.c | 3 | ||||
-rw-r--r-- | src/or/or.h | 5 | ||||
-rw-r--r-- | src/or/rendservice.c | 4 | ||||
-rw-r--r-- | src/or/tor_main.c | 16 | ||||
-rw-r--r-- | src/test/bench.c | 2 | ||||
-rw-r--r-- | src/test/test_hs_intropoint.c | 1 |
19 files changed, 193 insertions, 60 deletions
diff --git a/src/common/compat.c b/src/common/compat.c index b4bd6eba06..6a61c6c919 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -1675,7 +1675,7 @@ get_max_sockets(void) * fail by returning -1 and <b>max_out</b> is untouched. * * If we are unable to set the limit value because of setrlimit() failing, - * return -1 and <b>max_out</b> is set to the current maximum value returned + * return 0 and <b>max_out</b> is set to the current maximum value returned * by getrlimit(). * * Otherwise, return 0 and store the maximum we found inside <b>max_out</b> @@ -1740,13 +1740,14 @@ set_max_file_descriptors(rlim_t limit, int *max_out) rlim.rlim_cur = rlim.rlim_max; if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) { - int bad = 1; + int couldnt_set = 1; + const int setrlimit_errno = errno; #ifdef OPEN_MAX uint64_t try_limit = OPEN_MAX - ULIMIT_BUFFER; if (errno == EINVAL && try_limit < (uint64_t) rlim.rlim_cur) { /* On some platforms, OPEN_MAX is the real limit, and getrlimit() is * full of nasty lies. I'm looking at you, OSX 10.5.... */ - rlim.rlim_cur = try_limit; + rlim.rlim_cur = MIN((rlim_t) try_limit, rlim.rlim_cur); if (setrlimit(RLIMIT_NOFILE, &rlim) == 0) { if (rlim.rlim_cur < (rlim_t)limit) { log_warn(LD_CONFIG, "We are limited to %lu file descriptors by " @@ -1761,14 +1762,13 @@ set_max_file_descriptors(rlim_t limit, int *max_out) (unsigned long)try_limit, (unsigned long)OPEN_MAX, (unsigned long)rlim.rlim_max); } - bad = 0; + couldnt_set = 0; } } #endif /* defined(OPEN_MAX) */ - if (bad) { + if (couldnt_set) { log_warn(LD_CONFIG,"Couldn't set maximum number of file descriptors: %s", - strerror(errno)); - return -1; + strerror(setrlimit_errno)); } } /* leave some overhead for logs, etc, */ diff --git a/src/common/compat.h b/src/common/compat.h index 0aabee68c8..93301feda0 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -10,6 +10,9 @@ #ifdef _WIN32 #include <winsock2.h> #include <ws2tcpip.h> +#ifndef SIO_IDEAL_SEND_BACKLOG_QUERY +#define SIO_IDEAL_SEND_BACKLOG_QUERY 0x4004747b +#endif #endif #include "torint.h" #include "testsupport.h" diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c index b5e9cc9332..735385557c 100644 --- a/src/common/compat_libevent.c +++ b/src/common/compat_libevent.c @@ -243,7 +243,8 @@ tor_init_libevent_rng(void) void tor_libevent_free_all(void) { - event_base_free(the_event_base); + if (the_event_base) + event_base_free(the_event_base); the_event_base = NULL; } diff --git a/src/or/command.c b/src/or/command.c index ae419ad068..bd70e37a07 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -328,12 +328,6 @@ command_process_create_cell(cell_t *cell, channel_t *chan) if (connection_or_digest_is_known_relay(chan->identity_digest)) { rep_hist_note_circuit_handshake_requested(create_cell->handshake_type); - // Needed for chutney: Sometimes relays aren't in the consensus yet, and - // get marked as clients. This resets their channels once they appear. - // Probably useful for normal operation wrt relay flapping, too. - channel_clear_client(chan); - } else { - channel_mark_client(chan); } if (create_cell->handshake_type != ONION_HANDSHAKE_TYPE_FAST) { diff --git a/src/or/config.c b/src/or/config.c index ebb536b0f9..afaf867851 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -574,6 +574,7 @@ static config_var_t option_vars_[] = { VAR("__ReloadTorrcOnSIGHUP", BOOL, ReloadTorrcOnSIGHUP, "1"), VAR("__AllDirActionsPrivate", BOOL, AllDirActionsPrivate, "0"), VAR("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"), + VAR("__DisableSignalHandlers", BOOL, DisableSignalHandlers, "0"), VAR("__LeaveStreamsUnattached",BOOL, LeaveStreamsUnattached, "0"), VAR("__HashedControlSessionPassword", LINELIST, HashedControlSessionPassword, NULL), @@ -4705,6 +4706,7 @@ options_transition_allowed(const or_options_t *old, NO_CHANGE_BOOL(DisableDebuggerAttachment); NO_CHANGE_BOOL(NoExec); NO_CHANGE_INT(OwningControllerFD); + NO_CHANGE_BOOL(DisableSignalHandlers); if (sandbox_is_active()) { #define SB_NOCHANGE_STR(opt) \ diff --git a/src/or/connection.c b/src/or/connection.c index 3c37c59b40..a020bef775 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -3761,6 +3761,44 @@ connection_outbuf_too_full(connection_t *conn) return (conn->outbuf_flushlen > 10*CELL_PAYLOAD_SIZE); } +/** + * On Windows Vista and Windows 7, tune the send buffer size according to a + * hint from the OS. + * + * This should help fix slow upload rates. + */ +static void + +update_send_buffer_size(tor_socket_t sock) +{ +#ifdef _WIN32 + /* We only do this on Vista and 7, because earlier versions of Windows + * don't have the SIO_IDEAL_SEND_BACKLOG_QUERY functionality, and on + * later versions it isn't necessary. */ + static int isVistaOr7 = -1; + if (isVistaOr7 == -1) { + isVistaOr7 = 0; + OSVERSIONINFO osvi = { 0 }; + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion < 2) + isVistaOr7 = 1; + } + if (!isVistaOr7) + return; + if (get_options()->ConstrainedSockets) + return; + ULONG isb = 0; + DWORD bytesReturned = 0; + if (!WSAIoctl(sock, SIO_IDEAL_SEND_BACKLOG_QUERY, NULL, 0, + &isb, sizeof(isb), &bytesReturned, NULL, NULL)) { + setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (const char*)&isb, sizeof(isb)); + } +#else + (void) sock; +#endif +} + /** Try to flush more bytes onto <b>conn</b>-\>s. * * This function gets called either from conn_write_callback() in main.c @@ -3879,6 +3917,9 @@ connection_handle_write_impl(connection_t *conn, int force) result = buf_flush_to_tls(conn->outbuf, or_conn->tls, max_to_write, &conn->outbuf_flushlen); + if (result >= 0) + update_send_buffer_size(conn->s); + /* If we just flushed the last bytes, tell the channel on the * or_conn to check if it needs to geoip_change_dirreq_state() */ /* XXXX move this to flushed_some or finished_flushing -NM */ @@ -3953,6 +3994,7 @@ connection_handle_write_impl(connection_t *conn, int force) connection_mark_for_close(conn); return -1; } + update_send_buffer_size(conn->s); n_written = (size_t) result; } diff --git a/src/or/connection_or.c b/src/or/connection_or.c index a877761491..8379f58030 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -1970,6 +1970,12 @@ connection_or_set_state_open(or_connection_t *conn) connection_or_change_state(conn, OR_CONN_STATE_OPEN); control_event_or_conn_status(conn, OR_CONN_EVENT_CONNECTED, 0); + /* Link protocol 3 appeared in Tor 0.2.3.6-alpha, so any connection + * that uses an earlier link protocol should not be treated as a relay. */ + if (conn->link_proto < 3) { + channel_mark_client(TLS_CHAN_TO_BASE(conn->chan)); + } + or_handshake_state_free(conn->handshake_state); conn->handshake_state = NULL; connection_start_reading(TO_CONN(conn)); diff --git a/src/or/consdiff.c b/src/or/consdiff.c index 1baa11897c..deaf465fe7 100644 --- a/src/or/consdiff.c +++ b/src/or/consdiff.c @@ -1285,8 +1285,11 @@ consdiff_apply_diff(const smartlist_t *cons1, STATIC int consensus_split_lines(smartlist_t *out, const char *s, memarea_t *area) { + const char *end_of_str = s + strlen(s); + tor_assert(*end_of_str == '\0'); + while (*s) { - const char *eol = strchr(s, '\n'); + const char *eol = memchr(s, '\n', end_of_str - s); if (!eol) { /* File doesn't end with newline. */ return -1; diff --git a/src/or/hs_circuit.c b/src/or/hs_circuit.c index 95073522ed..753c0fcd6a 100644 --- a/src/or/hs_circuit.c +++ b/src/or/hs_circuit.c @@ -485,9 +485,14 @@ can_relaunch_service_rendezvous_point(const origin_circuit_t *circ) goto disallow; } + /* We check failure_count >= hs_get_service_max_rend_failures()-1 below, and + * the -1 is because we increment the failure count for our current failure + * *after* this clause. */ + int max_rend_failures = hs_get_service_max_rend_failures() - 1; + /* A failure count that has reached maximum allowed or circuit that expired, * we skip relaunching. */ - if (circ->build_state->failure_count > MAX_REND_FAILURES || + if (circ->build_state->failure_count > max_rend_failures || circ->build_state->expiry_time <= time(NULL)) { log_info(LD_REND, "Attempt to build a rendezvous circuit to %s has " "failed with %d attempts and expiry time %ld. " @@ -546,7 +551,7 @@ retry_service_rendezvous_point(const origin_circuit_t *circ) /* Transfer build state information to the new circuit state in part to * catch any other failures. */ - new_circ->build_state->failure_count = bstate->failure_count++; + new_circ->build_state->failure_count = bstate->failure_count+1; new_circ->build_state->expiry_time = bstate->expiry_time; new_circ->hs_ident = hs_ident_circuit_dup(circ->hs_ident); diff --git a/src/or/hs_common.c b/src/or/hs_common.c index 4c56b2d11f..0e7d789705 100644 --- a/src/or/hs_common.c +++ b/src/or/hs_common.c @@ -210,6 +210,23 @@ hs_check_service_private_dir(const char *username, const char *path, return 0; } +/* Default, minimum and maximum values for the maximum rendezvous failures + * consensus parameter. */ +#define MAX_REND_FAILURES_DEFAULT 2 +#define MAX_REND_FAILURES_MIN 1 +#define MAX_REND_FAILURES_MAX 10 + +/** How many times will a hidden service operator attempt to connect to + * a requested rendezvous point before giving up? */ +int +hs_get_service_max_rend_failures(void) +{ + return networkstatus_get_param(NULL, "hs_service_max_rdv_failures", + MAX_REND_FAILURES_DEFAULT, + MAX_REND_FAILURES_MIN, + MAX_REND_FAILURES_MAX); +} + /** Get the default HS time period length in minutes from the consensus. */ STATIC uint64_t get_time_period_length(void) diff --git a/src/or/hs_common.h b/src/or/hs_common.h index f59c2b6050..83ba1b8599 100644 --- a/src/or/hs_common.h +++ b/src/or/hs_common.h @@ -177,6 +177,8 @@ void hs_cleanup_circ(circuit_t *circ); int hs_check_service_private_dir(const char *username, const char *path, unsigned int dir_group_readable, unsigned int create); +int hs_get_service_max_rend_failures(void); + char *hs_path_from_filename(const char *directory, const char *filename); void hs_build_address(const ed25519_public_key_t *key, uint8_t version, char *addr_out); diff --git a/src/or/main.c b/src/or/main.c index 5d4825ca95..10e606f3ac 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -742,6 +742,20 @@ shutdown_did_not_work_callback(evutil_socket_t fd, short event, void *arg) // LCOV_EXCL_STOP } +#ifdef ENABLE_RESTART_DEBUGGING +static struct event *tor_shutdown_event_loop_for_restart_event = NULL; +static void +tor_shutdown_event_loop_for_restart_cb( + evutil_socket_t fd, short event, void *arg) +{ + (void)fd; + (void)event; + (void)arg; + tor_event_free(tor_shutdown_event_loop_for_restart_event); + tor_shutdown_event_loop_and_exit(0); +} +#endif + /** * After finishing the current callback (if any), shut down the main loop, * clean up the process, and exit with <b>exitcode</b>. @@ -2596,7 +2610,7 @@ do_main_loop(void) } } - handle_signals(1); + handle_signals(); monotime_init(); timers_initialize(); @@ -2741,6 +2755,31 @@ do_main_loop(void) main_loop_should_exit = 0; main_loop_exit_value = 0; +#ifdef ENABLE_RESTART_DEBUGGING + { + static int first_time = 1; + + if (first_time && getenv("TOR_DEBUG_RESTART")) { + first_time = 0; + const char *sec_str = getenv("TOR_DEBUG_RESTART_AFTER_SECONDS"); + long sec; + int sec_ok=0; + if (sec_str && + (sec = tor_parse_long(sec_str, 10, 0, INT_MAX, &sec_ok, NULL)) && + sec_ok) { + /* Okay, we parsed the seconds. */ + } else { + sec = 5; + } + struct timeval restart_after = { (time_t) sec, 0 }; + tor_shutdown_event_loop_for_restart_event = + tor_evtimer_new(tor_libevent_get_base(), + tor_shutdown_event_loop_for_restart_cb, NULL); + event_add(tor_shutdown_event_loop_for_restart_event, &restart_after); + } + } +#endif + return run_main_loop_until_done(); } @@ -3104,9 +3143,15 @@ exit_function(void) #else #define UNIX_ONLY 1 #endif + static struct { + /** A numeric code for this signal. Must match the signal value if + * try_to_register is true. */ int signal_value; + /** True if we should try to register this signal with libevent and catch + * corresponding posix signals. False otherwise. */ int try_to_register; + /** Pointer to hold the event object constructed for this signal. */ struct event *signal_event; } signal_handlers[] = { #ifdef SIGINT @@ -3140,50 +3185,40 @@ static struct { { -1, -1, NULL } }; -/** Set up the signal handlers for either parent or child process */ +/** Set up the signal handler events for this process, and register them + * with libevent if appropriate. */ void -handle_signals(int is_parent) +handle_signals(void) { int i; - if (is_parent) { - for (i = 0; signal_handlers[i].signal_value >= 0; ++i) { - if (signal_handlers[i].try_to_register) { - signal_handlers[i].signal_event = - tor_evsignal_new(tor_libevent_get_base(), - signal_handlers[i].signal_value, - signal_callback, - &signal_handlers[i].signal_value); - if (event_add(signal_handlers[i].signal_event, NULL)) - log_warn(LD_BUG, "Error from libevent when adding " - "event for signal %d", - signal_handlers[i].signal_value); - } else { - signal_handlers[i].signal_event = - tor_event_new(tor_libevent_get_base(), -1, - EV_SIGNAL, signal_callback, - &signal_handlers[i].signal_value); - } + const int enabled = !get_options()->DisableSignalHandlers; + + for (i = 0; signal_handlers[i].signal_value >= 0; ++i) { + /* Signal handlers are only registered with libevent if they need to catch + * real POSIX signals. We construct these signal handler events in either + * case, though, so that controllers can activate them with the SIGNAL + * command. + */ + if (enabled && signal_handlers[i].try_to_register) { + signal_handlers[i].signal_event = + tor_evsignal_new(tor_libevent_get_base(), + signal_handlers[i].signal_value, + signal_callback, + &signal_handlers[i].signal_value); + if (event_add(signal_handlers[i].signal_event, NULL)) + log_warn(LD_BUG, "Error from libevent when adding " + "event for signal %d", + signal_handlers[i].signal_value); + } else { + signal_handlers[i].signal_event = + tor_event_new(tor_libevent_get_base(), -1, + EV_SIGNAL, signal_callback, + &signal_handlers[i].signal_value); } - } else { -#ifndef _WIN32 - struct sigaction action; - action.sa_flags = 0; - sigemptyset(&action.sa_mask); - action.sa_handler = SIG_IGN; - sigaction(SIGINT, &action, NULL); - sigaction(SIGTERM, &action, NULL); - sigaction(SIGPIPE, &action, NULL); - sigaction(SIGUSR1, &action, NULL); - sigaction(SIGUSR2, &action, NULL); - sigaction(SIGHUP, &action, NULL); -#ifdef SIGXFSZ - sigaction(SIGXFSZ, &action, NULL); -#endif -#endif /* !defined(_WIN32) */ } } -/* Make sure the signal handler for signal_num will be called. */ +/* Cause the signal handler for signal_num to be called in the event loop. */ void activate_signal(int signal_num) { diff --git a/src/or/main.h b/src/or/main.h index d8593b57d9..c49d216f4e 100644 --- a/src/or/main.h +++ b/src/or/main.h @@ -66,7 +66,7 @@ MOCK_DECL(long,get_uptime,(void)); unsigned get_signewnym_epoch(void); -void handle_signals(int is_parent); +void handle_signals(void); void activate_signal(int signal_num); int try_locking(const or_options_t *options, int err_if_locked); diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index deef62bd40..aa0a8d15c3 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -2077,6 +2077,7 @@ networkstatus_note_certs_arrived(const char *source_dir) { int i; for (i=0; i<N_CONSENSUS_FLAVORS; ++i) { + const char *flavor_name = networkstatus_get_flavor_name(i); consensus_waiting_for_certs_t *waiting = &consensus_waiting_for_certs[i]; if (!waiting->consensus) continue; @@ -2084,7 +2085,7 @@ networkstatus_note_certs_arrived(const char *source_dir) char *waiting_body = waiting->body; if (!networkstatus_set_current_consensus( waiting_body, - networkstatus_get_flavor_name(i), + flavor_name, NSSET_WAS_WAITING_FOR_CERTS, source_dir)) { tor_free(waiting_body); diff --git a/src/or/or.h b/src/or/or.h index d3d8877047..c81e29c95c 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -4696,6 +4696,11 @@ typedef struct { /** List of files that were opened by %include in torrc and torrc-defaults */ smartlist_t *FilesOpenedByIncludes; + + /** If true, Tor shouldn't install any posix signal handlers, since it is + * running embedded inside another process. + */ + int DisableSignalHandlers; } or_options_t; #define LOG_PROTOCOL_WARN (get_protocol_warning_severity_level()) diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 06166d7cf3..52bd6683fd 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -2042,7 +2042,8 @@ rend_service_receive_introduction(origin_circuit_t *circuit, /* Launch a circuit to the client's chosen rendezvous point. */ - for (i=0;i<MAX_REND_FAILURES;i++) { + int max_rend_failures=hs_get_service_max_rend_failures(); + for (i=0;i<max_rend_failures;i++) { int flags = CIRCLAUNCH_NEED_CAPACITY | CIRCLAUNCH_IS_INTERNAL; if (circ_needs_uptime) flags |= CIRCLAUNCH_NEED_UPTIME; /* A Single Onion Service only uses a direct connection if its @@ -2938,7 +2939,6 @@ rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc) cpath_build_state_t *newstate, *oldstate; tor_assert(oldcirc->base_.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND); - oldstate = oldcirc->build_state; tor_assert(oldstate); diff --git a/src/or/tor_main.c b/src/or/tor_main.c index c203d8248f..703669ac99 100644 --- a/src/or/tor_main.c +++ b/src/or/tor_main.c @@ -3,6 +3,11 @@ * Copyright (c) 2007-2017, The Tor Project, Inc. */ /* See LICENSE for licensing information */ +#include "orconfig.h" +#ifdef ENABLE_RESTART_DEBUGGING +#include <stdlib.h> +#endif + /** * \file tor_main.c * \brief Stub module containing a main() function. @@ -19,9 +24,18 @@ int tor_main(int argc, char *argv[]); int main(int argc, char *argv[]) { - int r = tor_main(argc, argv); + int r; +#ifdef ENABLE_RESTART_DEBUGGING + int restart_count = getenv("TOR_DEBUG_RESTART") ? 1 : 0; + again: +#endif + r = tor_main(argc, argv); if (r < 0 || r > 255) return 1; +#ifdef ENABLE_RESTART_DEBUGGING + else if (r == 0 && restart_count--) + goto again; +#endif else return r; } diff --git a/src/test/bench.c b/src/test/bench.c index f30b609900..24ff8b255c 100644 --- a/src/test/bench.c +++ b/src/test/bench.c @@ -718,6 +718,8 @@ main(int argc, const char **argv) init_logging(1); options->command = CMD_RUN_UNITTESTS; options->DataDirectory = tor_strdup(""); + options->KeyDirectory = tor_strdup(""); + options->CacheDirectory = tor_strdup(""); options_init(options); if (set_options(options, &errmsg) < 0) { printf("Failed to set initial options: %s\n", errmsg); diff --git a/src/test/test_hs_intropoint.c b/src/test/test_hs_intropoint.c index 6a7962b212..66832087a0 100644 --- a/src/test/test_hs_intropoint.c +++ b/src/test/test_hs_intropoint.c @@ -725,6 +725,7 @@ test_introduce1_validation(void *arg) /* Create our decoy cell that we'll modify as we go to test the validation * function of that parsed cell. */ cell = helper_create_introduce1_cell(); + tt_assert(cell); /* It should NOT be a legacy cell which will trigger a BUG(). */ memset(cell->legacy_key_id, 'a', sizeof(cell->legacy_key_id)); |