diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/or/circuitlist.c | 2 | ||||
-rw-r--r-- | src/core/or/conflux_pool.c | 43 | ||||
-rw-r--r-- | src/core/or/conflux_pool.h | 2 | ||||
-rw-r--r-- | src/core/or/connection_edge.c | 110 | ||||
-rw-r--r-- | src/core/or/connection_edge.h | 2 | ||||
-rw-r--r-- | src/core/or/connection_or.c | 4 | ||||
-rw-r--r-- | src/core/or/dos.c | 127 | ||||
-rw-r--r-- | src/core/or/dos.h | 34 | ||||
-rw-r--r-- | src/core/or/dos_options.inc | 13 | ||||
-rw-r--r-- | src/core/or/or_circuit_st.h | 4 | ||||
-rw-r--r-- | src/core/or/policies.c | 2 | ||||
-rw-r--r-- | src/core/or/relay.c | 3 | ||||
-rw-r--r-- | src/core/or/scheduler_kist.c | 14 |
13 files changed, 347 insertions, 13 deletions
diff --git a/src/core/or/circuitlist.c b/src/core/or/circuitlist.c index b90c7ebb58..643d97b064 100644 --- a/src/core/or/circuitlist.c +++ b/src/core/or/circuitlist.c @@ -65,6 +65,7 @@ #include "core/or/conflux.h" #include "core/or/conflux_pool.h" #include "core/or/crypt_path.h" +#include "core/or/dos.h" #include "core/or/extendinfo.h" #include "core/or/status.h" #include "core/or/trace_probes_circuit.h" @@ -1130,6 +1131,7 @@ or_circuit_new(circid_t p_circ_id, channel_t *p_chan) cell_queue_init(&circ->p_chan_cells); init_circuit_base(TO_CIRCUIT(circ)); + dos_stream_init_circ_tbf(circ); tor_trace(TR_SUBSYS(circuit), TR_EV(new_or), circ); return circ; diff --git a/src/core/or/conflux_pool.c b/src/core/or/conflux_pool.c index 74781b307a..82043d607f 100644 --- a/src/core/or/conflux_pool.c +++ b/src/core/or/conflux_pool.c @@ -1624,7 +1624,22 @@ linked_circuit_free(circuit_t *circ, bool is_client) /* Circuit can be freed without being closed and so we try to delete this leg * so we can learn if this circuit is the last leg or not. */ - cfx_del_leg(circ->conflux, circ); + if (cfx_del_leg(circ->conflux, circ)) { + /* Check for instances of bug #40870, which we suspect happen + * during exit. If any happen outside of exit, BUG and warn. */ + if (!circ->conflux->in_full_teardown) { + /* We should bug and warn if we're not in a shutdown process; that + * means we got here somehow without a close. */ + if (BUG(!shutting_down)) { + log_warn(LD_BUG, + "Conflux circuit %p being freed without being marked for " + "full teardown via close, with shutdown state %d. " + "Please report this.", circ, shutting_down); + conflux_log_set(LOG_WARN, circ->conflux, is_client); + } + circ->conflux->in_full_teardown = true; + } + } if (CONFLUX_NUM_LEGS(circ->conflux) > 0) { /* The last leg will free the streams but until then, we nullify to avoid @@ -2146,14 +2161,36 @@ conflux_log_set(int loglevel, const conflux_t *cfx, bool is_client) } } +/** + * Conflux needs a notification when tor_shutdown() begins, so that + * when circuits are freed, new legs are not launched. + * + * This needs a separate notification from conflux_pool_free_all(), + * because circuits must be freed before that function. + */ +void +conflux_notify_shutdown(void) +{ + shutting_down = true; +} + +#ifdef TOR_UNIT_TESTS +/** + * For unit tests: Clear the shutting down state so we resume building legs. + */ +void +conflux_clear_shutdown(void) +{ + shutting_down = false; +} +#endif + /** Free and clean up the conflux pool subsystem. This is called by the subsys * manager AFTER all circuits have been freed which implies that all objects in * the pools aren't referenced anymore. */ void conflux_pool_free_all(void) { - shutting_down = true; - digest256map_free(client_linked_pool, free_conflux_void_); digest256map_free(server_linked_pool, free_conflux_void_); digest256map_free(client_unlinked_pool, free_unlinked_void_); diff --git a/src/core/or/conflux_pool.h b/src/core/or/conflux_pool.h index afa4d9d058..eba726b03a 100644 --- a/src/core/or/conflux_pool.h +++ b/src/core/or/conflux_pool.h @@ -12,6 +12,7 @@ #include "core/or/or.h" void conflux_pool_init(void); +void conflux_notify_shutdown(void); void conflux_pool_free_all(void); origin_circuit_t *conflux_get_circ_for_conn(const entry_connection_t *conn, @@ -41,6 +42,7 @@ void conflux_log_set(int loglevel, const conflux_t *cfx, bool is_client); #ifdef TOR_UNIT_TESTS bool launch_new_set(int num_legs); +void conflux_clear_shutdown(void); digest256map_t *get_linked_pool(bool is_client); digest256map_t *get_unlinked_pool(bool is_client); extern uint8_t DEFAULT_CLIENT_UX; diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c index f21779a80c..b36d0d9013 100644 --- a/src/core/or/connection_edge.c +++ b/src/core/or/connection_edge.c @@ -73,6 +73,7 @@ #include "core/or/conflux_util.h" #include "core/or/circuitstats.h" #include "core/or/connection_or.h" +#include "core/or/dos.h" #include "core/or/extendinfo.h" #include "core/or/policies.h" #include "core/or/reasons.h" @@ -105,6 +106,7 @@ #include "lib/buf/buffers.h" #include "lib/crypt_ops/crypto_rand.h" #include "lib/crypt_ops/crypto_util.h" +#include "lib/encoding/confline.h" #include "core/or/cell_st.h" #include "core/or/cpath_build_state_st.h" @@ -3989,6 +3991,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) begin_cell_t bcell; int rv; uint8_t end_reason=0; + dos_stream_defense_type_t dos_defense_type; assert_circuit_ok(circ); if (!CIRCUIT_IS_ORIGIN(circ)) { @@ -4147,6 +4150,24 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) log_debug(LD_EXIT,"about to start the dns_resolve()."); + // in the future we may want to have a similar defense for BEGIN_DIR and + // BEGIN sent to OS. + dos_defense_type = dos_stream_new_begin_or_resolve_cell(or_circ); + switch (dos_defense_type) { + case DOS_STREAM_DEFENSE_NONE: + break; + case DOS_STREAM_DEFENSE_REFUSE_STREAM: + // we don't use END_STREAM_REASON_RESOURCELIMIT because it would make a + // client mark us as non-functional until they get a new consensus. + relay_send_end_cell_from_edge(rh.stream_id, circ, END_STREAM_REASON_MISC, + layer_hint); + connection_free_(TO_CONN(n_stream)); + return 0; + case DOS_STREAM_DEFENSE_CLOSE_CIRCUIT: + connection_free_(TO_CONN(n_stream)); + return -END_CIRC_REASON_RESOURCELIMIT; + } + /* send it off to the gethostbyname farm */ switch (dns_resolve(n_stream)) { case 1: /* resolve worked; now n_stream is attached to circ. */ @@ -4170,17 +4191,21 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) * Called when we receive a RELAY_COMMAND_RESOLVE cell 'cell' along the * circuit <b>circ</b>; * begin resolving the hostname, and (eventually) reply with a RESOLVED cell. + * + * Return -(some circuit end reason) if we want to tear down <b>circ</b>. + * Else return 0. */ int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ) { edge_connection_t *dummy_conn; relay_header_t rh; + dos_stream_defense_type_t dos_defense_type; assert_circuit_ok(TO_CIRCUIT(circ)); relay_header_unpack(&rh, cell->payload); if (rh.length > RELAY_PAYLOAD_SIZE) - return -1; + return 0; /* Note the RESOLVE stream as seen. */ rep_hist_note_exit_stream(RELAY_COMMAND_RESOLVE); @@ -4203,6 +4228,19 @@ connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ) dummy_conn->on_circuit = TO_CIRCUIT(circ); + dos_defense_type = dos_stream_new_begin_or_resolve_cell(circ); + switch (dos_defense_type) { + case DOS_STREAM_DEFENSE_NONE: + break; + case DOS_STREAM_DEFENSE_REFUSE_STREAM: + dns_send_resolved_error_cell(dummy_conn, RESOLVED_TYPE_ERROR_TRANSIENT); + connection_free_(TO_CONN(dummy_conn)); + return 0; + case DOS_STREAM_DEFENSE_CLOSE_CIRCUIT: + connection_free_(TO_CONN(dummy_conn)); + return -END_CIRC_REASON_RESOURCELIMIT; + } + /* send it off to the gethostbyname farm */ switch (dns_resolve(dummy_conn)) { case -1: /* Impossible to resolve; a resolved cell was sent. */ @@ -4237,6 +4275,76 @@ my_exit_policy_rejects(const tor_addr_t *addr, return 0; } +/* Reapply exit policy to existing connections, possibly terminating + * connections + * no longer allowed by the policy. + */ +void +connection_reapply_exit_policy(config_line_t *changes) +{ + int marked_for_close = 0; + smartlist_t *conn_list = NULL; + smartlist_t *policy = NULL; + int config_change_relevant = 0; + + if (get_options()->ReevaluateExitPolicy == 0) { + return; + } + + for (const config_line_t *line = changes; + line && !config_change_relevant; + line = line->next) { + const char* exit_policy_options[] = { + "ExitRelay", + "ExitPolicy", + "ReducedExitPolicy", + "ReevaluateExitPolicy", + "IPv6Exit", + NULL + }; + for (unsigned int i = 0; exit_policy_options[i] != NULL; ++i) { + if (strcmp(line->key, exit_policy_options[i]) == 0) { + config_change_relevant = 1; + break; + } + } + } + + if (!config_change_relevant) { + /* Policy did not change: no need to iterate over connections */ + return; + } + + // we can't use router_compare_to_my_exit_policy as it depend on the + // descriptor, which is regenerated asynchronously, so we have to parse the + // policy ourselves. + // We don't verify for our own IP, it's not part of the configuration. + if (BUG(policies_parse_exit_policy_from_options(get_options(), NULL, NULL, + &policy) != 0)) { + return; + } + + conn_list = connection_list_by_type_purpose(CONN_TYPE_EXIT, + EXIT_PURPOSE_CONNECT); + + SMARTLIST_FOREACH_BEGIN(conn_list, connection_t *, conn) { + addr_policy_result_t verdict = compare_tor_addr_to_addr_policy(&conn->addr, + conn->port, + policy); + if (verdict != ADDR_POLICY_ACCEPTED) { + connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_EXITPOLICY); + connection_mark_for_close(conn); + ++marked_for_close; + } + } SMARTLIST_FOREACH_END(conn); + + smartlist_free(conn_list); + smartlist_free(policy); + + log_info(LD_GENERAL, "Marked %d connections to be closed as no longer " + "allowed per ExitPolicy", marked_for_close); +} + /** Return true iff the consensus allows network reentry. The default value is * false if the parameter is not found. */ static bool diff --git a/src/core/or/connection_edge.h b/src/core/or/connection_edge.h index 59fc17dea5..1bb0e6d368 100644 --- a/src/core/or/connection_edge.h +++ b/src/core/or/connection_edge.h @@ -13,6 +13,7 @@ #define TOR_CONNECTION_EDGE_H #include "lib/testsupport/testsupport.h" +#include "lib/encoding/confline.h" #include "feature/hs/hs_service.h" @@ -101,6 +102,7 @@ void connection_entry_set_controller_wait(entry_connection_t *conn); void connection_ap_about_to_close(entry_connection_t *edge_conn); void connection_exit_about_to_close(edge_connection_t *edge_conn); +void connection_reapply_exit_policy(config_line_t *changes); MOCK_DECL(int, connection_ap_handshake_send_begin,(entry_connection_t *ap_conn)); diff --git a/src/core/or/connection_or.c b/src/core/or/connection_or.c index 343c1a67ed..30ce5e0c57 100644 --- a/src/core/or/connection_or.c +++ b/src/core/or/connection_or.c @@ -104,7 +104,7 @@ static void connection_or_check_canonicity(or_connection_t *conn, /** * Cast a `connection_t *` to an `or_connection_t *`. * - * Exit with an assertion failure if the input is not an `or_connnection_t`. + * Exit with an assertion failure if the input is not an `or_connection_t`. **/ or_connection_t * TO_OR_CONN(connection_t *c) @@ -116,7 +116,7 @@ TO_OR_CONN(connection_t *c) /** * Cast a `const connection_t *` to a `const or_connection_t *`. * - * Exit with an assertion failure if the input is not an `or_connnection_t`. + * Exit with an assertion failure if the input is not an `or_connection_t`. **/ const or_connection_t * CONST_TO_OR_CONN(const connection_t *c) diff --git a/src/core/or/dos.c b/src/core/or/dos.c index ccdb30dbee..b789f87aae 100644 --- a/src/core/or/dos.c +++ b/src/core/or/dos.c @@ -79,6 +79,24 @@ static uint64_t conn_num_addr_connect_rejected; static uint32_t dos_num_circ_max_outq; /* + * Stream denial of service mitigation. + * + * Namespace used for this mitigation framework is "dos_stream_". + */ + +/* Is the connection DoS mitigation enabled? */ +static unsigned int dos_stream_enabled = 0; + +/* Consensus parameters. They can be changed when a new consensus arrives. + * They are initialized with the hardcoded default values. */ +static dos_stream_defense_type_t dos_stream_defense_type; +static uint32_t dos_stream_rate = DOS_STREAM_RATE_DEFAULT; +static uint32_t dos_stream_burst = DOS_STREAM_BURST_DEFAULT; + +/* Keep some stats for the heartbeat so we can report out. */ +static uint64_t stream_num_rejected; + +/* * General interface of the denial of service mitigation subsystem. */ @@ -258,6 +276,59 @@ get_param_conn_connect_defense_time_period(const networkstatus_t *ns) INT32_MAX); } +/* Return true iff the stream creation mitigation is enabled. We look at the + * consensus for this else a default value is returned. */ +MOCK_IMPL(STATIC unsigned int, +get_param_stream_enabled, (const networkstatus_t *ns)) +{ + if (dos_get_options()->DoSStreamCreationEnabled != -1) { + return dos_get_options()->DoSStreamCreationEnabled; + } + + return !!networkstatus_get_param(ns, "DoSStreamCreationEnabled", + DOS_STREAM_ENABLED_DEFAULT, 0, 1); +} + +/* Return the parameter for the time rate that is how many stream per circuit + * over this time span. */ +static uint32_t +get_param_stream_rate(const networkstatus_t *ns) +{ + /* This is in seconds. */ + if (dos_get_options()->DoSStreamCreationRate) { + return dos_get_options()->DoSStreamCreationRate; + } + return networkstatus_get_param(ns, "DoSStreamCreationRate", + DOS_STREAM_RATE_DEFAULT, + 1, INT32_MAX); +} + +/* Return the parameter for the maximum circuit count for the circuit time + * rate. */ +static uint32_t +get_param_stream_burst(const networkstatus_t *ns) +{ + if (dos_get_options()->DoSStreamCreationBurst) { + return dos_get_options()->DoSStreamCreationBurst; + } + return networkstatus_get_param(ns, "DoSStreamCreationBurst", + DOS_STREAM_BURST_DEFAULT, + 1, INT32_MAX); +} + +/* Return the consensus parameter of the circuit creation defense type. */ +static uint32_t +get_param_stream_defense_type(const networkstatus_t *ns) +{ + if (dos_get_options()->DoSStreamCreationDefenseType) { + return dos_get_options()->DoSStreamCreationDefenseType; + } + return networkstatus_get_param(ns, "DoSStreamCreationDefenseType", + DOS_STREAM_DEFENSE_TYPE_DEFAULT, + DOS_STREAM_DEFENSE_NONE, + DOS_STREAM_DEFENSE_MAX); +} + /* Set circuit creation parameters located in the consensus or their default * if none are present. Called at initialization or when the consensus * changes. */ @@ -283,6 +354,12 @@ set_dos_parameters(const networkstatus_t *ns) /* Circuit. */ dos_num_circ_max_outq = get_param_dos_num_circ_max_outq(ns); + + /* Stream. */ + dos_stream_enabled = get_param_stream_enabled(ns); + dos_stream_defense_type = get_param_stream_defense_type(ns); + dos_stream_rate = get_param_stream_rate(ns); + dos_stream_burst = get_param_stream_burst(ns); } /* Free everything for the circuit creation DoS mitigation subsystem. */ @@ -760,6 +837,48 @@ dos_conn_addr_get_defense_type(const tor_addr_t *addr) return DOS_CONN_DEFENSE_NONE; } +/* Stream creation public API. */ + +/** Return the number of rejected stream and resolve. */ +uint64_t +dos_get_num_stream_rejected(void) +{ + return stream_num_rejected; +} + +/* Return the action to take against a BEGIN or RESOLVE cell. Return + * DOS_STREAM_DEFENSE_NONE when no action should be taken. + * Increment the appropriate counter when the cell was found to go over a + * limit. */ +dos_stream_defense_type_t +dos_stream_new_begin_or_resolve_cell(or_circuit_t *circ) +{ + if (!dos_stream_enabled || circ == NULL) + return DOS_STREAM_DEFENSE_NONE; + + token_bucket_ctr_refill(&circ->stream_limiter, + (uint32_t) monotime_coarse_absolute_sec()); + + if (token_bucket_ctr_get(&circ->stream_limiter) > 0) { + token_bucket_ctr_dec(&circ->stream_limiter, 1); + return DOS_STREAM_DEFENSE_NONE; + } + /* if defense type is DOS_STREAM_DEFENSE_NONE but DoSStreamEnabled is true, + * we count offending cells as rejected, despite them being actually + * accepted. */ + ++stream_num_rejected; + return dos_stream_defense_type; +} + +/* Initialize the token bucket for stream rate limit on a circuit. */ +void +dos_stream_init_circ_tbf(or_circuit_t *circ) +{ + token_bucket_ctr_init(&circ->stream_limiter, dos_stream_rate, + dos_stream_burst, + (uint32_t) monotime_coarse_absolute_sec()); +} + /* General API */ /* Take any appropriate actions for the given geoip entry that is about to get @@ -945,6 +1064,14 @@ dos_log_heartbeat(void) "[DoSRefuseSingleHopClientRendezvous disabled]"); } + if (dos_stream_enabled) { + smartlist_add_asprintf(elems, + "%" PRIu64 " stream rejected", + stream_num_rejected); + } else { + smartlist_add_asprintf(elems, "[DoSStreamCreationEnabled disabled]"); + } + /* HS DoS stats. */ smartlist_add_asprintf(elems, "%" PRIu64 " INTRODUCE2 rejected", diff --git a/src/core/or/dos.h b/src/core/or/dos.h index 4a2227f132..03606287d1 100644 --- a/src/core/or/dos.h +++ b/src/core/or/dos.h @@ -90,6 +90,7 @@ uint64_t dos_get_num_cc_rejected(void); uint64_t dos_get_num_conn_addr_rejected(void); uint64_t dos_get_num_conn_addr_connect_rejected(void); uint64_t dos_get_num_single_hop_refused(void); +uint64_t dos_get_num_stream_rejected(void); /* * Circuit creation DoS mitigation subsystemn interface. @@ -159,6 +160,37 @@ typedef enum dos_conn_defense_type_t { dos_conn_defense_type_t dos_conn_addr_get_defense_type(const tor_addr_t *addr); +/* + * Stream creation DoS mitigation subsystem interface. + */ + +/* DoSStreamCreationEnabled default. Disabled by deault. */ +#define DOS_STREAM_ENABLED_DEFAULT 0 +/* DoSStreamCreationDefenseType maps to the dos_stream_defense_type_t enum */ +#define DOS_STREAM_DEFENSE_TYPE_DEFAULT DOS_STREAM_DEFENSE_REFUSE_STREAM +/* DosStreamCreationRate is 100 per seconds. */ +#define DOS_STREAM_RATE_DEFAULT 100 +/* DosStreamCreationBurst default. */ +#define DOS_STREAM_BURST_DEFAULT 300 + +/* Type of defense that we can use for the stream creation DoS mitigation. */ +typedef enum dos_stream_defense_type_t { + /* No defense used. */ + DOS_STREAM_DEFENSE_NONE = 1, + /* Reject the stream */ + DOS_STREAM_DEFENSE_REFUSE_STREAM = 2, + /* Close the circuit */ + DOS_STREAM_DEFENSE_CLOSE_CIRCUIT = 3, + + /* Maximum value that can be used. Useful for the boundaries of the + * consensus parameter. */ + DOS_STREAM_DEFENSE_MAX = 3, +} dos_stream_defense_type_t; + +dos_stream_defense_type_t dos_stream_new_begin_or_resolve_cell( + or_circuit_t *circ); +void dos_stream_init_circ_tbf(or_circuit_t *circ); + #ifdef DOS_PRIVATE STATIC uint32_t get_param_conn_max_concurrent_count( @@ -176,6 +208,8 @@ MOCK_DECL(STATIC unsigned int, get_param_cc_enabled, (const networkstatus_t *ns)); MOCK_DECL(STATIC unsigned int, get_param_conn_enabled, (const networkstatus_t *ns)); +MOCK_DECL(STATIC unsigned int, get_param_stream_enabled, + (const networkstatus_t *ns)); #endif /* defined(DOS_PRIVATE) */ diff --git a/src/core/or/dos_options.inc b/src/core/or/dos_options.inc index 9baa7a35b8..4d15c33f3d 100644 --- a/src/core/or/dos_options.inc +++ b/src/core/or/dos_options.inc @@ -50,6 +50,19 @@ CONF_VAR(DoSConnectionConnectBurst, POSINT, 0, "0") /** Allowed rate of client connection allowed per address. */ CONF_VAR(DoSConnectionConnectRate, POSINT, 0, "0") +/** Autobool: Is the stream creation DoS mitigation subsystem enabled? */ +CONF_VAR(DoSStreamCreationEnabled, AUTOBOOL, 0, "auto") + +/** Stream rate used to refill the token bucket. */ +CONF_VAR(DoSStreamCreationRate, POSINT, 0, "0") + +/** Maximum allowed burst of stream. */ +CONF_VAR(DoSStreamCreationBurst, POSINT, 0, "0") + +/** When an circuit is detected as malicious, what defense should be used + * against it. See the dos_stream_defense_type_t enum. */ +CONF_VAR(DoSStreamCreationDefenseType, INT, 0, "0") + /** For how much time (in seconds) the connection connect rate defense is * applicable for a malicious address. A random time delta is added to the * defense time of an address which will be between 1 second and half of this diff --git a/src/core/or/or_circuit_st.h b/src/core/or/or_circuit_st.h index d5a7007928..28e357338a 100644 --- a/src/core/or/or_circuit_st.h +++ b/src/core/or/or_circuit_st.h @@ -102,6 +102,10 @@ struct or_circuit_t { * used if this is a service introduction circuit at the intro point * (purpose = CIRCUIT_PURPOSE_INTRO_POINT). */ token_bucket_ctr_t introduce2_bucket; + + /** RELAY_BEGIN and RELAY_RESOLVE cell bucket controlling how much can go on + * this circuit. Only used if this is the end of a circuit on an exit node.*/ + token_bucket_ctr_t stream_limiter; }; #endif /* !defined(OR_CIRCUIT_ST_H) */ diff --git a/src/core/or/policies.c b/src/core/or/policies.c index 1864b84d5e..4641632b60 100644 --- a/src/core/or/policies.c +++ b/src/core/or/policies.c @@ -1066,7 +1066,7 @@ socks_policy_permits_address(const tor_addr_t *addr) } /** Return 1 if <b>addr</b> is permitted to connect to our metrics port, - * based on <b>socks_policy</b>. Else return 0. + * based on <b>metrics_policy</b>. Else return 0. */ int metrics_policy_permits_address(const tor_addr_t *addr) diff --git a/src/core/or/relay.c b/src/core/or/relay.c index 6abe802355..0cda6e7bf7 100644 --- a/src/core/or/relay.c +++ b/src/core/or/relay.c @@ -2015,8 +2015,7 @@ handle_relay_cell_command(cell_t *cell, circuit_t *circ, circ->purpose); return 0; } - connection_exit_begin_resolve(cell, TO_OR_CIRCUIT(circ)); - return 0; + return connection_exit_begin_resolve(cell, TO_OR_CIRCUIT(circ)); case RELAY_COMMAND_RESOLVED: if (conn) { log_fn(LOG_PROTOCOL_WARN, domain, diff --git a/src/core/or/scheduler_kist.c b/src/core/or/scheduler_kist.c index 69804247c8..c4b15a9950 100644 --- a/src/core/or/scheduler_kist.c +++ b/src/core/or/scheduler_kist.c @@ -447,10 +447,16 @@ update_socket_written(socket_table_t *table, channel_t *chan, size_t bytes) * by only writing a channel's outbuf to the kernel if it has 8 cells or more * in it. * - * Note: The number 8 has been picked for no particular reasons except that it - * is 4096 bytes which is a common number for buffering. A TLS record can hold - * up to 16KiB thus using 8 cells means that a relay will at most send a TLS - * record of 4KiB or 1/4 of the maximum capacity of a TLS record. + * Note: The number 8 was picked so that, when using 512-byte cells, it + * would produce 4096 bytes: a common number for buffering. A TLS + * record can hold up to 16KiB; thus, using 8 512-byte cells means that + * a relay will at most send a TLS record of 4KiB or 1/4 of the maximum + * capacity of a TLS record. + * + * Of course, the above calculation became incorrect when we moved to + * 514-byte cells in order to accommodate a 4-byte circuit ID; we may + * want to consider profiling with '7' to see if it produces better + * results. (TODO) */ MOCK_IMPL(int, channel_should_write_to_kernel, (outbuf_table_t *table, channel_t *chan)) |