commit 712bf069781d7a6336501aab628f62ada4f4c4d7 Author: Yawning Angel yawning@schwanenlied.me Date: Wed May 20 17:41:27 2015 +0000
Add support for 'HiddenServiceMaxStream' to 'ADD_ONION'.
Done as a separate commit to ease backporting the tunables to 0.2.6.x. --- src/or/control.c | 21 ++++++++++++++++++++- src/or/rendservice.c | 26 +++++++++++++++++++++++++- src/or/rendservice.h | 2 ++ 3 files changed, 47 insertions(+), 2 deletions(-)
diff --git a/src/or/control.c b/src/or/control.c index 4eeb897..746dfff 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -3566,9 +3566,12 @@ handle_control_add_onion(control_connection_t *conn, smartlist_t *port_cfgs = smartlist_new(); int discard_pk = 0; int detach = 0; + int max_streams = 0; + int max_streams_close_circuit = 0; for (size_t i = 1; i < arg_len; i++) { static const char *port_prefix = "Port="; static const char *flags_prefix = "Flags="; + static const char *max_s_prefix = "MaxStreams=";
const char *arg = smartlist_get(args, i); if (!strcasecmpstart(arg, port_prefix)) { @@ -3582,15 +3585,27 @@ handle_control_add_onion(control_connection_t *conn, goto out; } smartlist_add(port_cfgs, cfg); + } else if (!strcasecmpstart(arg, max_s_prefix)) { + /* "MaxStreams=[0..65535]". */ + const char *max_s_str = arg + strlen(max_s_prefix); + int ok = 0; + max_streams = (int)tor_parse_long(max_s_str, 10, 0, 65535, &ok, NULL); + if (!ok) { + connection_printf_to_buf(conn, "512 Invalid MaxStreams\r\n"); + goto out; + } } else if (!strcasecmpstart(arg, flags_prefix)) { /* "Flags=Flag[,Flag]", where Flag can be: * * 'DiscardPK' - If tor generates the keypair, do not include it in * the response. * * 'Detach' - Do not tie this onion service to any particular control * connection. + * * 'MaxStreamsCloseCircuit' - Close the circuit if MaxStreams is + * exceeded. */ static const char *discard_flag = "DiscardPK"; static const char *detach_flag = "Detach"; + static const char *max_s_close_flag = "MaxStreamsCloseCircuit";
smartlist_t *flags = smartlist_new(); int bad = 0; @@ -3607,6 +3622,8 @@ handle_control_add_onion(control_connection_t *conn, discard_pk = 1; } else if (!strcasecmp(flag, detach_flag)) { detach = 1; + } else if (!strcasecmp(flag, max_s_close_flag)) { + max_streams_close_circuit = 1; } else { connection_printf_to_buf(conn, "512 Invalid 'Flags' argument: %s\r\n", @@ -3652,7 +3669,9 @@ handle_control_add_onion(control_connection_t *conn, * regardless of success/failure. */ char *service_id = NULL; - int ret = rend_service_add_ephemeral(pk, port_cfgs, &service_id); + int ret = rend_service_add_ephemeral(pk, port_cfgs, max_streams, + max_streams_close_circuit, + &service_id); port_cfgs = NULL; /* port_cfgs is now owned by the rendservice code. */ switch (ret) { case RSAE_OKAY: diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 5d2225e..0329d70 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -266,6 +266,23 @@ rend_add_service(rend_service_t *service)
service->intro_nodes = smartlist_new();
+ if (service->max_streams_per_circuit < 0) { + log_warn(LD_CONFIG, "Hidden service (%s) configured with negative max " + "streams per circuit; ignoring.", + rend_service_escaped_dir(service)); + rend_service_free(service); + return -1; + } + + if (service->max_streams_close_circuit < 0 || + service->max_streams_close_circuit > 1) { + log_warn(LD_CONFIG, "Hidden service (%s) configured with invalid " + "max streams handling; ignoring.", + rend_service_escaped_dir(service)); + rend_service_free(service); + return -1; + } + if (service->auth_type != REND_NO_AUTH && smartlist_len(service->clients) == 0) { log_warn(LD_CONFIG, "Hidden service (%s) with client authorization but no " @@ -792,7 +809,10 @@ rend_config_services(const or_options_t *options, int validate_only) return 0; }
-/** Add the ephemeral service <b>pk</b>/<b>ports</b> if possible. +/** Add the ephemeral service <b>pk</b>/<b>ports</b> if possible, with + * <b>max_streams_per_circuit</b> streams allowed per rendezvous circuit, + * and circuit closure on max streams being exceeded set by + * <b>max_streams_close_circuit</b>. * * Regardless of sucess/failure, callers should not touch pk/ports after * calling this routine, and may assume that correct cleanup has been done @@ -803,6 +823,8 @@ rend_config_services(const or_options_t *options, int validate_only) rend_service_add_ephemeral_status_t rend_service_add_ephemeral(crypto_pk_t *pk, smartlist_t *ports, + int max_streams_per_circuit, + int max_streams_close_circuit, char **service_id_out) { *service_id_out = NULL; @@ -816,6 +838,8 @@ rend_service_add_ephemeral(crypto_pk_t *pk, s->ports = ports; s->intro_period_started = time(NULL); s->n_intro_points_wanted = NUM_INTRO_POINTS_DEFAULT; + s->max_streams_per_circuit = max_streams_per_circuit; + s->max_streams_close_circuit = max_streams_close_circuit; if (rend_service_derive_key_digests(s) < 0) { rend_service_free(s); return RSAE_BADPRIVKEY; diff --git a/src/or/rendservice.h b/src/or/rendservice.h index ec783d5..b540d2c 100644 --- a/src/or/rendservice.h +++ b/src/or/rendservice.h @@ -117,6 +117,8 @@ typedef enum { } rend_service_add_ephemeral_status_t; rend_service_add_ephemeral_status_t rend_service_add_ephemeral(crypto_pk_t *pk, smartlist_t *ports, + int max_streams_per_circuit, + int max_streams_close_circuit, char **service_id_out); int rend_service_del_ephemeral(const char *service_id);
tor-commits@lists.torproject.org