|
@@ -50,7 +50,6 @@ static int router_nickname_matches(const routerinfo_t *router,
|
|
|
const char *nickname);
|
|
|
static void trusted_dir_server_free(trusted_dir_server_t *ds);
|
|
|
static int signed_desc_digest_is_recognized(signed_descriptor_t *desc);
|
|
|
-static void update_router_have_minimum_dir_info(void);
|
|
|
static const char *signed_descriptor_get_body_impl(
|
|
|
const signed_descriptor_t *desc,
|
|
|
int with_annotations);
|
|
@@ -2940,33 +2939,6 @@ routerlist_reset_warnings(void)
|
|
|
networkstatus_reset_warnings();
|
|
|
}
|
|
|
|
|
|
-/** Mark the router with ID <b>digest</b> as running or non-running
|
|
|
- * in our routerlist. */
|
|
|
-void
|
|
|
-router_set_status(const char *digest, int up)
|
|
|
-{
|
|
|
- node_t *node;
|
|
|
- tor_assert(digest);
|
|
|
-
|
|
|
- SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d,
|
|
|
- if (tor_memeq(d->digest, digest, DIGEST_LEN))
|
|
|
- d->is_running = up);
|
|
|
-
|
|
|
- node = node_get_mutable_by_id(digest);
|
|
|
- if (node) {
|
|
|
-#if 0
|
|
|
- log_debug(LD_DIR,"Marking router %s as %s.",
|
|
|
- node_describe(node), up ? "up" : "down");
|
|
|
-#endif
|
|
|
- if (!up && node_is_me(node) && !net_is_disabled())
|
|
|
- log_warn(LD_NET, "We just marked ourself as down. Are your external "
|
|
|
- "addresses reachable?");
|
|
|
- node->is_running = up;
|
|
|
- }
|
|
|
-
|
|
|
- router_dir_info_changed();
|
|
|
-}
|
|
|
-
|
|
|
/** Add <b>router</b> to the routerlist, if we don't already have it. Replace
|
|
|
* older entries (if any) with the same key. Note: Callers should not hold
|
|
|
* their pointers to <b>router</b> if this function fails; <b>router</b>
|
|
@@ -3993,30 +3965,6 @@ initiate_descriptor_downloads(const routerstatus_t *source,
|
|
|
tor_free(resource);
|
|
|
}
|
|
|
|
|
|
-/** Return 0 if this routerstatus is obsolete, too new, isn't
|
|
|
- * running, or otherwise not a descriptor that we would make any
|
|
|
- * use of even if we had it. Else return 1. */
|
|
|
-static INLINE int
|
|
|
-client_would_use_router(const routerstatus_t *rs, time_t now,
|
|
|
- const or_options_t *options)
|
|
|
-{
|
|
|
- if (!rs->is_flagged_running && !options->FetchUselessDescriptors) {
|
|
|
- /* If we had this router descriptor, we wouldn't even bother using it.
|
|
|
- * But, if we want to have a complete list, fetch it anyway. */
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if (rs->published_on + options->TestingEstimatedDescriptorPropagationTime
|
|
|
- > now) {
|
|
|
- /* Most caches probably don't have this descriptor yet. */
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if (rs->published_on + OLD_ROUTER_DESC_MAX_AGE < now) {
|
|
|
- /* We'd drop it immediately for being too old. */
|
|
|
- return 0;
|
|
|
- }
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
/** Max amount of hashes to download per request.
|
|
|
* Since squid does not like URLs >= 4096 bytes we limit it to 96.
|
|
|
* 4096 - strlen(http://255.255.255.255/tor/server/d/.z) == 4058
|
|
@@ -4529,231 +4477,6 @@ update_extrainfo_downloads(time_t now)
|
|
|
smartlist_free(wanted);
|
|
|
}
|
|
|
|
|
|
-/** True iff, the last time we checked whether we had enough directory info
|
|
|
- * to build circuits, the answer was "yes". */
|
|
|
-static int have_min_dir_info = 0;
|
|
|
-/** True iff enough has changed since the last time we checked whether we had
|
|
|
- * enough directory info to build circuits that our old answer can no longer
|
|
|
- * be trusted. */
|
|
|
-static int need_to_update_have_min_dir_info = 1;
|
|
|
-/** String describing what we're missing before we have enough directory
|
|
|
- * info. */
|
|
|
-static char dir_info_status[128] = "";
|
|
|
-
|
|
|
-/** Return true iff we have enough networkstatus and router information to
|
|
|
- * start building circuits. Right now, this means "more than half the
|
|
|
- * networkstatus documents, and at least 1/4 of expected routers." */
|
|
|
-//XXX should consider whether we have enough exiting nodes here.
|
|
|
-int
|
|
|
-router_have_minimum_dir_info(void)
|
|
|
-{
|
|
|
- if (PREDICT_UNLIKELY(need_to_update_have_min_dir_info)) {
|
|
|
- update_router_have_minimum_dir_info();
|
|
|
- need_to_update_have_min_dir_info = 0;
|
|
|
- }
|
|
|
- return have_min_dir_info;
|
|
|
-}
|
|
|
-
|
|
|
-/** Called when our internal view of the directory has changed. This can be
|
|
|
- * when the authorities change, networkstatuses change, the list of routerdescs
|
|
|
- * changes, or number of running routers changes.
|
|
|
- */
|
|
|
-void
|
|
|
-router_dir_info_changed(void)
|
|
|
-{
|
|
|
- need_to_update_have_min_dir_info = 1;
|
|
|
- rend_hsdir_routers_changed();
|
|
|
-}
|
|
|
-
|
|
|
-/** Return a string describing what we're missing before we have enough
|
|
|
- * directory info. */
|
|
|
-const char *
|
|
|
-get_dir_info_status_string(void)
|
|
|
-{
|
|
|
- return dir_info_status;
|
|
|
-}
|
|
|
-
|
|
|
-/** Iterate over the servers listed in <b>consensus</b>, and count how many of
|
|
|
- * them seem like ones we'd use, and how many of <em>those</em> we have
|
|
|
- * descriptors for. Store the former in *<b>num_usable</b> and the latter in
|
|
|
- * *<b>num_present</b>. If <b>in_set</b> is non-NULL, only consider those
|
|
|
- * routers in <b>in_set</b>. If <b>exit_only</b> is true, only consider nodes
|
|
|
- * with the Exit flag.
|
|
|
- */
|
|
|
-static void
|
|
|
-count_usable_descriptors(int *num_present, int *num_usable,
|
|
|
- const networkstatus_t *consensus,
|
|
|
- const or_options_t *options, time_t now,
|
|
|
- routerset_t *in_set, int exit_only)
|
|
|
-{
|
|
|
- const int md = (consensus->flavor == FLAV_MICRODESC);
|
|
|
- *num_present = 0, *num_usable=0;
|
|
|
-
|
|
|
- SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *, rs)
|
|
|
- {
|
|
|
- if (exit_only && ! rs->is_exit)
|
|
|
- continue;
|
|
|
- if (in_set && ! routerset_contains_routerstatus(in_set, rs, -1))
|
|
|
- continue;
|
|
|
- if (client_would_use_router(rs, now, options)) {
|
|
|
- const char * const digest = rs->descriptor_digest;
|
|
|
- int present;
|
|
|
- ++*num_usable; /* the consensus says we want it. */
|
|
|
- if (md)
|
|
|
- present = NULL != microdesc_cache_lookup_by_digest256(NULL, digest);
|
|
|
- else
|
|
|
- present = NULL != router_get_by_descriptor_digest(digest);
|
|
|
- if (present) {
|
|
|
- /* we have the descriptor listed in the consensus. */
|
|
|
- ++*num_present;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- SMARTLIST_FOREACH_END(rs);
|
|
|
-
|
|
|
- log_debug(LD_DIR, "%d usable, %d present (%s).", *num_usable, *num_present,
|
|
|
- md ? "microdescs" : "descs");
|
|
|
-}
|
|
|
-
|
|
|
-/** We just fetched a new set of descriptors. Compute how far through
|
|
|
- * the "loading descriptors" bootstrapping phase we are, so we can inform
|
|
|
- * the controller of our progress. */
|
|
|
-int
|
|
|
-count_loading_descriptors_progress(void)
|
|
|
-{
|
|
|
- int num_present = 0, num_usable=0;
|
|
|
- time_t now = time(NULL);
|
|
|
- const networkstatus_t *consensus =
|
|
|
- networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor());
|
|
|
- double fraction;
|
|
|
-
|
|
|
- if (!consensus)
|
|
|
- return 0; /* can't count descriptors if we have no list of them */
|
|
|
-
|
|
|
- count_usable_descriptors(&num_present, &num_usable,
|
|
|
- consensus, get_options(), now, NULL, 0);
|
|
|
-
|
|
|
- if (num_usable == 0)
|
|
|
- return 0; /* don't div by 0 */
|
|
|
- fraction = num_present / (num_usable/4.);
|
|
|
- if (fraction > 1.0)
|
|
|
- return 0; /* it's not the number of descriptors holding us back */
|
|
|
- return BOOTSTRAP_STATUS_LOADING_DESCRIPTORS + (int)
|
|
|
- (fraction*(BOOTSTRAP_STATUS_CONN_OR-1 -
|
|
|
- BOOTSTRAP_STATUS_LOADING_DESCRIPTORS));
|
|
|
-}
|
|
|
-
|
|
|
-/** Change the value of have_min_dir_info, setting it true iff we have enough
|
|
|
- * network and router information to build circuits. Clear the value of
|
|
|
- * need_to_update_have_min_dir_info. */
|
|
|
-static void
|
|
|
-update_router_have_minimum_dir_info(void)
|
|
|
-{
|
|
|
- int num_present = 0, num_usable=0;
|
|
|
- int num_exit_present = 0, num_exit_usable = 0;
|
|
|
- time_t now = time(NULL);
|
|
|
- int res;
|
|
|
- const or_options_t *options = get_options();
|
|
|
- const networkstatus_t *consensus =
|
|
|
- networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor());
|
|
|
- int using_md;
|
|
|
-
|
|
|
- if (!consensus) {
|
|
|
- if (!networkstatus_get_latest_consensus())
|
|
|
- strlcpy(dir_info_status, "We have no usable consensus.",
|
|
|
- sizeof(dir_info_status));
|
|
|
- else
|
|
|
- strlcpy(dir_info_status, "We have no recent usable consensus.",
|
|
|
- sizeof(dir_info_status));
|
|
|
- res = 0;
|
|
|
- goto done;
|
|
|
- }
|
|
|
-
|
|
|
- if (should_delay_dir_fetches(get_options())) {
|
|
|
- log_notice(LD_DIR, "no known bridge descriptors running yet; stalling");
|
|
|
- strlcpy(dir_info_status, "No live bridge descriptors.",
|
|
|
- sizeof(dir_info_status));
|
|
|
- res = 0;
|
|
|
- goto done;
|
|
|
- }
|
|
|
-
|
|
|
- using_md = consensus->flavor == FLAV_MICRODESC;
|
|
|
-
|
|
|
- count_usable_descriptors(&num_present, &num_usable, consensus, options, now,
|
|
|
- NULL, 0);
|
|
|
- count_usable_descriptors(&num_exit_present, &num_exit_usable,
|
|
|
- consensus, options, now, options->ExitNodes, 1);
|
|
|
-
|
|
|
-/* What fraction of desired server descriptors do we need before we will
|
|
|
- * build circuits? */
|
|
|
-#define FRAC_USABLE_NEEDED .75
|
|
|
-/* What fraction of desired _exit_ server descriptors do we need before we
|
|
|
- * will build circuits? */
|
|
|
-#define FRAC_EXIT_USABLE_NEEDED .5
|
|
|
-
|
|
|
- if (num_present < num_usable * FRAC_USABLE_NEEDED) {
|
|
|
- tor_snprintf(dir_info_status, sizeof(dir_info_status),
|
|
|
- "We have only %d/%d usable %sdescriptors.",
|
|
|
- num_present, num_usable, using_md ? "micro" : "");
|
|
|
- res = 0;
|
|
|
- control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0);
|
|
|
- goto done;
|
|
|
- } else if (num_present < 2) {
|
|
|
- tor_snprintf(dir_info_status, sizeof(dir_info_status),
|
|
|
- "Only %d %sdescriptor%s here and believed reachable!",
|
|
|
- num_present, using_md ? "micro" : "", num_present ? "" : "s");
|
|
|
- res = 0;
|
|
|
- goto done;
|
|
|
- } else if (num_exit_present < num_exit_usable * FRAC_EXIT_USABLE_NEEDED) {
|
|
|
- tor_snprintf(dir_info_status, sizeof(dir_info_status),
|
|
|
- "We have only %d/%d usable exit node descriptors.",
|
|
|
- num_exit_present, num_exit_usable);
|
|
|
- res = 0;
|
|
|
- control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0);
|
|
|
- goto done;
|
|
|
- }
|
|
|
-
|
|
|
- /* Check for entry nodes. */
|
|
|
- if (options->EntryNodes) {
|
|
|
- count_usable_descriptors(&num_present, &num_usable, consensus, options,
|
|
|
- now, options->EntryNodes, 0);
|
|
|
-
|
|
|
- if (!num_usable || !num_present) {
|
|
|
- tor_snprintf(dir_info_status, sizeof(dir_info_status),
|
|
|
- "We have only %d/%d usable entry node %sdescriptors.",
|
|
|
- num_present, num_usable, using_md?"micro":"");
|
|
|
- res = 0;
|
|
|
- goto done;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- res = 1;
|
|
|
-
|
|
|
- done:
|
|
|
- if (res && !have_min_dir_info) {
|
|
|
- log(LOG_NOTICE, LD_DIR,
|
|
|
- "We now have enough directory information to build circuits.");
|
|
|
- control_event_client_status(LOG_NOTICE, "ENOUGH_DIR_INFO");
|
|
|
- control_event_bootstrap(BOOTSTRAP_STATUS_CONN_OR, 0);
|
|
|
- }
|
|
|
- if (!res && have_min_dir_info) {
|
|
|
- int quiet = directory_too_idle_to_fetch_descriptors(options, now);
|
|
|
- log(quiet ? LOG_INFO : LOG_NOTICE, LD_DIR,
|
|
|
- "Our directory information is no longer up-to-date "
|
|
|
- "enough to build circuits: %s", dir_info_status);
|
|
|
-
|
|
|
- /* a) make us log when we next complete a circuit, so we know when Tor
|
|
|
- * is back up and usable, and b) disable some activities that Tor
|
|
|
- * should only do while circuits are working, like reachability tests
|
|
|
- * and fetching bridge descriptors only over circuits. */
|
|
|
- can_complete_circuit = 0;
|
|
|
-
|
|
|
- control_event_client_status(LOG_NOTICE, "NOT_ENOUGH_DIR_INFO");
|
|
|
- }
|
|
|
- have_min_dir_info = res;
|
|
|
- need_to_update_have_min_dir_info = 0;
|
|
|
-}
|
|
|
-
|
|
|
/** Reset the descriptor download failure count on all routers, so that we
|
|
|
* can retry any long-failed routers immediately.
|
|
|
*/
|