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

[or-cvs] More digest/nickname fixes



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

Modified Files:
	circuitbuild.c circuitlist.c circuituse.c connection.c 
	connection_or.c directory.c or.h rendclient.c rendservice.c 
	router.c routerlist.c routerparse.c test.c 
Log Message:
More digest/nickname fixes

Index: circuitbuild.c
===================================================================
RCS file: /home/or/cvsroot/src/or/circuitbuild.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- circuitbuild.c	2 Jul 2004 23:08:59 -0000	1.6
+++ circuitbuild.c	2 Jul 2004 23:40:03 -0000	1.7
@@ -21,7 +21,7 @@
 static int
 circuit_deliver_create_cell(circuit_t *circ, char *payload);
 static cpath_build_state_t *
-onion_new_cpath_build_state(uint8_t purpose, const char *exit_nickname);
+onion_new_cpath_build_state(uint8_t purpose, const char *exit_digest);
 static int
 onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t
                    *state, routerinfo_t **router_out);
@@ -75,7 +75,7 @@
   tor_assert(CIRCUIT_IS_ORIGIN(circ) && circ->cpath);
 
   snprintf(s, sizeof(buf)-1, "circ (length %d, exit %s): ",
-          circ->build_state->desired_path_len, circ->build_state->chosen_exit);
+          circ->build_state->desired_path_len, circ->build_state->chosen_exit_name);
   hop=circ->cpath;
   do {
     s = buf + strlen(buf);
@@ -148,7 +148,7 @@
   if(CIRCUIT_IS_ORIGIN(circ)) { /* circ starts at this node */
     if(circ->state == CIRCUIT_STATE_BUILDING)
       log(severity,"Building: desired len %d, planned exit node %s.",
-          circ->build_state->desired_path_len, circ->build_state->chosen_exit);
+          circ->build_state->desired_path_len, circ->build_state->chosen_exit_name);
     for(hop=circ->cpath;hop->next != circ->cpath; hop=hop->next)
       log(severity,"hop: state %d, addr 0x%.8x, port %d", hop->state,
           (unsigned int)hop->addr,
@@ -185,7 +185,7 @@
   }
 }
 
