[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] stop most cases of hanging up on a socks connection without...



Update of /home2/or/cvsroot/tor/src/or
In directory moria.mit.edu:/home2/arma/work/onion/cvs/tor/src/or

Modified Files:
	circuitbuild.c connection.c connection_edge.c control.c 
	hibernate.c main.c or.h relay.c rendclient.c 
Log Message:
stop most cases of hanging up on a socks connection without sending
the socks reject. audit for remaining ones. also make things more
uniform so we always remember to hold-open-until-flushed, etc.


Index: circuitbuild.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/circuitbuild.c,v
retrieving revision 1.95
retrieving revision 1.96
diff -u -d -r1.95 -r1.96
--- circuitbuild.c	26 Mar 2005 05:54:50 -0000	1.95
+++ circuitbuild.c	27 Mar 2005 04:55:12 -0000	1.96
@@ -722,8 +722,7 @@
         /* no need to send 'end' relay cells,
          * because the other side's already dead
          */
-        stream->has_sent_end = 1;
-        connection_mark_for_close(stream);
+        connection_close_unattached_ap(stream, END_STREAM_REASON_DESTROY);
       }
     }
 

Index: connection.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/connection.c,v
retrieving revision 1.348
retrieving revision 1.349
diff -u -d -r1.348 -r1.349
--- connection.c	26 Mar 2005 01:43:39 -0000	1.348
+++ connection.c	27 Mar 2005 04:55:12 -0000	1.349
@@ -281,7 +281,8 @@
       if (conn->socks_request->has_finished == 0) {
         /* since conn gets removed right after this function finishes,
          * there's no point trying to send back a reply at this point. */
-        log_fn(LOG_WARN,"Bug: Closing stream without sending back a socks reply.");
+        log_fn(LOG_WARN,"Bug: Closing stream (marked at %s:%d) without sending back a socks reply.",
+               conn->marked_for_close_file, conn->marked_for_close);
       } else {
         control_event_stream_status(conn, STREAM_EVENT_CLOSED);
       }

Index: connection_edge.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/connection_edge.c,v
retrieving revision 1.307
retrieving revision 1.308
diff -u -d -r1.307 -r1.308
--- connection_edge.c	26 Mar 2005 06:27:51 -0000	1.307
+++ connection_edge.c	27 Mar 2005 04:55:12 -0000	1.308
@@ -20,6 +20,26 @@
 static int connection_ap_handshake_process_socks(connection_t *conn);
 static int address_is_in_virtual_range(const char *addr);
 
+/** An AP stream has failed/finished. If it hasn't already sent back
+ * a socks reply, send one now (based on endreason). Also set
+ * has_sent_end to 1, and mark the conn.
+ */
+void
+connection_close_unattached_ap(connection_t *conn, int endreason) {
+  tor_assert(conn->type == CONN_TYPE_AP);
+  conn->has_sent_end = 1; /* no circ yet */
+  if (!conn->socks_request->has_finished) {
+    socks5_reply_status_t socksreason =
+      connection_edge_end_reason_socks5_response(endreason);
+    if (conn->socks_request->command == SOCKS_COMMAND_CONNECT)
+      connection_ap_handshake_socks_reply(conn, NULL, 0, socksreason);
+    else
+      connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL);
+  }
+  connection_mark_for_close(conn);
+  conn->hold_open_until_flushed = 1;
+}
+
 /** There was an EOF. Send an end and mark the connection for close.
  */
 int connection_edge_reached_eof(connection_t *conn) {
@@ -45,9 +65,9 @@
     /* only mark it if not already marked. it's possible to
      * get the 'end' right around when the client hangs up on us. */
     connection_edge_end(conn, END_STREAM_REASON_DONE, conn->cpath_layer);
+    if (conn->socks_request) /* eof, so don't send a socks reply back */
+      conn->socks_request->has_finished = 1;
     connection_mark_for_close(conn);
-//    conn->hold_open_until_flushed = 1; /* just because we shouldn't read
-//                                          doesn't mean we shouldn't write */
   }
   return 0;
 #endif
