summaryrefslogtreecommitdiff
path: root/src/or/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/main.c')
-rw-r--r--src/or/main.c293
1 files changed, 59 insertions, 234 deletions
diff --git a/src/or/main.c b/src/or/main.c
index d4d98ee317..66a8571901 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -46,6 +46,7 @@
#include "onion.h"
#include "periodic.h"
#include "policies.h"
+#include "protover.h"
#include "transports.h"
#include "relay.h"
#include "rendclient.h"
@@ -57,6 +58,7 @@
#include "routerlist.h"
#include "routerparse.h"
#include "scheduler.h"
+#include "shared_random.h"
#include "statefile.h"
#include "status.h"
#include "util_process.h"
@@ -68,15 +70,7 @@
#include "memarea.h"
#include "sandbox.h"
-#ifdef HAVE_EVENT2_EVENT_H
#include <event2/event.h>
-#else
-#include <event.h>
-#endif
-
-#ifdef USE_BUFFEREVENTS
-#include <event2/bufferevent.h>
-#endif
#ifdef HAVE_SYSTEMD
# if defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__)
@@ -104,8 +98,6 @@ static int run_main_loop_until_done(void);
static void process_signal(int sig);
/********* START VARIABLES **********/
-
-#ifndef USE_BUFFEREVENTS
int global_read_bucket; /**< Max number of bytes I can read this second. */
int global_write_bucket; /**< Max number of bytes I can write this second. */
@@ -119,7 +111,6 @@ static int stats_prev_global_read_bucket;
/** What was the write bucket before the last second_elapsed_callback() call?
* (used to determine how many bytes we've written). */
static int stats_prev_global_write_bucket;
-#endif
/* DOCDOC stats_prev_n_read */
static uint64_t stats_prev_n_read = 0;
@@ -172,9 +163,6 @@ static int can_complete_circuits = 0;
/** How often do we check for router descriptors that we should download
* when we have enough directory info? */
#define LAZY_DESCRIPTOR_RETRY_INTERVAL (60)
-/** How often do we 'forgive' undownloadable router descriptors and attempt
- * to download them again? */
-#define DESCRIPTOR_FAILURE_RESET_INTERVAL (60*60)
/** Decides our behavior when no logs are configured/before any
* logs have been configured. For 0, we log notice to stdout as normal.
@@ -191,28 +179,6 @@ int quiet_level = 0;
*
****************************************************************************/
-#if defined(_WIN32) && defined(USE_BUFFEREVENTS)
-/** Remove the kernel-space send and receive buffers for <b>s</b>. For use
- * with IOCP only. */
-static int
-set_buffer_lengths_to_zero(tor_socket_t s)
-{
- int zero = 0;
- int r = 0;
- if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&zero,
- (socklen_t)sizeof(zero))) {
- log_warn(LD_NET, "Unable to clear SO_SNDBUF");
- r = -1;
- }
- if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&zero,
- (socklen_t)sizeof(zero))) {
- log_warn(LD_NET, "Unable to clear SO_RCVBUF");
- r = -1;
- }
- return r;
-}
-#endif
-
/** Return 1 if we have successfully built a circuit, and nothing has changed
* to make us think that maybe we can't.
*/
@@ -255,66 +221,9 @@ connection_add_impl(connection_t *conn, int is_connecting)
conn->conn_array_index = smartlist_len(connection_array);
smartlist_add(connection_array, conn);
-#ifdef USE_BUFFEREVENTS
- if (connection_type_uses_bufferevent(conn)) {
- if (SOCKET_OK(conn->s) && !conn->linked) {
-
-#ifdef _WIN32
- if (tor_libevent_using_iocp_bufferevents() &&
- get_options()->UserspaceIOCPBuffers) {
- set_buffer_lengths_to_zero(conn->s);
- }
-#endif
-
- conn->bufev = bufferevent_socket_new(
- tor_libevent_get_base(),
- conn->s,
- BEV_OPT_DEFER_CALLBACKS);
- if (!conn->bufev) {
- log_warn(LD_BUG, "Unable to create socket bufferevent");
- smartlist_del(connection_array, conn->conn_array_index);
- conn->conn_array_index = -1;
- return -1;
- }
- if (is_connecting) {
- /* Put the bufferevent into a "connecting" state so that we'll get
- * a "connected" event callback on successful write. */
- bufferevent_socket_connect(conn->bufev, NULL, 0);
- }
- connection_configure_bufferevent_callbacks(conn);
- } else if (conn->linked && conn->linked_conn &&
- connection_type_uses_bufferevent(conn->linked_conn)) {
- tor_assert(!(SOCKET_OK(conn->s)));
- if (!conn->bufev) {
- struct bufferevent *pair[2] = { NULL, NULL };
- if (bufferevent_pair_new(tor_libevent_get_base(),
- BEV_OPT_DEFER_CALLBACKS,
- pair) < 0) {
- log_warn(LD_BUG, "Unable to create bufferevent pair");
- smartlist_del(connection_array, conn->conn_array_index);
- conn->conn_array_index = -1;
- return -1;
- }
- tor_assert(pair[0]);
- conn->bufev = pair[0];
- conn->linked_conn->bufev = pair[1];
- } /* else the other side already was added, and got a bufferevent_pair */
- connection_configure_bufferevent_callbacks(conn);
- } else {
- tor_assert(!conn->linked);
- }
-
- if (conn->bufev)
- tor_assert(conn->inbuf == NULL);
-
- if (conn->linked_conn && conn->linked_conn->bufev)
- tor_assert(conn->linked_conn->inbuf == NULL);
- }
-#else
(void) is_connecting;
-#endif
- if (!HAS_BUFFEREVENT(conn) && (SOCKET_OK(conn->s) || conn->linked)) {
+ if (SOCKET_OK(conn->s) || conn->linked) {
conn->read_event = tor_event_new(tor_libevent_get_base(),
conn->s, EV_READ|EV_PERSIST, conn_read_callback, conn);
conn->write_event = tor_event_new(tor_libevent_get_base(),
@@ -343,12 +252,6 @@ connection_unregister_events(connection_t *conn)
log_warn(LD_BUG, "Error removing write event for %d", (int)conn->s);
tor_free(conn->write_event);
}
-#ifdef USE_BUFFEREVENTS
- if (conn->bufev) {
- bufferevent_free(conn->bufev);
- conn->bufev = NULL;
- }
-#endif
if (conn->type == CONN_TYPE_AP_DNS_LISTENER) {
dnsserv_close_listener(conn);
}
@@ -479,8 +382,8 @@ connection_in_array(connection_t *conn)
/** Set <b>*array</b> to an array of all connections. <b>*array</b> must not
* be modified.
*/
-smartlist_t *
-get_connection_array(void)
+MOCK_IMPL(smartlist_t *,
+get_connection_array, (void))
{
if (!connection_array)
connection_array = smartlist_new();
@@ -508,17 +411,6 @@ get_bytes_written,(void))
void
connection_watch_events(connection_t *conn, watchable_events_t events)
{
- IF_HAS_BUFFEREVENT(conn, {
- short ev = ((short)events) & (EV_READ|EV_WRITE);
- short old_ev = bufferevent_get_enabled(conn->bufev);
- if ((ev & ~old_ev) != 0) {
- bufferevent_enable(conn->bufev, ev);
- }
- if ((old_ev & ~ev) != 0) {
- bufferevent_disable(conn->bufev, old_ev & ~ev);
- }
- return;
- });
if (events & READ_EVENT)
connection_start_reading(conn);
else
@@ -536,9 +428,6 @@ connection_is_reading(connection_t *conn)
{
tor_assert(conn);
- IF_HAS_BUFFEREVENT(conn,
- return (bufferevent_get_enabled(conn->bufev) & EV_READ) != 0;
- );
return conn->reading_from_linked_conn ||
(conn->read_event && event_pending(conn->read_event, EV_READ, NULL));
}
@@ -589,11 +478,6 @@ connection_stop_reading,(connection_t *conn))
{
tor_assert(conn);
- IF_HAS_BUFFEREVENT(conn, {
- bufferevent_disable(conn->bufev, EV_READ);
- return;
- });
-
if (connection_check_event(conn, conn->read_event) < 0) {
return;
}
@@ -616,11 +500,6 @@ connection_start_reading,(connection_t *conn))
{
tor_assert(conn);
- IF_HAS_BUFFEREVENT(conn, {
- bufferevent_enable(conn->bufev, EV_READ);
- return;
- });
-
if (connection_check_event(conn, conn->read_event) < 0) {
return;
}
@@ -644,10 +523,6 @@ connection_is_writing(connection_t *conn)
{
tor_assert(conn);
- IF_HAS_BUFFEREVENT(conn,
- return (bufferevent_get_enabled(conn->bufev) & EV_WRITE) != 0;
- );
-
return conn->writing_to_linked_conn ||
(conn->write_event && event_pending(conn->write_event, EV_WRITE, NULL));
}
@@ -658,11 +533,6 @@ connection_stop_writing,(connection_t *conn))
{
tor_assert(conn);
- IF_HAS_BUFFEREVENT(conn, {
- bufferevent_disable(conn->bufev, EV_WRITE);
- return;
- });
-
if (connection_check_event(conn, conn->write_event) < 0) {
return;
}
@@ -686,11 +556,6 @@ connection_start_writing,(connection_t *conn))
{
tor_assert(conn);
- IF_HAS_BUFFEREVENT(conn, {
- bufferevent_enable(conn->bufev, EV_WRITE);
- return;
- });
-
if (connection_check_event(conn, conn->write_event) < 0) {
return;
}
@@ -796,6 +661,23 @@ close_closeable_connections(void)
}
}
+/** Count moribund connections for the OOS handler */
+MOCK_IMPL(int,
+connection_count_moribund, (void))
+{
+ int moribund = 0;
+
+ /*
+ * Count things we'll try to kill when close_closeable_connections()
+ * runs next.
+ */
+ SMARTLIST_FOREACH_BEGIN(closeable_connection_lst, connection_t *, conn) {
+ if (SOCKET_OK(conn->s) && connection_is_moribund(conn)) ++moribund;
+ } SMARTLIST_FOREACH_END(conn);
+
+ return moribund;
+}
+
/** Libevent callback: this gets invoked when (connection_t*)<b>conn</b> has
* some data to read. */
static void
@@ -888,21 +770,6 @@ conn_close_if_marked(int i)
assert_connection_ok(conn, now);
/* assert_all_pending_dns_resolves_ok(); */
-#ifdef USE_BUFFEREVENTS
- if (conn->bufev) {
- if (conn->hold_open_until_flushed &&
- evbuffer_get_length(bufferevent_get_output(conn->bufev))) {
- /* don't close yet. */
- return 0;
- }
- if (conn->linked_conn && ! conn->linked_conn->marked_for_close) {
- /* We need to do this explicitly so that the linked connection
- * notices that there was an EOF. */
- bufferevent_flush(conn->bufev, EV_WRITE, BEV_FINISHED);
- }
- }
-#endif
-
log_debug(LD_NET,"Cleaning up connection (fd "TOR_SOCKET_T_FORMAT").",
conn->s);
@@ -912,7 +779,6 @@ conn_close_if_marked(int i)
if (conn->proxy_state == PROXY_INFANT)
log_failed_proxy_connection(conn);
- IF_HAS_BUFFEREVENT(conn, goto unlink);
if ((SOCKET_OK(conn->s) || conn->linked_conn) &&
connection_wants_to_flush(conn)) {
/* s == -1 means it's an incomplete edge connection, or that the socket
@@ -971,7 +837,7 @@ conn_close_if_marked(int i)
connection_stop_writing(conn);
}
if (connection_is_reading(conn)) {
- /* XXXX024 We should make this code unreachable; if a connection is
+ /* XXXX+ We should make this code unreachable; if a connection is
* marked for close and flushing, there is no point in reading to it
* at all. Further, checking at this point is a bit of a hack: it
* would make much more sense to react in
@@ -997,9 +863,6 @@ conn_close_if_marked(int i)
}
}
-#ifdef USE_BUFFEREVENTS
- unlink:
-#endif
connection_unlink(conn); /* unlink, remove, free */
return 1;
}
@@ -1145,11 +1008,7 @@ run_connection_housekeeping(int i, time_t now)
the connection or send a keepalive, depending. */
or_conn = TO_OR_CONN(conn);
-#ifdef USE_BUFFEREVENTS
- tor_assert(conn->bufev);
-#else
tor_assert(conn->outbuf);
-#endif
chan = TLS_CHAN_TO_BASE(or_conn->chan);
tor_assert(chan);
@@ -1259,7 +1118,6 @@ static int periodic_events_initialized = 0;
CALLBACK(rotate_onion_key);
CALLBACK(check_ed_keys);
CALLBACK(launch_descriptor_fetches);
-CALLBACK(reset_descriptor_failures);
CALLBACK(rotate_x509_certificate);
CALLBACK(add_entropy);
CALLBACK(launch_reachability_tests);
@@ -1291,7 +1149,6 @@ static periodic_event_item_t periodic_events[] = {
CALLBACK(rotate_onion_key),
CALLBACK(check_ed_keys),
CALLBACK(launch_descriptor_fetches),
- CALLBACK(reset_descriptor_failures),
CALLBACK(rotate_x509_certificate),
CALLBACK(add_entropy),
CALLBACK(launch_reachability_tests),
@@ -1624,15 +1481,6 @@ launch_descriptor_fetches_callback(time_t now, const or_options_t *options)
}
static int
-reset_descriptor_failures_callback(time_t now, const or_options_t *options)
-{
- (void)now;
- (void)options;
- router_reset_descriptor_download_failures();
- return DESCRIPTOR_FAILURE_RESET_INTERVAL;
-}
-
-static int
rotate_x509_certificate_callback(time_t now, const or_options_t *options)
{
static int first = 1;
@@ -1647,8 +1495,8 @@ rotate_x509_certificate_callback(time_t now, const or_options_t *options)
* TLS context. */
log_info(LD_GENERAL,"Rotating tls context.");
if (router_initialize_tls_context() < 0) {
- log_warn(LD_BUG, "Error reinitializing TLS context");
- tor_assert(0);
+ log_err(LD_BUG, "Error reinitializing TLS context");
+ tor_assert_unreached();
}
/* We also make sure to rotate the TLS connections themselves if they've
@@ -2069,25 +1917,10 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg)
/* the second has rolled over. check more stuff. */
seconds_elapsed = current_second ? (int)(now - current_second) : 0;
-#ifdef USE_BUFFEREVENTS
- {
- uint64_t cur_read,cur_written;
- connection_get_rate_limit_totals(&cur_read, &cur_written);
- bytes_written = (size_t)(cur_written - stats_prev_n_written);
- bytes_read = (size_t)(cur_read - stats_prev_n_read);
- stats_n_bytes_read += bytes_read;
- stats_n_bytes_written += bytes_written;
- if (accounting_is_enabled(options) && seconds_elapsed >= 0)
- accounting_add_bytes(bytes_read, bytes_written, seconds_elapsed);
- stats_prev_n_written = cur_written;
- stats_prev_n_read = cur_read;
- }
-#else
bytes_read = (size_t)(stats_n_bytes_read - stats_prev_n_read);
bytes_written = (size_t)(stats_n_bytes_written - stats_prev_n_written);
stats_prev_n_read = stats_n_bytes_read;
stats_prev_n_written = stats_n_bytes_written;
-#endif
control_event_bandwidth_used((uint32_t)bytes_read,(uint32_t)bytes_written);
control_event_stream_bandwidth_used();
@@ -2159,12 +1992,11 @@ systemd_watchdog_callback(periodic_timer_t *timer, void *arg)
}
#endif
-#ifndef USE_BUFFEREVENTS
/** Timer: used to invoke refill_callback(). */
static periodic_timer_t *refill_timer = NULL;
/** Libevent callback: invoked periodically to refill token buckets
- * and count r/w bytes. It is only used when bufferevents are disabled. */
+ * and count r/w bytes. */
static void
refill_callback(periodic_timer_t *timer, void *arg)
{
@@ -2208,7 +2040,6 @@ refill_callback(periodic_timer_t *timer, void *arg)
current_millisecond = now; /* remember what time it is, for next time */
}
-#endif
#ifndef _WIN32
/** Called when a possibly ignorable libevent error occurs; ensures that we
@@ -2235,8 +2066,8 @@ ip_address_changed(int at_interface)
{
const or_options_t *options = get_options();
int server = server_mode(options);
- int exit_reject_private = (server && options->ExitRelay
- && options->ExitPolicyRejectPrivate);
+ int exit_reject_interfaces = (server && options->ExitRelay
+ && options->ExitPolicyRejectLocalInterfaces);
if (at_interface) {
if (! server) {
@@ -2254,8 +2085,8 @@ ip_address_changed(int at_interface)
}
/* Exit relays incorporate interface addresses in their exit policies when
- * ExitPolicyRejectPrivate is set */
- if (exit_reject_private || (server && !at_interface)) {
+ * ExitPolicyRejectLocalInterfaces is set */
+ if (exit_reject_interfaces || (server && !at_interface)) {
mark_my_descriptor_dirty("IP address changed");
}
@@ -2384,13 +2215,6 @@ do_main_loop(void)
}
}
-#ifdef USE_BUFFEREVENTS
- log_warn(LD_GENERAL, "Tor was compiled with the --enable-bufferevents "
- "option. This is still experimental, and might cause strange "
- "bugs. If you want a more stable Tor, be sure to build without "
- "--enable-bufferevents.");
-#endif
-
handle_signals(1);
/* load the private keys, if we're supposed to have them, and set up the
@@ -2404,10 +2228,8 @@ do_main_loop(void)
/* Set up our buckets */
connection_bucket_init();
-#ifndef USE_BUFFEREVENTS
stats_prev_global_read_bucket = global_read_bucket;
stats_prev_global_write_bucket = global_write_bucket;
-#endif
/* initialize the bootstrap status events to know we're starting up */
control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0);
@@ -2462,6 +2284,13 @@ do_main_loop(void)
cpu_init();
}
+ /* Setup shared random protocol subsystem. */
+ if (authdir_mode_publishes_statuses(get_options())) {
+ if (sr_init(1) < 0) {
+ return -1;
+ }
+ }
+
/* set up once-a-second callback. */
if (! second_timer) {
struct timeval one_second;
@@ -2497,7 +2326,6 @@ do_main_loop(void)
}
#endif
-#ifndef USE_BUFFEREVENTS
if (!refill_timer) {
struct timeval refill_interval;
int msecs = get_options()->TokenBucketRefillInterval;
@@ -2511,7 +2339,6 @@ do_main_loop(void)
NULL);
tor_assert(refill_timer);
}
-#endif
#ifdef HAVE_SYSTEMD
{
@@ -2573,9 +2400,7 @@ run_main_loop_once(void)
return -1;
#endif
} else {
- if (ERRNO_IS_EINPROGRESS(e))
- log_warn(LD_BUG,
- "libevent call returned EINPROGRESS? Please report.");
+ tor_assert_nonfatal_once(! ERRNO_IS_EINPROGRESS(e));
log_debug(LD_NET,"libevent call interrupted.");
/* You can't trust the results of this poll(). Go back to the
* top of the big for loop. */
@@ -2706,9 +2531,6 @@ get_uptime,(void))
return stats_n_seconds_working;
}
-extern uint64_t rephist_total_alloc;
-extern uint32_t rephist_total_num;
-
/**
* Write current memory usage information to the log.
*/
@@ -3010,14 +2832,9 @@ tor_init(int argc, char *argv[])
{
const char *version = get_version();
- const char *bev_str =
-#ifdef USE_BUFFEREVENTS
- "(with bufferevents) ";
-#else
- "";
-#endif
- log_notice(LD_GENERAL, "Tor v%s %srunning on %s with Libevent %s, "
- "OpenSSL %s and Zlib %s.", version, bev_str,
+
+ log_notice(LD_GENERAL, "Tor %s running on %s with Libevent %s, "
+ "OpenSSL %s and Zlib %s.", version,
get_uname(),
tor_libevent_get_version_str(),
crypto_openssl_get_version_str(),
@@ -3032,11 +2849,6 @@ tor_init(int argc, char *argv[])
"Expect more bugs than usual.");
}
-#ifdef NON_ANONYMOUS_MODE_ENABLED
- log_warn(LD_GENERAL, "This copy of Tor was compiled to run in a "
- "non-anonymous mode. It will provide NO ANONYMITY.");
-#endif
-
if (network_init()<0) {
log_err(LD_BUG,"Error initializing network; exiting.");
return -1;
@@ -3048,15 +2860,18 @@ tor_init(int argc, char *argv[])
return -1;
}
+ /* The options are now initialised */
+ const or_options_t *options = get_options();
+
#ifndef _WIN32
if (geteuid()==0)
log_warn(LD_GENERAL,"You are running Tor as root. You don't need to, "
"and you probably shouldn't.");
#endif
- if (crypto_global_init(get_options()->HardwareAccel,
- get_options()->AccelName,
- get_options()->AccelDir)) {
+ if (crypto_global_init(options->HardwareAccel,
+ options->AccelName,
+ options->AccelDir)) {
log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting.");
return -1;
}
@@ -3065,6 +2880,9 @@ tor_init(int argc, char *argv[])
log_warn(LD_NET, "Problem initializing libevent RNG.");
}
+ /* Scan/clean unparseable descroptors; after reading config */
+ routerparse_init();
+
return 0;
}
@@ -3166,9 +2984,11 @@ tor_free_all(int postfork)
scheduler_free_all();
nodelist_free_all();
microdesc_free_all();
+ routerparse_free_all();
ext_orport_free_all();
control_free_all();
sandbox_free_getaddrinfo_cache();
+ protover_free_all();
if (!postfork) {
config_free_all();
or_state_free_all();
@@ -3189,9 +3009,7 @@ tor_free_all(int postfork)
smartlist_free(active_linked_connection_lst);
periodic_timer_free(second_timer);
teardown_periodic_events();
-#ifndef USE_BUFFEREVENTS
periodic_timer_free(refill_timer);
-#endif
if (!postfork) {
release_lockfile();
@@ -3230,6 +3048,9 @@ tor_cleanup(void)
accounting_record_bandwidth_usage(now, get_or_state());
or_state_mark_dirty(get_or_state(), 0); /* force an immediate save. */
or_state_save(now);
+ if (authdir_mode(options)) {
+ sr_save_and_cleanup();
+ }
if (authdir_mode_tests_reachability(options))
rep_hist_record_mtbf_data(now, 0);
keypin_close_journal();
@@ -3388,6 +3209,7 @@ sandbox_init_filter(void)
OPEN_DATADIR_SUFFIX("cached-extrainfo.new", ".tmp");
OPEN_DATADIR("cached-extrainfo.tmp.tmp");
OPEN_DATADIR_SUFFIX("state", ".tmp");
+ OPEN_DATADIR_SUFFIX("sr-state", ".tmp");
OPEN_DATADIR_SUFFIX("unparseable-desc", ".tmp");
OPEN_DATADIR_SUFFIX("v3-status-votes", ".tmp");
OPEN_DATADIR("key-pinning-journal");
@@ -3440,6 +3262,7 @@ sandbox_init_filter(void)
RENAME_SUFFIX("cached-extrainfo", ".new");
RENAME_SUFFIX("cached-extrainfo.new", ".tmp");
RENAME_SUFFIX("state", ".tmp");
+ RENAME_SUFFIX("sr-state", ".tmp");
RENAME_SUFFIX("unparseable-desc", ".tmp");
RENAME_SUFFIX("v3-status-votes", ".tmp");
@@ -3653,6 +3476,8 @@ tor_main(int argc, char *argv[])
#endif
}
+ monotime_init();
+
switch (get_options()->command) {
case CMD_RUN_TOR:
#ifdef NT_SERVICE