diff options
Diffstat (limited to 'src/or/main.c')
-rw-r--r-- | src/or/main.c | 293 |
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 |