aboutsummaryrefslogtreecommitdiff
path: root/src/or/circuituse.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2011-07-07 14:54:54 -0400
committerNick Mathewson <nickm@torproject.org>2011-07-19 01:58:45 -0400
commitaef30547dc4aa77fc79517a6dcad7712b59af371 (patch)
treed73ae474b559433a0ff40b0a8930b034478e7df2 /src/or/circuituse.c
parent20c0581a7935369fecb6c62b7cf5c7c244cdb533 (diff)
downloadtor-aef30547dc4aa77fc79517a6dcad7712b59af371.tar
tor-aef30547dc4aa77fc79517a6dcad7712b59af371.tar.gz
Add an option to limit the number of non-open client circuits.
This is mainly meant as a way to keep clients from accidentally DOSing themselves by (e.g.) enabling IsolateDestAddr or IsolateDestPort on a port that they use for HTTP.
Diffstat (limited to 'src/or/circuituse.c')
-rw-r--r--src/or/circuituse.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 93098e527..dcb6bfa50 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -288,6 +288,27 @@ circuit_get_best(const edge_connection_t *conn,
return best;
}
+/** Return the number of not-yet-open general-purpose origin circuits. */
+static int
+count_pending_general_client_circuits(void)
+{
+ const circuit_t *circ;
+
+ int count = 0;
+
+ for (circ = global_circuitlist; circ; circ = circ->next) {
+ if (circ->marked_for_close ||
+ circ->state == CIRCUIT_STATE_OPEN ||
+ circ->purpose != CIRCUIT_PURPOSE_C_GENERAL ||
+ !CIRCUIT_IS_ORIGIN(circ))
+ continue;
+
+ ++count;
+ }
+
+ return count;
+}
+
#if 0
/** Check whether, according to the policies in <b>options</b>, the
* circuit <b>circ</b> makes sense. */
@@ -1347,6 +1368,20 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
if (!circ) {
extend_info_t *extend_info=NULL;
uint8_t new_circ_purpose;
+ const int n_pending = count_pending_general_client_circuits();
+
+ if (n_pending >= options->MaxClientCircuitsPending) {
+ static ratelim_t delay_limit = RATELIM_INIT(10*60);
+ char *m;
+ if ((m = rate_limit_log(&delay_limit, approx_time()))) {
+ log_notice(LD_APP, "We'd like to launch a circuit to handle a "
+ "connection, but we already have %d general-purpose client "
+ "circuits pending. Waiting until some finish.",
+ n_pending);
+ tor_free(m);
+ }
+ return 0;
+ }
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
/* need to pick an intro point */