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