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

📄 router.c

📁 关于tor匿名通信的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
router_pick_published_address(or_options_t *options, uint32_t *addr)
{
  if (resolve_my_address(LOG_INFO, options, addr, NULL) < 0) {
    log_info(LD_CONFIG, "Could not determine our address locally. "
             "Checking if directory headers provide any hints.");
    if (router_guess_address_from_dir_headers(addr) < 0) {
      log_info(LD_CONFIG, "No hints from directory headers either. "
               "Will try again later.");
      return -1;
    }
  }
  return 0;
}

/** If <b>force</b> is true, or our descriptor is out-of-date, rebuild a fresh
 * routerinfo, signed server descriptor, and extra-info document for this OR.
 * Return 0 on success, -1 on temporary error.
 */
int
router_rebuild_descriptor(int force)
{
  routerinfo_t *ri;
  extrainfo_t *ei;
  uint32_t addr;
  char platform[256];
  int hibernating = we_are_hibernating();
  or_options_t *options = get_options();

  if (desc_clean_since && !force)
    return 0;

  if (router_pick_published_address(options, &addr) < 0) {
    /* Stop trying to rebuild our descriptor every second. We'll
     * learn that it's time to try again when server_has_changed_ip()
     * marks it dirty. */
    desc_clean_since = time(NULL);
    return -1;
  }

  ri = tor_malloc_zero(sizeof(routerinfo_t));
  ri->cache_info.routerlist_index = -1;
  ri->address = tor_dup_addr(addr);
  ri->nickname = tor_strdup(options->Nickname);
  ri->addr = addr;
  ri->or_port = options->ORPort;
  ri->dir_port = options->DirPort;
  ri->cache_info.published_on = time(NULL);
  ri->onion_pkey = crypto_pk_dup_key(get_onion_key()); /* must invoke from
                                                        * main thread */
  ri->identity_pkey = crypto_pk_dup_key(get_identity_key());
  if (crypto_pk_get_digest(ri->identity_pkey,
                           ri->cache_info.identity_digest)<0) {
    routerinfo_free(ri);
    return -1;
  }
  get_platform_str(platform, sizeof(platform));
  ri->platform = tor_strdup(platform);

  /* compute ri->bandwidthrate as the min of various options */
  ri->bandwidthrate = (int)options->BandwidthRate;
  if (ri->bandwidthrate > options->MaxAdvertisedBandwidth)
    ri->bandwidthrate = (int)options->MaxAdvertisedBandwidth;
  if (options->RelayBandwidthRate > 0 &&
      ri->bandwidthrate > options->RelayBandwidthRate)
    ri->bandwidthrate = (int)options->RelayBandwidthRate;

  /* and compute ri->bandwidthburst similarly */
  ri->bandwidthburst = (int)options->BandwidthBurst;
  if (options->RelayBandwidthBurst > 0 &&
      ri->bandwidthburst > options->RelayBandwidthBurst)
    ri->bandwidthburst = (int)options->RelayBandwidthBurst;

  ri->bandwidthcapacity = hibernating ? 0 : rep_hist_bandwidth_assess();

  policies_parse_exit_policy(options->ExitPolicy, &ri->exit_policy,
                             options->ExitPolicyRejectPrivate,
                             ri->address);

  if (desc_routerinfo) { /* inherit values */
    ri->is_valid = desc_routerinfo->is_valid;
    ri->is_running = desc_routerinfo->is_running;
    ri->is_named = desc_routerinfo->is_named;
  }
  if (authdir_mode(options))
    ri->is_valid = ri->is_named = 1; /* believe in yourself */
  if (options->MyFamily) {
    smartlist_t *family;
    if (!warned_nonexistent_family)
      warned_nonexistent_family = smartlist_create();
    family = smartlist_create();
    ri->declared_family = smartlist_create();
    smartlist_split_string(family, options->MyFamily, ",",
                           SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    SMARTLIST_FOREACH(family, char *, name,
     {
       routerinfo_t *member;
       if (!strcasecmp(name, options->Nickname))
         member = ri;
       else
         member = router_get_by_nickname(name, 1);
       if (!member) {
         int is_legal = is_legal_nickname_or_hexdigest(name);
         if (!smartlist_string_isin(warned_nonexistent_family, name) &&
             !is_legal_hexdigest(name)) {
           if (is_legal)
             log_warn(LD_CONFIG,
                      "I have no descriptor for the router named \"%s\" in my "
                      "declared family; I'll use the nickname as is, but "
                      "this may confuse clients.", name);
           else
             log_warn(LD_CONFIG, "There is a router named \"%s\" in my "
                      "declared family, but that isn't a legal nickname. "
                      "Skipping it.", escaped(name));
           smartlist_add(warned_nonexistent_family, tor_strdup(name));
         }
         if (is_legal) {
           smartlist_add(ri->declared_family, name);
           name = NULL;
         }
       } else if (router_is_me(member)) {
         /* Don't list ourself in our own family; that's redundant */
       } else {
         char *fp = tor_malloc(HEX_DIGEST_LEN+2);
         fp[0] = '$';
         base16_encode(fp+1,HEX_DIGEST_LEN+1,
                       member->cache_info.identity_digest, DIGEST_LEN);
         smartlist_add(ri->declared_family, fp);
         if (smartlist_string_isin(warned_nonexistent_family, name))
           smartlist_string_remove(warned_nonexistent_family, name);
       }
       tor_free(name);
     });

    /* remove duplicates from the list */
    smartlist_sort_strings(ri->declared_family);
    smartlist_uniq_strings(ri->declared_family);

    smartlist_free(family);
  }

  /* Now generate the extrainfo. */
  ei = tor_malloc_zero(sizeof(extrainfo_t));
  ei->cache_info.is_extrainfo = 1;
  strlcpy(ei->nickname, get_options()->Nickname, sizeof(ei->nickname));
  ei->cache_info.published_on = ri->cache_info.published_on;
  memcpy(ei->cache_info.identity_digest, ri->cache_info.identity_digest,
         DIGEST_LEN);
  ei->cache_info.signed_descriptor_body = tor_malloc(8192);
  if (extrainfo_dump_to_string(ei->cache_info.signed_descriptor_body, 8192,
                               ei, get_identity_key()) < 0) {
    log_warn(LD_BUG, "Couldn't generate extra-info descriptor.");
    extrainfo_free(ei);
    return -1;
  }
  ei->cache_info.signed_descriptor_len =
    strlen(ei->cache_info.signed_descriptor_body);
  router_get_extrainfo_hash(ei->cache_info.signed_descriptor_body,
                            ei->cache_info.signed_descriptor_digest);

  /* Now finish the router descriptor. */
  memcpy(ri->cache_info.extra_info_digest,
         ei->cache_info.signed_descriptor_digest,
         DIGEST_LEN);
  ri->cache_info.signed_descriptor_body = tor_malloc(8192);
  if (router_dump_router_to_string(ri->cache_info.signed_descriptor_body, 8192,
                                   ri, get_identity_key())<0) {
    log_warn(LD_BUG, "Couldn't generate router descriptor.");
    return -1;
  }
  ri->cache_info.signed_descriptor_len =
    strlen(ri->cache_info.signed_descriptor_body);

  ri->purpose =
    options->BridgeRelay ? ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
  if (!options->BridgeRelay) {
    ri->cache_info.send_unencrypted = 1;
    ei->cache_info.send_unencrypted = 1;
  }

  router_get_router_hash(ri->cache_info.signed_descriptor_body,
                         ri->cache_info.signed_descriptor_digest);

  tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei, NULL, NULL));

  if (desc_routerinfo)
    routerinfo_free(desc_routerinfo);
  desc_routerinfo = ri;
  if (desc_extrainfo)
    extrainfo_free(desc_extrainfo);
  desc_extrainfo = ei;

  desc_clean_since = time(NULL);
  desc_needs_upload = 1;
  control_event_my_descriptor_changed();
  return 0;
}