-/** Build a new circuit for <b>purpose</b>. If <b>exit_nickname</b>
+/** Build a new circuit for <b>purpose</b>. If <b>exit_digest</b>
  * is defined, then use that as your exit router, else choose a suitable
  * exit node.
  *
@@ -193,14 +193,14 @@
  * it's not open already.
  */
 circuit_t *circuit_establish_circuit(uint8_t purpose,
-                                     const char *exit_nickname) {
+                                     const char *exit_digest) {
   routerinfo_t *firsthop;
   connection_t *n_conn;
   circuit_t *circ;
 
   circ = circuit_new(0, NULL); /* sets circ->p_circ_id and circ->p_conn */
   circ->state = CIRCUIT_STATE_OR_WAIT;
-  circ->build_state = onion_new_cpath_build_state(purpose, exit_nickname);
+  circ->build_state = onion_new_cpath_build_state(purpose, exit_digest);
   circ->purpose = purpose;
 
   if (! circ->build_state) {
@@ -302,6 +302,10 @@
   tor_assert(circ && circ->n_conn && circ->n_conn->type == CONN_TYPE_OR);
   tor_assert(payload);
 
+  /* XXXX008 How can we keep a good upgrade path here?  We should
+   * compare keys, not nicknames...but older servers will compare nicknames.
+   * Should we check server version from the most recent directory? Hm.
+   */
   circ_id_type = decide_circ_id_type(options.Nickname,
                                      circ->n_conn->nickname);
   circ->n_circ_id = get_unique_circ_id_by_conn(circ->n_conn, circ_id_type);
@@ -345,7 +349,7 @@
   if(circ->cpath->state == CPATH_STATE_CLOSED) {
     log_fn(LOG_DEBUG,"First skin; sending create cell.");
 
-    router = router_get_by_nickname(circ->n_conn->nickname);
+    router = router_get_by_digest(circ->n_conn->identity_digest);
     if (!router) {
       log_fn(LOG_WARN,"Couldn't find routerinfo for %s",
              circ->n_conn->nickname);
@@ -945,22 +949,29 @@
  * return it.
  */
 static cpath_build_state_t *
-onion_new_cpath_build_state(uint8_t purpose, const char *exit_nickname)
+onion_new_cpath_build_state(uint8_t purpose, const char *exit_digest)
 {
   routerlist_t *rl;
   int r;
   cpath_build_state_t *info;
   routerinfo_t *exit;
-
   router_get_routerlist(&rl);
   r = new_route_len(options.PathlenCoinWeight, purpose, rl->routers);
   if (r < 0)
     return NULL;
   info = tor_malloc_zero(sizeof(cpath_build_state_t));
   info->desired_path_len = r;
-  if(exit_nickname) { /* the circuit-builder pre-requested one */
-    log_fn(LOG_INFO,"Using requested exit node '%s'", exit_nickname);
-    info->chosen_exit = tor_strdup(exit_nickname);
+  if(exit_digest) { /* the circuit-builder pre-requested one */
+    memcpy(info->chosen_exit_digest, exit_digest, DIGEST_LEN);
+    exit = router_get_by_digest(exit_digest);
+    if (exit) {
+      info->chosen_exit_name = tor_strdup(exit->nickname);
+    } else {
+      info->chosen_exit_name = tor_malloc(HEX_DIGEST_LEN+1);
+      base16_encode(info->chosen_exit_name, HEX_DIGEST_LEN+1,
+                    exit_digest, DIGEST_LEN);
+    }
+    log_fn(LOG_INFO,"Using requested exit node '%s'", info->chosen_exit_name);
   } else { /* we have to decide one */
     exit = choose_good_exit_server(purpose, rl);
     if(!exit) {
@@ -968,7 +979,8 @@
       tor_free(info);
       return NULL;
     }
-    info->chosen_exit = tor_strdup(exit->nickname);
+    memcpy(info->chosen_exit_digest, exit->identity_digest, DIGEST_LEN);
+    info->chosen_exit_name = tor_strdup(exit->nickname);
   }
   return info;
 }
@@ -1091,12 +1103,12 @@
 
   if(cur_len == state->desired_path_len - 1) { /* Picking last node */
     log_fn(LOG_DEBUG, "Contemplating last hop: choice already made: %s",
-           state->chosen_exit);
-    choice = router_get_by_nickname(state->chosen_exit);
+           state->chosen_exit_name);
+    choice = router_get_by_digest(state->chosen_exit_digest);
     smartlist_free(excludednodes);
     if(!choice) {
       log_fn(LOG_WARN,"Our chosen exit %s is no longer in the directory? Discarding this circuit.",
-             state->chosen_exit);
+             state->chosen_exit_name);
       return -1;
     }
   } else if(cur_len == 0) { /* picking first node */
@@ -1104,7 +1116,7 @@
     sl = smartlist_create();
     add_nickname_list_to_smartlist(sl,options.EntryNodes);
     /* XXX one day, consider picking chosen_exit knowing what's in EntryNodes */
-    remove_twins_from_smartlist(sl,router_get_by_nickname(state->chosen_exit));
+    remove_twins_from_smartlist(sl,router_get_by_digest(state->chosen_exit_digest));
     remove_twins_from_smartlist(sl,router_get_my_routerinfo());
     smartlist_subtract(sl,excludednodes);
     choice = smartlist_choose(sl);
@@ -1112,7 +1124,7 @@
     if(!choice) {
       sl = smartlist_create();
       router_add_running_routers_to_smartlist(sl);
-      remove_twins_from_smartlist(sl,router_get_by_nickname(state->chosen_exit));
+      remove_twins_from_smartlist(sl,router_get_by_digest(state->chosen_exit_digest));
       remove_twins_from_smartlist(sl,router_get_my_routerinfo());
       smartlist_subtract(sl,excludednodes);
       choice = smartlist_choose(sl);
@@ -1127,7 +1139,7 @@
     log_fn(LOG_DEBUG, "Contemplating intermediate hop: random choice.");
     sl = smartlist_create();
     router_add_running_routers_to_smartlist(sl);
-    remove_twins_from_smartlist(sl,router_get_by_nickname(state->chosen_exit));
+    remove_twins_from_smartlist(sl,router_get_by_digest(state->chosen_exit_digest));
     remove_twins_from_smartlist(sl,router_get_my_routerinfo());
     for (i = 0, cpath = *head_ptr; i < cur_len; ++i, cpath=cpath->next) {
       r = router_get_by_digest(cpath->identity_digest);
@@ -1145,7 +1157,7 @@
   }
 
   log_fn(LOG_DEBUG,"Chose router %s for hop %d (exit is %s)",
-         choice->nickname, cur_len, state->chosen_exit);
+         choice->nickname, cur_len, state->chosen_exit_name);
 
   hop = tor_malloc_zero(sizeof(crypt_path_t));
 

Index: circuitlist.c
===================================================================
RCS file: /home/or/cvsroot/src/or/circuitlist.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- circuitlist.c	2 Jul 2004 09:29:00 -0000	1.7
+++ circuitlist.c	2 Jul 2004 23:40:03 -0000	1.8
@@ -113,7 +113,7 @@
   if (circ->p_digest)
     crypto_free_digest_env(circ->p_digest);
   if(circ->build_state) {
-    tor_free(circ->build_state->chosen_exit);
+    tor_free(circ->build_state->chosen_exit_name);
     if (circ->build_state->pending_final_cpath)
       circuit_free_cpath_node(circ->build_state->pending_final_cpath);
   }
@@ -361,8 +361,8 @@
     tor_assert(circ->state == CIRCUIT_STATE_OPEN);
     /* treat this like getting a nack from it */
     log_fn(LOG_INFO,"Failed intro circ %s to %s (awaiting ack). Removing from descriptor.",
-           circ->rend_query, circ->build_state->chosen_exit);
-    rend_client_remove_intro_point(circ->build_state->chosen_exit, circ->rend_query);
+           circ->rend_query, circ->build_state->chosen_exit_name);
+    rend_client_remove_intro_point(circ->build_state->chosen_exit_name, circ->rend_query);
   }
 
   if(circ->n_conn)

Index: circuituse.c
===================================================================
RCS file: /home/or/cvsroot/src/or/circuituse.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- circuituse.c	2 Jul 2004 09:29:00 -0000	1.4
+++ circuituse.c	2 Jul 2004 23:40:03 -0000	1.5
@@ -66,7 +66,7 @@
      * circuit, it's the magical extra bob hop. so just check the nickname
      * of the one we meant to finish at.
      */
-    exitrouter = router_get_by_nickname(circ->build_state->chosen_exit);
+    exitrouter = router_get_by_digest(circ->build_state->chosen_exit_digest);
 
     if(!exitrouter) {
       log_fn(LOG_INFO,"Skipping broken circ (exit router vanished)");
@@ -201,12 +201,12 @@
       if(!victim->timestamp_dirty)
         log_fn(LOG_DEBUG,"Considering %sopen purp %d to %s (circid %d). (clean).",
                victim->state == CIRCUIT_STATE_OPEN ? "" : "non",
-               victim->purpose, victim->build_state->chosen_exit,
+               victim->purpose, victim->build_state->chosen_exit_name,
                victim->n_circ_id);
       else
         log_fn(LOG_DEBUG,"Considering %sopen purp %d to %s (circid %d). %d secs since dirty.",
                victim->state == CIRCUIT_STATE_OPEN ? "" : "non",
-               victim->purpose, victim->build_state->chosen_exit,
+               victim->purpose, victim->build_state->chosen_exit_name,
                victim->n_circ_id,
                (int)(now - victim->timestamp_dirty));
     }
@@ -266,7 +266,7 @@
        !circ->marked_for_close && circ->purpose == CIRCUIT_PURPOSE_C_GENERAL &&
        (!circ->timestamp_dirty ||
         circ->timestamp_dirty + options.NewCircuitPeriod < now)) {
-      exitrouter = router_get_by_nickname(circ->build_state->chosen_exit);
+      exitrouter = router_get_by_digest(circ->build_state->chosen_exit_digest);
       if(exitrouter && connection_ap_can_use_exit(conn, exitrouter) != ADDR_POLICY_REJECTED)
         if(++num >= MIN_CIRCUITS_HANDLING_STREAM)
           return 1;
@@ -305,7 +305,7 @@
     if(options.RunTesting && circ &&
                circ->timestamp_created + TESTING_CIRCUIT_INTERVAL < now) {
       log_fn(LOG_INFO,"Creating a new testing circuit.");
-      circuit_launch_new(CIRCUIT_PURPOSE_C_GENERAL, NULL);
+      circuit_launch_by_identity(CIRCUIT_PURPOSE_C_GENERAL, NULL);
     }
   }
 
@@ -318,7 +318,7 @@
    * go ahead and try another. */
   if(!circ && circuit_count_building(CIRCUIT_PURPOSE_C_GENERAL)
               < CIRCUIT_MIN_BUILDING_GENERAL) {
-    circuit_launch_new(CIRCUIT_PURPOSE_C_GENERAL, NULL);
+    circuit_launch_by_identity(CIRCUIT_PURPOSE_C_GENERAL, NULL);
   }
 
   /* XXX count idle rendezvous circs and build more */
@@ -565,10 +565,10 @@
       /* Don't increment failure count, since Alice may have picked
        * the rendezvous point maliciously */
       if (failed_at_last_hop) {
-        log_fn(LOG_INFO,"Couldn't connect to Alice's chosen rend point %s. Sucks to be Alice.", circ->build_state->chosen_exit);
+        log_fn(LOG_INFO,"Couldn't connect to Alice's chosen rend point %s. Sucks to be Alice.", circ->build_state->chosen_exit_name);
       } else {
         log_fn(LOG_INFO,"Couldn't connect to Alice's chosen rend point %s, because an earlier node failed.",
-               circ->build_state->chosen_exit);
+               circ->build_state->chosen_exit_name);
         rend_service_relaunch_rendezvous(circ);
       }
       break;
