1 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
2 * Copyright (c) 2007-2021, The Tor Project, Inc. */
3 /* See LICENSE for licensing information */
6 * \file control_getinfo.c
7 * \brief Implementation for miscellaneous controller getinfo commands.
10 #define CONTROL_EVENTS_PRIVATE
11 #define CONTROL_MODULE_PRIVATE
12 #define CONTROL_GETINFO_PRIVATE
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"
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"
78 static char *list_getinfo_options(void);
79 static char *download_status_to_string(const download_status_t
*dl
);
81 /** Implementation helper for GETINFO: knows the answers for various
82 * trivial-to-implement questions. */
84 getinfo_helper_misc(control_connection_t
*conn
, const char *question
,
85 char **answer
, const char **errmsg
)
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);
95 *answer
= tor_strdup(a
);
96 } else if (!strcmp(question
, "config-defaults-file")) {
97 const char *a
= get_torrc_fname(1);
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")) {
111 smartlist_t
*event_names
= smartlist_new();
113 for (i
= 0; control_event_table
[i
].event_name
!= NULL
; ++i
) {
114 smartlist_add(event_names
, (char *)control_event_table
[i
].event_name
);
117 *answer
= smartlist_join_strings(event_names
, " ", 0, NULL
);
119 smartlist_free(event_names
);
120 } else if (!strcmp(question
, "signal/names")) {
121 smartlist_t
*signal_names
= smartlist_new();
123 for (j
= 0; signal_table
[j
].signal_name
!= NULL
; ++j
) {
124 smartlist_add(signal_names
, (char*)signal_table
[j
].signal_name
);
127 *answer
= smartlist_join_strings(signal_names
, " ", 0, NULL
);
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")) {
134 if (!relay_find_addr_to_publish(get_options(), AF_INET
,
135 RELAY_FIND_ADDR_CACHE_ONLY
, &addr
)) {
136 *errmsg
= "Address unknown";
139 *answer
= tor_addr_to_str_dup(&addr
);
140 tor_assert_nonfatal(*answer
);
141 } else if (!strcmp(question
, "address/v6")) {
143 if (!relay_find_addr_to_publish(get_options(), AF_INET6
,
144 RELAY_FIND_ADDR_CACHE_ONLY
, &addr
)) {
145 *errmsg
= "Address unknown";
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")) {
166 tor_asprintf(answer
, "%d", myPid
);
167 } else if (!strcmp(question
, "process/uid")) {
169 *answer
= tor_strdup("-1");
171 int myUid
= geteuid();
172 tor_asprintf(answer
, "%d", myUid
);
173 #endif /* defined(_WIN32) */
174 } else if (!strcmp(question
, "process/user")) {
176 *answer
= tor_strdup("");
178 int myUid
= geteuid();
179 const struct passwd
*myPwEntry
= tor_getpwuid(myUid
);
182 *answer
= tor_strdup(myPwEntry
->pw_name
);
184 *answer
= tor_strdup("");
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";
199 server_key
= get_server_identity_key();
200 *answer
= tor_malloc(HEX_DIGEST_LEN
+1);
201 crypto_pk_get_fingerprint(server_key
, *answer
, 0);
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.
211 * New code should never use this; it's for backward compatibility.
213 * NOTE: <b>ri_body</b> is as returned by signed_descriptor_get_body: it might
214 * not be NUL-terminated. */
216 munge_extrainfo_into_routerinfo(const char *ri_body
,
217 const signed_descriptor_t
*ri
,
218 const signed_descriptor_t
*ei
)
220 char *out
= NULL
, *outp
;
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
;
229 outp
= out
= tor_malloc(ri_len
+ei_len
+1);
230 if (!(router_sig
= tor_memstr(ri_body
, ri_len
, "\nrouter-signature")))
233 memcpy(out
, ri_body
, router_sig
-ri_body
);
234 outp
+= router_sig
-ri_body
;
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
)))
242 if (!(eol
= memchr(cp
, '\n', ei_len
- (cp
-ei_body
))))
244 memcpy(outp
, cp
, eol
-cp
+1);
247 memcpy(outp
, router_sig
, ri_len
- (router_sig
-ri_body
));
249 tor_assert(outp
-out
< (int)(ri_len
+ei_len
+1));
254 return tor_strndup(ri_body
, ri
->signed_descriptor_len
);
257 /** Implementation helper for GETINFO: answers requests for information about
258 * which ports are bound. */
260 getinfo_helper_listeners(control_connection_t
*control_conn
,
261 const char *question
,
262 char **answer
, const char **errmsg
)
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
;
291 return 0; /* unknown key */
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
);
298 if (conn
->type
!= type
|| conn
->marked_for_close
|| !SOCKET_OK(conn
->s
))
301 if (getsockname(conn
->s
, (struct sockaddr
*)&ss
, &ss_len
) < 0) {
302 smartlist_add_asprintf(res
, "%s:%d", conn
->address
, (int)conn
->port
);
304 char *tmp
= tor_sockaddr_to_str((struct sockaddr
*)&ss
);
305 smartlist_add(res
, esc_for_log(tmp
));
309 } SMARTLIST_FOREACH_END(conn
);
311 *answer
= smartlist_join_strings(res
, " ", 0, NULL
);
313 SMARTLIST_FOREACH(res
, char *, cp
, tor_free(cp
));
318 /** Implementation helper for GETINFO: answers requests for information about
319 * the current time in both local and UTC forms. */
321 getinfo_helper_current_time(control_connection_t
*control_conn
,
322 const char *question
,
323 char **answer
, const char **errmsg
)
329 tor_gettimeofday(&now
);
330 char timebuf
[ISO_TIME_LEN
+1];
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
);
339 *answer
= tor_strdup(timebuf
);
343 /** GETINFO helper for dumping different consensus flavors
344 * returns: 0 on success -1 on error. */
346 getinfo_helper_current_consensus(consensus_flavor_t flavor
,
350 const char *flavor_name
= networkstatus_get_flavor_name(flavor
);
351 if (BUG(!strcmp(flavor_name
, "??"))) {
352 *errmsg
= "Internal error: unrecognized flavor name.";
355 if (we_want_to_fetch_flavor(get_options(), flavor
)) {
356 /** Check from the cache */
357 const cached_dir_t
*consensus
= dirserv_get_consensus(flavor_name
);
359 *answer
= tor_strdup(consensus
->dir
);
362 if (!*answer
) { /* try loading it from disk */
364 tor_mmap_t
*mapped
= networkstatus_map_cached_consensus(flavor_name
);
366 *answer
= tor_memdup_nulterm(mapped
->data
, mapped
->size
);
367 tor_munmap_file(mapped
);
369 if (!*answer
) { /* generate an error */
370 *errmsg
= "Could not open cached consensus. "
371 "Make sure FetchUselessDescriptors is set to 1.";
378 /** Helper for getinfo_helper_dir.
380 * Add a signed_descriptor_t to <b>descs_out</b> for each router matching
381 * <b>key</b>. The key should be either
382 * - "/tor/server/authority" for our own routerinfo;
383 * - "/tor/server/all" for all the routerinfos we have, concatenated;
384 * - "/tor/server/fp/FP" where FP is a plus-separated sequence of
385 * hex identity digests; or
386 * - "/tor/server/d/D" where D is a plus-separated sequence
387 * of server descriptor digests, in hex.
389 * Return 0 if we found some matching descriptors, or -1 if we do not
390 * have any descriptors, no matching descriptors, or if we did not
391 * recognize the key (URL).
392 * If -1 is returned *<b>msg</b> will be set to an appropriate error
396 controller_get_routerdescs(smartlist_t
*descs_out
, const char *key
,
401 if (!strcmp(key
, "/tor/server/all")) {
402 routerlist_t
*rl
= router_get_routerlist();
403 SMARTLIST_FOREACH(rl
->routers
, routerinfo_t
*, r
,
404 smartlist_add(descs_out
, &(r
->cache_info
)));
405 } else if (!strcmp(key
, "/tor/server/authority")) {
406 const routerinfo_t
*ri
= router_get_my_routerinfo();
408 smartlist_add(descs_out
, (void*) &(ri
->cache_info
));
409 } else if (!strcmpstart(key
, "/tor/server/d/")) {
410 smartlist_t
*digests
= smartlist_new();
411 key
+= strlen("/tor/server/d/");
412 dir_split_resource_into_fingerprints(key
, digests
, NULL
,
413 DSR_HEX
|DSR_SORT_UNIQ
);
414 SMARTLIST_FOREACH(digests
, const char *, d
,
416 signed_descriptor_t
*sd
= router_get_by_descriptor_digest(d
);
418 smartlist_add(descs_out
,sd
);
420 SMARTLIST_FOREACH(digests
, char *, d
, tor_free(d
));
421 smartlist_free(digests
);
422 } else if (!strcmpstart(key
, "/tor/server/fp/")) {
423 smartlist_t
*digests
= smartlist_new();
424 time_t cutoff
= time(NULL
) - ROUTER_MAX_AGE_TO_PUBLISH
;
425 key
+= strlen("/tor/server/fp/");
426 dir_split_resource_into_fingerprints(key
, digests
, NULL
,
427 DSR_HEX
|DSR_SORT_UNIQ
);
428 SMARTLIST_FOREACH_BEGIN(digests
, const char *, d
) {
429 if (router_digest_is_me(d
)) {
430 /* calling router_get_my_routerinfo() to make sure it exists */
431 const routerinfo_t
*ri
= router_get_my_routerinfo();
433 smartlist_add(descs_out
, (void*) &(ri
->cache_info
));
435 const routerinfo_t
*ri
= router_get_by_id_digest(d
);
436 /* Don't actually serve a descriptor that everyone will think is
437 * expired. This is an (ugly) workaround to keep buggy 0.1.1.10
438 * Tors from downloading descriptors that they will throw away.
440 if (ri
&& ri
->cache_info
.published_on
> cutoff
)
441 smartlist_add(descs_out
, (void*) &(ri
->cache_info
));
443 } SMARTLIST_FOREACH_END(d
);
444 SMARTLIST_FOREACH(digests
, char *, d
, tor_free(d
));
445 smartlist_free(digests
);
447 *msg
= "Key not recognized";
451 if (!smartlist_len(descs_out
)) {
452 *msg
= "Servers unavailable";
458 /** Implementation helper for GETINFO: knows the answers for questions about
459 * directory information. */
461 getinfo_helper_dir(control_connection_t
*control_conn
,
462 const char *question
, char **answer
,
466 if (!strcmpstart(question
, "desc/id/")) {
467 const routerinfo_t
*ri
= NULL
;
468 const node_t
*node
= node_get_by_hex_id(question
+strlen("desc/id/"), 0);
472 const char *body
= signed_descriptor_get_body(&ri
->cache_info
);
474 *answer
= tor_strndup(body
, ri
->cache_info
.signed_descriptor_len
);
475 } else if (! we_fetch_router_descriptors(get_options())) {
476 /* Descriptors won't be available, provide proper error */
477 *errmsg
= "We fetch microdescriptors, not router "
478 "descriptors. You'll need to use md/id/* "
479 "instead of desc/id/*.";
482 } else if (!strcmpstart(question
, "desc/name/")) {
483 const routerinfo_t
*ri
= NULL
;
484 /* XXX Setting 'warn_if_unnamed' here is a bit silly -- the
485 * warning goes to the user, not to the controller. */
487 node_get_by_nickname(question
+strlen("desc/name/"), 0);
491 const char *body
= signed_descriptor_get_body(&ri
->cache_info
);
493 *answer
= tor_strndup(body
, ri
->cache_info
.signed_descriptor_len
);
494 } else if (! we_fetch_router_descriptors(get_options())) {
495 /* Descriptors won't be available, provide proper error */
496 *errmsg
= "We fetch microdescriptors, not router "
497 "descriptors. You'll need to use md/name/* "
498 "instead of desc/name/*.";
501 } else if (!strcmp(question
, "desc/download-enabled")) {
502 int r
= we_fetch_router_descriptors(get_options());
503 tor_asprintf(answer
, "%d", !!r
);
504 } else if (!strcmp(question
, "desc/all-recent")) {
505 routerlist_t
*routerlist
= router_get_routerlist();
506 smartlist_t
*sl
= smartlist_new();
507 if (routerlist
&& routerlist
->routers
) {
508 SMARTLIST_FOREACH(routerlist
->routers
, const routerinfo_t
*, ri
,
510 const char *body
= signed_descriptor_get_body(&ri
->cache_info
);
513 tor_strndup(body
, ri
->cache_info
.signed_descriptor_len
));
516 *answer
= smartlist_join_strings(sl
, "", 0, NULL
);
517 SMARTLIST_FOREACH(sl
, char *, c
, tor_free(c
));
519 } else if (!strcmp(question
, "desc/all-recent-extrainfo-hack")) {
520 /* XXXX Remove this once Torstat asks for extrainfos. */
521 routerlist_t
*routerlist
= router_get_routerlist();
522 smartlist_t
*sl
= smartlist_new();
523 if (routerlist
&& routerlist
->routers
) {
524 SMARTLIST_FOREACH_BEGIN(routerlist
->routers
, const routerinfo_t
*, ri
) {
525 const char *body
= signed_descriptor_get_body(&ri
->cache_info
);
526 signed_descriptor_t
*ei
= extrainfo_get_by_descriptor_digest(
527 ri
->cache_info
.extra_info_digest
);
529 smartlist_add(sl
, munge_extrainfo_into_routerinfo(body
,
530 &ri
->cache_info
, ei
));
533 tor_strndup(body
, ri
->cache_info
.signed_descriptor_len
));
535 } SMARTLIST_FOREACH_END(ri
);
537 *answer
= smartlist_join_strings(sl
, "", 0, NULL
);
538 SMARTLIST_FOREACH(sl
, char *, c
, tor_free(c
));
540 } else if (!strcmpstart(question
, "hs/client/desc/id/")) {
541 hostname_type_t addr_type
;
543 question
+= strlen("hs/client/desc/id/");
544 if (hs_address_is_valid(question
)) {
545 addr_type
= ONION_V3_HOSTNAME
;
547 *errmsg
= "Invalid address";
551 if (addr_type
== ONION_V3_HOSTNAME
) {
552 ed25519_public_key_t service_pk
;
555 /* The check before this if/else makes sure of this. */
556 tor_assert(addr_type
== ONION_V3_HOSTNAME
);
558 if (hs_parse_address(question
, &service_pk
, NULL
, NULL
) < 0) {
559 *errmsg
= "Invalid v3 address";
563 desc
= hs_cache_lookup_encoded_as_client(&service_pk
);
565 *answer
= tor_strdup(desc
);
567 *errmsg
= "Not found in cache";
571 } else if (!strcmpstart(question
, "hs/service/desc/id/")) {
572 hostname_type_t addr_type
;
574 question
+= strlen("hs/service/desc/id/");
575 if (hs_address_is_valid(question
)) {
576 addr_type
= ONION_V3_HOSTNAME
;
578 *errmsg
= "Invalid address";
582 if (addr_type
== ONION_V3_HOSTNAME
) {
583 ed25519_public_key_t service_pk
;
586 /* The check before this if/else makes sure of this. */
587 tor_assert(addr_type
== ONION_V3_HOSTNAME
);
589 if (hs_parse_address(question
, &service_pk
, NULL
, NULL
) < 0) {
590 *errmsg
= "Invalid v3 address";
594 desc
= hs_service_lookup_current_desc(&service_pk
);
596 /* Newly allocated string, we have ownership. */
599 *errmsg
= "Not found in cache";
603 } else if (!strcmp(question
, "md/all")) {
604 const smartlist_t
*nodes
= nodelist_get_list();
607 if (smartlist_len(nodes
) == 0) {
608 *answer
= tor_strdup("");
612 smartlist_t
*microdescs
= smartlist_new();
614 SMARTLIST_FOREACH_BEGIN(nodes
, node_t
*, n
) {
615 if (n
->md
&& n
->md
->body
) {
616 char *copy
= tor_strndup(n
->md
->body
, n
->md
->bodylen
);
617 smartlist_add(microdescs
, copy
);
619 } SMARTLIST_FOREACH_END(n
);
621 *answer
= smartlist_join_strings(microdescs
, "", 0, NULL
);
622 SMARTLIST_FOREACH(microdescs
, char *, md
, tor_free(md
));
623 smartlist_free(microdescs
);
624 } else if (!strcmpstart(question
, "md/id/")) {
625 const node_t
*node
= node_get_by_hex_id(question
+strlen("md/id/"), 0);
626 const microdesc_t
*md
= NULL
;
627 if (node
) md
= node
->md
;
628 if (md
&& md
->body
) {
629 *answer
= tor_strndup(md
->body
, md
->bodylen
);
631 } else if (!strcmpstart(question
, "md/name/")) {
632 /* XXX Setting 'warn_if_unnamed' here is a bit silly -- the
633 * warning goes to the user, not to the controller. */
634 const node_t
*node
= node_get_by_nickname(question
+strlen("md/name/"), 0);
635 /* XXXX duplicated code */
636 const microdesc_t
*md
= NULL
;
637 if (node
) md
= node
->md
;
638 if (md
&& md
->body
) {
639 *answer
= tor_strndup(md
->body
, md
->bodylen
);
641 } else if (!strcmp(question
, "md/download-enabled")) {
642 int r
= we_fetch_microdescriptors(get_options());
643 tor_asprintf(answer
, "%d", !!r
);
644 } else if (!strcmpstart(question
, "desc-annotations/id/")) {
645 const routerinfo_t
*ri
= NULL
;
647 node_get_by_hex_id(question
+strlen("desc-annotations/id/"), 0);
651 const char *annotations
=
652 signed_descriptor_get_annotations(&ri
->cache_info
);
654 *answer
= tor_strndup(annotations
,
655 ri
->cache_info
.annotations_len
);
657 } else if (!strcmpstart(question
, "dir/server/")) {
658 size_t answer_len
= 0;
660 smartlist_t
*descs
= smartlist_new();
664 tor_asprintf(&url
, "/tor/%s", question
+4);
665 res
= controller_get_routerdescs(descs
, url
, &msg
);
667 log_warn(LD_CONTROL
, "getinfo '%s': %s", question
, msg
);
668 smartlist_free(descs
);
673 SMARTLIST_FOREACH(descs
, signed_descriptor_t
*, sd
,
674 answer_len
+= sd
->signed_descriptor_len
);
675 cp
= *answer
= tor_malloc(answer_len
+1);
676 SMARTLIST_FOREACH(descs
, signed_descriptor_t
*, sd
,
678 memcpy(cp
, signed_descriptor_get_body(sd
),
679 sd
->signed_descriptor_len
);
680 cp
+= sd
->signed_descriptor_len
;
684 smartlist_free(descs
);
685 } else if (!strcmpstart(question
, "dir/status/")) {
686 *answer
= tor_strdup("");
687 } else if (!strcmp(question
, "dir/status-vote/current/consensus")) {
688 int consensus_result
= getinfo_helper_current_consensus(FLAV_NS
,
690 if (consensus_result
< 0) {
693 } else if (!strcmp(question
,
694 "dir/status-vote/current/consensus-microdesc")) {
695 int consensus_result
= getinfo_helper_current_consensus(FLAV_MICRODESC
,
697 if (consensus_result
< 0) {
700 } else if (!strcmpstart(question
, "extra-info/digest/")) {
701 question
+= strlen("extra-info/digest/");
702 if (strlen(question
) == HEX_DIGEST_LEN
) {
704 signed_descriptor_t
*sd
= NULL
;
705 if (base16_decode(d
, sizeof(d
), question
, strlen(question
))
707 /* XXXX this test should move into extrainfo_get_by_descriptor_digest,
708 * but I don't want to risk affecting other parts of the code,
709 * especially since the rules for using our own extrainfo (including
710 * when it might be freed) are different from those for using one
711 * we have downloaded. */
712 if (router_extrainfo_digest_is_me(d
))
713 sd
= &(router_get_my_extrainfo()->cache_info
);
715 sd
= extrainfo_get_by_descriptor_digest(d
);
718 const char *body
= signed_descriptor_get_body(sd
);
720 *answer
= tor_strndup(body
, sd
->signed_descriptor_len
);
728 /** Given a smartlist of 20-byte digests, return a newly allocated string
729 * containing each of those digests in order, formatted in HEX, and terminated
732 digest_list_to_string(const smartlist_t
*sl
)
737 /* Allow for newlines, and a \0 at the end */
738 len
= smartlist_len(sl
) * (HEX_DIGEST_LEN
+ 1) + 1;
739 result
= tor_malloc_zero(len
);
742 SMARTLIST_FOREACH_BEGIN(sl
, const char *, digest
) {
743 base16_encode(s
, HEX_DIGEST_LEN
+ 1, digest
, DIGEST_LEN
);
744 s
[HEX_DIGEST_LEN
] = '\n';
745 s
+= HEX_DIGEST_LEN
+ 1;
746 } SMARTLIST_FOREACH_END(digest
);
752 /** Turn a download_status_t into a human-readable description in a newly
753 * allocated string. The format is specified in control-spec.txt, under
754 * the documentation for "GETINFO download/..." . */
756 download_status_to_string(const download_status_t
*dl
)
759 char tbuf
[ISO_TIME_LEN
+1];
760 const char *schedule_str
, *want_authority_str
;
761 const char *increment_on_str
, *backoff_str
;
764 /* Get some substrings of the eventual output ready */
765 format_iso_time(tbuf
, download_status_get_next_attempt_at(dl
));
767 switch (dl
->schedule
) {
768 case DL_SCHED_GENERIC
:
769 schedule_str
= "DL_SCHED_GENERIC";
771 case DL_SCHED_CONSENSUS
:
772 schedule_str
= "DL_SCHED_CONSENSUS";
774 case DL_SCHED_BRIDGE
:
775 schedule_str
= "DL_SCHED_BRIDGE";
778 schedule_str
= "unknown";
782 switch (dl
->want_authority
) {
783 case DL_WANT_ANY_DIRSERVER
:
784 want_authority_str
= "DL_WANT_ANY_DIRSERVER";
786 case DL_WANT_AUTHORITY
:
787 want_authority_str
= "DL_WANT_AUTHORITY";
790 want_authority_str
= "unknown";
794 switch (dl
->increment_on
) {
795 case DL_SCHED_INCREMENT_FAILURE
:
796 increment_on_str
= "DL_SCHED_INCREMENT_FAILURE";
798 case DL_SCHED_INCREMENT_ATTEMPT
:
799 increment_on_str
= "DL_SCHED_INCREMENT_ATTEMPT";
802 increment_on_str
= "unknown";
806 backoff_str
= "DL_SCHED_RANDOM_EXPONENTIAL";
808 /* Now assemble them */
810 "next-attempt-at %s\n"
811 "n-download-failures %u\n"
812 "n-download-attempts %u\n"
814 "want-authority %s\n"
817 "last-backoff-position %u\n"
818 "last-delay-used %d\n",
820 dl
->n_download_failures
,
821 dl
->n_download_attempts
,
826 dl
->last_backoff_position
,
827 dl
->last_delay_used
);
833 /** Handle the consensus download cases for getinfo_helper_downloads() */
835 getinfo_helper_downloads_networkstatus(const char *flavor
,
836 download_status_t
**dl_to_emit
,
840 * We get the one for the current bootstrapped status by default, or
841 * take an extra /bootstrap or /running suffix
843 if (strcmp(flavor
, "ns") == 0) {
844 *dl_to_emit
= networkstatus_get_dl_status_by_flavor(FLAV_NS
);
845 } else if (strcmp(flavor
, "ns/bootstrap") == 0) {
846 *dl_to_emit
= networkstatus_get_dl_status_by_flavor_bootstrap(FLAV_NS
);
847 } else if (strcmp(flavor
, "ns/running") == 0 ) {
848 *dl_to_emit
= networkstatus_get_dl_status_by_flavor_running(FLAV_NS
);
849 } else if (strcmp(flavor
, "microdesc") == 0) {
850 *dl_to_emit
= networkstatus_get_dl_status_by_flavor(FLAV_MICRODESC
);
851 } else if (strcmp(flavor
, "microdesc/bootstrap") == 0) {
853 networkstatus_get_dl_status_by_flavor_bootstrap(FLAV_MICRODESC
);
854 } else if (strcmp(flavor
, "microdesc/running") == 0) {
856 networkstatus_get_dl_status_by_flavor_running(FLAV_MICRODESC
);
858 *errmsg
= "Unknown flavor";
862 /** Handle the cert download cases for getinfo_helper_downloads() */
864 getinfo_helper_downloads_cert(const char *fp_sk_req
,
865 download_status_t
**dl_to_emit
,
866 smartlist_t
**digest_list
,
870 char id_digest
[DIGEST_LEN
];
871 char sk_digest
[DIGEST_LEN
];
874 * We have to handle four cases; fp_sk_req is the request with
875 * a prefix of "downloads/cert/" snipped off.
877 * Case 1: fp_sk_req = "fps"
878 * - We should emit a digest_list with a list of all the identity
879 * fingerprints that can be queried for certificate download status;
880 * get it by calling list_authority_ids_with_downloads().
882 * Case 2: fp_sk_req = "fp/<fp>" for some fingerprint fp
883 * - We want the default certificate for this identity fingerprint's
884 * download status; this is the download we get from URLs starting
885 * in /fp/ on the directory server. We can get it with
886 * id_only_download_status_for_authority_id().
888 * Case 3: fp_sk_req = "fp/<fp>/sks" for some fingerprint fp
889 * - We want a list of all signing key digests for this identity
890 * fingerprint which can be queried for certificate download status.
891 * Get it with list_sk_digests_for_authority_id().
893 * Case 4: fp_sk_req = "fp/<fp>/<sk>" for some fingerprint fp and
894 * signing key digest sk
895 * - We want the download status for the certificate for this specific
896 * signing key and fingerprint. These correspond to the ones we get
897 * from URLs starting in /fp-sk/ on the directory server. Get it with
898 * list_sk_digests_for_authority_id().
901 if (strcmp(fp_sk_req
, "fps") == 0) {
902 *digest_list
= list_authority_ids_with_downloads();
903 if (!(*digest_list
)) {
904 *errmsg
= "Failed to get list of authority identity digests (!)";
906 } else if (!strcmpstart(fp_sk_req
, "fp/")) {
907 fp_sk_req
+= strlen("fp/");
908 /* Okay, look for another / to tell the fp from fp-sk cases */
909 sk_req
= strchr(fp_sk_req
, '/');
911 /* okay, split it here and try to parse <fp> */
912 if (base16_decode(id_digest
, DIGEST_LEN
,
913 fp_sk_req
, sk_req
- fp_sk_req
) == DIGEST_LEN
) {
914 /* Skip past the '/' */
916 if (strcmp(sk_req
, "sks") == 0) {
917 /* We're asking for the list of signing key fingerprints */
918 *digest_list
= list_sk_digests_for_authority_id(id_digest
);
919 if (!(*digest_list
)) {
920 *errmsg
= "Failed to get list of signing key digests for this "
921 "authority identity digest";
924 /* We've got a signing key digest */
925 if (base16_decode(sk_digest
, DIGEST_LEN
,
926 sk_req
, strlen(sk_req
)) == DIGEST_LEN
) {
928 download_status_for_authority_id_and_sk(id_digest
, sk_digest
);
929 if (!(*dl_to_emit
)) {
930 *errmsg
= "Failed to get download status for this identity/"
931 "signing key digest pair";
934 *errmsg
= "That didn't look like a signing key digest";
938 *errmsg
= "That didn't look like an identity digest";
941 /* We're either in downloads/certs/fp/<fp>, or we can't parse <fp> */
942 if (strlen(fp_sk_req
) == HEX_DIGEST_LEN
) {
943 if (base16_decode(id_digest
, DIGEST_LEN
,
944 fp_sk_req
, strlen(fp_sk_req
)) == DIGEST_LEN
) {
945 *dl_to_emit
= id_only_download_status_for_authority_id(id_digest
);
946 if (!(*dl_to_emit
)) {
947 *errmsg
= "Failed to get download status for this authority "
951 *errmsg
= "That didn't look like a digest";
954 *errmsg
= "That didn't look like a digest";
958 *errmsg
= "Unknown certificate download status query";
962 /** Handle the routerdesc download cases for getinfo_helper_downloads() */
964 getinfo_helper_downloads_desc(const char *desc_req
,
965 download_status_t
**dl_to_emit
,
966 smartlist_t
**digest_list
,
969 char desc_digest
[DIGEST_LEN
];
971 * Two cases to handle here:
973 * Case 1: desc_req = "descs"
974 * - Emit a list of all router descriptor digests, which we get by
975 * calling router_get_descriptor_digests(); this can return NULL
976 * if we have no current ns-flavor consensus.
978 * Case 2: desc_req = <fp>
979 * - Check on the specified fingerprint and emit its download_status_t
980 * using router_get_dl_status_by_descriptor_digest().
983 if (strcmp(desc_req
, "descs") == 0) {
984 *digest_list
= router_get_descriptor_digests();
985 if (!(*digest_list
)) {
986 *errmsg
= "We don't seem to have a networkstatus-flavored consensus";
989 * Microdescs don't use the download_status_t mechanism, so we don't
990 * answer queries about their downloads here; see microdesc.c.
992 } else if (strlen(desc_req
) == HEX_DIGEST_LEN
) {
993 if (base16_decode(desc_digest
, DIGEST_LEN
,
994 desc_req
, strlen(desc_req
)) == DIGEST_LEN
) {
995 /* Okay we got a digest-shaped thing; try asking for it */
996 *dl_to_emit
= router_get_dl_status_by_descriptor_digest(desc_digest
);
997 if (!(*dl_to_emit
)) {
998 *errmsg
= "No such descriptor digest found";
1001 *errmsg
= "That didn't look like a digest";
1004 *errmsg
= "Unknown router descriptor download status query";
1008 /** Handle the bridge download cases for getinfo_helper_downloads() */
1010 getinfo_helper_downloads_bridge(const char *bridge_req
,
1011 download_status_t
**dl_to_emit
,
1012 smartlist_t
**digest_list
,
1013 const char **errmsg
)
1015 char bridge_digest
[DIGEST_LEN
];
1017 * Two cases to handle here:
1019 * Case 1: bridge_req = "bridges"
1020 * - Emit a list of all bridge identity digests, which we get by
1021 * calling list_bridge_identities(); this can return NULL if we are
1022 * not using bridges.
1024 * Case 2: bridge_req = <fp>
1025 * - Check on the specified fingerprint and emit its download_status_t
1026 * using get_bridge_dl_status_by_id().
1029 if (strcmp(bridge_req
, "bridges") == 0) {
1030 *digest_list
= list_bridge_identities();
1031 if (!(*digest_list
)) {
1032 *errmsg
= "We don't seem to be using bridges";
1034 } else if (strlen(bridge_req
) == HEX_DIGEST_LEN
) {
1035 if (base16_decode(bridge_digest
, DIGEST_LEN
,
1036 bridge_req
, strlen(bridge_req
)) == DIGEST_LEN
) {
1037 /* Okay we got a digest-shaped thing; try asking for it */
1038 *dl_to_emit
= get_bridge_dl_status_by_id(bridge_digest
);
1039 if (!(*dl_to_emit
)) {
1040 *errmsg
= "No such bridge identity digest found";
1043 *errmsg
= "That didn't look like a digest";
1046 *errmsg
= "Unknown bridge descriptor download status query";
1050 /** Implementation helper for GETINFO: knows the answers for questions about
1051 * download status information. */
1053 getinfo_helper_downloads(control_connection_t
*control_conn
,
1054 const char *question
, char **answer
,
1055 const char **errmsg
)
1057 download_status_t
*dl_to_emit
= NULL
;
1058 smartlist_t
*digest_list
= NULL
;
1060 /* Assert args are sane */
1061 tor_assert(control_conn
!= NULL
);
1062 tor_assert(question
!= NULL
);
1063 tor_assert(answer
!= NULL
);
1064 tor_assert(errmsg
!= NULL
);
1066 /* We check for this later to see if we should supply a default */
1069 /* Are we after networkstatus downloads? */
1070 if (!strcmpstart(question
, "downloads/networkstatus/")) {
1071 getinfo_helper_downloads_networkstatus(
1072 question
+ strlen("downloads/networkstatus/"),
1073 &dl_to_emit
, errmsg
);
1075 } else if (!strcmpstart(question
, "downloads/cert/")) {
1076 getinfo_helper_downloads_cert(
1077 question
+ strlen("downloads/cert/"),
1078 &dl_to_emit
, &digest_list
, errmsg
);
1079 /* Router descriptors? */
1080 } else if (!strcmpstart(question
, "downloads/desc/")) {
1081 getinfo_helper_downloads_desc(
1082 question
+ strlen("downloads/desc/"),
1083 &dl_to_emit
, &digest_list
, errmsg
);
1084 /* Bridge descriptors? */
1085 } else if (!strcmpstart(question
, "downloads/bridge/")) {
1086 getinfo_helper_downloads_bridge(
1087 question
+ strlen("downloads/bridge/"),
1088 &dl_to_emit
, &digest_list
, errmsg
);
1090 *errmsg
= "Unknown download status query";
1094 *answer
= download_status_to_string(dl_to_emit
);
1097 } else if (digest_list
) {
1098 *answer
= digest_list_to_string(digest_list
);
1099 SMARTLIST_FOREACH(digest_list
, void *, s
, tor_free(s
));
1100 smartlist_free(digest_list
);
1105 *errmsg
= "Unknown error";
1112 /** Implementation helper for GETINFO: knows how to generate summaries of the
1113 * current states of things we send events about. */
1115 getinfo_helper_events(control_connection_t
*control_conn
,
1116 const char *question
, char **answer
,
1117 const char **errmsg
)
1119 const or_options_t
*options
= get_options();
1120 (void) control_conn
;
1121 if (!strcmp(question
, "circuit-status")) {
1122 smartlist_t
*status
= smartlist_new();
1123 SMARTLIST_FOREACH_BEGIN(circuit_get_global_list(), circuit_t
*, circ_
) {
1124 origin_circuit_t
*circ
;
1127 if (! CIRCUIT_IS_ORIGIN(circ_
) || circ_
->marked_for_close
)
1129 circ
= TO_ORIGIN_CIRCUIT(circ_
);
1131 if (circ
->base_
.state
== CIRCUIT_STATE_OPEN
)
1133 else if (circ
->base_
.state
== CIRCUIT_STATE_GUARD_WAIT
)
1134 state
= "GUARD_WAIT";
1135 else if (circ
->cpath
)
1140 circdesc
= circuit_describe_status_for_controller(circ
);
1142 smartlist_add_asprintf(status
, "%lu %s%s%s",
1143 (unsigned long)circ
->global_identifier
,
1144 state
, *circdesc
? " " : "", circdesc
);
1147 SMARTLIST_FOREACH_END(circ_
);
1148 *answer
= smartlist_join_strings(status
, "\r\n", 0, NULL
);
1149 SMARTLIST_FOREACH(status
, char *, cp
, tor_free(cp
));
1150 smartlist_free(status
);
1151 } else if (!strcmp(question
, "stream-status")) {
1152 smartlist_t
*conns
= get_connection_array();
1153 smartlist_t
*status
= smartlist_new();
1155 SMARTLIST_FOREACH_BEGIN(conns
, connection_t
*, base_conn
) {
1157 entry_connection_t
*conn
;
1159 origin_circuit_t
*origin_circ
= NULL
;
1160 if (base_conn
->type
!= CONN_TYPE_AP
||
1161 base_conn
->marked_for_close
||
1162 base_conn
->state
== AP_CONN_STATE_SOCKS_WAIT
||
1163 base_conn
->state
== AP_CONN_STATE_NATD_WAIT
)
1165 conn
= TO_ENTRY_CONN(base_conn
);
1166 switch (base_conn
->state
)
1168 case AP_CONN_STATE_CONTROLLER_WAIT
:
1169 case AP_CONN_STATE_CIRCUIT_WAIT
:
1170 if (conn
->socks_request
&&
1171 SOCKS_COMMAND_IS_RESOLVE(conn
->socks_request
->command
))
1172 state
= "NEWRESOLVE";
1176 case AP_CONN_STATE_RENDDESC_WAIT
:
1177 case AP_CONN_STATE_CONNECT_WAIT
:
1178 state
= "SENTCONNECT"; break;
1179 case AP_CONN_STATE_RESOLVE_WAIT
:
1180 state
= "SENTRESOLVE"; break;
1181 case AP_CONN_STATE_OPEN
:
1182 state
= "SUCCEEDED"; break;
1184 log_warn(LD_BUG
, "Asked for stream in unknown state %d",
1188 circ
= circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn
));
1189 if (circ
&& CIRCUIT_IS_ORIGIN(circ
))
1190 origin_circ
= TO_ORIGIN_CIRCUIT(circ
);
1191 write_stream_target_to_buf(conn
, buf
, sizeof(buf
));
1192 smartlist_add_asprintf(status
, "%lu %s %lu %s",
1193 (unsigned long) base_conn
->global_identifier
,state
,
1195 (unsigned long)origin_circ
->global_identifier
: 0ul,
1197 } SMARTLIST_FOREACH_END(base_conn
);
1198 *answer
= smartlist_join_strings(status
, "\r\n", 0, NULL
);
1199 SMARTLIST_FOREACH(status
, char *, cp
, tor_free(cp
));
1200 smartlist_free(status
);
1201 } else if (!strcmp(question
, "orconn-status")) {
1202 smartlist_t
*conns
= get_connection_array();
1203 smartlist_t
*status
= smartlist_new();
1204 SMARTLIST_FOREACH_BEGIN(conns
, connection_t
*, base_conn
) {
1207 or_connection_t
*conn
;
1208 if (base_conn
->type
!= CONN_TYPE_OR
|| base_conn
->marked_for_close
)
1210 conn
= TO_OR_CONN(base_conn
);
1211 if (conn
->base_
.state
== OR_CONN_STATE_OPEN
)
1212 state
= "CONNECTED";
1213 else if (conn
->nickname
)
1217 orconn_target_get_name(name
, sizeof(name
), conn
);
1218 smartlist_add_asprintf(status
, "%s %s", name
, state
);
1219 } SMARTLIST_FOREACH_END(base_conn
);
1220 *answer
= smartlist_join_strings(status
, "\r\n", 0, NULL
);
1221 SMARTLIST_FOREACH(status
, char *, cp
, tor_free(cp
));
1222 smartlist_free(status
);
1223 } else if (!strcmpstart(question
, "address-mappings/")) {
1224 time_t min_e
, max_e
;
1225 smartlist_t
*mappings
;
1226 question
+= strlen("address-mappings/");
1227 if (!strcmp(question
, "all")) {
1228 min_e
= 0; max_e
= TIME_MAX
;
1229 } else if (!strcmp(question
, "cache")) {
1230 min_e
= 2; max_e
= TIME_MAX
;
1231 } else if (!strcmp(question
, "config")) {
1232 min_e
= 0; max_e
= 0;
1233 } else if (!strcmp(question
, "control")) {
1234 min_e
= 1; max_e
= 1;
1238 mappings
= smartlist_new();
1239 addressmap_get_mappings(mappings
, min_e
, max_e
, 1);
1240 *answer
= smartlist_join_strings(mappings
, "\r\n", 0, NULL
);
1241 SMARTLIST_FOREACH(mappings
, char *, cp
, tor_free(cp
));
1242 smartlist_free(mappings
);
1243 } else if (!strcmpstart(question
, "status/")) {
1244 /* Note that status/ is not a catch-all for events; there's only supposed
1245 * to be a status GETINFO if there's a corresponding STATUS event. */
1246 if (!strcmp(question
, "status/circuit-established")) {
1247 *answer
= tor_strdup(have_completed_a_circuit() ? "1" : "0");
1248 } else if (!strcmp(question
, "status/enough-dir-info")) {
1249 *answer
= tor_strdup(router_have_minimum_dir_info() ? "1" : "0");
1250 } else if (!strcmp(question
, "status/good-server-descriptor") ||
1251 !strcmp(question
, "status/accepted-server-descriptor")) {
1252 /* They're equivalent for now, until we can figure out how to make
1253 * good-server-descriptor be what we want. See comment in
1254 * control-spec.txt. */
1255 *answer
= tor_strdup(directories_have_accepted_server_descriptor()
1257 } else if (!strcmp(question
, "status/reachability-succeeded/or")) {
1258 *answer
= tor_strdup(
1259 router_all_orports_seem_reachable(options
) ?
1261 } else if (!strcmp(question
, "status/reachability-succeeded/dir")) {
1262 *answer
= tor_strdup(
1263 router_dirport_seems_reachable(options
) ?
1265 } else if (!strcmp(question
, "status/reachability-succeeded")) {
1267 answer
, "OR=%d DIR=%d",
1268 router_all_orports_seem_reachable(options
) ? 1 : 0,
1269 router_dirport_seems_reachable(options
) ? 1 : 0);
1270 } else if (!strcmp(question
, "status/bootstrap-phase")) {
1271 *answer
= control_event_boot_last_msg();
1272 } else if (!strcmpstart(question
, "status/version/")) {
1273 int is_server
= server_mode(options
);
1274 networkstatus_t
*c
= networkstatus_get_latest_consensus();
1275 version_status_t status
;
1276 const char *recommended
;
1278 recommended
= is_server
? c
->server_versions
: c
->client_versions
;
1279 status
= tor_version_is_obsolete(VERSION
, recommended
);
1282 status
= VS_UNKNOWN
;
1285 if (!strcmp(question
, "status/version/recommended")) {
1286 *answer
= tor_strdup(recommended
);
1289 if (!strcmp(question
, "status/version/current")) {
1292 case VS_RECOMMENDED
: *answer
= tor_strdup("recommended"); break;
1293 case VS_OLD
: *answer
= tor_strdup("obsolete"); break;
1294 case VS_NEW
: *answer
= tor_strdup("new"); break;
1295 case VS_NEW_IN_SERIES
: *answer
= tor_strdup("new in series"); break;
1296 case VS_UNRECOMMENDED
: *answer
= tor_strdup("unrecommended"); break;
1297 case VS_EMPTY
: *answer
= tor_strdup("none recommended"); break;
1298 case VS_UNKNOWN
: *answer
= tor_strdup("unknown"); break;
1299 default: tor_fragile_assert();
1302 } else if (!strcmp(question
, "status/clients-seen")) {
1303 char *bridge_stats
= geoip_get_bridge_stats_controller(time(NULL
));
1304 if (!bridge_stats
) {
1305 *errmsg
= "No bridge-client stats available";
1308 *answer
= bridge_stats
;
1309 } else if (!strcmp(question
, "status/fresh-relay-descs")) {
1310 if (!server_mode(options
)) {
1311 *errmsg
= "Only relays have descriptors";
1317 if ((result
= router_build_fresh_descriptor(&r
, &e
)) < 0) {
1319 case TOR_ROUTERINFO_ERROR_NO_EXT_ADDR
:
1320 *errmsg
= "Cannot get relay address while generating descriptor";
1322 case TOR_ROUTERINFO_ERROR_DIGEST_FAILED
:
1323 *errmsg
= "Key digest failed";
1325 case TOR_ROUTERINFO_ERROR_CANNOT_GENERATE
:
1326 *errmsg
= "Cannot generate router descriptor";
1329 *errmsg
= "Error generating descriptor";
1334 size_t size
= r
->cache_info
.signed_descriptor_len
+ 1;
1336 size
+= e
->cache_info
.signed_descriptor_len
+ 1;
1338 tor_assert(r
->cache_info
.signed_descriptor_len
);
1339 char *descs
= tor_malloc(size
);
1341 memcpy(cp
, signed_descriptor_get_body(&r
->cache_info
),
1342 r
->cache_info
.signed_descriptor_len
);
1343 cp
+= r
->cache_info
.signed_descriptor_len
- 1;
1345 if (cp
[0] == '\0') {
1347 } else if (cp
[0] != '\n') {
1351 memcpy(cp
, signed_descriptor_get_body(&e
->cache_info
),
1352 e
->cache_info
.signed_descriptor_len
);
1353 cp
+= e
->cache_info
.signed_descriptor_len
- 1;
1355 if (cp
[0] == '\n') {
1357 } else if (cp
[0] != '\0') {
1370 /** Implementation helper for GETINFO: knows how to enumerate hidden services
1371 * created via the control port. */
1373 getinfo_helper_onions(control_connection_t
*control_conn
,
1374 const char *question
, char **answer
,
1375 const char **errmsg
)
1377 smartlist_t
*onion_list
= NULL
;
1378 (void) errmsg
; /* no errors from this method */
1380 if (control_conn
&& !strcmp(question
, "onions/current")) {
1381 onion_list
= control_conn
->ephemeral_onion_services
;
1382 } else if (!strcmp(question
, "onions/detached")) {
1383 onion_list
= get_detached_onion_services();
1387 if (!onion_list
|| smartlist_len(onion_list
) == 0) {
1389 *answer
= tor_strdup("");
1393 *answer
= smartlist_join_strings(onion_list
, "\r\n", 0, NULL
);
1400 /** Implementation helper for GETINFO: answers queries about network
1403 getinfo_helper_liveness(control_connection_t
*control_conn
,
1404 const char *question
, char **answer
,
1405 const char **errmsg
)
1409 if (strcmp(question
, "network-liveness") == 0) {
1410 if (get_cached_network_liveness()) {
1411 *answer
= tor_strdup("up");
1413 *answer
= tor_strdup("down");
1420 /** Implementation helper for GETINFO: answers queries about circuit onion
1421 * handshake rephist values */
1423 getinfo_helper_rephist(control_connection_t
*control_conn
,
1424 const char *question
, char **answer
,
1425 const char **errmsg
)
1427 (void) control_conn
;
1431 if (!strcmp(question
, "stats/ntor/assigned")) {
1433 rep_hist_get_circuit_handshake_assigned(ONION_HANDSHAKE_TYPE_NTOR
);
1434 } else if (!strcmp(question
, "stats/ntor/requested")) {
1436 rep_hist_get_circuit_handshake_requested(ONION_HANDSHAKE_TYPE_NTOR
);
1437 } else if (!strcmp(question
, "stats/tap/assigned")) {
1439 rep_hist_get_circuit_handshake_assigned(ONION_HANDSHAKE_TYPE_TAP
);
1440 } else if (!strcmp(question
, "stats/tap/requested")) {
1442 rep_hist_get_circuit_handshake_requested(ONION_HANDSHAKE_TYPE_TAP
);
1444 *errmsg
= "Unrecognized handshake type";
1448 tor_asprintf(answer
, "%d", result
);
1453 /** Implementation helper for GETINFO: answers queries about shared random
1456 getinfo_helper_sr(control_connection_t
*control_conn
,
1457 const char *question
, char **answer
,
1458 const char **errmsg
)
1460 (void) control_conn
;
1463 if (!strcmp(question
, "sr/current")) {
1464 *answer
= sr_get_current_for_control();
1465 } else if (!strcmp(question
, "sr/previous")) {
1466 *answer
= sr_get_previous_for_control();
1468 /* Else statement here is unrecognized key so do nothing. */
1473 /** Callback function for GETINFO: on a given control connection, try to
1474 * answer the question <b>q</b> and store the newly-allocated answer in
1475 * *<b>a</b>. If an internal error occurs, return -1 and optionally set
1476 * *<b>error_out</b> to point to an error message to be delivered to the
1477 * controller. On success, _or if the key is not recognized_, return 0. Do not
1478 * set <b>a</b> if the key is not recognized but you may set <b>error_out</b>
1479 * to improve the error message.
1481 typedef int (*getinfo_helper_t
)(control_connection_t
*,
1482 const char *q
, char **a
,
1483 const char **error_out
);
1485 /** A single item for the GETINFO question-to-answer-function table. */
1486 typedef struct getinfo_item_t
{
1487 const char *varname
; /**< The value (or prefix) of the question. */
1488 getinfo_helper_t fn
; /**< The function that knows the answer: NULL if
1489 * this entry is documentation-only. */
1490 const char *desc
; /**< Description of the variable. */
1491 int is_prefix
; /** Must varname match exactly, or must it be a prefix? */
1494 #define ITEM(name, fn, desc) { name, getinfo_helper_##fn, desc, 0 }
1495 #define PREFIX(name, fn, desc) { name, getinfo_helper_##fn, desc, 1 }
1496 #define DOC(name, desc) { name, NULL, desc, 0 }
1498 /** Table mapping questions accepted by GETINFO to the functions that know how
1499 * to answer them. */
1500 static const getinfo_item_t getinfo_items
[] = {
1501 ITEM("version", misc
, "The current version of Tor."),
1502 ITEM("bw-event-cache", misc
, "Cached BW events for a short interval."),
1503 ITEM("config-file", misc
, "Current location of the \"torrc\" file."),
1504 ITEM("config-defaults-file", misc
, "Current location of the defaults file."),
1505 ITEM("config-text", misc
,
1506 "Return the string that would be written by a saveconf command."),
1507 ITEM("config-can-saveconf", misc
,
1508 "Is it possible to save the configuration to the \"torrc\" file?"),
1509 ITEM("accounting/bytes", accounting
,
1510 "Number of bytes read/written so far in the accounting interval."),
1511 ITEM("accounting/bytes-left", accounting
,
1512 "Number of bytes left to write/read so far in the accounting interval."),
1513 ITEM("accounting/enabled", accounting
, "Is accounting currently enabled?"),
1514 ITEM("accounting/hibernating", accounting
, "Are we hibernating or awake?"),
1515 ITEM("accounting/interval-start", accounting
,
1516 "Time when the accounting period starts."),
1517 ITEM("accounting/interval-end", accounting
,
1518 "Time when the accounting period ends."),
1519 ITEM("accounting/interval-wake", accounting
,
1520 "Time to wake up in this accounting period."),
1521 ITEM("helper-nodes", entry_guards
, NULL
), /* deprecated */
1522 ITEM("entry-guards", entry_guards
,
1523 "Which nodes are we using as entry guards?"),
1524 ITEM("fingerprint", misc
, NULL
),
1525 PREFIX("config/", config
, "Current configuration values."),
1527 "List of configuration options, types, and documentation."),
1528 DOC("config/defaults",
1529 "List of default values for configuration options. "
1530 "See also config/names"),
1531 PREFIX("current-time/", current_time
, "Current time."),
1532 DOC("current-time/local", "Current time on the local system."),
1533 DOC("current-time/utc", "Current UTC time."),
1534 PREFIX("downloads/networkstatus/", downloads
,
1535 "Download statuses for networkstatus objects"),
1536 DOC("downloads/networkstatus/ns",
1537 "Download status for current-mode networkstatus download"),
1538 DOC("downloads/networkstatus/ns/bootstrap",
1539 "Download status for bootstrap-time networkstatus download"),
1540 DOC("downloads/networkstatus/ns/running",
1541 "Download status for run-time networkstatus download"),
1542 DOC("downloads/networkstatus/microdesc",
1543 "Download status for current-mode microdesc download"),
1544 DOC("downloads/networkstatus/microdesc/bootstrap",
1545 "Download status for bootstrap-time microdesc download"),
1546 DOC("downloads/networkstatus/microdesc/running",
1547 "Download status for run-time microdesc download"),
1548 PREFIX("downloads/cert/", downloads
,
1549 "Download statuses for certificates, by id fingerprint and "
1551 DOC("downloads/cert/fps",
1552 "List of authority fingerprints for which any download statuses "
1554 DOC("downloads/cert/fp/<fp>",
1555 "Download status for <fp> with the default signing key; corresponds "
1556 "to /fp/ URLs on directory server."),
1557 DOC("downloads/cert/fp/<fp>/sks",
1558 "List of signing keys for which specific download statuses are "
1559 "available for this id fingerprint"),
1560 DOC("downloads/cert/fp/<fp>/<sk>",
1561 "Download status for <fp> with signing key <sk>; corresponds "
1562 "to /fp-sk/ URLs on directory server."),
1563 PREFIX("downloads/desc/", downloads
,
1564 "Download statuses for router descriptors, by descriptor digest"),
1565 DOC("downloads/desc/descs",
1566 "Return a list of known router descriptor digests"),
1567 DOC("downloads/desc/<desc>",
1568 "Return a download status for a given descriptor digest"),
1569 PREFIX("downloads/bridge/", downloads
,
1570 "Download statuses for bridge descriptors, by bridge identity "
1572 DOC("downloads/bridge/bridges",
1573 "Return a list of configured bridge identity digests with download "
1575 DOC("downloads/bridge/<desc>",
1576 "Return a download status for a given bridge identity digest"),
1577 ITEM("info/names", misc
,
1578 "List of GETINFO options, types, and documentation."),
1579 ITEM("events/names", misc
,
1580 "Events that the controller can ask for with SETEVENTS."),
1581 ITEM("signal/names", misc
, "Signal names recognized by the SIGNAL command"),
1582 ITEM("features/names", misc
, "What arguments can USEFEATURE take?"),
1583 PREFIX("desc/id/", dir
, "Router descriptors by ID."),
1584 PREFIX("desc/name/", dir
, "Router descriptors by nickname."),
1585 ITEM("desc/all-recent", dir
,
1586 "All non-expired, non-superseded router descriptors."),
1587 ITEM("desc/download-enabled", dir
,
1588 "Do we try to download router descriptors?"),
1589 ITEM("desc/all-recent-extrainfo-hack", dir
, NULL
), /* Hack. */
1590 ITEM("md/all", dir
, "All known microdescriptors."),
1591 PREFIX("md/id/", dir
, "Microdescriptors by ID"),
1592 PREFIX("md/name/", dir
, "Microdescriptors by name"),
1593 ITEM("md/download-enabled", dir
,
1594 "Do we try to download microdescriptors?"),
1595 PREFIX("extra-info/digest/", dir
, "Extra-info documents by digest."),
1596 PREFIX("hs/client/desc/id", dir
,
1597 "Hidden Service descriptor in client's cache by onion."),
1598 PREFIX("hs/service/desc/id/", dir
,
1599 "Hidden Service descriptor in services's cache by onion."),
1600 PREFIX("net/listeners/", listeners
, "Bound addresses by type"),
1601 ITEM("ns/all", networkstatus
,
1602 "Brief summary of router status (v2 directory format)"),
1603 PREFIX("ns/id/", networkstatus
,
1604 "Brief summary of router status by ID (v2 directory format)."),
1605 PREFIX("ns/name/", networkstatus
,
1606 "Brief summary of router status by nickname (v2 directory format)."),
1607 PREFIX("ns/purpose/", networkstatus
,
1608 "Brief summary of router status by purpose (v2 directory format)."),
1609 PREFIX("consensus/", networkstatus
,
1610 "Information about and from the ns consensus."),
1611 ITEM("network-status", dir
,
1612 "Brief summary of router status (v1 directory format)"),
1613 ITEM("network-liveness", liveness
,
1614 "Current opinion on whether the network is live"),
1615 ITEM("circuit-status", events
, "List of current circuits originating here."),
1616 ITEM("stream-status", events
,"List of current streams."),
1617 ITEM("orconn-status", events
, "A list of current OR connections."),
1618 ITEM("dormant", misc
,
1619 "Is Tor dormant (not building circuits because it's idle)?"),
1620 PREFIX("address-mappings/", events
, NULL
),
1621 DOC("address-mappings/all", "Current address mappings."),
1622 DOC("address-mappings/cache", "Current cached DNS replies."),
1623 DOC("address-mappings/config",
1624 "Current address mappings from configuration."),
1625 DOC("address-mappings/control", "Current address mappings from controller."),
1626 PREFIX("status/", events
, NULL
),
1627 DOC("status/circuit-established",
1628 "Whether we think client functionality is working."),
1629 DOC("status/enough-dir-info",
1630 "Whether we have enough up-to-date directory information to build "
1632 DOC("status/bootstrap-phase",
1633 "The last bootstrap phase status event that Tor sent."),
1634 DOC("status/clients-seen",
1635 "Breakdown of client countries seen by a bridge."),
1636 DOC("status/fresh-relay-descs",
1637 "A fresh relay/ei descriptor pair for Tor's current state. Not stored."),
1638 DOC("status/version/recommended", "List of currently recommended versions."),
1639 DOC("status/version/current", "Status of the current version."),
1640 ITEM("address", misc
, "IP address of this Tor host, if we can guess it."),
1641 ITEM("address/v4", misc
,
1642 "IPv4 address of this Tor host, if we can guess it."),
1643 ITEM("address/v6", misc
,
1644 "IPv6 address of this Tor host, if we can guess it."),
1645 ITEM("traffic/read", misc
,"Bytes read since the process was started."),
1646 ITEM("traffic/written", misc
,
1647 "Bytes written since the process was started."),
1648 ITEM("uptime", misc
, "Uptime of the Tor daemon in seconds."),
1649 ITEM("process/pid", misc
, "Process id belonging to the main tor process."),
1650 ITEM("process/uid", misc
, "User id running the tor process."),
1651 ITEM("process/user", misc
,
1652 "Username under which the tor process is running."),
1653 ITEM("process/descriptor-limit", misc
, "File descriptor limit."),
1654 ITEM("limits/max-mem-in-queues", misc
, "Actual limit on memory in queues"),
1655 PREFIX("desc-annotations/id/", dir
, "Router annotations by hexdigest."),
1656 PREFIX("dir/server/", dir
,"Router descriptors as retrieved from a DirPort."),
1657 PREFIX("dir/status/", dir
,
1658 "v2 networkstatus docs as retrieved from a DirPort."),
1659 ITEM("dir/status-vote/current/consensus", dir
,
1660 "v3 Networkstatus consensus as retrieved from a DirPort."),
1661 ITEM("dir/status-vote/current/consensus-microdesc", dir
,
1662 "v3 Microdescriptor consensus as retrieved from a DirPort."),
1663 ITEM("exit-policy/default", policies
,
1664 "The default value appended to the configured exit policy."),
1665 ITEM("exit-policy/reject-private/default", policies
,
1666 "The default rules appended to the configured exit policy by"
1667 " ExitPolicyRejectPrivate."),
1668 ITEM("exit-policy/reject-private/relay", policies
,
1669 "The relay-specific rules appended to the configured exit policy by"
1670 " ExitPolicyRejectPrivate and/or ExitPolicyRejectLocalInterfaces."),
1671 ITEM("exit-policy/full", policies
, "The entire exit policy of onion router"),
1672 ITEM("exit-policy/ipv4", policies
, "IPv4 parts of exit policy"),
1673 ITEM("exit-policy/ipv6", policies
, "IPv6 parts of exit policy"),
1674 PREFIX("ip-to-country/", geoip
, "Perform a GEOIP lookup"),
1675 ITEM("onions/current", onions
,
1676 "Onion services owned by the current control connection."),
1677 ITEM("onions/detached", onions
,
1678 "Onion services detached from the control connection."),
1679 ITEM("sr/current", sr
, "Get current shared random value."),
1680 ITEM("sr/previous", sr
, "Get previous shared random value."),
1681 PREFIX("stats/ntor/", rephist
, "NTor circuit handshake stats."),
1682 ITEM("stats/ntor/assigned", rephist
,
1683 "Assigned NTor circuit handshake stats."),
1684 ITEM("stats/ntor/requested", rephist
,
1685 "Requested NTor circuit handshake stats."),
1686 PREFIX("stats/tap/", rephist
, "TAP circuit handshake stats."),
1687 ITEM("stats/tap/assigned", rephist
,
1688 "Assigned TAP circuit handshake stats."),
1689 ITEM("stats/tap/requested", rephist
,
1690 "Requested TAP circuit handshake stats."),
1691 { NULL
, NULL
, NULL
, 0 }
1694 /** Allocate and return a list of recognized GETINFO options. */
1696 list_getinfo_options(void)
1699 smartlist_t
*lines
= smartlist_new();
1701 for (i
= 0; getinfo_items
[i
].varname
; ++i
) {
1702 if (!getinfo_items
[i
].desc
)
1705 smartlist_add_asprintf(lines
, "%s%s -- %s\n",
1706 getinfo_items
[i
].varname
,
1707 getinfo_items
[i
].is_prefix
? "*" : "",
1708 getinfo_items
[i
].desc
);
1710 smartlist_sort_strings(lines
);
1712 ans
= smartlist_join_strings(lines
, "", 0, NULL
);
1713 SMARTLIST_FOREACH(lines
, char *, cp
, tor_free(cp
));
1714 smartlist_free(lines
);
1719 /** Lookup the 'getinfo' entry <b>question</b>, and return
1720 * the answer in <b>*answer</b> (or NULL if key not recognized).
1721 * Return 0 if success or unrecognized, or -1 if recognized but
1722 * internal error. */
1724 handle_getinfo_helper(control_connection_t
*control_conn
,
1725 const char *question
, char **answer
,
1726 const char **err_out
)
1729 *answer
= NULL
; /* unrecognized key by default */
1731 for (i
= 0; getinfo_items
[i
].varname
; ++i
) {
1733 if (getinfo_items
[i
].is_prefix
)
1734 match
= !strcmpstart(question
, getinfo_items
[i
].varname
);
1736 match
= !strcmp(question
, getinfo_items
[i
].varname
);
1738 tor_assert(getinfo_items
[i
].fn
);
1739 return getinfo_items
[i
].fn(control_conn
, question
, answer
, err_out
);
1743 return 0; /* unrecognized */
1746 const control_cmd_syntax_t getinfo_syntax
= {
1747 .max_args
= UINT_MAX
,
1750 /** Called when we receive a GETINFO command. Try to fetch all requested
1751 * information, and reply with information or error message. */
1753 handle_control_getinfo(control_connection_t
*conn
,
1754 const control_cmd_args_t
*args
)
1756 const smartlist_t
*questions
= args
->args
;
1757 smartlist_t
*answers
= smartlist_new();
1758 smartlist_t
*unrecognized
= smartlist_new();
1761 SMARTLIST_FOREACH_BEGIN(questions
, const char *, q
) {
1762 const char *errmsg
= NULL
;
1764 if (handle_getinfo_helper(conn
, q
, &ans
, &errmsg
) < 0) {
1766 errmsg
= "Internal error";
1767 control_write_endreply(conn
, 551, errmsg
);
1772 /* use provided error message */
1773 control_reply_add_str(unrecognized
, 552, errmsg
);
1775 /* use default error message */
1776 control_reply_add_printf(unrecognized
, 552,
1777 "Unrecognized key \"%s\"", q
);
1780 control_reply_add_one_kv(answers
, 250, KV_RAW
, q
, ans
);
1783 } SMARTLIST_FOREACH_END(q
);
1785 control_reply_add_done(answers
);
1787 if (smartlist_len(unrecognized
)) {
1788 control_write_reply_lines(conn
, unrecognized
);
1789 /* If there were any unrecognized queries, don't write real answers */
1793 control_write_reply_lines(conn
, answers
);
1796 control_reply_free(answers
);
1797 control_reply_free(unrecognized
);