[or-cvs] Add and document router-status line using new unified liven...

Nick Mathewson nickm at seul.org
Wed Oct 27 00:48:53 UTC 2004


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

Modified Files:
	dirserv.c or.h routerlist.c routerparse.c 
Log Message:
Add and document router-status line using new unified liveness/verifiedness format; continue to generate running-routers; continue to parse running-routers when no router-status line is found

Index: dirserv.c
===================================================================
RCS file: /home/or/cvsroot/src/or/dirserv.c,v
retrieving revision 1.99
retrieving revision 1.100
diff -u -d -r1.99 -r1.100
--- dirserv.c	15 Oct 2004 05:09:48 -0000	1.99
+++ dirserv.c	27 Oct 2004 00:48:51 -0000	1.100
@@ -20,7 +20,8 @@
 static int the_directory_is_dirty = 1;
 static int runningrouters_is_dirty = 1;
 
-static int list_running_servers(char **nicknames_out);
+static int list_server_status(char **running_routers_out,
+                              char **router_status_out);
 static void directory_remove_unrecognized(void);
 static int dirserv_regenerate_directory(void);
 
@@ -456,71 +457,80 @@
   return 0;
 }
 
-/** Set *<b>nicknames_out</b> to a comma-separated list of all the ORs that we
- * believe are currently running (because we have open connections to
- * them).  Return 0 on success; -1 on error.
+/**
+ * Allocate and return a description of the status of the server <b>desc</b>,
+ * for use in a running-routers line (if <b>rr_format</b> is true), or in a
+ * router-status line (if <b>rr_format</b> is false.  The server is listed 
+ * as running iff <b>is_live</b> is true.
  */
