Browse Source

Choose directory servers from routerstatus list, not from routerinfo list. This way, as soon was we have a networkstatus, we can ask a cache to give us routers, rather than needing to ask the directories.

svn:r5586
Nick Mathewson 19 years ago
parent
commit
9482b1b9d5
6 changed files with 154 additions and 97 deletions
  1. 2 2
      doc/TODO
  2. 1 1
      src/common/ht.h
  3. 66 43
      src/or/directory.c
  4. 19 11
      src/or/or.h
  5. 2 1
      src/or/relay.c
  6. 64 39
      src/or/routerlist.c

+ 2 - 2
doc/TODO

@@ -194,8 +194,8 @@ N     - Clients use Stable and Fast instead of uptime and bandwidth to
       servers?
       servers?
       - Is this still necessary?
       - Is this still necessary?
     o All versions of Tor should get cosmetic changes rate-limited.
     o All versions of Tor should get cosmetic changes rate-limited.
-    - Pick directories from networkstatus objects, not from routerlist.
+    o Pick directories from networkstatus objects, not from routerlist.
-      - But! We can't do this easily, since we want to know about platform,
+      o But! We can't do this easily, since we want to know about platform,
         and networkstatus doesn't tell us Tor version.  Can we solve this?
         and networkstatus doesn't tell us Tor version.  Can we solve this?
         Should we do it by adding flags to networkstatus or what?
         Should we do it by adding flags to networkstatus or what?
 
 

+ 1 - 1
src/common/ht.h

@@ -24,7 +24,7 @@
   }
   }
 
 
 #define HT_INITIALIZER()                        \
 #define HT_INITIALIZER()                        \
-  { 0, NULL, 0, 0, -1 }
+  { NULL, 0, 0, 0, -1 }
 
 
 #define HT_INIT(root) do {                      \
 #define HT_INIT(root) do {                      \
     (root)->hth_table_length = 0;               \
     (root)->hth_table_length = 0;               \

+ 66 - 43
src/or/directory.c

@@ -31,11 +31,6 @@ const char directory_c_id[] =
  *   connection_finished_connecting() in connection.c
  *   connection_finished_connecting() in connection.c
  */
  */
 static void
 static void
