| 
					
				 | 
			
			
				@@ -509,14 +509,22 @@ parse_inaddr_arpa_address(const char *address, struct in_addr *in) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * do that for us.) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * If we have a cached answer, send the answer back along <b>exitconn</b>'s 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * attached circuit. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * circuit. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * Else, if seen before and pending, add conn to the pending list, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * and return 0. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * Else, if not seen before, add conn to pending list, hand to 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  * dns farm, and return 0. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * Exitconn's on_circuit field must be set, but exitconn should not 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * yet be linked onto the n_streams/resolving_streams list of that circuit. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * On success, link the connection to n_streams if it's an exit connection. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * On "pending", link the connection to resolving streams.  Otherwise, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * clear its on_circuit field. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* XXXX020 Split this into a helper that checks whether there is an answer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * and a caller that takes appropriate action based on what happened. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 dns_resolve(edge_connection_t *exitconn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -530,6 +538,7 @@ dns_resolve(edge_connection_t *exitconn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   assert_connection_ok(TO_CONN(exitconn), 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   tor_assert(exitconn->_base.s == -1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   assert_cache_ok(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tor_assert(oncirc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   is_resolve = exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -538,8 +547,12 @@ dns_resolve(edge_connection_t *exitconn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (tor_inet_aton(exitconn->_base.address, &in) != 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     exitconn->_base.addr = ntohl(in.s_addr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     exitconn->address_ttl = DEFAULT_DNS_TTL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (is_resolve) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (is_resolve) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      exitconn->next_stream = oncirc->n_streams; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      oncirc->n_streams = exitconn; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (address_is_invalid_destination(exitconn->_base.address, 0)) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -548,7 +561,8 @@ dns_resolve(edge_connection_t *exitconn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         escaped_safe_str(exitconn->_base.address)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (is_resolve) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    circuit_detach_stream(TO_CIRCUIT(oncirc), exitconn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    //circuit_detach_stream(TO_CIRCUIT(oncirc), exitconn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    exitconn->on_circuit = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (!exitconn->_base.marked_for_close) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       connection_free(TO_CONN(exitconn)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return -1; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -581,7 +595,8 @@ dns_resolve(edge_connection_t *exitconn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (exitconn->_base.purpose == EXIT_PURPOSE_RESOLVE) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      circuit_detach_stream(TO_CIRCUIT(oncirc), exitconn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      //circuit_detach_stream(TO_CIRCUIT(oncirc), exitconn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      exitconn->on_circuit = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if (!exitconn->_base.marked_for_close) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         connection_free(TO_CONN(exitconn)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return -1; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -606,6 +621,9 @@ dns_resolve(edge_connection_t *exitconn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   "resolve of %s", exitconn->_base.s, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   escaped_safe_str(exitconn->_base.address)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         exitconn->_base.state = EXIT_CONN_STATE_RESOLVING; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        exitconn->next_stream = oncirc->resolving_streams; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        oncirc->resolving_streams = exitconn; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       case CACHE_STATE_CACHED_VALID: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         log_debug(LD_EXIT,"Connection (fd %d) found cached answer for %s", 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -621,6 +639,12 @@ dns_resolve(edge_connection_t *exitconn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           if (is_resolve) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             send_resolved_cell(exitconn, RESOLVED_TYPE_IPV4); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!is_resolve) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          /* It's a connect; add it into the linked list of n_streams on this 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+             circuit */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          exitconn->next_stream = oncirc->n_streams; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          oncirc->n_streams = exitconn; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       case CACHE_STATE_CACHED_FAILED: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         log_debug(LD_EXIT,"Connection (fd %d) found cached error for %s", 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -628,7 +652,8 @@ dns_resolve(edge_connection_t *exitconn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   escaped_safe_str(exitconn->_base.address)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (is_resolve) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           send_resolved_cell(exitconn, RESOLVED_TYPE_ERROR); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        circuit_detach_stream(TO_CIRCUIT(oncirc), exitconn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // circuit_detach_stream(TO_CIRCUIT(oncirc), exitconn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        exitconn->on_circuit = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (!exitconn->_base.marked_for_close) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           connection_free(TO_CONN(exitconn)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return -1; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -658,7 +683,18 @@ dns_resolve(edge_connection_t *exitconn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   log_debug(LD_EXIT,"Launching %s.", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             escaped_safe_str(exitconn->_base.address)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   assert_cache_ok(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  return launch_resolve(exitconn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  r = launch_resolve(exitconn); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (r == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    exitconn->next_stream = oncirc->resolving_streams; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    oncirc->resolving_streams = exitconn; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tor_assert(r<0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    exitconn->on_circuit = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!exitconn->_base.marked_for_close) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      connection_free(TO_CONN(exitconn)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return r; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** Log an error and abort if conn is waiting for a DNS resolve. 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1160,7 +1196,7 @@ evdns_callback(int result, char type, int count, int ttl, void *addresses, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /** For eventdns: start resolving as necessary to find the target for 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * <b>exitconn</b> */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * <b>exitconn</b>.  Returns -1 on error, 0 on "resolve launched." */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static int 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 launch_resolve(edge_connection_t *exitconn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 |