Browse Source

Catch and report a few more bootstrapping failure cases when Tor
fails to establish a TCP connection. Cleanup on 0.2.1.x.


svn:r16803

Roger Dingledine 15 years ago
parent
commit
d37fae2f4e
6 changed files with 42 additions and 25 deletions
  1. 7 3
      ChangeLog
  2. 0 3
      src/or/circuituse.c
  3. 11 11
      src/or/connection.c
  4. 18 5
      src/or/connection_or.c
  5. 4 0
      src/or/main.c
  6. 2 3
      src/or/or.h

+ 7 - 3
ChangeLog

@@ -1,10 +1,12 @@
 Changes in version 0.2.1.6-alpha - 2008-09-xx
+  o Major bugfixes:
+    - Fix a bug when parsing ports in tor_addr_port_parse() that caused
+      Tor to fail to start if you had it configured to use a bridge
+      relay. Fixes bug 809. Bugfix on 0.2.1.5-alpha.
+
   o Minor bugfixes:
     - Fix compile on OpenBSD 4.4-current. Bugfix on 0.2.1.5-alpha.
       Reported by Tas.
-    - When parsing ports in tor_addr_port_parse(), yield the port if
-      the port variable is provided, not just if it's nonzero.  Fixes
-      bug 809.  Bugfix on 0.2.1.5-alpha.
     - Fixed some memory leaks --some quite frequent, some almost impossible
       to trigger-- based on results of a static analysis tool. (XXX Can we
       say which? -NM)
@@ -12,6 +14,8 @@ Changes in version 0.2.1.6-alpha - 2008-09-xx
       correctly.  (Found by Riastradh.)
     - Fix an assertion bug in parsing policy-related options; possible fix
       for bug 811.
+    - Catch and report a few more bootstrapping failure cases when Tor
+      fails to establish a TCP connection. Cleanup on 0.2.1.x.
 
   o Minor features:
     - Use a lockfile to make sure that two Tor processes are not

+ 0 - 3
src/or/circuituse.c

@@ -756,9 +756,6 @@ circuit_build_failed(origin_circuit_t *circ)
                "(%s:%d). I'm going to try to rotate to a better connection.",
                n_conn->_base.address, n_conn->_base.port);
       n_conn->_base.or_is_obsolete = 1;
-      if (n_conn->_base.state < OR_CONN_STATE_TLS_HANDSHAKING &&
-          !n_conn->socket_error)
-        n_conn->socket_error = END_OR_CONN_REASON_TIMEOUT;
       entry_guard_register_connect_status(n_conn->identity_digest, 0,
                                           time(NULL));
     }

+ 11 - 11
src/or/connection.c

@@ -547,14 +547,7 @@ connection_about_to_close_connection(connection_t *conn)
           entry_guard_register_connect_status(or_conn->identity_digest,0,now);
           if (!options->HttpsProxy)
             router_set_status(or_conn->identity_digest, 0);
