aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/compat.c14
-rw-r--r--src/common/compat.h3
-rw-r--r--src/common/compat_libevent.c3
-rw-r--r--src/or/command.c6
-rw-r--r--src/or/config.c2
-rw-r--r--src/or/connection.c42
-rw-r--r--src/or/connection_or.c6
-rw-r--r--src/or/consdiff.c5
-rw-r--r--src/or/hs_circuit.c9
-rw-r--r--src/or/hs_common.c17
-rw-r--r--src/or/hs_common.h2
-rw-r--r--src/or/main.c111
-rw-r--r--src/or/main.h2
-rw-r--r--src/or/networkstatus.c3
-rw-r--r--src/or/or.h5
-rw-r--r--src/or/rendservice.c4
-rw-r--r--src/or/tor_main.c16
-rw-r--r--src/test/bench.c2
-rw-r--r--src/test/test_hs_intropoint.c1
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));