Filename: xxx-separate-streams-by-port.txt
Title: Separate streams across circuits by destination port
Version: $Revision$
Last-Modified: $Date$
Author: Robert Hogan
Created: 21-Oct-2008
Status: Draft

Here's a patch Robert Hogan wrote to use only one destination port per
circuit. It's based on a wishlist item Roger wrote, to never send AIM
usernames over the same circuit that we're hoping to browse anonymously
through. The remaining open question is: how many extra circuits does this
cause an ordinary user to create? My guess is not very many, but I'm wary
of putting this in until we have some better estimate. On the other hand,
not putting it in means that we have a known security flaw. Hm.

Index: src/or/or.h
===================================================================
--- src/or/or.h (revision 17143)
+++ src/or/or.h (working copy)
@@ -1874,6 +1874,7 @@

   uint8_t state; /**< Current status of this circuit. */
   uint8_t purpose; /**< Why are we creating this circuit? */
+  uint16_t service; /**< Port conn must have to use this circuit. */

   /** How many relay data cells can we package (read from edge streams)
    * on this circuit before we receive a circuit-level sendme cell asking
Index: src/or/circuituse.c
===================================================================
--- src/or/circuituse.c (revision 17143)
+++ src/or/circuituse.c (working copy)
@@ -62,10 +62,16 @@
       return 0;
   }

-  if (purpose == CIRCUIT_PURPOSE_C_GENERAL)
+  if (purpose == CIRCUIT_PURPOSE_C_GENERAL) {
     if (circ->timestamp_dirty &&
        circ->timestamp_dirty+get_options()->MaxCircuitDirtiness <= now)
       return 0;
+    /* If the circuit is dirty and used for services on another port,
+      then it is not suitable. */
+    if (circ->service && conn->socks_request->port &&
+       (circ->service != conn->socks_request->port))
+      return 0;
+  }

   /* decide if this circ is suitable for this conn */

@@ -1351,7 +1357,9 @@
     if (connection_ap_handshake_send_resolve(conn) < 0)
       return -1;
   }
-
+  if (conn->socks_request->port
+     && (TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_C_GENERAL))
+    TO_CIRCUIT(circ)->service = conn->socks_request->port;
   return 1;
 }

