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

[or-cvs] Add a new AddressMap directive to rewrite incoming socks ad...



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

Modified Files:
	circuituse.c config.c connection_edge.c main.c or.h relay.c 
Log Message:
Add a new AddressMap directive to rewrite incoming socks addresses.
Add a new TrackHostExits directive to trigger addressmaps for
certain incoming socks addresses, for sites that break when your exit
keeps changing.
Redo the client-side dns cache so it's just an addressmap too.


Index: circuituse.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/circuituse.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -d -r1.49 -r1.50
--- circuituse.c	2 Feb 2005 06:26:52 -0000	1.49
+++ circuituse.c	22 Feb 2005 00:53:07 -0000	1.50
@@ -385,7 +385,7 @@
     circuit_reset_failure_count(1);
     time_to_new_circuit = now + get_options()->NewCircuitPeriod;
     if (proxy_mode(get_options()))
-      client_dns_clean();
+      addressmap_clean(now);
     circuit_expire_old_circuits();
 
 #if 0 /* disable for now, until predict-and-launch-new can cull leftovers */
@@ -768,7 +768,6 @@
                                 uint8_t desired_circuit_purpose,
                                 circuit_t **circp) {
   circuit_t *circ;
-  uint32_t addr;
   int is_resolve;
   int need_uptime;
 
@@ -801,7 +800,10 @@
 
   /* Do we need to check exit policy? */
   if (!is_resolve && !connection_edge_is_rendezvous_stream(conn)) {
-    addr = client_dns_lookup_entry(conn->socks_request->address);
+    struct in_addr in;
+    uint32_t addr = 0;
+    if (tor_inet_aton(conn->socks_request->address, &in))
+      addr = ntohl(in.s_addr);
     if (router_exit_policy_all_routers_reject(addr, conn->socks_request->port,
                                               need_uptime)) {
       log_fn(LOG_NOTICE,"No Tor server exists that allows exit to %s:%d. Rejecting.",
@@ -899,6 +901,53 @@
   apconn->cpath_layer = circ->cpath->prev;
 }
 
+/** If an exit wasn't specifically chosen, save the history for future
+ * use */
+static void
+consider_recording_trackhost(connection_t *conn, circuit_t *circ) {
+  int found_needle = 0;
+  char *str;
+  or_options_t *options = get_options();
+  size_t len;
+  char *new_address;
+
+  /* Search the addressmap for this conn's destination. */
+  /* If he's not in the address map.. */
+  if (!options->TrackHostExits ||
+      addressmap_already_mapped(conn->socks_request->address))
+    return; /* nothing to track, or already mapped */
+
+  SMARTLIST_FOREACH(options->TrackHostExits, const char *, cp, {
+    if (cp[0] == '.') { /* match end */
+      /* XXX strstr is probably really bad here */
+      if ((str = strstr(conn->socks_request->address, &cp[1]))) {
+        if (str == conn->socks_request->address
+          || strcmp(str, &cp[1]) == 0) {
+          found_needle = 1;
+        }
+      }
+    } else if (strcmp(cp, conn->socks_request->address) == 0) {
+      found_needle = 1;
+    }
+  });
+
+  if (!found_needle)
+    return;
+
+  /* Add this exit/hostname pair to the addressmap. */
+  len = strlen(conn->socks_request->address) + 1 /* '.' */ +
+        strlen(circ->build_state->chosen_exit_name) + 1 /* '.' */ +
+        strlen("exit") + 1 /* '\0' */;
+  new_address = tor_malloc(len);
+
+  tor_snprintf(new_address, len, "%s.%s.exit",
+               conn->socks_request->address,
+               circ->build_state->chosen_exit_name);
+
+  addressmap_register(conn->socks_request->address, new_address,
+                      time(NULL) + options->TrackHostExitsExpire);
+}
+
 /** Try to find a safe live circuit for CONN_TYPE_AP connection conn. If
  * we don't find one: if conn cannot be handled by any known nodes,
  * warn and return -1 (conn needs to die);
@@ -957,7 +1006,7 @@
     link_apconn_to_circ(conn, circ);
     tor_assert(conn->socks_request);
     if (conn->socks_request->command == SOCKS_COMMAND_CONNECT) {
-//      consider_recording_trackhost(conn, circ);
+      consider_recording_trackhost(conn, circ);
       connection_ap_handshake_send_begin(conn, circ);
     } else {
       connection_ap_handshake_send_resolve(conn, circ);

Index: config.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/config.c,v
retrieving revision 1.312
retrieving revision 1.313
diff -u -d -r1.312 -r1.313
--- config.c	11 Feb 2005 01:26:46 -0000	1.312
+++ config.c	22 Feb 2005 00:53:07 -0000	1.313
@@ -120,6 +120,9 @@
   VAR("StrictEntryNodes",    BOOL,     StrictEntryNodes,     "0"),
   VAR("ExitPolicy",          LINELIST, ExitPolicy,           NULL),
   VAR("ExcludeNodes",        STRING,   ExcludeNodes,         NULL),
+  VAR("TrackHostExits",      CSV,      TrackHostExits,       NULL),
+  VAR("TrackHostExitsExpire",INTERVAL, TrackHostExitsExpire, "30 minutes"),
+  VAR("AddressMap",          LINELIST, AddressMap,           NULL),
   VAR("FascistFirewall",     BOOL,     FascistFirewall,      "0"),
   VAR("FirewallPorts",       CSV,      FirewallPorts,        "80,443"),
   VAR("MyFamily",            STRING,   MyFamily,             NULL),
@@ -186,6 +189,7 @@
 static int options_validate(or_options_t *options);
 static int options_transition_allowed(or_options_t *old, or_options_t *new);
 static int check_nickname_list(const char *lst, const char *name);
+static void config_register_addressmaps(or_options_t *options);
 
 static int parse_dir_server_line(const char *line, int validate_only);
 static int parse_redirect_line(smartlist_t *result,
@@ -333,6 +337,9 @@
   if (options->PidFile)
     write_pidfile(options->PidFile);
 
+  /* Register addressmap directives */
+  config_register_addressmaps(options);
+
   /* Update address policies. */
   parse_socks_policy();
   parse_dir_policy();
@@ -1797,6 +1804,29 @@
   return -1;
 }
 
+static void
+config_register_addressmaps(or_options_t *options) {
+  smartlist_t *elts;
+  struct config_line_t *opt;
+  char *from, *to;
+
+  elts = smartlist_create();
+  for (opt = options->AddressMap; opt; opt = opt->next) {
+    smartlist_split_string(elts, opt->value, NULL,
+                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 2);
+    if (smartlist_len(elts) >= 2) {
+      from = smartlist_get(elts,0);
+      to = smartlist_get(elts,1);
+      addressmap_register(from, tor_strdup(to), 0);
+    } else {
+      log_fn(LOG_WARN,"AddressMap '%s' has too few arguments. Ignoring.", opt->value);
+    }
+    SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp));
+    smartlist_clear(elts);
+  }
+  smartlist_free(elts);
+}
+
 /** If <b>range</b> is of the form MIN-MAX, for MIN and MAX both
  * recognized log severity levels, set *<b>min_out</b> to MIN and
  * *<b>max_out</b> to MAX and return 0.  Else, if <b>range<b> is of

Index: connection_edge.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/connection_edge.c,v
retrieving revision 1.278
retrieving revision 1.279
diff -u -d -r1.278 -r1.279
--- connection_edge.c	17 Feb 2005 01:12:50 -0000	1.278
+++ connection_edge.c	22 Feb 2005 00:53:07 -0000	1.279
@@ -329,6 +329,169 @@
   }
 }
 
+/** A client-side struct to remember requests to rewrite addresses
+ * to new addresses. These structs make up a tree, with addressmap
+ * below as its root.
+ *
+ * There are 5 ways to set an address mapping:
+ * - A MapAddress command from the controller [permanent]
+ * - An AddressMap directive in the torrc [permanent]
+ * - When a TrackHostExits torrc directive is triggered [temporary]
+ * - When a dns resolve succeeds [temporary]
+ * - When a dns resolve fails [temporary]
+ *
+ * When an addressmap request is made but one is already registered,
+ * the new one is replaced only if the currently registered one has
+ * no "new_address" (that is, it's in the process of dns resolve),
+ * or if the new one is permanent (expires==0).
+ */
+typedef struct {
+  char *new_address;
+  time_t expires;
+  int num_resolve_failures;
+} addressmap_entry_t;
+
+/** The tree of client-side address rewrite instructions. */
+static strmap_t *addressmap;
+
+/** Initialize addressmap. */
+void addressmap_init(void) {
+  addressmap = strmap_new();
+}
+
+/** Free the memory associated with the addressmap entry <b>_ent</b>. */
+static void
+addressmap_ent_free(void *_ent) {
+  addressmap_entry_t *ent = _ent;
+  tor_free(ent->new_address);
+  tor_free(ent);
+}
+
+/** A helper function for addressmap_clean() below. If ent is too old,
+ * then remove it from the tree and return NULL, else return ent.
+ */
+static void *
+_addressmap_remove_if_expired(const char *addr,
+                              addressmap_entry_t *ent,
+                              time_t *nowp) {
+  if (ent->expires && ent->expires < *nowp) {
+    log(LOG_NOTICE, "Addressmap: expiring remap (%s to %s)",
+           addr, ent->new_address);
+    addressmap_ent_free(ent);
+    return NULL;
+  } else {
+    return ent;
+  }
+}
+
+/** Clean out entries from the addressmap cache that were
+ * added long enough ago that they are no longer valid.
+ */
+void addressmap_clean(time_t now) {
+  strmap_foreach(addressmap,
+                 (strmap_foreach_fn)_addressmap_remove_if_expired, &now);
+}
+
+/** Free all the elements in the addressmap, and free the addressmap
+ * itself. */
+void addressmap_free_all(void) {
+  strmap_free(addressmap, addressmap_ent_free);
+  addressmap = NULL;
+}
+
+/** Look at address, and rewrite it until it doesn't want any
+ * more rewrites; but don't get into an infinite loop.
+ * Don't write more than maxlen chars into address.
+ */
+void addressmap_rewrite(char *address, size_t maxlen) {
+  addressmap_entry_t *ent;
+  int rewrites;
+
+  for (rewrites = 0; rewrites < 16; rewrites++) {
+    ent = strmap_get(addressmap, address);
+
+    if (!ent || !ent->new_address)
+      return; /* done, no rewrite needed */
+
+    log_fn(LOG_NOTICE, "Addressmap: rewriting '%s' to '%s'",
+           address, ent->new_address);
+    strlcpy(address, ent->new_address, maxlen);
+  }
+  log_fn(LOG_WARN,"Loop detected: we've rewritten '%s' 16 times! Using it as-is.",
+         address);
+  /* it's fine to rewrite a rewrite, but don't loop forever */
+}
+
+/** Return 1 if <b>address</b> is already registered, else return 0 */
+int addressmap_already_mapped(const char *address) {
+  return strmap_get(addressmap, address) ? 1 : 0;
+}
+
+/** Register a request to map <b>address</b> to <b>new_address</b>,
+ * which will expire on <b>expires</b> (or 0 if never expires).
+ *
+ * new_address should be a newly dup'ed string, which we'll use or
+ * free as appropriate. We will leave address alone.
+ */
+void addressmap_register(const char *address, char *new_address, time_t expires) {
+  addressmap_entry_t *ent;
+
+  ent = strmap_get(addressmap, address);
+  if (ent && ent->new_address && expires) {
+    log_fn(LOG_NOTICE,"Addressmap ('%s' to '%s') not performed, since it's already mapped to '%s'", address, new_address, ent->new_address);
+    tor_free(new_address);
+    return;
+  }
+  if (ent) { /* we'll replace it */
+    tor_free(ent->new_address);
+  } else { /* make a new one and register it */
+    ent = tor_malloc_zero(sizeof(addressmap_entry_t));
+    strmap_set(addressmap, address, ent);
+  }
+  ent->new_address = new_address;
+  ent->expires = expires;
+  ent->num_resolve_failures = 0;
+
+  log_fn(LOG_NOTICE, "Addressmap: (re)mapped '%s' to '%s'",
+         address, ent->new_address);
+}
+
+/** An attempt to resolve <b>address</b> failed at some OR.
+ * Increment the number of resolve failures we have on record
+ * for it, and then return that number.
+ */
+int client_dns_incr_failures(const char *address)
+{
+  addressmap_entry_t *ent;
+  ent = strmap_get(addressmap,address);
+  if (!ent) {
+    ent = tor_malloc_zero(sizeof(addressmap_entry_t));
+    ent->expires = time(NULL)+MAX_DNS_ENTRY_AGE;
+    strmap_set(addressmap,address,ent);
+  }
+  ++ent->num_resolve_failures;
+  log_fn(LOG_NOTICE,"Address %s now has %d resolve failures.",
+         address, ent->num_resolve_failures);
+  return ent->num_resolve_failures;
+}
+
+/** Record the fact that <b>address</b> resolved to <b>val</b>.
+ * We can now use this in subsequent streams via addressmap_rewrite()
+ * so we can more correctly choose an exit that will allow <b>address</b>.
+ */
+void client_dns_set_addressmap(const char *address, uint32_t val)
+{
+  struct in_addr in;
+
+  tor_assert(address); tor_assert(val);
+
+  if (tor_inet_aton(address, &in))
+    return; /* don't set an addressmap back to ourselves! */
+  in.s_addr = htonl(val);
+  addressmap_register(address, strdup(inet_ntoa(in)),
+                      time(NULL) + MAX_DNS_ENTRY_AGE);
+}
+
 /** Return 1 if <b>address</b> has funny characters in it like
  * colons. Return 0 if it's fine.
  */
