⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 networkstatus.c

📁 关于tor匿名通信的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      /* This can never be signed enough:  Kill it. */
      if (!was_waiting_for_certs) {
        log_warn(LD_DIR, "Not enough good signatures on networkstatus "
                 "consensus");
        result = -2;
      }
      if (was_waiting_for_certs && (r < -1) && from_cache)
        unlink(unverified_fname);
      goto done;
    }
  }

  /* Are we missing any certificates at all? */
  if (r != 1 && dl_certs)
    authority_certs_fetch_missing(c, now);

  if (control_event_is_interesting(EVENT_NS))
    notify_control_networkstatus_changed(current_consensus, c);

  if (current_consensus) {
    networkstatus_copy_old_consensus_info(c, current_consensus);
    networkstatus_vote_free(current_consensus);
  }

  if (consensus_waiting_for_certs &&
      consensus_waiting_for_certs->valid_after <= c->valid_after) {
    networkstatus_vote_free(consensus_waiting_for_certs);
    consensus_waiting_for_certs = NULL;
    if (consensus != consensus_waiting_for_certs_body)
      tor_free(consensus_waiting_for_certs_body);
    else
      consensus_waiting_for_certs_body = NULL;
    consensus_waiting_for_certs_set_at = 0;
    consensus_waiting_for_certs_dl_failed = 0;
    unlink(unverified_fname);
  }

  /* Reset the failure count only if this consensus is actually valid. */
  if (c->valid_after <= now && now <= c->valid_until) {
    download_status_reset(&consensus_dl_status);
  } else {
    if (!from_cache)
      download_status_failed(&consensus_dl_status, 0);
  }

  current_consensus = c;
  c = NULL; /* Prevent free. */

  update_consensus_networkstatus_fetch_time(now);
  dirvote_recalculate_timing(get_options(), now);
  routerstatus_list_update_named_server_map();

  if (!from_cache) {
    write_str_to_file(consensus_fname, consensus, 0);
  }

  if (directory_caches_dir_info(get_options()))
    dirserv_set_cached_networkstatus_v3(consensus,
                                        current_consensus->valid_after);

  if (ftime_definitely_before(now, current_consensus->valid_after)) {
    char tbuf[ISO_TIME_LEN+1];
    char dbuf[64];
    long delta = now - current_consensus->valid_after;
    format_iso_time(tbuf, current_consensus->valid_after);
    format_time_interval(dbuf, sizeof(dbuf), delta);
    log_warn(LD_GENERAL, "Our clock is %s behind the time published in the "
             "consensus network status document (%s GMT).  Tor needs an "
             "accurate clock to work correctly. Please check your time and "
             "date settings!", dbuf, tbuf);
    control_event_general_status(LOG_WARN,
                    "CLOCK_SKEW MIN_SKEW=%ld SOURCE=CONSENSUS", delta);
  }

  router_dir_info_changed();

  result = 0;
 done:
  if (c)
    networkstatus_vote_free(c);
  tor_free(consensus_fname);
  tor_free(unverified_fname);
  return result;
}

/** Called when we have gotten more certificates: see whether we can
 * now verify a pending consensus. */
void
networkstatus_note_certs_arrived(void)
{
  if (consensus_waiting_for_certs) {
    if (networkstatus_check_consensus_signature(
                                    consensus_waiting_for_certs, 0)>=0) {
      if (!networkstatus_set_current_consensus(
                                 consensus_waiting_for_certs_body,
                                 NSSET_WAS_WAITING_FOR_CERTS)) {
        tor_free(consensus_waiting_for_certs_body);
      }
    }
  }
}

/** If the network-status list has changed since the last time we called this
 * function, update the status of every routerinfo from the network-status
 * list. If <b>dir_version</b> is 2, it's a v2 networkstatus that changed.
 * If <b>dir_version</b> is 3, it's a v3 consensus that changed.
 */
