summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Perry <mikeperry-git@fscked.org>2009-12-29 04:17:12 +0100
committerMike Perry <mikeperry-git@fscked.org>2010-02-18 09:08:31 -0800
commitac68704f07c2b70321b72e3b8665cb6d12da7e6b (patch)
tree2c8d329bd53f299e710a16eee4bb5662a0dd6c16
parent8512e337734a1eb8746df8500ec0f1f8b1fdc5e8 (diff)
downloadtor-ac68704f07c2b70321b72e3b8665cb6d12da7e6b.tar.gz
tor-ac68704f07c2b70321b72e3b8665cb6d12da7e6b.zip
Allow "EXTENDCIRCUIT 0" to omit a path.
-rw-r--r--doc/spec/control-spec.txt19
-rw-r--r--src/or/control.c53
2 files changed, 54 insertions, 18 deletions
diff --git a/doc/spec/control-spec.txt b/doc/spec/control-spec.txt
index 4057ffa741..7d3312a5a8 100644
--- a/doc/spec/control-spec.txt
+++ b/doc/spec/control-spec.txt
@@ -606,15 +606,20 @@
3.10. EXTENDCIRCUIT
Sent from the client to the server. The format is:
- "EXTENDCIRCUIT" SP CircuitID SP
- ServerSpec *("," ServerSpec)
- [SP "purpose=" Purpose] CRLF
+ "EXTENDCIRCUIT" SP CircuitID
+ [SP ServerSpec *("," ServerSpec)
+ SP "purpose=" Purpose] CRLF
This request takes one of two forms: either the CircuitID is zero, in
- which case it is a request for the server to build a new circuit according
- to the specified path, or the CircuitID is nonzero, in which case it is a
- request for the server to extend an existing circuit with that ID according
- to the specified path.
+ which case it is a request for the server to build a new circuit,
+ or the CircuitID is nonzero, in which case it is a request for the
+ server to extend an existing circuit with that ID according to the
+ specified path.
+
+ If the CircuitID is 0, the controller has the option of providing
+ a path for Tor to use to build the circuit. If it does not provide
+ a path, Tor will select one automatically from high capacity nodes
+ according to path-spec.txt.
If CircuitID is 0 and "purpose=" is specified, then the circuit's
purpose is set. Two choices are recognized: "general" and
diff --git a/src/or/control.c b/src/or/control.c
index c34848d454..a7e60d55f0 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -2055,27 +2055,58 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
router_nicknames = smartlist_create();
- args = getargs_helper("EXTENDCIRCUIT", conn, body, 2, -1);
+ args = getargs_helper("EXTENDCIRCUIT", conn, body, 1, -1);
if (!args)
goto done;
zero_circ = !strcmp("0", (char*)smartlist_get(args,0));
+
+ if (zero_circ) {
+ char *purp = NULL;
+ if (smartlist_len(args) == 2) {
+ // "EXTENDCIRCUIT 0 PURPOSE=foo"
+ purp = smartlist_get(args,1);
+ } else if (smartlist_len(args) == 3) {
+ // "EXTENDCIRCUIT 0 router1,router2 PURPOSE=foo"
+ purp = smartlist_get(args,2);
+ }
+
+ if (purp && strcmpstart(purp, "purpose=") != 0)
+ purp = NULL;
+
+ if (purp) {
+ intended_purpose = circuit_purpose_from_string(purp);
+ if (intended_purpose == CIRCUIT_PURPOSE_UNKNOWN) {
+ connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp);
+ SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
+ smartlist_free(args);
+ }
+ }
+
+ if ((smartlist_len(args) == 1) || (purp && (smartlist_len(args) == 2))) {
+ // "EXTENDCIRCUIT 0" || EXTENDCIRCUIT 0 PURPOSE=foo"
+ circ = circuit_launch_by_router(intended_purpose, NULL,
+ CIRCLAUNCH_NEED_CAPACITY);
+ if (!circ) {
+ connection_write_str_to_buf("551 Couldn't start circuit\r\n", conn);
+ } else {
+ connection_printf_to_buf(conn, "250 EXTENDED %lu\r\n",
+ (unsigned long)circ->global_identifier);
+ }
+ goto done;
+ }
+ // "EXTENDCIRCUIT 0 router1,router2" ||
+ // "EXTENDCIRCUIT 0 router1,router2 PURPOSE=foo"
+ }
+
if (!zero_circ && !(circ = get_circ(smartlist_get(args,0)))) {
connection_printf_to_buf(conn, "552 Unknown circuit \"%s\"\r\n",
(char*)smartlist_get(args, 0));
+ goto done;
}
+
smartlist_split_string(router_nicknames, smartlist_get(args,1), ",", 0, 0);
- if (zero_circ && smartlist_len(args)>2) {
- char *purp = smartlist_get(args,2);
- intended_purpose = circuit_purpose_from_string(purp);
- if (intended_purpose == CIRCUIT_PURPOSE_UNKNOWN) {
- connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n", purp);
- SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
- smartlist_free(args);
- goto done;
- }
- }
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
smartlist_free(args);
if (!zero_circ && !circ) {