@@ -383,6 +546,11 @@
     return sockshere;
   } /* else socks handshake is done, continue processing */
 
+  tor_strlower(socks->address); /* normalize it */
+
+  /* For address map controls, remap the address */
+  addressmap_rewrite(socks->address, sizeof(socks->address));
+
   /* Parse the address provided by SOCKS.  Modify it in-place if it
    * specifies a hidden-service (.onion) or particular exit node (.exit).
    */
@@ -408,7 +576,7 @@
     }
 
     if (socks->command == SOCKS_COMMAND_RESOLVE) {
-      uint32_t answer = 0;
+      uint32_t answer;
       struct in_addr in;
       /* Reply to resolves immediately if we can. */
       if (strlen(socks->address) > RELAY_PAYLOAD_SIZE) {
@@ -416,11 +584,8 @@
         connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_ERROR,0,NULL);
         return -1;
       }
-      if (tor_inet_aton(socks->address, &in)) /* see if it's an IP already */
+      if (tor_inet_aton(socks->address, &in)) { /* see if it's an IP already */
         answer = in.s_addr;
-      if (!answer && !conn->chosen_exit_name) /* if it's not .exit, check cache */
-        answer = htonl(client_dns_lookup_entry(socks->address));
-      if (answer) {
         connection_ap_handshake_socks_resolved(conn,RESOLVED_TYPE_IPV4,4,
                                                (char*)&answer);
         conn->has_sent_end = 1;
@@ -514,8 +679,6 @@
 {
   char payload[CELL_PAYLOAD_SIZE];
   int payload_len;
-  struct in_addr in;
-  const char *string_addr;
 
   tor_assert(ap_conn->type == CONN_TYPE_AP);
   tor_assert(ap_conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
@@ -530,18 +693,10 @@
     return -1;
   }
 
-  if (circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) {
-    in.s_addr = htonl(client_dns_lookup_entry(ap_conn->socks_request->address));
-    string_addr = in.s_addr ? inet_ntoa(in) : NULL;
-
-    tor_snprintf(payload,RELAY_PAYLOAD_SIZE,
-             "%s:%d",
-             string_addr ? string_addr : ap_conn->socks_request->address,
-             ap_conn->socks_request->port);
-  } else {
-    tor_snprintf(payload,RELAY_PAYLOAD_SIZE,
-             ":%d", ap_conn->socks_request->port);
-  }
+  tor_snprintf(payload,RELAY_PAYLOAD_SIZE, "%s:%d",
+               (circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) ?
+                 ap_conn->socks_request->address : "",
+               ap_conn->socks_request->port);
   payload_len = strlen(payload)+1;
 
   log_fn(LOG_DEBUG,"Sending relay cell to begin stream %d.",ap_conn->stream_id);
@@ -670,7 +825,7 @@
   if (answer_type == RESOLVED_TYPE_IPV4) {
     uint32_t a = get_uint32(answer);
     if (a)
-      client_dns_set_entry(conn->socks_request->address, ntohl(a));
+      client_dns_set_addressmap(conn->socks_request->address, ntohl(a));
   }
 
   if (conn->socks_request->socks_version == 4) {
@@ -844,6 +999,7 @@
     tor_free(address);
     return 0;
   }
+  tor_strlower(address);
   n_stream->address = address;
   n_stream->state = EXIT_CONN_STATE_RESOLVEFAILED;
   /* default to failed, change in dns_resolve if it turns out not to fail */
@@ -1018,8 +1174,6 @@
  */
 int connection_ap_can_use_exit(connection_t *conn, routerinfo_t *exit)
 {
-  uint32_t addr;
-
   tor_assert(conn);
   tor_assert(conn->type == CONN_TYPE_AP);
   tor_assert(conn->socks_request);
@@ -1042,7 +1196,10 @@
   }
 
   if (conn->socks_request->command != SOCKS_COMMAND_RESOLVE) {
-    addr = client_dns_lookup_entry(conn->socks_request->address);
+    struct in_addr in;
+    uint32_t addr = 0;
+    if (tor_inet_aton(conn->socks_request->address, &in))
+      addr = ntohl(in.s_addr);
     if (router_compare_addr_to_addr_policy(addr, conn->socks_request->port,
           exit->exit_policy) == ADDR_POLICY_REJECTED)
       return 0;
@@ -1098,164 +1255,6 @@
   return 0;
 }
 
-/* ***** Client DNS code ***** */
-
-/* XXX Perhaps this should get merged with the dns.c code somehow. */
-/* XXX But we can't just merge them, because then nodes that act as
- *     both OR and OP could be attacked: people could rig the dns cache
- *     by answering funny things to stream begin requests, and later
- *     other clients would reuse those funny addr's. Hm.
- */
-
-/** A client-side struct to remember the resolved IP (addr) for
- * a given address. These structs make up a tree, with client_dns_map
- * below as its root.
- */
-struct client_dns_entry {
-  uint32_t addr; /**< The resolved IP of this entry. */
-  time_t expires; /**< At what second does addr expire? */
-  int n_failures; /**< How many times has this entry failed to resolve so far? */
-};
-
-/** How many elements are in the client dns cache currently? */
-static int client_dns_size = 0;
-/** The tree of client-side cached DNS resolves. */
-static strmap_t *client_dns_map = NULL;
-
-/** Initialize client_dns_map and client_dns_size. */
-void client_dns_init(void) {
-  client_dns_map = strmap_new();
-  client_dns_size = 0;
-}
-
-/** Return the client_dns_entry that corresponds to <b>address</b>.
- * If it's not there, allocate and return a new entry for <b>address</b>.
- */
-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;
-}
-
-/** Return the IP associated with <b>address</b>, if we know it
- * and it's still fresh enough. Otherwise return 0.
- */
-uint32_t client_dns_lookup_entry(const char *address)
-{
-  struct client_dns_entry *ent;
-  struct in_addr in;
-  time_t now;
-
-  tor_assert(address);
-
-  if (tor_inet_aton(address, &in)) {
-    log_fn(LOG_DEBUG, "Using static address %s (%08lX)", address,
-           (unsigned long)ntohl(in.s_addr));
-    return ntohl(in.s_addr);
-  }
-  ent = strmap_get_lc(client_dns_map,address);
-  if (!ent || !ent->addr) {
-    log_fn(LOG_DEBUG, "No entry found for address %s", address);
-    return 0;
-  } else {
-    now = time(NULL);
-    if (ent->expires < now) {
-      log_fn(LOG_DEBUG, "Expired entry found for address %s", address);
-      strmap_remove_lc(client_dns_map,address);
-      tor_free(ent);
-      --client_dns_size;
-      return 0;
-    }
-    in.s_addr = htonl(ent->addr);
-    log_fn(LOG_DEBUG, "Found cached entry for address %s: %s", address,
-           inet_ntoa(in));
-    return ent->addr;
-  }
-}
-
-/** An attempt to resolve <b>address</b> failed at some OR.
- * Increment the number of resolve failures we have on record
- * for it, and then return that number.
- */
-int client_dns_incr_failures(const char *address)
-{
-  struct client_dns_entry *ent;
-  ent = _get_or_create_ent(address);
-  ++ent->n_failures;
-  log_fn(LOG_DEBUG,"Address %s now has %d resolve failures.",
-         address, ent->n_failures);
-  return ent->n_failures;
-}
-
-/** Record the fact that <b>address</b> resolved to <b>val</b>.
- * We can now use this in subsequent streams in client_dns_lookup_entry(),
- * so we can more correctly choose a router that will allow <b>address</b>
- * to exit from him.
- */
-void client_dns_set_entry(const char *address, uint32_t val)
-{
-  struct client_dns_entry *ent;
-  struct in_addr in;
-  time_t now;
-
-  tor_assert(address);
-  tor_assert(val);
-
-  if (tor_inet_aton(address, &in))
-    return;
-  now = time(NULL);
-  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;
-}
-
-/** A helper function for client_dns_clean() below. If ent is too old,
- * then remove it from the tree and return NULL, else return ent.
- */
-static void* _remove_if_expired(const char *addr,
-                                struct client_dns_entry *ent,
-                                time_t *nowp)
-{
-  if (ent->expires < *nowp) {
-    --client_dns_size;
-    tor_free(ent);
-    return NULL;
-  } else {
-    return ent;
-  }
-}
-
-/** Clean out entries from the client-side DNS cache that were
- * resolved long enough ago that they are no longer valid.
- */
-void client_dns_clean(void)
-{
-  time_t now;
-
-  if (!client_dns_size)
-    return;
-  now = time(NULL);
-  strmap_foreach(client_dns_map, (strmap_foreach_fn)_remove_if_expired, &now);
-}
-
-void client_dns_free_all(void)
-{
-  strmap_free(client_dns_map, free);
-  client_dns_map = NULL;
-}
-
 /** Make connection redirection follow the provided list of
  * exit_redirect_t */
 void
@@ -1284,20 +1283,18 @@
 
     s = strrchr(address,'.');
     if (!s) return 0; /* no dot, thus normal */
-    if (!strcasecmp(s+1,"exit")) {
+    if (!strcmp(s+1,"exit")) {
       *s = 0; /* null-terminate it */
       return EXIT_HOSTNAME; /* .exit */
     }
-    if (strcasecmp(s+1,"onion"))
+    if (strcmp(s+1,"onion"))
       return NORMAL_HOSTNAME; /* neither .exit nor .onion, thus normal */
 
     /* so it is .onion */
     *s = 0; /* null-terminate it */
     if (strlcpy(query, address, REND_SERVICE_ID_LEN+1) >= REND_SERVICE_ID_LEN+1)
       goto failed;
-    tor_strlower(query);
     if (rend_valid_service_id(query)) {
-      tor_strlower(address);
       return ONION_HOSTNAME; /* success */
     }
 failed:

Index: main.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/main.c,v
retrieving revision 1.446
retrieving revision 1.447
diff -u -d -r1.446 -r1.447
--- main.c	11 Feb 2005 01:41:19 -0000	1.446
+++ main.c	22 Feb 2005 00:53:08 -0000	1.447
@@ -1263,7 +1263,7 @@
   rep_hist_init();
   /* Initialize the service cache. */
   rend_cache_init();
-  client_dns_init(); /* Init the client dns cache. Do it always, since it's cheap. */
+  addressmap_init(); /* Init the client dns cache. Do it always, since it's cheap. */
 
   /* give it somewhere to log to initially */
   add_temp_log();
@@ -1308,7 +1308,7 @@
 {
   routerlist_free_current();
   free_trusted_dir_servers();
-  client_dns_free_all();
+  addressmap_free_all();
   free_socks_policy();
   free_dir_policy();
   dirserv_free_all();

Index: or.h
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/or.h,v
retrieving revision 1.535
retrieving revision 1.536
diff -u -d -r1.535 -r1.536
--- or.h	13 Feb 2005 22:31:26 -0000	1.535
+++ or.h	22 Feb 2005 00:53:08 -0000	1.536
@@ -950,6 +950,10 @@
   smartlist_t *FirewallPorts; /**< Which ports our firewall allows (strings). */
   /** Application ports that require all nodes in circ to have sufficient uptime. */
   smartlist_t *LongLivedPorts;
+  /** Should we try to reuse the same exit node for a given host */
+  smartlist_t *TrackHostExits;
+  int TrackHostExitsExpire; /**< Number of seconds until we expire an addressmap */
+  struct config_line_t *AddressMap; /**< List of address map directives. */
   int DirFetchPeriod; /**< How often do we fetch new directories? */
   int DirPostPeriod; /**< How often do we post our server descriptor to the
                       * authoritative directory servers? */
@@ -1212,6 +1216,7 @@
 
 connection_t *connection_get_by_type(int type);
 connection_t *connection_get_by_type_state(int type, int state);
+connection_t *connection_get_by_type_purpose(int type, int purpose);
 connection_t *connection_get_by_type_state_lastwritten(int type, int state);
 connection_t *connection_get_by_type_state_rendquery(int type, int state, const char *rendquery);
 connection_t *connection_get_by_type_purpose(int type, int purpose);
@@ -1258,16 +1263,19 @@
 void connection_ap_expire_beginning(void);
 void connection_ap_attach_pending(void);
 
+void addressmap_init(void);
+void addressmap_clean(time_t now);
+void addressmap_free_all(void);
+void addressmap_rewrite(char *address, size_t maxlen);
+int addressmap_already_mapped(const char *address);
+void addressmap_register(const char *address, char *new_address, time_t expires);
+int client_dns_incr_failures(const char *address);
+void client_dns_set_addressmap(const char *address, uint32_t val);
+
 void parse_socks_policy(void);
 void free_socks_policy(void);
 int socks_policy_permits_address(uint32_t addr);
 
-void client_dns_init(void);
-uint32_t client_dns_lookup_entry(const char *address);
-int client_dns_incr_failures(const char *address);
-void client_dns_set_entry(const char *address, uint32_t val);
-void client_dns_clean(void);
-void client_dns_free_all(void);
 void set_exit_redirects(smartlist_t *lst);
 typedef enum hostname_type_t {
   NORMAL_HOSTNAME, ONION_HOSTNAME, EXIT_HOSTNAME

Index: relay.c
===================================================================
RCS file: /home2/or/cvsroot/tor/src/or/relay.c,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -d -r1.38 -r1.39
--- relay.c	13 Feb 2005 16:17:32 -0000	1.38
+++ relay.c	22 Feb 2005 00:53:08 -0000	1.39
@@ -516,7 +516,7 @@
         connection_mark_for_close(conn);
         return 0;
       }
-      client_dns_set_entry(conn->socks_request->address, addr);
+      client_dns_set_addressmap(conn->socks_request->address, addr);
 
       /* check if he *ought* to have allowed it */
       exitrouter = router_get_by_digest(circ->build_state->chosen_exit_digest);
@@ -589,7 +589,7 @@
         connection_mark_for_close(conn);
         return 0;
       }
-      client_dns_set_entry(conn->socks_request->address, addr);
+      client_dns_set_addressmap(conn->socks_request->address, addr);
     }
     circuit_log_path(LOG_INFO,circ);
     connection_ap_handshake_socks_reply(conn, NULL, 0, 1);