Browse Source

Add a new circuit purpose 'controller' to let the controller
ask for a circuit that Tor won't try to use.

Extend the EXTENDCIRCUIT controller command to let you specify
the purpose if you're starting a new circuit.

Add a new SETCIRCUITPURPOSE controller command to let you
change a circuit's purpose after it's been created.


svn:r6075

Roger Dingledine 19 years ago
parent
commit
329af979e0
3 changed files with 99 additions and 14 deletions
  1. 25 12
      doc/control-spec.txt
  2. 71 1
      src/or/control.c
  3. 3 1
      src/or/or.h

+ 25 - 12
doc/control-spec.txt

@@ -405,19 +405,32 @@ $Id$
 3.10. EXTENDCIRCUIT
 3.10. EXTENDCIRCUIT
 
 
   Sent from the client to the server.  The format is:
   Sent from the client to the server.  The format is:
-      "EXTENDCIRCUIT" SP CircuitID SP ServerID *("," ServerID) CRLF
+      "EXTENDCIRCUIT" SP CircuitID SP
+                      ServerID *("," ServerID) SP
+                      ("purpose=" Purpose) CRLF
 
 
-  This request takes one of two forms: either the Circuit ID is zero, in
+  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
   which case it is a request for the server to build a new circuit according
-  to the specified path, or the Circuit ID is nonzero, in which case it is a
+  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
   request for the server to extend an existing circuit with that ID according
   to the specified path.
   to the specified path.
 
 
-  If the request is successful, the server sends a reply containing a message
-  body consisting of the Circuit ID of the (maybe newly created) circuit.
-  The syntax is "250" SP "EXTENDED" SP CircuitID CRLF.
+  If CircuitID is 0 and "purpose=" is specified, then the circuit's
+  purpose is set. Two choices are recognized: "general" and
+  "controller". If not specified, circuits are created as "general".
 
 
-3.11. ATTACHSTREAM
+  If the request is successful, the server sends a reply containing a
+  message body consisting of the CircuitID of the (maybe newly created)
+  circuit. The syntax is "250" SP "EXTENDED" SP CircuitID CRLF.
+
+3.11. SETCIRCUITPURPOSE
+
+  Sent from the client to the server.  The format is:
+      "SETCIRCUITPURPOSE" SP CircuitID SP Purpose CRLF
+
+  This changes the circuit's purpose. See EXTENDCIRCUIT above for details.
+
+3.12. ATTACHSTREAM
 
 
   Sent from the client to the server.  The syntax is:
   Sent from the client to the server.  The syntax is:
      "ATTACHSTREAM" SP StreamID SP CircuitID CRLF
      "ATTACHSTREAM" SP StreamID SP CircuitID CRLF
@@ -446,7 +459,7 @@ $Id$
   via TC when "__LeaveStreamsUnattached" is false may cause a race between
   via TC when "__LeaveStreamsUnattached" is false may cause a race between
   Tor and the controller, as both attempt to attach streams to circuits.}
   Tor and the controller, as both attempt to attach streams to circuits.}
 
 
-3.12. POSTDESCRIPTOR
+3.13. POSTDESCRIPTOR
 
 
   Sent from the client to the server. The syntax is:
   Sent from the client to the server. The syntax is:
     "+POSTDESCRIPTOR" CRLF Descriptor CRLF "." CRLF
     "+POSTDESCRIPTOR" CRLF Descriptor CRLF "." CRLF
@@ -462,7 +475,7 @@ $Id$
   why the server was not added.  If the descriptor is added, Tor replies with
   why the server was not added.  If the descriptor is added, Tor replies with
   "250 OK".
   "250 OK".
 
 
-3.13. REDIRECTSTREAM
+3.14. REDIRECTSTREAM
 
 
   Sent from the client to the server. The syntax is:
   Sent from the client to the server. The syntax is:
     "REDIRECTSTREAM" SP StreamID SP Address (SP Port) CRLF
     "REDIRECTSTREAM" SP StreamID SP Address (SP Port) CRLF
@@ -477,7 +490,7 @@ $Id$
 
 
   Tor replies with "250 OK" on success.
   Tor replies with "250 OK" on success.
 
 
