1 /* Copyright (c) 2009-2016, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
7 * \brief Implements microdescriptors -- an abbreviated description of
8 * less-frequently-changing router information.
12 #include "circuitbuild.h"
14 #include "directory.h"
16 #include "entrynodes.h"
17 #include "microdesc.h"
18 #include "networkstatus.h"
22 #include "routerlist.h"
23 #include "routerparse.h"
25 /** A data structure to hold a bunch of cached microdescriptors. There are
26 * two active files in the cache: a "cache file" that we mmap, and a "journal
27 * file" that we append to. Periodically, we rebuild the cache file to hold
28 * only the microdescriptors that we want to keep */
29 struct microdesc_cache_t
{
30 /** Map from sha256-digest to microdesc_t for every microdesc_t in the
32 HT_HEAD(microdesc_map
, microdesc_t
) map
;
34 /** Name of the cache file. */
36 /** Name of the journal file. */
38 /** Mmap'd contents of the cache file, or NULL if there is none. */
39 tor_mmap_t
*cache_content
;
40 /** Number of bytes used in the journal file. */
42 /** Number of bytes in descriptors removed as too old. */
45 /** Total bytes of microdescriptor bodies we have added to this cache */
46 uint64_t total_len_seen
;
47 /** Total number of microdescriptors we have added to this cache */
50 /** True iff we have loaded this cache from disk ever. */
54 static microdesc_cache_t
*get_microdesc_cache_noload(void);
56 /** Helper: computes a hash of <b>md</b> to place it in a hash table. */
57 static inline unsigned int
58 microdesc_hash_(microdesc_t
*md
)
60 return (unsigned) siphash24g(md
->digest
, sizeof(md
->digest
));
63 /** Helper: compares <b>a</b> and <b>b</b> for equality for hash-table
66 microdesc_eq_(microdesc_t
*a
, microdesc_t
*b
)
68 return tor_memeq(a
->digest
, b
->digest
, DIGEST256_LEN
);
71 HT_PROTOTYPE(microdesc_map
, microdesc_t
, node
,
72 microdesc_hash_
, microdesc_eq_
)
73 HT_GENERATE2(microdesc_map
, microdesc_t
, node
,
74 microdesc_hash_
, microdesc_eq_
, 0.6,
75 tor_reallocarray_
, tor_free_
)
77 /** Write the body of <b>md</b> into <b>f</b>, with appropriate annotations.
78 * On success, return the total number of bytes written, and set
79 * *<b>annotation_len_out</b> to the number of bytes written as
82 dump_microdescriptor(int fd
, microdesc_t
*md
, size_t *annotation_len_out
)
86 if (md
->body
== NULL
) {
87 *annotation_len_out
= 0;
90 /* XXXX drops unknown annotations. */
91 if (md
->last_listed
) {
92 char buf
[ISO_TIME_LEN
+1];
93 char annotation
[ISO_TIME_LEN
+32];
94 format_iso_time(buf
, md
->last_listed
);
95 tor_snprintf(annotation
, sizeof(annotation
), "@last-listed %s\n", buf
);
96 if (write_all(fd
, annotation
, strlen(annotation
), 0) < 0) {
98 "Couldn't write microdescriptor annotation: %s",
102 r
+= strlen(annotation
);
103 *annotation_len_out
= r
;
105 *annotation_len_out
= 0;
108 md
->off
= tor_fd_getpos(fd
);
109 written
= write_all(fd
, md
->body
, md
->bodylen
, 0);
110 if (written
!= (ssize_t
)md
->bodylen
) {
111 written
= written
< 0 ? 0 : written
;
113 "Couldn't dump microdescriptor (wrote %ld out of %lu): %s",
114 (long)written
, (unsigned long)md
->bodylen
,
122 /** Holds a pointer to the current microdesc_cache_t object, or NULL if no
123 * such object has been allocated. */
124 static microdesc_cache_t
*the_microdesc_cache
= NULL
;
126 /** Return a pointer to the microdescriptor cache, loading it if necessary. */
128 get_microdesc_cache(void)
130 microdesc_cache_t
*cache
= get_microdesc_cache_noload();
131 if (PREDICT_UNLIKELY(cache
->is_loaded
== 0)) {
132 microdesc_cache_reload(cache
);
137 /** Return a pointer to the microdescriptor cache, creating (but not loading)
138 * it if necessary. */
139 static microdesc_cache_t
*
140 get_microdesc_cache_noload(void)
142 if (PREDICT_UNLIKELY(the_microdesc_cache
==NULL
)) {
143 microdesc_cache_t
*cache
= tor_malloc_zero(sizeof(*cache
));
144 HT_INIT(microdesc_map
, &cache
->map
);
145 cache
->cache_fname
= get_datadir_fname("cached-microdescs");
146 cache
->journal_fname
= get_datadir_fname("cached-microdescs.new");
147 the_microdesc_cache
= cache
;
149 return the_microdesc_cache
;
152 /* There are three sources of microdescriptors:
153 1) Generated by us while acting as a directory authority.
154 2) Loaded from the cache on disk.
158 /** Decode the microdescriptors from the string starting at <b>s</b> and
159 * ending at <b>eos</b>, and store them in <b>cache</b>. If <b>no_save</b>,
160 * mark them as non-writable to disk. If <b>where</b> is SAVED_IN_CACHE,
161 * leave their bodies as pointers to the mmap'd cache. If where is
162 * <b>SAVED_NOWHERE</b>, do not allow annotations. If listed_at is not -1,
163 * set the last_listed field of every microdesc to listed_at. If
164 * requested_digests is non-null, then it contains a list of digests we mean
165 * to allow, so we should reject any non-requested microdesc with a different
166 * digest, and alter the list to contain only the digests of those microdescs
168 * Return a newly allocated list of the added microdescriptors, or NULL */
170 microdescs_add_to_cache(microdesc_cache_t
*cache
,
171 const char *s
, const char *eos
, saved_location_t where
,
172 int no_save
, time_t listed_at
,
173 smartlist_t
*requested_digests256
)
175 void * const DIGEST_REQUESTED
= (void*)1;
176 void * const DIGEST_RECEIVED
= (void*)2;
177 void * const DIGEST_INVALID
= (void*)3;
179 smartlist_t
*descriptors
, *added
;
180 const int allow_annotations
= (where
!= SAVED_NOWHERE
);
181 smartlist_t
*invalid_digests
= smartlist_new();
183 descriptors
= microdescs_parse_from_string(s
, eos
,
185 where
, invalid_digests
);
186 if (listed_at
!= (time_t)-1) {
187 SMARTLIST_FOREACH(descriptors
, microdesc_t
*, md
,
188 md
->last_listed
= listed_at
);
190 if (requested_digests256
) {
191 digest256map_t
*requested
;
192 requested
= digest256map_new();
193 /* Set requested[d] to DIGEST_REQUESTED for every md we requested. */
194 SMARTLIST_FOREACH(requested_digests256
, const uint8_t *, cp
,
195 digest256map_set(requested
, cp
, DIGEST_REQUESTED
));
196 /* Set requested[d] to DIGEST_INVALID for every md we requested which we
197 * will never be able to parse. Remove the ones we didn't request from
200 SMARTLIST_FOREACH_BEGIN(invalid_digests
, uint8_t *, cp
) {
201 if (digest256map_get(requested
, cp
)) {
202 digest256map_set(requested
, cp
, DIGEST_INVALID
);
205 SMARTLIST_DEL_CURRENT(invalid_digests
, cp
);
207 } SMARTLIST_FOREACH_END(cp
);
208 /* Update requested[d] to 2 for the mds we asked for and got. Delete the
209 * ones we never requested from the 'descriptors' smartlist.
211 SMARTLIST_FOREACH_BEGIN(descriptors
, microdesc_t
*, md
) {
212 if (digest256map_get(requested
, (const uint8_t*)md
->digest
)) {
213 digest256map_set(requested
, (const uint8_t*)md
->digest
,
216 log_fn(LOG_PROTOCOL_WARN
, LD_DIR
, "Received non-requested microdesc");
218 SMARTLIST_DEL_CURRENT(descriptors
, md
);
220 } SMARTLIST_FOREACH_END(md
);
221 /* Remove the ones we got or the invalid ones from requested_digests256.
223 SMARTLIST_FOREACH_BEGIN(requested_digests256
, uint8_t *, cp
) {
224 void *status
= digest256map_get(requested
, cp
);
225 if (status
== DIGEST_RECEIVED
|| status
== DIGEST_INVALID
) {
227 SMARTLIST_DEL_CURRENT(requested_digests256
, cp
);
229 } SMARTLIST_FOREACH_END(cp
);
230 digest256map_free(requested
, NULL
);
233 /* For every requested microdescriptor that was unparseable, mark it
234 * as not to be retried. */
235 if (smartlist_len(invalid_digests
)) {
236 networkstatus_t
*ns
=
237 networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC
);
239 SMARTLIST_FOREACH_BEGIN(invalid_digests
, char *, d
) {
241 router_get_mutable_consensus_status_by_descriptor_digest(ns
, d
);
242 if (rs
&& tor_memeq(d
, rs
->descriptor_digest
, DIGEST256_LEN
)) {
243 download_status_mark_impossible(&rs
->dl_status
);
245 } SMARTLIST_FOREACH_END(d
);
248 SMARTLIST_FOREACH(invalid_digests
, uint8_t *, d
, tor_free(d
));
249 smartlist_free(invalid_digests
);
251 added
= microdescs_add_list_to_cache(cache
, descriptors
, where
, no_save
);
252 smartlist_free(descriptors
);
256 /** As microdescs_add_to_cache, but takes a list of microdescriptors instead of
257 * a string to decode. Frees any members of <b>descriptors</b> that it does
260 microdescs_add_list_to_cache(microdesc_cache_t
*cache
,
261 smartlist_t
*descriptors
, saved_location_t where
,
265 open_file_t
*open_file
= NULL
;
270 if (where
== SAVED_NOWHERE
&& !no_save
) {
271 fd
= start_writing_to_file(cache
->journal_fname
,
272 OPEN_FLAGS_APPEND
|O_BINARY
,
275 log_warn(LD_DIR
, "Couldn't append to journal in %s: %s",
276 cache
->journal_fname
, strerror(errno
));
280 added
= smartlist_new();
281 SMARTLIST_FOREACH_BEGIN(descriptors
, microdesc_t
*, md
) {
283 md2
= HT_FIND(microdesc_map
, &cache
->map
, md
);
285 /* We already had this one. */
286 if (md2
->last_listed
< md
->last_listed
)
287 md2
->last_listed
= md
->last_listed
;
289 if (where
!= SAVED_NOWHERE
)
290 cache
->bytes_dropped
+= size
;
294 /* Okay, it's a new one. */
296 size_t annotation_len
;
297 size
= dump_microdescriptor(fd
, md
, &annotation_len
);
299 /* we already warned in dump_microdescriptor */
300 abort_writing_to_file(open_file
);
303 md
->saved_location
= SAVED_IN_JOURNAL
;
304 cache
->journal_len
+= size
;
307 md
->saved_location
= where
;
310 md
->no_save
= no_save
;
312 HT_INSERT(microdesc_map
, &cache
->map
, md
);
314 smartlist_add(added
, md
);
316 cache
->total_len_seen
+= md
->bodylen
;
317 } SMARTLIST_FOREACH_END(md
);
320 if (finish_writing_to_file(open_file
) < 0) {
321 log_warn(LD_DIR
, "Error appending to microdescriptor file: %s",
323 smartlist_clear(added
);
329 networkstatus_t
*ns
= networkstatus_get_latest_consensus();
330 if (ns
&& ns
->flavor
== FLAV_MICRODESC
)
331 SMARTLIST_FOREACH(added
, microdesc_t
*, md
, nodelist_add_microdesc(md
));
334 if (smartlist_len(added
))
335 router_dir_info_changed();
340 /** Remove every microdescriptor in <b>cache</b>. */
342 microdesc_cache_clear(microdesc_cache_t
*cache
)
344 microdesc_t
**entry
, **next
;
346 for (entry
= HT_START(microdesc_map
, &cache
->map
); entry
; entry
= next
) {
347 microdesc_t
*md
= *entry
;
348 next
= HT_NEXT_RMV(microdesc_map
, &cache
->map
, entry
);
352 HT_CLEAR(microdesc_map
, &cache
->map
);
353 if (cache
->cache_content
) {
354 int res
= tor_munmap_file(cache
->cache_content
);
357 "tor_munmap_file() failed clearing microdesc cache; "
358 "we are probably about to leak memory.");
359 /* TODO something smarter? */
361 cache
->cache_content
= NULL
;
363 cache
->total_len_seen
= 0;
365 cache
->bytes_dropped
= 0;
368 /** Reload the contents of <b>cache</b> from disk. If it is empty, load it
369 * for the first time. Return 0 on success, -1 on failure. */
371 microdesc_cache_reload(microdesc_cache_t
*cache
)
374 char *journal_content
;
379 microdesc_cache_clear(cache
);
381 cache
->is_loaded
= 1;
383 mm
= cache
->cache_content
= tor_mmap_file(cache
->cache_fname
);
385 added
= microdescs_add_to_cache(cache
, mm
->data
, mm
->data
+mm
->size
,
386 SAVED_IN_CACHE
, 0, -1, NULL
);
388 total
+= smartlist_len(added
);
389 smartlist_free(added
);
393 journal_content
= read_file_to_str(cache
->journal_fname
,
394 RFTS_IGNORE_MISSING
, &st
);
395 if (journal_content
) {
396 cache
->journal_len
= (size_t) st
.st_size
;
397 added
= microdescs_add_to_cache(cache
, journal_content
,
398 journal_content
+st
.st_size
,
399 SAVED_IN_JOURNAL
, 0, -1, NULL
);
401 total
+= smartlist_len(added
);
402 smartlist_free(added
);
404 tor_free(journal_content
);
406 log_info(LD_DIR
, "Reloaded microdescriptor cache. Found %d descriptors.",
409 microdesc_cache_rebuild(cache
, 0 /* don't force */);
414 /** By default, we remove any microdescriptors that have gone at least this
415 * long without appearing in a current consensus. */
416 #define TOLERATE_MICRODESC_AGE (7*24*60*60)
418 /** Remove all microdescriptors from <b>cache</b> that haven't been listed for
419 * a long time. Does not rebuild the cache on disk. If <b>cutoff</b> is
420 * positive, specifically remove microdescriptors that have been unlisted
421 * since <b>cutoff</b>. If <b>force</b> is true, remove microdescriptors even
422 * if we have no current live microdescriptor consensus.
425 microdesc_cache_clean(microdesc_cache_t
*cache
, time_t cutoff
, int force
)
427 microdesc_t
**mdp
, *victim
;
428 int dropped
=0, kept
=0;
429 size_t bytes_dropped
= 0;
430 time_t now
= time(NULL
);
432 /* If we don't know a live consensus, don't believe last_listed values: we
433 * might be starting up after being down for a while. */
435 ! networkstatus_get_reasonably_live_consensus(now
, FLAV_MICRODESC
))
439 cutoff
= now
- TOLERATE_MICRODESC_AGE
;
441 for (mdp
= HT_START(microdesc_map
, &cache
->map
); mdp
!= NULL
; ) {
442 const int is_old
= (*mdp
)->last_listed
< cutoff
;
443 const unsigned held_by_nodes
= (*mdp
)->held_by_nodes
;
444 if (is_old
&& !held_by_nodes
) {
447 mdp
= HT_NEXT_RMV(microdesc_map
, &cache
->map
, mdp
);
448 victim
->held_in_map
= 0;
449 bytes_dropped
+= victim
->bodylen
;
450 microdesc_free(victim
);
453 /* It's old, but it has held_by_nodes set. That's not okay. */
454 /* Let's try to diagnose and fix #7164 . */
455 smartlist_t
*nodes
= nodelist_find_nodes_with_microdesc(*mdp
);
456 const networkstatus_t
*ns
= networkstatus_get_latest_consensus();
457 long networkstatus_age
= -1;
458 const int ht_badness
= HT_REP_IS_BAD_(microdesc_map
, &cache
->map
);
460 networkstatus_age
= now
- ns
->valid_after
;
462 log_warn(LD_BUG
, "Microdescriptor seemed very old "
463 "(last listed %d hours ago vs %d hour cutoff), but is still "
464 "marked as being held by %d node(s). I found %d node(s) "
465 "holding it. Current networkstatus is %ld hours old. "
466 "Hashtable badness is %d.",
467 (int)((now
- (*mdp
)->last_listed
) / 3600),
468 (int)((now
- cutoff
) / 3600),
470 smartlist_len(nodes
),
471 networkstatus_age
/ 3600,
474 SMARTLIST_FOREACH_BEGIN(nodes
, const node_t
*, node
) {
475 const char *rs_match
= "No RS";
476 const char *rs_present
= "";
478 if (tor_memeq(node
->rs
->descriptor_digest
,
479 (*mdp
)->digest
, DIGEST256_LEN
)) {
480 rs_match
= "Microdesc digest in RS matches";
482 rs_match
= "Microdesc digest in RS does match";
485 /* This should be impossible, but let's see! */
486 rs_present
= " RS not present in networkstatus.";
487 SMARTLIST_FOREACH(ns
->routerstatus_list
, routerstatus_t
*,rs
, {
488 if (rs
== node
->rs
) {
489 rs_present
= " RS okay in networkstatus.";
494 log_warn(LD_BUG
, " [%d]: ID=%s. md=%p, rs=%p, ri=%p. %s.%s",
496 hex_str(node
->identity
, DIGEST_LEN
),
497 node
->md
, node
->rs
, node
->ri
, rs_match
, rs_present
);
498 } SMARTLIST_FOREACH_END(node
);
499 smartlist_free(nodes
);
500 (*mdp
)->last_listed
= now
;
504 mdp
= HT_NEXT(microdesc_map
, &cache
->map
, mdp
);
509 log_info(LD_DIR
, "Removed %d/%d microdescriptors as old.",
510 dropped
,dropped
+kept
);
511 cache
->bytes_dropped
+= bytes_dropped
;
516 should_rebuild_md_cache(microdesc_cache_t
*cache
)
518 const size_t old_len
=
519 cache
->cache_content
? cache
->cache_content
->size
: 0;
520 const size_t journal_len
= cache
->journal_len
;
521 const size_t dropped
= cache
->bytes_dropped
;
523 if (journal_len
< 16384)
524 return 0; /* Don't bother, not enough has happened yet. */
525 if (dropped
> (journal_len
+ old_len
) / 3)
526 return 1; /* We could save 1/3 or more of the currently used space. */
527 if (journal_len
> old_len
/ 2)
528 return 1; /* We should append to the regular file */
534 * Mark <b>md</b> as having no body, and release any storage previously held
538 microdesc_wipe_body(microdesc_t
*md
)
543 if (md
->saved_location
!= SAVED_IN_CACHE
)
547 md
->saved_location
= SAVED_NOWHERE
;
553 /** Regenerate the main cache file for <b>cache</b>, clear the journal file,
554 * and update every microdesc_t in the cache with pointers to its new
555 * location. If <b>force</b> is true, do this unconditionally. If
556 * <b>force</b> is false, do it only if we expect to save space on disk. */
558 microdesc_cache_rebuild(microdesc_cache_t
*cache
, int force
)
560 open_file_t
*open_file
;
565 off_t off
= 0, off_real
;
566 int orig_size
, new_size
;
569 cache
= the_microdesc_cache
;
574 /* Remove dead descriptors */
575 microdesc_cache_clean(cache
, 0/*cutoff*/, 0/*force*/);
577 if (!force
&& !should_rebuild_md_cache(cache
))
580 log_info(LD_DIR
, "Rebuilding the microdescriptor cache...");
582 orig_size
= (int)(cache
->cache_content
? cache
->cache_content
->size
: 0);
583 orig_size
+= (int)cache
->journal_len
;
585 fd
= start_writing_to_file(cache
->cache_fname
,
586 OPEN_FLAGS_REPLACE
|O_BINARY
,
591 wrote
= smartlist_new();
593 HT_FOREACH(mdp
, microdesc_map
, &cache
->map
) {
594 microdesc_t
*md
= *mdp
;
595 size_t annotation_len
;
596 if (md
->no_save
|| !md
->body
)
599 size
= dump_microdescriptor(fd
, md
, &annotation_len
);
601 microdesc_wipe_body(md
);
603 /* rewind, in case it was a partial write. */
604 tor_fd_setpos(fd
, off
);
607 tor_assert(((size_t)size
) == annotation_len
+ md
->bodylen
);
608 md
->off
= off
+ annotation_len
;
610 off_real
= tor_fd_getpos(fd
);
611 if (off_real
!= off
) {
612 log_warn(LD_BUG
, "Discontinuity in position in microdescriptor cache."
613 "By my count, I'm at "I64_FORMAT
614 ", but I should be at "I64_FORMAT
,
615 I64_PRINTF_ARG(off
), I64_PRINTF_ARG(off_real
));
619 if (md
->saved_location
!= SAVED_IN_CACHE
) {
621 md
->saved_location
= SAVED_IN_CACHE
;
623 smartlist_add(wrote
, md
);
626 /* We must do this unmap _before_ we call finish_writing_to_file(), or
627 * windows will not actually replace the file. */
628 if (cache
->cache_content
) {
629 res
= tor_munmap_file(cache
->cache_content
);
632 "Failed to unmap old microdescriptor cache while rebuilding");
634 cache
->cache_content
= NULL
;
637 if (finish_writing_to_file(open_file
) < 0) {
638 log_warn(LD_DIR
, "Error rebuilding microdescriptor cache: %s",
640 /* Okay. Let's prevent from making things worse elsewhere. */
641 cache
->cache_content
= NULL
;
642 HT_FOREACH(mdp
, microdesc_map
, &cache
->map
) {
643 microdesc_t
*md
= *mdp
;
644 if (md
->saved_location
== SAVED_IN_CACHE
) {
645 microdesc_wipe_body(md
);
648 smartlist_free(wrote
);
652 cache
->cache_content
= tor_mmap_file(cache
->cache_fname
);
654 if (!cache
->cache_content
&& smartlist_len(wrote
)) {
655 log_err(LD_DIR
, "Couldn't map file that we just wrote to %s!",
657 smartlist_free(wrote
);
660 SMARTLIST_FOREACH_BEGIN(wrote
, microdesc_t
*, md
) {
661 tor_assert(md
->saved_location
== SAVED_IN_CACHE
);
662 md
->body
= (char*)cache
->cache_content
->data
+ md
->off
;
663 if (PREDICT_UNLIKELY(
664 md
->bodylen
< 9 || fast_memneq(md
->body
, "onion-key", 9) != 0)) {
665 /* XXXX once bug 2022 is solved, we can kill this block and turn it
666 * into just the tor_assert(fast_memeq) */
667 off_t avail
= cache
->cache_content
->size
- md
->off
;
669 tor_assert(avail
>= 0);
670 bad_str
= tor_strndup(md
->body
, MIN(128, (size_t)avail
));
671 log_err(LD_BUG
, "After rebuilding microdesc cache, offsets seem wrong. "
672 " At offset %d, I expected to find a microdescriptor starting "
673 " with \"onion-key\". Instead I got %s.",
674 (int)md
->off
, escaped(bad_str
));
676 tor_assert(fast_memeq(md
->body
, "onion-key", 9));
678 } SMARTLIST_FOREACH_END(md
);
680 smartlist_free(wrote
);
682 write_str_to_file(cache
->journal_fname
, "", 1);
683 cache
->journal_len
= 0;
684 cache
->bytes_dropped
= 0;
686 new_size
= cache
->cache_content
? (int)cache
->cache_content
->size
: 0;
687 log_info(LD_DIR
, "Done rebuilding microdesc cache. "
688 "Saved %d bytes; %d still used.",
689 orig_size
-new_size
, new_size
);
694 /** Make sure that the reference count of every microdescriptor in cache is
697 microdesc_check_counts(void)
700 if (!the_microdesc_cache
)
703 HT_FOREACH(mdp
, microdesc_map
, &the_microdesc_cache
->map
) {
704 microdesc_t
*md
= *mdp
;
705 unsigned int found
=0;
706 const smartlist_t
*nodes
= nodelist_get_list();
707 SMARTLIST_FOREACH(nodes
, node_t
*, node
, {
708 if (node
->md
== md
) {
712 tor_assert(found
== md
->held_by_nodes
);
716 /** Deallocate a single microdescriptor. Note: the microdescriptor MUST have
717 * previously been removed from the cache if it had ever been inserted. */
719 microdesc_free_(microdesc_t
*md
, const char *fname
, int lineno
)
724 /* Make sure that the microdesc was really removed from the appropriate data
726 if (md
->held_in_map
) {
727 microdesc_cache_t
*cache
= get_microdesc_cache_noload();
728 microdesc_t
*md2
= HT_FIND(microdesc_map
, &cache
->map
, md
);
730 log_warn(LD_BUG
, "microdesc_free() called from %s:%d, but md was still "
731 "in microdesc_map", fname
, lineno
);
732 HT_REMOVE(microdesc_map
, &cache
->map
, md
);
734 log_warn(LD_BUG
, "microdesc_free() called from %s:%d with held_in_map "
735 "set, but microdesc was not in the map.", fname
, lineno
);
737 tor_fragile_assert();
739 if (md
->held_by_nodes
) {
740 microdesc_cache_t
*cache
= get_microdesc_cache_noload();
742 const smartlist_t
*nodes
= nodelist_get_list();
743 const int ht_badness
= HT_REP_IS_BAD_(microdesc_map
, &cache
->map
);
744 SMARTLIST_FOREACH(nodes
, node_t
*, node
, {
745 if (node
->md
== md
) {
751 log_warn(LD_BUG
, "microdesc_free() called from %s:%d, but md was still "
752 "referenced %d node(s); held_by_nodes == %u, ht_badness == %d",
753 fname
, lineno
, found
, md
->held_by_nodes
, ht_badness
);
755 log_warn(LD_BUG
, "microdesc_free() called from %s:%d with held_by_nodes "
756 "set to %u, but md was not referenced by any nodes. "
758 fname
, lineno
, md
->held_by_nodes
, ht_badness
);
760 tor_fragile_assert();
762 //tor_assert(md->held_in_map == 0);
763 //tor_assert(md->held_by_nodes == 0);
766 crypto_pk_free(md
->onion_pkey
);
767 tor_free(md
->onion_curve25519_pkey
);
768 tor_free(md
->ed25519_identity_pkey
);
769 if (md
->body
&& md
->saved_location
!= SAVED_IN_CACHE
)
773 SMARTLIST_FOREACH(md
->family
, char *, cp
, tor_free(cp
));
774 smartlist_free(md
->family
);
776 short_policy_free(md
->exit_policy
);
777 short_policy_free(md
->ipv6_exit_policy
);
782 /** Free all storage held in the microdesc.c module. */
784 microdesc_free_all(void)
786 if (the_microdesc_cache
) {
787 microdesc_cache_clear(the_microdesc_cache
);
788 tor_free(the_microdesc_cache
->cache_fname
);
789 tor_free(the_microdesc_cache
->journal_fname
);
790 tor_free(the_microdesc_cache
);
794 /** If there is a microdescriptor in <b>cache</b> whose sha256 digest is
795 * <b>d</b>, return it. Otherwise return NULL. */
797 microdesc_cache_lookup_by_digest256(microdesc_cache_t
*cache
, const char *d
)
799 microdesc_t
*md
, search
;
801 cache
= get_microdesc_cache();
802 memcpy(search
.digest
, d
, DIGEST256_LEN
);
803 md
= HT_FIND(microdesc_map
, &cache
->map
, &search
);
807 /** Return the mean size of decriptors added to <b>cache</b> since it was last
808 * cleared. Used to estimate the size of large downloads. */
810 microdesc_average_size(microdesc_cache_t
*cache
)
813 cache
= get_microdesc_cache();
816 return (size_t)(cache
->total_len_seen
/ cache
->n_seen
);
819 /** Return a smartlist of all the sha256 digest of the microdescriptors that
820 * are listed in <b>ns</b> but not present in <b>cache</b>. Returns pointers
821 * to internals of <b>ns</b>; you should not free the members of the resulting
822 * smartlist. Omit all microdescriptors whose digest appear in <b>skip</b>. */
824 microdesc_list_missing_digest256(networkstatus_t
*ns
, microdesc_cache_t
*cache
,
825 int downloadable_only
, digest256map_t
*skip
)
827 smartlist_t
*result
= smartlist_new();
828 time_t now
= time(NULL
);
829 tor_assert(ns
->flavor
== FLAV_MICRODESC
);
830 SMARTLIST_FOREACH_BEGIN(ns
->routerstatus_list
, routerstatus_t
*, rs
) {
831 if (microdesc_cache_lookup_by_digest256(cache
, rs
->descriptor_digest
))
833 if (downloadable_only
&&
834 !download_status_is_ready(&rs
->dl_status
, now
,
835 get_options()->TestingMicrodescMaxDownloadTries
))
837 if (skip
&& digest256map_get(skip
, (const uint8_t*)rs
->descriptor_digest
))
839 if (tor_mem_is_zero(rs
->descriptor_digest
, DIGEST256_LEN
))
841 /* XXXX Also skip if we're a noncache and wouldn't use this router.
844 smartlist_add(result
, rs
->descriptor_digest
);
845 } SMARTLIST_FOREACH_END(rs
);
849 /** Launch download requests for microdescriptors as appropriate.
851 * Specifically, we should launch download requests if we are configured to
852 * download mirodescriptors, and there are some microdescriptors listed in the
853 * current microdesc consensus that we don't have, and either we never asked
854 * for them, or we failed to download them but we're willing to retry.
857 update_microdesc_downloads(time_t now
)
859 const or_options_t
*options
= get_options();
860 networkstatus_t
*consensus
;
861 smartlist_t
*missing
;
862 digest256map_t
*pending
;
864 if (should_delay_dir_fetches(options
, NULL
))
866 if (directory_too_idle_to_fetch_descriptors(options
, now
))
869 consensus
= networkstatus_get_reasonably_live_consensus(now
, FLAV_MICRODESC
);
873 if (!we_fetch_microdescriptors(options
))
876 pending
= digest256map_new();
877 list_pending_microdesc_downloads(pending
);
879 missing
= microdesc_list_missing_digest256(consensus
,
880 get_microdesc_cache(),
883 digest256map_free(pending
, NULL
);
885 launch_descriptor_downloads(DIR_PURPOSE_FETCH_MICRODESC
,
888 smartlist_free(missing
);
891 /** For every microdescriptor listed in the current microdecriptor consensus,
892 * update its last_listed field to be at least as recent as the publication
893 * time of the current microdescriptor consensus.
896 update_microdescs_from_networkstatus(time_t now
)
898 microdesc_cache_t
*cache
= get_microdesc_cache();
900 networkstatus_t
*ns
=
901 networkstatus_get_reasonably_live_consensus(now
, FLAV_MICRODESC
);
906 tor_assert(ns
->flavor
== FLAV_MICRODESC
);
908 SMARTLIST_FOREACH_BEGIN(ns
->routerstatus_list
, routerstatus_t
*, rs
) {
909 md
= microdesc_cache_lookup_by_digest256(cache
, rs
->descriptor_digest
);
910 if (md
&& ns
->valid_after
> md
->last_listed
)
911 md
->last_listed
= ns
->valid_after
;
912 } SMARTLIST_FOREACH_END(rs
);
915 /** Return true iff we should prefer to use microdescriptors rather than
916 * routerdescs for building circuits. */
918 we_use_microdescriptors_for_circuits(const or_options_t
*options
)
920 int ret
= options
->UseMicrodescriptors
;
922 /* UseMicrodescriptors is "auto"; we need to decide: */
923 /* We'll use microdescriptors iff we are
924 * not a server, and we're not autofetching everything. */
925 /* XXXX++ what does not being a server have to do with it? also there's
926 * a partitioning issue here where bridges differ from clients. */
927 ret
= !server_mode(options
) && !options
->FetchUselessDescriptors
;
932 /** Return true iff we should try to download microdescriptors at all. */
934 we_fetch_microdescriptors(const or_options_t
*options
)
936 if (directory_caches_dir_info(options
))
938 if (options
->FetchUselessDescriptors
)
940 return we_use_microdescriptors_for_circuits(options
);
943 /** Return true iff we should try to download router descriptors at all. */
945 we_fetch_router_descriptors(const or_options_t
*options
)
947 if (directory_caches_dir_info(options
))
949 if (options
->FetchUselessDescriptors
)
951 return ! we_use_microdescriptors_for_circuits(options
);
954 /** Return the consensus flavor we actually want to use to build circuits. */
956 usable_consensus_flavor
,(void))
958 if (we_use_microdescriptors_for_circuits(get_options())) {
959 return FLAV_MICRODESC
;