@@ -70,9 +90,7 @@
   switch (conn->state) {
     case AP_CONN_STATE_SOCKS_WAIT:
       if (connection_ap_handshake_process_socks(conn) < 0) {
-        conn->has_sent_end = 1; /* no circ yet */
-        connection_mark_for_close(conn);
-        conn->hold_open_until_flushed = 1; /* redundant but shouldn't hurt */
+        connection_close_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
         return -1;
       }
       return 0;
@@ -113,9 +131,13 @@
     return 0; /* already marked; probably got an 'end' */
   log_fn(LOG_INFO,"CircID %d: At an edge. Marking connection for close.",
          circ_id);
-  conn->has_sent_end = 1; /* we're closing the circuit, nothing to send to */
-  connection_mark_for_close(conn);
-  conn->hold_open_until_flushed = 1;
+  if (conn->type == CONN_TYPE_AP) {
+    connection_close_unattached_ap(conn, END_STREAM_REASON_DESTROY);
+  } else {
+    conn->has_sent_end = 1; /* we're closing the circuit, nothing to send to */
+    connection_mark_for_close(conn);
+    conn->hold_open_until_flushed = 1;
+  }
   conn->cpath_layer = NULL;
   return 0;
 }
@@ -280,7 +302,7 @@
     if (conn->state == AP_CONN_STATE_CONTROLLER_WAIT) {
       if (now - conn->timestamp_lastread >= 120) {
         log_fn(LOG_NOTICE, "Closing unattached stream.");
-        connection_mark_for_close(conn);
+        connection_close_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
       }
       continue;
     }
@@ -294,8 +316,7 @@
     if (!circ) { /* it's vanished? */
       log_fn(LOG_INFO,"Conn is waiting (address %s), but lost its circ.",
              conn->socks_request->address);
-      conn->has_sent_end = 1; /* No circuit to receive end cell. */
-      connection_mark_for_close(conn);
+      connection_close_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
       continue;
     }
     if (circ->purpose == CIRCUIT_PURPOSE_C_REND_JOINED) {
@@ -303,7 +324,7 @@
         log_fn(LOG_NOTICE,"Rend stream is %d seconds late. Giving up on address '%s'.",
                (int)(now - conn->timestamp_lastread), conn->socks_request->address);
         connection_edge_end(conn, END_STREAM_REASON_TIMEOUT, conn->cpath_layer);
-        connection_mark_for_close(conn);
+        connection_close_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
       }
       continue;
     }
@@ -324,10 +345,7 @@
     conn->timestamp_lastread += 15;
     /* move it back into 'pending' state, and try to attach. */
     if (connection_ap_detach_retriable(conn, circ)<0) {
-      /* it will never work */
-      /* Don't need to send end -- we're not connected */
-      conn->has_sent_end = 1;
-      connection_mark_for_close(conn);
+      connection_close_unattached_ap(conn, END_STREAM_REASON_MISC);
     }
   } /* end for */
 }
@@ -350,10 +368,7 @@
         conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
       continue;
     if (connection_ap_handshake_attach_circuit(conn) < 0) {
-      /* -1 means it will never work */
-      /* Don't send end; there is no 'other side' yet */
-      conn->has_sent_end = 1;
-      connection_mark_for_close(conn);
+      connection_close_unattached_ap(conn, END_STREAM_REASON_MISC);
     }
   }
 }
@@ -911,9 +926,7 @@
         answer = in.s_addr;
         connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV4,4,
                                                (char*)&answer);
-        conn->has_sent_end = 1;
-        connection_mark_for_close(conn);
-        conn->hold_open_until_flushed = 1;
+        connection_close_unattached_ap(conn, END_STREAM_REASON_DONE);
         return 0;
       }
       rep_hist_note_used_resolve(time(NULL)); /* help predict this next time */
@@ -1016,9 +1029,7 @@
 
   ap_conn->stream_id = get_unique_stream_id_by_circ(circ);
   if (ap_conn->stream_id==0) {
-    /* Don't send end: there is no 'other side' yet */
-    ap_conn->has_sent_end = 1;
-    connection_mark_for_close(ap_conn);
+    connection_close_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
     circuit_mark_for_close(circ);
     return -1;
   }
@@ -1038,7 +1049,8 @@
   ap_conn->package_window = STREAMWINDOW_START;
   ap_conn->deliver_window = STREAMWINDOW_START;
   ap_conn->state = AP_CONN_STATE_CONNECT_WAIT;
-  log_fn(LOG_INFO,"Address/port sent, ap socket %d, n_circ_id %d",ap_conn->s,circ->n_circ_id);
+  log_fn(LOG_INFO,"Address/port sent, ap socket %d, n_circ_id %d",
+         ap_conn->s, circ->n_circ_id);
   control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT);
   return 0;
 }
