diff --git a/src/or/control.c b/src/or/control.c
index 39e82c1664..ced46710de 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -538,37 +538,25 @@ handle_control_mapaddress(connection_t *conn, uint32_t len, const char *body)
return 0;
}
-static char *
-handle_getinfo_helper(const char *question)
+/** Lookup the 'getinfo' entry question, and return
+ * the answer in *answer (or NULL if key not recognized).
+ * Return 0 if success, or -1 if internal error. */
+static int
+handle_getinfo_helper(const char *question, char **answer)
{
+ *answer = NULL; /* unrecognized key by default */
if (!strcmp(question, "version")) {
- return tor_strdup(VERSION);
+ *answer = tor_strdup(VERSION);
} else if (!strcmpstart(question, "desc/id/")) {
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;
- router_get_routerlist(&rl);
- if (!rl)
- return tor_strdup("");
- answer = tor_malloc(smartlist_len(rl->routers)*(HEX_DIGEST_LEN+1)+1);
- cp = answer;
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
- {
- base16_encode(cp, HEX_DIGEST_LEN+1, r->identity_digest, DIGEST_LEN);
- cp += HEX_DIGEST_LEN;
- *cp++ = ',';
- });
- return answer;
+ if (ri && ri->signed_descriptor)
+ *answer = tor_strdup(ri->signed_descriptor);
+ } else if (!strcmp(question, "network-status")) {
+ if (list_server_status(NULL, answer) < 0)
+ return -1;
} else if (!strcmpstart(question, "addr-mappings/")) {
time_t min_e, max_e;
smartlist_t *mappings;
- char *answer;
if (!strcmp(question, "addr-mappings/all")) {
min_e = 0; max_e = TIME_MAX;
} else if (!strcmp(question, "addr-mappings/cache")) {
@@ -578,18 +566,15 @@ handle_getinfo_helper(const char *question)
} else if (!strcmp(question, "addr-mappings/control")) {
min_e = 1; max_e = 1;
} else {
- return NULL;
+ return 0;
}
mappings = smartlist_create();
addressmap_get_mappings(mappings, min_e, max_e);
- answer = smartlist_join_strings(mappings, "\n", 1, NULL);
+ *answer = smartlist_join_strings(mappings, "\n", 1, NULL);
SMARTLIST_FOREACH(mappings, char *, cp, tor_free(cp));
smartlist_free(mappings);
- return answer;
- } else {
- /* unrecognized key */
- return NULL;
}
+ return 0;
}
static int
@@ -607,15 +592,16 @@ handle_control_getinfo(connection_t *conn, uint32_t len, const char *body)
msg_len = 0;
SMARTLIST_FOREACH(questions, const char *, q,
{
- ans = handle_getinfo_helper(q);
- if (!ans) {
+ if (handle_getinfo_helper(q, &ans) < 0) {
+ send_control_error(conn, ERR_INTERNAL, body);
+ goto done;
+ } if (!ans) {
send_control_error(conn, ERR_UNRECOGNIZED_CONFIG_KEY, body);
goto done;
- } else {
- smartlist_add(answers, tor_strdup(q));
- smartlist_add(answers, ans);
- msg_len += 2 + strlen(ans) + strlen(q);
}
+ smartlist_add(answers, tor_strdup(q));
+ smartlist_add(answers, ans);
+ msg_len += 2 + strlen(ans) + strlen(q);
});
msg = smartlist_join_strings2(answers, "\0", 1, 1, &msg_len);
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index e1da307e14..3df96e14f5 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -20,8 +20,6 @@ const char dirserv_c_id[] = "$Id$";
static int the_directory_is_dirty = 1;
static int runningrouters_is_dirty = 1;
-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);
/* Should be static; exposed for testing */
@@ -515,7 +513,7 @@ list_single_server_status(routerinfo_t *desc, int is_live,
* and store them in *running_routers_out and *router_status_out
* respectively. Return 0 on success, -1 on failure.
*/
-static int
+int
list_server_status(char **running_routers_out, char **router_status_out)
{
/* List of entries in running-routers style: An optional !, then either
diff --git a/src/or/or.h b/src/or/or.h
index 9c6af5e5cc..769ceacc07 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1454,6 +1454,7 @@ const char *dirserv_get_nickname_by_digest(const char *digest);
int dirserv_add_descriptor(const char **desc, const char **msg);
int dirserv_load_from_directory_string(const char *dir);
void dirserv_free_descriptors(void);
+int list_server_status(char **running_routers_out, char **router_status_out);
void dirserv_remove_old_servers(int age);
int dirserv_dump_directory_to_string(char **dir_out,
crypto_pk_env_t *private_key);