@@ -588,9 +588,8 @@
  * success. */
 #define MAX_CIRCUIT_FAILURES 5
 
-/** Launch a new circuit and return a pointer to it. Return NULL if you failed. */
-circuit_t *circuit_launch_new(uint8_t purpose, const char *exit_nickname) {
-
+circuit_t *circuit_launch_by_identity(uint8_t purpose, const char *exit_digest)
+{
   if (n_circuit_failures > MAX_CIRCUIT_FAILURES) {
     /* too many failed circs in a row. don't try. */
 //    log_fn(LOG_INFO,"%d failures so far, not trying.",n_circuit_failures);
@@ -598,7 +597,23 @@
   }
 
   /* try a circ. if it fails, circuit_mark_for_close will increment n_circuit_failures */
-  return circuit_establish_circuit(purpose, exit_nickname);
+  return circuit_establish_circuit(purpose, exit_digest);
+}
+
+/** Launch a new circuit and return a pointer to it. Return NULL if you failed. */
+circuit_t *circuit_launch_by_nickname(uint8_t purpose, const char *exit_nickname)
+{
+  const char *digest = NULL;
+
+  if (exit_nickname) {
+    routerinfo_t *r = router_get_by_nickname(exit_nickname);
+    if (!r) {
+      log_fn(LOG_WARN, "No such OR as '%s'", exit_nickname);
+      return NULL;
+    }
+    digest = r->identity_digest;
+  }
+  return circuit_launch_by_identity(purpose, digest);
 }
 
 /** Record another failure at opening a general circuit. When we have
@@ -682,7 +697,7 @@
     else
       new_circ_purpose = desired_circuit_purpose;
 
-    circ = circuit_launch_new(new_circ_purpose, exitname);
+    circ = circuit_launch_by_nickname(new_circ_purpose, exitname);
     tor_free(exitname);
 
     if(circ &&

Index: connection.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection.c,v
retrieving revision 1.233
retrieving revision 1.234
diff -u -d -r1.233 -r1.234
--- connection.c	1 Jul 2004 01:16:58 -0000	1.233
+++ connection.c	2 Jul 2004 23:40:03 -0000	1.234
@@ -712,7 +712,7 @@
        conn->state == DIR_CONN_STATE_CONNECTING) {
        /* it's a directory server and connecting failed: forget about this router */
        /* XXX I suspect pollerr may make Windows not get to this point. :( */
-       router_mark_as_down(conn->nickname);
+       router_mark_as_down(conn->identity_digest);
     }
     /* There's a read error; kill the connection.*/
     connection_close_immediate(conn); /* Don't flush; connection is dead. */
