Przeglądaj źródła

Initial conversion to use node_t throughout our codebase.

A node_t is an abstraction over routerstatus_t, routerinfo_t, and
microdesc_t.  It should try to present a consistent interface to all
of them.  There should be a node_t for a server whenever there is
  * A routerinfo_t for it in the routerlist
  * A routerstatus_t in the current_consensus.
(note that a microdesc_t alone isn't enough to make a node_t exist,
since microdescriptors aren't usable on their own.)

There are three ways to get a node_t right now: looking it up by ID,
looking it up by nickname, and iterating over the whole list of
microdescriptors.

All (or nearly all) functions that are supposed to return "a router"
-- especially those used in building connections and circuits --
should return a node_t, not a routerinfo_t or a routerstatus_t.

A node_t should hold all the *mutable* flags about a node.  This
patch moves the is_foo flags from routerinfo_t into node_t.  The
flags in routerstatus_t remain, but they get set from the consensus
and should not change.

Some other highlights of this patch are:

  * Looking up routerinfo and routerstatus by nickname is now
    unified and based on the "look up a node by nickname" function.
    This tries to look only at the values from current consensus,
    and not get confused by the routerinfo_t->is_named flag, which
    could get set for other weird reasons.  This changes the
    behavior of how authorities (when acting as clients) deal with
    nodes that have been listed by nickname.

  * I tried not to artificially increase the size of the diff here
    by moving functions around.  As a result, some functions that
    now operate on nodes are now in the wrong file -- they should
    get moved to nodelist.c once this refactoring settles down.
    This moving should happen as part of a patch that moves
    functions AND NOTHING ELSE.

  * Some old code is now left around inside #if 0/1 blocks, and
    should get removed once I've verified that I don't want it
    sitting around to see how we used to do things.

There are still some unimplemented functions: these are flagged
with "UNIMPLEMENTED_NODELIST()."  I'll work on filling in the
implementation here, piece by piece.

I wish this patch could have been smaller, but there did not seem to
be any piece of it that was independent from the rest.  Moving flags
forces many functions that once returned routerinfo_t * to return
node_t *, which forces their friends to change, and so on.
Nick Mathewson 13 lat temu
rodzic
commit
26e897420e

+ 10 - 0
changes/nodelist

@@ -0,0 +1,10 @@
+  o Code refactorings
+    - Unified our node-listing and selecting logic.  We had at least
+      two major ways to look at the question of "which Tor servers do
+      we know about": our list of router descriptors, and the current
+      consensus.  We're adding a third in microdescriptors.  Having
+      so many systems without an abstraction layer over them was
+      hurting the codebase.  Now, we have a new "node_t" abstraction
+      that presents a consistent interface to a client's view of
+      a Tor node, and holds (nearly) all of the mutable state
+      formerly in routerinfo_t and routerstatus_t.

Plik diff jest za duży
+ 214 - 194
src/or/circuitbuild.c


+ 3 - 2
src/or/circuitbuild.h

@@ -45,9 +45,10 @@ extend_info_t *extend_info_alloc(const char *nickname, const char *digest,
                                  crypto_pk_env_t *onion_key,
                                  const tor_addr_t *addr, uint16_t port);
 extend_info_t *extend_info_from_router(const routerinfo_t *r);
+extend_info_t *extend_info_from_node(const node_t *node);
 extend_info_t *extend_info_dup(extend_info_t *info);
 void extend_info_free(extend_info_t *info);
-const routerinfo_t *build_state_get_exit_router(cpath_build_state_t *state);
+const node_t *build_state_get_exit_node(cpath_build_state_t *state);
 const char *build_state_get_exit_nickname(cpath_build_state_t *state);
 
 void entry_guards_compute_status(or_options_t *options, time_t now);
@@ -55,7 +56,7 @@ int entry_guard_register_connect_status(const char *digest, int succeeded,
                                         int mark_relay_status, time_t now);
 void entry_nodes_should_be_added(void);
 int entry_list_is_constrained(or_options_t *options);
-const routerinfo_t *choose_random_entry(cpath_build_state_t *state);
+const node_t *choose_random_entry(cpath_build_state_t *state);
 int entry_guards_parse_state(or_state_t *state, int set, char **msg);
 void entry_guards_update_state(or_state_t *state);
 int getinfo_helper_entry_guards(control_connection_t *conn,

+ 5 - 4
src/or/circuitlist.c

@@ -19,6 +19,7 @@
 #include "connection_or.h"
 #include "control.h"
 #include "networkstatus.h"
+#include "nodelist.h"
 #include "onion.h"
 #include "relay.h"
 #include "rendclient.h"
@@ -946,15 +947,15 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
         if (info) {
           /* need to make sure we don't duplicate hops */
           crypt_path_t *hop = circ->cpath;
-          const routerinfo_t *ri1 = router_get_by_digest(info->identity_digest);
+          const node_t *ri1 = node_get_by_id(info->identity_digest);
           do {
-            const routerinfo_t *ri2;
+            const node_t *ri2;
             if (!memcmp(hop->extend_info->identity_digest,
                         info->identity_digest, DIGEST_LEN))
               goto next;
             if (ri1 &&
-                (ri2 = router_get_by_digest(hop->extend_info->identity_digest))
-                && routers_in_same_family(ri1, ri2))
+                (ri2 = node_get_by_id(hop->extend_info->identity_digest))
+                && nodes_in_same_family(ri1, ri2))
               goto next;
             hop=hop->next;
           } while (hop!=circ->cpath);

+ 29 - 37
src/or/circuituse.c

@@ -17,6 +17,7 @@
 #include "connection.h"
 #include "connection_edge.h"
 #include "control.h"
+#include "nodelist.h"
 #include "policies.h"
 #include "rendclient.h"
 #include "rendcommon.h"
@@ -43,7 +44,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
                       int need_uptime, int need_internal,
                       time_t now)
 {
-  const routerinfo_t *exitrouter;
+  const node_t *exitnode;
   cpath_build_state_t *build_state;
   tor_assert(circ);
   tor_assert(conn);
@@ -85,7 +86,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
    * of the one we meant to finish at.
    */
   build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
-  exitrouter = build_state_get_exit_router(build_state);
+  exitnode = build_state_get_exit_node(build_state);
 
   if (need_uptime && !build_state->need_uptime)
     return 0;
@@ -93,7 +94,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
     return 0;
 
   if (purpose == CIRCUIT_PURPOSE_C_GENERAL) {
-    if (!exitrouter && !build_state->onehop_tunnel) {
+    if (!exitnode && !build_state->onehop_tunnel) {
       log_debug(LD_CIRC,"Not considering circuit with unknown router.");
       return 0; /* this circuit is screwed and doesn't know it yet,
                  * or is a rendezvous circuit. */
@@ -127,7 +128,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
         return 0;
       }
     }
-    if (exitrouter && !connection_ap_can_use_exit(conn, exitrouter, 0)) {
+    if (exitnode && !connection_ap_can_use_exit(conn, exitnode, 0)) {
       /* can't exit from this router */
       return 0;
     }
@@ -473,7 +474,7 @@ circuit_stream_is_being_handled(edge_connection_t *conn,
                                 uint16_t port, int min)
 {
   circuit_t *circ;
-  const routerinfo_t *exitrouter;
+  const node_t *exitnode;
   int num=0;
   time_t now = time(NULL);
   int need_uptime = smartlist_string_num_isin(get_options()->LongLivedPorts,
@@ -489,14 +490,14 @@ circuit_stream_is_being_handled(edge_connection_t *conn,
       if (build_state->is_internal || build_state->onehop_tunnel)
         continue;
 
-      exitrouter = build_state_get_exit_router(build_state);
-      if (exitrouter && (!need_uptime || build_state->need_uptime)) {
+      exitnode = build_state_get_exit_node(build_state);
+      if (exitnode && (!need_uptime || build_state->need_uptime)) {
         int ok;
         if (conn) {
-          ok = connection_ap_can_use_exit(conn, exitrouter, 0);
+          ok = connection_ap_can_use_exit(conn, exitnode, 0);
         } else {
-          addr_policy_result_t r = compare_addr_to_addr_policy(
-              0, port, exitrouter->exit_policy);
+          addr_policy_result_t r;
+          r = compare_addr_to_node_policy(0, port, exitnode);
           ok = r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED;
         }
         if (ok) {
@@ -563,7 +564,7 @@ circuit_predict_and_launch_new(void)
     log_info(LD_CIRC,
              "Have %d clean circs (%d internal), need another exit circ.",
              num, num_internal);
-    circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+    circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
     return;
   }
 
@@ -575,7 +576,7 @@ circuit_predict_and_launch_new(void)
              "Have %d clean circs (%d internal), need another internal "
              "circ for my hidden service.",
              num, num_internal);
-    circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+    circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
     return;
   }
 
@@ -593,7 +594,7 @@ circuit_predict_and_launch_new(void)
              "Have %d clean circs (%d uptime-internal, %d internal), need"
              " another hidden service circ.",
              num, num_uptime_internal, num_internal);
-    circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+    circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
     return;
   }
 
@@ -606,7 +607,7 @@ circuit_predict_and_launch_new(void)
     flags = CIRCLAUNCH_NEED_CAPACITY;
     log_info(LD_CIRC,
              "Have %d clean circs need another buildtime test circ.", num);
-    circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+    circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
     return;
   }
 }
@@ -644,7 +645,7 @@ circuit_build_needed_circs(time_t now)
         circ &&
         circ->timestamp_created + TESTING_CIRCUIT_INTERVAL < now) {
       log_fn(LOG_INFO,"Creating a new testing circuit.");
-      circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, 0);
+      circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, 0);
     }
 #endif
   }
@@ -1076,17 +1077,9 @@ static int did_circs_fail_last_period = 0;
 /** Launch a new circuit; see circuit_launch_by_extend_info() for
  * details on arguments. */
 origin_circuit_t *
-circuit_launch_by_router(uint8_t purpose,
-                         const routerinfo_t *exit, int flags)
+circuit_launch(uint8_t purpose, int flags)
 {
-  origin_circuit_t *circ;
-  extend_info_t *info = NULL;
-  if (exit)
-    info = extend_info_from_router(exit);
-  circ = circuit_launch_by_extend_info(purpose, info, flags);
-
-  extend_info_free(info);
-  return circ;
+  return circuit_launch_by_extend_info(purpose, NULL, flags);
 }
 
 /** Launch a new circuit with purpose <b>purpose</b> and exit node
@@ -1256,9 +1249,9 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
       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)) {
+      if (router_exit_policy_all_nodes_reject(addr,
+                                              conn->socks_request->port,
+                                              need_uptime)) {
         log_notice(LD_APP,
                    "No Tor server allows exit to %s:%d. Rejecting.",
                    safe_str_client(conn->socks_request->address),
@@ -1267,10 +1260,9 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
       }
     } else {
       /* XXXX022 Duplicates checks in connection_ap_handshake_attach_circuit */
-      const routerinfo_t *router =
-        router_get_by_nickname(conn->chosen_exit_name, 1);
+      const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1);
       int opt = conn->chosen_exit_optional;
