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

[or-cvs] r8562: Backport 8478: fix long-standing server-side DNS bug. (in tor/branches/tor-0_1_1-patches: . src/or)



Author: nickm
Date: 2006-10-01 14:13:16 -0400 (Sun, 01 Oct 2006)
New Revision: 8562

Modified:
   tor/branches/tor-0_1_1-patches/ChangeLog
   tor/branches/tor-0_1_1-patches/src/or/connection_edge.c
   tor/branches/tor-0_1_1-patches/src/or/dns.c
   tor/branches/tor-0_1_1-patches/src/or/or.h
Log:
Backport 8478: fix long-standing server-side DNS bug.

Modified: tor/branches/tor-0_1_1-patches/ChangeLog
===================================================================
--- tor/branches/tor-0_1_1-patches/ChangeLog	2006-10-01 07:53:17 UTC (rev 8561)
+++ tor/branches/tor-0_1_1-patches/ChangeLog	2006-10-01 18:13:16 UTC (rev 8562)
@@ -8,6 +8,9 @@
       This should improve client CPU usage by 25-50%.
     - Don't crash if, after a server has been running for a while,
       it can't resolve its hostname.
+    - When a client asks us to resolve (not connect to) an address,
+      and we have a cached answer, give them the cached answer.
+      Previously, we would give them no answer at all.
 
   o Minor bugfixes:
     - Allow Tor to start when RunAsDaemon is set but no logs are set.

Modified: tor/branches/tor-0_1_1-patches/src/or/connection_edge.c
===================================================================
--- tor/branches/tor-0_1_1-patches/src/or/connection_edge.c	2006-10-01 07:53:17 UTC (rev 8561)
+++ tor/branches/tor-0_1_1-patches/src/or/connection_edge.c	2006-10-01 18:13:16 UTC (rev 8562)
@@ -1669,7 +1669,7 @@
   }
 
   /* send it off to the gethostbyname farm */