/** Mark descriptor out of date if it's older than <b>when</b> */
void
mark_my_descriptor_dirty_if_older_than(time_t when)
{
  if (desc_clean_since < when)
    mark_my_descriptor_dirty();
}

/** Call when the current descriptor is out of date. */
void
mark_my_descriptor_dirty(void)
{
  desc_clean_since = 0;
}

/** How frequently will we republish our descriptor because of large (factor
 * of 2) shifts in estimated bandwidth? */
#define MAX_BANDWIDTH_CHANGE_FREQ (20*60)

/** Check whether bandwidth has changed a lot since the last time we announced
 * bandwidth. If so, mark our descriptor dirty. */
void
check_descriptor_bandwidth_changed(time_t now)
{
  static time_t last_changed = 0;
  uint64_t prev, cur;
  if (!desc_routerinfo)
    return;

  prev = desc_routerinfo->bandwidthcapacity;
  cur = we_are_hibernating() ? 0 : rep_hist_bandwidth_assess();
  if ((prev != cur && (!prev || !cur)) ||
      cur > prev*2 ||
      cur < prev/2) {
    if (last_changed+MAX_BANDWIDTH_CHANGE_FREQ < now) {
      log_info(LD_GENERAL,
               "Measured bandwidth has changed; rebuilding descriptor.");
      mark_my_descriptor_dirty();
      last_changed = now;
    }
  }
}

/** Note at log level severity that our best guess of address has changed from
 * <b>prev</b> to <b>cur</b>. */
