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