@@ -828,8 +828,9 @@
         log_fn(LOG_DEBUG,"in-progress connect failed. Removing.");
         connection_close_immediate(conn);
         connection_mark_for_close(conn);
-        if (conn->nickname)
-          router_mark_as_down(conn->nickname);
+        /* Previously we tested conn->nickname; is this right? */
+        if (conn->type == CONN_TYPE_OR)
+          router_mark_as_down(conn->identity_digest);
         return -1;
       } else {
         return 0; /* no change, see if next time is better */

Index: connection_or.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_or.c,v
retrieving revision 1.112
retrieving revision 1.113
diff -u -d -r1.112 -r1.113
--- connection_or.c	2 Jul 2004 09:29:00 -0000	1.112
+++ connection_or.c	2 Jul 2004 23:40:03 -0000	1.113
@@ -304,6 +304,8 @@
   }
   log_fn(LOG_DEBUG,"The router's cert is valid.");
 
+  /* XXXX008 This isn't right; fix this one we launch by identity digest
+   * XXXX008 rather than by nickname */
   if (conn->nickname) {
     /* I initiated this connection. */
     if (strcasecmp(conn->nickname, nickname)) {

Index: directory.c
===================================================================
RCS file: /home/or/cvsroot/src/or/directory.c,v
retrieving revision 1.112
retrieving revision 1.113
diff -u -d -r1.112 -r1.113
--- directory.c	1 Jul 2004 01:16:58 -0000	1.112
+++ directory.c	2 Jul 2004 23:40:03 -0000	1.113
@@ -149,7 +149,7 @@
     /* then we want to connect directly */
     switch(connection_connect(conn, conn->address, conn->addr, conn->port)) {
       case -1:
-        router_mark_as_down(conn->nickname); /* don't try him again */
+        router_mark_as_down(conn->identity_digest); /* don't try him again */
         connection_free(conn);
         return;
       case 1:

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.374
retrieving revision 1.375
diff -u -d -r1.374 -r1.375
--- or.h	2 Jul 2004 09:29:00 -0000	1.374
+++ or.h	2 Jul 2004 23:40:03 -0000	1.375
@@ -674,7 +674,9 @@
   /** Intended length of the final circuit. */
   int desired_path_len;
   /** Nickname of planned exit node. */
-  char *chosen_exit;
+  char *chosen_exit_name;
+  /** Identity of planned exit node. */
+  char chosen_exit_digest[DIGEST_LEN];
   /** The crypt_path_t to append after rendezvous: used for rendezvous. */
   struct crypt_path_t *pending_final_cpath;
   /** How many times has building a circuit for this task failed? */
@@ -919,7 +921,7 @@
 void circuit_rep_hist_note_result(circuit_t *circ);
 void circuit_dump_by_conn(connection_t *conn, int severity);
 circuit_t *circuit_establish_circuit(uint8_t purpose,
-                                     const char *exit_nickname);
+                                     const char *exit_digest);
 void circuit_n_conn_done(connection_t *or_conn, int success);
 int circuit_send_next_onion_skin(circuit_t *circ);
 int circuit_extend(cell_t *cell, circuit_t *circ);
@@ -968,7 +970,8 @@
 void circuit_about_to_close_connection(connection_t *conn);
 void circuit_has_opened(circuit_t *circ);
 void circuit_build_failed(circuit_t *circ);
-circuit_t *circuit_launch_new(uint8_t purpose, const char *exit_nickname);
+circuit_t *circuit_launch_by_nickname(uint8_t purpose, const char *exit_nickname);
+circuit_t *circuit_launch_by_identity(uint8_t purpose, const char *exit_digest);
 void circuit_reset_failure_count(void);
 int connection_ap_handshake_attach_circuit(connection_t *conn);
 
@@ -1346,6 +1349,7 @@
 struct smartlist_t;
 void add_nickname_list_to_smartlist(struct smartlist_t *sl, const char *list);
 void router_add_running_routers_to_smartlist(struct smartlist_t *sl);
+int router_nickname_matches(routerinfo_t *router, const char *nickname);
 routerinfo_t *router_choose_random_node(char *preferred, char *excluded,
                                         struct smartlist_t *excludedsmartlist);
 routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port);
@@ -1357,7 +1361,7 @@
 void routerlist_clear_trusted_directories(void);
 void routerinfo_free(routerinfo_t *router);
 routerinfo_t *routerinfo_copy(const routerinfo_t *router);
-void router_mark_as_down(char *nickname);
+void router_mark_as_down(const char *digest);
 void routerlist_remove_old_routers(void);
 int router_load_routerlist_from_file(char *routerfile, int trusted);
 int router_load_routerlist_from_string(const char *s, int trusted);

Index: rendclient.c
===================================================================
RCS file: /home/or/cvsroot/src/or/rendclient.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -d -r1.52 -r1.53
--- rendclient.c	13 May 2004 07:24:49 -0000	1.52
+++ rendclient.c	2 Jul 2004 23:40:03 -0000	1.53
@@ -90,7 +90,7 @@
   }
 
   /* write the remaining items into tmp */