static void
log_addr_has_changed(int severity, uint32_t prev, uint32_t cur)
{
  char addrbuf_prev[INET_NTOA_BUF_LEN];
  char addrbuf_cur[INET_NTOA_BUF_LEN];
  struct in_addr in_prev;
  struct in_addr in_cur;

  in_prev.s_addr = htonl(prev);
  tor_inet_ntoa(&in_prev, addrbuf_prev, sizeof(addrbuf_prev));

  in_cur.s_addr = htonl(cur);
  tor_inet_ntoa(&in_cur, addrbuf_cur, sizeof(addrbuf_cur));

  if (prev)
    log_fn(severity, LD_GENERAL,
           "Our IP Address has changed from %s to %s; "
           "rebuilding descriptor.",
           addrbuf_prev, addrbuf_cur);
  else
    log_notice(LD_GENERAL,
             "Guessed our IP address as %s.",
             addrbuf_cur);
}

/** Check whether our own address as defined by the Address configuration
 * has changed. This is for routers that get their address from a service
 * like dyndns. If our address has changed, mark our descriptor dirty. */
void
check_descriptor_ipaddress_changed(time_t now)
{
  uint32_t prev, cur;
  or_options_t *options = get_options();
  (void) now;

  if (!desc_routerinfo)
    return;

  prev = desc_routerinfo->addr;
  if (resolve_my_address(LOG_INFO, options, &cur, NULL) < 0) {
    log_info(LD_CONFIG,"options->Address didn't resolve into an IP.");
    return;
  }

  if (prev != cur) {
    log_addr_has_changed(LOG_INFO, prev, cur);
    ip_address_changed(0);
  }
}

/** The most recently guessed value of our IP address, based on directory
 * headers. */
static uint32_t last_guessed_ip = 0;

/** A directory server <b>d_conn</b> told us our IP address is
 * <b>suggestion</b>.
 * If this address is different from the one we think we are now, and
 * if our computer doesn't actually know its IP address, then switch. */
void
router_new_address_suggestion(const char *suggestion,
                              const dir_connection_t *d_conn)
{
  uint32_t addr, cur = 0;
  struct in_addr in;
  or_options_t *options = get_options();

  /* first, learn what the IP address actually is */
  if (!tor_inet_aton(suggestion, &in)) {
    log_debug(LD_DIR, "Malformed X-Your-Address-Is header %s. Ignoring.",
              escaped(suggestion));
    return;
  }
  addr = ntohl(in.s_addr);

  log_debug(LD_DIR, "Got X-Your-Address-Is: %s.", suggestion);

  if (!server_mode(options)) {
    last_guessed_ip = addr; /* store it in case we need it later */
    return;
  }

  if (resolve_my_address(LOG_INFO, options, &cur, NULL) >= 0) {
    /* We're all set -- we already know our address. Great. */
    last_guessed_ip = cur; /* store it in case we need it later */
    return;
  }
  if (is_internal_IP(addr, 0)) {
    /* Don't believe anybody who says our IP is, say, 127.0.0.1. */
    return;
  }
  if (addr == d_conn->_base.addr) {
    /* Don't believe anybody who says our IP is their IP. */
    log_debug(LD_DIR, "A directory server told us our IP address is %s, "
              "but he's just reporting his own IP address. Ignoring.",
              suggestion);
    return;
  }

  /* Okay.  We can't resolve our own address, and X-Your-Address-Is is giving
   * us an answer different from what we had the last time we managed to
   * resolve it. */
  if (last_guessed_ip != addr) {
    control_event_server_status(LOG_NOTICE,
                                "EXTERNAL_ADDRESS ADDRESS=%s METHOD=DIRSERV",
                                suggestion);
    log_addr_has_changed(LOG_NOTICE, last_guessed_ip, addr);
    ip_address_changed(0);
    last_guessed_ip = addr; /* router_rebuild_descriptor() will fetch it */
  }
}

/** We failed to resolve our address locally, but we'd like to build
 * a descriptor and publish / test reachability. If we have a guess
 * about our address based on directory headers, answer it and return
 * 0; else return -1. */
static int
router_guess_address_from_dir_headers(uint32_t *guess)
{
  if (last_guessed_ip) {
    *guess = last_guessed_ip;
    return 0;
  }
  return -1;
}

extern const char tor_svn_revision[]; /* from main.c */

/** Set <b>platform</b> (max length <b>len</b>) to a NUL-terminated short
 * string describing the version of Tor and the operating system we're
 * currently running on.
 */
void
get_platform_str(char *platform, size_t len)
{
  tor_snprintf(platform, len, "Tor %s on %s", get_version(), get_uname());
}

/* XXX need to audit this thing and count fenceposts. maybe
 *     refactor so we don't have to keep asking if we're
 *     near the end of maxlen?
 */
#define DEBUG_ROUTER_DUMP_ROUTER_TO_STRING

/** OR only: Given a routerinfo for this router, and an identity key to sign
 * with, encode the routerinfo as a signed server descriptor and write the
 * result into <b>s</b>, using at most <b>maxlen</b> bytes.  Return -1 on
 * failure, and the number of bytes used on success.
 */
int
router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
                             crypto_pk_env_t *ident_key)
{

⌨️ 快捷键说明

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