@@ -1061,9 +1073,7 @@
 
   ap_conn->stream_id = get_unique_stream_id_by_circ(circ);
   if (ap_conn->stream_id==0) {
-    /* Don't send end: there is no 'other side' yet */
-    ap_conn->has_sent_end = 1;
-    connection_mark_for_close(ap_conn);
+    connection_close_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
     circuit_mark_for_close(circ);
     return -1;
   }
@@ -1079,7 +1089,8 @@
     return -1; /* circuit is closed, don't continue */
 
   ap_conn->state = AP_CONN_STATE_RESOLVE_WAIT;
-  log_fn(LOG_INFO,"Address sent for resolve, ap socket %d, n_circ_id %d",ap_conn->s,circ->n_circ_id);
+  log_fn(LOG_INFO,"Address sent for resolve, ap socket %d, n_circ_id %d",
+         ap_conn->s, circ->n_circ_id);
   control_event_stream_status(ap_conn, STREAM_EVENT_SENT_RESOLVE);
   return 0;
 }
@@ -1133,8 +1144,7 @@
 
   /* attaching to a dirty circuit is fine */
   if (connection_ap_handshake_attach_circuit(conn) < 0) {
-    conn->has_sent_end = 1; /* no circ to send to */
-    connection_mark_for_close(conn);
+    connection_close_unattached_ap(conn, END_STREAM_REASON_MISC);
     tor_close_socket(fd[1]);
     return -1;
   }
@@ -1202,7 +1212,6 @@
           (answer_type == RESOLVED_TYPE_IPV4 ||
            answer_type == RESOLVED_TYPE_IPV6) ?
                                SOCKS5_SUCCEEDED : SOCKS5_HOST_UNREACHABLE);
-  conn->socks_request->has_finished = 1;
 }
 
 /** Send a socks reply to stream <b>conn</b>, using the appropriate

Index: control.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/control.c,v
retrieving revision 1.68
retrieving revision 1.69
diff -u -d -r1.68 -r1.69
--- control.c	24 Mar 2005 06:28:21 -0000	1.68
+++ control.c	27 Mar 2005 04:55:12 -0000	1.69
@@ -736,7 +736,7 @@
   if (!circ_id) {
     ap_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
     if (connection_ap_handshake_attach_circuit(ap_conn)<0)
-      connection_mark_for_close(ap_conn);
+      connection_close_unattached_ap(ap_conn, END_STREAM_REASON_MISC);
     send_control_done(conn);
     return 0;
   }
@@ -802,7 +802,6 @@
   uint32_t conn_id;
   connection_t *ap_conn;
   uint8_t reason;
-  int hold_open;
 
   if (len < 6) {
     send_control_error(conn, ERR_SYNTAX, "closestream message too short");
@@ -811,7 +810,6 @@
 
   conn_id = ntohl(get_uint32(body));
   reason = *(uint8_t*)(body+4);
-  hold_open = (*(uint8_t*)(body+5)) & 1;
 
   if (!(ap_conn = connection_get_by_global_id(conn_id))
       || ap_conn->state != CONN_TYPE_AP
@@ -820,19 +818,11 @@
                        "No AP connection found with given ID");
     return 0;
   }
-
-  if (!ap_conn->socks_request->has_finished) {
-    socks5_reply_status_t status =
-      connection_edge_end_reason_socks5_response(reason);
-    connection_ap_handshake_socks_reply(ap_conn, NULL, 0, status);
-  }
-  if (hold_open)
-    ap_conn->hold_open_until_flushed = 1;
-  connection_mark_for_close(ap_conn);
-
+  connection_close_unattached_ap(ap_conn, reason);
   send_control_done(conn);
   return 0;
 }
+
 static int
 handle_control_closecircuit(connection_t *conn, uint32_t len,
                             const char *body)

Index: hibernate.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/hibernate.c,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -d -r1.48 -r1.49
--- hibernate.c	12 Mar 2005 20:13:38 -0000	1.48
+++ hibernate.c	27 Mar 2005 04:55:12 -0000	1.49
@@ -741,7 +741,10 @@
       connection_edge_end(conn, END_STREAM_REASON_HIBERNATING,
                           conn->cpath_layer);
     log_fn(LOG_INFO,"Closing conn type %d", conn->type);
-    connection_mark_for_close(conn);
+    if (conn->type == CONN_TYPE_AP) /* send socks failure if needed */
+      connection_close_unattached_ap(conn, END_STREAM_REASON_HIBERNATING);
+    else
+      connection_mark_for_close(conn);
   }
 
   accounting_record_bandwidth_usage(now);

