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

[or-cvs] Implement more control spec functionality



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

Modified Files:
	config.c control.c directory.c dirserv.c or.h router.c 
	routerlist.c routerparse.c 
Log Message:
Implement more control spec functionality
- Mapaddress
- Postdescriptor
- GetInfo on descriptors

Required changes elsewhere:
- Keep the most recent running_routers_t in the routerlist_t. That way we
  can learn about new routers and remember whether we were last told that
  they were up or down.  Also enables more simplifications.
- Keep the signed descriptor inside routerinfo_t.  This makes
  descriptor_entry_t in dirservers.c unneeded.
- Rename AddressMap (the verb) to MapAddress. Keep AddressMap as a noun.
- Check addresses for plausibility before mapping them.



Index: config.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/config.c,v
retrieving revision 1.317
retrieving revision 1.318
diff -u -d -r1.317 -r1.318
--- config.c	24 Feb 2005 10:56:55 -0000	1.317
+++ config.c	25 Feb 2005 20:46:13 -0000	1.318
@@ -123,7 +123,7 @@
   VAR("ExcludeNodes",        STRING,   ExcludeNodes,         NULL),
   VAR("TrackHostExits",      CSV,      TrackHostExits,       NULL),
   VAR("TrackHostExitsExpire",INTERVAL, TrackHostExitsExpire, "30 minutes"),
-  VAR("AddressMap",          LINELIST, AddressMap,           NULL),
+  VAR("MapAddress",          LINELIST, AddressMap,           NULL),
   VAR("FascistFirewall",     BOOL,     FascistFirewall,      "0"),
   VAR("FirewallPorts",       CSV,      FirewallPorts,        "80,443"),
   VAR("MyFamily",            STRING,   MyFamily,             NULL),
@@ -1824,9 +1824,18 @@
     if (smartlist_len(elts) >= 2) {
       from = smartlist_get(elts,0);
       to = smartlist_get(elts,1);
-      addressmap_register(from, tor_strdup(to), 0);
+      if (!is_plausible_address(from)) {
+        log_fn(LOG_WARN,"Skipping invalid argument '%s' to MapAddress",from);
+      } else if (!is_plausible_address(to)) {
+        log_fn(LOG_WARN,"Skipping invalid argument '%s' to MapAddress",to);
+      } else {
+        addressmap_register(from, tor_strdup(to), 0);
+        if (smartlist_len(elts)>2) {
+          log_fn(LOG_WARN,"Ignoring extra arguments to MapAddress.");
+        }
+      }
     } else {
-      log_fn(LOG_WARN,"AddressMap '%s' has too few arguments. Ignoring.", opt->value);
+      log_fn(LOG_WARN,"MapAddress '%s' has too few arguments. Ignoring.", opt->value);
     }
     SMARTLIST_FOREACH(elts, char*, cp, tor_free(cp));
     smartlist_clear(elts);

Index: control.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/control.c,v
retrieving revision 1.43
retrieving revision 1.44
diff -u -d -r1.43 -r1.44
--- control.c	25 Feb 2005 06:37:07 -0000	1.43
+++ control.c	25 Feb 2005 20:46:13 -0000	1.44
@@ -117,6 +117,7 @@
 static void send_control_message(connection_t *conn, uint16_t type,
                                  uint16_t len, const char *body);
 static void send_control_done(connection_t *conn);
+static void send_control_done2(connection_t *conn, const char *msg, size_t len);
 static void send_control_error(connection_t *conn, uint16_t error,
                                const char *message);
 static void send_control_event(uint16_t event, uint16_t len, const char *body);
@@ -192,6 +193,11 @@
   send_control_message(conn, CONTROL_CMD_DONE, 0, NULL);
 }
 
+static void send_control_done2(connection_t *conn, const char *msg, size_t len)
+{
+  send_control_message(conn, CONTROL_CMD_DONE, len, msg);
+}
+
 /** Send an error message with error code <b>error</b> and body
  * <b>message</b> down the connection <b>conn</b> */
 static void