void
routers_update_all_from_networkstatus(time_t now, int dir_version)
{
  routerinfo_t *me;
  routerlist_t *rl = router_get_routerlist();
  networkstatus_t *consensus = networkstatus_get_live_consensus(now);
  or_options_t *options = get_options();

  if (networkstatus_v2_list_has_changed)
    download_status_map_update_from_v2_networkstatus();

  if (!consensus || dir_version < 3) /* nothing more we should do */
    return;

  /* More routers may be up or down now: we need to recalc whether there's
   * enough directory info. */
  router_dir_info_changed();

  routers_update_status_from_consensus_networkstatus(rl->routers, 0);
  SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri,
                    ri->cache_info.routerlist_index = ri_sl_idx);
  if (rl->old_routers)
    signed_descs_update_status_from_consensus_networkstatus(rl->old_routers);

  /* XXX020 these warnings don't help anymore; we should disable them -RD */
  me = router_get_my_routerinfo();
  if (me && !have_warned_about_invalid_status) {
    routerstatus_t *rs = networkstatus_vote_find_entry(consensus,
                                        me->cache_info.identity_digest);

    if (!rs) {
      log_info(LD_GENERAL, "The latest consensus does not list us."
               "Are you misconfigured?");
      have_warned_about_invalid_status = 1;
    } else if (rs->is_unnamed) {
      /* Maybe upgrade this to notice? XXXX020 */
      log_info(LD_GENERAL,  "The directory have assigned the nickname "
               "you're using (%s) to a different identity; you may want to "
               "choose a different nickname.", options->Nickname);
      have_warned_about_invalid_status = 1;
    } else if (!rs->is_named) {
      log_debug(LD_GENERAL, "The directory authorities do not currently "
                "recognize your nickname.");
      have_warned_about_invalid_status = 1;
    }
  }

  if (!have_warned_about_old_version) {
    int is_server = server_mode(get_options());
    version_status_t status;
    const char *recommended = is_server ?
      consensus->server_versions : consensus->client_versions;
    status = tor_version_is_obsolete(VERSION, recommended);

    if (status == VS_RECOMMENDED) {
      log_info(LD_GENERAL, "The directory authorities say my version is ok.");
    } else if (status == VS_EMPTY) {
      log_info(LD_GENERAL,
               "The directory authorities don't recommend any versions.");
    } else if (status == VS_NEW || status == VS_NEW_IN_SERIES) {
      if (!have_warned_about_new_version) {
        log_notice(LD_GENERAL, "This version of Tor (%s) is newer than any "
                   "recommended version%s, according to the directory "
                   "authorities. Recommended versions are: %s",
                   VERSION,
                   status == VS_NEW_IN_SERIES ? " in its series" : "",
                   recommended);
        have_warned_about_new_version = 1;
        control_event_general_status(LOG_WARN, "DANGEROUS_VERSION "
                                     "CURRENT=%s REASON=%s RECOMMENDED=\"%s\"",
                                     VERSION, "NEW", recommended);
      }
    } else {
      log_warn(LD_GENERAL, "Please upgrade! "
               "This version of Tor (%s) is %s, according to the directory "
               "authorities. Recommended versions are: %s",
               VERSION,
               status == VS_OLD ? "obsolete" : "not recommended",
               recommended);
      have_warned_about_old_version = 1;
      control_event_general_status(LOG_WARN, "DANGEROUS_VERSION "
           "CURRENT=%s REASON=%s RECOMMENDED=\"%s\"",
           VERSION, status == VS_OLD ? "OBSOLETE" : "UNRECOMMENDED",
           recommended);
    }
  }
}

/** Update v2_download_status_map to contain an entry for every router
 * descriptor listed in the v2 networkstatuses. */
static void
download_status_map_update_from_v2_networkstatus(void)
{
  digestmap_t *dl_status;
  if (!networkstatus_v2_list)
    return;
  if (!v2_download_status_map)
    v2_download_status_map = digestmap_new();

  dl_status = digestmap_new();
  SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
  {
    SMARTLIST_FOREACH(ns->entries, routerstatus_t *, rs,
    {
      const char *d = rs->descriptor_digest;
      download_status_t *s;
      if (digestmap_get(dl_status, d))
        continue;
      if (!(s = digestmap_remove(v2_download_status_map, d))) {
        s = tor_malloc_zero(sizeof(download_status_t));
      }
      digestmap_set(dl_status, d, s);
    });
  });
  digestmap_free(v2_download_status_map, _tor_free);
  v2_download_status_map = dl_status;
  networkstatus_v2_list_has_changed = 0;
}

/** Update our view of the list of named servers from the most recently
 * retrieved networkstatus consensus. */