-static int
-list_running_servers(char **nicknames_out)
+static char *
+list_single_server_status(descriptor_entry_t *desc, int is_live,
+                          int rr_format)
 {
-  connection_t **connection_array;
-  int n_conns;
-  connection_t *conn;
+  char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
   char *cp;
-  int i;
-  size_t length;
-  smartlist_t *nicknames_up, *nicknames_down;
-  char *name;
-  const char *s;
-
-  *nicknames_out = NULL;
-  nicknames_up = smartlist_create();
-  nicknames_down = smartlist_create();
-  smartlist_add(nicknames_up, tor_strdup(options.Nickname));
 
-  get_connection_array(&connection_array, &n_conns);
-  for (i = 0; i<n_conns; ++i) {
-    conn = connection_array[i];
-    if (conn->type != CONN_TYPE_OR || !conn->nickname)
-      continue; /* only list connections to ORs with certificates. */
-    s = dirserv_get_nickname_by_digest(conn->identity_digest);
-    if (s) {
-      name = tor_strdup(s);
-    } else {
-      name = tor_malloc(HEX_DIGEST_LEN+2);
-      *name = '$';
-      base16_encode(name+1, HEX_DIGEST_LEN+1, conn->identity_digest, DIGEST_LEN);
-    }
+  tor_assert(desc);
+  tor_assert(desc->router);
 
-    if(conn->state == OR_CONN_STATE_OPEN)
-      smartlist_add(nicknames_up, name);
-    else
-      smartlist_add(nicknames_down, name);
+  cp = buf;
+  if (!is_live) {
+    *cp++ = '!';
   }
-  length = smartlist_len(nicknames_up) +
-           2*smartlist_len(nicknames_down) + 1;
-           /* spaces + EOS + !'s + 1. */
-  SMARTLIST_FOREACH(nicknames_up, char *, c, length += strlen(c));
-  SMARTLIST_FOREACH(nicknames_down, char *, c, length += strlen(c));
-  *nicknames_out = tor_malloc_zero(length);
-  cp = *nicknames_out;
-  for (i = 0; i<smartlist_len(nicknames_up); ++i) {
-    if (i)
-      strcat(cp, " ");
-    strcat(cp, (char*)smartlist_get(nicknames_up,i)); /* can't overflow */
-    while (*cp)
-      ++cp;
+  if (desc->verified) {
+    strcpy(cp, desc->nickname);
+    cp += strlen(cp);
+    if (!rr_format)
+      *cp++ = '=';
   }
-  for (i = 0; i<smartlist_len(nicknames_down); ++i) {
-    strcat(cp, " !");
-    strcat(cp, (char*)smartlist_get(nicknames_down,i)); /* can't overflow */
-    while (*cp)
-      ++cp;
+  if (!desc->verified || !rr_format) {
+    *cp++ = '$';
+    base16_encode(cp, HEX_DIGEST_LEN+1, desc->router->identity_digest,
+                  DIGEST_LEN);
   }
-  SMARTLIST_FOREACH(nicknames_up, char *, victim, tor_free(victim));
-  SMARTLIST_FOREACH(nicknames_down, char *, victim, tor_free(victim));
-  smartlist_free(nicknames_up);
-  smartlist_free(nicknames_down);
+  return tor_strdup(buf);
+}
+
+/** Allocate the contents of a running-routers line and a router-status line,
+ * and store them in *<b>running_routers_out</b> and *<b>router_status_out</b>
+ * respectively.  Return 0 on success, -1 on failure.
+ */
+static int
+list_server_status(char **running_routers_out, char **router_status_out)
+{
+  /* List of entries in running-routers style: An optional !, then either
+   * a nickname or a dollar-prefixed hexdigest. */
+  smartlist_t *rr_entries; 
+  /* List of entries in a router-status style: An optional !, then an optional
+   * equals-suffixed nickname, then a dollar-prefixed hexdigest. */
+  smartlist_t *rs_entries;
+
+  tor_assert(running_routers_out || router_status_out);
+
+  rr_entries = smartlist_create();
+  rs_entries = smartlist_create();
+
+  SMARTLIST_FOREACH(descriptor_list, descriptor_entry_t *, d,
+  {
+    int is_live;
+    tor_assert(d->router);
+    connection_t *conn = connection_get_by_identity_digest(
+                    d->router->identity_digest, CONN_TYPE_OR);
+    is_live = (conn && conn->state == OR_CONN_STATE_OPEN);
+    smartlist_add(rr_entries, list_single_server_status(d, is_live, 1));
+    smartlist_add(rs_entries, list_single_server_status(d, is_live, 0));
+  });
+
+  if (running_routers_out)
+    *running_routers_out = smartlist_join_strings(rr_entries, " ", 0);
+  if (router_status_out)
+    *router_status_out = smartlist_join_strings(rs_entries, " ", 0);
+
+  SMARTLIST_FOREACH(rr_entries, char *, cp, tor_free(cp));
+  SMARTLIST_FOREACH(rs_entries, char *, cp, tor_free(cp));
+  smartlist_free(rr_entries);
+  smartlist_free(rs_entries);
+
   return 0;
 }
 
@@ -557,7 +567,8 @@
 dirserv_dump_directory_to_string(char *s, size_t maxlen,
                                  crypto_pk_env_t *private_key)
 {
-  char *cp, *eos;
+  char *eos, *cp;
+  char *running_routers, *router_status;
   char *identity_pkey; /* Identity key, DER64-encoded. */
   char *recommended_versions;
   char digest[20];
@@ -570,7 +581,7 @@
   if (!descriptor_list)
     descriptor_list = smartlist_create();
 
-  if (list_running_servers(&cp))
+  if (list_server_status(&running_routers, &router_status))
     return -1;
 
   /* ASN.1-encode the public key.  This is a temporary measure; once
@@ -612,10 +623,13 @@
            "published %s\n"
            "recommended-software %s\n"
            "running-routers %s\n"
+           "opt router-status %s\n"
            "opt dir-signing-key %s\n\n",
-           published, recommended_versions, cp, identity_pkey);
+           published, recommended_versions, running_routers, router_status,
+           identity_pkey);
 
-  tor_free(cp);
+  tor_free(running_routers);
+  tor_free(router_status);
   tor_free(identity_pkey);
   i = strlen(s);
   cp = s+i;
@@ -788,6 +802,7 @@
 static int generate_runningrouters(crypto_pk_env_t *private_key)
 {
   char *s, *cp;
+  char *router_status;
   char digest[DIGEST_LEN];
   char signature[PK_BYTES];
   int i;
@@ -798,7 +813,7 @@
 
   len = 1024+(MAX_HEX_NICKNAME_LEN+2)*smartlist_len(descriptor_list);
   s = tor_malloc_zero(len);
-  if (list_running_servers(&cp))
+  if (list_server_status(NULL, &router_status))
     return -1;
   /* ASN.1-encode the public key.  This is a temporary measure; once
    * everyone is running 0.0.9pre3 or later, we can shift to using a
@@ -822,12 +837,12 @@
   format_iso_time(published, published_on);
   sprintf(s, "network-status\n"
              "published %s\n"
-             "running-routers %s\n"
+             "router-status %s\n"
              "opt dir-signing-key %s\n"
              "directory-signature %s\n"
              "-----BEGIN SIGNATURE-----\n",
-          published, cp, identity_pkey, options.Nickname);
-  tor_free(cp);
+          published, router_status, identity_pkey, options.Nickname);
+  tor_free(router_status);
   tor_free(identity_pkey);
   if (router_get_runningrouters_hash(s,digest)) {
     log_fn(LOG_WARN,"couldn't compute digest");

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.444
retrieving revision 1.445
diff -u -d -r1.444 -r1.445
--- or.h	25 Oct 2004 06:16:26 -0000	1.444
+++ or.h	27 Oct 2004 00:48:51 -0000	1.445
@@ -621,6 +621,7 @@
   time_t published_on; /**< When was the list marked as published? */
   /** Which ORs are on the list?  Entries may be prefixed with ! and $. */
   smartlist_t *running_routers;
+  int is_running_routers_format; /**< Are we using the old entry format? */
 } running_routers_t;
 
 /** Holds accounting information for a single step in the layered encryption
@@ -1469,9 +1470,14 @@
 void running_routers_free(running_routers_t *rr);
 void routerlist_update_from_runningrouters(routerlist_t *list,
                                            running_routers_t *rr);
+int routers_update_status_from_entry(smartlist_t *routers,
+                                        time_t list_time,
+                                        const char *s,
+                                        int rr_format);
 int router_update_status_from_smartlist(routerinfo_t *r,
                                         time_t list_time,
-                                        smartlist_t *running_list);
+                                        smartlist_t *running_list,
+                                        int rr_format);
 void add_trusted_dir_server(const char *addr, uint16_t port,const char *digest);
 void clear_trusted_dir_servers(void);
 
@@ -1493,6 +1499,7 @@
 int router_parse_list_from_string(const char **s,
                                   routerlist_t **dest,
                                   smartlist_t *good_nickname_list,
+                                  int rr_format,                        
                                   time_t published);
 int router_parse_routerlist_from_directory(const char *s,
                                            routerlist_t **dest,

Index: routerlist.c
===================================================================
RCS file: /home/or/cvsroot/src/or/routerlist.c,v
retrieving revision 1.165
retrieving revision 1.166
diff -u -d -r1.165 -r1.166
--- routerlist.c	19 Oct 2004 18:19:59 -0000	1.165
+++ routerlist.c	27 Oct 2004 00:48:51 -0000	1.166
@@ -1018,8 +1018,8 @@
 void routerlist_update_from_runningrouters(routerlist_t *list,
                                            running_routers_t *rr)
 {
-  int n_routers, i;
-  routerinfo_t *router, *me = router_get_my_routerinfo();
+  routerinfo_t *me = router_get_my_routerinfo();
+  smartlist_t *all_routers;
   if (!list)
     return;
   if (list->published_on >= rr->published_on)
@@ -1027,18 +1027,15 @@
   if (list->running_routers_updated_on >= rr->published_on)
     return;
 
-  if(me) { /* learn if the dirservers think I'm verified */
-    router_update_status_from_smartlist(me,
-                                        rr->published_on,
-                                        rr->running_routers);
-  }
-  n_routers = smartlist_len(list->routers);
-  for (i=0; i<n_routers; ++i) {
-    router = smartlist_get(list->routers, i);
-    router_update_status_from_smartlist(router,
-                                        rr->published_on,
-                                        rr->running_routers);
-  }
+  all_routers = smartlist_create();
+  if(me) /* learn if the dirservers think I'm verified */
+    smartlist_add(all_routers, me);
+  
+  smartlist_add_all(all_routers,list->routers);
+  SMARTLIST_FOREACH(rr->running_routers, const char *, cp,
+     routers_update_status_from_entry(all_routers, rr->published_on,
+                                      cp, rr->is_running_routers_format));
+  smartlist_free(all_routers);
   list->running_routers_updated_on = rr->published_on;
 }
 
@@ -1046,6 +1043,14 @@
  * based in its status in the list of strings stored in <b>running_list</b>.
  * All entries in <b>running_list</b> follow one of these formats:
  * <ol><li> <b>nickname</b> -- router is running and verified.
+ *          (running-routers format)
+ *     <li> !<b>nickname</b> -- router is not-running and verified.
+ *          (running-routers format)
+ *     <li> <b>nickname</b>=$<b>hexdigest</b> -- router is running and 
+ *          verified. (router-status format)
+ *          (router-status format)
+ *     <li> !<b>nickname</b>=$<b>hexdigest</b> -- router is running and 
+ *          verified. (router-status format)
  *     <li> !<b>nickname</b> -- router is not-running and verified.
  *     <li> $<b>hexdigest</b> -- router is running and unverified.
  *     <li> !$<b>hexdigest</b> -- router is not-running and unverified.
@@ -1053,57 +1058,115 @@
  *
  * Return 1 if we found router in running_list, else return 0.
  */
-int router_update_status_from_smartlist(routerinfo_t *router,
-                                        time_t list_time,
-                                        smartlist_t *running_list)
+int routers_update_status_from_entry(smartlist_t *routers,
+                                     time_t list_time,
+                                     const char *s,
+                                     int rr_format)
 {
-  int n_names, i, running, approved;
-  const char *name;
-#if 1
-  char *cp;
-  size_t n;
-  n = 0;
-  for (i=0; i<smartlist_len(running_list); ++i) {
-    name = smartlist_get(running_list, i);
-    n += strlen(name) + 1;
+  int is_running = 1;
+  int is_verified = 0;
+  int hex_digest_set = 0;
+  char nickname[MAX_NICKNAME_LEN+1];
+  char hexdigest[HEX_DIGEST_LEN+1];
+  char digest[DIGEST_LEN];
+  const char *cp, *end;
+
+  /* First, parse the entry. */
+  cp = s;
+  if (*cp == '!') {
+    is_running = 0;
+    ++cp;
   }
-  cp = tor_malloc(n+2);
-  cp[0] = '\0';
-  for (i=0; i<smartlist_len(running_list); ++i) {
-    name = smartlist_get(running_list, i);
-    strlcat(cp, name, n);
-    strlcat(cp, " ", n);
+
+  if (*cp != '$') {
+    /* It starts with a non-dollar character; that's a nickname.  The nickname
+     * entry will either extend to a NUL (old running-routers format) or to an
+     * equals sign (new router-status format). */
+    is_verified = 1;
+    end = strchr(cp, '=');
+    if (!end)
+      end = strchr(cp,'\0');
+    tor_assert(end);
+    /* 'end' now points on character beyond the end of the nickname */
+    if (end == cp || end-cp > MAX_NICKNAME_LEN) {
+      log_fn(LOG_WARN, "Bad nickname length (%d) in router status entry (%s)",
+             end-cp, s);
+      return -1;
+    }
+    memcpy(nickname, cp, end-cp);
+    nickname[end-cp]='\0';
+    if (!is_legal_nickname(nickname)) {
+      log_fn(LOG_WARN, "Bad nickname (%s) in router status entry (%s)",
+             nickname, s);
+      return -1;
+    }
+    cp = end;
+    if (*cp == '=')
+      ++cp;
   }
-  log_fn(LOG_DEBUG, "Updating status of %s from list \"%s\"",
-         router->nickname, cp);
-  tor_free(cp);
-#endif
+  /* 'end' now points to the start of a hex digest, or EOS. */
 
-  running = approved = 0;
-  n_names = smartlist_len(running_list);
-  for (i=0; i<n_names; ++i) {
-    name = smartlist_get(running_list, i);
-    if (*name != '!') {
-      if (router_nickname_matches(router, name)) {
-        if (router->status_set_at < list_time) {
-          router->status_set_at = list_time;
-          router->is_running = 1;
-        }
-        router->is_verified = (name[0] != '$');
-        return 1;
-      }
-    } else { /* *name == '!' */
-      name++;
-      if (router_nickname_matches(router, name)) {
-        if (router->status_set_at < list_time) {
-          router->status_set_at = list_time;
-          router->is_running = 0;
-        }
-        router->is_verified = (name[0] != '$');
-        return 1;
-      }
+  /* Parse the hexdigest portion of the status. */
+  if (*cp == '$') {
+    hex_digest_set = 1;
+    ++cp;
+    if (strlen(cp) != HEX_DIGEST_LEN) {
+      log_fn(LOG_WARN, "Bad length (%d) on digest in router status entry (%s)",
+             strlen(cp), s);
+      return -1;
+    }
+    strcpy(hexdigest, cp);
+    if (base16_decode(digest, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0) {
+      log_fn(LOG_WARN, "Invalid digest in router status entry (%s)", s);
+      return -1;
+    }
+  }
+
+  /* Make sure that the entry was in the right format. */
+  if (rr_format) {
+    if (is_verified == hex_digest_set) {
+      log_fn(LOG_WARN, "Invalid syntax for running-routers member (%s)", s);
+      return -1;
+    }
+  } else {
+    if (!hex_digest_set) {
+      log_fn(LOG_WARN, "Invalid syntax for router-status member (%s)", s);
+      return -1;
     }
   }
+
+  /* Okay, we're done parsing. For all routers that match, update their status.
+   */
+  SMARTLIST_FOREACH(routers, routerinfo_t *, r,
+  {
+    int nickname_matches = is_verified && !strcasecmp(r->nickname, nickname);
+    int digest_matches = !memcmp(digest, r->identity_digest, DIGEST_LEN);
+    if (nickname_matches && (digest_matches||rr_format))
+      r->is_verified = 1;
+    else if (digest_matches)
+      r->is_verified = 0;
+    if (digest_matches || (nickname_matches&&rr_format))
+      if (r->status_set_at < list_time) {
+        r->is_running = is_running;
+        r->status_set_at = time(NULL);
+      }
+  });
+ 
+  return 0;
+}
+
+int router_update_status_from_smartlist(routerinfo_t *router,
+                                        time_t list_time,
+                                        smartlist_t *running_list,
+                                        int rr_format)
+{
+  smartlist_t *rl;
+  rl = smartlist_create();
+  smartlist_add(rl,router);
+  SMARTLIST_FOREACH(running_list, const char *, cp,
+            routers_update_status_from_entry(rl,list_time,cp,rr_format));
+                                                
+  smartlist_free(rl);
   return 0;
 }
 

Index: routerparse.c
===================================================================
RCS file: /home/or/cvsroot/src/or/routerparse.c,v
retrieving revision 1.63
retrieving revision 1.64
diff -u -d -r1.63 -r1.64
--- routerparse.c	19 Oct 2004 18:19:59 -0000	1.63
+++ routerparse.c	27 Oct 2004 00:48:51 -0000	1.64
@@ -32,6 +32,7 @@
   K_ROUTER_SIGNATURE,
   K_PUBLISHED,
   K_RUNNING_ROUTERS,
+  K_ROUTER_STATUS,
   K_PLATFORM,
   K_OPT,
   K_BANDWIDTH,
@@ -106,6 +107,7 @@
   { "onion-key",           K_ONION_KEY,           NO_ARGS, NEED_KEY,RTR_ONLY },
   { "router-signature",    K_ROUTER_SIGNATURE,    NO_ARGS, NEED_OBJ,RTR_ONLY },
   { "running-routers",     K_RUNNING_ROUTERS,     ARGS,    NO_OBJ,  DIR_ONLY },
+  { "router-status",       K_ROUTER_STATUS,       ARGS,    NO_OBJ,  DIR_ONLY },
   { "ports",               K_PORTS,               ARGS,    NO_OBJ,  RTR_ONLY },
   { "bandwidth",           K_BANDWIDTH,           ARGS,    NO_OBJ,  RTR_ONLY },
   { "platform",            K_PLATFORM,        CONCAT_ARGS, NO_OBJ,  RTR_ONLY },
@@ -393,9 +395,13 @@
   }
   versions = tok->n_args ? tor_strdup(tok->args[0]) : tor_strdup("");
 
-  if (!(tok = find_first_by_keyword(tokens, K_RUNNING_ROUTERS))) {
-    log_fn(LOG_WARN, "Missing running-routers line from directory.");
-    goto err;
+  /* Prefer router-status, then running-routers. */
+  if (!(tok = find_first_by_keyword(tokens, K_ROUTER_STATUS))) {
+    if (!(tok = find_first_by_keyword(tokens, K_RUNNING_ROUTERS))) {
+      log_fn(LOG_WARN,
+             "Missing running-routers/router-status line from directory.");
+      goto err;
+    }
   }
 
   good_nickname_list = smartlist_create();
@@ -408,25 +414,21 @@
    * router. */
   str = end;
   if (router_parse_list_from_string(&str, &new_dir,
-                                    good_nickname_list, published_on)) {
+                                    good_nickname_list, 
+                                    tok->tp==K_RUNNING_ROUTERS,
+                                    published_on)) {
     log_fn(LOG_WARN, "Error reading routers from directory");
     goto err;
   }
 
-  new_dir->software_versions = versions; versions = NULL;
-  new_dir->published_on = published_on;
-
-  SMARTLIST_FOREACH(tokens, directory_token_t *, tok, token_free(tok));
-  smartlist_free(tokens);
-  tokens = NULL;
-
   /* Determine if my routerinfo is considered verified. */
   {
     static int have_warned_about_unverified_status = 0;
     routerinfo_t *me = router_get_my_routerinfo();
     if(me) {
       if(router_update_status_from_smartlist(me, published_on,
-                                             good_nickname_list)==1 &&
+                                             good_nickname_list,
+                                          tok->tp==K_RUNNING_ROUTERS)==1 &&
         me->is_verified == 0 && !have_warned_about_unverified_status) {
         log_fn(LOG_WARN,"Dirserver %s lists your server as unverified. Please consider sending your identity fingerprint to the tor-ops.", dirnickname);
         have_warned_about_unverified_status = 1;
@@ -434,6 +436,13 @@
     }
   }
 
+  new_dir->software_versions = versions; versions = NULL;
+  new_dir->published_on = published_on;
+
+  SMARTLIST_FOREACH(tokens, directory_token_t *, tok, token_free(tok));
+  smartlist_free(tokens);
+  tokens = NULL;
+
   if (*dest)
     routerlist_free(*dest);
   *dest = new_dir;
@@ -497,14 +506,18 @@
      goto err;
   }
 
-  if (!(tok = find_first_by_keyword(tokens, K_RUNNING_ROUTERS))) {
-    log_fn(LOG_WARN, "Missing running-routers line from directory.");
-    goto err;
+  if (!(tok = find_first_by_keyword(tokens, K_ROUTER_STATUS))) {
+    if (!(tok = find_first_by_keyword(tokens, K_RUNNING_ROUTERS))) {
+      log_fn(LOG_WARN,
+             "Missing running-routers/router-status line from directory.");
+      goto err;
+    }
   }
 
   new_list = tor_malloc_zero(sizeof(running_routers_t));
   new_list->published_on = published_on;
   new_list->running_routers = smartlist_create();
+  new_list->is_running_routers_format = (tok->tp == K_RUNNING_ROUTERS);
   for (i=0;i<tok->n_args;++i) {
     smartlist_add(new_list->running_routers, tok->args[i]);
   }
@@ -661,7 +674,7 @@
 int
 router_parse_list_from_string(const char **s, routerlist_t **dest,
                               smartlist_t *good_nickname_list,
-                              time_t published_on)
+                              int rr_format, time_t published_on)
 {
   routerinfo_t *router;
   smartlist_t *routers;
@@ -692,10 +705,7 @@
       continue;
     }
 
-    if (good_nickname_list) {
-      router_update_status_from_smartlist(router, published_on,
-                                          good_nickname_list);
-    } else {
+    if (!good_nickname_list) {
       router->is_running = 1; /* start out assuming all dirservers are up */
       router->is_verified = 1;
       router->status_set_at = time(NULL);
@@ -704,6 +714,12 @@
     log_fn(LOG_DEBUG,"just added router #%d.",smartlist_len(routers));
   }
 
+  if (good_nickname_list) {
+    SMARTLIST_FOREACH(good_nickname_list, const char *, cp,
+           routers_update_status_from_entry(routers, published_on,
+                                            cp, rr_format));
+  }
+
   if (*dest)
     routerlist_free(*dest);
   *dest = tor_malloc_zero(sizeof(routerlist_t));



More information about the tor-commits mailing list