-  strncpy(tmp, rendcirc->build_state->chosen_exit, (MAX_NICKNAME_LEN+1)); /* nul pads */
+  strncpy(tmp, rendcirc->build_state->chosen_exit_name, (MAX_NICKNAME_LEN+1)); /* nul pads */
   memcpy(tmp+MAX_NICKNAME_LEN+1, rendcirc->rend_cookie, REND_COOKIE_LEN);
   if (crypto_dh_get_public(cpath->handshake_state,
                            tmp+MAX_NICKNAME_LEN+1+REND_COOKIE_LEN,
@@ -164,7 +164,7 @@
     return -1;
   }
 
-  tor_assert(circ->build_state->chosen_exit);
+  tor_assert(circ->build_state->chosen_exit_name);
 
   if (request_len == 0) {
     /* It's an ACK; the introduction point relayed our introduction request. */
@@ -187,14 +187,15 @@
      * points. If any remain, extend to a new one and try again.
      * If none remain, refetch the service descriptor.
      */
-    if(rend_client_remove_intro_point(circ->build_state->chosen_exit,
+    if(rend_client_remove_intro_point(circ->build_state->chosen_exit_name,
                                       circ->rend_query) > 0) {
       /* There are introduction points left. re-extend the circuit to
        * another intro point and try again. */
+      routerinfo_t *r;
       nickname = rend_client_get_random_intro(circ->rend_query);
       tor_assert(nickname);
-      log_fn(LOG_INFO,"Got nack for %s from %s, extending to %s.", circ->rend_query, circ->build_state->chosen_exit, nickname);
-      if (!router_get_by_nickname(nickname)) {
+      log_fn(LOG_INFO,"Got nack for %s from %s, extending to %s.", circ->rend_query, circ->build_state->chosen_exit_name, nickname);
+      if (!(r = router_get_by_nickname(nickname))) {
         log_fn(LOG_WARN, "Advertised intro point '%s' for %s is not known. Closing.",
                nickname, circ->rend_query);
         circuit_mark_for_close(circ);
@@ -203,8 +204,9 @@
       log_fn(LOG_INFO, "Chose new intro point %s for %s (circ %d)",
              nickname, circ->rend_query, circ->n_circ_id);
       circ->state = CIRCUIT_STATE_BUILDING;
-      tor_free(circ->build_state->chosen_exit);
-      circ->build_state->chosen_exit = tor_strdup(nickname);
+      tor_free(circ->build_state->chosen_exit_name);
+      circ->build_state->chosen_exit_name = tor_strdup(nickname);
+      memcpy(circ->build_state->chosen_exit_digest, r->identity_digest, DIGEST_LEN);
       ++circ->build_state->desired_path_len;
       if (circuit_send_next_onion_skin(circ)<0) {
         log_fn(LOG_WARN, "Couldn't extend circuit to new intro point.");

Index: rendservice.c
===================================================================
RCS file: /home/or/cvsroot/src/or/rendservice.c,v
retrieving revision 1.72
retrieving revision 1.73
diff -u -d -r1.72 -r1.73
--- rendservice.c	2 Jun 2004 19:44:41 -0000	1.72
+++ rendservice.c	2 Jul 2004 23:40:03 -0000	1.73
@@ -437,7 +437,7 @@
 
   /* Launch a circuit to alice's chosen rendezvous point.
    */
-  launched = circuit_launch_new(CIRCUIT_PURPOSE_S_CONNECT_REND, rp_nickname);
+  launched = circuit_launch_by_nickname(CIRCUIT_PURPOSE_S_CONNECT_REND, rp_nickname);
   log_fn(LOG_INFO,
         "Accepted intro; launching circuit to '%s' (cookie %s) for service %s",
          rp_nickname, hexcookie, serviceid);
@@ -487,18 +487,18 @@
   if (!oldcirc->build_state ||
       oldcirc->build_state->failure_count > MAX_REND_FAILURES) {
     log_fn(LOG_INFO,"Attempt to build circuit to %s for rendezvous has failed too many times; giving up.",
-           oldcirc->build_state->chosen_exit);
+           oldcirc->build_state->chosen_exit_name);
     return;
   }
 
   log_fn(LOG_INFO,"Reattempting rendezvous circuit to %s",
-         oldcirc->build_state->chosen_exit);
+         oldcirc->build_state->chosen_exit_name);
 
-  newcirc = circuit_launch_new(CIRCUIT_PURPOSE_S_CONNECT_REND,
-                               oldcirc->build_state->chosen_exit);
+  newcirc = circuit_launch_by_nickname(CIRCUIT_PURPOSE_S_CONNECT_REND,
+                               oldcirc->build_state->chosen_exit_name);
   if (!newcirc) {
     log_fn(LOG_WARN,"Couldn't relaunch rendezvous circuit to %s",
-           oldcirc->build_state->chosen_exit);
+           oldcirc->build_state->chosen_exit_name);
     return;
   }
   oldstate = oldcirc->build_state;
@@ -525,7 +525,7 @@
          nickname, service->service_id);
 
   ++service->n_intro_circuits_launched;
-  launched = circuit_launch_new(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, nickname);
+  launched = circuit_launch_by_nickname(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, nickname);
   if (!launched) {
     log_fn(LOG_WARN, "Can't launch circuit to establish introduction at '%s'",
            nickname);
@@ -715,8 +715,8 @@
   while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
                                                   CIRCUIT_PURPOSE_S_INTRO))) {
     tor_assert(circ->cpath);
-    if (circ->build_state->chosen_exit &&
-        !strcasecmp(circ->build_state->chosen_exit, router->nickname)) {
+    if (circ->build_state->chosen_exit_name &&
+        !strcasecmp(circ->build_state->chosen_exit_name, router->nickname)) {
       return circ;
     }
   }
@@ -725,8 +725,8 @@
   while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
                                         CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
     tor_assert(circ->cpath);
-    if (circ->build_state->chosen_exit &&
-        !strcasecmp(circ->build_state->chosen_exit, router->nickname)) {
+    if (circ->build_state->chosen_exit_name &&
+        !strcasecmp(circ->build_state->chosen_exit_name, router->nickname)) {
       return circ;
     }
   }

Index: router.c
===================================================================
RCS file: /home/or/cvsroot/src/or/router.c,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -d -r1.57 -r1.58
--- router.c	2 Jul 2004 09:29:01 -0000	1.57
+++ router.c	2 Jul 2004 23:40:03 -0000	1.58
@@ -394,6 +394,7 @@
 int router_is_me(routerinfo_t *router)
 {
   tor_assert(router);
+  /* XXXX008 should compare identity instead? */
   return options.Nickname && !strcasecmp(router->nickname, options.Nickname);
 }
 

Index: routerlist.c
===================================================================
RCS file: /home/or/cvsroot/src/or/routerlist.c,v
retrieving revision 1.91
retrieving revision 1.92
diff -u -d -r1.91 -r1.92
--- routerlist.c	1 Jul 2004 23:13:04 -0000	1.91
+++ routerlist.c	2 Jul 2004 23:40:03 -0000	1.92
@@ -207,19 +207,46 @@
   return NULL;
 }
 
+/* DOCDOC */
+static INLINE int router_hex_digest_matches(routerinfo_t *router,
+                                     const char *hexdigest)
+{
+  char digest[DIGEST_LEN];
+  tor_assert(hexdigest);
+  if (hexdigest[0] == '$')
+    ++hexdigest;
+
+  if (base16_decode(digest, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0)
+    return 0;
+  else
+    return (!memcmp(digest, router->identity_digest, DIGEST_LEN));
+}
+
+/* DOCDOC */
+int router_nickname_matches(routerinfo_t *router, const char *nickname)
+{
+  if (nickname[0]!='$' && !strcasecmp(router->nickname, nickname))
+    return 1;
+  else
+    return router_hex_digest_matches(router, nickname);
+}
+
 /** Return the router in our routerlist whose (case-insensitive)
  * nickname or (case-sensitive) hexadecimal key digest is
  * <b>nickname</b>.  Return NULL if no such router is known.
  */
 routerinfo_t *router_get_by_nickname(const char *nickname)
 {
-  int i, maybedigest;
+  int i, maybedigest, mustbedigest;
   routerinfo_t *router;
   char digest[DIGEST_LEN];
 
   tor_assert(nickname);
   if (!routerlist)
     return NULL;
+  if (nickname[0] == '$')
+    return router_get_by_hexdigest(nickname);
+
   maybedigest = (strlen(nickname) == HEX_DIGEST_LEN) &&
     (base16_decode(digest,DIGEST_LEN,nickname,HEX_DIGEST_LEN) == 0);
 
@@ -242,6 +269,8 @@
   tor_assert(hexdigest);
   if (!routerlist)
     return NULL;
+  if (hexdigest[0]=='$')
+    ++hexdigest;
   if (strlen(hexdigest) != HEX_DIGEST_LEN ||
       base16_decode(digest,DIGEST_LEN,hexdigest,HEX_DIGEST_LEN) < 0)
     return NULL;
@@ -326,10 +355,10 @@
 }
 
 /** Mark the router named <b>nickname</b> as non-running in our routerlist. */
-void router_mark_as_down(char *nickname) {
+void router_mark_as_down(const char *digest) {
   routerinfo_t *router;
-  tor_assert(nickname);
-  router = router_get_by_nickname(nickname);
+  tor_assert(digest);
+  router = router_get_by_digest(digest);
   if(!router) /* we don't seem to know about him in the first place */
     return;
   log_fn(LOG_DEBUG,"Marking %s as down.",router->nickname);
@@ -350,6 +379,7 @@
    */
   for (i = 0; i < smartlist_len(routerlist->routers); ++i) {
     r = smartlist_get(routerlist->routers, i);
+    /* XXXX008 should just compare digests instead. */
     if (!strcasecmp(router->nickname, r->nickname)) {
       if (!crypto_pk_cmp_keys(router->identity_pkey, r->identity_pkey)) {
         if (router->published_on > r->published_on) {
@@ -377,6 +407,8 @@
           return -1;
         }
       } else {
+        /* XXXX008 It's okay to have two keys for a nickname as soon as
+         * all the 007 clients are dead. */
         log_fn(LOG_WARN, "Identity key mismatch for router '%s'",
                router->nickname);
         routerinfo_free(router);
@@ -698,13 +730,16 @@
     router = smartlist_get(list->routers, i);
     for (j=0; j<n_names; ++j) {
       name = smartlist_get(rr->running_routers, j);
-      if (!strcasecmp(name, router->nickname)) {
-        router->is_running = 1;
-        break;
-      }
-      if (*name == '!' && strcasecmp(name+1, router->nickname)) {
-        router->is_running = 0;
-        break;
+      if (*name != '!') {
+        if (router_nickname_matches(router, name)) {
+          router->is_running = 1;
+          break;
+        }
+      } else { /* *name == '!' */
+        if (router_nickname_matches(router, name)) {
+          router->is_running = 0;
+          break;
+        }
       }
     }
   }

Index: routerparse.c
===================================================================
RCS file: /home/or/cvsroot/src/or/routerparse.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- routerparse.c	1 Jul 2004 01:16:59 -0000	1.8
+++ routerparse.c	2 Jul 2004 23:40:03 -0000	1.9
@@ -539,7 +539,7 @@
 int
 router_parse_list_from_string(const char **s, routerlist_t **dest,
 			      int n_good_nicknames,
-			      const char **good_nickname_lst)
+			      const char **good_nickname_list)
 {
   routerinfo_t *router;
   smartlist_t *routers;
@@ -574,7 +574,7 @@
     if (n_good_nicknames>=0) {
       router->is_running = 0;
       for (i = 0; i < n_good_nicknames; ++i) {
-        if (0==strcasecmp(good_nickname_lst[i], router->nickname)) {
+        if (router_nickname_matches(router, good_nickname_list[i])) {
           router->is_running = 1;
           break;
         }

Index: test.c
===================================================================
RCS file: /home/or/cvsroot/src/or/test.c,v
retrieving revision 1.95
retrieving revision 1.96
diff -u -d -r1.95 -r1.96
--- test.c	21 Jun 2004 04:37:27 -0000	1.95
+++ test.c	2 Jul 2004 23:40:03 -0000	1.96
@@ -420,6 +420,17 @@
   test_eq(i,0);
   test_streq(data2, "772w2rfobvomsywe");
 
+  /* Base16 tests */
+  strcpy(data1, "6chrs\xff");
+  i = base16_encode(data2, 13, data1, 6);
+  test_eq(i,0);
+  test_streq(data2, "3663687273FF");
+
+  strcpy(data1, "f0d678affc000100");
+  i = base16_decode(data2, 8, data1, 16);
+  test_eq(i,0);
+  test_memeq(data2, "\xf0\xd6\x78\xaf\xfc\x00\x01\x00",8);
+
   free(data1);
   free(data2);
   free(data3);