@@ -445,7 +451,46 @@
 static int
 handle_control_mapaddress(connection_t *conn, uint16_t len, const char *body)
 {
-  send_control_error(conn,ERR_UNRECOGNIZED_TYPE,"not yet implemented");
+  smartlist_t *elts;
+  smartlist_t *lines;
+  smartlist_t *reply;
+  char *r;
+  size_t sz;
+  lines = smartlist_create();
+  elts = smartlist_create();
+  reply = smartlist_create();
+  smartlist_split_string(lines, body, "\n",
+                         SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+  SMARTLIST_FOREACH(lines, const char *, line,
+  {
+    smartlist_split_string(elts, body, " ", 0, 2);
+    if (smartlist_len(elts) == 2) {
+      const char *from = smartlist_get(elts,0);
+      const char *to = smartlist_get(elts,1);
+      if (!is_plausible_address(from)) {
+        log_fn(LOG_WARN,"Skipping invalid argument '%s' in MapAddress msg",from);
+      } else if (!is_plausible_address(to)) {
+        log_fn(LOG_WARN,"Skipping invalid argument '%s' in AddressMap msg",to);
+      } else {
+        addressmap_register(from, tor_strdup(to), 0);
+        smartlist_add(reply, tor_strdup(line));
+      }
+    } else {
+      log_fn(LOG_WARN, "Skipping MapAddress line with wrong number of items.");
+    }
+    SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
+    smartlist_clear(elts);
+  });
+  SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
+  smartlist_free(lines);
+  smartlist_free(elts);
+
+  r = smartlist_join_strings(reply, "\n", 1, &sz);
+  send_control_done2(conn,sz,r);
+
+  SMARTLIST_FOREACH(reply, char *, cp, tor_free(cp));
+  smartlist_free(reply);
+  tor_free(r);
   return 0;
 }
 
@@ -455,7 +500,12 @@
   if (!strcmp(question, "version")) {
     return tor_strdup(VERSION);
   } else if (!strcmpstart(question, "desc/id/")) {
-    return NULL; /* XXXX */
+    routerinfo_t *ri = router_get_by_hexdigest(question+strlen("desc/id/"));
+    if (!ri)
+      return NULL;
+    if (!ri->signed_descriptor)
+      return NULL;
+    return tor_strdup(ri->signed_descriptor);
   } else if (!strcmp(question, "desc/all-ids")) {
     routerlist_t *rl;
     char *answer, *cp;
@@ -540,7 +590,14 @@
 handle_control_postdescriptor(connection_t *conn, uint16_t len,
                               const char *body)
 {
-  send_control_error(conn,ERR_UNRECOGNIZED_TYPE,"not yet implemented");
+  if (router_load_single_router(body)<0) {
+    /* XXXX a more specific error would be nice. */
+    send_control_error(conn,ERR_UNSPECIFIED,
+                       "Could not parse descriptor or add it");
+    return 0;
+  }
+
+  send_control_done(conn);
   return 0;
 }
 

Index: directory.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/directory.c,v
retrieving revision 1.214
retrieving revision 1.215
diff -u -d -r1.214 -r1.215
--- directory.c	24 Feb 2005 10:56:55 -0000	1.214
+++ directory.c	25 Feb 2005 20:46:13 -0000	1.215
@@ -723,9 +723,11 @@
       return -1;
     }
     router_get_routerlist(&rl);
-    if (rl)
-      routerlist_update_from_runningrouters(rl,rrs);
-    running_routers_free(rrs);
+    if (rl) {
+      routerlist_set_runningrouters(rl,rrs);
+    } else {
+      running_routers_free(rrs);
+    }
   }
 
   if (conn->purpose == DIR_PURPOSE_UPLOAD_DIR) {

Index: dirserv.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/dirserv.c,v
retrieving revision 1.142
retrieving revision 1.143
diff -u -d -r1.142 -r1.143
--- dirserv.c	10 Feb 2005 23:18:39 -0000	1.142
+++ dirserv.c	25 Feb 2005 20:46:13 -0000	1.143
@@ -249,29 +249,12 @@
  *    Descriptor list
  */
 
-/** A directory server's view of a server descriptor.  Contains both
- * parsed and unparsed versions. */
-typedef struct descriptor_entry_t {
-  char *nickname;
-  time_t published;
-  size_t desc_len;
-  char *descriptor;
-  int verified;
-  routerinfo_t *router;
-} descriptor_entry_t;
-
-/** List of all server descriptors that this dirserv is holding. */
+/** List of routerinfo_t for all server descriptors that this dirserv
+ * is holding.
+ * XXXX This should eventually get coalesced into routerlist.c
+ */
 static smartlist_t *descriptor_list = NULL;
 
-/** Release the storage held by <b>desc</b> */
-static void free_descriptor_entry(descriptor_entry_t *desc)
-{
-  tor_free(desc->descriptor);
-  tor_free(desc->nickname);
-  routerinfo_free(desc->router);
-  tor_free(desc);
-}
-
 /** Release all storage that the dirserv is holding for server
  * descriptors. */
 void
@@ -279,8 +262,8 @@
 {
   if (!descriptor_list)
     return;
-  SMARTLIST_FOREACH(descriptor_list, descriptor_entry_t *, d,
-                    free_descriptor_entry(d));
+  SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
+                    routerinfo_free(ri));
   smartlist_clear(descriptor_list);
 }
 