Index: main.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/main.c,v
retrieving revision 1.473
retrieving revision 1.474
diff -u -d -r1.473 -r1.474
--- main.c	26 Mar 2005 05:54:50 -0000	1.473
+++ main.c	27 Mar 2005 04:55:12 -0000	1.474
@@ -476,11 +476,10 @@
 
   while ((conn = connection_get_by_type_state(CONN_TYPE_AP,
                                               AP_CONN_STATE_CIRCUIT_WAIT))) {
-    conn->has_sent_end = 1; /* it's not connected anywhere, so no need to end */
     log_fn(LOG_NOTICE,"Network down? Failing connection to '%s:%d'.",
            conn->socks_request->address, conn->socks_request->port);
-    connection_ap_handshake_socks_reply(conn, NULL, 0, SOCKS5_NET_UNREACHABLE);
-    connection_mark_for_close(conn);
+    connection_close_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
+// XXX should maybe reflect SOCKS5_NET_UNREACHABLE here. what reason is that?
   }
 }
 
@@ -589,14 +588,14 @@
       conn->hold_open_until_flushed = 1;
     } else if (!clique_mode(options) && !circuit_get_by_conn(conn) &&
                (!router || !server_mode(options) || !router_is_clique_mode(router))) {
-      log_fn(LOG_INFO,"Expiring non-used connection to %d (%s:%d) [Not in clique mode].",
+      log_fn(LOG_INFO,"Expiring non-used OR connection to %d (%s:%d) [Not in clique mode].",
              i,conn->address, conn->port);
       connection_mark_for_close(conn);
       conn->hold_open_until_flushed = 1;
     } else if (
          now >= conn->timestamp_lastempty + options->KeepalivePeriod*10 &&
          now >= conn->timestamp_lastwritten + options->KeepalivePeriod*10) {
-      log_fn(LOG_NOTICE,"Expiring stuck connection to %d (%s:%d). (%d bytes to flush; %d seconds since last write)",
+      log_fn(LOG_NOTICE,"Expiring stuck OR connection to %d (%s:%d). (%d bytes to flush; %d seconds since last write)",
              i, conn->address, conn->port,
              (int)buf_datalen(conn->outbuf),
              (int)(now-conn->timestamp_lastwritten));

Index: or.h
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/or.h,v
retrieving revision 1.573
retrieving revision 1.574
diff -u -d -r1.573 -r1.574
--- or.h	26 Mar 2005 01:43:39 -0000	1.573
+++ or.h	27 Mar 2005 04:55:12 -0000	1.574
@@ -1308,6 +1308,7 @@
 
 /********************************* connection_edge.c ***************************/
 
+void connection_close_unattached_ap(connection_t *conn, int endreason);
 int connection_edge_reached_eof(connection_t *conn);
 int connection_edge_process_inbuf(connection_t *conn, int package_partial);
 int connection_edge_destroy(uint16_t circ_id, connection_t *conn);

Index: relay.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/relay.c,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -d -r1.56 -r1.57
--- relay.c	26 Mar 2005 06:27:04 -0000	1.56
+++ relay.c	27 Mar 2005 04:55:13 -0000	1.57
@@ -416,8 +416,12 @@
   if (!circ) {
     log_fn(LOG_WARN,"no circ. Closing conn.");
     tor_assert(fromconn);
-    fromconn->has_sent_end = 1; /* no circ to send to */
-    connection_mark_for_close(fromconn);
+    if (fromconn->type == CONN_TYPE_AP) {
+      connection_close_unattached_ap(fromconn, END_STREAM_REASON_INTERNAL);
+    } else {
+      fromconn->has_sent_end = 1; /* no circ to send to */
+      connection_mark_for_close(fromconn);
+    }
     return -1;
   }
 
@@ -496,13 +500,13 @@
     case END_STREAM_REASON_CONNECTREFUSED:
       return SOCKS5_CONNECTION_REFUSED;
     case END_STREAM_REASON_EXITPOLICY:
-      return SOCKS5_CONNECTION_REFUSED;
+      return SOCKS5_CONNECTION_REFUSED; // XXX should be SOCKS5_NOT_ALLOWED ?
     case END_STREAM_REASON_DESTROY:
       return SOCKS5_GENERAL_ERROR;
     case END_STREAM_REASON_DONE:
       return SOCKS5_SUCCEEDED;
     case END_STREAM_REASON_TIMEOUT:
-      return SOCKS5_TTL_EXPIRED;
+      return SOCKS5_TTL_EXPIRED; // XXX is this correct?
     case END_STREAM_REASON_RESOURCELIMIT:
       return SOCKS5_GENERAL_ERROR;
     case END_STREAM_REASON_HIBERNATING:
@@ -603,8 +607,7 @@
       } else {
         log_fn(LOG_INFO,"Address '%s' resolved to 0.0.0.0. Closing,",
                conn->socks_request->address);
-        conn->has_sent_end = 1; /* we just got an 'end', don't need to send one */
-        connection_mark_for_close(conn);
+        connection_close_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
         return 0;
       }
       client_dns_set_addressmap(conn->socks_request->address, addr,
@@ -658,12 +661,13 @@
                                           rh->length));
     if (CIRCUIT_IS_ORIGIN(circ))
       circuit_log_path(LOG_INFO,circ);
-    conn->has_sent_end = 1; /* we just got an 'end', don't need to send one */
-    if (conn->type == CONN_TYPE_AP)
-      connection_ap_handshake_socks_reply(conn, NULL, 0,
-        connection_edge_end_reason_socks5_response(*(char *)
-          (cell->payload+RELAY_HEADER_SIZE)));
-    connection_mark_for_close(conn);
+    if (conn->type == CONN_TYPE_AP) {
+      connection_close_unattached_ap(conn,
+        *(char *)(cell->payload+RELAY_HEADER_SIZE));
+    } else {
+      conn->has_sent_end = 1; /* we just got an 'end', don't need to send one */
+      connection_mark_for_close(conn);
+    }
     return 0;
   }
 
