diff --git a/src/or/control.c b/src/or/control.c index 546e3e07c9..ebcce1e73d 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -59,6 +59,7 @@ const char control_c_id[] = "$Id$"; #define ERR_UNAUTHORIZED 0x0007 #define ERR_REJECTED_AUTHENTICATION 0x0008 #define ERR_RESOURCE_EXHAUSETED 0x0009 +#define ERR_TOO_LONG 0x000A /* Recognized asynchronous event types. */ #define _EVENT_MIN 0x0001 @@ -447,10 +448,79 @@ handle_control_mapaddress(connection_t *conn, uint16_t len, const char *body) send_control_error(conn,ERR_UNRECOGNIZED_TYPE,"not yet implemented"); return 0; } + +static char * +handle_getinfo_helper(const char *question) +{ + if (!strcmp(question, "version")) { + return tor_strdup(VERSION); + } else if (!strcmpstart(question, "desc/id/")) { + return NULL; /* XXXX */ + } 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; + } else if (!strcmp(question, "addr-mappings")) { + return NULL; /* XXXX */ + } else { + /* unrecognized key */ + return NULL; + } +} + static int handle_control_getinfo(connection_t *conn, uint16_t len, const char *body) { - send_control_error(conn,ERR_UNRECOGNIZED_TYPE,"not yet implemented"); + smartlist_t *questions = NULL; + smartlist_t *answers = NULL; + char *msg = NULL, *ans; + size_t msg_len; + + questions = smartlist_create(); + smartlist_split_string(questions, body, "\n", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + answers = smartlist_create(); + SMARTLIST_FOREACH(questions, const char *, q, + { + ans = handle_getinfo_helper(q); + 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); + } + }); + + if (msg_len > 65535) { + /* XXXX What if it *is* this long? */ + send_control_error(conn, ERR_TOO_LONG, body); + goto done; + } + + msg = smartlist_join_strings2(answers, "\0", 1, 1, &msg_len); + send_control_message(conn, CONTROL_CMD_INFOVALUE, + (uint16_t)msg_len, msg_len?msg:NULL); + + done: + if (answers) SMARTLIST_FOREACH(answers, char *, cp, tor_free(cp)); + if (questions) SMARTLIST_FOREACH(questions, char *, cp, tor_free(cp)); + smartlist_free(answers); + smartlist_free(questions); + tor_free(msg); + return 0; } static int