-3.14. CLOSESTREAM
+3.15. CLOSESTREAM
 
 
   Sent from the client to the server.  The syntax is:
   Sent from the client to the server.  The syntax is:
 
 
@@ -491,7 +504,7 @@ $Id$
   Tor replies with "250 OK" on success, or a 512 if there aren't enough
   Tor replies with "250 OK" on success, or a 512 if there aren't enough
   arguments, or a 552 if it doesn't recognize the StreamID or reason.
   arguments, or a 552 if it doesn't recognize the StreamID or reason.
 
 
-3.15. CLOSECIRCUIT
+3.16. CLOSECIRCUIT
 
 
    The syntax is:
    The syntax is:
      CLOSECIRCUIT SP CircuitID *(SP Flag) CRLF
      CLOSECIRCUIT SP CircuitID *(SP Flag) CRLF
@@ -506,7 +519,7 @@ $Id$
   Tor replies with "250 OK" on success, or a 512 if there aren't enough
   Tor replies with "250 OK" on success, or a 512 if there aren't enough
   arguments, or a 552 if it doesn't recognize the CircuitID.
   arguments, or a 552 if it doesn't recognize the CircuitID.
 
 
-3.16. QUIT
+3.17. QUIT
 
 
   Tells the server to hang up on this controller connection. This command
   Tells the server to hang up on this controller connection. This command
   can be used before authenticating.
   can be used before authenticating.

+ 71 - 1
src/or/control.c

@@ -169,6 +169,8 @@ static int handle_control_getinfo(connection_t *conn, uint32_t len,
                                   const char *body);
                                   const char *body);
 static int handle_control_extendcircuit(connection_t *conn, uint32_t len,
 static int handle_control_extendcircuit(connection_t *conn, uint32_t len,
                                         const char *body);
                                         const char *body);
+static int handle_control_setcircuitpurpose(connection_t *conn, uint32_t len,
+                                        const char *body);
 static int handle_control_attachstream(connection_t *conn, uint32_t len,
 static int handle_control_attachstream(connection_t *conn, uint32_t len,
                                         const char *body);
                                         const char *body);
 static int handle_control_postdescriptor(connection_t *conn, uint32_t len,
 static int handle_control_postdescriptor(connection_t *conn, uint32_t len,
@@ -1541,6 +1543,25 @@ handle_control_getinfo(connection_t *conn, uint32_t len, const char *body)
   return 0;
   return 0;
 }
 }
 
 
+/** If <b>string</b> contains a recognized circuit purpose,
+ * possibly prefaced with the string "purpose=", then assign it
+ * and return 0. Otherwise return -1. */
+static int
+get_purpose(char *string, uint8_t *purpose)
+{
+  if (!strcmpstart(string, "purpose="))
+    string += strlen("purpose=");
+
+  if (!strcmp(string, "general"))
+    *purpose = CIRCUIT_PURPOSE_C_GENERAL;
+  else if (!strcmp(string, "controller"))
+    *purpose = CIRCUIT_PURPOSE_CONTROLLER;
+  else { /* not a recognized purpose */
+    return -1;
+  }
+  return 0;
+}
+
 /** Called when we get an EXTENDCIRCUIT message.  Try to extend the listed
 /** Called when we get an EXTENDCIRCUIT message.  Try to extend the listed
  * circuit, and report success or failure. */
  * circuit, and report success or failure. */
 static int
 static int
@@ -1552,6 +1573,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
   circuit_t *circ = NULL;
   circuit_t *circ = NULL;
   int zero_circ, v0;
   int zero_circ, v0;
   char reply[4];
   char reply[4];
+  uint8_t intended_purpose = CIRCUIT_PURPOSE_C_GENERAL;
 
 
   v0 = STATE_IS_V0(conn->state);
   v0 = STATE_IS_V0(conn->state);
   router_nicknames = smartlist_create();
   router_nicknames = smartlist_create();
@@ -1600,6 +1622,13 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
     if (!zero_circ && !circ) {
     if (!zero_circ && !circ) {
       goto done;
       goto done;
     }
     }