-          if (conn->state == OR_CONN_STATE_CONNECTING) {
-            control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
-              errno_to_orconn_end_reason(or_conn->socket_error));
-            if (!authdir_mode_tests_reachability(options))
-              control_event_bootstrap_problem(
-                tor_socket_strerror(or_conn->socket_error),
-                errno_to_orconn_end_reason(or_conn->socket_error));
-          } else {
+          if (conn->state >= OR_CONN_STATE_TLS_HANDSHAKING) {
             int reason = tls_error_to_orconn_end_reason(or_conn->tls_error);
             control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
                                          reason);
@@ -1947,8 +1940,13 @@ loop_again:
   before = buf_datalen(conn->inbuf);
   if (connection_read_to_buf(conn, &max_to_read) < 0) {
     /* There's a read error; kill the connection.*/
-    if (conn->type == CONN_TYPE_OR)
-      TO_OR_CONN(conn)->socket_error = tor_socket_errno(conn->s);
+    if (conn->type == CONN_TYPE_OR &&
+        conn->state == OR_CONN_STATE_CONNECTING) {
+      int socket_error = tor_socket_errno(conn->s);
+      connection_or_connect_failed(TO_OR_CONN(conn),
+                                   errno_to_orconn_end_reason(socket_error),
+                                   tor_socket_strerror(socket_error));
+    }
     if (CONN_IS_EDGE(conn)) {
       edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
       connection_edge_end_errno(edge_conn);
@@ -2254,7 +2252,9 @@ connection_handle_write(connection_t *conn, int force)
         if (CONN_IS_EDGE(conn))
           connection_edge_end_errno(TO_EDGE_CONN(conn));
         if (conn->type == CONN_TYPE_OR)
-          TO_OR_CONN(conn)->socket_error = e;
+          connection_or_connect_failed(TO_OR_CONN(conn),
+                                       errno_to_orconn_end_reason(e),
+                                       tor_socket_strerror(e));
 
         connection_close_immediate(conn);
         connection_mark_for_close(conn);

+ 18 - 5
src/or/connection_or.c

@@ -492,6 +492,21 @@ connection_or_get_by_identity_digest(const char *digest)
   return best;
 }
 
+/** <b>conn</b> is in the 'connecting' state, and it failed to complete
+ * a TCP connection. Send notifications appropriately.
+ *
+ * <b>reason</b> specifies the or_conn_end_reason for the failure;
+ * <b>msg</b> specifies the strerror-style error message.
+ */
+void
+connection_or_connect_failed(or_connection_t *conn,
+                             int reason, const char *msg)
+{
+  control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED, reason);
+  if (!authdir_mode_tests_reachability(get_options()))
+    control_event_bootstrap_problem(msg, reason);
+}
+
 /** Launch a new OR connection to <b>addr</b>:<b>port</b> and expect to
  * handshake with an OR with identity digest <b>id_digest</b>.
  *
@@ -548,11 +563,9 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
                                             time(NULL));
         router_set_status(conn->identity_digest, 0);
       }
-      control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED,
-                                   errno_to_orconn_end_reason(socket_error));
-      if (!authdir_mode_tests_reachability(options))
-        control_event_bootstrap_problem(tor_socket_strerror(socket_error),
-                                     errno_to_orconn_end_reason(socket_error));
+      connection_or_connect_failed(conn,
+                                   errno_to_orconn_end_reason(socket_error),
+                                   tor_socket_strerror(socket_error));
       connection_free(TO_CONN(conn));
       return NULL;
     case 0:

+ 4 - 0
src/or/main.c

@@ -743,6 +743,10 @@ run_connection_housekeeping(int i, time_t now)
     log_info(LD_OR,
              "Expiring non-used OR connection to fd %d (%s:%d) [Obsolete].",
              conn->s, conn->address, conn->port);
+    if (conn->state == OR_CONN_STATE_CONNECTING)
+      connection_or_connect_failed(TO_OR_CONN(conn),
+                                   END_OR_CONN_REASON_TIMEOUT,
+                                   "Tor gave up on the connection");
     connection_mark_for_close(conn);
     conn->hold_open_until_flushed = 1;
     return;

+ 2 - 3
src/or/or.h

@@ -941,9 +941,6 @@ typedef struct or_connection_t {
 
   tor_tls_t *tls; /**< TLS connection state. */
   int tls_error; /**< Last tor_tls error code. */
-  /* XXX either merge this with tls_error, or do all our activity right
-   * when we compute this value so we don't have to store it. */
-  int socket_error; /**< If conn dies, remember why. */
   /** When we last used this conn for any client traffic. If not
    * recent, we can rate limit it further. */
   time_t client_used;
@@ -2991,6 +2988,8 @@ int connection_or_flushed_some(or_connection_t *conn);
 int connection_or_finished_flushing(or_connection_t *conn);
 int connection_or_finished_connecting(or_connection_t *conn);
 
+void connection_or_connect_failed(or_connection_t *conn,
+                                  int reason, const char *msg);
 or_connection_t *connection_or_connect(const tor_addr_t *addr, uint16_t port,
                                        const char *id_digest);