tor  0.4.0.1-alpha
dirserv.c
Go to the documentation of this file.
1 /* Copyright (c) 2001-2004, Roger Dingledine.
2  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3  * Copyright (c) 2007-2019, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 
6 #define DIRSERV_PRIVATE
7 #include "core/or/or.h"
8 
9 #include "app/config/config.h"
11 #include "feature/dircache/conscache.h"
12 #include "feature/dircache/consdiffmgr.h"
17 #include "feature/relay/router.h"
19 #include "feature/stats/predict_ports.h"
20 
21 #include "feature/dircache/cached_dir_st.h"
22 #include "feature/dircommon/dir_connection_st.h"
23 #include "feature/nodelist/extrainfo_st.h"
24 #include "feature/nodelist/microdesc_st.h"
25 #include "feature/nodelist/routerinfo_st.h"
26 #include "feature/nodelist/routerlist_st.h"
27 
28 #include "lib/compress/compress.h"
29 
54 static void clear_cached_dir(cached_dir_t *d);
56  const uint8_t *fp,
57  int extrainfo);
58 
59 static int spooled_resource_lookup_body(const spooled_resource_t *spooled,
60  int conn_is_encrypted,
61  const uint8_t **body_out,
62  size_t *size_out,
63  time_t *published_out);
65  const spooled_resource_t *spooled,
66  time_t *published_out);
67 static cached_dir_t *lookup_cached_dir_by_fp(const uint8_t *fp);
68 
69 /********************************************************************/
70 
71 /* A set of functions to answer questions about how we'd like to behave
72  * as a directory mirror/client. */
73 
76 int
78 {
79  const routerinfo_t *me;
80  uint32_t addr;
81  int refuseunknown;
82  if (options->FetchDirInfoEarly)
83  return 1;
84  if (options->BridgeRelay == 1)
85  return 0;
86  if (server_mode(options) &&
87  router_pick_published_address(options, &addr, 1) < 0)
88  return 1; /* we don't know our IP address; ask an authority. */
89  refuseunknown = ! router_my_exit_policy_is_reject_star() &&
91  if (!dir_server_mode(options) && !refuseunknown)
92  return 0;
93  if (!server_mode(options) || !advertised_server_mode())
94  return 0;
95  me = router_get_my_routerinfo();
96  if (!me || (!me->supports_tunnelled_dir_requests && !refuseunknown))
97  return 0; /* if we don't service directory requests, return 0 too */
98  return 1;
99 }
100 
104 int
106 {
107  return directory_fetches_from_authorities(options);
108 }
109 
116 int
118 {
119  return options->UseBridges != 0;
120 }
121 
127 int
129 {
130  return dir_server_mode(options) || options->BridgeRelay;
131 }
132 
142 int
144 {
145  if (options->BridgeRelay || dir_server_mode(options))
146  return 1;
147  if (!server_mode(options) || !advertised_server_mode())
148  return 0;
149  /* We need an up-to-date view of network info if we're going to try to
150  * block exit attempts from unknown relays. */
151  return ! router_my_exit_policy_is_reject_star() &&
153 }
154 
158 int
160 {
161  return options->BridgeRelay != 0 || dir_server_mode(options);
162 }
163 
168 int
170  time_t now)
171 {
172  return !directory_caches_dir_info(options) &&
173  !options->FetchUselessDescriptors &&
175 }
176 
177 /********************************************************************/
178 
181 static strmap_t *cached_consensuses = NULL;
182 
185 void
187 {
188  if (!d || --d->refcnt > 0)
189  return;
190  clear_cached_dir(d);
191  tor_free(d);
192 }
193 
196 cached_dir_t *
197 new_cached_dir(char *s, time_t published)
198 {
199  cached_dir_t *d = tor_malloc_zero(sizeof(cached_dir_t));
200  d->refcnt = 1;
201  d->dir = s;
202  d->dir_len = strlen(s);
203  d->published = published;
205  d->dir, d->dir_len, ZLIB_METHOD)) {
206  log_warn(LD_BUG, "Error compressing directory");
207  }
208  return d;
209 }
210 
212 static void
214 {
215  tor_free(d->dir);
217  memset(d, 0, sizeof(cached_dir_t));
218 }
219 
221 static void
223 {
224  cached_dir_t *d;
225  if (!_d)
226  return;
227 
228  d = (cached_dir_t *)_d;
230 }
231 
235 void
237  size_t networkstatus_len,
238  const char *flavor_name,
239  const common_digests_t *digests,
240  const uint8_t *sha3_as_signed,
241  time_t published)
242 {
243  cached_dir_t *new_networkstatus;
244  cached_dir_t *old_networkstatus;
245  if (!cached_consensuses)
246  cached_consensuses = strmap_new();
247 
248  new_networkstatus =
249  new_cached_dir(tor_memdup_nulterm(networkstatus, networkstatus_len),
250  published);
251  memcpy(&new_networkstatus->digests, digests, sizeof(common_digests_t));
252  memcpy(&new_networkstatus->digest_sha3_as_signed, sha3_as_signed,
253  DIGEST256_LEN);
254  old_networkstatus = strmap_set(cached_consensuses, flavor_name,
255  new_networkstatus);
256  if (old_networkstatus)
257  cached_dir_decref(old_networkstatus);
258 }
259 
262 cached_dir_t *
263 dirserv_get_consensus(const char *flavor_name)
264 {
265  if (!cached_consensuses)
266  return NULL;
267  return strmap_get(cached_consensuses, flavor_name);
268 }
269 
275 int
277  const char *key,
278  dir_spool_source_t source,
279  int conn_is_encrypted,
280  const char **msg_out)
281 {
282  *msg_out = NULL;
283 
284  if (!strcmp(key, "all")) {
285  const routerlist_t *rl = router_get_routerlist();
286  SMARTLIST_FOREACH_BEGIN(rl->routers, const routerinfo_t *, r) {
287  spooled_resource_t *spooled;
288  spooled = spooled_resource_new(source,
289  (const uint8_t *)r->cache_info.identity_digest,
290  DIGEST_LEN);
291  /* Treat "all" requests as if they were unencrypted */
292  conn_is_encrypted = 0;
293  smartlist_add(spool_out, spooled);
294  } SMARTLIST_FOREACH_END(r);
295  } else if (!strcmp(key, "authority")) {
296  const routerinfo_t *ri = router_get_my_routerinfo();
297  if (ri)
298  smartlist_add(spool_out,
299  spooled_resource_new(source,
300  (const uint8_t *)ri->cache_info.identity_digest,
301  DIGEST_LEN));
302  } else if (!strcmpstart(key, "d/")) {
303  key += strlen("d/");
304  dir_split_resource_into_spoolable(key, source, spool_out, NULL,
305  DSR_HEX|DSR_SORT_UNIQ);
306  } else if (!strcmpstart(key, "fp/")) {
307  key += strlen("fp/");
308  dir_split_resource_into_spoolable(key, source, spool_out, NULL,
309  DSR_HEX|DSR_SORT_UNIQ);
310  } else {
311  *msg_out = "Not found";
312  return -1;
313  }
314 
315  if (! conn_is_encrypted) {
316  /* Remove anything that insists it not be sent unencrypted. */
317  SMARTLIST_FOREACH_BEGIN(spool_out, spooled_resource_t *, spooled) {
318  const uint8_t *body = NULL;
319  size_t bodylen = 0;
320  int r = spooled_resource_lookup_body(spooled, conn_is_encrypted,
321  &body, &bodylen, NULL);
322  if (r < 0 || body == NULL || bodylen == 0) {
323  SMARTLIST_DEL_CURRENT(spool_out, spooled);
324  spooled_resource_free(spooled);
325  }
326  } SMARTLIST_FOREACH_END(spooled);
327  }
328 
329  if (!smartlist_len(spool_out)) {
330  *msg_out = "Servers unavailable";
331  return -1;
332  }
333  return 0;
334 }
335 
354 int
355 dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
356  const char **msg)
357 {
358  *msg = NULL;
359 
360  if (!strcmp(key, "/tor/server/all")) {
363  smartlist_add(descs_out, &(r->cache_info)));
364  } else if (!strcmp(key, "/tor/server/authority")) {
365  const routerinfo_t *ri = router_get_my_routerinfo();
366  if (ri)
367  smartlist_add(descs_out, (void*) &(ri->cache_info));
368  } else if (!strcmpstart(key, "/tor/server/d/")) {
369  smartlist_t *digests = smartlist_new();
370  key += strlen("/tor/server/d/");
371  dir_split_resource_into_fingerprints(key, digests, NULL,
372  DSR_HEX|DSR_SORT_UNIQ);
373  SMARTLIST_FOREACH(digests, const char *, d,
374  {
376  if (sd)
377  smartlist_add(descs_out,sd);
378  });
379  SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
380  smartlist_free(digests);
381  } else if (!strcmpstart(key, "/tor/server/fp/")) {
382  smartlist_t *digests = smartlist_new();
383  time_t cutoff = time(NULL) - ROUTER_MAX_AGE_TO_PUBLISH;
384  key += strlen("/tor/server/fp/");
385  dir_split_resource_into_fingerprints(key, digests, NULL,
386  DSR_HEX|DSR_SORT_UNIQ);
387  SMARTLIST_FOREACH_BEGIN(digests, const char *, d) {
388  if (router_digest_is_me(d)) {
389  /* calling router_get_my_routerinfo() to make sure it exists */
390  const routerinfo_t *ri = router_get_my_routerinfo();
391  if (ri)
392  smartlist_add(descs_out, (void*) &(ri->cache_info));
393  } else {
394  const routerinfo_t *ri = router_get_by_id_digest(d);
395  /* Don't actually serve a descriptor that everyone will think is
396  * expired. This is an (ugly) workaround to keep buggy 0.1.1.10
397  * Tors from downloading descriptors that they will throw away.
398  */
399  if (ri && ri->cache_info.published_on > cutoff)
400  smartlist_add(descs_out, (void*) &(ri->cache_info));
401  }
402  } SMARTLIST_FOREACH_END(d);
403  SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
404  smartlist_free(digests);
405  } else {
406  *msg = "Key not recognized";
407  return -1;
408  }
409 
410  if (!smartlist_len(descs_out)) {
411  *msg = "Servers unavailable";
412  return -1;
413  }
414  return 0;
415 }
416 
417 /* ==========
418  * Spooling code.
419  * ========== */
420 
422 spooled_resource_new(dir_spool_source_t source,
423  const uint8_t *digest, size_t digestlen)
424 {
425  spooled_resource_t *spooled = tor_malloc_zero(sizeof(spooled_resource_t));
426  spooled->spool_source = source;
427  switch (source) {
428  case DIR_SPOOL_NETWORKSTATUS:
429  spooled->spool_eagerly = 0;
430  break;
431  case DIR_SPOOL_SERVER_BY_DIGEST:
432  case DIR_SPOOL_SERVER_BY_FP:
433  case DIR_SPOOL_EXTRA_BY_DIGEST:
434  case DIR_SPOOL_EXTRA_BY_FP:
435  case DIR_SPOOL_MICRODESC:
436  default:
437  spooled->spool_eagerly = 1;
438  break;
439  case DIR_SPOOL_CONSENSUS_CACHE_ENTRY:
440  tor_assert_unreached();
441  break;
442  }
443  tor_assert(digestlen <= sizeof(spooled->digest));
444  if (digest)
445  memcpy(spooled->digest, digest, digestlen);
446  return spooled;
447 }
448 
458 {
459  spooled_resource_t *spooled = tor_malloc_zero(sizeof(spooled_resource_t));
460  spooled->spool_source = DIR_SPOOL_CONSENSUS_CACHE_ENTRY;
461  spooled->spool_eagerly = 0;
462  consensus_cache_entry_incref(entry);
463  spooled->consensus_cache_entry = entry;
464 
465  int r = consensus_cache_entry_get_body(entry,
466  &spooled->cce_body,
467  &spooled->cce_len);
468  if (r == 0) {
469  return spooled;
470  } else {
471  spooled_resource_free(spooled);
472  return NULL;
473  }
474 }
475 
477 void
479 {
480  if (spooled == NULL)
481  return;
482 
483  if (spooled->cached_dir_ref) {
485  }
486 
487  if (spooled->consensus_cache_entry) {
488  consensus_cache_entry_decref(spooled->consensus_cache_entry);
489  }
490 
491  tor_free(spooled);
492 }
493 
496 #define DIRSERV_CACHED_DIR_CHUNK_SIZE 8192
497 
500 static double
502 {
503  /* We should put in better estimates here, depending on the number of
504  objects and their type */
505  (void) source;
506  return 0.5;
507 }
508 
515 static size_t
517  dir_connection_t *conn,
518  int compressed,
519  time_t *published_out)
520 {
521  if (spooled->spool_eagerly) {
522  const uint8_t *body = NULL;
523  size_t bodylen = 0;
524  int r = spooled_resource_lookup_body(spooled,
526  &body, &bodylen,
527  published_out);
528  if (r == -1 || body == NULL || bodylen == 0)
529  return 0;
530  if (compressed) {
531  double ratio = estimate_compression_ratio(spooled->spool_source);
532  bodylen = (size_t)(bodylen * ratio);
533  }
534  return bodylen;
535  } else {
536  cached_dir_t *cached;
537  if (spooled->consensus_cache_entry) {
538  if (published_out) {
539  consensus_cache_entry_get_valid_after(
540  spooled->consensus_cache_entry, published_out);
541  }
542 
543  return spooled->cce_len;
544  }
545  if (spooled->cached_dir_ref) {
546  cached = spooled->cached_dir_ref;
547  } else {
548  cached = spooled_resource_lookup_cached_dir(spooled,
549  published_out);
550  }
551  if (cached == NULL) {
552  return 0;
553  }
554  size_t result = compressed ? cached->dir_compressed_len : cached->dir_len;
555  return result;
556  }
557 }
558 
560 typedef enum {
561  SRFS_ERR = -1,
562  SRFS_MORE = 0,
563  SRFS_DONE
565 
573  dir_connection_t *conn)
574 {
575  if (spooled->spool_eagerly) {
576  /* Spool_eagerly resources are sent all-at-once. */
577  const uint8_t *body = NULL;
578  size_t bodylen = 0;
579  int r = spooled_resource_lookup_body(spooled,
581  &body, &bodylen, NULL);
582  if (r == -1 || body == NULL || bodylen == 0) {
583  /* Absent objects count as "done". */
584  return SRFS_DONE;
585  }
586  if (conn->compress_state) {
587  connection_buf_add_compress((const char*)body, bodylen, conn, 0);
588  } else {
589  connection_buf_add((const char*)body, bodylen, TO_CONN(conn));
590  }
591  return SRFS_DONE;
592  } else {
593  cached_dir_t *cached = spooled->cached_dir_ref;
595  if (cached == NULL && cce == NULL) {
596  /* The cached_dir_t hasn't been materialized yet. So let's look it up. */
597  cached = spooled->cached_dir_ref =
598  spooled_resource_lookup_cached_dir(spooled, NULL);
599  if (!cached) {
600  /* Absent objects count as done. */
601  return SRFS_DONE;
602  }
603  ++cached->refcnt;
604  tor_assert_nonfatal(spooled->cached_dir_offset == 0);
605  }
606 
607  if (BUG(!cached && !cce))
608  return SRFS_DONE;
609 
610  int64_t total_len;
611  const char *ptr;
612  if (cached) {
613  total_len = cached->dir_compressed_len;
614  ptr = cached->dir_compressed;
615  } else {
616  total_len = spooled->cce_len;
617  ptr = (const char *)spooled->cce_body;
618  }
619  /* How many bytes left to flush? */
620  int64_t remaining;
621  remaining = total_len - spooled->cached_dir_offset;
622  if (BUG(remaining < 0))
623  return SRFS_ERR;
624  ssize_t bytes = (ssize_t) MIN(DIRSERV_CACHED_DIR_CHUNK_SIZE, remaining);
625  if (conn->compress_state) {
626  connection_buf_add_compress(
627  ptr + spooled->cached_dir_offset,
628  bytes, conn, 0);
629  } else {
630  connection_buf_add(ptr + spooled->cached_dir_offset,
631  bytes, TO_CONN(conn));
632  }
633  spooled->cached_dir_offset += bytes;
634  if (spooled->cached_dir_offset >= (off_t)total_len) {
635  return SRFS_DONE;
636  } else {
637  return SRFS_MORE;
638  }
639  }
640 }
641 
649 static cached_dir_t *
651  time_t *published_out)
652 {
653  tor_assert(spooled->spool_eagerly == 0);
655  if (d != NULL) {
656  if (published_out)
657  *published_out = d->published;
658  }
659  return d;
660 }
661 
668 static int
670  int conn_is_encrypted,
671  const uint8_t **body_out,
672  size_t *size_out,
673  time_t *published_out)
674 {
675  tor_assert(spooled->spool_eagerly == 1);
676 
677  const signed_descriptor_t *sd = NULL;
678 
679  switch (spooled->spool_source) {
680  case DIR_SPOOL_EXTRA_BY_FP: {
681  sd = get_signed_descriptor_by_fp(spooled->digest, 1);
682  break;
683  }
684  case DIR_SPOOL_SERVER_BY_FP: {
685  sd = get_signed_descriptor_by_fp(spooled->digest, 0);
686  break;
687  }
688  case DIR_SPOOL_SERVER_BY_DIGEST: {
689  sd = router_get_by_descriptor_digest((const char *)spooled->digest);
690  break;
691  }
692  case DIR_SPOOL_EXTRA_BY_DIGEST: {
693  sd = extrainfo_get_by_descriptor_digest((const char *)spooled->digest);
694  break;
695  }
696  case DIR_SPOOL_MICRODESC: {
699  (const char *)spooled->digest);
700  if (! md || ! md->body) {
701  return -1;
702  }
703  *body_out = (const uint8_t *)md->body;
704  *size_out = md->bodylen;
705  if (published_out)
706  *published_out = TIME_MAX;
707  return 0;
708  }
709  case DIR_SPOOL_NETWORKSTATUS:
710  case DIR_SPOOL_CONSENSUS_CACHE_ENTRY:
711  default:
712  /* LCOV_EXCL_START */
713  tor_assert_nonfatal_unreached();
714  return -1;
715  /* LCOV_EXCL_STOP */
716  }
717 
718  /* If we get here, then we tried to set "sd" to a signed_descriptor_t. */
719 
720  if (sd == NULL) {
721  return -1;
722  }
723  if (sd->send_unencrypted == 0 && ! conn_is_encrypted) {
724  /* we did this check once before (so we could have an accurate size
725  * estimate and maybe send a 404 if somebody asked for only bridges on
726  * a connection), but we need to do it again in case a previously
727  * unknown bridge descriptor has shown up between then and now. */
728  return -1;
729  }
730  *body_out = (const uint8_t *) signed_descriptor_get_body(sd);
731  *size_out = sd->signed_descriptor_len;
732  if (published_out)
733  *published_out = sd->published_on;
734  return 0;
735 }
736 
741 static cached_dir_t *
742 lookup_cached_dir_by_fp(const uint8_t *fp)
743 {
744  cached_dir_t *d = NULL;
745  if (tor_digest_is_zero((const char *)fp) && cached_consensuses) {
746  d = strmap_get(cached_consensuses, "ns");
747  } else if (memchr(fp, '\0', DIGEST_LEN) && cached_consensuses) {
748  /* this here interface is a nasty hack: we're shoving a flavor into
749  * a digest field. */
750  d = strmap_get(cached_consensuses, (const char *)fp);
751  }
752  return d;
753 }
754 
761 void
763  time_t cutoff,
764  int compression,
765  size_t *size_out,
766  int *n_expired_out)
767 {
768  if (BUG(!conn))
769  return;
770 
771  smartlist_t *spool = conn->spool;
772  if (!spool) {
773  if (size_out)
774  *size_out = 0;
775  if (n_expired_out)
776  *n_expired_out = 0;
777  return;
778  }
779  int n_expired = 0;
780  uint64_t total = 0;
781  SMARTLIST_FOREACH_BEGIN(spool, spooled_resource_t *, spooled) {
782  time_t published = TIME_MAX;
783  size_t sz = spooled_resource_estimate_size(spooled, conn,
784  compression, &published);
785  if (published < cutoff) {
786  ++n_expired;
787  SMARTLIST_DEL_CURRENT(spool, spooled);
788  spooled_resource_free(spooled);
789  } else if (sz == 0) {
790  SMARTLIST_DEL_CURRENT(spool, spooled);
791  spooled_resource_free(spooled);
792  } else {
793  total += sz;
794  }
795  } SMARTLIST_FOREACH_END(spooled);
796 
797  if (size_out) {
798  *size_out = (total > SIZE_MAX) ? SIZE_MAX : (size_t)total;
799  }
800  if (n_expired_out)
801  *n_expired_out = n_expired;
802 }
803 
805 static int
806 dirserv_spool_sort_comparison_(const void **a_, const void **b_)
807 {
808  const spooled_resource_t *a = *a_;
809  const spooled_resource_t *b = *b_;
810  return fast_memcmp(a->digest, b->digest, sizeof(a->digest));
811 }
812 
814 void
816 {
817  if (conn->spool == NULL)
818  return;
820 }
821 
826 static const signed_descriptor_t *
827 get_signed_descriptor_by_fp(const uint8_t *fp, int extrainfo)
828 {
829  if (router_digest_is_me((const char *)fp)) {
830  if (extrainfo)
831  return &(router_get_my_extrainfo()->cache_info);
832  else
833  return &(router_get_my_routerinfo()->cache_info);
834  } else {
835  const routerinfo_t *ri = router_get_by_id_digest((const char *)fp);
836  if (ri) {
837  if (extrainfo)
838  return extrainfo_get_by_descriptor_digest(
839  ri->cache_info.extra_info_digest);
840  else
841  return &ri->cache_info;
842  }
843  }
844  return NULL;
845 }
846 
849 #define DIRSERV_BUFFER_MIN 16384
850 
859 int
861 {
863  if (conn->spool == NULL)
864  return 0;
865 
866  while (connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN &&
867  smartlist_len(conn->spool)) {
868  spooled_resource_t *spooled =
869  smartlist_get(conn->spool, smartlist_len(conn->spool)-1);
871  status = spooled_resource_flush_some(spooled, conn);
872  if (status == SRFS_ERR) {
873  return -1;
874  } else if (status == SRFS_MORE) {
875  return 0;
876  }
877  tor_assert(status == SRFS_DONE);
878 
879  /* If we're here, we're done flushing this resource. */
880  tor_assert(smartlist_pop_last(conn->spool) == spooled);
881  spooled_resource_free(spooled);
882  }
883 
884  if (smartlist_len(conn->spool) > 0) {
885  /* We're still spooling something. */
886  return 0;
887  }
888 
889  /* If we get here, we're done. */
890  smartlist_free(conn->spool);
891  conn->spool = NULL;
892  if (conn->compress_state) {
893  /* Flush the compression state: there could be more bytes pending in there,
894  * and we don't want to omit bytes. */
895  connection_buf_add_compress("", 0, conn, 1);
896  tor_compress_free(conn->compress_state);
897  conn->compress_state = NULL;
898  }
899  return 0;
900 }
901 
904 void
906 {
907  if (!conn || ! conn->spool)
908  return;
910  spooled_resource_free(s));
911  smartlist_free(conn->spool);
912  conn->spool = NULL;
913 }
914 
916 void
918 {
919  strmap_free(cached_consensuses, free_cached_dir_);
920  cached_consensuses = NULL;
921 }
time_t published
Definition: cached_dir_st.h:17
Header file for dirserv.c.
int directory_fetches_dir_info_early(const or_options_t *options)
Definition: dirserv.c:105
extrainfo_t * router_get_my_extrainfo(void)
Definition: router.c:1689
dir_spool_source_bitfield_t spool_source
Definition: dirserv.h:51
void dir_conn_clear_spool(dir_connection_t *conn)
Definition: dirserv.c:905
void spooled_resource_free_(spooled_resource_t *spooled)
Definition: dirserv.c:478
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define TO_CONN(c)
Definition: or.h:735
char * dir_compressed
Definition: cached_dir_st.h:14
char extra_info_digest[DIGEST_LEN]
int dir_server_mode(const or_options_t *options)
Definition: routermode.c:20
Header file for connection.c.
static cached_dir_t * spooled_resource_lookup_cached_dir(const spooled_resource_t *spooled, time_t *published_out)
Definition: dirserv.c:650
int should_refuse_unknown_exits(const or_options_t *options)
Definition: router.c:1328
size_t dir_compressed_len
Definition: cached_dir_st.h:16
uint8_t state
Definition: connection_st.h:44
Headers for compress.c.
struct cached_dir_t * cached_dir_ref
Definition: dirserv.h:60
unsigned spool_eagerly
Definition: dirserv.h:47
Header file for directory.c.
void smartlist_add(smartlist_t *sl, void *element)
void * smartlist_pop_last(smartlist_t *sl)
const char * signed_descriptor_get_body(const signed_descriptor_t *desc)
Definition: routerlist.c:794
int dirserv_get_routerdesc_spool(smartlist_t *spool_out, const char *key, dir_spool_source_t source, int conn_is_encrypted, const char **msg_out)
Definition: dirserv.c:276
int directory_caches_unknown_auth_certs(const or_options_t *options)
Definition: dirserv.c:128
smartlist_t * spool
Header file for config.c.
uint8_t digest[DIGEST256_LEN]
Definition: dirserv.h:55
struct tor_compress_state_t * compress_state
Header file for microdesc.c.
off_t cached_dir_offset
Definition: dirserv.h:71
int directory_fetches_from_authorities(const or_options_t *options)
Definition: dirserv.c:77
int strcmpstart(const char *s1, const char *s2)
Definition: util_string.c:209
unsigned int supports_tunnelled_dir_requests
Definition: routerinfo_st.h:83
int directory_too_idle_to_fetch_descriptors(const or_options_t *options, time_t now)
Definition: dirserv.c:169
#define tor_free(p)
Definition: malloc.h:52
struct consensus_cache_entry_t * consensus_cache_entry
Definition: dirserv.h:65
Definition: conscache.c:27
static int dirserv_spool_sort_comparison_(const void **a_, const void **b_)
Definition: dirserv.c:806
#define SMARTLIST_DEL_CURRENT(sl, var)
int connection_dirserv_flushed_some(dir_connection_t *conn)
Definition: dirserv.c:860
static void clear_cached_dir(cached_dir_t *d)
Definition: dirserv.c:213
size_t bodylen
Definition: microdesc_st.h:51
spooled_resource_t * spooled_resource_new_from_cache_entry(consensus_cache_entry_t *entry)
Definition: dirserv.c:457
static strmap_t * cached_consensuses
Definition: dirserv.c:181
#define DIGEST256_LEN
Definition: digest_sizes.h:23
int directory_permits_begindir_requests(const or_options_t *options)
Definition: dirserv.c:159
static const signed_descriptor_t * get_signed_descriptor_by_fp(const uint8_t *fp, int extrainfo)
Definition: dirserv.c:827
int directory_fetches_dir_info_later(const or_options_t *options)
Definition: dirserv.c:117
tor_assert(buffer)
void cached_dir_decref(cached_dir_t *d)
Definition: dirserv.c:186
int tor_compress(char **out, size_t *out_len, const char *in, size_t in_len, compress_method_t method)
Definition: compress.c:242
Header file for routermode.c.
const routerinfo_t * router_get_by_id_digest(const char *digest)
Definition: routerlist.c:690
static double estimate_compression_ratio(dir_spool_source_t source)
Definition: dirserv.c:501
#define DIGEST_LEN
Definition: digest_sizes.h:20
dir_spool_source_t
Definition: dirserv.h:20
spooled_resource_flush_status_t
Definition: dirserv.c:560
Master header file for Tor-specific functionality.
int rep_hist_circbuilding_dormant(time_t now)
void dirserv_free_all(void)
Definition: dirserv.c:917
static void free_cached_dir_(void *_d)
Definition: dirserv.c:222
static size_t spooled_resource_estimate_size(const spooled_resource_t *spooled, dir_connection_t *conn, int compressed, time_t *published_out)
Definition: dirserv.c:516
void dirserv_spool_sort(dir_connection_t *conn)
Definition: dirserv.c:815
signed_descriptor_t * router_get_by_descriptor_digest(const char *digest)
Definition: routerlist.c:698
#define DIRSERV_CACHED_DIR_CHUNK_SIZE
Definition: dirserv.c:496
char * body
Definition: microdesc_st.h:49
int tor_digest_is_zero(const char *digest)
Definition: util_string.c:96
microdesc_t * microdesc_cache_lookup_by_digest256(microdesc_cache_t *cache, const char *d)
Definition: microdesc.c:916
int FetchUselessDescriptors
uint8_t digest_sha3_as_signed[DIGEST256_LEN]
Definition: cached_dir_st.h:20
cached_dir_t * new_cached_dir(char *s, time_t published)
Definition: dirserv.c:197
char identity_digest[DIGEST_LEN]
cached_dir_t * dirserv_get_consensus(const char *flavor_name)
Definition: dirserv.c:263
#define ROUTER_MAX_AGE_TO_PUBLISH
Definition: or.h:162
size_t dir_len
Definition: cached_dir_st.h:15
microdesc_cache_t * get_microdesc_cache(void)
Definition: microdesc.c:245
#define SMARTLIST_FOREACH(sl, type, var, cmd)
int connection_dir_is_encrypted(const dir_connection_t *conn)
Definition: directory.c:160
Header file for router.c.
common_digests_t digests
Definition: cached_dir_st.h:18
int dirserv_get_routerdescs(smartlist_t *descs_out, const char *key, const char **msg)
Definition: dirserv.c:355
void dirserv_spool_remove_missing_and_guess_size(dir_connection_t *conn, time_t cutoff, int compression, size_t *size_out, int *n_expired_out)
Definition: dirserv.c:762
int dir_split_resource_into_fingerprints(const char *resource, smartlist_t *fp_out, int *compressed_out, int flags)
Definition: directory.c:544
int router_digest_is_me(const char *digest)
Definition: router.c:1589
#define fast_memcmp(a, b, c)
Definition: di_ops.h:26
static int spooled_resource_lookup_body(const spooled_resource_t *spooled, int conn_is_encrypted, const uint8_t **body_out, size_t *size_out, time_t *published_out)
Definition: dirserv.c:669
int dir_split_resource_into_spoolable(const char *resource, dir_spool_source_t source, smartlist_t *spool_out, int *compressed_out, int flags)
Definition: directory.c:626
int directory_caches_dir_info(const or_options_t *options)
Definition: dirserv.c:143
#define DIRSERV_BUFFER_MIN
Definition: dirserv.c:849
static cached_dir_t * lookup_cached_dir_by_fp(const uint8_t *fp)
Definition: dirserv.c:742
static spooled_resource_flush_status_t spooled_resource_flush_some(spooled_resource_t *spooled, dir_connection_t *conn)
Definition: dirserv.c:572
void dirserv_set_cached_consensus_networkstatus(const char *networkstatus, size_t networkstatus_len, const char *flavor_name, const common_digests_t *digests, const uint8_t *sha3_as_signed, time_t published)
Definition: dirserv.c:236
void smartlist_sort(smartlist_t *sl, int(*compare)(const void **a, const void **b))
Definition: smartlist.c:334
#define DIR_CONN_STATE_SERVER_WRITING
Definition: directory.h:29
routerlist_t * router_get_routerlist(void)
Definition: routerlist.c:809
#define LD_BUG
Definition: log.h:82
smartlist_t * routers
Definition: routerlist_st.h:27
Header file for routerlist.c.