-  switch (dns_resolve(n_stream)) {
+  switch (dns_resolve(n_stream, NULL)) {
     case 1: /* resolve worked */
 
       /* add it into the linked list of n_streams on this circuit */
@@ -1723,7 +1723,7 @@
   dummy_conn->purpose = EXIT_PURPOSE_RESOLVE;
 
   /* send it off to the gethostbyname farm */
-  switch (dns_resolve(dummy_conn)) {
+  switch (dns_resolve(dummy_conn, circ)) {
     case -1: /* Impossible to resolve; a resolved cell was sent. */
       /* Connection freed; don't touch it. */
       return 0;

Modified: tor/branches/tor-0_1_1-patches/src/or/dns.c
===================================================================
--- tor/branches/tor-0_1_1-patches/src/or/dns.c	2006-10-01 07:53:17 UTC (rev 8561)
+++ tor/branches/tor-0_1_1-patches/src/or/dns.c	2006-10-01 18:13:16 UTC (rev 8562)
@@ -71,13 +71,14 @@
 } cached_resolve_t;
 
 static void purge_expired_resolves(uint32_t now);
-static int assign_to_dnsworker(connection_t *exitconn);
+static int assign_to_dnsworker(connection_t *exitconn, circuit_t *oncirc);
 static void dns_purge_resolve(cached_resolve_t *resolve);
 static void dns_found_answer(char *address, uint32_t addr, char outcome);
 static int dnsworker_main(void *data);
 static int spawn_dnsworker(void);
 static int spawn_enough_dnsworkers(void);
-static void send_resolved_cell(connection_t *conn, uint8_t answer_type);
+static void send_resolved_cell(connection_t *conn, circuit_t *circ,
+                               uint8_t answer_type);
 
 /** Hash table of cached_resolve objects. */
 static HT_HEAD(cache_map, cached_resolve_t) cache_root;
@@ -199,7 +200,7 @@
 /** Send a response to the RESOVLE request of a connection. answer_type must
  *  be one of RESOLVED_TYPE_(IPV4|ERROR|ERROR_TRANSIENT) */
 static void
-send_resolved_cell(connection_t *conn, uint8_t answer_type)
+send_resolved_cell(connection_t *conn, circuit_t *circ, uint8_t answer_type)
 {
   char buf[RELAY_PAYLOAD_SIZE];
   size_t buflen;
@@ -229,7 +230,12 @@
     default:
       tor_assert(0);
     }
-  connection_edge_send_command(conn, circuit_get_by_edge_conn(conn),
+
+  if (circ == NULL) {
+    circ = circuit_get_by_edge_conn(conn);
+  }
+
+  connection_edge_send_command(conn, circ,
                                RELAY_COMMAND_RESOLVED, buf, buflen,
                                conn->cpath_layer);
 }
@@ -261,7 +267,7 @@
  * dns farm, and return 0.
  */
 int
-dns_resolve(connection_t *exitconn)
+dns_resolve(connection_t *exitconn, circuit_t *oncirc)
 {
   cached_resolve_t *resolve;
   cached_resolve_t search;
@@ -277,7 +283,7 @@
   if (tor_inet_aton(exitconn->address, &in) != 0) {
     exitconn->addr = ntohl(in.s_addr);
     if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
-      send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
+      send_resolved_cell(exitconn, oncirc, RESOLVED_TYPE_IPV4);
     return 1;
   }
 
@@ -310,13 +316,13 @@
         log_debug(LD_EXIT,"Connection (fd %d) found cached answer for %s",
                   exitconn->s, escaped_safe_str(exitconn->address));
         if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
-          send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4);
+          send_resolved_cell(exitconn, oncirc, RESOLVED_TYPE_IPV4);
         return 1;
       case CACHE_STATE_FAILED:
         log_debug(LD_EXIT,"Connection (fd %d) found cached error for %s",
                   exitconn->s, escaped_safe_str(exitconn->address));
         if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
-          send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR);
+          send_resolved_cell(exitconn, oncirc, RESOLVED_TYPE_ERROR);
         circ = circuit_get_by_edge_conn(exitconn);
         if (circ)
           circuit_detach_stream(circ, exitconn);
@@ -339,14 +345,14 @@
   exitconn->state = EXIT_CONN_STATE_RESOLVING;
 
   insert_resolve(resolve);
-  return assign_to_dnsworker(exitconn);
+  return assign_to_dnsworker(exitconn, oncirc);
 }
 
 /** Find or spawn a dns worker process to handle resolving
  * <b>exitconn</b>-\>address; tell that dns worker to begin resolving.
  */
 static int
-assign_to_dnsworker(connection_t *exitconn)
+assign_to_dnsworker(connection_t *exitconn, circuit_t *oncirc)
 {
   connection_t *dnsconn;
   unsigned char len;
@@ -365,7 +371,7 @@
   if (!dnsconn) {
     log_warn(LD_EXIT,"no idle dns workers. Failing.");
     if (exitconn->purpose == EXIT_PURPOSE_RESOLVE)
-      send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR_TRANSIENT);
+      send_resolved_cell(exitconn, oncirc, RESOLVED_TYPE_ERROR_TRANSIENT);
     goto err;
   }
 
@@ -631,7 +637,7 @@
         /* This detach must happen after we send the end cell. */
         circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn);
       } else {
-        send_resolved_cell(pendconn, RESOLVED_TYPE_ERROR);
+        send_resolved_cell(pendconn, NULL, RESOLVED_TYPE_ERROR);
         /* This detach must happen after we send the resolved cell. */
         circuit_detach_stream(circuit_get_by_edge_conn(pendconn), pendconn);
       }
@@ -655,7 +661,7 @@
         /* prevent double-remove.  This isn't really an accurate state,
          * but it does the right thing. */
         pendconn->state = EXIT_CONN_STATE_RESOLVEFAILED;
-        send_resolved_cell(pendconn, RESOLVED_TYPE_IPV4);
+        send_resolved_cell(pendconn, NULL, RESOLVED_TYPE_IPV4);
         circ = circuit_get_by_edge_conn(pendconn);
         tor_assert(circ);
         circuit_detach_stream(circ, pendconn);

Modified: tor/branches/tor-0_1_1-patches/src/or/or.h
===================================================================
--- tor/branches/tor-0_1_1-patches/src/or/or.h	2006-10-01 07:53:17 UTC (rev 8561)
+++ tor/branches/tor-0_1_1-patches/src/or/or.h	2006-10-01 18:13:16 UTC (rev 8562)
@@ -1961,7 +1961,7 @@
 void assert_connection_edge_not_dns_pending(connection_t *conn);
 void assert_all_pending_dns_resolves_ok(void);
 void dns_cancel_pending_resolve(char *question);
-int dns_resolve(connection_t *exitconn);
+int dns_resolve(connection_t *exitconn, circuit_t *oncirc);
 
 /********************************* hibernate.c **********************/