-directory_initiate_command_trusted_dir(trusted_dir_server_t *dirserv,
-                                      uint8_t purpose, int private_connection,
-                                      const char *resource,
-                                      const char *payload, size_t payload_len);
-static void
 directory_initiate_command(const char *address, uint32_t addr, uint16_t port,
 directory_initiate_command(const char *address, uint32_t addr, uint16_t port,
                            const char *platform,
                            const char *platform,
                            const char *digest, uint8_t purpose,
                            const char *digest, uint8_t purpose,
@@ -143,10 +138,11 @@ directory_post_to_dirservers(uint8_t purpose, const char *payload,
    */
    */
   SMARTLIST_FOREACH(dirservers, trusted_dir_server_t *, ds,
   SMARTLIST_FOREACH(dirservers, trusted_dir_server_t *, ds,
     {
     {
+      routerstatus_t *rs = &(ds->fake_status);
       post_via_tor = purpose_is_private(purpose) ||
       post_via_tor = purpose_is_private(purpose) ||
                      !fascist_firewall_allows_address(ds->addr,ds->dir_port);
                      !fascist_firewall_allows_address(ds->addr,ds->dir_port);
-      directory_initiate_command_trusted_dir(ds, purpose, post_via_tor,
+      directory_initiate_command_routerstatus(rs, purpose, post_via_tor,
-                                             NULL, payload, payload_len);
+                                              NULL, payload, payload_len);
     });
     });
 }
 }
 
 
@@ -159,8 +155,7 @@ void
 directory_get_from_dirserver(uint8_t purpose, const char *resource,
 directory_get_from_dirserver(uint8_t purpose, const char *resource,
                              int retry_if_no_servers)
                              int retry_if_no_servers)
 {
 {
-  routerinfo_t *r = NULL;
+  routerstatus_t *rs = NULL;
-  trusted_dir_server_t *ds = NULL;
   or_options_t *options = get_options();
   or_options_t *options = get_options();
   int fetch_fresh_first = server_mode(options) && options->DirPort != 0;
   int fetch_fresh_first = server_mode(options) && options->DirPort != 0;
   int directconn = !purpose_is_private(purpose);
   int directconn = !purpose_is_private(purpose);
@@ -175,19 +170,21 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource,
         !strcmpstart(resource,"fp/") && strlen(resource) == HEX_DIGEST_LEN+3) {
         !strcmpstart(resource,"fp/") && strlen(resource) == HEX_DIGEST_LEN+3) {
       /* Try to ask the actual dirserver its opinion. */
       /* Try to ask the actual dirserver its opinion. */
       char digest[DIGEST_LEN];
       char digest[DIGEST_LEN];
+      trusted_dir_server_t *ds;
       base16_decode(digest, DIGEST_LEN, resource+3, HEX_DIGEST_LEN);
       base16_decode(digest, DIGEST_LEN, resource+3, HEX_DIGEST_LEN);
       ds = router_get_trusteddirserver_by_digest(digest);
       ds = router_get_trusteddirserver_by_digest(digest);
+      rs = &(ds->fake_status);
     }
     }
-    if (!ds && fetch_fresh_first) {
+    if (!rs && fetch_fresh_first) {
       /* only ask authdirservers, and don't ask myself */
       /* only ask authdirservers, and don't ask myself */
-      ds = router_pick_trusteddirserver(need_v1_support, 1, 1,
+      rs = router_pick_trusteddirserver(need_v1_support, 1, 1,
                                         retry_if_no_servers);
                                         retry_if_no_servers);
     }
     }
-    if (!ds) {
+    if (!rs) {
       /* anybody with a non-zero dirport will do */
       /* anybody with a non-zero dirport will do */
-      r = router_pick_directory_server(1, 1, need_v2_support,
+      rs = router_pick_directory_server(1, 1, need_v2_support,
-                                       retry_if_no_servers);
+                                        retry_if_no_servers);
-      if (!r) {
+      if (!rs) {
         const char *which;
         const char *which;
         if (purpose == DIR_PURPOSE_FETCH_DIR)
         if (purpose == DIR_PURPOSE_FETCH_DIR)
           which = "directory";
           which = "directory";
@@ -199,9 +196,9 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource,
           which = "server descriptors";
           which = "server descriptors";
         info(LD_DIR,
         info(LD_DIR,
              "No router found for %s; falling back to dirserver list", which);
              "No router found for %s; falling back to dirserver list", which);
-        ds = router_pick_trusteddirserver(1, 1, 1,
+        rs = router_pick_trusteddirserver(1, 1, 1,
                                           retry_if_no_servers);
                                           retry_if_no_servers);
-        if (!ds)
+        if (!rs)
           directconn = 0; /* last resort: try routing it via Tor */
           directconn = 0; /* last resort: try routing it via Tor */
       }
       }
     }
     }
@@ -210,20 +207,18 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource,
     /* Never use fascistfirewall; we're going via Tor. */
     /* Never use fascistfirewall; we're going via Tor. */
     if (purpose == DIR_PURPOSE_FETCH_RENDDESC) {
     if (purpose == DIR_PURPOSE_FETCH_RENDDESC) {
       /* only ask authdirservers, any of them will do */
       /* only ask authdirservers, any of them will do */
-      ds = router_pick_trusteddirserver(0, 0, 0, retry_if_no_servers);
+      rs = router_pick_trusteddirserver(0, 0, 0, retry_if_no_servers);
     } else {
     } else {
       /* anybody with a non-zero dirport will do. Disregard firewalls. */
       /* anybody with a non-zero dirport will do. Disregard firewalls. */
-      r = router_pick_directory_server(1, 0, need_v2_support,
+      rs = router_pick_directory_server(1, 0, need_v2_support,
-                                       retry_if_no_servers);
+                                        retry_if_no_servers);
+      /* XXXX If no rs, fall back to trusted dir servers? -NM */
     }
     }
   }
   }
 
 
