[or-cvs] Handle END_STREAM_REASON_{EXITPOLICY|RESOLVEFAILED}

Nick Mathewson nickm at seul.org
Tue Apr 13 17:49:43 UTC 2004


Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/tmp/cvs-serv21969/src/or

Modified Files:
	connection_edge.c 
Log Message:
Handle END_STREAM_REASON_{EXITPOLICY|RESOLVEFAILED}

Index: connection_edge.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_edge.c,v
retrieving revision 1.157
retrieving revision 1.158
diff -u -d -r1.157 -r1.158
--- connection_edge.c	12 Apr 2004 23:33:47 -0000	1.157
+++ connection_edge.c	13 Apr 2004 17:49:41 -0000	1.158
@@ -15,6 +15,7 @@
 
 static uint32_t client_dns_lookup_entry(const char *address);
 static void client_dns_set_entry(const char *address, uint32_t val);
+static int client_dns_incr_failures(const char *address);
 
 void relay_header_pack(char *dest, const relay_header_t *src) {
   *(uint8_t*)(dest) = src->command;
@@ -216,23 +217,46 @@
   return 0;
 }
 
+#define MAX_RESOLVE_FAILURES 3
+
 int connection_edge_process_relay_cell_not_open(
     relay_header_t *rh, cell_t *cell, circuit_t *circ,
     connection_t *conn, crypt_path_t *layer_hint) {
   uint32_t addr;
+  int reason;
 
   if(rh->command == RELAY_COMMAND_END) {
+    reason = *(cell->payload+RELAY_HEADER_SIZE);
+    /* We have to check this here, since we aren't connected yet. */
+    if (rh->length >= 5 && reason == END_STREAM_REASON_EXITPOLICY) {
+      addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+1));
+      client_dns_set_entry(conn->socks_request->address, addr);
+      conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
+      if(connection_ap_handshake_attach_circuit(conn) >= 0)
+        return 0;
+      /* else, conn will get closed below */
+    } else if (rh->length && reason == END_STREAM_REASON_RESOLVEFAILED) {
+      if (client_dns_incr_failures(conn->socks_request->address)
+          < MAX_RESOLVE_FAILURES) {
+        /* We haven't retried too many times; reattach the connection. */
+        conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
+        if(connection_ap_handshake_attach_circuit(conn) >= 0)
+          return 0;
+        /* else, conn will get closed below */
+      }
+    }
     log_fn(LOG_INFO,"Edge got end (%s) before we're connected. Marking for close.",
       connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, 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 */
     connection_mark_for_close(conn, 0);
-    /* XXX This is where we should check if reason is EXITPOLICY, and reattach */
     /* XXX here we should send a socks reject back if necessary, and hold
      * open til flushed */
     return 0;
   }
+
+
   if(conn->type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_CONNECTED) {
     if(conn->state != AP_CONN_STATE_CONNECT_WAIT) {
       log_fn(LOG_WARN,"Got 'connected' while not in state connect_wait. Dropping.");
@@ -269,7 +293,6 @@
                                        connection_t *conn,
                                        crypt_path_t *layer_hint) {
   static int num_seen=0;
-  uint32_t addr;
   relay_header_t rh;
 
   assert(cell && circ);
@@ -339,23 +362,6 @@
           connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, rh.length));
         return 0;
       }
-      if(rh.length >= 5 &&
-         *(cell->payload+RELAY_HEADER_SIZE) == END_STREAM_REASON_EXITPOLICY) {
-
-        /* XXX this will never be reached, since we're in 'connect_wait' state
-         * but this is only reached when we're in 'open' state. Put it higher. */
-
-        /* No need to close the connection. We'll hold it open while
-         * we try a new exit node.
-         * cell->payload+RELAY_HEADER_SIZE+1 holds the destination addr.
-         */
-        addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+1));
-        client_dns_set_entry(conn->socks_request->address, addr);
-        conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
-        if(connection_ap_handshake_attach_circuit(conn) >= 0)
-          return 0;
-        /* else, conn will get closed below */
-      }
 /* XXX add to this log_fn the exit node's nickname? */
       log_fn(LOG_INFO,"end cell (%s) for stream %d. Removing stream.",
         connection_edge_end_reason(cell->payload+RELAY_HEADER_SIZE, rh.length),
@@ -1256,6 +1262,7 @@
 struct client_dns_entry {
   uint32_t addr;
   time_t expires;
+  int n_failures;
 };
 static int client_dns_size = 0;
 static strmap_t *client_dns_map = NULL;
@@ -1265,6 +1272,20 @@
   client_dns_size = 0;
 }
 
+static struct client_dns_entry *
+_get_or_create_ent(const char *address)
+{
+  struct client_dns_entry *ent;
+  ent = strmap_get_lc(client_dns_map,address);
+  if (!ent) {
+    ent = tor_malloc_zero(sizeof(struct client_dns_entry));
+    ent->expires = time(NULL)+MAX_DNS_ENTRY_AGE;
+    strmap_set_lc(client_dns_map,address,ent);
+    ++client_dns_size;
+  }
+  return ent;
+}
+
 static uint32_t client_dns_lookup_entry(const char *address)
 {
   struct client_dns_entry *ent;
@@ -1279,7 +1300,7 @@
     return ntohl(in.s_addr);
   }
   ent = strmap_get_lc(client_dns_map,address);
-  if (!ent) {
+  if (!ent && !ent->addr) {
     log_fn(LOG_DEBUG, "No entry found for address %s", address);
     return 0;
   } else {
@@ -1298,6 +1319,13 @@
   }
 }
 
+static int client_dns_incr_failures(const char *address)
+{
+  struct client_dns_entry *ent;
+  ent = _get_or_create_ent(address);
+  return ++ent->n_failures;
+}
+
 static void client_dns_set_entry(const char *address, uint32_t val)
 {
   struct client_dns_entry *ent;
@@ -1310,23 +1338,13 @@
   if (tor_inet_aton(address, &in))
     return;
   now = time(NULL);
-  ent = strmap_get_lc(client_dns_map, address);
-  if (ent) {
-    in.s_addr = htonl(val);
-    log_fn(LOG_DEBUG, "Updating entry for address %s: %s", address,
-           inet_ntoa(in));
-    ent->addr = val;
-    ent->expires = now+MAX_DNS_ENTRY_AGE;
-  } else {
-    in.s_addr = htonl(val);
-    log_fn(LOG_DEBUG, "Caching result for address %s: %s", address,
-           inet_ntoa(in));
-    ent = tor_malloc(sizeof(struct client_dns_entry));
-    ent->addr = val;
-    ent->expires = now+MAX_DNS_ENTRY_AGE;
-    strmap_set_lc(client_dns_map, address, ent);
-    ++client_dns_size;
-  }
+  ent = _get_or_create_ent(address);
+  in.s_addr = htonl(val);
+  log_fn(LOG_DEBUG, "Updating entry for address %s: %s", address,
+         inet_ntoa(in));
+  ent->addr = val;
+  ent->expires = now+MAX_DNS_ENTRY_AGE;
+  ent->n_failures = 0;
 }
 
 static void* _remove_if_expired(const char *addr,



More information about the tor-commits mailing list