+    if (zero_circ && smartlist_len(args)>2) {
+      if (get_purpose(smartlist_get(args,2), &intended_purpose) < 0) {
+        connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n",
+                                 (char *)smartlist_get(args,2));
+        goto done;
+      }
+    }
   }
   }
 
 
   routers = smartlist_create();
   routers = smartlist_create();
@@ -1625,7 +1654,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
 
 
   if (zero_circ) {
   if (zero_circ) {
     /* start a new circuit */
     /* start a new circuit */
-    circ = circuit_init(CIRCUIT_PURPOSE_C_GENERAL, 0, 0, 0);
+    circ = circuit_init(intended_purpose, 0, 0, 0);
   }
   }
 
 
   /* now circ refers to something that is ready to be extended */
   /* now circ refers to something that is ready to be extended */
@@ -1677,6 +1706,44 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len,
   return 0;
   return 0;
 }
 }
 
 
+/** Called when we get a SETCIRCUITPURPOSE message. If we can find
+ * the circuit and it's a valid purpose, change it. */
+static int
+handle_control_setcircuitpurpose(connection_t *conn, uint32_t len,
+                                 const char *body)
+{
+  circuit_t *circ;
+  uint8_t new_purpose;
+  smartlist_t *args = smartlist_create();
+  smartlist_split_string(args, body, " ",
+                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+  if (smartlist_len(args)<2) {
+    connection_printf_to_buf(conn,
+                             "512 Missing argument to SETCIRCUITPURPOSE\r\n");
+    goto done;
+  }
+
+  if (!(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;
+  }
+
+  if (get_purpose(smartlist_get(args,1), &new_purpose) < 0) {
+    connection_printf_to_buf(conn, "552 Unknown purpose \"%s\"\r\n",
+                             (char *)smartlist_get(args,1));
+    goto done;
+  }
+
+  circ->purpose = new_purpose;
+  connection_write_str_to_buf("250 OK\r\n", conn);
+
+done:
+  SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
+  smartlist_free(args);
+  return 0;
+}
+
 /** Called when we get an ATTACHSTREAM message.  Try to attach the requested
 /** Called when we get an ATTACHSTREAM message.  Try to attach the requested
  * stream, and report success or failure. */
  * stream, and report success or failure. */
 static int
 static int
@@ -2187,6 +2254,9 @@ connection_control_process_inbuf_v1(connection_t *conn)
   } else if (!strcasecmp(conn->incoming_cmd, "EXTENDCIRCUIT")) {
   } else if (!strcasecmp(conn->incoming_cmd, "EXTENDCIRCUIT")) {
     if (handle_control_extendcircuit(conn, data_len, args))
     if (handle_control_extendcircuit(conn, data_len, args))
       return -1;
       return -1;
+  } else if (!strcasecmp(conn->incoming_cmd, "SETCIRCUITPURPOSE")) {
+    if (handle_control_setcircuitpurpose(conn, data_len, args))
+      return -1;
   } else if (!strcasecmp(conn->incoming_cmd, "ATTACHSTREAM")) {
   } else if (!strcasecmp(conn->incoming_cmd, "ATTACHSTREAM")) {
     if (handle_control_attachstream(conn, data_len, args))
     if (handle_control_attachstream(conn, data_len, args))
       return -1;
       return -1;

+ 3 - 1
src/or/or.h

@@ -423,7 +423,9 @@ typedef enum {
 #define CIRCUIT_PURPOSE_S_REND_JOINED 16
 #define CIRCUIT_PURPOSE_S_REND_JOINED 16
 /** A testing circuit; not meant to be used for actual traffic. */
 /** A testing circuit; not meant to be used for actual traffic. */
 #define CIRCUIT_PURPOSE_TESTING 17
 #define CIRCUIT_PURPOSE_TESTING 17
-#define _CIRCUIT_PURPOSE_MAX 17
+/** A controller made this circuit and Tor should not use it. */
+#define CIRCUIT_PURPOSE_CONTROLLER 18
+#define _CIRCUIT_PURPOSE_MAX 18
 
 
 /** True iff the circuit purpose <b>p</b> is for a circuit that
 /** True iff the circuit purpose <b>p</b> is for a circuit that
  * originated at this node. */
  * originated at this node. */