]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
When a stream at an exit relay is in state "resolving" or
authorRoger Dingledine <arma@torproject.org>
Sun, 14 Dec 2008 19:40:56 +0000 (19:40 +0000)
committerRoger Dingledine <arma@torproject.org>
Sun, 14 Dec 2008 19:40:56 +0000 (19:40 +0000)
"connecting" and it receives an "end" relay cell, the exit relay
would silently ignore the end cell and not close the stream. If
the client never closes the circuit, then the exit relay never
closes the TCP connection. Bug introduced in Tor 0.1.2.1-alpha;
reported by "wood".

svn:r17625

ChangeLog
src/or/relay.c

index e9625aff7f5955b972f3dc46e54db2e0fd252e93..f9660654948c470eb0f7cee9a62ca6bbe6c37a10 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,12 @@ Changes in version 0.2.1.9-alpha - 200?-??-??
     - Fix a logic error that would automatically reject all but the first
       configured DNS server.  Bugfix on 0.2.1.5-alpha.  Possible fix for part
       of bug 813/868.  Bug spotted by coderman.
+    - When a stream at an exit relay is in state "resolving" or
+      "connecting" and it receives an "end" relay cell, the exit relay
+      would silently ignore the end cell and not close the stream. If
+      the client never closes the circuit, then the exit relay never
+      closes the TCP connection. Bug introduced in Tor 0.1.2.1-alpha;
+      reported by "wood".
 
   o Minor features:
     - Give a better error message when an overzealous init script says,
index e5d6d73be0a441a17f151c53033517f674746024..0158f512267572141b8d9b96360022742133147d 100644 (file)
@@ -594,11 +594,12 @@ edge_reason_is_retriable(int reason)
          reason == END_STREAM_REASON_MISC;
 }
 
-/** Called when we receive an END cell on a stream that isn't open yet.
+/** Called when we receive an END cell on a stream that isn't open yet,
+ * from the client side.
  * Arguments are as for connection_edge_process_relay_cell().
  */
 static int
-connection_edge_process_end_not_open(
+connection_ap_process_end_not_open(
     relay_header_t *rh, cell_t *cell, origin_circuit_t *circ,
     edge_connection_t *conn, crypt_path_t *layer_hint)
 {
@@ -608,8 +609,7 @@ connection_edge_process_end_not_open(
   int control_reason = reason | END_STREAM_REASON_FLAG_REMOTE;
   (void) layer_hint; /* unused */
 
-  if (rh->length > 0 && edge_reason_is_retriable(reason) &&
-      conn->_base.type == CONN_TYPE_AP) {
+  if (rh->length > 0 && edge_reason_is_retriable(reason)) {
     log_info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.",
              safe_str(conn->socks_request->address),
              stream_end_reason_to_string(reason));
@@ -725,17 +725,10 @@ connection_edge_process_end_not_open(
   log_info(LD_APP,
            "Edge got end (%s) before we're connected. Marking for close.",
        stream_end_reason_to_string(rh->length > 0 ? reason : -1));
-  if (conn->_base.type == CONN_TYPE_AP) {
-    circuit_log_path(LOG_INFO,LD_APP,circ);
-    /* need to test because of detach_retriable*/
-    if (!conn->_base.marked_for_close)
-      connection_mark_unattached_ap(conn, control_reason);
-  } else {
-    /* we just got an 'end', don't need to send one */
-    conn->_base.edge_has_sent_end = 1;
-    conn->end_reason = control_reason;
-    connection_mark_for_close(TO_CONN(conn));
-  }
+  circuit_log_path(LOG_INFO,LD_APP,circ);
+  /* need to test because of detach_retriable*/
+  if (!conn->_base.marked_for_close)
+    connection_mark_unattached_ap(conn, control_reason);
   return 0;
 }
 
@@ -767,12 +760,18 @@ connection_edge_process_relay_cell_not_open(
     edge_connection_t *conn, crypt_path_t *layer_hint)
 {
   if (rh->command == RELAY_COMMAND_END) {
-    if (CIRCUIT_IS_ORIGIN(circ))
-      return connection_edge_process_end_not_open(rh, cell,
-                                                 TO_ORIGIN_CIRCUIT(circ), conn,
-                                                 layer_hint);
-    else
+    if (CIRCUIT_IS_ORIGIN(circ) && conn->_base.type == CONN_TYPE_AP) {
+      return connection_ap_process_end_not_open(rh, cell,
+                                                TO_ORIGIN_CIRCUIT(circ), conn,
+                                                layer_hint);
+    } else {
+      /* we just got an 'end', don't need to send one */
+      conn->_base.edge_has_sent_end = 1;
+      conn->end_reason = *(cell->payload+RELAY_HEADER_SIZE) |
+                         END_STREAM_REASON_FLAG_REMOTE;
+      connection_mark_for_close(TO_CONN(conn));
       return 0;
+    }
   }
 
   if (conn->_base.type == CONN_TYPE_AP &&