@@ -681,7 +685,7 @@
       if (!addr) {
         log_fn(LOG_INFO,"...but it claims the IP address was 0.0.0.0. Closing.");
         connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL, conn->cpath_layer);
-        connection_mark_for_close(conn);
+        connection_close_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
         return 0;
       }
       client_dns_set_addressmap(conn->socks_request->address, addr,
@@ -705,17 +709,14 @@
     tor_assert(conn->socks_request->command == SOCKS_COMMAND_RESOLVE);
     if (rh->length < 2 || cell->payload[RELAY_HEADER_SIZE+1]+2>rh->length) {
       log_fn(LOG_WARN, "Dropping malformed 'resolved' cell");
-      conn->has_sent_end = 1;
-      connection_mark_for_close(conn);
+      connection_close_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
       return 0;
     }
     connection_ap_handshake_socks_resolved(conn,
                    cell->payload[RELAY_HEADER_SIZE], /*answer_type*/
                    cell->payload[RELAY_HEADER_SIZE+1], /*answer_len*/
                    cell->payload+RELAY_HEADER_SIZE+2); /* answer */
-    conn->has_sent_end = 1;
-    connection_mark_for_close(conn);
-    conn->hold_open_until_flushed = 1;
+    connection_close_unattached_ap(conn, END_STREAM_REASON_DONE);
     return 0;
   }
 

Index: rendclient.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/rendclient.c,v
retrieving revision 1.79
retrieving revision 1.80
diff -u -d -r1.79 -r1.80
--- rendclient.c	23 Mar 2005 06:21:48 -0000	1.79
+++ rendclient.c	27 Mar 2005 04:55:13 -0000	1.80
@@ -394,14 +394,12 @@
       if (connection_ap_handshake_attach_circuit(conn) < 0) {
         /* it will never work */
         log_fn(LOG_WARN,"attaching to a rend circ failed. Closing conn.");
-        conn->has_sent_end = 1;
-        connection_mark_for_close(conn);
+        connection_close_unattached_ap(conn, END_STREAM_REASON_MISC);
       }
       tor_assert(conn->state != AP_CONN_STATE_RENDDESC_WAIT); /* avoid loop */
     } else { /* 404, or fetch didn't get that far */
       log_fn(LOG_NOTICE,"Closing stream for '%s.onion': hidden service is unavailable (try again later).", query);
-      conn->has_sent_end = 1;
-      connection_mark_for_close(conn);
+      connection_close_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
     }
   }
 }