-      if (router && !connection_ap_can_use_exit(conn, router, 0)) {
+      if (node && !connection_ap_can_use_exit(conn, node, 0)) {
         log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
                "Requested exit point '%s' would refuse request. %s.",
                conn->chosen_exit_name, opt ? "Trying others" : "Closing");
@@ -1318,11 +1310,11 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
      */
     if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) {
       if (conn->chosen_exit_name) {
-        const routerinfo_t *r;
+        const node_t *r;
         int opt = conn->chosen_exit_optional;
-        r = router_get_by_nickname(conn->chosen_exit_name, 1);
+        r = node_get_by_nickname(conn->chosen_exit_name, 1);
         if (r) {
-          extend_info = extend_info_from_router(r);
+          extend_info = extend_info_from_node(r);
         } else {
           log_debug(LD_DIR, "considering %d, %s",
                     want_onehop, conn->chosen_exit_name);
@@ -1572,9 +1564,9 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
     origin_circuit_t *circ=NULL;
 
     if (conn->chosen_exit_name) {
-      const routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1);
+      const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1);
       int opt = conn->chosen_exit_optional;
-      if (!router && !want_onehop) {
+      if (!node && !want_onehop) {
         /* We ran into this warning when trying to extend a circuit to a
          * hidden service directory for which we didn't have a router
          * descriptor. See flyspray task 767 for more details. We should
@@ -1590,7 +1582,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
         }
         return -1;
       }
-      if (router && !connection_ap_can_use_exit(conn, router, 0)) {
+      if (node && !connection_ap_can_use_exit(conn, node, 0)) {
         log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
                "Requested exit point '%s' would refuse request. %s.",
                conn->chosen_exit_name, opt ? "Trying others" : "Closing");

+ 1 - 2
src/or/circuituse.h

@@ -41,8 +41,7 @@ void circuit_build_failed(origin_circuit_t *circ);
 origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
                                                 extend_info_t *info,
                                                 int flags);
-origin_circuit_t *circuit_launch_by_router(uint8_t purpose,
-                                           const routerinfo_t *exit, int flags);
+origin_circuit_t *circuit_launch(uint8_t purpose, int flags);
 void circuit_reset_failure_count(int timeout);
 int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
                                                   origin_circuit_t *circ,

+ 4 - 3
src/or/command.c

@@ -25,6 +25,7 @@
 #include "control.h"
 #include "cpuworker.h"
 #include "hibernate.h"
+#include "nodelist.h"
 #include "onion.h"
 #include "relay.h"
 #include "router.h"
@@ -267,15 +268,15 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn)
   }
 
   if (circuit_id_in_use_on_orconn(cell->circ_id, conn)) {
-    const routerinfo_t *router = router_get_by_digest(conn->identity_digest);
+    const node_t *node = node_get_by_id(conn->identity_digest);
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
            "Received CREATE cell (circID %d) for known circ. "
            "Dropping (age %d).",
            cell->circ_id, (int)(time(NULL) - conn->_base.timestamp_created));
-    if (router)
+    if (node)
       log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
              "Details: nickname \"%s\", platform %s.",
-             router->nickname, escaped(router->platform));
+             node_get_nickname(node), escaped(node_get_platform(node)));
     return;
   }
 

+ 18 - 18
src/or/connection_edge.c

@@ -23,6 +23,7 @@
 #include "dirserv.h"
 #include "hibernate.h"
 #include "main.h"
+#include "nodelist.h"
 #include "policies.h"
 #include "reasons.h"
 #include "relay.h"
@@ -587,7 +588,7 @@ void
 circuit_discard_optional_exit_enclaves(extend_info_t *info)
 {
   edge_connection_t *edge_conn;
-  const routerinfo_t *r1, *r2;
+  const node_t *r1, *r2;
 
   smartlist_t *conns = get_connection_array();
   SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
@@ -599,8 +600,8 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info)
     if (!edge_conn->chosen_exit_optional &&
         !edge_conn->chosen_exit_retries)
       continue;
-    r1 = router_get_by_nickname(edge_conn->chosen_exit_name, 0);
-    r2 = router_get_by_nickname(info->nickname, 0);
+    r1 = node_get_by_nickname(edge_conn->chosen_exit_name, 0);
+    r2 = node_get_by_nickname(info->nickname, 0);
     if (!r1 || !r2 || r1 != r2)
       continue;
     tor_assert(edge_conn->socks_request);
@@ -1575,12 +1576,12 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
         return -1;
       }
     } else {
-      const routerinfo_t *r;
+      const node_t *r;
       conn->chosen_exit_name = tor_strdup(socks->address);
-      r = router_get_by_nickname(conn->chosen_exit_name, 1);
+      r = node_get_by_nickname(conn->chosen_exit_name, 1);
       *socks->address = 0;
       if (r) {
-        strlcpy(socks->address, r->address, sizeof(socks->address));
+        node_get_address_string(r, socks->address, sizeof(socks->address));
       } else {
         log_warn(LD_APP,
                  "Unrecognized server in exit address '%s.exit'. Refusing.",
@@ -1631,16 +1632,16 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
 
       if (!conn->use_begindir && !conn->chosen_exit_name && !circ) {
         /* see if we can find a suitable enclave exit */
-        const routerinfo_t *r =
+        const node_t *r =
           router_find_exact_exit_enclave(socks->address, socks->port);
         if (r) {
           log_info(LD_APP,
                    "Redirecting address %s to exit at enclave router %s",
-                   safe_str_client(socks->address), r->nickname);
+                   safe_str_client(socks->address), node_get_nickname(r));
           /* use the hex digest, not nickname, in case there are two
              routers with this nickname */
           conn->chosen_exit_name =
-            tor_strdup(hex_str(r->cache_info.identity_digest, DIGEST_LEN));
+            tor_strdup(hex_str(r->identity, DIGEST_LEN));
           conn->chosen_exit_optional = 1;
         }
       }
@@ -2896,7 +2897,7 @@ connection_edge_is_rendezvous_stream(edge_connection_t *conn)
  * this relay, return 0.
  */
 int
-connection_ap_can_use_exit(edge_connection_t *conn, const routerinfo_t *exit,
+connection_ap_can_use_exit(edge_connection_t *conn, const node_t *exit,
                            int excluded_means_no)
 {
   or_options_t *options = get_options();
@@ -2910,10 +2911,10 @@ connection_ap_can_use_exit(edge_connection_t *conn, const routerinfo_t *exit,
    * make sure the exit node of the existing circuit matches exactly.
    */
   if (conn->chosen_exit_name) {
-    const routerinfo_t *chosen_exit =
-      router_get_by_nickname(conn->chosen_exit_name, 1);
-    if (!chosen_exit || memcmp(chosen_exit->cache_info.identity_digest,
-                               exit->cache_info.identity_digest, DIGEST_LEN)) {
+    const node_t *chosen_exit =
+      node_get_by_nickname(conn->chosen_exit_name, 1);
+    if (!chosen_exit || memcmp(chosen_exit->identity,
+                               exit->identity, DIGEST_LEN)) {
       /* doesn't match */
 //      log_debug(LD_APP,"Requested node '%s', considering node '%s'. No.",
 //                conn->chosen_exit_name, exit->nickname);
@@ -2928,8 +2929,7 @@ connection_ap_can_use_exit(edge_connection_t *conn, const routerinfo_t *exit,
     addr_policy_result_t r;
     if (tor_inet_aton(conn->socks_request->address, &in))
       addr = ntohl(in.s_addr);
-    r = compare_addr_to_addr_policy(addr, conn->socks_request->port,
-                                    exit->exit_policy);
+    r = compare_addr_to_node_policy(addr, conn->socks_request->port, exit);
     if (r == ADDR_POLICY_REJECTED)
       return 0; /* We know the address, and the exit policy rejects it. */
     if (r == ADDR_POLICY_PROBABLY_REJECTED && !conn->chosen_exit_name)
@@ -2938,12 +2938,12 @@ connection_ap_can_use_exit(edge_connection_t *conn, const routerinfo_t *exit,
                  * this node, err on the side of caution. */
   } else if (SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) {
     /* Don't send DNS requests to non-exit servers by default. */
-    if (!conn->chosen_exit_name && policy_is_reject_star(exit->exit_policy))
+    if (!conn->chosen_exit_name && node_exit_policy_rejects_all(exit))
       return 0;
   }
   if (options->_ExcludeExitNodesUnion &&
       (options->StrictNodes || excluded_means_no) &&
-      routerset_contains_router(options->_ExcludeExitNodesUnion, exit)) {
+      routerset_contains_node(options->_ExcludeExitNodesUnion, exit)) {
     /* If we are trying to avoid this node as exit, and we have StrictNodes
      * set, then this is not a suitable exit. Refuse it.
      *

+ 1 - 1
src/or/connection_edge.h

@@ -48,7 +48,7 @@ int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ);
 void connection_exit_connect(edge_connection_t *conn);
 int connection_edge_is_rendezvous_stream(edge_connection_t *conn);
 int connection_ap_can_use_exit(edge_connection_t *conn,
-                               const routerinfo_t *exit,
+                               const node_t *exit,
                                int excluded_means_no);
 void connection_ap_expire_beginning(void);
 void connection_ap_attach_pending(void);

+ 9 - 6
src/or/connection_or.c

@@ -22,6 +22,7 @@
 #include "geoip.h"
 #include "main.h"
 #include "networkstatus.h"
+#include "nodelist.h"
 #include "reasons.h"
 #include "relay.h"
 #include "rephist.h"
@@ -438,7 +439,7 @@ connection_or_init_conn_from_address(or_connection_t *conn,
                                      const char *id_digest,
                                      int started_here)
 {
-  const routerinfo_t *r = router_get_by_digest(id_digest);
+  const node_t *r = node_get_by_id(id_digest);
   connection_or_set_identity_digest(conn, id_digest);
   connection_or_update_token_buckets_helper(conn, 1, get_options());
 
@@ -446,8 +447,10 @@ connection_or_init_conn_from_address(or_connection_t *conn,
   tor_addr_copy(&conn->_base.addr, addr);
   tor_addr_copy(&conn->real_addr, addr);
   if (r) {
+    tor_addr_t node_addr;
+    node_get_addr(r, &node_addr);
     /* XXXX proposal 118 will make this more complex. */
-    if (tor_addr_eq_ipv4h(&conn->_base.addr, r->addr))
+    if (tor_addr_eq(&conn->_base.addr, &node_addr))
       conn->is_canonical = 1;
     if (!started_here) {
       /* Override the addr/port, so our log messages will make sense.
@@ -460,12 +463,12 @@ connection_or_init_conn_from_address(or_connection_t *conn,
        * right IP address and port 56244, that wouldn't be as helpful. now we
        * log the "right" port too, so we know if it's moria1 or moria2.
        */
-      tor_addr_from_ipv4h(&conn->_base.addr, r->addr);
-      conn->_base.port = r->or_port;
+      tor_addr_copy(&conn->_base.addr, &node_addr);
+      conn->_base.port = node_get_orport(r);
     }
-    conn->nickname = tor_strdup(r->nickname);
+    conn->nickname = tor_strdup(node_get_nickname(r));
     tor_free(conn->_base.address);
-    conn->_base.address = tor_strdup(r->address);
+    conn->_base.address = tor_dup_addr(&node_addr);
   } else {
     const char *n;
     /* If we're an authoritative directory server, we may know a

+ 26 - 20
src/or/control.c

@@ -26,6 +26,7 @@
 #include "hibernate.h"
 #include "main.h"
 #include "networkstatus.h"
+#include "nodelist.h"
 #include "policies.h"
 #include "reasons.h"
 #include "router.h"
@@ -2107,7 +2108,7 @@ static int
 handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
                              const char *body)
 {
-  smartlist_t *router_nicknames=NULL, *routers=NULL;
+  smartlist_t *router_nicknames=NULL, *nodes=NULL;
   origin_circuit_t *circ = NULL;
   int zero_circ;
   uint8_t intended_purpose = CIRCUIT_PURPOSE_C_GENERAL;
@@ -2138,8 +2139,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
     if ((smartlist_len(args) == 1) ||
         (smartlist_len(args) >= 2 && is_keyval_pair(smartlist_get(args, 1)))) {
       // "EXTENDCIRCUIT 0" || EXTENDCIRCUIT 0 foo=bar"
-      circ = circuit_launch_by_router(intended_purpose, NULL,
-                                      CIRCLAUNCH_NEED_CAPACITY);
+      circ = circuit_launch(intended_purpose, CIRCLAUNCH_NEED_CAPACITY);
       if (!circ) {
         connection_write_str_to_buf("551 Couldn't start circuit\r\n", conn);
       } else {
@@ -2167,17 +2167,21 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
   SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
   smartlist_free(args);
 
-  routers = smartlist_create();
+  nodes = smartlist_create();
   SMARTLIST_FOREACH(router_nicknames, const char *, n,
   {
-    const routerinfo_t *r = router_get_by_nickname(n, 1);
-    if (!r) {
+    const node_t *node = node_get_by_nickname(n, 1);
+    if (!node) {
       connection_printf_to_buf(conn, "552 No such router \"%s\"\r\n", n);
       goto done;
     }
-    smartlist_add(routers, (void*) r);
+    if (!node_has_descriptor(node)) {
+      connection_printf_to_buf(conn, "552 descriptor for \"%s\"\r\n", n);
+      goto done;
+    }
+    smartlist_add(nodes, (void*)node);
   });
-  if (!smartlist_len(routers)) {
+  if (!smartlist_len(nodes)) {
     connection_write_str_to_buf("512 No router names provided\r\n", conn);
     goto done;
   }
@@ -2188,9 +2192,10 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
   }
 
   /* now circ refers to something that is ready to be extended */
-  SMARTLIST_FOREACH(routers, const routerinfo_t *, r,
+  SMARTLIST_FOREACH(nodes, const node_t *, node,
   {
-    extend_info_t *info = extend_info_from_router(r);
+    extend_info_t *info = extend_info_from_node(node);
+    tor_assert(info); /* True, since node_has_descriptor(node) == true */
     circuit_append_new_exit(circ, info);
     extend_info_free(info);
   });
@@ -2224,7 +2229,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
  done:
   SMARTLIST_FOREACH(router_nicknames, char *, n, tor_free(n));
   smartlist_free(router_nicknames);
-  smartlist_free(routers);
+  smartlist_free(nodes);
   return 0;
 }
 
@@ -2340,16 +2345,17 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
   }
   /* Is this a single hop circuit? */
   if (circ && (circuit_get_cpath_len(circ)<2 || hop==1)) {
-    const routerinfo_t *r = NULL;
+    const node_t *node = NULL;
     char *exit_digest;
     if (circ->build_state &&
         circ->build_state->chosen_exit &&
         !tor_digest_is_zero(circ->build_state->chosen_exit->identity_digest)) {
       exit_digest = circ->build_state->chosen_exit->identity_digest;
-      r = router_get_by_digest(exit_digest);
+      node = node_get_by_id(exit_digest);
     }
     /* Do both the client and relay allow one-hop exit circuits? */
-    if (!r || !r->allow_single_hop_exits ||
+    if (!node ||
+        !node_allows_single_hop_exits(node) ||
         !get_options()->AllowSingleHopCircuits) {
       connection_write_str_to_buf(
       "551 Can't attach stream to this one-hop circuit.\r\n", conn);
@@ -3177,10 +3183,10 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
 static void
 orconn_target_get_name(char *name, size_t len, or_connection_t *conn)
 {
-  const routerinfo_t *ri = router_get_by_digest(conn->identity_digest);
-  if (ri) {
+  const node_t *node = node_get_by_id(conn->identity_digest);
+  if (node) {
     tor_assert(len > MAX_VERBOSE_NICKNAME_LEN);
-    router_get_verbose_nickname(name, ri);
+    node_get_verbose_nickname(node, name);
   } else if (! tor_digest_is_zero(conn->identity_digest)) {
     name[0] = '$';
     base16_encode(name+1, len-1, conn->identity_digest,
@@ -3722,9 +3728,9 @@ control_event_guard(const char *nickname, const char *digest,
 
   {
     char buf[MAX_VERBOSE_NICKNAME_LEN+1];
-    const routerinfo_t *ri = router_get_by_digest(digest);
-    if (ri) {
-      router_get_verbose_nickname(buf, ri);
+    const node_t *node = node_get_by_id(digest);
+    if (node) {
+      node_get_verbose_nickname(node, buf);
     } else {
       tor_snprintf(buf, sizeof(buf), "$%s~%s", hbuf, nickname);
     }

+ 19 - 14
src/or/directory.c

@@ -17,6 +17,7 @@
 #include "main.h"
 #include "microdesc.h"
 #include "networkstatus.h"
+#include "nodelist.h"
 #include "policies.h"
 #include "rendclient.h"
 #include "rendcommon.h"
@@ -219,13 +220,14 @@ dir_conn_purpose_to_string(int purpose)
 int
 router_supports_extrainfo(const char *identity_digest, int is_authority)
 {
-  const routerinfo_t *ri = router_get_by_digest(identity_digest);
+  const node_t *node = node_get_by_id(identity_digest);
 
-  if (ri) {
-    if (ri->caches_extra_info)
+  if (node->ri) {
+    if (node->ri->caches_extra_info)
       return 1;
-    if (is_authority && ri->platform &&
-        tor_version_as_new_as(ri->platform, "Tor 0.2.0.0-alpha-dev (r10070)"))
+    if (is_authority && node->ri->platform &&
+        tor_version_as_new_as(node->ri->platform,
+                              "Tor 0.2.0.0-alpha-dev (r10070)"))
       return 1;
   }
   if (is_authority) {
@@ -401,10 +403,12 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
        * possible directory question. This won't be true forever. -RD */
       /* It certainly is not true with conditional consensus downloading,
        * so, for now, never assume the server supports that. */
-      const routerinfo_t *ri = choose_random_entry(NULL);
-      if (ri) {
+      const node_t *node = choose_random_entry(NULL);
+      if (node && node->ri) {
+        /* every bridge has a routerinfo. */
         tor_addr_t addr;
-        tor_addr_from_ipv4h(&addr, ri->addr);
+        routerinfo_t *ri = node->ri;
+        node_get_addr(node, &addr);
         directory_initiate_command(ri->address, &addr,
                                    ri->or_port, 0,
                                    0, /* don't use conditional consensus url */
@@ -523,18 +527,19 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
                                              time_t if_modified_since,
                                              const rend_data_t *rend_query)
 {
-  const routerinfo_t *router;
+  const node_t *node;
   char address_buf[INET_NTOA_BUF_LEN+1];
   struct in_addr in;
   const char *address;
   tor_addr_t addr;
-  router = router_get_by_digest(status->identity_digest);
-  if (!router && anonymized_connection) {
+  node = node_get_by_id(status->identity_digest);
+  if (!node && anonymized_connection) {
     log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
                      "don't have its router descriptor.", status->nickname);
     return;
-  } else if (router) {
-    address = router->address;
+  } else if (node) {
+    node_get_address_string(node, address_buf, sizeof(address_buf));
+    address = address_buf;
   } else {
     in.s_addr = htonl(status->addr);
     tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
@@ -3694,7 +3699,7 @@ dir_microdesc_download_failed(smartlist_t *failed,
   if (! consensus)
     return;
   SMARTLIST_FOREACH_BEGIN(failed, const char *, d) {
-    rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus, d);
+    rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus,d);
     if (!rs)
       continue;
     dls = &rs->dl_status;

+ 116 - 83
src/or/dirserv.c

@@ -16,6 +16,7 @@
 #include "hibernate.h"
 #include "microdesc.h"
 #include "networkstatus.h"
+#include "nodelist.h"
 #include "policies.h"
 #include "rephist.h"
 #include "router.h"
@@ -65,8 +66,6 @@ static char *format_versions_list(config_line_t *ln);
 struct authdir_config_t;
 static int add_fingerprint_to_dir(const char *nickname, const char *fp,
                                   struct authdir_config_t *list);
-static uint32_t dirserv_router_get_status(const routerinfo_t *router,
-                                          const char **msg);
 static uint32_t
 dirserv_get_status_impl(const char *fp, const char *nickname,
                         const char *address,
@@ -304,7 +303,7 @@ dirserv_load_fingerprint_file(void)
  *
  * If the status is 'FP_REJECT' and <b>msg</b> is provided, set
  * *<b>msg</b> to an explanation of why. */
-static uint32_t
+uint32_t
 dirserv_router_get_status(const routerinfo_t *router, const char **msg)
 {
   char d[DIGEST_LEN];
@@ -361,7 +360,7 @@ dirserv_get_name_status(const char *id_digest, const char *nickname)
   return 0;
 }
 
-/** Helper: As dirserv_get_router_status, but takes the router fingerprint
+/** Helper: As dirserv_router_get_status, but takes the router fingerprint
  * (hex, no spaces), nickname, address (used for logging only), IP address, OR
  * port, platform (logging only) and contact info (logging only) as arguments.
  *
@@ -376,7 +375,7 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
                         const char **msg, int should_log)
 {
   int reject_unlisted = get_options()->AuthDirRejectUnlisted;
-  uint32_t result = 0;
+  uint32_t result;
   router_status_t *status_by_digest;
 
   if (!fingerprint_list)
@@ -534,7 +533,7 @@ dirserv_router_has_valid_address(routerinfo_t *ri)
  */
 int
 authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
-                               int complain)
+                               int complain, int *valid_out)
 {
   /* Okay.  Now check whether the fingerprint is recognized. */
   uint32_t status = dirserv_router_get_status(ri, msg);
@@ -575,15 +574,24 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
     *msg = "Rejected: Address is not an IP, or IP is a private address.";
     return -1;
   }
-  /* Okay, looks like we're willing to accept this one. */
-  ri->is_named = (status & FP_NAMED) ? 1 : 0;
-  ri->is_valid = (status & FP_INVALID) ? 0 : 1;
-  ri->is_bad_directory = (status & FP_BADDIR) ? 1 : 0;
-  ri->is_bad_exit = (status & FP_BADEXIT) ? 1 : 0;
+
+  *valid_out = ! (status & FP_INVALID);
 
   return 0;
 }
 
+/** Update the relevant flags of <b>node</b> based on our opinion as a
+ * directory authority in <b>authstatus</b>, as returned by
+ * dirserv_router_get_status or equivalent.  */
+void
+dirserv_set_node_flags_from_authoritative_status(node_t *node,
+                                                 uint32_t authstatus)
+{
+  node->is_valid = (authstatus & FP_INVALID) ? 0 : 1;
+  node->is_bad_directory = (authstatus & FP_BADDIR) ? 1 : 0;
+  node->is_bad_exit = (authstatus & FP_BADEXIT) ? 1 : 0;
+}
+
 /** True iff <b>a</b> is more severe than <b>b</b>. */
 static int
 WRA_MORE_SEVERE(was_router_added_t a, was_router_added_t b)
@@ -752,8 +760,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
     routerlist_descriptors_added(changed, 0);
     smartlist_free(changed);
     if (!*msg) {
-      *msg =  ri->is_valid ? "Descriptor for valid server accepted" :
-        "Descriptor for invalid server accepted";
+      *msg =  "Descriptor accepted";
     }
     log_info(LD_DIRSERV,
              "Added descriptor from '%s' (source: %s): %s.",
@@ -808,50 +815,60 @@ dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
 static void
 directory_remove_invalid(void)
 {
-  int i;
   int changed = 0;
   routerlist_t *rl = router_get_routerlist();
+  smartlist_t *nodes = smartlist_create();
+  smartlist_add_all(nodes, nodelist_get_list());
 
-  routerlist_assert_ok(rl);
-
-  for (i = 0; i < smartlist_len(rl->routers); ++i) {
+  SMARTLIST_FOREACH_BEGIN(nodes, node_t *, node) {
     const char *msg;
-    routerinfo_t *ent = smartlist_get(rl->routers, i);
-    uint32_t r = dirserv_router_get_status(ent, &msg);
+    routerinfo_t *ent = node->ri;
+    uint32_t r;
+    if (!ent)
+      continue;
+    r = dirserv_router_get_status(ent, &msg);
     if (r & FP_REJECT) {
       log_info(LD_DIRSERV, "Router '%s' is now rejected: %s",
                ent->nickname, msg?msg:"");
       routerlist_remove(rl, ent, 0, time(NULL));
-      i--;
       changed = 1;
       continue;
     }
-    if (bool_neq((r & FP_NAMED), ent->is_named)) {
+#if 0
+    if (bool_neq((r & FP_NAMED), ent->auth_says_is_named)) {
       log_info(LD_DIRSERV,
                "Router '%s' is now %snamed.", ent->nickname,
                (r&FP_NAMED)?"":"un");
       ent->is_named = (r&FP_NAMED)?1:0;
       changed = 1;
     }
-    if (bool_neq((r & FP_INVALID), !ent->is_valid)) {
+    if (bool_neq((r & FP_UNNAMED), ent->auth_says_is_unnamed)) {
+      log_info(LD_DIRSERV,
+               "Router '%s' is now %snamed. (FP_UNNAMED)", ent->nickname,
+               (r&FP_NAMED)?"":"un");
+      ent->is_named = (r&FP_NUNAMED)?0:1;
+      changed = 1;
+    }
+#endif
+    if (bool_neq((r & FP_INVALID), !node->is_valid)) {
       log_info(LD_DIRSERV, "Router '%s' is now %svalid.", ent->nickname,
                (r&FP_INVALID) ? "in" : "");
-      ent->is_valid = (r&FP_INVALID)?0:1;
+      node->is_valid = (r&FP_INVALID)?0:1;
       changed = 1;
     }
-    if (bool_neq((r & FP_BADDIR), ent->is_bad_directory)) {
+    if (bool_neq((r & FP_BADDIR), node->is_bad_directory)) {
       log_info(LD_DIRSERV, "Router '%s' is now a %s directory", ent->nickname,
                (r & FP_BADDIR) ? "bad" : "good");
-      ent->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
+      node->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
       changed = 1;
     }
-    if (bool_neq((r & FP_BADEXIT), ent->is_bad_exit)) {
+    if (bool_neq((r & FP_BADEXIT), node->is_bad_exit)) {
       log_info(LD_DIRSERV, "Router '%s' is now a %s exit", ent->nickname,
                (r & FP_BADEXIT) ? "bad" : "good");
-      ent->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
+      node->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
       changed = 1;
     }
-  }
+  } SMARTLIST_FOREACH_END(node);
   if (changed)
     directory_set_dirty();
 
@@ -894,10 +911,11 @@ directory_set_dirty(void)
  * as running iff <b>is_live</b> is true.
  */
 static char *
-list_single_server_status(routerinfo_t *desc, int is_live)
+list_single_server_status(const routerinfo_t *desc, int is_live)
 {
   char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
   char *cp;
+  const node_t *node;
 
   tor_assert(desc);
 
@@ -905,7 +923,8 @@ list_single_server_status(routerinfo_t *desc, int is_live)
   if (!is_live) {
     *cp++ = '!';
   }
-  if (desc->is_valid) {
+  node = node_get_by_id(desc->cache_info.identity_digest);
+  if (node && node->is_valid) {
     strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf));
     cp += strlen(cp);
     *cp++ = '=';
@@ -944,6 +963,8 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
     unreachable.
    */
   int answer;
+  node_t *node = node_get_mutable_by_id(router->cache_info.identity_digest);
+  tor_assert(node);
 
   if (router_is_me(router)) {
     /* We always know if we are down ourselves. */
@@ -968,7 +989,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
     rep_hist_note_router_unreachable(router->cache_info.identity_digest, now);
   }
 
-  router->is_running = answer;
+  node->is_running = answer;
 }
 
 /** Based on the routerinfo_ts in <b>routers</b>, allocate the
@@ -996,6 +1017,8 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
   rs_entries = smartlist_create();
 
   SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
+    const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
+    tor_assert(node);
     if (authdir) {
       /* Update router status in routerinfo_t. */
       dirserv_set_router_is_running(ri, now);
@@ -1003,12 +1026,13 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
     if (for_controller) {
       char name_buf[MAX_VERBOSE_NICKNAME_LEN+2];
       char *cp = name_buf;
-      if (!ri->is_running)
+      if (!node->is_running)
         *cp++ = '!';
       router_get_verbose_nickname(cp, ri);
       smartlist_add(rs_entries, tor_strdup(name_buf));
     } else if (ri->cache_info.published_on >= cutoff) {
-      smartlist_add(rs_entries, list_single_server_status(ri, ri->is_running));
+      smartlist_add(rs_entries, list_single_server_status(ri,
+                                                          node->is_running));
     }
   } SMARTLIST_FOREACH_END(ri);
 
@@ -1046,12 +1070,12 @@ format_versions_list(config_line_t *ln)
  * not hibernating, and not too old. Else return 0.
  */
 static int
-router_is_active(routerinfo_t *ri, time_t now)
+router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
 {
   time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
   if (ri->cache_info.published_on < cutoff)
     return 0;
-  if (!ri->is_running || !ri->is_valid || ri->is_hibernating)
+  if (!node->is_running || !node->is_valid || ri->is_hibernating)
     return 0;
   return 1;
 }
@@ -1717,7 +1741,7 @@ static uint64_t total_exit_bandwidth = 0;
 /** Helper: estimate the uptime of a router given its stated uptime and the
  * amount of time since it last stated its stated uptime. */
 static INLINE long
-real_uptime(routerinfo_t *router, time_t now)
+real_uptime(const routerinfo_t *router, time_t now)
 {
   if (now < router->cache_info.published_on)
     return router->uptime;
@@ -1768,7 +1792,8 @@ dirserv_thinks_router_is_unreliable(time_t now,
  * been set.
  */
 static int
-dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now)
+dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
+                                const node_t *node, time_t now)
 {
   long uptime = real_uptime(router, now);
 
@@ -1778,7 +1803,7 @@ dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now)
    * version is too old. */
   return (router->wants_to_be_hs_dir && router->dir_port &&
           uptime > get_options()->MinUptimeHidServDirectoryV2 &&
-          router->is_running);
+          node->is_running);
 }
 
 /** Look through the routerlist, the Mean Time Between Failure history, and
@@ -1826,19 +1851,22 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
   /* Weighted fractional uptime for each active router. */
   wfus = tor_malloc(sizeof(double)*smartlist_len(rl->routers));
 
+  nodelist_assert_ok();
+
   /* Now, fill in the arrays. */
-  SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
-    if (router_is_active(ri, now)) {
+  SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
+    routerinfo_t *ri = node->ri;
+    if (ri && router_is_active(ri, node, now)) {
       const char *id = ri->cache_info.identity_digest;
       uint32_t bw;
-      ri->is_exit = (!router_exit_policy_rejects_all(ri) &&
-                    exit_policy_is_general_exit(ri->exit_policy));
+      node->is_exit = (!router_exit_policy_rejects_all(ri) &&
+                       exit_policy_is_general_exit(ri->exit_policy));
       uptimes[n_active] = (uint32_t)real_uptime(ri, now);
       mtbfs[n_active] = rep_hist_get_stability(id, now);
       tks  [n_active] = rep_hist_get_weighted_time_known(id, now);
       bandwidths[n_active] = bw = router_get_advertised_bandwidth(ri);
       total_bandwidth += bw;
-      if (ri->is_exit && !ri->is_bad_exit) {
+      if (node->is_exit && !node->is_bad_exit) {
         total_exit_bandwidth += bw;
       } else {
         bandwidths_excluding_exits[n_active_nonexit] = bw;
@@ -1846,7 +1874,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
       }
       ++n_active;
     }
-  });
+  } SMARTLIST_FOREACH_END(node);
 
   /* Now, compute thresholds. */
   if (n_active) {
@@ -1872,15 +1900,17 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
   /* Now that we have a time-known that 7/8 routers are known longer than,
    * fill wfus with the wfu of every such "familiar" router. */
   n_familiar = 0;
-  SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
-      if (router_is_active(ri, now)) {
+
+  SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
+      routerinfo_t *ri = node->ri;
+      if (ri && router_is_active(ri, node, now)) {
         const char *id = ri->cache_info.identity_digest;
         long tk = rep_hist_get_weighted_time_known(id, now);
         if (tk < guard_tk)
           continue;
         wfus[n_familiar++] = rep_hist_get_weighted_fractional_uptime(id, now);
       }
-    });
+  } SMARTLIST_FOREACH_END(node);
   if (n_familiar)
     guard_wfu = median_double(wfus, n_familiar);
   if (guard_wfu > WFU_TO_GUARANTEE_GUARD)
@@ -2123,6 +2153,8 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
   routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b;
   int first_is_auth, second_is_auth;
   uint32_t bw_first, bw_second;
+  const node_t *node_first, *node_second;
+  int first_is_running, second_is_running;
 
   /* we return -1 if first should appear before second... that is,
    * if first is a better router. */
@@ -2145,9 +2177,14 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
   else if (!first_is_auth && second_is_auth)
     return 1;
 
-  else if (first->is_running && !second->is_running)
+  node_first = node_get_by_id(first->cache_info.identity_digest);
+  node_second = node_get_by_id(second->cache_info.identity_digest);
+  first_is_running = node_first && node_first->is_running;
+  second_is_running = node_second && node_second->is_running;
+
+  if (first_is_running && !second_is_running)
     return -1;
-  else if (!first->is_running && second->is_running)
+  else if (!first_is_running && second_is_running)
     return 1;
 
   bw_first = router_get_advertised_bandwidth(first);
@@ -2216,7 +2253,9 @@ get_possible_sybil_list(const smartlist_t *routers)
  */
 void
 set_routerstatus_from_routerinfo(routerstatus_t *rs,
-                                 routerinfo_t *ri, time_t now,
+                                 node_t *node,
+                                 routerinfo_t *ri,
+                                 time_t now,
                                  int naming, int listbadexits,
                                  int listbaddirs)
 {
@@ -2228,48 +2267,46 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
     router_digest_is_trusted_dir(ri->cache_info.identity_digest);
 
   /* Already set by compute_performance_thresholds. */
-  rs->is_exit = ri->is_exit;
-  rs->is_stable = ri->is_stable =
-    router_is_active(ri, now) &&
+  rs->is_exit = node->is_exit;
+  rs->is_stable = node->is_stable =
+    router_is_active(ri, node, now) &&
     !dirserv_thinks_router_is_unreliable(now, ri, 1, 0) &&
     !unstable_version;
-  rs->is_fast = ri->is_fast =
-    router_is_active(ri, now) &&
+  rs->is_fast = node->is_fast =
+    router_is_active(ri, node, now) &&
     !dirserv_thinks_router_is_unreliable(now, ri, 0, 1);
-  rs->is_running = ri->is_running; /* computed above */
+  rs->is_running = node->is_running; /* computed above */
 
   if (naming) {
     uint32_t name_status = dirserv_get_name_status(
-                         ri->cache_info.identity_digest, ri->nickname);
+                                              node->identity, ri->nickname);
     rs->is_named = (naming && (name_status & FP_NAMED)) ? 1 : 0;
     rs->is_unnamed = (naming && (name_status & FP_UNNAMED)) ? 1 : 0;
   }
-  rs->is_valid = ri->is_valid;
+  rs->is_valid = node->is_valid;
 
-  if (rs->is_fast &&
+  if (node->is_fast &&
       (router_get_advertised_bandwidth(ri) >= BANDWIDTH_TO_GUARANTEE_GUARD ||
        router_get_advertised_bandwidth(ri) >=
                               MIN(guard_bandwidth_including_exits,
                                   guard_bandwidth_excluding_exits))) {
-    long tk = rep_hist_get_weighted_time_known(
-                                      ri->cache_info.identity_digest, now);
-    double wfu = rep_hist_get_weighted_fractional_uptime(
-                                      ri->cache_info.identity_digest, now);
+    long tk = rep_hist_get_weighted_time_known(node->identity, now);
+    double wfu = rep_hist_get_weighted_fractional_uptime(node->identity, now);
     rs->is_possible_guard = (wfu >= guard_wfu && tk >= guard_tk) ? 1 : 0;
   } else {
     rs->is_possible_guard = 0;
   }
-  rs->is_bad_directory = listbaddirs && ri->is_bad_directory;
-  rs->is_bad_exit = listbadexits && ri->is_bad_exit;
-  ri->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, now);
-  rs->is_hs_dir = ri->is_hs_dir;
+  rs->is_bad_directory = listbaddirs && node->is_bad_directory;
+  rs->is_bad_exit = listbadexits && node->is_bad_exit;
+  node->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, node, now);
+  rs->is_hs_dir = node->is_hs_dir;
   rs->is_v2_dir = ri->dir_port != 0;
 
   if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME))
     rs->is_named = rs->is_unnamed = 0;
 
   rs->published_on = ri->cache_info.published_on;
-  memcpy(rs->identity_digest, ri->cache_info.identity_digest, DIGEST_LEN);
+  memcpy(rs->identity_digest, node->identity, DIGEST_LEN);
   memcpy(rs->descriptor_digest, ri->cache_info.signed_descriptor_digest,
          DIGEST_LEN);
   rs->addr = ri->addr;
@@ -2294,18 +2331,6 @@ clear_status_flags_on_sybil(routerstatus_t *rs)
    * forget to add it to this clause. */
 }
 
-/** Clear all the status flags in routerinfo <b>router</b>. We put this
- * function here because it's eerily similar to
- * clear_status_flags_on_sybil() above. One day we should merge them. */
-void
-router_clear_status_flags(routerinfo_t *router)
-{
-  router->is_valid = router->is_running = router->is_hs_dir =
-    router->is_fast = router->is_stable =
-    router->is_possible_guard = router->is_exit =
-    router->is_bad_exit = router->is_bad_directory = 0;
-}
-
 /**
  * Helper function to parse out a line in the measured bandwidth file
  * into a measured_bw_line_t output structure. Returns -1 on failure
@@ -2553,10 +2578,13 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
       routerstatus_t *rs;
       vote_routerstatus_t *vrs;
       microdesc_t *md;
+      node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+      if (!node)
+        continue;
 
       vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
       rs = &vrs->status;
-      set_routerstatus_from_routerinfo(rs, ri, now,
+      set_routerstatus_from_routerinfo(rs, node, ri, now,
                                        naming, listbadexits, listbaddirs);
 
       if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
@@ -2796,8 +2824,12 @@ generate_v2_networkstatus_opinion(void)
     if (ri->cache_info.published_on >= cutoff) {
       routerstatus_t rs;
       char *version = version_from_platform(ri->platform);
-
-      set_routerstatus_from_routerinfo(&rs, ri, now,
+      node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+      if (!node) {
+        tor_free(version);
+        continue;
+      }
+      set_routerstatus_from_routerinfo(&rs, node, ri, now,
                                        naming, listbadexits, listbaddirs);
 
       if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
@@ -3122,6 +3154,7 @@ dirserv_orconn_tls_done(const char *address,
       }
     }
   });
+
   /* FFFF Maybe we should reinstate the code that dumps routers with the same
    * addr/port but with nonmatching keys, but instead of dumping, we should
    * skip testing. */

+ 7 - 3
src/or/dirserv.h

@@ -40,8 +40,6 @@
    MAX_V_LINE_LEN                                                       \
    )
 
-#define UNNAMED_ROUTER_NICKNAME "Unnamed"
-
 int connection_dirserv_flushed_some(dir_connection_t *conn);
 
 int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
@@ -104,7 +102,13 @@ int dirserv_should_launch_reachability_test(const routerinfo_t *ri,
 void dirserv_single_reachability_test(time_t now, routerinfo_t *router);
 void dirserv_test_reachability(time_t now);
 int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
-                                   int complain);
+                                   int complain,
+                                   int *valid_out);
+uint32_t dirserv_router_get_status(const routerinfo_t *router,
+                                   const char **msg);
+void dirserv_set_node_flags_from_authoritative_status(node_t *node,
+                                                      uint32_t authstatus);
+
 int dirserv_would_reject_router(const routerstatus_t *rs);
 int dirserv_remove_old_statuses(smartlist_t *fps, time_t cutoff);
 int dirserv_have_any_serverdesc(smartlist_t *fps, int spool_src);

+ 1 - 0
src/or/dirvote.h

@@ -63,6 +63,7 @@ const char *dirvote_get_pending_detached_signatures(void);
 #define DGV_INCLUDE_PREVIOUS 4
 const cached_dir_t *dirvote_get_vote(const char *fp, int flags);
 void set_routerstatus_from_routerinfo(routerstatus_t *rs,
+                                      node_t *node,
                                       routerinfo_t *ri, time_t now,
                                       int naming, int listbadexits,
                                       int listbaddirs);

+ 1 - 0
src/or/microdesc.c

@@ -587,3 +587,4 @@ update_microdescs_from_networkstatus(time_t now)
       md->last_listed = ns->valid_after;
   } SMARTLIST_FOREACH_END(rs);
 }
+

+ 14 - 112
src/or/networkstatus.c

@@ -107,9 +107,8 @@ void
 networkstatus_reset_warnings(void)
 {
   if (current_consensus) {
-    SMARTLIST_FOREACH(current_consensus->routerstatus_list,
-                      routerstatus_t *, rs,
-                      rs->name_lookup_warned = 0);
+    SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node,
+                      node->name_lookup_warned = 0);
   }
 
   have_warned_about_old_version = 0;
@@ -1070,92 +1069,11 @@ const routerstatus_t *
 router_get_consensus_status_by_nickname(const char *nickname,
                                         int warn_if_unnamed)
 {
-  char digest[DIGEST_LEN];
-  routerstatus_t *best=NULL;
-  smartlist_t *matches=NULL;
-  const char *named_id=NULL;
-
-  if (!current_consensus || !nickname)
-    return NULL;
-
-  /* Is this name really a hexadecimal identity digest? */
-  if (nickname[0] == '$') {
-    if (base16_decode(digest, DIGEST_LEN, nickname+1, strlen(nickname+1))<0)
-      return NULL;
-    return networkstatus_vote_find_entry(current_consensus, digest);
-  } else if (strlen(nickname) == HEX_DIGEST_LEN &&
-       (base16_decode(digest, DIGEST_LEN, nickname, strlen(nickname))==0)) {
-    return networkstatus_vote_find_entry(current_consensus, digest);
-  }
-
-  /* Is there a server that is Named with this name? */
-  if (named_server_map)
-    named_id = strmap_get_lc(named_server_map, nickname);
-  if (named_id)
-    return networkstatus_vote_find_entry(current_consensus, named_id);
-
-  /* Okay; is this name listed as Unnamed? */
-  if (unnamed_server_map &&
-      strmap_get_lc(unnamed_server_map, nickname)) {
-    log_info(LD_GENERAL, "The name %s is listed as Unnamed; it is not the "
-             "canonical name of any server we know.", escaped(nickname));
+  const node_t *node = node_get_by_nickname(nickname, warn_if_unnamed);
+  if (node)
+    return node->rs;
+  else
     return NULL;
-  }
-
-  /* This name is not canonical for any server; go through the list and
-   * see who it matches. */
-  /*XXXX This is inefficient; optimize it if it matters. */
-  matches = smartlist_create();
-  SMARTLIST_FOREACH(current_consensus->routerstatus_list,
-                    routerstatus_t *, lrs,
-    {
-      if (!strcasecmp(lrs->nickname, nickname)) {
-        if (lrs->is_named) {
-          tor_fragile_assert() /* This should never happen. */
-          smartlist_free(matches);
-          return lrs;
-        } else {
-          if (lrs->is_unnamed) {
-            tor_fragile_assert(); /* nor should this. */
-            smartlist_clear(matches);
-            best=NULL;
-            break;
-          }
-          smartlist_add(matches, lrs);
-          best = lrs;
-        }
-      }
-    });
-
-  if (smartlist_len(matches)>1 && warn_if_unnamed) {
-    int any_unwarned=0;
-    SMARTLIST_FOREACH(matches, routerstatus_t *, lrs,
-      {
-        if (! lrs->name_lookup_warned) {
-          lrs->name_lookup_warned=1;
-          any_unwarned=1;
-        }
-      });
-    if (any_unwarned) {
-      log_warn(LD_CONFIG,"There are multiple matches for the nickname \"%s\","
-               " but none is listed as named by the directory authorities. "
-               "Choosing one arbitrarily.", nickname);
-    }
-  } else if (warn_if_unnamed && best && !best->name_lookup_warned) {
-    char fp[HEX_DIGEST_LEN+1];
-    base16_encode(fp, sizeof(fp),
-                  best->identity_digest, DIGEST_LEN);
-    log_warn(LD_CONFIG,
-         "When looking up a status, you specified a server \"%s\" by name, "
-         "but the directory authorities do not have any key registered for "
-         "this nickname -- so it could be used by any server, "
-         "not just the one you meant. "
-         "To make sure you get the same server in the future, refer to "
-         "it by key, as \"$%s\".", nickname, fp);
-    best->name_lookup_warned = 1;
-  }
-  smartlist_free(matches);
-  return best;
 }
 
 /** Return the identity digest that's mapped to officially by
@@ -1629,7 +1547,6 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c,
                                 rs_new->identity_digest, DIGEST_LEN),
                          STMT_NIL) {
     /* Okay, so we're looking at the same identity. */
-    rs_new->name_lookup_warned = rs_old->name_lookup_warned;
     rs_new->last_dir_503_at = rs_old->last_dir_503_at;
 
     if (!memcmp(rs_old->descriptor_digest, rs_new->descriptor_digest,
@@ -2062,7 +1979,6 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
   trusted_dir_server_t *ds;
   or_options_t *options = get_options();
   int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
-  int namingdir = authdir && options->NamingAuthoritativeDir;
   networkstatus_t *ns = current_consensus;
   if (!ns || !smartlist_len(ns->routerstatus_list))
     return;
@@ -2076,25 +1992,19 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
                          memcmp(rs->identity_digest,
                                router->cache_info.identity_digest, DIGEST_LEN),
   {
+#if 0
     /* We have no routerstatus for this router. Clear flags and skip it. */
-    if (!namingdir)
-      router->is_named = 0;
     if (!authdir) {
       if (router->purpose == ROUTER_PURPOSE_GENERAL)
         router_clear_status_flags(router);
     }
+#endif
   }) {
     /* We have a routerstatus for this router. */
     const char *digest = router->cache_info.identity_digest;
 
     ds = router_get_trusteddirserver_by_digest(digest);
 
-    if (!namingdir) {
-      if (rs->is_named && !strcasecmp(router->nickname, rs->nickname))
-        router->is_named = 1;
-      else
-        router->is_named = 0;
-    }
     /* Is it the same descriptor, or only the same identity? */
     if (!memcmp(router->cache_info.signed_descriptor_digest,
                 rs->descriptor_digest, DIGEST_LEN)) {
@@ -2102,18 +2012,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
         router->cache_info.last_listed_as_valid_until = ns->valid_until;
     }
 
-    if (!authdir) {
-      /* If we're not an authdir, believe others. */
-      router->is_valid = rs->is_valid;
-      router->is_running = rs->is_running;
-      router->is_fast = rs->is_fast;
-      router->is_stable = rs->is_stable;
-      router->is_possible_guard = rs->is_possible_guard;
-      router->is_exit = rs->is_exit;
-      router->is_bad_directory = rs->is_bad_directory;
-      router->is_bad_exit = rs->is_bad_exit;
-      router->is_hs_dir = rs->is_hs_dir;
-    } else {
+    if (authdir) {
       /* If we _are_ an authority, we should check whether this router
        * is one that will cause us to need a reachability test. */
       routerinfo_t *old_router =
@@ -2123,7 +2022,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
           dirserv_should_launch_reachability_test(router, old_router);
       }
     }
-    if (router->is_running && ds) {
+    if (rs->is_running && ds) {
       download_status_reset(&ds->v2_ns_dl_status);
     }
     if (reset_failures) {
@@ -2214,6 +2113,9 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now)
 
   statuses = smartlist_create();
   SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
+    node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+    if (!node)
+      continue;
     if (ri->cache_info.published_on < cutoff)
       continue;
     if (ri->purpose != purpose)
@@ -2221,7 +2123,7 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now)
     if (bridge_auth && ri->purpose == ROUTER_PURPOSE_BRIDGE)
       dirserv_set_router_is_running(ri, now);
     /* then generate and write out status lines for each of them */
-    set_routerstatus_from_routerinfo(&rs, ri, now, 0, 0, 0);
+    set_routerstatus_from_routerinfo(&rs, node, ri, now, 0, 0, 0);
     smartlist_add(statuses, networkstatus_getinfo_helper_single(&rs));
   });
 

+ 3 - 2
src/or/networkstatus.h

@@ -59,8 +59,9 @@ const routerstatus_t *router_get_consensus_status_by_descriptor_digest(
 routerstatus_t *router_get_mutable_consensus_status_by_descriptor_digest(
                                    networkstatus_t *consensus,
                                    const char *digest);
-const routerstatus_t *router_get_consensus_status_by_nickname(const char *nickname,
-                                                       int warn_if_unnamed);
+const routerstatus_t *router_get_consensus_status_by_nickname(
+                                   const char *nickname,
+                                   int warn_if_unnamed);
 const char *networkstatus_get_router_digest_by_nickname(const char *nickname);
 int networkstatus_nickname_is_unnamed(const char *nickname);
 void networkstatus_consensus_download_failed(int status_code,

+ 397 - 21
src/or/nodelist.c

@@ -5,14 +5,17 @@
 /* See LICENSE for licensing information */
 
 #include "or.h"
-#include "nodelist.h"
+#include "config.h"
+#include "dirserv.h"
 #include "microdesc.h"
 #include "networkstatus.h"
+#include "nodelist.h"
+#include "router.h"
 #include "routerlist.h"
 
 #include <string.h>
 
-static void nodelist_drop_node(node_t *node);
+static void nodelist_drop_node(node_t *node, int remove_from_ht);
 static void node_free(node_t *node);
 
 /** A nodelist_t holds a node_t object for every router we're "willing to use
@@ -24,6 +27,7 @@ typedef struct nodelist_t {
   smartlist_t *nodes;
   /* Hash table to map from node ID digest to node. */
   HT_HEAD(nodelist_map, node_t) nodes_by_id;
+
 } nodelist_t;
 
 static INLINE unsigned int
@@ -63,10 +67,9 @@ init_nodelist(void)
   }
 }
 
-/** Return the node_t whose identity is <b>identity_digest</b>, or NULL
- * if no such node exists. */
+/** As node_get_by_id, but returns a non-const pointer */
 node_t *
-node_get_by_id(const char *identity_digest)
+node_get_mutable_by_id(const char *identity_digest)
 {
   node_t search, *node;
   if (PREDICT_UNLIKELY(the_nodelist == NULL))
@@ -77,6 +80,14 @@ node_get_by_id(const char *identity_digest)
   return node;
 }
 
+/** Return the node_t whose identity is <b>identity_digest</b>, or NULL
+ * if no such node exists. */
+const node_t *
+node_get_by_id(const char *identity_digest)
+{
+  return node_get_mutable_by_id(identity_digest);
+}
+
 /** Internal: return the node_t whose identity_digest is
  * <b>identity_digest</b>.  If none exists, create a new one, add it to the
  * nodelist, and return it.
@@ -88,7 +99,7 @@ node_get_or_create(const char *identity_digest)
 {
   node_t *node;
 
-  if ((node = node_get_by_id(identity_digest)))
+  if ((node = node_get_mutable_by_id(identity_digest)))
     return node;
 
   node = tor_malloc_zero(sizeof(node_t));
@@ -98,6 +109,8 @@ node_get_or_create(const char *identity_digest)
   smartlist_add(the_nodelist->nodes, node);
   node->nodelist_idx = smartlist_len(the_nodelist->nodes) - 1;
 
+  node->country = -1;
+
   return node;
 }
 
@@ -109,6 +122,16 @@ nodelist_add_routerinfo(routerinfo_t *ri)
   init_nodelist();
   node = node_get_or_create(ri->cache_info.identity_digest);
   node->ri = ri;
+
+  if (node->country == -1)
+    node_set_country(node);
+
+  if (authdir_mode(get_options())) {
+    const char *discard=NULL;
+    uint32_t status = dirserv_router_get_status(ri, &discard);
+    dirserv_set_node_flags_from_authoritative_status(node, status);
+  }
+
   return node;
 }
 
@@ -133,7 +156,7 @@ nodelist_add_microdesc(microdesc_t *md)
   rs = router_get_consensus_status_by_descriptor_digest(ns, md->digest);
   if (rs == NULL)
     return NULL;
-  node = node_get_by_id(rs->identity_digest);
+  node = node_get_mutable_by_id(rs->identity_digest);
   if (node)
     node->md = md;
   return node;
@@ -147,6 +170,8 @@ nodelist_add_microdesc(microdesc_t *md)
 void
 nodelist_set_consensus(networkstatus_t *ns)
 {
+  or_options_t *options = get_options();
+  int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
   init_nodelist();
 
   SMARTLIST_FOREACH(the_nodelist->nodes, node_t *, node,
@@ -162,8 +187,43 @@ nodelist_set_consensus(networkstatus_t *ns)
                                                        rs->descriptor_digest);
       }
     }
+
+    node_set_country(node);
+
+    /* If we're not an authdir, believe others. */
+    if (!authdir) {
+      node->is_valid = rs->is_valid;
+      node->is_running = rs->is_running;
+      node->is_fast = rs->is_fast;
+      node->is_stable = rs->is_stable;
+      node->is_possible_guard = rs->is_possible_guard;
+      node->is_exit = rs->is_exit;
+      node->is_bad_directory = rs->is_bad_directory;
+      node->is_bad_exit = rs->is_bad_exit;
+      node->is_hs_dir = rs->is_hs_dir;
+    }
+
   } SMARTLIST_FOREACH_END(rs);
+
   nodelist_purge();
+
+  if (! authdir) {
+    SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+      /* We have no routerstatus for this router. Clear flags so we can skip
+       * it, maybe.*/
+      if (!node->rs) {
+        tor_assert(node->ri); /* if it had only an md, or nothing, purge
+                               * would have removed it. */
+        if (node->ri->purpose == ROUTER_PURPOSE_GENERAL) {
+          /* Clear all flags. */
+          node->is_valid = node->is_running = node->is_hs_dir =
+            node->is_fast = node->is_stable =
+            node->is_possible_guard = node->is_exit =
+            node->is_bad_exit = node->is_bad_directory = 0;
+        }
+      }
+    } SMARTLIST_FOREACH_END(node);
+  }
 }
 
 /** Helper: return true iff a node has a usable amount of information*/
@@ -178,7 +238,7 @@ node_is_usable(const node_t *node)
 void
 nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md)
 {
-  node_t *node = node_get_by_id(identity_digest);
+  node_t *node = node_get_mutable_by_id(identity_digest);
   if (node && node->md == md)
     node->md = NULL;
 }
@@ -187,11 +247,11 @@ nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md)
 void
 nodelist_remove_routerinfo(routerinfo_t *ri)
 {
-  node_t *node = node_get_by_id(ri->cache_info.identity_digest);
+  node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
   if (node && node->ri == ri) {
     node->ri = NULL;
     if (! node_is_usable(node)) {
-      nodelist_drop_node(node);
+      nodelist_drop_node(node, 1);
       node_free(node);
     }
   }
@@ -200,12 +260,14 @@ nodelist_remove_routerinfo(routerinfo_t *ri)
 /** Remove <b>node</b> from the nodelist.  (Asserts that it was there to begin
  * with.) */
 static void
-nodelist_drop_node(node_t *node)
+nodelist_drop_node(node_t *node, int remove_from_ht)
 {
   node_t *tmp;
   int idx;
-  tmp = HT_REMOVE(nodelist_map, &the_nodelist->nodes_by_id, node);
-  tor_assert(tmp == node);
+  if (remove_from_ht) {
+    tmp = HT_REMOVE(nodelist_map, &the_nodelist->nodes_by_id, node);
+    tor_assert(tmp == node);
+  }
 
   idx = node->nodelist_idx;
   tor_assert(idx >= 0);
@@ -238,6 +300,7 @@ nodelist_purge(void)
   if (PREDICT_UNLIKELY(the_nodelist == NULL))
     return;
 
+  /* Remove the non-usable nodes. */
   for (iter = HT_START(nodelist_map, &the_nodelist->nodes_by_id); iter; ) {
     node_t *node = *iter;
 
@@ -245,11 +308,11 @@ nodelist_purge(void)
       iter = HT_NEXT(nodelist_map, &the_nodelist->nodes_by_id, iter);
     } else {
       iter = HT_NEXT_RMV(nodelist_map, &the_nodelist->nodes_by_id, iter);
-      nodelist_drop_node(node);
+      nodelist_drop_node(node, 0);
       node_free(node);
     }
   }
-
+  nodelist_assert_ok();
 }
 
 /** Release all storage held by the nodelist. */
@@ -286,25 +349,25 @@ nodelist_assert_ok(void)
   /* every routerinfo in rl->routers should be in the nodelist. */
   if (rl) {
     SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, ri) {
-      node_t *node = node_get_by_id(ri->cache_info.identity_digest);
+      const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
       tor_assert(node && node->ri == ri);
       tor_assert(0 == memcmp(ri->cache_info.identity_digest,
                              node->identity, DIGEST_LEN));
       tor_assert(! digestmap_get(dm, node->identity));
-      digestmap_set(dm, node->identity, node);
+      digestmap_set(dm, node->identity, (void*)node);
     } SMARTLIST_FOREACH_END(ri);
   }
 
   /* every routerstatus in ns should be in the nodelist */
   if (ns) {
     SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
-      node_t *node = node_get_by_id(rs->identity_digest);
+      const node_t *node = node_get_by_id(rs->identity_digest);
       tor_assert(node && node->rs == rs);
       tor_assert(0 == memcmp(rs->identity_digest, node->identity, DIGEST_LEN));
-      digestmap_set(dm, node->identity, node);
+      digestmap_set(dm, node->identity, (void*)node);
       if (ns->flavor == FLAV_MICRODESC) {
-        /* If it's a microdesc consensus, every entry that has a microdescriptor
-         * should be in the nodelist.
+        /* If it's a microdesc consensus, every entry that has a
+         * microdescriptor should be in the nodelist.
          */
         microdesc_t *md =
           microdesc_cache_lookup_by_digest256(NULL, rs->descriptor_digest);
@@ -326,3 +389,316 @@ nodelist_assert_ok(void)
   digestmap_free(dm, NULL);
 }
 
+/** Return a list of a node_t * for every node we know about.  The caller
+ * MUST NOT modify the list. (You can set and clear flags in the nodes if
+ * you must, but you must not add or remove nodes.) */
+smartlist_t *
+nodelist_get_list(void)
+{
+  init_nodelist();
+  return the_nodelist->nodes;
+}
+
+/** Given a nickname (possibly verbose, possibly a hexadecimal digest), return
+ * the corresponding node_t, or NULL if none exists.  Warn the user if
+ * <b>warn_if_unnamed</b> is set, and they have specified a router by
+ * nickname, but the Named flag isn't set for that router. */
+const node_t *
+node_get_by_nickname(const char *nickname, int warn_if_unnamed)
+{
+  char digest_buf[DIGEST_LEN];
+  char nn_buf[MAX_NICKNAME_LEN+1];
+  char nn_char='\0';
+
+  if (!the_nodelist)
+    return NULL;
+
+  /* ???? NM Naming authorities had an additional weird behavior here where
+     they would treat their own namings as slightly authoritative in a
+     strange and inconsistent way.  I think that this way is better, but we
+     could get the old behavior back if we wanted to by adding a function
+     to look in the fp_by_name table in fingerprint_list, and using this
+     function to override the name-to-digest lookup below if we are a
+     naming server.  -NM
+   */
+
+  /* Handle these cases: DIGEST, $DIGEST, $DIGEST=name, $DIGEST~name. */
+  if (hex_digest_nickname_decode(nickname, digest_buf, &nn_char, nn_buf)==0) {
+    const node_t *node = node_get_by_id(digest_buf);
+    if (!node)
+      return NULL;
+    if (nn_char) {
+      const char *real_name = node_get_nickname(node);
+      if (!real_name || strcasecmp(real_name, nn_buf))
+        return NULL;
+      if (nn_char == '=') {
+        const char *named_id =
+          networkstatus_get_router_digest_by_nickname(nn_buf);
+        if (!named_id || memcmp(named_id, digest_buf, DIGEST_LEN))
+          return NULL;
+      }
+    }
+    return node;
+  }
+
+  if (!strcasecmp(nickname, UNNAMED_ROUTER_NICKNAME))
+    return NULL;
+
+  /* Okay, so if we get here, the nickname is just a nickname.  Is there
+   * a binding for it in the consensus? */
+  {
+    const char *named_id =
+      networkstatus_get_router_digest_by_nickname(nickname);
+    if (named_id)
+      return node_get_by_id(named_id);
+  }
+
+  /* Is it marked as owned-by-someone-else? */
+  if (networkstatus_nickname_is_unnamed(nickname)) {
+    log_info(LD_GENERAL, "The name %s is listed as Unnamed: there is some "
+             "router that holds it, but not one listed in the current "
+             "consensus.", escaped(nickname));
+    return NULL;
+  }
+
+  /* Okay, so the name is not canonical for anybody. */
+  {
+    smartlist_t *matches = smartlist_create();
+    const node_t *choice = NULL;
+
+    SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+      if (!strcasecmp(node_get_nickname(node), nickname))
+        smartlist_add(matches, node);
+    } SMARTLIST_FOREACH_END(node);
+
+    if (smartlist_len(matches)>1 && warn_if_unnamed) {
+      int any_unwarned = 0;
+      SMARTLIST_FOREACH_BEGIN(matches, node_t *, node) {
+        if (!node->name_lookup_warned) {
+          node->name_lookup_warned = 1;
+          any_unwarned = 1;
+        }
+      } SMARTLIST_FOREACH_END(node);
+
+      if (any_unwarned) {
+        log_warn(LD_CONFIG, "There are multiple matches for the name %s, "
+                 "but none is listed as Named in the directory consensus. "
+                 "Choosing one arbitrarily.", nickname);
+      }
+    } else if (smartlist_len(matches)>1 && warn_if_unnamed) {
+      char fp[HEX_DIGEST_LEN+1];
+      node_t *node = smartlist_get(matches, 0);
+      if (node->name_lookup_warned) {
+        base16_encode(fp, sizeof(fp), node->identity, DIGEST_LEN);
+        log_warn(LD_CONFIG,
+                 "You specified a server \"%s\" by name, but the directory "
+                 "authorities do not have any key registered for this "
+                 "nickname -- so it could be used by any server, not just "
+                 "the one you meant. "
+                 "To make sure you get the same server in the future, refer "
+                 "to it by key, as \"$%s\".", nickname, fp);
+        node->name_lookup_warned = 1;
+      }
+    }
+
+    if (smartlist_len(matches))
+      choice = smartlist_get(matches, 0);
+
+    smartlist_free(matches);
+    return choice;
+  }
+}
+
+/** Return the nickname of <b>node</b>, or NULL if we can't find one. */
+const char *
+node_get_nickname(const node_t *node)
+{
+  if (node->rs)
+    return node->rs->nickname;
+  else if (node->ri)
+    return node->ri->nickname;
+  else
+    return NULL;
+}
+
+/** Return true iff the nickname of <b>node</b> is canonical, based on the
+ * latest consensus. */
+int
+node_is_named(const node_t *node)
+{
+  const char *named_id;
+  const char *nickname = node_get_nickname(node);
+  if (!nickname)
+    return 0;
+  named_id = networkstatus_get_router_digest_by_nickname(nickname);
+  if (!named_id)
+    return 0;
+  return !memcmp(named_id, node->identity, DIGEST_LEN);
+}
+
+/** Return true iff <b>node</b> appears to be a directory authority or
+ * directory cache */
+int
+node_is_dir(const node_t *node)
+{
+  if (node->rs)
+    return node->rs->dir_port != 0;
+  else if (node->ri)
+    return node->ri->dir_port != 0;
+  else
+    return 0;
+}
+
+
+/** Return true iff <b>node</b> has either kind of usable descriptor -- that
+ * is, a routerdecriptor or a microdescriptor. */
+int
+node_has_descriptor(const node_t *node)
+{
+  return (node->ri ||
+          (node->rs && node->md));
+}
+
+/** Return the router_purpose of <b>node</b>. */
+int
+node_get_purpose(const node_t *node)
+{
+  if (node->ri)
+    return node->ri->purpose;
+  else
+    return ROUTER_PURPOSE_GENERAL;
+}
+
+/** Compute the verbose ("extended") nickname of <b>node</b> and store it
+ * into the MAX_VERBOSE_NICKNAME_LEN+1 character buffer at
+ * <b>verbose_nickname_out</b> */
+void
+node_get_verbose_nickname(const node_t *node,
+                          char *verbose_name_out)
+{
+  const char *nickname = node_get_nickname(node);
+  int is_named = node_is_named(node);
+  verbose_name_out[0] = '$';
+  base16_encode(verbose_name_out+1, HEX_DIGEST_LEN+1, node->identity,
+                DIGEST_LEN);
+  if (!nickname)
+    return;
+  verbose_name_out[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
+  strlcpy(verbose_name_out+1+HEX_DIGEST_LEN+1, nickname, MAX_NICKNAME_LEN+1);
+}
+
+/** Return true iff it seems that <b>node</b> allows circuits to exit
+ * through it directlry from the client. */
+int
+node_allows_single_hop_exits(const node_t *node)
+{
+  (void)node;
+  UNIMPLEMENTED_NODELIST();
+  return 0;
+}
+
+/** Return true iff it seems that <b>node</b> has an exit policy that
+ * doesn't actually permit anything to exit. */
+int
+node_exit_policy_rejects_all(const node_t *node)
+{
+  (void)node;
+  UNIMPLEMENTED_NODELIST();
+  return 0;
+}
+
+/** Copy the address for <b>node</b> into *<b>addr_out</b>. */
+int
+node_get_addr(const node_t *node, tor_addr_t *addr_out)
+{
+  if (node->ri) {
+    tor_addr_from_ipv4h(addr_out, node->ri->addr);
+    return 0;
+  } else if (node->rs) {
+    tor_addr_from_ipv4h(addr_out, node->rs->addr);
+    return 0;
+  }
+  return -1;
+}
+
+/** Return the host-order IPv4 address for <b>node</b>, or 0 if it doesn't
+ * seem to have one.  */
+uint32_t
+node_get_addr_ipv4h(const node_t *node)
+{
+  if (node->ri) {
+    return node->ri->addr;
+  } else if (node->rs) {
+    return node->rs->addr;
+  }
+  return 0;
+}
+
+/** Copy a string representation of the IP address for <b>node</b> into the
+ * <b>len</b>-byte buffer at <b>buf</b>.
+ */
+void
+node_get_address_string(const node_t *node, char *buf, size_t len)
+{
+  if (node->ri) {
+    strlcpy(buf, node->ri->address, len);
+  } else if (node->rs) {
+    tor_addr_t addr;
+    tor_addr_from_ipv4h(&addr, node->rs->addr);
+    tor_addr_to_str(buf, &addr, len, 0);
+  } else {
+    buf[0] = '\0';
+  }
+}
+
+/** Return <b>node</b>'s declared uptime, or -1 if it doesn't seem to have
+ * one. */
+long
+node_get_declared_uptime(const node_t *node)
+{
+  (void)node;
+  UNIMPLEMENTED_NODELIST();
+  return 0;
+}
+
+/** Return <b>node</b>'s declared or_port */
+uint16_t
+node_get_orport(const node_t *node)
+{
+  if (node->ri)
+    return node->ri->or_port;
+  else if (node->rs)
+    return node->rs->or_port;
+  else
+    return 0;
+}
+
+/** Return <b>node</b>'s platform string */
+const char *
+node_get_platform(const node_t *node)
+{
+  (void)node;
+  UNIMPLEMENTED_NODELIST();
+  return NULL;
+}
+
+/** Return <b>node</b>'s time of publication. */
+time_t
+node_get_published_on(const node_t *node)
+{
+  (void)node;
+  UNIMPLEMENTED_NODELIST();
+  return 0;
+}
+
+/** Return true iff <b>node</b> is one representing this router. */
+int
+node_is_me(const node_t *node)
+{
+  return router_digest_is_me(node->identity);
+}
+
+/* KILLTHIS XXXX NM -- it's a dummy to keep UNIMPLEMENTED_NODELIST()
+ * working */
+int unimplemented_nodelist_truth = 1;
+

+ 38 - 1
src/or/nodelist.h

@@ -12,7 +12,8 @@
 #ifndef _TOR_NODELIST_H
 #define _TOR_NODELIST_H
 
-node_t *node_get_by_id(const char *identity_digest);
+node_t *node_get_mutable_by_id(const char *identity_digest);
+const node_t *node_get_by_id(const char *identity_digest);
 node_t *nodelist_add_routerinfo(routerinfo_t *ri);
 node_t *nodelist_add_microdesc(microdesc_t *md);
 void nodelist_set_consensus(networkstatus_t *ns);
@@ -24,5 +25,41 @@ void nodelist_purge(void);
 void nodelist_free_all(void);
 void nodelist_assert_ok(void);
 
+const node_t *node_get_by_nickname(const char *nickname, int warn_if_unnamed);
+void node_get_verbose_nickname(const node_t *node,
+                               char *verbose_name_out);
+int node_is_named(const node_t *node);
+int node_is_dir(const node_t *node);
+int node_has_descriptor(const node_t *node);
+int node_get_purpose(const node_t *node);
+#define node_is_bridge(node) \
+  (node_get_purpose((node)) == ROUTER_PURPOSE_BRIDGE)
+int node_is_me(const node_t *node);
+int node_exit_policy_rejects_all(const node_t *node);
+int node_get_addr(const node_t *node, tor_addr_t *addr_out);
+uint32_t node_get_addr_ipv4h(const node_t *node);
+int node_allows_single_hop_exits(const node_t *node);
+uint16_t node_get_orport(const node_t *node);
+const char *node_get_nickname(const node_t *node);
+const char *node_get_platform(const node_t *node);
+void node_get_address_string(const node_t *node, char *cp, size_t len);
+long node_get_declared_uptime(const node_t *node);
+time_t node_get_published_on(const node_t *node);
+
+smartlist_t *nodelist_get_list(void);
+
+/* XXXX These need to move out of routerlist.c */
+void nodelist_refresh_countries(void);
+void node_set_country(node_t *node);
+void nodelist_add_node_family(smartlist_t *nodes, const node_t *node);
+int nodes_in_same_family(const node_t *node1, const node_t *node2);
+
+/* This means: implement this code or function or thing, nick! */
+#define UNIMPLEMENTED_NODELIST()                        \
+  while (unimplemented_nodelist_truth) {                \
+    tor_assert(0);                                      \
+  }
+extern int unimplemented_nodelist_truth;
+
 #endif
 

+ 71 - 29
src/or/or.h

@@ -809,6 +809,9 @@ typedef enum {
  * Tor 0.1.2.x is obsolete, we can remove this. */
 #define DEFAULT_CLIENT_NICKNAME "client"
 
+/** Name chosen by routers that don't configure nicknames */
+#define UNNAMED_ROUTER_NICKNAME "Unnamed"
+
 /** Number of bytes in a SOCKS4 header. */
 #define SOCKS4_NETWORK_LEN 8
 
@@ -1510,52 +1513,44 @@ typedef struct {
   unsigned int allow_single_hop_exits:1;  /**< Whether the router says
                                            * it allows single hop exits. */
 
-  /* local info */
-  unsigned int is_running:1; /**< As far as we know, is this OR currently
-                              * running? */
-  unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR?
-                               *  (For Authdir: Have we validated this OR?)
-                               */
-  unsigned int is_named:1; /**< Do we believe the nickname that this OR gives
-                            * us? */
-  unsigned int is_fast:1; /** Do we think this is a fast OR? */
-  unsigned int is_stable:1; /** Do we think this is a stable OR? */
-  unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */
-  unsigned int is_exit:1; /**< Do we think this is an OK exit? */
-  unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked,
-                               * or otherwise nasty? */
-  unsigned int is_bad_directory:1; /**< Do we think this directory is junky,
-                                    * underpowered, or otherwise useless? */
   unsigned int wants_to_be_hs_dir:1; /**< True iff this router claims to be
                                       * a hidden service directory. */
-  unsigned int is_hs_dir:1; /**< True iff this router is a hidden service
-                             * directory according to the authorities. */
   unsigned int policy_is_reject_star:1; /**< True iff the exit policy for this
                                          * router rejects everything. */
   /** True if, after we have added this router, we should re-launch
    * tests for it. */
   unsigned int needs_retest_if_added:1;
 
-/** Tor can use this router for general positions in circuits. */
+/** Tor can use this router for general positions in circuits; we got it
+ * from a directory server as usual, or we're an authority and a server
+ * uploaded it. */
 #define ROUTER_PURPOSE_GENERAL 0
-/** Tor should avoid using this router for circuit-building. */
+/** Tor should avoid using this router for circuit-building: we got it
+ * from a crontroller.  If the controller wants to use it, it'll have to
+ * ask for it by identity. */
 #define ROUTER_PURPOSE_CONTROLLER 1
-/** Tor should use this router only for bridge positions in circuits. */
+/** Tor should use this router only for bridge positions in circuits: we got
+ * it via a directory request from the bridge itself, or a bridge
+ * authority. x*/
 #define ROUTER_PURPOSE_BRIDGE 2
 /** Tor should not use this router; it was marked in cached-descriptors with
  * a purpose we didn't recognize. */
 #define ROUTER_PURPOSE_UNKNOWN 255
 
-  uint8_t purpose; /** What positions in a circuit is this router good for? */
+  /* In what way did we find out about this router?  One of ROUTER_PURPOSE_*.
+   * Routers of different purposes are kept segregated and used for different
+   * things; see notes on ROUTER_PURPOSE_* macros above.
+   */
+  uint8_t purpose;
 
   /* The below items are used only by authdirservers for
    * reachability testing. */
+
   /** When was the last time we could reach this OR? */
   time_t last_reachable;
   /** When did we start testing reachability for this OR? */
   time_t testing_since;
-  /** According to the geoip db what country is this router in? */
-  country_t country;
+
 } routerinfo_t;
 
 /** Information needed to keep and cache a signed extra-info document. */
@@ -1643,9 +1638,6 @@ typedef struct routerstatus_t {
    * from this authority.)  Applies in v2 networkstatus document only.
    */
   unsigned int need_to_mirror:1;
-  unsigned int name_lookup_warned:1; /**< Have we warned the user for referring
-                                      * to this (unnamed) router by nickname?
-                                      */
   time_t last_dir_503_at; /**< When did this router last tell us that it
                            * was too busy to serve directory info? */
   download_status_t dl_status;
@@ -1698,17 +1690,66 @@ typedef struct microdesc_t {
                       * XXX this probably should not stay a string. */
 } microdesc_t;
 
-/** DOCDOC */
+/** A node_t represents a Tor router.
+ *
+ * Specifically, a node_t is a Tor router as we are using it: a router that
+ * we are considering for circuits, connections, and so on.  A node_t is a
+ * thin wrapper around the routerstatus, routerinfo, and microdesc for a
+ * single wrapper, and provides a consistent interface for all of them.
+ *
+ * Also, a node_t has mutable state.  While a routerinfo, a routerstatus,
+ * and a microdesc have[*] only the information read from a router
+ * descriptor, a consensus entry, and a microdescriptor (respectively)...
+ * a node_t has flags based on *our own current opinion* of the node.
+ *
+ * [*] Actually, there is some leftover information in each that is mutable.
+ *  We should try to excise that.
+ */
 typedef struct node_t {
+  /* Indexing information */
+
   /** Used to look up the node_t by its identity digest. */
   HT_ENTRY(node_t) ht_ent;
   /** Position of the node within the list of nodes */
   int nodelist_idx;
 
+  /** The identity digest of this node_t.  No more than one node_t per
+   * identity may exist at a time. */
   char identity[DIGEST_LEN];
+
   microdesc_t *md;
   routerinfo_t *ri;
   routerstatus_t *rs;
+
+  /* local info: copied from routerstatus, then possibly frobbed based
+   * on experience.  Authorities set this stuff directly. */
+
+  unsigned int is_running:1; /**< As far as we know, is this OR currently
+                              * running? */
+  unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR?
+                               *  (For Authdir: Have we validated this OR?)
+                               */
+  unsigned int is_fast:1; /** Do we think this is a fast OR? */
+  unsigned int is_stable:1; /** Do we think this is a stable OR? */
+  unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */
+  unsigned int is_exit:1; /**< Do we think this is an OK exit? */
+  unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked,
+                               * or otherwise nasty? */
+  unsigned int is_bad_directory:1; /**< Do we think this directory is junky,
+                                    * underpowered, or otherwise useless? */
+  unsigned int is_hs_dir:1; /**< True iff this router is a hidden service
+                             * directory according to the authorities. */
+
+  /* Local info: warning state. */
+
+  unsigned int name_lookup_warned:1; /**< Have we warned the user for referring
+                                      * to this (unnamed) router by nickname?
+                                      */
+
+  /* Local info: derived. */
+
+  /** According to the geoip db what country is this router in? */
+  country_t country;
 } node_t;
 
 /** How many times will we try to download a router's descriptor before giving
@@ -3548,7 +3589,8 @@ typedef enum {
   CRN_NEED_GUARD = 1<<2,
   CRN_ALLOW_INVALID = 1<<3,
   /* XXXX not used, apparently. */
-  CRN_WEIGHT_AS_EXIT = 1<<5
+  CRN_WEIGHT_AS_EXIT = 1<<5,
+  CRN_NEED_DESC = 1<<6
 } router_crn_flags_t;
 
 /** Return value for router_add_to_routerlist() and dirserv_add_descriptor() */

+ 52 - 0
src/or/policies.c

@@ -11,6 +11,7 @@
 #include "or.h"
 #include "config.h"
 #include "dirserv.h"
+#include "nodelist.h"
 #include "policies.h"
 #include "routerparse.h"
 #include "ht.h"
@@ -269,6 +270,22 @@ fascist_firewall_allows_or(const routerinfo_t *ri)
   return fascist_firewall_allows_address_or(&addr, ri->or_port);
 }
 
+/** Return true iff we think our firewall will let us make an OR connection to
+ * <b>node</b>. */
+int
+fascist_firewall_allows_node(const node_t *node)
+{
+  if (node->ri) {
+    return fascist_firewall_allows_or(node->ri);
+  } else if (node->rs) {
+    tor_addr_t addr;
+    tor_addr_from_ipv4h(&addr, node->rs->addr);
+    return fascist_firewall_allows_address_or(&addr, node->rs->or_port);
+  } else {
+    return 1;
+  }
+}
+
 /** Return true iff we think our firewall will let us make a directory
  * connection to addr:port. */
 int
@@ -858,6 +875,7 @@ policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
   return 0;
 }
 
+#if 0
 /** Replace the exit policy of <b>r</b> with reject *:*. */
 void
 policies_set_router_exitpolicy_to_reject_all(routerinfo_t *r)
@@ -868,6 +886,15 @@ policies_set_router_exitpolicy_to_reject_all(routerinfo_t *r)
   item = router_parse_addr_policy_item_from_string("reject *:*", -1);
   smartlist_add(r->exit_policy, item);
 }
+#endif
+
+/** Replace the exit policy of <b>node</b> with reject *:* */
+void
+policies_set_node_exitpolicy_to_reject_all(node_t *node)
+{
+  (void)node;
+  UNIMPLEMENTED_NODELIST();
+}
 
 /** Return 1 if there is at least one /8 subnet in <b>policy</b> that
  * allows exiting to <b>port</b>.  Otherwise, return 0. */
@@ -1288,6 +1315,31 @@ policy_summarize(smartlist_t *policy)
   return result;
 }
 
+/** Decides whether addr:port is probably or definitely accepted or rejcted by
+ * <b>node</b>.  See compare_tor_addr_to_addr_policy for details on addr/port
+ * interpretation. */
+addr_policy_result_t
+compare_addr_to_node_policy(uint32_t addr, uint16_t port, const node_t *node)
+{
+  tor_addr_t a;
+  tor_addr_from_ipv4h(&a, addr);
+  return compare_tor_addr_to_node_policy(&a, port, node);
+}
+
+/** Decides whether addr:port is probably or definitely accepted or rejcted by
+ * <b>node</b>.  See compare_tor_addr_to_addr_policy for details on addr/port
+ * interpretation. */
+addr_policy_result_t
+compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port,
+                                const node_t *node)
+{
+  (void)addr;
+  (void)port;
+  (void)node;
+  UNIMPLEMENTED_NODELIST();
+  return 0;
+}
+
 /** Implementation for GETINFO control command: knows the answer for questions
  * about "exit-policy/..." */
 int

+ 8 - 1
src/or/policies.h

@@ -20,6 +20,7 @@
 int firewall_is_fascist_or(void);
 int fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port);
 int fascist_firewall_allows_or(const routerinfo_t *ri);
+int fascist_firewall_allows_node(const node_t *node);
 int fascist_firewall_allows_address_dir(const tor_addr_t *addr, uint16_t port);
 int dir_policy_permits_address(const tor_addr_t *addr);
 int socks_policy_permits_address(const tor_addr_t *addr);
@@ -38,10 +39,16 @@ addr_policy_result_t compare_tor_addr_to_addr_policy(const tor_addr_t *addr,
                               uint16_t port, const smartlist_t *policy);
 addr_policy_result_t compare_addr_to_addr_policy(uint32_t addr,
                               uint16_t port, const smartlist_t *policy);
+
+addr_policy_result_t compare_addr_to_node_policy(uint32_t addr,
+                              uint16_t port, const node_t *node);
+addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr,
+                              uint16_t port, const node_t *node);
+
 int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
                                int rejectprivate, const char *local_address,
                                int add_default_policy);
-void policies_set_router_exitpolicy_to_reject_all(routerinfo_t *exitrouter);
+void policies_set_node_exitpolicy_to_reject_all(node_t *exitrouter);
 int exit_policy_is_general_exit(smartlist_t *policy);
 int policy_is_reject_star(const smartlist_t *policy);
 int getinfo_helper_policies(control_connection_t *conn,

+ 6 - 5
src/or/relay.c

@@ -24,6 +24,7 @@
 #include "main.h"
 #include "mempool.h"
 #include "networkstatus.h"
+#include "nodelist.h"
 #include "policies.h"
 #include "reasons.h"
 #include "relay.h"
@@ -712,7 +713,7 @@ connection_ap_process_end_not_open(
     edge_connection_t *conn, crypt_path_t *layer_hint)
 {
   struct in_addr in;
-  routerinfo_t *exitrouter;
+  node_t *exitrouter;
   int reason = *(cell->payload+RELAY_HEADER_SIZE);
   int control_reason = reason | END_STREAM_REASON_FLAG_REMOTE;
   (void) layer_hint; /* unused */
@@ -725,7 +726,7 @@ connection_ap_process_end_not_open(
     log_info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.",
              safe_str(conn->socks_request->address),
              stream_end_reason_to_string(reason));
-    exitrouter = router_get_mutable_by_digest(chosen_exit_digest);
+    exitrouter = node_get_mutable_by_id(chosen_exit_digest);
     switch (reason) {
       case END_STREAM_REASON_EXITPOLICY:
         if (rh->length >= 5) {
@@ -760,8 +761,8 @@ connection_ap_process_end_not_open(
           log_info(LD_APP,
                  "Exitrouter '%s' seems to be more restrictive than its exit "
                  "policy. Not using this router as exit for now.",
-                 exitrouter->nickname);
-          policies_set_router_exitpolicy_to_reject_all(exitrouter);
+                 node_get_nickname(exitrouter));
+          policies_set_node_exitpolicy_to_reject_all(exitrouter);
         }
         /* rewrite it to an IP if we learned one. */
         if (addressmap_rewrite(conn->socks_request->address,
@@ -824,7 +825,7 @@ connection_ap_process_end_not_open(
       case END_STREAM_REASON_HIBERNATING:
       case END_STREAM_REASON_RESOURCELIMIT:
         if (exitrouter) {
-          policies_set_router_exitpolicy_to_reject_all(exitrouter);
+          policies_set_node_exitpolicy_to_reject_all(exitrouter);
         }
         if (conn->chosen_exit_optional) {
           /* stop wanting a specific exit */

+ 4 - 4
src/or/rendclient.c

@@ -16,6 +16,7 @@
 #include "connection_edge.h"
 #include "directory.h"
 #include "main.h"
+#include "nodelist.h"
 #include "relay.h"
 #include "rendclient.h"
 #include "rendcommon.h"
@@ -738,7 +739,6 @@ rend_client_get_random_intro(const rend_data_t *rend_query)
   int i;
   rend_cache_entry_t *entry;
   rend_intro_point_t *intro;
-  const routerinfo_t *router;
 
   if (rend_cache_lookup_entry(rend_query->onion_address, -1, &entry) < 1) {
     log_warn(LD_REND,
@@ -755,8 +755,8 @@ rend_client_get_random_intro(const rend_data_t *rend_query)
   intro = smartlist_get(entry->parsed->intro_nodes, i);
   /* Do we need to look up the router or is the extend info complete? */
   if (!intro->extend_info->onion_key) {
-    router = router_get_by_nickname(intro->extend_info->nickname, 0);
-    if (!router) {
+    const node_t *node = node_get_by_nickname(intro->extend_info->nickname, 0);
+    if (!node) {
       log_info(LD_REND, "Unknown router with nickname '%s'; trying another.",
                intro->extend_info->nickname);
       rend_intro_point_free(intro);
@@ -764,7 +764,7 @@ rend_client_get_random_intro(const rend_data_t *rend_query)
       goto again;
     }
     extend_info_free(intro->extend_info);
-    intro->extend_info = extend_info_from_router(router);
+    intro->extend_info = extend_info_from_node(node);
   }
   return extend_info_dup(intro->extend_info);
 }

+ 21 - 20
src/or/rendservice.c

@@ -14,6 +14,7 @@
 #include "config.h"
 #include "directory.h"
 #include "networkstatus.h"
+#include "nodelist.h"
 #include "rendclient.h"
 #include "rendcommon.h"
 #include "rendservice.h"
@@ -1001,7 +1002,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
   } else {
     char *rp_nickname;
     size_t nickname_field_len;
-    const routerinfo_t *router;
+    const node_t *node;
     int version;
     if (*buf == 1) {
       rp_nickname = buf+1;
@@ -1028,8 +1029,8 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
     len -= nickname_field_len;
     len -= rp_nickname - buf; /* also remove header space used by version, if
                                * any */
-    router = router_get_by_nickname(rp_nickname, 0);
-    if (!router) {
+    node = node_get_by_nickname(rp_nickname, 0);
+    if (!node) {
       log_info(LD_REND, "Couldn't find router %s named in introduce2 cell.",
                escaped_safe_str_client(rp_nickname));
       /* XXXX Add a no-such-router reason? */
@@ -1037,7 +1038,7 @@ rend_service_introduce(origin_circuit_t *circuit, const char *request,
       goto err;
     }
 
-    extend_info = extend_info_from_router(router);
+    extend_info = extend_info_from_node(node);
   }
 
   if (len != REND_COOKIE_LEN+DH_KEY_LEN) {
@@ -1754,19 +1755,19 @@ void
 rend_services_introduce(void)
 {
   int i,j,r;
-  const routerinfo_t *router;
+  const node_t *node;
   rend_service_t *service;
   rend_intro_point_t *intro;
   int changed, prev_intro_nodes;
-  smartlist_t *intro_routers;
+  smartlist_t *intro_nodes;
   time_t now;
   or_options_t *options = get_options();
 
-  intro_routers = smartlist_create();
+  intro_nodes = smartlist_create();
   now = time(NULL);
 
   for (i=0; i < smartlist_len(rend_service_list); ++i) {
-    smartlist_clear(intro_routers);
+    smartlist_clear(intro_nodes);
     service = smartlist_get(rend_service_list, i);
 
     tor_assert(service);
@@ -1786,8 +1787,8 @@ rend_services_introduce(void)
        service. */
     for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
       intro = smartlist_get(service->intro_nodes, j);
-      router = router_get_by_digest(intro->extend_info->identity_digest);
-      if (!router || !find_intro_circuit(intro, service->pk_digest)) {
+      node = node_get_by_id(intro->extend_info->identity_digest);
+      if (!node || !find_intro_circuit(intro, service->pk_digest)) {
         log_info(LD_REND,"Giving up on %s as intro point for %s.",
                  intro->extend_info->nickname, service->service_id);
         if (service->desc) {
@@ -1806,8 +1807,8 @@ rend_services_introduce(void)
         smartlist_del(service->intro_nodes,j--);
         changed = 1;
       }
-      if (router)
-        smartlist_add(intro_routers, (void*)router);
+      if (node)
+        smartlist_add(intro_nodes, (void*)node);
     }
 
     /* We have enough intro points, and the intro points we thought we had were
@@ -1836,26 +1837,26 @@ rend_services_introduce(void)
 #define NUM_INTRO_POINTS_INIT (NUM_INTRO_POINTS + 2)
     for (j=prev_intro_nodes; j < (prev_intro_nodes == 0 ?
              NUM_INTRO_POINTS_INIT : NUM_INTRO_POINTS); ++j) {
-      router_crn_flags_t flags = CRN_NEED_UPTIME;
+      router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
       if (get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION)
         flags |= CRN_ALLOW_INVALID;
-      router = router_choose_random_node(intro_routers,
-                                         options->ExcludeNodes, flags);
-      if (!router) {
+      node = router_choose_random_node(intro_nodes,
+                                       options->ExcludeNodes, flags);
+      if (!node) {
         log_warn(LD_REND,
                  "Could only establish %d introduction points for %s.",
                  smartlist_len(service->intro_nodes), service->service_id);
         break;
       }
       changed = 1;
-      smartlist_add(intro_routers, (void*)router);
+      smartlist_add(intro_nodes, (void*)node);
       intro = tor_malloc_zero(sizeof(rend_intro_point_t));
-      intro->extend_info = extend_info_from_router(router);
+      intro->extend_info = extend_info_from_node(node);
       intro->intro_key = crypto_new_pk_env();
       tor_assert(!crypto_pk_generate_key(intro->intro_key));
       smartlist_add(service->intro_nodes, intro);
       log_info(LD_REND, "Picked router %s as an intro point for %s.",
-               router->nickname, service->service_id);
+               node_get_nickname(node), service->service_id);
     }
 
     /* If there's no need to launch new circuits, stop here. */
@@ -1872,7 +1873,7 @@ rend_services_introduce(void)
       }
     }
   }
-  smartlist_free(intro_routers);
+  smartlist_free(intro_nodes);
 }
 
 /** Regenerate and upload rendezvous service descriptors for all

+ 17 - 16
src/or/rephist.c

@@ -14,6 +14,7 @@
 #include "circuitlist.h"
 #include "circuituse.h"
 #include "config.h"
+#include "nodelist.h"
 #include "rephist.h"
 #include "router.h"
 #include "routerlist.h"
@@ -579,7 +580,7 @@ rep_hist_dump_stats(time_t now, int severity)
   size_t len;
   int ret;
   unsigned long upt, downt;
-  const routerinfo_t *r;
+  const node_t *node;
 
   rep_history_clean(now - get_options()->RephistTrackTime);
 
@@ -593,8 +594,8 @@ rep_hist_dump_stats(time_t now, int severity)
     digestmap_iter_get(orhist_it, &digest1, &or_history_p);
     or_history = (or_history_t*) or_history_p;
 
-    if ((r = router_get_by_digest(digest1)))
-      name1 = r->nickname;
+    if ((node = node_get_by_id(digest1)) && node_get_nickname(node))
+      name1 = node_get_nickname(node);
     else
       name1 = "(unknown)";
     base16_encode(hexdigest1, sizeof(hexdigest1), digest1, DIGEST_LEN);
@@ -624,8 +625,8 @@ rep_hist_dump_stats(time_t now, int severity)
            lhist_it = digestmap_iter_next(or_history->link_history_map,
                                           lhist_it)) {
         digestmap_iter_get(lhist_it, &digest2, &link_history_p);
-        if ((r = router_get_by_digest(digest2)))
-          name2 = r->nickname;
+        if ((node = node_get_by_id(digest2)) && node_get_nickname(node))
+          name2 = node_get_nickname(node);
         else
           name2 = "(unknown)";
 
@@ -871,28 +872,28 @@ rep_hist_get_router_stability_doc(time_t now)
   }
 
   DIGESTMAP_FOREACH(history_map, id, or_history_t *, hist) {
-    const routerinfo_t *ri;
+    const node_t *node;
     char dbuf[BASE64_DIGEST_LEN+1];
     char header_buf[512];
     char *info;
     digest_to_base64(dbuf, id);
-    ri = router_get_by_digest(id);
-    if (ri) {
-      char *ip = tor_dup_ip(ri->addr);
+    node = node_get_by_id(id);
+    if (node) {
+      char ip[INET_NTOA_BUF_LEN+1];
       char tbuf[ISO_TIME_LEN+1];
-      format_iso_time(tbuf, ri->cache_info.published_on);
+      node_get_address_string(node,ip,sizeof(ip));
+      format_iso_time(tbuf, node_get_published_on(node));
       tor_snprintf(header_buf, sizeof(header_buf),
                    "router %s %s %s\n"
                    "published %s\n"
                    "relevant-flags %s%s%s\n"
                    "declared-uptime %ld\n",
-                   dbuf, ri->nickname, ip,
+                   dbuf, node_get_nickname(node), ip,
                    tbuf,
-                   ri->is_running ? "Running " : "",
-                   ri->is_valid ? "Valid " : "",
-                   ri->is_hibernating ? "Hibernating " : "",
-                   ri->uptime);
-      tor_free(ip);
+                   node->is_running ? "Running " : "",
+                   node->is_valid ? "Valid " : "",
+                   node->ri && node->ri->is_hibernating ? "Hibernating " : "",
+                   node_get_declared_uptime(node));
     } else {
       tor_snprintf(header_buf, sizeof(header_buf),
                    "router %s {no descriptor}\n", dbuf);

+ 24 - 15
src/or/router.c

@@ -7,6 +7,7 @@
 #define ROUTER_PRIVATE
 
 #include "or.h"
+#include "circuitbuild.h"
 #include "circuitlist.h"
 #include "circuituse.h"
 #include "config.h"
@@ -19,6 +20,7 @@
 #include "hibernate.h"
 #include "main.h"
 #include "networkstatus.h"
+#include "nodelist.h"
 #include "policies.h"
 #include "relay.h"
 #include "rephist.h"
@@ -780,11 +782,14 @@ consider_testing_reachability(int test_or, int test_dir)
     return;
 
   if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) {
+    extend_info_t *ei;
     log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
              !orport_reachable ? "reachability" : "bandwidth",
              me->address, me->or_port);
-    circuit_launch_by_router(CIRCUIT_PURPOSE_TESTING, me,
-                             CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
+    ei = extend_info_from_router(me);
+    circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
+                            CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
+    extend_info_free(ei);
   }
 
   tor_addr_from_ipv4h(&addr, me->addr);
@@ -1333,13 +1338,12 @@ router_rebuild_descriptor(int force)
   ri->policy_is_reject_star =
     policy_is_reject_star(ri->exit_policy);
 
-  if (desc_routerinfo) { /* inherit values */
-    ri->is_valid = desc_routerinfo->is_valid;
-    ri->is_running = desc_routerinfo->is_running;
-    ri->is_named = desc_routerinfo->is_named;
-  }
+#if 0
+  /* XXXX NM NM I belive this is safe to remove */
   if (authdir_mode(options))
     ri->is_valid = ri->is_named = 1; /* believe in yourself */
+#endif
+
   if (options->MyFamily) {
     smartlist_t *family;
     if (!warned_nonexistent_family)
@@ -1349,11 +1353,11 @@ router_rebuild_descriptor(int force)
     smartlist_split_string(family, options->MyFamily, ",",
       SPLIT_SKIP_SPACE|SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
     SMARTLIST_FOREACH_BEGIN(family, char *, name) {
-        const routerinfo_t *member;
+       const node_t *member;
        if (!strcasecmp(name, options->Nickname))
-         member = ri;
+         goto skip; /* Don't list ourself, that's redundant */
        else
-         member = router_get_by_nickname(name, 1);
+         member = node_get_by_nickname(name, 1);
        if (!member) {
          int is_legal = is_legal_nickname_or_hexdigest(name);
          if (!smartlist_string_isin(warned_nonexistent_family, name) &&
@@ -1373,17 +1377,19 @@ router_rebuild_descriptor(int force)
            smartlist_add(ri->declared_family, name);
            name = NULL;
          }
-       } else if (router_is_me(member)) {
+       } else if (router_digest_is_me(member->identity)) {
          /* Don't list ourself in our own family; that's redundant */
+         /* XXX shouldn't be possible */
        } else {
          char *fp = tor_malloc(HEX_DIGEST_LEN+2);
          fp[0] = '$';
          base16_encode(fp+1,HEX_DIGEST_LEN+1,
-                       member->cache_info.identity_digest, DIGEST_LEN);
+                       member->identity, DIGEST_LEN);
          smartlist_add(ri->declared_family, fp);
          if (smartlist_string_isin(warned_nonexistent_family, name))
            smartlist_string_remove(warned_nonexistent_family, name);
        }
+    skip:
        tor_free(name);
     } SMARTLIST_FOREACH_END(name);
 
@@ -1443,8 +1449,6 @@ router_rebuild_descriptor(int force)
                          strlen(ri->cache_info.signed_descriptor_body),
                          ri->cache_info.signed_descriptor_digest);
 
-  routerinfo_set_country(ri);
-
   tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei, NULL, NULL));
 
   routerinfo_free(desc_routerinfo);
@@ -2098,10 +2102,15 @@ is_legal_hexdigest(const char *s)
 void
 router_get_verbose_nickname(char *buf, const routerinfo_t *router)
 {
+  const char *good_digest = networkstatus_get_router_digest_by_nickname(
+                                                         router->nickname);
+  int is_named = good_digest && !memcmp(good_digest,
+                                        router->cache_info.identity_digest,
+                                        DIGEST_LEN);
   buf[0] = '$';
   base16_encode(buf+1, HEX_DIGEST_LEN+1, router->cache_info.identity_digest,
                 DIGEST_LEN);
-  buf[1+HEX_DIGEST_LEN] = router->is_named ? '=' : '~';
+  buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
   strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
 }
 

Plik diff jest za duży
+ 297 - 266
src/or/routerlist.c


+ 29 - 24
src/or/routerlist.h

@@ -27,33 +27,30 @@ int router_reload_router_list(void);
 int authority_cert_dl_looks_uncertain(const char *id_digest);
 smartlist_t *router_get_trusted_dir_servers(void);
 
-const routerstatus_t *router_pick_directory_server(authority_type_t type, int flags);
+const routerstatus_t *router_pick_directory_server(authority_type_t type,
+                                                   int flags);
 trusted_dir_server_t *router_get_trusteddirserver_by_digest(const char *d);
 trusted_dir_server_t *trusteddirserver_get_by_v3_auth_digest(const char *d);
-const routerstatus_t *router_pick_trusteddirserver(authority_type_t type, int flags);
+const routerstatus_t *router_pick_trusteddirserver(authority_type_t type,
+                                                   int flags);
 int router_get_my_share_of_directory_requests(double *v2_share_out,
                                               double *v3_share_out);
 void router_reset_status_download_failures(void);
 void routerlist_add_family(smartlist_t *sl, const routerinfo_t *router);
-int routers_in_same_family(const routerinfo_t *r1, const routerinfo_t *r2);
 int routers_have_same_or_addr(const routerinfo_t *r1, const routerinfo_t *r2);
-void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
-                                    int must_be_running);
 int router_nickname_is_in_list(const routerinfo_t *router, const char *list);
 const routerinfo_t *routerlist_find_my_routerinfo(void);
-const routerinfo_t *router_find_exact_exit_enclave(const char *address,
+const node_t *router_find_exact_exit_enclave(const char *address,
                                              uint16_t port);
-int router_is_unreliable(const routerinfo_t *router, int need_uptime,
+int node_is_unreliable(const node_t *router, int need_uptime,
                          int need_capacity, int need_guard);
 uint32_t router_get_advertised_bandwidth(const routerinfo_t *router);
 uint32_t router_get_advertised_bandwidth_capped(const routerinfo_t *router);
 
-const routerinfo_t *routerlist_sl_choose_by_bandwidth(smartlist_t *sl,
-                                                bandwidth_weight_rule_t rule);
-const routerstatus_t *routerstatus_sl_choose_by_bandwidth(smartlist_t *sl,
-                                                bandwidth_weight_rule_t rule);
+const node_t *node_sl_choose_by_bandwidth(smartlist_t *sl,
+                                          bandwidth_weight_rule_t rule);
 
-const routerinfo_t *router_choose_random_node(smartlist_t *excludedsmartlist,
+const node_t *router_choose_random_node(smartlist_t *excludedsmartlist,
                                         struct routerset_t *excludedset,
                                         router_crn_flags_t flags);
 
@@ -133,8 +130,9 @@ void router_load_extrainfo_from_string(const char *s, const char *eos,
                                        int descriptor_digests);
 
 void routerlist_retry_directory_downloads(time_t now);
-int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port,
-                                          int need_uptime);
+int router_exit_policy_all_nodes_reject(uint32_t addr, uint16_t port,
+                                        int need_uptime);
+
 int router_exit_policy_rejects_all(const routerinfo_t *router);
 trusted_dir_server_t *add_trusted_dir_server(const char *nickname,
                            const char *address,
@@ -165,29 +163,31 @@ const char *esc_router_info(const routerinfo_t *router);
 void routers_sort_by_identity(smartlist_t *routers);
 
 routerset_t *routerset_new(void);
+void routerset_refresh_countries(routerset_t *rs);
 int routerset_parse(routerset_t *target, const char *s,
                     const char *description);
 void routerset_union(routerset_t *target, const routerset_t *source);
 int routerset_is_list(const routerset_t *set);
 int routerset_needs_geoip(const routerset_t *set);
-int routerset_contains_router(const routerset_t *set, const routerinfo_t *ri);
+int routerset_contains_router(const routerset_t *set, const routerinfo_t *ri,
+                              country_t country);
 int routerset_contains_routerstatus(const routerset_t *set,
-                                    const routerstatus_t *rs);
+                                    const routerstatus_t *rs,
+                                    country_t country);
 int routerset_contains_extendinfo(const routerset_t *set,
                                   const extend_info_t *ei);
-void routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
-                               int running_only);
-void routersets_get_disjunction(smartlist_t *target, const smartlist_t *source,
+int routerset_contains_node(const routerset_t *set, const node_t *node);
+void routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
+                             int running_only);
+void routersets_get_node_disjunction(smartlist_t *target,
+                                const smartlist_t *source,
                                 const routerset_t *include,
                                 const routerset_t *exclude, int running_only);
-void routerset_subtract_routers(smartlist_t *out,
-                                const routerset_t *routerset);
+void routerset_subtract_nodes(smartlist_t *out,
+                              const routerset_t *routerset);
 char *routerset_to_string(const routerset_t *routerset);
-void routerset_refresh_countries(routerset_t *target);
 int routerset_equal(const routerset_t *old, const routerset_t *new);
 void routerset_free(routerset_t *routerset);
-void routerinfo_set_country(routerinfo_t *ri);
-void routerlist_refresh_countries(void);
 void refresh_all_country_info(void);
 
 int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
@@ -201,5 +201,10 @@ void launch_descriptor_downloads(int purpose,
                                  const routerstatus_t *source,
                                  time_t now);
 
+int hex_digest_nickname_decode(const char *hexdigest,
+                               char *digest_out,
+                               char *nickname_qualifier_out,
+                               char *nickname_out);
+
 #endif
 

+ 0 - 3
src/or/routerparse.c

@@ -1344,7 +1344,6 @@ router_parse_entry_from_string(const char *s, const char *end,
   tor_assert(tok->n_args >= 5);
 
   router = tor_malloc_zero(sizeof(routerinfo_t));
-  router->country = -1;
   router->cache_info.routerlist_index = -1;
   router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
   router->cache_info.signed_descriptor_len = end-s;
@@ -1543,8 +1542,6 @@ router_parse_entry_from_string(const char *s, const char *end,
                             "router descriptor") < 0)
     goto err;
 
-  routerinfo_set_country(router);
-
   if (!router->or_port) {
     log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
     goto err;

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików