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

📄 router.c

📁 关于tor匿名通信的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  origin_circuit_t *circ = NULL;

  log_notice(LD_OR,"Performing bandwidth self-test...done.");
  while ((circ = circuit_get_next_by_pk_and_purpose(circ, NULL,
                                              CIRCUIT_PURPOSE_TESTING))) {
    /* dump cells_per_circuit drop cells onto this circ */
    int i = cells_per_circuit;
    if (circ->_base.state != CIRCUIT_STATE_OPEN)
      continue;
    circ->_base.timestamp_dirty = now;
    while (i-- > 0) {
      if (relay_send_command_from_edge(0, TO_CIRCUIT(circ),
                                       RELAY_COMMAND_DROP,
                                       NULL, 0, circ->cpath->prev)<0) {
        return; /* stop if error */
      }
    }
  }
}

/** Return true iff we believe ourselves to be an authoritative
 * directory server.
 */
int
authdir_mode(or_options_t *options)
{
  return options->AuthoritativeDir != 0;
}
/** Return true iff we believe ourselves to be a v1 authoritative
 * directory server.
 */
int
authdir_mode_v1(or_options_t *options)
{
  return authdir_mode(options) && options->V1AuthoritativeDir != 0;
}
/** Return true iff we believe ourselves to be a v2 authoritative
 * directory server.
 */
int
authdir_mode_v2(or_options_t *options)
{
  return authdir_mode(options) && options->V2AuthoritativeDir != 0;
}
/** Return true iff we believe ourselves to be a v3 authoritative
 * directory server.
 */
int
authdir_mode_v3(or_options_t *options)
{
  return authdir_mode(options) && options->V3AuthoritativeDir != 0;
}
/** Return true iff we are a v1, v2, or v3 directory authority. */
int
authdir_mode_any_main(or_options_t *options)
{
  return options->V1AuthoritativeDir ||
         options->V2AuthoritativeDir ||
         options->V3AuthoritativeDir;
}
/** Return true if we believe ourselves to be any kind of
 * authoritative directory beyond just a hidserv authority. */
int
authdir_mode_any_nonhidserv(or_options_t *options)
{
  return options->BridgeAuthoritativeDir ||
         authdir_mode_any_main(options);
}
/** Return true iff we are an authoritative directory server that is
 * authoritative about receiving and serving descriptors of type
 * <b>purpose</b> its dirport.  Use -1 for "any purpose". */
int
authdir_mode_handles_descs(or_options_t *options, int purpose)
{
  if (purpose < 0)
    return authdir_mode_any_nonhidserv(options);
  else if (purpose == ROUTER_PURPOSE_GENERAL)
    return authdir_mode_any_main(options);
  else if (purpose == ROUTER_PURPOSE_BRIDGE)
    return (options->BridgeAuthoritativeDir);
  else
    return 0;
}
/** Return true iff we are an authoritative directory server that
 * publishes its own network statuses.
 */
int
authdir_mode_publishes_statuses(or_options_t *options)
{
  if (authdir_mode_bridge(options))
    return 0;
  return authdir_mode_any_nonhidserv(options);
}
/** Return true iff we are an authoritative directory server that
 * tests reachability of the descriptors it learns about.
 */
int
authdir_mode_tests_reachability(or_options_t *options)
{
  return authdir_mode_handles_descs(options, -1);
}
/** Return true iff we believe ourselves to be a bridge authoritative
 * directory server.
 */
int
authdir_mode_bridge(or_options_t *options)
{
  return authdir_mode(options) && options->BridgeAuthoritativeDir != 0;
}
/** Return true iff we once tried to stay connected to all ORs at once.
 * FFFF this function, and the notion of staying connected to ORs, is
 * nearly obsolete. One day there will be a proposal for getting rid of
 * it.
 */
int
clique_mode(or_options_t *options)
{
  return authdir_mode_tests_reachability(options);
}

/** Return true iff we are trying to be a server.
 */
int
server_mode(or_options_t *options)
{
  if (options->ClientOnly) return 0;
  return (options->ORPort != 0 || options->ORListenAddress);
}

/** Remember if we've advertised ourselves to the dirservers. */
static int server_is_advertised=0;

/** Return true iff we have published our descriptor lately.
 */
int
advertised_server_mode(void)
{
  return server_is_advertised;
}

/**
 * Called with a boolean: set whether we have recently published our
 * descriptor.
 */
static void
set_server_advertised(int s)
{
  server_is_advertised = s;
}

/** Return true iff we are trying to be a socks proxy. */
int
proxy_mode(or_options_t *options)
{
  return (options->SocksPort != 0 || options->SocksListenAddress ||
          options->TransPort != 0 || options->TransListenAddress ||
          options->NatdPort != 0 || options->NatdListenAddress ||
          options->DNSPort != 0 || options->DNSListenAddress);
}

/** Decide if we're a publishable server. We are a publishable server if:
 * - We don't have the ClientOnly option set
 * and
 * - We have the PublishServerDescriptor option set to non-empty
 * and
 * - We have ORPort set
 * and
 * - We believe we are reachable from the outside; or
 * - We are an authoritative directory server.
 */
static int
decide_if_publishable_server(void)
{
  or_options_t *options = get_options();

  if (options->ClientOnly)
    return 0;
  if (options->_PublishServerDescriptor == NO_AUTHORITY)
    return 0;
  if (!server_mode(options))
    return 0;
  if (authdir_mode(options))
    return 1;

  return check_whether_orport_reachable();
}

/** Initiate server descriptor upload as reasonable (if server is publishable,
 * etc).  <b>force</b> is as for router_upload_dir_desc_to_dirservers.
 *
 * We need to rebuild the descriptor if it's dirty even if we're not
 * uploading, because our reachability testing *uses* our descriptor to
 * determine what IP address and ports to test.
 */
void
consider_publishable_server(int force)
{
  int rebuilt;

  if (!server_mode(get_options()))
    return;

  rebuilt = router_rebuild_descriptor(0);
  if (decide_if_publishable_server()) {
    set_server_advertised(1);
    if (rebuilt == 0)
      router_upload_dir_desc_to_dirservers(force);
  } else {
    set_server_advertised(0);
  }
}

/*
 * Clique maintenance -- to be phased out.
 */

/** Return true iff we believe this OR tries to keep connections open
 * to all other ORs. */
int
router_is_clique_mode(routerinfo_t *router)
{
  if (router_digest_is_trusted_dir(router->cache_info.identity_digest))
    return 1;
  return 0;
}

/*
 * OR descriptor generation.
 */

/** My routerinfo. */
static routerinfo_t *desc_routerinfo = NULL;
/** My extrainfo */
static extrainfo_t *desc_extrainfo = NULL;
/** Since when has our descriptor been "clean"?  0 if we need to regenerate it
 * now. */
static time_t desc_clean_since = 0;
/** Boolean: do we need to regenerate the above? */
static int desc_needs_upload = 0;

/** OR only: If <b>force</b> is true, or we haven't uploaded this
 * descriptor successfully yet, try to upload our signed descriptor to
 * all the directory servers we know about.
 */
void
router_upload_dir_desc_to_dirservers(int force)
{
  routerinfo_t *ri;
  extrainfo_t *ei;
  char *msg;
  size_t desc_len, extra_len = 0, total_len;
  authority_type_t auth = get_options()->_PublishServerDescriptor;

  ri = router_get_my_routerinfo();
  if (!ri) {
    log_info(LD_GENERAL, "No descriptor; skipping upload");
    return;
  }
  ei = router_get_my_extrainfo();
  if (auth == NO_AUTHORITY)
    return;
  if (!force && !desc_needs_upload)
    return;
  desc_needs_upload = 0;

  desc_len = ri->cache_info.signed_descriptor_len;
  extra_len = ei ? ei->cache_info.signed_descriptor_len : 0;
  total_len = desc_len + extra_len + 1;
  msg = tor_malloc(total_len);
  memcpy(msg, ri->cache_info.signed_descriptor_body, desc_len);
  if (ei) {
    memcpy(msg+desc_len, ei->cache_info.signed_descriptor_body, extra_len);
  }
  msg[desc_len+extra_len] = 0;

  directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_DIR,
                               (auth & BRIDGE_AUTHORITY) ?
                                 ROUTER_PURPOSE_BRIDGE :
                                 ROUTER_PURPOSE_GENERAL,
                               auth, msg, desc_len, extra_len);
  tor_free(msg);
}

/** OR only: Check whether my exit policy says to allow connection to
 * conn.  Return 0 if we accept; non-0 if we reject.
 */
int
router_compare_to_my_exit_policy(edge_connection_t *conn)
{
  if (!router_get_my_routerinfo()) /* make sure desc_routerinfo exists */
    return -1;

  /* make sure it's resolved to something. this way we can't get a
     'maybe' below. */
  if (!conn->_base.addr)
    return -1;

  return compare_addr_to_addr_policy(conn->_base.addr, conn->_base.port,
                   desc_routerinfo->exit_policy) != ADDR_POLICY_ACCEPTED;
}

/** Return true iff I'm a server and <b>digest</b> is equal to
 * my identity digest. */
int
router_digest_is_me(const char *digest)
{
  return identitykey && !memcmp(identitykey_digest, digest, DIGEST_LEN);
}

/** Return true iff I'm a server and <b>digest</b> is equal to
 * my identity digest. */
int
router_extrainfo_digest_is_me(const char *digest)
{
  extrainfo_t *ei = router_get_my_extrainfo();
  if (!ei)
    return 0;

  return !memcmp(digest,
                 ei->cache_info.signed_descriptor_digest,
                 DIGEST_LEN);
}

/** A wrapper around router_digest_is_me(). */
int
router_is_me(routerinfo_t *router)
{
  return router_digest_is_me(router->cache_info.identity_digest);
}

/** Return true iff <b>fp</b> is a hex fingerprint of my identity digest. */
int
router_fingerprint_is_me(const char *fp)
{
  char digest[DIGEST_LEN];
  if (strlen(fp) == HEX_DIGEST_LEN &&
      base16_decode(digest, sizeof(digest), fp, HEX_DIGEST_LEN) == 0)
    return router_digest_is_me(digest);

  return 0;
}

/** Return a routerinfo for this OR, rebuilding a fresh one if
 * necessary.  Return NULL on error, or if called on an OP. */
routerinfo_t *
router_get_my_routerinfo(void)
{
  if (!server_mode(get_options()))
    return NULL;
  if (router_rebuild_descriptor(0))
    return NULL;
  return desc_routerinfo;
}

/** OR only: Return a signed server descriptor for this OR, rebuilding a fresh
 * one if necessary.  Return NULL on error.
 */
const char *
router_get_my_descriptor(void)
{
  const char *body;
  if (!router_get_my_routerinfo())
    return NULL;
  /* Make sure this is nul-terminated. */
  tor_assert(desc_routerinfo->cache_info.saved_location == SAVED_NOWHERE);
  body = signed_descriptor_get_body(&desc_routerinfo->cache_info);
  tor_assert(!body[desc_routerinfo->cache_info.signed_descriptor_len]);
  log_debug(LD_GENERAL,"my desc is '%s'", body);
  return body;
}

/* Return the extrainfo document for this OR, or NULL if we have none.
 * Rebuilt it (and the server descriptor) if necessary. */
extrainfo_t *
router_get_my_extrainfo(void)
{
  if (!server_mode(get_options()))
    return NULL;
  if (router_rebuild_descriptor(0))
    return NULL;
  return desc_extrainfo;
}

/** A list of nicknames that we've warned about including in our family
 * declaration verbatim rather than as digests. */
static smartlist_t *warned_nonexistent_family = NULL;

static int router_guess_address_from_dir_headers(uint32_t *guess);

/** Make a current best guess at our address, either because
 * it's configured in torrc, or because we've learned it from
 * dirserver headers. Place the answer in *<b>addr</b> and return
 * 0 on success, else return -1 if we have no guess. */
int

⌨️ 快捷键说明

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