-  if (r)
+  if (rs)
-    directory_initiate_command_router(r, purpose, !directconn,
+    directory_initiate_command_routerstatus(rs, purpose, !directconn,
-                                      resource, NULL, 0);
+                                            resource, NULL, 0);
-  else if (ds)
-    directory_initiate_command_trusted_dir(ds, purpose, !directconn,
-                                           resource, NULL, 0);
   else {
   else {
     notice(LD_DIR,
     notice(LD_DIR,
            "No running dirservers known. Will try again later. (purpose %d)",
            "No running dirservers known. Will try again later. (purpose %d)",
@@ -247,28 +242,56 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource,
  * want to fetch.
  * want to fetch.
  */
  */
 void
 void
-directory_initiate_command_router(routerinfo_t *router, uint8_t purpose,
+directory_initiate_command_router(routerinfo_t *router,
-                                  int private_connection, const char *resource,
+                                  uint8_t purpose,
-                                  const char *payload, size_t payload_len)
+                                  int private_connection,
+                                  const char *resource,
+                                  const char *payload,
+                                  size_t payload_len)
 {
 {
   directory_initiate_command(router->address, router->addr, router->dir_port,
   directory_initiate_command(router->address, router->addr, router->dir_port,
-                         router->platform, router->cache_info.identity_digest,
+                             router->platform,
-                         purpose, private_connection, resource,
+                             router->cache_info.identity_digest,
-                         payload, payload_len);
+                             purpose, private_connection, resource,
+                             payload, payload_len);
 }
 }
 
 
-/** As directory_initiate_command_router, but send the command to a trusted
+/** Launch a new connection to the directory server <b>status</b> to upload or
- * directory server <b>dirserv</b>. **/
+ * download a service or rendezvous descriptor. <b>purpose</b> determines what
-static void
+ * kind of directory connection we're launching, and must be one of
-directory_initiate_command_trusted_dir(trusted_dir_server_t *dirserv,
+ * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}.
-                                       uint8_t purpose, int private_connection,
+ *
-                                       const char *resource,
+ * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
-                                       const char *payload, size_t payload_len)
+ * of the HTTP post.  Otherwise, <b>payload</b> should be NULL.
+ *
+ * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
+ * want to fetch.
+ */
+void
+directory_initiate_command_routerstatus(routerstatus_t *status,
+                                        uint8_t purpose,
+                                        int private_connection,
+                                        const char *resource,
+                                        const char *payload,
+                                        size_t payload_len)
 {
 {
-  directory_initiate_command(dirserv->address, dirserv->addr,
+  const char *platform = NULL;
-               dirserv->dir_port, NULL, dirserv->digest, purpose,
+  routerinfo_t *router;
-               private_connection, resource,
+  char address_buf[INET_NTOA_BUF_LEN];
-               payload, payload_len);
+  struct in_addr in;
+  const char *address;
+  if ((router = router_get_by_digest(status->identity_digest))) {
+    platform = router->platform;
+    address = router->address;
+  } else {
+    in.s_addr = htonl(status->addr);
+    tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
+    address = address_buf;
+  }
+  directory_initiate_command(address, status->addr, status->dir_port,
+                             platform, status->identity_digest,
+                             purpose, private_connection, resource,
+                             payload, payload_len);
 }
 }
 
 
 /** Called when we are unable to complete the client's request to a
 /** Called when we are unable to complete the client's request to a

+ 19 - 11
src/or/or.h

@@ -1822,6 +1822,12 @@ void directory_initiate_command_router(routerinfo_t *router, uint8_t purpose,
                                        const char *resource,
                                        const char *resource,
                                        const char *payload,
                                        const char *payload,
                                        size_t payload_len);
                                        size_t payload_len);
+void directory_initiate_command_routerstatus(routerstatus_t *status,
+                                             uint8_t purpose,
+                                             int private_connection,
+                                             const char *resource,
+                                             const char *payload,
+                                             size_t payload_len);
 
 
 int parse_http_response(const char *headers, int *code, time_t *date,
 int parse_http_response(const char *headers, int *code, time_t *date,
                         int *compression, char **response);
                         int *compression, char **response);
@@ -2183,24 +2189,26 @@ typedef struct trusted_dir_server_t {
   uint16_t dir_port; /**< Directory port */
   uint16_t dir_port; /**< Directory port */
   char digest[DIGEST_LEN]; /**< Digest of identity key */
   char digest[DIGEST_LEN]; /**< Digest of identity key */
   unsigned int is_running:1; /**< True iff we think this server is running. */
   unsigned int is_running:1; /**< True iff we think this server is running. */
-  unsigned int supports_v1_protocol:1; /**< True iff this server is an
+  unsigned int is_v1_authority:1; /**< True iff this server is an
-                                        * authority for the older ("v1")
+                                   * authority for the older ("v1")
-                                        * directory protocol.*/
+                                   * directory protocol.*/
   int n_networkstatus_failures; /**< How many times have we asked for this
   int n_networkstatus_failures; /**< How many times have we asked for this
                                  * server's network-status unsuccessfully? */
                                  * server's network-status unsuccessfully? */
+  routerstatus_t fake_status; /**< Used when we need to pass this trusted
+                               * dir_server_t as a routerstatus_t. */
 } trusted_dir_server_t;
 } trusted_dir_server_t;
 
 
 int router_reload_router_list(void);
 int router_reload_router_list(void);
 int router_reload_networkstatus(void);
 int router_reload_networkstatus(void);
 void router_get_trusted_dir_servers(smartlist_t **outp);
 void router_get_trusted_dir_servers(smartlist_t **outp);
-routerinfo_t *router_pick_directory_server(int requireother,
+routerstatus_t *router_pick_directory_server(int requireother,
-                                           int fascistfirewall,
+                                             int fascistfirewall,
-                                           int for_v2_directory,
+                                             int for_v2_directory,
-                                           int retry_if_no_servers);
+                                             int retry_if_no_servers);
-trusted_dir_server_t *router_pick_trusteddirserver(int need_v1_support,
+routerstatus_t *router_pick_trusteddirserver(int need_v1_authority,
-                                                   int requireother,
+                                             int requireother,
-                                                   int fascistfirewall,
+                                             int fascistfirewall,
-                                                   int retry_if_no_servers);
+                                             int retry_if_no_servers);
 trusted_dir_server_t *router_get_trusteddirserver_by_digest(
 trusted_dir_server_t *router_get_trusteddirserver_by_digest(
      const char *digest);
      const char *digest);
 int all_trusted_directory_servers_down(void);
 int all_trusted_directory_servers_down(void);

+ 2 - 1
src/or/relay.c

@@ -3,7 +3,8 @@
  * Copyright 2004-2005 Roger Dingledine, Nick Mathewson. */
  * Copyright 2004-2005 Roger Dingledine, Nick Mathewson. */
 /* See LICENSE for licensing information */
 /* See LICENSE for licensing information */
 /* $Id$ */
 /* $Id$ */
-const char relay_c_id[] = "$Id$";
+const char relay_c_id[] =
+  "$Id$";
 
 
 /**
 /**
  * \file relay.c
  * \file relay.c

+ 64 - 39
src/or/routerlist.c

@@ -18,11 +18,11 @@ const char routerlist_c_id[] =
 /****************************************************************************/
 /****************************************************************************/
 
 
 /* static function prototypes */
 /* static function prototypes */
-static routerinfo_t *router_pick_directory_server_impl(int requireother,
+static routerstatus_t *router_pick_directory_server_impl(int requireother,
-                                                       int fascistfirewall,
+                                                         int fascistfirewall,
-                                                       int for_v2_directory);
+                                                         int for_v2_directory);
-static trusted_dir_server_t *router_pick_trusteddirserver_impl(
+static routerstatus_t *router_pick_trusteddirserver_impl(
-                int need_v1_support, int requireother, int fascistfirewall);
+                 int need_v1_authority, int requireother, int fascistfirewall);
 static void mark_all_trusteddirservers_up(void);
 static void mark_all_trusteddirservers_up(void);
 static int router_nickname_is_in_list(routerinfo_t *router, const char *list);
 static int router_nickname_is_in_list(routerinfo_t *router, const char *list);
 static int router_nickname_matches(routerinfo_t *router, const char *nickname);
 static int router_nickname_matches(routerinfo_t *router, const char *nickname);
@@ -321,13 +321,13 @@ router_get_trusted_dir_servers(smartlist_t **outp)
  * (that is, a trusted dirserver, or one running 0.0.9rc5-cvs or later).
  * (that is, a trusted dirserver, or one running 0.0.9rc5-cvs or later).
  * Other args are as in router_pick_directory_server_impl().
  * Other args are as in router_pick_directory_server_impl().
  */
  */
-routerinfo_t *
+routerstatus_t *
 router_pick_directory_server(int requireother,
 router_pick_directory_server(int requireother,
                              int fascistfirewall,
                              int fascistfirewall,
                              int for_v2_directory,
                              int for_v2_directory,
                              int retry_if_no_servers)
                              int retry_if_no_servers)
 {
 {
-  routerinfo_t *choice;
+  routerstatus_t *choice;
 
 
   if (!routerlist)
   if (!routerlist)
     return NULL;
     return NULL;
@@ -358,6 +358,9 @@ router_pick_directory_server(int requireother,
   return choice;
   return choice;
 }
 }
 
 
+/** Return the trusted_dir_server_t for the directory authority whose identity
+ * key hashes to <b>digest</b>, or NULL if no such authority is known.
+ */
 trusted_dir_server_t *
 trusted_dir_server_t *
 router_get_trusteddirserver_by_digest(const char *digest)
 router_get_trusteddirserver_by_digest(const char *digest)
 {
 {
@@ -376,24 +379,26 @@ router_get_trusteddirserver_by_digest(const char *digest)
 /** Try to find a running trusted dirserver. If there are no running
 /** Try to find a running trusted dirserver. If there are no running
  * trusted dirservers and <b>retry_if_no_servers</b> is non-zero,
  * trusted dirservers and <b>retry_if_no_servers</b> is non-zero,
  * set them all as running again, and try again.
  * set them all as running again, and try again.
+ * If <b>need_v1_authority</b> is set, return only trusted servers
+ * that are authorities for the V1 directory protocol.
  * Other args are as in router_pick_trusteddirserver_impl().
  * Other args are as in router_pick_trusteddirserver_impl().
  */
  */
-trusted_dir_server_t *
+routerstatus_t *
-router_pick_trusteddirserver(int need_v1_support,
+router_pick_trusteddirserver(int need_v1_authority,
                              int requireother,
                              int requireother,
                              int fascistfirewall,
                              int fascistfirewall,
                              int retry_if_no_servers)
                              int retry_if_no_servers)
 {
 {
-  trusted_dir_server_t *choice;
+  routerstatus_t *choice;
 
 
-  choice = router_pick_trusteddirserver_impl(need_v1_support,
+  choice = router_pick_trusteddirserver_impl(need_v1_authority,
                                              requireother, fascistfirewall);
                                              requireother, fascistfirewall);
   if (choice || !retry_if_no_servers)
   if (choice || !retry_if_no_servers)
     return choice;
     return choice;
 
 
   info(LD_DIR,"No trusted dirservers are reachable. Trying them all again.");
   info(LD_DIR,"No trusted dirservers are reachable. Trying them all again.");
   mark_all_trusteddirservers_up();
   mark_all_trusteddirservers_up();
-  return router_pick_trusteddirserver_impl(need_v1_support,
+  return router_pick_trusteddirserver_impl(need_v1_authority,
                                            requireother, fascistfirewall);
                                            requireother, fascistfirewall);
 }
 }
 
 
@@ -405,37 +410,34 @@ router_pick_trusteddirserver(int need_v1_support,
  * choose a directory server new enough to support the v2 directory
  * choose a directory server new enough to support the v2 directory
  * functionality.
  * functionality.
  */
  */
-static routerinfo_t *
+static routerstatus_t *
 router_pick_directory_server_impl(int requireother, int fascistfirewall,
 router_pick_directory_server_impl(int requireother, int fascistfirewall,
                                   int for_v2_directory)
                                   int for_v2_directory)
 {
 {
-  routerinfo_t *result;
+  routerstatus_t *result;
   smartlist_t *sl;
   smartlist_t *sl;
 
 
-  if (!routerlist)
+  if (!routerstatus_list)
     return NULL;
     return NULL;
 
 
   /* Find all the running dirservers we know about. */
   /* Find all the running dirservers we know about. */
   sl = smartlist_create();
   sl = smartlist_create();
-  SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
+  SMARTLIST_FOREACH(routerstatus_list, local_routerstatus_t *, _local_status,
   {
   {
-    if (!router->is_running || !router->dir_port || !router->is_verified)
+    routerstatus_t *status = &(_local_status->status);
+    if (!status->is_running || !status->dir_port || !status->is_valid)
       continue;
       continue;
-    if (requireother && router_is_me(router))
+    if (requireother && router_digest_is_me(status->identity_digest))
       continue;
       continue;
     if (fascistfirewall) {
     if (fascistfirewall) {
-      if (!fascist_firewall_allows_address(router->addr, router->dir_port))
+      if (!fascist_firewall_allows_address(status->addr, status->dir_port))
         continue;
         continue;
     }
     }
-    /* Before 0.1.1.6-alpha, only trusted dirservers served status info.
-     * Before 0.1.1.7-alpha, retrieving nonexistent server IDs could bork
-     * the directory server.
-     */
     if (for_v2_directory &&
     if (for_v2_directory &&
-        !(tor_version_as_new_as(router->platform,"0.1.1.7-alpha") ||
+        !(status->is_v2_dir ||
-          router_digest_is_trusted_dir(router->cache_info.identity_digest)))
+          router_digest_is_trusted_dir(status->identity_digest)))
       continue;
       continue;
-    smartlist_add(sl, router);
+    smartlist_add(sl, status);
   });
   });
 
 
   result = smartlist_choose(sl);
   result = smartlist_choose(sl);
@@ -443,19 +445,19 @@ router_pick_directory_server_impl(int requireother, int fascistfirewall,
   return result;
   return result;
 }
 }
 
 
-/** Choose randomly from among the trusted dirservers that are up.
+/** Choose randomly from among the trusted dirservers that are up.  If
- * If <b>fascistfirewall</b>,
+ * <b>fascistfirewall</b>, make sure the port we pick is allowed by our
- * make sure the port we pick is allowed by our firewall options.
+ * firewall options.  If <b>requireother</b>, it cannot be us.  If
- * If <b>requireother</b>, it cannot be us.  If <b>need_v1_support</b>, choose
+ * <b>need_v1_authority</b>, choose a trusted authority for the v1 directory
- * a trusted authority for the v1 directory system.
+ * system.
  */
  */
-static trusted_dir_server_t *
+static routerstatus_t *
-router_pick_trusteddirserver_impl(int need_v1_support,
+router_pick_trusteddirserver_impl(int need_v1_authority,
                                   int requireother, int fascistfirewall)
                                   int requireother, int fascistfirewall)
 {
 {
   smartlist_t *sl;
   smartlist_t *sl;
   routerinfo_t *me;
   routerinfo_t *me;
-  trusted_dir_server_t *ds;
+  routerstatus_t *rs;
   sl = smartlist_create();
   sl = smartlist_create();
   me = router_get_my_routerinfo();
   me = router_get_my_routerinfo();
 
 
@@ -465,7 +467,7 @@ router_pick_trusteddirserver_impl(int need_v1_support,
   SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d,
   SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d,
     {
     {
       if (!d->is_running) continue;
       if (!d->is_running) continue;
-      if (need_v1_support && !d->supports_v1_protocol)
+      if (need_v1_authority && !d->is_v1_authority)
         continue;
         continue;
       if (requireother && me && router_digest_is_me(d->digest))
       if (requireother && me && router_digest_is_me(d->digest))
           continue;
           continue;
@@ -473,12 +475,12 @@ router_pick_trusteddirserver_impl(int need_v1_support,
         if (!fascist_firewall_allows_address(d->addr, d->dir_port))
         if (!fascist_firewall_allows_address(d->addr, d->dir_port))
           continue;
           continue;
       }
       }
-      smartlist_add(sl, d);
+      smartlist_add(sl, &d->fake_status);
     });
     });
 
 
-  ds = smartlist_choose(sl);
+  rs = smartlist_choose(sl);
   smartlist_free(sl);
   smartlist_free(sl);
-  return ds;
+  return rs;
 }
 }
 
 
 /** Go through and mark the authoritative dirservers as up. */
 /** Go through and mark the authoritative dirservers as up. */
@@ -2526,7 +2528,7 @@ add_trusted_dir_server(const char *nickname, const char *address,
   ent->addr = a;
   ent->addr = a;
   ent->dir_port = port;
   ent->dir_port = port;
   ent->is_running = 1;
   ent->is_running = 1;
-  ent->supports_v1_protocol = supports_v1;
+  ent->is_v1_authority = supports_v1;
   memcpy(ent->digest, digest, DIGEST_LEN);
   memcpy(ent->digest, digest, DIGEST_LEN);
 
 
   dlen = 64 + strlen(hostname) + (nickname?strlen(nickname):0);
   dlen = 64 + strlen(hostname) + (nickname?strlen(nickname):0);
@@ -2538,6 +2540,16 @@ add_trusted_dir_server(const char *nickname, const char *address,
     tor_snprintf(ent->description, dlen, "directory server at %s:%d",
     tor_snprintf(ent->description, dlen, "directory server at %s:%d",
                  hostname, (int)port);
                  hostname, (int)port);
 
 
+  ent->fake_status.addr = ent->addr;
+  memcpy(ent->fake_status.identity_digest, digest, DIGEST_LEN);
+  strlcpy(ent->fake_status.nickname, nickname,
+          sizeof(ent->fake_status.nickname));
+  ent->fake_status.dir_port = ent->dir_port;
+  ent->fake_status.is_running = 1;
+  ent->fake_status.is_named = 1;
+  ent->fake_status.is_valid = 1;
+  ent->fake_status.is_v2_dir = 1;
+
   smartlist_add(trusted_dir_servers, ent);
   smartlist_add(trusted_dir_servers, ent);
 }
 }
 
 
@@ -2848,6 +2860,7 @@ routerstatus_list_update_from_networkstatus(time_t now)
    */
    */
   while (1) {
   while (1) {
     int n_running=0, n_named=0, n_valid=0, n_listing=0;
     int n_running=0, n_named=0, n_valid=0, n_listing=0;
+    int n_v2_dir=0, n_fast=0, n_stable=0, n_exit=0;
     const char *the_name = NULL;
     const char *the_name = NULL;
     local_routerstatus_t *rs_out, *rs_old;
     local_routerstatus_t *rs_out, *rs_old;
     routerstatus_t *rs, *most_recent;
     routerstatus_t *rs, *most_recent;
@@ -2902,6 +2915,14 @@ routerstatus_list_update_from_networkstatus(time_t now)
         ++n_valid;
         ++n_valid;
       if (rs->is_running && ns->is_recent)
       if (rs->is_running && ns->is_recent)
         ++n_running;
         ++n_running;
+      if (rs->is_exit)
+        ++n_exit;
+      if (rs->is_fast)
+        ++n_fast;
+      if (rs->is_stable)
+        ++n_stable;
+      if (rs->is_v2_dir)
+        ++n_v2_dir;
     }
     }
     rs_out = tor_malloc_zero(sizeof(local_routerstatus_t));
     rs_out = tor_malloc_zero(sizeof(local_routerstatus_t));
     memcpy(&rs_out->status, most_recent, sizeof(routerstatus_t));
     memcpy(&rs_out->status, most_recent, sizeof(routerstatus_t));
@@ -2930,6 +2951,10 @@ routerstatus_list_update_from_networkstatus(time_t now)
               sizeof(rs_out->status.nickname));
               sizeof(rs_out->status.nickname));
     rs_out->status.is_valid = n_valid > n_statuses/2;
     rs_out->status.is_valid = n_valid > n_statuses/2;
     rs_out->status.is_running = n_running > n_recent/2;
     rs_out->status.is_running = n_running > n_recent/2;
+    rs_out->status.is_exit = n_exit > n_statuses/2;
+    rs_out->status.is_fast = n_fast > n_statuses/2;
+    rs_out->status.is_stable = n_stable > n_statuses/2;
+    rs_out->status.is_v2_dir = n_v2_dir > n_statuses/2;
   }
   }
   SMARTLIST_FOREACH(routerstatus_list, local_routerstatus_t *, rs,
   SMARTLIST_FOREACH(routerstatus_list, local_routerstatus_t *, rs,
                     local_routerstatus_free(rs));
                     local_routerstatus_free(rs));