tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

control_getinfo.c (66868B)


      1 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
      2 * Copyright (c) 2007-2021, The Tor Project, Inc. */
      3 /* See LICENSE for licensing information */
      4 
      5 /**
      6 * \file control_getinfo.c
      7 * \brief Implementation for miscellaneous controller getinfo commands.
      8 */
      9 
     10 #define CONTROL_EVENTS_PRIVATE
     11 #define CONTROL_MODULE_PRIVATE
     12 #define CONTROL_GETINFO_PRIVATE
     13 
     14 #include "core/or/or.h"
     15 #include "app/config/config.h"
     16 #include "core/mainloop/connection.h"
     17 #include "core/mainloop/mainloop.h"
     18 #include "core/or/circuitlist.h"
     19 #include "core/or/connection_edge.h"
     20 #include "core/or/connection_or.h"
     21 #include "core/or/policies.h"
     22 #include "core/or/versions.h"
     23 #include "feature/client/addressmap.h"
     24 #include "feature/client/bridges.h"
     25 #include "feature/client/entrynodes.h"
     26 #include "feature/control/control.h"
     27 #include "feature/control/control_cmd.h"
     28 #include "feature/control/control_events.h"
     29 #include "feature/control/control_fmt.h"
     30 #include "feature/control/control_getinfo.h"
     31 #include "feature/control/control_proto.h"
     32 #include "feature/control/getinfo_geoip.h"
     33 #include "feature/dircache/dirserv.h"
     34 #include "feature/dirclient/dirclient.h"
     35 #include "feature/dirclient/dlstatus.h"
     36 #include "feature/dircommon/directory.h"
     37 #include "feature/hibernate/hibernate.h"
     38 #include "feature/hs/hs_cache.h"
     39 #include "feature/hs_common/shared_random_client.h"
     40 #include "feature/nodelist/authcert.h"
     41 #include "feature/nodelist/microdesc.h"
     42 #include "feature/nodelist/networkstatus.h"
     43 #include "feature/nodelist/nodelist.h"
     44 #include "feature/nodelist/routerinfo.h"
     45 #include "feature/nodelist/routerlist.h"
     46 #include "feature/relay/relay_find_addr.h"
     47 #include "feature/relay/router.h"
     48 #include "feature/relay/routermode.h"
     49 #include "feature/relay/selftest.h"
     50 #include "feature/stats/geoip_stats.h"
     51 #include "feature/stats/predict_ports.h"
     52 #include "feature/stats/rephist.h"
     53 #include "lib/version/torversion.h"
     54 #include "lib/encoding/kvline.h"
     55 
     56 #include "core/or/entry_connection_st.h"
     57 #include "core/or/or_connection_st.h"
     58 #include "core/or/origin_circuit_st.h"
     59 #include "core/or/socks_request_st.h"
     60 #include "feature/control/control_connection_st.h"
     61 #include "feature/control/control_cmd_args_st.h"
     62 #include "feature/dircache/cached_dir_st.h"
     63 #include "feature/nodelist/extrainfo_st.h"
     64 #include "feature/nodelist/microdesc_st.h"
     65 #include "feature/nodelist/networkstatus_st.h"
     66 #include "feature/nodelist/node_st.h"
     67 #include "feature/nodelist/routerinfo_st.h"
     68 #include "feature/nodelist/routerlist_st.h"
     69 
     70 #ifdef HAVE_UNISTD_H
     71 #include <unistd.h>
     72 #endif
     73 
     74 #ifndef _WIN32
     75 #include <pwd.h>
     76 #endif
     77 
     78 static char *list_getinfo_options(void);
     79 static char *download_status_to_string(const download_status_t *dl);
     80 
     81 /** Implementation helper for GETINFO: knows the answers for various
     82 * trivial-to-implement questions. */
     83 static int
     84 getinfo_helper_misc(control_connection_t *conn, const char *question,
     85                    char **answer, const char **errmsg)
     86 {
     87  (void) conn;
     88  if (!strcmp(question, "version")) {
     89    *answer = tor_strdup(get_version());
     90  } else if (!strcmp(question, "bw-event-cache")) {
     91    *answer = get_bw_samples();
     92  } else if (!strcmp(question, "config-file")) {
     93    const char *a = get_torrc_fname(0);
     94    if (a)
     95      *answer = tor_strdup(a);
     96  } else if (!strcmp(question, "config-defaults-file")) {
     97    const char *a = get_torrc_fname(1);
     98    if (a)
     99      *answer = tor_strdup(a);
    100  } else if (!strcmp(question, "config-text")) {
    101    *answer = options_dump(get_options(), OPTIONS_DUMP_MINIMAL);
    102  } else if (!strcmp(question, "config-can-saveconf")) {
    103    *answer = tor_strdup(get_options()->IncludeUsed ? "0" : "1");
    104  } else if (!strcmp(question, "info/names")) {
    105    *answer = list_getinfo_options();
    106  } else if (!strcmp(question, "dormant")) {
    107    int dormant = rep_hist_circbuilding_dormant(time(NULL));
    108    *answer = tor_strdup(dormant ? "1" : "0");
    109  } else if (!strcmp(question, "events/names")) {
    110    int i;
    111    smartlist_t *event_names = smartlist_new();
    112 
    113    for (i = 0; control_event_table[i].event_name != NULL; ++i) {
    114      smartlist_add(event_names, (char *)control_event_table[i].event_name);
    115    }
    116 
    117    *answer = smartlist_join_strings(event_names, " ", 0, NULL);
    118 
    119    smartlist_free(event_names);
    120  } else if (!strcmp(question, "signal/names")) {
    121    smartlist_t *signal_names = smartlist_new();
    122    int j;
    123    for (j = 0; signal_table[j].signal_name != NULL; ++j) {
    124      smartlist_add(signal_names, (char*)signal_table[j].signal_name);
    125    }
    126 
    127    *answer = smartlist_join_strings(signal_names, " ", 0, NULL);
    128 
    129    smartlist_free(signal_names);
    130  } else if (!strcmp(question, "features/names")) {
    131    *answer = tor_strdup("VERBOSE_NAMES EXTENDED_EVENTS");
    132  } else if (!strcmp(question, "address") || !strcmp(question, "address/v4")) {
    133    tor_addr_t addr;
    134    if (!relay_find_addr_to_publish(get_options(), AF_INET,
    135                                    RELAY_FIND_ADDR_CACHE_ONLY, &addr)) {
    136      *errmsg = "Address unknown";
    137      return -1;
    138    }
    139    *answer = tor_addr_to_str_dup(&addr);
    140    tor_assert_nonfatal(*answer);
    141  } else if (!strcmp(question, "address/v6")) {
    142    tor_addr_t addr;
    143    if (!relay_find_addr_to_publish(get_options(), AF_INET6,
    144                                    RELAY_FIND_ADDR_CACHE_ONLY, &addr)) {
    145      *errmsg = "Address unknown";
    146      return -1;
    147    }
    148    *answer = tor_addr_to_str_dup(&addr);
    149    tor_assert_nonfatal(*answer);
    150  } else if (!strcmp(question, "traffic/read")) {
    151    tor_asprintf(answer, "%"PRIu64, (get_bytes_read()));
    152  } else if (!strcmp(question, "traffic/written")) {
    153    tor_asprintf(answer, "%"PRIu64, (get_bytes_written()));
    154  } else if (!strcmp(question, "uptime")) {
    155    long uptime_secs = get_uptime();
    156    tor_asprintf(answer, "%ld", uptime_secs);
    157  } else if (!strcmp(question, "process/pid")) {
    158    int myPid = -1;
    159 
    160 #ifdef _WIN32
    161      myPid = _getpid();
    162 #else
    163      myPid = getpid();
    164 #endif
    165 
    166    tor_asprintf(answer, "%d", myPid);
    167  } else if (!strcmp(question, "process/uid")) {
    168 #ifdef _WIN32
    169      *answer = tor_strdup("-1");
    170 #else
    171      int myUid = geteuid();
    172      tor_asprintf(answer, "%d", myUid);
    173 #endif /* defined(_WIN32) */
    174  } else if (!strcmp(question, "process/user")) {
    175 #ifdef _WIN32
    176      *answer = tor_strdup("");
    177 #else
    178      int myUid = geteuid();
    179      const struct passwd *myPwEntry = tor_getpwuid(myUid);
    180 
    181      if (myPwEntry) {
    182        *answer = tor_strdup(myPwEntry->pw_name);
    183      } else {
    184        *answer = tor_strdup("");
    185      }
    186 #endif /* defined(_WIN32) */
    187  } else if (!strcmp(question, "process/descriptor-limit")) {
    188    int max_fds = get_max_sockets();
    189    tor_asprintf(answer, "%d", max_fds);
    190  } else if (!strcmp(question, "limits/max-mem-in-queues")) {
    191    tor_asprintf(answer, "%"PRIu64,
    192                 (get_options()->MaxMemInQueues));
    193  } else if (!strcmp(question, "fingerprint")) {
    194    crypto_pk_t *server_key;
    195    if (!server_mode(get_options())) {
    196      *errmsg = "Not running in server mode";
    197      return -1;
    198    }
    199    server_key = get_server_identity_key();
    200    *answer = tor_malloc(HEX_DIGEST_LEN+1);
    201    crypto_pk_get_fingerprint(server_key, *answer, 0);
    202  }
    203  return 0;
    204 }
    205 
    206 /** Awful hack: return a newly allocated string based on a routerinfo and
    207 * (possibly) an extrainfo, sticking the read-history and write-history from
    208 * <b>ei</b> into the resulting string.  The thing you get back won't
    209 * necessarily have a valid signature.
    210 *
    211 * New code should never use this; it's for backward compatibility.
    212 *
    213 * NOTE: <b>ri_body</b> is as returned by signed_descriptor_get_body: it might
    214 * not be NUL-terminated. */
    215 static char *
    216 munge_extrainfo_into_routerinfo(const char *ri_body,
    217                                const signed_descriptor_t *ri,
    218                                const signed_descriptor_t *ei)
    219 {
    220  char *out = NULL, *outp;
    221  int i;
    222  const char *router_sig;
    223  const char *ei_body = signed_descriptor_get_body(ei);
    224  size_t ri_len = ri->signed_descriptor_len;
    225  size_t ei_len = ei->signed_descriptor_len;
    226  if (!ei_body)
    227    goto bail;
    228 
    229  outp = out = tor_malloc(ri_len+ei_len+1);
    230  if (!(router_sig = tor_memstr(ri_body, ri_len, "\nrouter-signature")))
    231    goto bail;
    232  ++router_sig;
    233  memcpy(out, ri_body, router_sig-ri_body);
    234  outp += router_sig-ri_body;
    235 
    236  for (i=0; i < 2; ++i) {
    237    const char *kwd = i ? "\nwrite-history " : "\nread-history ";
    238    const char *cp, *eol;
    239    if (!(cp = tor_memstr(ei_body, ei_len, kwd)))
    240      continue;
    241    ++cp;
    242    if (!(eol = memchr(cp, '\n', ei_len - (cp-ei_body))))
    243      continue;
    244    memcpy(outp, cp, eol-cp+1);
    245    outp += eol-cp+1;
    246  }
    247  memcpy(outp, router_sig, ri_len - (router_sig-ri_body));
    248  *outp++ = '\0';
    249  tor_assert(outp-out < (int)(ri_len+ei_len+1));
    250 
    251  return out;
    252 bail:
    253  tor_free(out);
    254  return tor_strndup(ri_body, ri->signed_descriptor_len);
    255 }
    256 
    257 /** Implementation helper for GETINFO: answers requests for information about
    258 * which ports are bound. */
    259 static int
    260 getinfo_helper_listeners(control_connection_t *control_conn,
    261                         const char *question,
    262                         char **answer, const char **errmsg)
    263 {
    264  int type;
    265  smartlist_t *res;
    266 
    267  (void)control_conn;
    268  (void)errmsg;
    269 
    270  if (!strcmp(question, "net/listeners/or"))
    271    type = CONN_TYPE_OR_LISTENER;
    272  else if (!strcmp(question, "net/listeners/extor"))
    273    type = CONN_TYPE_EXT_OR_LISTENER;
    274  else if (!strcmp(question, "net/listeners/dir"))
    275    type = CONN_TYPE_DIR_LISTENER;
    276  else if (!strcmp(question, "net/listeners/socks"))
    277    type = CONN_TYPE_AP_LISTENER;
    278  else if (!strcmp(question, "net/listeners/trans"))
    279    type = CONN_TYPE_AP_TRANS_LISTENER;
    280  else if (!strcmp(question, "net/listeners/natd"))
    281    type = CONN_TYPE_AP_NATD_LISTENER;
    282  else if (!strcmp(question, "net/listeners/httptunnel"))
    283    type = CONN_TYPE_AP_HTTP_CONNECT_LISTENER;
    284  else if (!strcmp(question, "net/listeners/dns"))
    285    type = CONN_TYPE_AP_DNS_LISTENER;
    286  else if (!strcmp(question, "net/listeners/control"))
    287    type = CONN_TYPE_CONTROL_LISTENER;
    288  else if (!strcmp(question, "net/listeners/metrics"))
    289    type = CONN_TYPE_METRICS_LISTENER;
    290  else
    291    return 0; /* unknown key */
    292 
    293  res = smartlist_new();
    294  SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
    295    struct sockaddr_storage ss;
    296    socklen_t ss_len = sizeof(ss);
    297 
    298    if (conn->type != type || conn->marked_for_close || !SOCKET_OK(conn->s))
    299      continue;
    300 
    301    if (getsockname(conn->s, (struct sockaddr *)&ss, &ss_len) < 0) {
    302      smartlist_add_asprintf(res, "%s:%d", conn->address, (int)conn->port);
    303    } else {
    304      char *tmp = tor_sockaddr_to_str((struct sockaddr *)&ss);
    305      smartlist_add(res, esc_for_log(tmp));
    306      tor_free(tmp);
    307    }
    308 
    309  } SMARTLIST_FOREACH_END(conn);
    310 
    311  *answer = smartlist_join_strings(res, " ", 0, NULL);
    312 
    313  SMARTLIST_FOREACH(res, char *, cp, tor_free(cp));
    314  smartlist_free(res);
    315  return 0;
    316 }
    317 
    318 /** Implementation helper for GETINFO: answers requests for information about
    319 * the current time in both local and UTC forms. */
    320 STATIC int
    321 getinfo_helper_current_time(control_connection_t *control_conn,
    322                         const char *question,
    323                         char **answer, const char **errmsg)
    324 {
    325  (void)control_conn;
    326  (void)errmsg;
    327 
    328  struct timeval now;
    329  tor_gettimeofday(&now);
    330  char timebuf[ISO_TIME_LEN+1];
    331 
    332  if (!strcmp(question, "current-time/local"))
    333    format_local_iso_time_nospace(timebuf, (time_t)now.tv_sec);
    334  else if (!strcmp(question, "current-time/utc"))
    335    format_iso_time_nospace(timebuf, (time_t)now.tv_sec);
    336  else
    337    return 0;
    338 
    339  *answer = tor_strdup(timebuf);
    340  return 0;
    341 }
    342 
    343 /** GETINFO helper for dumping different consensus flavors
    344 * returns: 0 on success -1 on error. */
    345 STATIC int
    346 getinfo_helper_current_consensus(consensus_flavor_t flavor,
    347                                 char** answer,
    348                                 const char** errmsg)
    349 {
    350  const char *flavor_name = networkstatus_get_flavor_name(flavor);
    351  if (BUG(!strcmp(flavor_name, "??"))) {
    352    *errmsg = "Internal error: unrecognized flavor name.";
    353    return -1;
    354  }
    355  tor_mmap_t *mapped = networkstatus_map_cached_consensus(flavor_name);
    356  if (mapped) {
    357    *answer = tor_memdup_nulterm(mapped->data, mapped->size);
    358    tor_munmap_file(mapped);
    359  }
    360  if (!*answer) { /* Maybe it's in the cache? */
    361    if (we_want_to_fetch_flavor(get_options(), flavor)) {
    362      const cached_dir_t *consensus = dirserv_get_consensus(flavor_name);
    363      if (consensus) {
    364        *answer = tor_strdup(consensus->dir);
    365      }
    366    }
    367  }
    368  if (!*answer) { /* generate an error */
    369    *errmsg = "Could not open cached consensus. "
    370      "Make sure FetchUselessDescriptors is set to 1.";
    371    return -1;
    372  }
    373  return 0;
    374 }
    375 
    376 /** Helper for getinfo_helper_dir.
    377 *
    378 * Add a signed_descriptor_t to <b>descs_out</b> for each router matching
    379 * <b>key</b>.  The key should be either
    380 *   - "/tor/server/authority" for our own routerinfo;
    381 *   - "/tor/server/all" for all the routerinfos we have, concatenated;
    382 *   - "/tor/server/fp/FP" where FP is a plus-separated sequence of
    383 *     hex identity digests; or
    384 *   - "/tor/server/d/D" where D is a plus-separated sequence
    385 *     of server descriptor digests, in hex.
    386 *
    387 * Return 0 if we found some matching descriptors, or -1 if we do not
    388 * have any descriptors, no matching descriptors, or if we did not
    389 * recognize the key (URL).
    390 * If -1 is returned *<b>msg</b> will be set to an appropriate error
    391 * message.
    392 */
    393 static int
    394 controller_get_routerdescs(smartlist_t *descs_out, const char *key,
    395                        const char **msg)
    396 {
    397  *msg = NULL;
    398 
    399  if (!strcmp(key, "/tor/server/all")) {
    400    routerlist_t *rl = router_get_routerlist();
    401    SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
    402                      smartlist_add(descs_out, &(r->cache_info)));
    403  } else if (!strcmp(key, "/tor/server/authority")) {
    404    const routerinfo_t *ri = router_get_my_routerinfo();
    405    if (ri)
    406      smartlist_add(descs_out, (void*) &(ri->cache_info));
    407  } else if (!strcmpstart(key, "/tor/server/d/")) {
    408    smartlist_t *digests = smartlist_new();
    409    key += strlen("/tor/server/d/");
    410    dir_split_resource_into_fingerprints(key, digests, NULL,
    411                                         DSR_HEX|DSR_SORT_UNIQ);
    412    SMARTLIST_FOREACH(digests, const char *, d,
    413       {
    414         signed_descriptor_t *sd = router_get_by_descriptor_digest(d);
    415         if (sd)
    416           smartlist_add(descs_out,sd);
    417       });
    418    SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
    419    smartlist_free(digests);
    420  } else if (!strcmpstart(key, "/tor/server/fp/")) {
    421    smartlist_t *digests = smartlist_new();
    422    time_t cutoff = time(NULL) - ROUTER_MAX_AGE_TO_PUBLISH;
    423    key += strlen("/tor/server/fp/");
    424    dir_split_resource_into_fingerprints(key, digests, NULL,
    425                                         DSR_HEX|DSR_SORT_UNIQ);
    426    SMARTLIST_FOREACH_BEGIN(digests, const char *, d) {
    427         if (router_digest_is_me(d)) {
    428           /* calling router_get_my_routerinfo() to make sure it exists */
    429           const routerinfo_t *ri = router_get_my_routerinfo();
    430           if (ri)
    431             smartlist_add(descs_out, (void*) &(ri->cache_info));
    432         } else {
    433           const routerinfo_t *ri = router_get_by_id_digest(d);
    434           /* Don't actually serve a descriptor that everyone will think is
    435            * expired.  This is an (ugly) workaround to keep buggy 0.1.1.10
    436            * Tors from downloading descriptors that they will throw away.
    437            */
    438           if (ri && ri->cache_info.published_on > cutoff)
    439             smartlist_add(descs_out, (void*) &(ri->cache_info));
    440         }
    441    } SMARTLIST_FOREACH_END(d);
    442    SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
    443    smartlist_free(digests);
    444  } else {
    445    *msg = "Key not recognized";
    446    return -1;
    447  }
    448 
    449  if (!smartlist_len(descs_out)) {
    450    *msg = "Servers unavailable";
    451    return -1;
    452  }
    453  return 0;
    454 }
    455 
    456 /** Implementation helper for GETINFO: knows the answers for questions about
    457 * directory information. */
    458 STATIC int
    459 getinfo_helper_dir(control_connection_t *control_conn,
    460                   const char *question, char **answer,
    461                   const char **errmsg)
    462 {
    463  (void) control_conn;
    464  if (!strcmpstart(question, "desc/id/")) {
    465    const routerinfo_t *ri = NULL;
    466    const node_t *node = node_get_by_hex_id(question+strlen("desc/id/"), 0);
    467    if (node)
    468      ri = node->ri;
    469    if (ri) {
    470      const char *body = signed_descriptor_get_body(&ri->cache_info);
    471      if (body)
    472        *answer = tor_strndup(body, ri->cache_info.signed_descriptor_len);
    473    } else if (! we_fetch_router_descriptors(get_options())) {
    474      /* Descriptors won't be available, provide proper error */
    475      *errmsg = "We fetch microdescriptors, not router "
    476                "descriptors. You'll need to use md/id/* "
    477                "instead of desc/id/*.";
    478      return 0;
    479    }
    480  } else if (!strcmpstart(question, "desc/name/")) {
    481    const routerinfo_t *ri = NULL;
    482    /* XXX Setting 'warn_if_unnamed' here is a bit silly -- the
    483     * warning goes to the user, not to the controller. */
    484    const node_t *node =
    485      node_get_by_nickname(question+strlen("desc/name/"), 0);
    486    if (node)
    487      ri = node->ri;
    488    if (ri) {
    489      const char *body = signed_descriptor_get_body(&ri->cache_info);
    490      if (body)
    491        *answer = tor_strndup(body, ri->cache_info.signed_descriptor_len);
    492    } else if (! we_fetch_router_descriptors(get_options())) {
    493      /* Descriptors won't be available, provide proper error */
    494      *errmsg = "We fetch microdescriptors, not router "
    495                "descriptors. You'll need to use md/name/* "
    496                "instead of desc/name/*.";
    497      return 0;
    498    }
    499  } else if (!strcmp(question, "desc/download-enabled")) {
    500    int r = we_fetch_router_descriptors(get_options());
    501    tor_asprintf(answer, "%d", !!r);
    502  } else if (!strcmp(question, "desc/all-recent")) {
    503    routerlist_t *routerlist = router_get_routerlist();
    504    smartlist_t *sl = smartlist_new();
    505    if (routerlist && routerlist->routers) {
    506      SMARTLIST_FOREACH(routerlist->routers, const routerinfo_t *, ri,
    507      {
    508        const char *body = signed_descriptor_get_body(&ri->cache_info);
    509        if (body)
    510          smartlist_add(sl,
    511                  tor_strndup(body, ri->cache_info.signed_descriptor_len));
    512      });
    513    }
    514    *answer = smartlist_join_strings(sl, "", 0, NULL);
    515    SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
    516    smartlist_free(sl);
    517  } else if (!strcmp(question, "desc/all-recent-extrainfo-hack")) {
    518    /* XXXX Remove this once Torstat asks for extrainfos. */
    519    routerlist_t *routerlist = router_get_routerlist();
    520    smartlist_t *sl = smartlist_new();
    521    if (routerlist && routerlist->routers) {
    522      SMARTLIST_FOREACH_BEGIN(routerlist->routers, const routerinfo_t *, ri) {
    523        const char *body = signed_descriptor_get_body(&ri->cache_info);
    524        signed_descriptor_t *ei = extrainfo_get_by_descriptor_digest(
    525                                     ri->cache_info.extra_info_digest);
    526        if (ei && body) {
    527          smartlist_add(sl, munge_extrainfo_into_routerinfo(body,
    528                                                        &ri->cache_info, ei));
    529        } else if (body) {
    530          smartlist_add(sl,
    531                  tor_strndup(body, ri->cache_info.signed_descriptor_len));
    532        }
    533      } SMARTLIST_FOREACH_END(ri);
    534    }
    535    *answer = smartlist_join_strings(sl, "", 0, NULL);
    536    SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
    537    smartlist_free(sl);
    538  } else if (!strcmpstart(question, "hs/client/desc/id/")) {
    539    hostname_type_t addr_type;
    540 
    541    question += strlen("hs/client/desc/id/");
    542    if (hs_address_is_valid(question)) {
    543      addr_type = ONION_V3_HOSTNAME;
    544    } else {
    545      *errmsg = "Invalid address";
    546      return -1;
    547    }
    548 
    549    if (addr_type == ONION_V3_HOSTNAME) {
    550      ed25519_public_key_t service_pk;
    551      const char *desc;
    552 
    553      /* The check before this if/else makes sure of this. */
    554      tor_assert(addr_type == ONION_V3_HOSTNAME);
    555 
    556      if (hs_parse_address(question, &service_pk, NULL, NULL) < 0) {
    557        *errmsg = "Invalid v3 address";
    558        return -1;
    559      }
    560 
    561      desc = hs_cache_lookup_encoded_as_client(&service_pk);
    562      if (desc) {
    563        *answer = tor_strdup(desc);
    564      } else {
    565        *errmsg = "Not found in cache";
    566        return -1;
    567      }
    568    }
    569  } else if (!strcmpstart(question, "hs/service/desc/id/")) {
    570    hostname_type_t addr_type;
    571 
    572    question += strlen("hs/service/desc/id/");
    573    if (hs_address_is_valid(question)) {
    574      addr_type = ONION_V3_HOSTNAME;
    575    } else {
    576      *errmsg = "Invalid address";
    577      return -1;
    578    }
    579 
    580    if (addr_type == ONION_V3_HOSTNAME) {
    581      ed25519_public_key_t service_pk;
    582      char *desc;
    583 
    584      /* The check before this if/else makes sure of this. */
    585      tor_assert(addr_type == ONION_V3_HOSTNAME);
    586 
    587      if (hs_parse_address(question, &service_pk, NULL, NULL) < 0) {
    588        *errmsg = "Invalid v3 address";
    589        return -1;
    590      }
    591 
    592      desc = hs_service_lookup_current_desc(&service_pk);
    593      if (desc) {
    594        /* Newly allocated string, we have ownership. */
    595        *answer = desc;
    596      } else {
    597        *errmsg = "Not found in cache";
    598        return -1;
    599      }
    600    }
    601  } else if (!strcmp(question, "md/all")) {
    602    const smartlist_t *nodes = nodelist_get_list();
    603    tor_assert(nodes);
    604 
    605    if (smartlist_len(nodes) == 0) {
    606      *answer = tor_strdup("");
    607      return 0;
    608    }
    609 
    610    smartlist_t *microdescs = smartlist_new();
    611 
    612    SMARTLIST_FOREACH_BEGIN(nodes, node_t *, n) {
    613      if (n->md && n->md->body) {
    614        char *copy = tor_strndup(n->md->body, n->md->bodylen);
    615        smartlist_add(microdescs, copy);
    616      }
    617    } SMARTLIST_FOREACH_END(n);
    618 
    619    *answer = smartlist_join_strings(microdescs, "", 0, NULL);
    620    SMARTLIST_FOREACH(microdescs, char *, md, tor_free(md));
    621    smartlist_free(microdescs);
    622  } else if (!strcmpstart(question, "md/id/")) {
    623    const node_t *node = node_get_by_hex_id(question+strlen("md/id/"), 0);
    624    const microdesc_t *md = NULL;
    625    if (node) md = node->md;
    626    if (md && md->body) {
    627      *answer = tor_strndup(md->body, md->bodylen);
    628    }
    629  } else if (!strcmpstart(question, "md/name/")) {
    630    /* XXX Setting 'warn_if_unnamed' here is a bit silly -- the
    631     * warning goes to the user, not to the controller. */
    632    const node_t *node = node_get_by_nickname(question+strlen("md/name/"), 0);
    633    /* XXXX duplicated code */
    634    const microdesc_t *md = NULL;
    635    if (node) md = node->md;
    636    if (md && md->body) {
    637      *answer = tor_strndup(md->body, md->bodylen);
    638    }
    639  } else if (!strcmp(question, "md/download-enabled")) {
    640    int r = we_fetch_microdescriptors(get_options());
    641    tor_asprintf(answer, "%d", !!r);
    642  } else if (!strcmpstart(question, "desc-annotations/id/")) {
    643    const routerinfo_t *ri = NULL;
    644    const node_t *node =
    645      node_get_by_hex_id(question+strlen("desc-annotations/id/"), 0);
    646    if (node)
    647      ri = node->ri;
    648    if (ri) {
    649      const char *annotations =
    650        signed_descriptor_get_annotations(&ri->cache_info);
    651      if (annotations)
    652        *answer = tor_strndup(annotations,
    653                              ri->cache_info.annotations_len);
    654    }
    655  } else if (!strcmpstart(question, "dir/server/")) {
    656    size_t answer_len = 0;
    657    char *url = NULL;
    658    smartlist_t *descs = smartlist_new();
    659    const char *msg;
    660    int res;
    661    char *cp;
    662    tor_asprintf(&url, "/tor/%s", question+4);
    663    res = controller_get_routerdescs(descs, url, &msg);
    664    if (res) {
    665      log_warn(LD_CONTROL, "getinfo '%s': %s", question, msg);
    666      smartlist_free(descs);
    667      tor_free(url);
    668      *errmsg = msg;
    669      return -1;
    670    }
    671    SMARTLIST_FOREACH(descs, signed_descriptor_t *, sd,
    672                      answer_len += sd->signed_descriptor_len);
    673    cp = *answer = tor_malloc(answer_len+1);
    674    SMARTLIST_FOREACH(descs, signed_descriptor_t *, sd,
    675                      {
    676                        memcpy(cp, signed_descriptor_get_body(sd),
    677                               sd->signed_descriptor_len);
    678                        cp += sd->signed_descriptor_len;
    679                      });
    680    *cp = '\0';
    681    tor_free(url);
    682    smartlist_free(descs);
    683  } else if (!strcmpstart(question, "dir/status/")) {
    684    *answer = tor_strdup("");
    685  } else if (!strcmp(question, "dir/status-vote/current/consensus")) {
    686    int consensus_result = getinfo_helper_current_consensus(FLAV_NS,
    687                                                            answer, errmsg);
    688    if (consensus_result < 0) {
    689      return -1;
    690    }
    691  } else if (!strcmp(question,
    692                     "dir/status-vote/current/consensus-microdesc")) {
    693    int consensus_result = getinfo_helper_current_consensus(FLAV_MICRODESC,
    694                                                            answer, errmsg);
    695    if (consensus_result < 0) {
    696      return -1;
    697    }
    698  } else if (!strcmpstart(question, "extra-info/digest/")) {
    699    question += strlen("extra-info/digest/");
    700    if (strlen(question) == HEX_DIGEST_LEN) {
    701      char d[DIGEST_LEN];
    702      signed_descriptor_t *sd = NULL;
    703      if (base16_decode(d, sizeof(d), question, strlen(question))
    704                        == sizeof(d)) {
    705        /* XXXX this test should move into extrainfo_get_by_descriptor_digest,
    706         * but I don't want to risk affecting other parts of the code,
    707         * especially since the rules for using our own extrainfo (including
    708         * when it might be freed) are different from those for using one
    709         * we have downloaded. */
    710        if (router_extrainfo_digest_is_me(d))
    711          sd = &(router_get_my_extrainfo()->cache_info);
    712        else
    713          sd = extrainfo_get_by_descriptor_digest(d);
    714      }
    715      if (sd) {
    716        const char *body = signed_descriptor_get_body(sd);
    717        if (body)
    718          *answer = tor_strndup(body, sd->signed_descriptor_len);
    719      }
    720    }
    721  }
    722 
    723  return 0;
    724 }
    725 
    726 /** Given a smartlist of 20-byte digests, return a newly allocated string
    727 * containing each of those digests in order, formatted in HEX, and terminated
    728 * with a newline. */
    729 static char *
    730 digest_list_to_string(const smartlist_t *sl)
    731 {
    732  int len;
    733  char *result, *s;
    734 
    735  /* Allow for newlines, and a \0 at the end */
    736  len = smartlist_len(sl) * (HEX_DIGEST_LEN + 1) + 1;
    737  result = tor_malloc_zero(len);
    738 
    739  s = result;
    740  SMARTLIST_FOREACH_BEGIN(sl, const char *, digest) {
    741    base16_encode(s, HEX_DIGEST_LEN + 1, digest, DIGEST_LEN);
    742    s[HEX_DIGEST_LEN] = '\n';
    743    s += HEX_DIGEST_LEN + 1;
    744  } SMARTLIST_FOREACH_END(digest);
    745  *s = '\0';
    746 
    747  return result;
    748 }
    749 
    750 /** Turn a download_status_t into a human-readable description in a newly
    751 * allocated string.  The format is specified in control-spec.txt, under
    752 * the documentation for "GETINFO download/..." .  */
    753 static char *
    754 download_status_to_string(const download_status_t *dl)
    755 {
    756  char *rv = NULL;
    757  char tbuf[ISO_TIME_LEN+1];
    758  const char *schedule_str, *want_authority_str;
    759  const char *increment_on_str, *backoff_str;
    760 
    761  if (dl) {
    762    /* Get some substrings of the eventual output ready */
    763    format_iso_time(tbuf, download_status_get_next_attempt_at(dl));
    764 
    765    switch (dl->schedule) {
    766      case DL_SCHED_GENERIC:
    767        schedule_str = "DL_SCHED_GENERIC";
    768        break;
    769      case DL_SCHED_CONSENSUS:
    770        schedule_str = "DL_SCHED_CONSENSUS";
    771        break;
    772      case DL_SCHED_BRIDGE:
    773        schedule_str = "DL_SCHED_BRIDGE";
    774        break;
    775      default:
    776        schedule_str = "unknown";
    777        break;
    778    }
    779 
    780    switch (dl->want_authority) {
    781      case DL_WANT_ANY_DIRSERVER:
    782        want_authority_str = "DL_WANT_ANY_DIRSERVER";
    783        break;
    784      case DL_WANT_AUTHORITY:
    785        want_authority_str = "DL_WANT_AUTHORITY";
    786        break;
    787      default:
    788        want_authority_str = "unknown";
    789        break;
    790    }
    791 
    792    switch (dl->increment_on) {
    793      case DL_SCHED_INCREMENT_FAILURE:
    794        increment_on_str = "DL_SCHED_INCREMENT_FAILURE";
    795        break;
    796      case DL_SCHED_INCREMENT_ATTEMPT:
    797        increment_on_str = "DL_SCHED_INCREMENT_ATTEMPT";
    798        break;
    799      default:
    800        increment_on_str = "unknown";
    801        break;
    802    }
    803 
    804    backoff_str = "DL_SCHED_RANDOM_EXPONENTIAL";
    805 
    806    /* Now assemble them */
    807    tor_asprintf(&rv,
    808                 "next-attempt-at %s\n"
    809                 "n-download-failures %u\n"
    810                 "n-download-attempts %u\n"
    811                 "schedule %s\n"
    812                 "want-authority %s\n"
    813                 "increment-on %s\n"
    814                 "backoff %s\n"
    815                 "last-backoff-position %u\n"
    816                 "last-delay-used %d\n",
    817                 tbuf,
    818                 dl->n_download_failures,
    819                 dl->n_download_attempts,
    820                 schedule_str,
    821                 want_authority_str,
    822                 increment_on_str,
    823                 backoff_str,
    824                 dl->last_backoff_position,
    825                 dl->last_delay_used);
    826  }
    827 
    828  return rv;
    829 }
    830 
    831 /** Handle the consensus download cases for getinfo_helper_downloads() */
    832 STATIC void
    833 getinfo_helper_downloads_networkstatus(const char *flavor,
    834                                       download_status_t **dl_to_emit,
    835                                       const char **errmsg)
    836 {
    837  /*
    838   * We get the one for the current bootstrapped status by default, or
    839   * take an extra /bootstrap or /running suffix
    840   */
    841  if (strcmp(flavor, "ns") == 0) {
    842    *dl_to_emit = networkstatus_get_dl_status_by_flavor(FLAV_NS);
    843  } else if (strcmp(flavor, "ns/bootstrap") == 0) {
    844    *dl_to_emit = networkstatus_get_dl_status_by_flavor_bootstrap(FLAV_NS);
    845  } else if (strcmp(flavor, "ns/running") == 0 ) {
    846    *dl_to_emit = networkstatus_get_dl_status_by_flavor_running(FLAV_NS);
    847  } else if (strcmp(flavor, "microdesc") == 0) {
    848    *dl_to_emit = networkstatus_get_dl_status_by_flavor(FLAV_MICRODESC);
    849  } else if (strcmp(flavor, "microdesc/bootstrap") == 0) {
    850    *dl_to_emit =
    851      networkstatus_get_dl_status_by_flavor_bootstrap(FLAV_MICRODESC);
    852  } else if (strcmp(flavor, "microdesc/running") == 0) {
    853    *dl_to_emit =
    854      networkstatus_get_dl_status_by_flavor_running(FLAV_MICRODESC);
    855  } else {
    856    *errmsg = "Unknown flavor";
    857  }
    858 }
    859 
    860 /** Handle the cert download cases for getinfo_helper_downloads() */
    861 STATIC void
    862 getinfo_helper_downloads_cert(const char *fp_sk_req,
    863                              download_status_t **dl_to_emit,
    864                              smartlist_t **digest_list,
    865                              const char **errmsg)
    866 {
    867  const char *sk_req;
    868  char id_digest[DIGEST_LEN];
    869  char sk_digest[DIGEST_LEN];
    870 
    871  /*
    872   * We have to handle four cases; fp_sk_req is the request with
    873   * a prefix of "downloads/cert/" snipped off.
    874   *
    875   * Case 1: fp_sk_req = "fps"
    876   *  - We should emit a digest_list with a list of all the identity
    877   *    fingerprints that can be queried for certificate download status;
    878   *    get it by calling list_authority_ids_with_downloads().
    879   *
    880   * Case 2: fp_sk_req = "fp/<fp>" for some fingerprint fp
    881   *  - We want the default certificate for this identity fingerprint's
    882   *    download status; this is the download we get from URLs starting
    883   *    in /fp/ on the directory server.  We can get it with
    884   *    id_only_download_status_for_authority_id().
    885   *
    886   * Case 3: fp_sk_req = "fp/<fp>/sks" for some fingerprint fp
    887   *  - We want a list of all signing key digests for this identity
    888   *    fingerprint which can be queried for certificate download status.
    889   *    Get it with list_sk_digests_for_authority_id().
    890   *
    891   * Case 4: fp_sk_req = "fp/<fp>/<sk>" for some fingerprint fp and
    892   *         signing key digest sk
    893   *   - We want the download status for the certificate for this specific
    894   *     signing key and fingerprint.  These correspond to the ones we get
    895   *     from URLs starting in /fp-sk/ on the directory server.  Get it with
    896   *     list_sk_digests_for_authority_id().
    897   */
    898 
    899  if (strcmp(fp_sk_req, "fps") == 0) {
    900    *digest_list = list_authority_ids_with_downloads();
    901    if (!(*digest_list)) {
    902      *errmsg = "Failed to get list of authority identity digests (!)";
    903    }
    904  } else if (!strcmpstart(fp_sk_req, "fp/")) {
    905    fp_sk_req += strlen("fp/");
    906    /* Okay, look for another / to tell the fp from fp-sk cases */
    907    sk_req = strchr(fp_sk_req, '/');
    908    if (sk_req) {
    909      /* okay, split it here and try to parse <fp> */
    910      if (base16_decode(id_digest, DIGEST_LEN,
    911                        fp_sk_req, sk_req - fp_sk_req) == DIGEST_LEN) {
    912        /* Skip past the '/' */
    913        ++sk_req;
    914        if (strcmp(sk_req, "sks") == 0) {
    915          /* We're asking for the list of signing key fingerprints */
    916          *digest_list = list_sk_digests_for_authority_id(id_digest);
    917          if (!(*digest_list)) {
    918            *errmsg = "Failed to get list of signing key digests for this "
    919                      "authority identity digest";
    920          }
    921        } else {
    922          /* We've got a signing key digest */
    923          if (base16_decode(sk_digest, DIGEST_LEN,
    924                            sk_req, strlen(sk_req)) == DIGEST_LEN) {
    925            *dl_to_emit =
    926              download_status_for_authority_id_and_sk(id_digest, sk_digest);
    927            if (!(*dl_to_emit)) {
    928              *errmsg = "Failed to get download status for this identity/"
    929                        "signing key digest pair";
    930            }
    931          } else {
    932            *errmsg = "That didn't look like a signing key digest";
    933          }
    934        }
    935      } else {
    936        *errmsg = "That didn't look like an identity digest";
    937      }
    938    } else {
    939      /* We're either in downloads/certs/fp/<fp>, or we can't parse <fp> */
    940      if (strlen(fp_sk_req) == HEX_DIGEST_LEN) {
    941        if (base16_decode(id_digest, DIGEST_LEN,
    942                          fp_sk_req, strlen(fp_sk_req)) == DIGEST_LEN) {
    943          *dl_to_emit = id_only_download_status_for_authority_id(id_digest);
    944          if (!(*dl_to_emit)) {
    945            *errmsg = "Failed to get download status for this authority "
    946                      "identity digest";
    947          }
    948        } else {
    949          *errmsg = "That didn't look like a digest";
    950        }
    951      } else {
    952        *errmsg = "That didn't look like a digest";
    953      }
    954    }
    955  } else {
    956    *errmsg = "Unknown certificate download status query";
    957  }
    958 }
    959 
    960 /** Handle the routerdesc download cases for getinfo_helper_downloads() */
    961 STATIC void
    962 getinfo_helper_downloads_desc(const char *desc_req,
    963                              download_status_t **dl_to_emit,
    964                              smartlist_t **digest_list,
    965                              const char **errmsg)
    966 {
    967  char desc_digest[DIGEST_LEN];
    968  /*
    969   * Two cases to handle here:
    970   *
    971   * Case 1: desc_req = "descs"
    972   *   - Emit a list of all router descriptor digests, which we get by
    973   *     calling router_get_descriptor_digests(); this can return NULL
    974   *     if we have no current ns-flavor consensus.
    975   *
    976   * Case 2: desc_req = <fp>
    977   *   - Check on the specified fingerprint and emit its download_status_t
    978   *     using router_get_dl_status_by_descriptor_digest().
    979   */
    980 
    981  if (strcmp(desc_req, "descs") == 0) {
    982    *digest_list = router_get_descriptor_digests();
    983    if (!(*digest_list)) {
    984      *errmsg = "We don't seem to have a networkstatus-flavored consensus";
    985    }
    986    /*
    987     * Microdescs don't use the download_status_t mechanism, so we don't
    988     * answer queries about their downloads here; see microdesc.c.
    989     */
    990  } else if (strlen(desc_req) == HEX_DIGEST_LEN) {
    991    if (base16_decode(desc_digest, DIGEST_LEN,
    992                      desc_req, strlen(desc_req)) == DIGEST_LEN) {
    993      /* Okay we got a digest-shaped thing; try asking for it */
    994      *dl_to_emit = router_get_dl_status_by_descriptor_digest(desc_digest);
    995      if (!(*dl_to_emit)) {
    996        *errmsg = "No such descriptor digest found";
    997      }
    998    } else {
    999      *errmsg = "That didn't look like a digest";
   1000    }
   1001  } else {
   1002    *errmsg = "Unknown router descriptor download status query";
   1003  }
   1004 }
   1005 
   1006 /** Handle the bridge download cases for getinfo_helper_downloads() */
   1007 STATIC void
   1008 getinfo_helper_downloads_bridge(const char *bridge_req,
   1009                                download_status_t **dl_to_emit,
   1010                                smartlist_t **digest_list,
   1011                                const char **errmsg)
   1012 {
   1013  char bridge_digest[DIGEST_LEN];
   1014  /*
   1015   * Two cases to handle here:
   1016   *
   1017   * Case 1: bridge_req = "bridges"
   1018   *   - Emit a list of all bridge identity digests, which we get by
   1019   *     calling list_bridge_identities(); this can return NULL if we are
   1020   *     not using bridges.
   1021   *
   1022   * Case 2: bridge_req = <fp>
   1023   *   - Check on the specified fingerprint and emit its download_status_t
   1024   *     using get_bridge_dl_status_by_id().
   1025   */
   1026 
   1027  if (strcmp(bridge_req, "bridges") == 0) {
   1028    *digest_list = list_bridge_identities();
   1029    if (!(*digest_list)) {
   1030      *errmsg = "We don't seem to be using bridges";
   1031    }
   1032  } else if (strlen(bridge_req) == HEX_DIGEST_LEN) {
   1033    if (base16_decode(bridge_digest, DIGEST_LEN,
   1034                      bridge_req, strlen(bridge_req)) == DIGEST_LEN) {
   1035      /* Okay we got a digest-shaped thing; try asking for it */
   1036      *dl_to_emit = get_bridge_dl_status_by_id(bridge_digest);
   1037      if (!(*dl_to_emit)) {
   1038        *errmsg = "No such bridge identity digest found";
   1039      }
   1040    } else {
   1041      *errmsg = "That didn't look like a digest";
   1042    }
   1043  } else {
   1044    *errmsg = "Unknown bridge descriptor download status query";
   1045  }
   1046 }
   1047 
   1048 /** Implementation helper for GETINFO: knows the answers for questions about
   1049 * download status information. */
   1050 STATIC int
   1051 getinfo_helper_downloads(control_connection_t *control_conn,
   1052                   const char *question, char **answer,
   1053                   const char **errmsg)
   1054 {
   1055  download_status_t *dl_to_emit = NULL;
   1056  smartlist_t *digest_list = NULL;
   1057 
   1058  /* Assert args are sane */
   1059  tor_assert(control_conn != NULL);
   1060  tor_assert(question != NULL);
   1061  tor_assert(answer != NULL);
   1062  tor_assert(errmsg != NULL);
   1063 
   1064  /* We check for this later to see if we should supply a default */
   1065  *errmsg = NULL;
   1066 
   1067  /* Are we after networkstatus downloads? */
   1068  if (!strcmpstart(question, "downloads/networkstatus/")) {
   1069    getinfo_helper_downloads_networkstatus(
   1070        question + strlen("downloads/networkstatus/"),
   1071        &dl_to_emit, errmsg);
   1072  /* Certificates? */
   1073  } else if (!strcmpstart(question, "downloads/cert/")) {
   1074    getinfo_helper_downloads_cert(
   1075        question + strlen("downloads/cert/"),
   1076        &dl_to_emit, &digest_list, errmsg);
   1077  /* Router descriptors? */
   1078  } else if (!strcmpstart(question, "downloads/desc/")) {
   1079    getinfo_helper_downloads_desc(
   1080        question + strlen("downloads/desc/"),
   1081        &dl_to_emit, &digest_list, errmsg);
   1082  /* Bridge descriptors? */
   1083  } else if (!strcmpstart(question, "downloads/bridge/")) {
   1084    getinfo_helper_downloads_bridge(
   1085        question + strlen("downloads/bridge/"),
   1086        &dl_to_emit, &digest_list, errmsg);
   1087  } else {
   1088    *errmsg = "Unknown download status query";
   1089  }
   1090 
   1091  if (dl_to_emit) {
   1092    *answer = download_status_to_string(dl_to_emit);
   1093 
   1094    return 0;
   1095  } else if (digest_list) {
   1096    *answer = digest_list_to_string(digest_list);
   1097    SMARTLIST_FOREACH(digest_list, void *, s, tor_free(s));
   1098    smartlist_free(digest_list);
   1099 
   1100    return 0;
   1101  } else {
   1102    if (!(*errmsg)) {
   1103      *errmsg = "Unknown error";
   1104    }
   1105 
   1106    return -1;
   1107  }
   1108 }
   1109 
   1110 /** Implementation helper for GETINFO: knows how to generate summaries of the
   1111 * current states of things we send events about. */
   1112 static int
   1113 getinfo_helper_events(control_connection_t *control_conn,
   1114                      const char *question, char **answer,
   1115                      const char **errmsg)
   1116 {
   1117  const or_options_t *options = get_options();
   1118  (void) control_conn;
   1119  if (!strcmp(question, "circuit-status")) {
   1120    smartlist_t *status = smartlist_new();
   1121    SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t *, circ_) {
   1122      origin_circuit_t *circ;
   1123      char *circdesc;
   1124      const char *state;
   1125      if (! CIRCUIT_IS_ORIGIN(circ_) || circ_->marked_for_close)
   1126        continue;
   1127      circ = TO_ORIGIN_CIRCUIT(circ_);
   1128 
   1129      if (circ->base_.state == CIRCUIT_STATE_OPEN)
   1130        state = "BUILT";
   1131      else if (circ->base_.state == CIRCUIT_STATE_GUARD_WAIT)
   1132        state = "GUARD_WAIT";
   1133      else if (circ->cpath)
   1134        state = "EXTENDED";
   1135      else
   1136        state = "LAUNCHED";
   1137 
   1138      circdesc = circuit_describe_status_for_controller(circ);
   1139 
   1140      smartlist_add_asprintf(status, "%lu %s%s%s",
   1141                   (unsigned long)circ->global_identifier,
   1142                   state, *circdesc ? " " : "", circdesc);
   1143      tor_free(circdesc);
   1144    }
   1145    SMARTLIST_FOREACH_END(circ_);
   1146    *answer = smartlist_join_strings(status, "\r\n", 0, NULL);
   1147    SMARTLIST_FOREACH(status, char *, cp, tor_free(cp));
   1148    smartlist_free(status);
   1149  } else if (!strcmp(question, "stream-status")) {
   1150    smartlist_t *conns = get_connection_array();
   1151    smartlist_t *status = smartlist_new();
   1152    char buf[256];
   1153    SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
   1154      const char *state;
   1155      entry_connection_t *conn;
   1156      circuit_t *circ;
   1157      origin_circuit_t *origin_circ = NULL;
   1158      if (base_conn->type != CONN_TYPE_AP ||
   1159          base_conn->marked_for_close ||
   1160          base_conn->state == AP_CONN_STATE_SOCKS_WAIT ||
   1161          base_conn->state == AP_CONN_STATE_NATD_WAIT)
   1162        continue;
   1163      conn = TO_ENTRY_CONN(base_conn);
   1164      switch (base_conn->state)
   1165        {
   1166        case AP_CONN_STATE_CONTROLLER_WAIT:
   1167        case AP_CONN_STATE_CIRCUIT_WAIT:
   1168          if (conn->socks_request &&
   1169              SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command))
   1170            state = "NEWRESOLVE";
   1171          else
   1172            state = "NEW";
   1173          break;
   1174        case AP_CONN_STATE_RENDDESC_WAIT:
   1175        case AP_CONN_STATE_CONNECT_WAIT:
   1176          state = "SENTCONNECT"; break;
   1177        case AP_CONN_STATE_RESOLVE_WAIT:
   1178          state = "SENTRESOLVE"; break;
   1179        case AP_CONN_STATE_OPEN:
   1180          state = "SUCCEEDED"; break;
   1181        default:
   1182          log_warn(LD_BUG, "Asked for stream in unknown state %d",
   1183                   base_conn->state);
   1184          continue;
   1185        }
   1186      circ = circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn));
   1187      if (circ && CIRCUIT_IS_ORIGIN(circ))
   1188        origin_circ = TO_ORIGIN_CIRCUIT(circ);
   1189      write_stream_target_to_buf(conn, buf, sizeof(buf));
   1190      smartlist_add_asprintf(status, "%lu %s %lu %s",
   1191                   (unsigned long) base_conn->global_identifier,state,
   1192                   origin_circ?
   1193                         (unsigned long)origin_circ->global_identifier : 0ul,
   1194                   buf);
   1195    } SMARTLIST_FOREACH_END(base_conn);
   1196    *answer = smartlist_join_strings(status, "\r\n", 0, NULL);
   1197    SMARTLIST_FOREACH(status, char *, cp, tor_free(cp));
   1198    smartlist_free(status);
   1199  } else if (!strcmp(question, "orconn-status")) {
   1200    smartlist_t *conns = get_connection_array();
   1201    smartlist_t *status = smartlist_new();
   1202    SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
   1203      const char *state;
   1204      char name[128];
   1205      or_connection_t *conn;
   1206      if (base_conn->type != CONN_TYPE_OR || base_conn->marked_for_close)
   1207        continue;
   1208      conn = TO_OR_CONN(base_conn);
   1209      if (conn->base_.state == OR_CONN_STATE_OPEN)
   1210        state = "CONNECTED";
   1211      else if (conn->nickname)
   1212        state = "LAUNCHED";
   1213      else
   1214        state = "NEW";
   1215      orconn_target_get_name(name, sizeof(name), conn);
   1216      smartlist_add_asprintf(status, "%s %s", name, state);
   1217    } SMARTLIST_FOREACH_END(base_conn);
   1218    *answer = smartlist_join_strings(status, "\r\n", 0, NULL);
   1219    SMARTLIST_FOREACH(status, char *, cp, tor_free(cp));
   1220    smartlist_free(status);
   1221  } else if (!strcmpstart(question, "address-mappings/")) {
   1222    time_t min_e, max_e;
   1223    smartlist_t *mappings;
   1224    question += strlen("address-mappings/");
   1225    if (!strcmp(question, "all")) {
   1226      min_e = 0; max_e = TIME_MAX;
   1227    } else if (!strcmp(question, "cache")) {
   1228      min_e = 2; max_e = TIME_MAX;
   1229    } else if (!strcmp(question, "config")) {
   1230      min_e = 0; max_e = 0;
   1231    } else if (!strcmp(question, "control")) {
   1232      min_e = 1; max_e = 1;
   1233    } else {
   1234      return 0;
   1235    }
   1236    mappings = smartlist_new();
   1237    addressmap_get_mappings(mappings, min_e, max_e, 1);
   1238    *answer = smartlist_join_strings(mappings, "\r\n", 0, NULL);
   1239    SMARTLIST_FOREACH(mappings, char *, cp, tor_free(cp));
   1240    smartlist_free(mappings);
   1241  } else if (!strcmpstart(question, "status/")) {
   1242    /* Note that status/ is not a catch-all for events; there's only supposed
   1243     * to be a status GETINFO if there's a corresponding STATUS event. */
   1244    if (!strcmp(question, "status/circuit-established")) {
   1245      *answer = tor_strdup(have_completed_a_circuit() ? "1" : "0");
   1246    } else if (!strcmp(question, "status/enough-dir-info")) {
   1247      *answer = tor_strdup(router_have_minimum_dir_info() ? "1" : "0");
   1248    } else if (!strcmp(question, "status/good-server-descriptor") ||
   1249               !strcmp(question, "status/accepted-server-descriptor")) {
   1250      /* They're equivalent for now, until we can figure out how to make
   1251       * good-server-descriptor be what we want. See comment in
   1252       * control-spec.txt. */
   1253      *answer = tor_strdup(directories_have_accepted_server_descriptor()
   1254                           ? "1" : "0");
   1255    } else if (!strcmp(question, "status/reachability-succeeded/or")) {
   1256      *answer = tor_strdup(
   1257                    router_all_orports_seem_reachable(options) ?
   1258                    "1" : "0");
   1259    } else if (!strcmp(question, "status/reachability-succeeded/dir")) {
   1260      *answer = tor_strdup("1"); /* obsolete since tor#2667) */
   1261    } else if (!strcmp(question, "status/reachability-succeeded")) {
   1262      tor_asprintf(
   1263          answer, "OR=%d DIR=%d",
   1264          router_all_orports_seem_reachable(options) ? 1 : 0,
   1265          1);
   1266    } else if (!strcmp(question, "status/bootstrap-phase")) {
   1267      *answer = control_event_boot_last_msg();
   1268    } else if (!strcmpstart(question, "status/version/")) {
   1269      int is_server = server_mode(options);
   1270      networkstatus_t *c = networkstatus_get_latest_consensus();
   1271      version_status_t status;
   1272      const char *recommended;
   1273      if (c) {
   1274        recommended = is_server ? c->server_versions : c->client_versions;
   1275        status = tor_version_is_obsolete(VERSION, recommended);
   1276      } else {
   1277        recommended = "?";
   1278        status = VS_UNKNOWN;
   1279      }
   1280 
   1281      if (!strcmp(question, "status/version/recommended")) {
   1282        *answer = tor_strdup(recommended);
   1283        return 0;
   1284      }
   1285      if (!strcmp(question, "status/version/current")) {
   1286        switch (status)
   1287          {
   1288          case VS_RECOMMENDED: *answer = tor_strdup("recommended"); break;
   1289          case VS_OLD: *answer = tor_strdup("obsolete"); break;
   1290          case VS_NEW: *answer = tor_strdup("new"); break;
   1291          case VS_NEW_IN_SERIES: *answer = tor_strdup("new in series"); break;
   1292          case VS_UNRECOMMENDED: *answer = tor_strdup("unrecommended"); break;
   1293          case VS_EMPTY: *answer = tor_strdup("none recommended"); break;
   1294          case VS_UNKNOWN: *answer = tor_strdup("unknown"); break;
   1295          default: tor_fragile_assert();
   1296          }
   1297      }
   1298    } else if (!strcmp(question, "status/clients-seen")) {
   1299      char *bridge_stats = geoip_get_bridge_stats_controller(time(NULL));
   1300      if (!bridge_stats) {
   1301        *errmsg = "No bridge-client stats available";
   1302        return -1;
   1303      }
   1304      *answer = bridge_stats;
   1305    } else if (!strcmp(question, "status/fresh-relay-descs")) {
   1306      if (!server_mode(options)) {
   1307        *errmsg = "Only relays have descriptors";
   1308        return -1;
   1309      }
   1310      routerinfo_t *r;
   1311      extrainfo_t *e;
   1312      int result;
   1313      if ((result = router_build_fresh_descriptor(&r, &e)) < 0) {
   1314        switch (result) {
   1315          case TOR_ROUTERINFO_ERROR_NO_EXT_ADDR:
   1316            *errmsg = "Cannot get relay address while generating descriptor";
   1317            break;
   1318          case TOR_ROUTERINFO_ERROR_DIGEST_FAILED:
   1319            *errmsg = "Key digest failed";
   1320            break;
   1321          case TOR_ROUTERINFO_ERROR_CANNOT_GENERATE:
   1322            *errmsg = "Cannot generate router descriptor";
   1323            break;
   1324          default:
   1325            *errmsg = "Error generating descriptor";
   1326            break;
   1327        }
   1328        return -1;
   1329      }
   1330      size_t size = r->cache_info.signed_descriptor_len + 1;
   1331      if (e) {
   1332        size += e->cache_info.signed_descriptor_len + 1;
   1333      }
   1334      tor_assert(r->cache_info.signed_descriptor_len);
   1335      char *descs = tor_malloc(size);
   1336      char *cp = descs;
   1337      memcpy(cp, signed_descriptor_get_body(&r->cache_info),
   1338             r->cache_info.signed_descriptor_len);
   1339      cp += r->cache_info.signed_descriptor_len - 1;
   1340      if (e) {
   1341        if (cp[0] == '\0') {
   1342          cp[0] = '\n';
   1343        } else if (cp[0] != '\n') {
   1344          cp[1] = '\n';
   1345          cp++;
   1346        }
   1347        memcpy(cp, signed_descriptor_get_body(&e->cache_info),
   1348               e->cache_info.signed_descriptor_len);
   1349        cp += e->cache_info.signed_descriptor_len - 1;
   1350      }
   1351      if (cp[0] == '\n') {
   1352        cp[0] = '\0';
   1353      } else if (cp[0] != '\0') {
   1354        cp[1] = '\0';
   1355      }
   1356      *answer = descs;
   1357      routerinfo_free(r);
   1358      extrainfo_free(e);
   1359    } else {
   1360      return 0;
   1361    }
   1362  }
   1363  return 0;
   1364 }
   1365 
   1366 /** Implementation helper for GETINFO: knows how to enumerate hidden services
   1367 * created via the control port. */
   1368 STATIC int
   1369 getinfo_helper_onions(control_connection_t *control_conn,
   1370                      const char *question, char **answer,
   1371                      const char **errmsg)
   1372 {
   1373  smartlist_t *onion_list = NULL;
   1374  (void) errmsg;  /* no errors from this method */
   1375 
   1376  if (control_conn && !strcmp(question, "onions/current")) {
   1377    onion_list = control_conn->ephemeral_onion_services;
   1378  } else if (!strcmp(question, "onions/detached")) {
   1379    onion_list = get_detached_onion_services();
   1380  } else {
   1381    return 0;
   1382  }
   1383  if (!onion_list || smartlist_len(onion_list) == 0) {
   1384    if (answer) {
   1385      *answer = tor_strdup("");
   1386    }
   1387  } else {
   1388    if (answer) {
   1389      *answer = smartlist_join_strings(onion_list, "\r\n", 0, NULL);
   1390    }
   1391  }
   1392 
   1393  return 0;
   1394 }
   1395 
   1396 /** Implementation helper for GETINFO: answers queries about network
   1397 * liveness. */
   1398 static int
   1399 getinfo_helper_liveness(control_connection_t *control_conn,
   1400                      const char *question, char **answer,
   1401                      const char **errmsg)
   1402 {
   1403  (void)control_conn;
   1404  (void)errmsg;
   1405  if (strcmp(question, "network-liveness") == 0) {
   1406    if (get_cached_network_liveness()) {
   1407      *answer = tor_strdup("up");
   1408    } else {
   1409      *answer = tor_strdup("down");
   1410    }
   1411  }
   1412 
   1413  return 0;
   1414 }
   1415 
   1416 /** Implementation helper for GETINFO: answers queries about circuit onion
   1417 * handshake rephist values */
   1418 STATIC int
   1419 getinfo_helper_rephist(control_connection_t *control_conn,
   1420                       const char *question, char **answer,
   1421                       const char **errmsg)
   1422 {
   1423  (void) control_conn;
   1424  (void) errmsg;
   1425  int result;
   1426 
   1427  if (!strcmp(question, "stats/ntor/assigned")) {
   1428    result =
   1429      rep_hist_get_circuit_handshake_assigned(ONION_HANDSHAKE_TYPE_NTOR);
   1430  } else if (!strcmp(question, "stats/ntor/requested")) {
   1431    result =
   1432      rep_hist_get_circuit_handshake_requested(ONION_HANDSHAKE_TYPE_NTOR);
   1433  } else if (!strcmp(question, "stats/tap/assigned")) {
   1434    result =
   1435      rep_hist_get_circuit_handshake_assigned(ONION_HANDSHAKE_TYPE_TAP);
   1436  } else if (!strcmp(question, "stats/tap/requested")) {
   1437    result =
   1438      rep_hist_get_circuit_handshake_requested(ONION_HANDSHAKE_TYPE_TAP);
   1439  } else {
   1440    *errmsg = "Unrecognized handshake type";
   1441    return -1;
   1442  }
   1443 
   1444  tor_asprintf(answer, "%d", result);
   1445 
   1446  return 0;
   1447 }
   1448 
   1449 /** Implementation helper for GETINFO: answers queries about shared random
   1450 * value. */
   1451 static int
   1452 getinfo_helper_sr(control_connection_t *control_conn,
   1453                  const char *question, char **answer,
   1454                  const char **errmsg)
   1455 {
   1456  (void) control_conn;
   1457  (void) errmsg;
   1458 
   1459  if (!strcmp(question, "sr/current")) {
   1460    *answer = sr_get_current_for_control();
   1461  } else if (!strcmp(question, "sr/previous")) {
   1462    *answer = sr_get_previous_for_control();
   1463  }
   1464  /* Else statement here is unrecognized key so do nothing. */
   1465 
   1466  return 0;
   1467 }
   1468 
   1469 /** Callback function for GETINFO: on a given control connection, try to
   1470 * answer the question <b>q</b> and store the newly-allocated answer in
   1471 * *<b>a</b>. If an internal error occurs, return -1 and optionally set
   1472 * *<b>error_out</b> to point to an error message to be delivered to the
   1473 * controller. On success, _or if the key is not recognized_, return 0. Do not
   1474 * set <b>a</b> if the key is not recognized but you may set <b>error_out</b>
   1475 * to improve the error message.
   1476 */
   1477 typedef int (*getinfo_helper_t)(control_connection_t *,
   1478                                const char *q, char **a,
   1479                                const char **error_out);
   1480 
   1481 /** A single item for the GETINFO question-to-answer-function table. */
   1482 typedef struct getinfo_item_t {
   1483  const char *varname; /**< The value (or prefix) of the question. */
   1484  getinfo_helper_t fn; /**< The function that knows the answer: NULL if
   1485                        * this entry is documentation-only. */
   1486  const char *desc; /**< Description of the variable. */
   1487  int is_prefix; /** Must varname match exactly, or must it be a prefix? */
   1488 } getinfo_item_t;
   1489 
   1490 #define ITEM(name, fn, desc) { name, getinfo_helper_##fn, desc, 0 }
   1491 #define PREFIX(name, fn, desc) { name, getinfo_helper_##fn, desc, 1 }
   1492 #define DOC(name, desc) { name, NULL, desc, 0 }
   1493 
   1494 /** Table mapping questions accepted by GETINFO to the functions that know how
   1495 * to answer them. */
   1496 static const getinfo_item_t getinfo_items[] = {
   1497  ITEM("version", misc, "The current version of Tor."),
   1498  ITEM("bw-event-cache", misc, "Cached BW events for a short interval."),
   1499  ITEM("config-file", misc, "Current location of the \"torrc\" file."),
   1500  ITEM("config-defaults-file", misc, "Current location of the defaults file."),
   1501  ITEM("config-text", misc,
   1502       "Return the string that would be written by a saveconf command."),
   1503  ITEM("config-can-saveconf", misc,
   1504       "Is it possible to save the configuration to the \"torrc\" file?"),
   1505  ITEM("accounting/bytes", accounting,
   1506       "Number of bytes read/written so far in the accounting interval."),
   1507  ITEM("accounting/bytes-left", accounting,
   1508      "Number of bytes left to write/read so far in the accounting interval."),
   1509  ITEM("accounting/enabled", accounting, "Is accounting currently enabled?"),
   1510  ITEM("accounting/hibernating", accounting, "Are we hibernating or awake?"),
   1511  ITEM("accounting/interval-start", accounting,
   1512       "Time when the accounting period starts."),
   1513  ITEM("accounting/interval-end", accounting,
   1514       "Time when the accounting period ends."),
   1515  ITEM("accounting/interval-wake", accounting,
   1516       "Time to wake up in this accounting period."),
   1517  ITEM("helper-nodes", entry_guards, NULL), /* deprecated */
   1518  ITEM("entry-guards", entry_guards,
   1519       "Which nodes are we using as entry guards?"),
   1520  ITEM("fingerprint", misc, NULL),
   1521  PREFIX("config/", config, "Current configuration values."),
   1522  DOC("config/names",
   1523      "List of configuration options, types, and documentation."),
   1524  DOC("config/defaults",
   1525      "List of default values for configuration options. "
   1526      "See also config/names"),
   1527  PREFIX("current-time/", current_time, "Current time."),
   1528  DOC("current-time/local", "Current time on the local system."),
   1529  DOC("current-time/utc", "Current UTC time."),
   1530  PREFIX("downloads/networkstatus/", downloads,
   1531         "Download statuses for networkstatus objects"),
   1532  DOC("downloads/networkstatus/ns",
   1533      "Download status for current-mode networkstatus download"),
   1534  DOC("downloads/networkstatus/ns/bootstrap",
   1535      "Download status for bootstrap-time networkstatus download"),
   1536  DOC("downloads/networkstatus/ns/running",
   1537      "Download status for run-time networkstatus download"),
   1538  DOC("downloads/networkstatus/microdesc",
   1539      "Download status for current-mode microdesc download"),
   1540  DOC("downloads/networkstatus/microdesc/bootstrap",
   1541      "Download status for bootstrap-time microdesc download"),
   1542  DOC("downloads/networkstatus/microdesc/running",
   1543      "Download status for run-time microdesc download"),
   1544  PREFIX("downloads/cert/", downloads,
   1545         "Download statuses for certificates, by id fingerprint and "
   1546         "signing key"),
   1547  DOC("downloads/cert/fps",
   1548      "List of authority fingerprints for which any download statuses "
   1549      "exist"),
   1550  DOC("downloads/cert/fp/<fp>",
   1551      "Download status for <fp> with the default signing key; corresponds "
   1552      "to /fp/ URLs on directory server."),
   1553  DOC("downloads/cert/fp/<fp>/sks",
   1554      "List of signing keys for which specific download statuses are "
   1555      "available for this id fingerprint"),
   1556  DOC("downloads/cert/fp/<fp>/<sk>",
   1557      "Download status for <fp> with signing key <sk>; corresponds "
   1558      "to /fp-sk/ URLs on directory server."),
   1559  PREFIX("downloads/desc/", downloads,
   1560         "Download statuses for router descriptors, by descriptor digest"),
   1561  DOC("downloads/desc/descs",
   1562      "Return a list of known router descriptor digests"),
   1563  DOC("downloads/desc/<desc>",
   1564      "Return a download status for a given descriptor digest"),
   1565  PREFIX("downloads/bridge/", downloads,
   1566         "Download statuses for bridge descriptors, by bridge identity "
   1567         "digest"),
   1568  DOC("downloads/bridge/bridges",
   1569      "Return a list of configured bridge identity digests with download "
   1570      "statuses"),
   1571  DOC("downloads/bridge/<desc>",
   1572      "Return a download status for a given bridge identity digest"),
   1573  ITEM("info/names", misc,
   1574       "List of GETINFO options, types, and documentation."),
   1575  ITEM("events/names", misc,
   1576       "Events that the controller can ask for with SETEVENTS."),
   1577  ITEM("signal/names", misc, "Signal names recognized by the SIGNAL command"),
   1578  ITEM("features/names", misc, "What arguments can USEFEATURE take?"),
   1579  PREFIX("desc/id/", dir, "Router descriptors by ID."),
   1580  PREFIX("desc/name/", dir, "Router descriptors by nickname."),
   1581  ITEM("desc/all-recent", dir,
   1582       "All non-expired, non-superseded router descriptors."),
   1583  ITEM("desc/download-enabled", dir,
   1584       "Do we try to download router descriptors?"),
   1585  ITEM("desc/all-recent-extrainfo-hack", dir, NULL), /* Hack. */
   1586  ITEM("md/all", dir, "All known microdescriptors."),
   1587  PREFIX("md/id/", dir, "Microdescriptors by ID"),
   1588  PREFIX("md/name/", dir, "Microdescriptors by name"),
   1589  ITEM("md/download-enabled", dir,
   1590       "Do we try to download microdescriptors?"),
   1591  PREFIX("extra-info/digest/", dir, "Extra-info documents by digest."),
   1592  PREFIX("hs/client/desc/id", dir,
   1593         "Hidden Service descriptor in client's cache by onion."),
   1594  PREFIX("hs/service/desc/id/", dir,
   1595         "Hidden Service descriptor in services's cache by onion."),
   1596  PREFIX("net/listeners/", listeners, "Bound addresses by type"),
   1597  ITEM("ns/all", networkstatus,
   1598       "Brief summary of router status (v2 directory format)"),
   1599  PREFIX("ns/id/", networkstatus,
   1600         "Brief summary of router status by ID (v2 directory format)."),
   1601  PREFIX("ns/name/", networkstatus,
   1602         "Brief summary of router status by nickname (v2 directory format)."),
   1603  PREFIX("ns/purpose/", networkstatus,
   1604         "Brief summary of router status by purpose (v2 directory format)."),
   1605  PREFIX("consensus/", networkstatus,
   1606         "Information about and from the ns consensus."),
   1607  ITEM("network-status", dir,
   1608       "Brief summary of router status (v1 directory format)"),
   1609  ITEM("network-liveness", liveness,
   1610       "Current opinion on whether the network is live"),
   1611  ITEM("circuit-status", events, "List of current circuits originating here."),
   1612  ITEM("stream-status", events,"List of current streams."),
   1613  ITEM("orconn-status", events, "A list of current OR connections."),
   1614  ITEM("dormant", misc,
   1615       "Is Tor dormant (not building circuits because it's idle)?"),
   1616  PREFIX("address-mappings/", events, NULL),
   1617  DOC("address-mappings/all", "Current address mappings."),
   1618  DOC("address-mappings/cache", "Current cached DNS replies."),
   1619  DOC("address-mappings/config",
   1620      "Current address mappings from configuration."),
   1621  DOC("address-mappings/control", "Current address mappings from controller."),
   1622  PREFIX("status/", events, NULL),
   1623  DOC("status/circuit-established",
   1624      "Whether we think client functionality is working."),
   1625  DOC("status/enough-dir-info",
   1626      "Whether we have enough up-to-date directory information to build "
   1627      "circuits."),
   1628  DOC("status/bootstrap-phase",
   1629      "The last bootstrap phase status event that Tor sent."),
   1630  DOC("status/clients-seen",
   1631      "Breakdown of client countries seen by a bridge."),
   1632  DOC("status/fresh-relay-descs",
   1633      "A fresh relay/ei descriptor pair for Tor's current state. Not stored."),
   1634  DOC("status/version/recommended", "List of currently recommended versions."),
   1635  DOC("status/version/current", "Status of the current version."),
   1636  ITEM("address", misc, "IP address of this Tor host, if we can guess it."),
   1637  ITEM("address/v4", misc,
   1638       "IPv4 address of this Tor host, if we can guess it."),
   1639  ITEM("address/v6", misc,
   1640       "IPv6 address of this Tor host, if we can guess it."),
   1641  ITEM("traffic/read", misc,"Bytes read since the process was started."),
   1642  ITEM("traffic/written", misc,
   1643       "Bytes written since the process was started."),
   1644  ITEM("uptime", misc, "Uptime of the Tor daemon in seconds."),
   1645  ITEM("process/pid", misc, "Process id belonging to the main tor process."),
   1646  ITEM("process/uid", misc, "User id running the tor process."),
   1647  ITEM("process/user", misc,
   1648       "Username under which the tor process is running."),
   1649  ITEM("process/descriptor-limit", misc, "File descriptor limit."),
   1650  ITEM("limits/max-mem-in-queues", misc, "Actual limit on memory in queues"),
   1651  PREFIX("desc-annotations/id/", dir, "Router annotations by hexdigest."),
   1652  PREFIX("dir/server/", dir,"Router descriptors as retrieved from a DirPort."),
   1653  PREFIX("dir/status/", dir,
   1654         "v2 networkstatus docs as retrieved from a DirPort."),
   1655  ITEM("dir/status-vote/current/consensus", dir,
   1656       "v3 Networkstatus consensus as retrieved from a DirPort."),
   1657  ITEM("dir/status-vote/current/consensus-microdesc", dir,
   1658       "v3 Microdescriptor consensus as retrieved from a DirPort."),
   1659  ITEM("exit-policy/default", policies,
   1660       "The default value appended to the configured exit policy."),
   1661  ITEM("exit-policy/reject-private/default", policies,
   1662       "The default rules appended to the configured exit policy by"
   1663       " ExitPolicyRejectPrivate."),
   1664  ITEM("exit-policy/reject-private/relay", policies,
   1665       "The relay-specific rules appended to the configured exit policy by"
   1666       " ExitPolicyRejectPrivate and/or ExitPolicyRejectLocalInterfaces."),
   1667  ITEM("exit-policy/full", policies, "The entire exit policy of onion router"),
   1668  ITEM("exit-policy/ipv4", policies, "IPv4 parts of exit policy"),
   1669  ITEM("exit-policy/ipv6", policies, "IPv6 parts of exit policy"),
   1670  PREFIX("ip-to-country/", geoip, "Perform a GEOIP lookup"),
   1671  ITEM("onions/current", onions,
   1672       "Onion services owned by the current control connection."),
   1673  ITEM("onions/detached", onions,
   1674       "Onion services detached from the control connection."),
   1675  ITEM("sr/current", sr, "Get current shared random value."),
   1676  ITEM("sr/previous", sr, "Get previous shared random value."),
   1677  PREFIX("stats/ntor/", rephist, "NTor circuit handshake stats."),
   1678  ITEM("stats/ntor/assigned", rephist,
   1679       "Assigned NTor circuit handshake stats."),
   1680  ITEM("stats/ntor/requested", rephist,
   1681       "Requested NTor circuit handshake stats."),
   1682  PREFIX("stats/tap/", rephist, "TAP circuit handshake stats."),
   1683  ITEM("stats/tap/assigned", rephist,
   1684       "Assigned TAP circuit handshake stats."),
   1685  ITEM("stats/tap/requested", rephist,
   1686       "Requested TAP circuit handshake stats."),
   1687  { NULL, NULL, NULL, 0 }
   1688 };
   1689 
   1690 /** Allocate and return a list of recognized GETINFO options. */
   1691 static char *
   1692 list_getinfo_options(void)
   1693 {
   1694  int i;
   1695  smartlist_t *lines = smartlist_new();
   1696  char *ans;
   1697  for (i = 0; getinfo_items[i].varname; ++i) {
   1698    if (!getinfo_items[i].desc)
   1699      continue;
   1700 
   1701    smartlist_add_asprintf(lines, "%s%s -- %s\n",
   1702                 getinfo_items[i].varname,
   1703                 getinfo_items[i].is_prefix ? "*" : "",
   1704                 getinfo_items[i].desc);
   1705  }
   1706  smartlist_sort_strings(lines);
   1707 
   1708  ans = smartlist_join_strings(lines, "", 0, NULL);
   1709  SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
   1710  smartlist_free(lines);
   1711 
   1712  return ans;
   1713 }
   1714 
   1715 /** Lookup the 'getinfo' entry <b>question</b>, and return
   1716 * the answer in <b>*answer</b> (or NULL if key not recognized).
   1717 * Return 0 if success or unrecognized, or -1 if recognized but
   1718 * internal error. */
   1719 static int
   1720 handle_getinfo_helper(control_connection_t *control_conn,
   1721                      const char *question, char **answer,
   1722                      const char **err_out)
   1723 {
   1724  int i;
   1725  *answer = NULL; /* unrecognized key by default */
   1726 
   1727  for (i = 0; getinfo_items[i].varname; ++i) {
   1728    int match;
   1729    if (getinfo_items[i].is_prefix)
   1730      match = !strcmpstart(question, getinfo_items[i].varname);
   1731    else
   1732      match = !strcmp(question, getinfo_items[i].varname);
   1733    if (match) {
   1734      tor_assert(getinfo_items[i].fn);
   1735      return getinfo_items[i].fn(control_conn, question, answer, err_out);
   1736    }
   1737  }
   1738 
   1739  return 0; /* unrecognized */
   1740 }
   1741 
   1742 const control_cmd_syntax_t getinfo_syntax = {
   1743  .max_args = UINT_MAX,
   1744 };
   1745 
   1746 /** Called when we receive a GETINFO command.  Try to fetch all requested
   1747 * information, and reply with information or error message. */
   1748 int
   1749 handle_control_getinfo(control_connection_t *conn,
   1750                       const control_cmd_args_t *args)
   1751 {
   1752  const smartlist_t *questions = args->args;
   1753  smartlist_t *answers = smartlist_new();
   1754  smartlist_t *unrecognized = smartlist_new();
   1755  char *ans = NULL;
   1756 
   1757  SMARTLIST_FOREACH_BEGIN(questions, const char *, q) {
   1758    const char *errmsg = NULL;
   1759 
   1760    if (handle_getinfo_helper(conn, q, &ans, &errmsg) < 0) {
   1761      if (!errmsg)
   1762        errmsg = "Internal error";
   1763      control_write_endreply(conn, 551, errmsg);
   1764      goto done;
   1765    }
   1766    if (!ans) {
   1767      if (errmsg) {
   1768        /* use provided error message */
   1769        control_reply_add_str(unrecognized, 552, errmsg);
   1770      } else {
   1771        /* use default error message */
   1772        control_reply_add_printf(unrecognized, 552,
   1773                                 "Unrecognized key \"%s\"", q);
   1774      }
   1775    } else {
   1776      control_reply_add_one_kv(answers, 250, KV_RAW, q, ans);
   1777      tor_free(ans);
   1778    }
   1779  } SMARTLIST_FOREACH_END(q);
   1780 
   1781  control_reply_add_done(answers);
   1782 
   1783  if (smartlist_len(unrecognized)) {
   1784    control_write_reply_lines(conn, unrecognized);
   1785    /* If there were any unrecognized queries, don't write real answers */
   1786    goto done;
   1787  }
   1788 
   1789  control_write_reply_lines(conn, answers);
   1790 
   1791 done:
   1792  control_reply_free(answers);
   1793  control_reply_free(unrecognized);
   1794 
   1795  return 0;
   1796 }