@@ -319,12 +302,10 @@
 int
 dirserv_add_descriptor(const char **desc, const char **msg)
 {
-  descriptor_entry_t *ent = NULL;
-  routerinfo_t *ri = NULL;
+  routerinfo_t *ri = NULL, *ri_old=NULL;
   int i, r, found=-1;
   char *start, *end;
   char *desc_tmp = NULL;
-  const char *cp;
   size_t desc_len;
   time_t now;
   int verified=1; /* whether we knew its fingerprint already */
@@ -346,10 +327,10 @@
     end = start+strlen(start);
   }
   desc_len = end-start;
-  cp = desc_tmp = tor_strndup(start, desc_len);
+  desc_tmp = tor_strndup(start, desc_len); /* Is this strndup still needed???*/
 
   /* Check: is the descriptor syntactically valid? */
-  ri = router_parse_entry_from_string(cp, NULL);
+  ri = router_parse_entry_from_string(desc_tmp, NULL);
   tor_free(desc_tmp);
   if (!ri) {
     log(LOG_WARN, "Couldn't parse descriptor");
@@ -402,15 +383,15 @@
 
   /* Do we already have an entry for this router? */
   for (i = 0; i < smartlist_len(descriptor_list); ++i) {
-    ent = smartlist_get(descriptor_list, i);
-    if (!strcasecmp(ri->nickname, ent->nickname)) {
+    ri_old = smartlist_get(descriptor_list, i);
+    if (!strcasecmp(ri->nickname, ri_old->nickname)) {
       found = i;
       break;
     }
   }
   if (found >= 0) {
     /* if so, decide whether to update it. */
-    if (ent->published >= ri->published_on) {
+    if (ri_old->published_on >= ri->published_on) {
       /* We already have a newer or equal-time descriptor */
       log_fn(LOG_INFO,"We already have a new enough desc for nickname '%s'. Not adding.",ri->nickname);
       *msg = "We already have a newer descriptor.";
@@ -419,10 +400,10 @@
       *desc = end;
       return verified;
     }
-    /* We don't have a newer one; we'll update this one. */
+    /* We don't alrady have a newer one; we'll update this one. */
     log_fn(LOG_INFO,"Dirserv updating desc for nickname '%s'",ri->nickname);
     *msg = verified?"Verified server updated":"Unverified server updated. (Have you sent us your key fingerprint?)";
-    free_descriptor_entry(ent);
+    routerinfo_free(ri_old);
     smartlist_del_keeporder(descriptor_list, found);
   } else {
     /* Add at the end. */
@@ -430,14 +411,8 @@
     *msg = verified?"Verified server added":"Unverified server added. (Have you sent us your key fingerprint?)";
   }
 
-  ent = tor_malloc(sizeof(descriptor_entry_t));
-  ent->nickname = tor_strdup(ri->nickname);
-  ent->published = ri->published_on;
-  ent->desc_len = desc_len;
-  ent->descriptor = tor_strndup(start,desc_len);
-  ent->router = ri;
-  ent->verified = verified;
-  smartlist_add(descriptor_list, ent);
+  ri->is_verified = verified;
+  smartlist_add(descriptor_list, ri);
 
   *desc = end;
   directory_set_dirty();
@@ -453,16 +428,16 @@
 directory_remove_unrecognized(void)
 {
   int i;
-  descriptor_entry_t *ent;
+  routerinfo_t *ent;
   if (!descriptor_list)
     descriptor_list = smartlist_create();
 
   for (i = 0; i < smartlist_len(descriptor_list); ++i) {
     ent = smartlist_get(descriptor_list, i);
-    if (dirserv_router_fingerprint_is_known(ent->router)<=0) {
+    if (dirserv_router_fingerprint_is_known(ent)<=0) {
       log(LOG_INFO, "Router '%s' is no longer recognized",
           ent->nickname);
-      free_descriptor_entry(ent);
+      routerinfo_free(ent);
       smartlist_del(descriptor_list, i--);
     }
   }
@@ -510,28 +485,27 @@
  * as running iff <b>is_live</b> is true.
  */
 static char *
-list_single_server_status(descriptor_entry_t *desc, int is_live,
+list_single_server_status(routerinfo_t *desc, int is_live,
                           int rr_format)
 {
   char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
   char *cp;
 
   tor_assert(desc);
-  tor_assert(desc->router);
 
   cp = buf;
   if (!is_live) {
     *cp++ = '!';
   }
-  if (desc->verified) {
+  if (desc->is_verified) {
     strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf));
     cp += strlen(cp);
     if (!rr_format)
       *cp++ = '=';
   }
-  if (!desc->verified || !rr_format) {
+  if (!desc->is_verified || !rr_format) {
     *cp++ = '$';
-    base16_encode(cp, HEX_DIGEST_LEN+1, desc->router->identity_digest,
+    base16_encode(cp, HEX_DIGEST_LEN+1, desc->identity_digest,
                   DIGEST_LEN);
   }
   return tor_strdup(buf);
@@ -556,20 +530,19 @@
   rr_entries = smartlist_create();
   rs_entries = smartlist_create();
 
-  SMARTLIST_FOREACH(descriptor_list, descriptor_entry_t *, d,
+  SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
   {
     int is_live;
     connection_t *conn;
-    tor_assert(d->router);
     conn = connection_get_by_identity_digest(
-                    d->router->identity_digest, CONN_TYPE_OR);
+                    ri->identity_digest, CONN_TYPE_OR);
     /* Treat a router as alive if
      *    - It's me, and I'm not hibernating.
      * or - we're connected to it. */
-    is_live = (router_is_me(d->router) && !we_are_hibernating()) ||
+    is_live = (router_is_me(ri) && !we_are_hibernating()) ||
       (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));
+    smartlist_add(rr_entries, list_single_server_status(ri, is_live, 1));
+    smartlist_add(rs_entries, list_single_server_status(ri, is_live, 0));
   });
 
   if (running_routers_out)
@@ -593,16 +566,16 @@
 {
   int i;
   time_t cutoff;
-  descriptor_entry_t *ent;
+  routerinfo_t *ent;
   if (!descriptor_list)
     descriptor_list = smartlist_create();
 
   cutoff = time(NULL) - age;
   for (i = 0; i < smartlist_len(descriptor_list); ++i) {
     ent = smartlist_get(descriptor_list, i);
-    if (ent->published <= cutoff) {
+    if (ent->published_on <= cutoff) {
       /* descriptor_list[i] is too old.  Remove it. */
-      free_descriptor_entry(ent);
+      routerinfo_free(ent);
       smartlist_del(descriptor_list, i--);
       directory_set_dirty();
     }
@@ -677,8 +650,8 @@
 
   buf_len = 2048+strlen(recommended_versions)+strlen(running_routers)+
     strlen(router_status);
-  SMARTLIST_FOREACH(descriptor_list, descriptor_entry_t *, d,
-                    buf_len += strlen(d->descriptor));
+  SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
+                    buf_len += strlen(ri->signed_descriptor));
   buf = tor_malloc(buf_len);
   /* We'll be comparing against buf_len throughout the rest of the
      function, though strictly speaking we shouldn't be able to exceed
@@ -702,8 +675,8 @@
   i = strlen(buf);
   cp = buf+i;
 
-  SMARTLIST_FOREACH(descriptor_list, descriptor_entry_t *, d,
-    if (strlcat(buf, d->descriptor, buf_len) >= buf_len)
+  SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
+    if (strlcat(buf, ri->signed_descriptor, buf_len) >= buf_len)
       goto truncated);
 
   /* These multiple strlcat calls are inefficient, but dwarfed by the RSA
@@ -1010,8 +983,8 @@
     fingerprint_list = NULL;
   }
   if (descriptor_list) {
-    SMARTLIST_FOREACH(descriptor_list, descriptor_entry_t*, d,
-                      free_descriptor_entry(d));
+    SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri,
+                      routerinfo_free(ri));
     smartlist_free(descriptor_list);
     descriptor_list = NULL;
   }

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/or.h,v
retrieving revision 1.541
retrieving revision 1.542
diff -u -d -r1.541 -r1.542
--- or.h	25 Feb 2005 05:42:01 -0000	1.541
+++ or.h	25 Feb 2005 20:46:13 -0000	1.542
@@ -620,6 +620,8 @@
 
 /** Information about another onion router in the network. */
 typedef struct {
+  char *signed_descriptor; /**< The original signed descriptor for this router*/
+
   char *address; /**< Location of OR: either a hostname or an IP address. */
   char *nickname; /**< Human-readable OR name. */
 
@@ -654,6 +656,14 @@
                                  * claims are its family. */
 } routerinfo_t;
 
+/** Contents of a running-routers list */
+typedef struct running_routers_t {
+  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;
+
 /** Contents of a directory of onion routers. */
 typedef struct {
   /** List of routerinfo_t */
@@ -665,18 +675,13 @@
    */
   time_t published_on;
   time_t running_routers_updated_on;
+  /** DOCDOC
+   */
+  running_routers_t *running_routers;
   /** Which router is claimed to have signed it? */
   char *signing_router;
 } routerlist_t;
 
-/** Contents of a running-routers list */
-typedef struct running_routers_t {
-  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
  * performed by a circuit.  Used only at the client edge of a circuit. */
 struct crypt_path_t {
@@ -1696,6 +1701,7 @@
 routerinfo_t *routerinfo_copy(const routerinfo_t *router);
 void router_mark_as_down(const char *digest);
 void routerlist_remove_old_routers(int age);
+int router_load_single_router(const char *s);
 int router_load_routerlist_from_directory(const char *s,crypto_pk_env_t *pkey,
                                         int dir_is_recent, int dir_is_cached);
 int router_compare_addr_to_addr_policy(uint32_t addr, uint16_t port,
@@ -1708,6 +1714,7 @@
 
 int router_exit_policy_rejects_all(routerinfo_t *router);
 void running_routers_free(running_routers_t *rr);
+void routerlist_set_runningrouters(routerlist_t *list, 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,

Index: router.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/router.c,v
retrieving revision 1.147
retrieving revision 1.148
diff -u -d -r1.147 -r1.148
--- router.c	22 Feb 2005 08:18:35 -0000	1.147
+++ router.c	25 Feb 2005 20:46:13 -0000	1.148
@@ -427,8 +427,6 @@
 
 /** My routerinfo. */
 static routerinfo_t *desc_routerinfo = NULL;
-/** String representation of my descriptor, signed by me. */
-static char descriptor[8192];
 /** Boolean: do we need to regenerate the above? */
 static int desc_is_dirty = 1;
 /** Boolean: do we need to regenerate the above? */
@@ -527,8 +525,8 @@
     if (router_rebuild_descriptor(1))
       return NULL;
   }
-  log_fn(LOG_DEBUG,"my desc is '%s'",descriptor);
-  return descriptor;
+  log_fn(LOG_DEBUG,"my desc is '%s'",desc_routerinfo->signed_descriptor);
+  return desc_routerinfo->signed_descriptor;
 }
 
 /** Rebuild a fresh routerinfo and signed server descriptor for this
@@ -579,14 +577,17 @@
     smartlist_split_string(ri->declared_family, options->MyFamily, ",",
                            SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
   }
+  ri->signed_descriptor = tor_malloc(8192);
+  if (router_dump_router_to_string(ri->signed_descriptor, 8192,
+                                   ri, get_identity_key())<0) {
+    log_fn(LOG_WARN, "Couldn't dump router to string.");
+    return -1;
+  }
 
   if (desc_routerinfo)
     routerinfo_free(desc_routerinfo);
   desc_routerinfo = ri;
-  if (router_dump_router_to_string(descriptor, 8192, ri, get_identity_key())<0) {
-    log_fn(LOG_WARN, "Couldn't dump router to string.");
-    return -1;
-  }
+
   desc_is_dirty = 0;
   desc_needs_upload = 1;
   return 0;

Index: routerlist.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/routerlist.c,v
retrieving revision 1.213
retrieving revision 1.214
diff -u -d -r1.213 -r1.214
--- routerlist.c	24 Feb 2005 23:01:26 -0000	1.213
+++ routerlist.c	25 Feb 2005 20:46:13 -0000	1.214
@@ -659,6 +659,7 @@
   if (!router)
     return;
 
+  tor_free(router->signed_descriptor);
   tor_free(router->address);
   tor_free(router->nickname);
   tor_free(router->platform);
@@ -713,6 +714,7 @@
   SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
                     routerinfo_free(r));
   smartlist_free(rl->routers);
+  running_routers_free(rl->running_routers);
   tor_free(rl->software_versions);
   tor_free(rl);
 }
@@ -856,6 +858,29 @@
 /*
  * Code to parse router descriptors and directories.
  */
+int
+router_load_single_router(const char *s)
+{
+  routerinfo_t *ri;
+
+  if (!(ri = router_parse_entry_from_string(s, NULL))) {
+    log_fn(LOG_WARN, "Error parsing router descriptor; dropping.");
+    return -1;
+  }
+  if (routerlist && routerlist->running_routers) {
+    running_routers_t *rr = routerlist->running_routers;
+    router_update_status_from_smartlist(ri,
+                                        rr->published_on,
+                                        rr->running_routers,
+                                        rr->is_running_routers_format);
+  }
+  if (router_add_to_routerlist(ri)<0) {
+    log_fn(LOG_WARN, "Couldn't add router to list; dropping.");
+    return -1;
+  }
+  log_fn(LOG_DEBUG, "Added router to list");
+  return 0;
+}
 
 /** Add to the current routerlist each router stored in the
  * signed directory <b>s</b>.  If pkey is provided, check the signature against
@@ -1137,7 +1162,8 @@
 /** Release all space held in <b>rr</b>. */
 void running_routers_free(running_routers_t *rr)
 {
-  tor_assert(rr);
+  if (!rr)
+    return;
   if (rr->running_routers) {
     SMARTLIST_FOREACH(rr->running_routers, char *, s, tor_free(s));
     smartlist_free(rr->running_routers);
@@ -1145,6 +1171,17 @@
   tor_free(rr);
 }
 
+/** DOCDOC*/
+void
+routerlist_set_runningrouters(routerlist_t *list, running_routers_t *rr)
+{
+  routerlist_update_from_runningrouters(list,rr);
+  if (list->running_routers != rr) {
+    running_routers_free(list->running_routers);
+    list->running_routers = rr;
+  }
+}
+
 /** Update the running/not-running status of every router in <b>list</b>, based
  * on the contents of <b>rr</b>. */
 /* Note: this function is not yet used, since nobody publishes just

Index: routerparse.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/routerparse.c,v
retrieving revision 1.100
retrieving revision 1.101
diff -u -d -r1.100 -r1.101
--- routerparse.c	22 Feb 2005 08:18:35 -0000	1.100
+++ routerparse.c	25 Feb 2005 20:46:13 -0000	1.101
@@ -312,6 +312,7 @@
   char digest[DIGEST_LEN];
   routerlist_t *new_dir = NULL;
   char *versions = NULL;
+  int nickname_list_is_running_routers;
   smartlist_t *good_nickname_list = NULL;
   time_t published_on;
   int i, r;
@@ -426,6 +427,7 @@
     }
   }
 
+  nickname_list_is_running_routers = (tok->tp == K_RUNNING_ROUTERS);
   good_nickname_list = smartlist_create();
   for (i=0; i<tok->n_args; ++i) {
     smartlist_add(good_nickname_list, tok->args[i]);
@@ -459,6 +461,11 @@
 
   new_dir->software_versions = versions; versions = NULL;
   new_dir->published_on = published_on;
+  new_dir->running_routers = tor_malloc_zero(sizeof(running_routers_t));
+  new_dir->running_routers->published_on = published_on;
+  new_dir->running_routers->running_routers = good_nickname_list;
+  new_dir->running_routers->is_running_routers_format =
+    nickname_list_is_running_routers;
 
   SMARTLIST_FOREACH(tokens, directory_token_t *, tok, token_free(tok));
   smartlist_free(tokens);
@@ -475,16 +482,16 @@
   if (new_dir)
     routerlist_free(new_dir);
   tor_free(versions);
+  if (good_nickname_list) {
+    SMARTLIST_FOREACH(good_nickname_list, char *, n, tor_free(n));
+    smartlist_free(good_nickname_list);
+  }
  done:
   if (declared_key) crypto_free_pk_env(declared_key);
   if (tokens) {
     SMARTLIST_FOREACH(tokens, directory_token_t *, tok, token_free(tok));
     smartlist_free(tokens);
   }
-  if (good_nickname_list) {
-    SMARTLIST_FOREACH(good_nickname_list, char *, n, tor_free(n));
-    smartlist_free(good_nickname_list);
-  }
   return r;
 }
 
@@ -802,6 +809,7 @@
   }
 
   router = tor_malloc_zero(sizeof(routerinfo_t));
+  router->signed_descriptor = tor_strndup(s, end-s);
   ports_set = bw_set = 0;
 
   if (tok->n_args == 2 || tok->n_args == 5 || tok->n_args == 6) {