static void
routerstatus_list_update_named_server_map(void)
{
  if (!current_consensus)
    return;

  if (named_server_map)
    strmap_free(named_server_map, _tor_free);
  named_server_map = strmap_new();
  if (unnamed_server_map)
    strmap_free(unnamed_server_map, NULL);
  unnamed_server_map = strmap_new();
  SMARTLIST_FOREACH(current_consensus->routerstatus_list, routerstatus_t *, rs,
    {
      if (rs->is_named) {
        strmap_set_lc(named_server_map, rs->nickname,
                      tor_memdup(rs->identity_digest, DIGEST_LEN));
      }
      if (rs->is_unnamed) {
        strmap_set_lc(unnamed_server_map, rs->nickname, (void*)1);
      }
    });
}

/** Given a list <b>routers</b> of routerinfo_t *, update each status field
 * according to our current consensus networkstatus.  May re-order
 * <b>routers</b>. */
void
routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
                                                   int reset_failures)
{
  trusted_dir_server_t *ds;
  or_options_t *options = get_options();
  int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
  int namingdir = authdir && options->NamingAuthoritativeDir;
  networkstatus_t *ns = current_consensus;
  if (!ns || !smartlist_len(ns->routerstatus_list))
    return;
  if (!networkstatus_v2_list)
    networkstatus_v2_list = smartlist_create();

  routers_sort_by_identity(routers);

  SMARTLIST_FOREACH_JOIN(ns->routerstatus_list, routerstatus_t *, rs,
                         routers, routerinfo_t *, router,
                         memcmp(rs->identity_digest,
                               router->cache_info.identity_digest, DIGEST_LEN),
  {
    /* We have no routerstatus for this router. Clear flags and skip it. */
    if (!namingdir)
      router->is_named = 0;
    if (!authdir) {
      if (router->purpose == ROUTER_PURPOSE_GENERAL)
        router_clear_status_flags(router);
    }
  }) {
    /* We have a routerstatus for this router. */
    const char *digest = router->cache_info.identity_digest;

    ds = router_get_trusteddirserver_by_digest(digest);

    if (!namingdir) {
      if (rs->is_named && !strcasecmp(router->nickname, rs->nickname))
        router->is_named = 1;
      else
        router->is_named = 0;
    }
    /* Is it the same descriptor, or only the same identity? */
    if (!memcmp(router->cache_info.signed_descriptor_digest,
                rs->descriptor_digest, DIGEST_LEN)) {
      if (ns->valid_until > router->cache_info.last_listed_as_valid_until)
        router->cache_info.last_listed_as_valid_until = ns->valid_until;
    }

    if (!authdir) {
      /* If we're not an authdir, believe others. */
      router->is_valid = rs->is_valid;
      router->is_running = rs->is_running;
      router->is_fast = rs->is_fast;
      router->is_stable = rs->is_stable;
      router->is_possible_guard = rs->is_possible_guard;
      router->is_exit = rs->is_exit;
      router->is_bad_directory = rs->is_bad_directory;
      router->is_bad_exit = rs->is_bad_exit;
      router->is_hs_dir = rs->is_hs_dir;
    }
    if (router->is_running && ds) {
      download_status_reset(&ds->v2_ns_dl_status);
    }
    if (reset_failures) {
      download_status_reset(&rs->dl_status);
    }
  } SMARTLIST_FOREACH_JOIN_END(rs, router);

  /* Now update last_listed_as_valid_until from v2 networkstatuses. */
  /* XXXX021 If this is slow, we need to rethink the code. */
  SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, {
    time_t live_until = ns->published_on + V2_NETWORKSTATUS_LIFETIME;
    SMARTLIST_FOREACH_JOIN(ns->entries, routerstatus_t *, rs,
                         routers, routerinfo_t *, ri,
                         memcmp(rs->identity_digest,
                                ri->cache_info.identity_digest, DIGEST_LEN),
                         STMT_NIL) {
      if (!memcmp(ri->cache_info.signed_descriptor_digest,
                  rs->descriptor_digest, DIGEST_LEN)) {
        if (live_until > ri->cache_info.last_listed_as_valid_until)
          ri->cache_info.last_listed_as_valid_until = live_until;
      }
    } SMARTLIST_FOREACH_JOIN_END(rs, ri);
  });

  router_dir_info_changed();
}

/** Given a list of signed_descriptor_t, update their fields (mainly, when
 * they were last listed) from the most recent consensus. */
void
signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs)
{
  networkstatus_t *ns = current_consensus;
  if (!ns)
    return;

  if (!ns->desc_digest_map) {
    char dummy[DIGEST_LEN];
    /* instantiates the digest map. */
    memset(dummy, 0, sizeof(dummy));
  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -