Back to index

tor  0.2.3.18-rc
Defines | Functions
router.h File Reference

Header file for router.c. More...

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define NODE_DESC_BUF_LEN   (MAX_VERBOSE_NICKNAME_LEN+4+TOR_ADDR_BUF_LEN)
 Longest allowed output of format_node_description, plus 1 character for NUL.

Functions

crypto_pk_tget_onion_key (void)
 Return the current onion key.
time_t get_onion_key_set_at (void)
 Return the time when the onion key was last set.
void set_server_identity_key (crypto_pk_t *k)
 Set the current server identity key to k.
crypto_pk_tget_server_identity_key (void)
 Returns the current server identity key; requires that the key has been set, and that we are running as a Tor server.
int server_identity_key_is_set (void)
 Return true iff the server identity key has been set.
void set_client_identity_key (crypto_pk_t *k)
 Set the current client identity key to k.
crypto_pk_tget_tlsclient_identity_key (void)
 Returns the current client identity key for use on outgoing TLS connections; requires that the key has been set.
int client_identity_key_is_set (void)
 Return true iff the client identity key has been set.
authority_cert_tget_my_v3_authority_cert (void)
 Return the key certificate for this v3 (voting) authority, or NULL if we have no such certificate.
crypto_pk_tget_my_v3_authority_signing_key (void)
 Return the v3 signing key for this v3 (voting) authority, or NULL if we have no such key.
authority_cert_tget_my_v3_legacy_cert (void)
 If we're an authority, and we're using a legacy authority identity key for emergency migration purposes, return the certificate associated with that key.
crypto_pk_tget_my_v3_legacy_signing_key (void)
 If we're an authority, and we're using a legacy authority identity key for emergency migration purposes, return that key.
void dup_onion_keys (crypto_pk_t **key, crypto_pk_t **last)
 Store a full copy of the current onion key into *key, and a full copy of the most recent onion key into *last.
void rotate_onion_key (void)
 Replace the previous onion key with the current onion key, and generate a new previous onion key.
crypto_pk_tinit_key_from_file (const char *fname, int generate, int severity)
 Try to read an RSA key from fname.
void v3_authority_check_key_expiry (void)
 If we're a v3 authority, check whether we have a certificate that's likely to expire soon.
int router_initialize_tls_context (void)
 Set up Tor's TLS contexts, based on our configuration and keys.
int init_keys (void)
 Initialize all OR private keys, and the TLS context, as necessary.
int check_whether_orport_reachable (void)
 Return 1 if ORPort is known reachable; else return 0.
int check_whether_dirport_reachable (void)
 Return 1 if we don't have a dirport configured, or if it's reachable.
void consider_testing_reachability (int test_or, int test_dir)
 Some time has passed, or we just got new directory information.
void router_orport_found_reachable (void)
 Annotate that we found our ORPort reachable.
void router_dirport_found_reachable (void)
 Annotate that we found our DirPort reachable.
void router_perform_bandwidth_test (int num_circs, time_t now)
 We have enough testing circuits open.
int net_is_disabled (void)
 Return true iff our network is in some sense disabled: either we're hibernating, entering hibernation, or.
int authdir_mode (const or_options_t *options)
 Return true iff we believe ourselves to be an authoritative directory server.
int authdir_mode_v1 (const or_options_t *options)
 Return true iff we believe ourselves to be a v1 authoritative directory server.
int authdir_mode_v2 (const or_options_t *options)
 Return true iff we believe ourselves to be a v2 authoritative directory server.
int authdir_mode_v3 (const or_options_t *options)
 Return true iff we believe ourselves to be a v3 authoritative directory server.
int authdir_mode_any_main (const or_options_t *options)
 Return true iff we are a v1, v2, or v3 directory authority.
int authdir_mode_any_nonhidserv (const or_options_t *options)
 Return true if we believe ourselves to be any kind of authoritative directory beyond just a hidserv authority.
int authdir_mode_handles_descs (const or_options_t *options, int purpose)
 Return true iff we are an authoritative directory server that is authoritative about receiving and serving descriptors of type purpose on its dirport.
int authdir_mode_publishes_statuses (const or_options_t *options)
 Return true iff we are an authoritative directory server that publishes its own network statuses.
int authdir_mode_tests_reachability (const or_options_t *options)
 Return true iff we are an authoritative directory server that tests reachability of the descriptors it learns about.
int authdir_mode_bridge (const or_options_t *options)
 Return true iff we believe ourselves to be a bridge authoritative directory server.
uint16_t router_get_active_listener_port_by_type (int listener_type)
 Return the port of the first active listener of type listener_type.
uint16_t router_get_advertised_or_port (const or_options_t *options)
 Return the port that we should advertise as our ORPort; this is either the one configured in the ORPort option, or the one we actually bound to if ORPort is "auto".
uint16_t router_get_advertised_dir_port (const or_options_t *options, uint16_t dirport)
 Return the port that we should advertise as our DirPort; this is one of three possibilities: The one that is passed as dirport if the DirPort option is 0, or the one configured in the DirPort option, or the one we actually bound to if DirPort is "auto".
int server_mode (const or_options_t *options)
 Return true iff we are trying to be a server.
int public_server_mode (const or_options_t *options)
 Return true iff we are trying to be a non-bridge server.
int advertised_server_mode (void)
 Return true iff we have published our descriptor lately.
int proxy_mode (const or_options_t *options)
 Return true iff we are trying to proxy client connections.
void consider_publishable_server (int force)
 Initiate server descriptor upload as reasonable (if server is publishable, etc).
int should_refuse_unknown_exits (const or_options_t *options)
 Return true iff the combination of options in options and parameters in the consensus mean that we don't want to allow exits from circuits we got from addresses not known to be servers.
void router_upload_dir_desc_to_dirservers (int force)
 OR only: If force 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 mark_my_descriptor_dirty_if_too_old (time_t now)
 Mark descriptor out of date if it's been "too long" since we last tried to upload one.
void mark_my_descriptor_dirty (const char *reason)
 Call when the current descriptor is out of date.
void check_descriptor_bandwidth_changed (time_t now)
 Check whether bandwidth has changed a lot since the last time we announced bandwidth.
void check_descriptor_ipaddress_changed (time_t now)
 Check whether our own address as defined by the Address configuration has changed.
void router_new_address_suggestion (const char *suggestion, const dir_connection_t *d_conn)
 A directory server d_conn told us our IP address is suggestion.
int router_compare_to_my_exit_policy (edge_connection_t *conn)
 OR only: Check whether my exit policy says to allow connection to conn.
int router_my_exit_policy_is_reject_star (void)
 Return true iff my exit policy is reject *:*.
const routerinfo_trouter_get_my_routerinfo (void)
 Return a routerinfo for this OR, rebuilding a fresh one if necessary.
extrainfo_trouter_get_my_extrainfo (void)
 Return the extrainfo document for this OR, or NULL if we have none.
const char * router_get_my_descriptor (void)
 OR only: Return a signed server descriptor for this OR, rebuilding a fresh one if necessary.
const char * router_get_descriptor_gen_reason (void)
 Return a human-readable string describing what triggered us to generate our current descriptor, or NULL if we don't know.
int router_digest_is_me (const char *digest)
 Return true iff I'm a server and digest is equal to my server identity key digest.
int router_extrainfo_digest_is_me (const char *digest)
 Return true iff I'm a server and digest is equal to my identity digest.
int router_is_me (const routerinfo_t *router)
 A wrapper around router_digest_is_me().
int router_fingerprint_is_me (const char *fp)
 Return true iff fp is a hex fingerprint of my identity digest.
int router_pick_published_address (const or_options_t *options, uint32_t *addr)
 Make a current best guess at our address, either because it's configured in torrc, or because we've learned it from dirserver headers.
int router_rebuild_descriptor (int force)
 If force is true, or our descriptor is out-of-date, rebuild a fresh routerinfo, signed server descriptor, and extra-info document for this OR.
int router_dump_router_to_string (char *s, size_t maxlen, routerinfo_t *router, crypto_pk_t *ident_key)
 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 s, using at most maxlen bytes.
void router_get_prim_orport (const routerinfo_t *router, tor_addr_port_t *addr_port_out)
 Copy the primary (IPv4) OR port (IP address and TCP port) for router into *ap_out.
void router_get_pref_orport (const routerinfo_t *router, tor_addr_port_t *addr_port_out)
 Copy the preferred OR port (IP address and TCP port) for router into *addr_out.
void router_get_pref_ipv6_orport (const routerinfo_t *router, tor_addr_port_t *addr_port_out)
 Copy the preferred IPv6 OR port (IP address and TCP port) for router into *ap_out.
int router_ipv6_preferred (const routerinfo_t *router)
 Return 1 if we prefer the IPv6 address and OR TCP port of router, else 0.
int extrainfo_dump_to_string (char **s, extrainfo_t *extrainfo, crypto_pk_t *ident_key)
 Write the contents of extrainfo and aggregated statistics to *s_out, signing them with ident_key.
int is_legal_nickname (const char *s)
 Return true iff s is a legally valid server nickname.
int is_legal_nickname_or_hexdigest (const char *s)
 Return true iff s is a legally valid server nickname or hex-encoded identity-key digest.
int is_legal_hexdigest (const char *s)
 Return true iff s is a legally valid hex-encoded identity-key digest.
const char * format_node_description (char *buf, const char *id_digest, int is_named, const char *nickname, const tor_addr_t *addr, uint32_t addr32h)
 Use buf (which must be at least NODE_DESC_BUF_LEN bytes long) to hold a human-readable description of a node with identity digest id_digest, named-status is_named, nickname nickname, and address addr or addr32h.
const char * router_get_description (char *buf, const routerinfo_t *ri)
 Use buf (which must be at least NODE_DESC_BUF_LEN bytes long) to hold a human-readable description of ri.
const char * node_get_description (char *buf, const node_t *node)
 Use buf (which must be at least NODE_DESC_BUF_LEN bytes long) to hold a human-readable description of node.
const char * routerstatus_get_description (char *buf, const routerstatus_t *rs)
 Use buf (which must be at least NODE_DESC_BUF_LEN bytes long) to hold a human-readable description of rs.
const char * extend_info_get_description (char *buf, const extend_info_t *ei)
 Use buf (which must be at least NODE_DESC_BUF_LEN bytes long) to hold a human-readable description of ei.
const char * router_describe (const routerinfo_t *ri)
 Return a human-readable description of the routerinfo_t ri.
const char * node_describe (const node_t *node)
 Return a human-readable description of the node_t node.
const char * routerstatus_describe (const routerstatus_t *ri)
 Return a human-readable description of the routerstatus_t rs.
const char * extend_info_describe (const extend_info_t *ei)
 Return a human-readable description of the extend_info_t ri.
void router_get_verbose_nickname (char *buf, const routerinfo_t *router)
 Set buf (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the verbose representation of the identity of router.
void routerstatus_get_verbose_nickname (char *buf, const routerstatus_t *router)
 Set buf (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the verbose representation of the identity of router.
void router_reset_warnings (void)
 Forget that we have issued any router-related warnings, so that we'll warn again if we see the same errors.
void router_reset_reachability (void)
 Forget what we have learned about our reachability status.
void router_free_all (void)
 Release all static resources held in router.c.
const char * router_purpose_to_string (uint8_t p)
 Given a router purpose, convert it to a string.
uint8_t router_purpose_from_string (const char *s)
 Given a string, convert it to a router purpose.

Detailed Description

Header file for router.c.

Definition in file router.h.


Define Documentation

Longest allowed output of format_node_description, plus 1 character for NUL.

This allows space for: "$FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF~xxxxxxxxxxxxxxxxxxx at" " [ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]" plus a terminating NUL.

Definition at line 109 of file router.h.


Function Documentation

int advertised_server_mode ( void  )

Return true iff we have published our descriptor lately.

Definition at line 1149 of file router.c.

Here is the caller graph for this function:

int authdir_mode ( const or_options_t options)

Return true iff we believe ourselves to be an authoritative directory server.

Definition at line 1026 of file router.c.

{
  return options->AuthoritativeDir != 0;
}

Here is the caller graph for this function:

int authdir_mode_any_main ( const or_options_t options)

Return true iff we are a v1, v2, or v3 directory authority.

Definition at line 1056 of file router.c.

{
  return options->V1AuthoritativeDir ||
         options->V2AuthoritativeDir ||
         options->V3AuthoritativeDir;
}

Here is the caller graph for this function:

int authdir_mode_any_nonhidserv ( const or_options_t options)

Return true if we believe ourselves to be any kind of authoritative directory beyond just a hidserv authority.

Definition at line 1065 of file router.c.

{
  return options->BridgeAuthoritativeDir ||
         authdir_mode_any_main(options);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int authdir_mode_bridge ( const or_options_t options)

Return true iff we believe ourselves to be a bridge authoritative directory server.

Definition at line 1107 of file router.c.

{
  return authdir_mode(options) && options->BridgeAuthoritativeDir != 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int authdir_mode_handles_descs ( const or_options_t options,
int  purpose 
)

Return true iff we are an authoritative directory server that is authoritative about receiving and serving descriptors of type purpose on its dirport.

Use -1 for "any purpose".

Definition at line 1074 of file router.c.

{
  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return true iff we are an authoritative directory server that publishes its own network statuses.

Definition at line 1089 of file router.c.

{
  if (authdir_mode_bridge(options))
    return 0;
  return authdir_mode_any_nonhidserv(options);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return true iff we are an authoritative directory server that tests reachability of the descriptors it learns about.

Definition at line 1099 of file router.c.

{
  return authdir_mode_handles_descs(options, -1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int authdir_mode_v1 ( const or_options_t options)

Return true iff we believe ourselves to be a v1 authoritative directory server.

Definition at line 1034 of file router.c.

{
  return authdir_mode(options) && options->V1AuthoritativeDir != 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int authdir_mode_v2 ( const or_options_t options)

Return true iff we believe ourselves to be a v2 authoritative directory server.

Definition at line 1042 of file router.c.

{
  return authdir_mode(options) && options->V2AuthoritativeDir != 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int authdir_mode_v3 ( const or_options_t options)

Return true iff we believe ourselves to be a v3 authoritative directory server.

Definition at line 1050 of file router.c.

{
  return authdir_mode(options) && options->V3AuthoritativeDir != 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void check_descriptor_bandwidth_changed ( time_t  now)

Check whether bandwidth has changed a lot since the last time we announced bandwidth.

If so, mark our descriptor dirty.

Definition at line 1795 of file router.c.

{
  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("bandwidth has changed");
      last_changed = now;
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void check_descriptor_ipaddress_changed ( time_t  now)

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.

Definition at line 1847 of file router.c.

{
  uint32_t prev, cur;
  const or_options_t *options = get_options();
  (void) now;

  if (!desc_routerinfo)
    return;

  /* XXXX ipv6 */
  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) {
    tor_addr_t tmp_prev, tmp_cur;
    tor_addr_from_ipv4h(&tmp_prev, prev);
    tor_addr_from_ipv4h(&tmp_cur, cur);
    log_addr_has_changed(LOG_NOTICE, &tmp_prev, &tmp_cur, "resolve");
    ip_address_changed(0);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return 1 if we don't have a dirport configured, or if it's reachable.

Definition at line 797 of file router.c.

{
  const or_options_t *options = get_options();
  return !options->DirPort ||
         options->AssumeReachable ||
         net_is_disabled() ||
         can_reach_dir_port;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return 1 if ORPort is known reachable; else return 0.

Definition at line 788 of file router.c.

{
  const or_options_t *options = get_options();
  return options->AssumeReachable ||
         can_reach_or_port;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return true iff the client identity key has been set.

Definition at line 205 of file router.c.

{
  return client_identitykey != NULL;
}

Here is the caller graph for this function:

void consider_publishable_server ( int  force)

Initiate server descriptor upload as reasonable (if server is publishable, etc).

force 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.

Definition at line 1216 of file router.c.

{
  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);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void consider_testing_reachability ( int  test_or,
int  test_dir 
)

Some time has passed, or we just got new directory information.

See if we currently believe our ORPort or DirPort to be unreachable. If so, launch a new test for it.

For ORPort, we simply try making a circuit that ends at ourselves. Success is noticed in onionskin_answer().

For DirPort, we make a connection via Tor to our DirPort and ask for our own server descriptor. Success is noticed in connection_dir_client_reached_eof().

Definition at line 894 of file router.c.

{
  const routerinfo_t *me = router_get_my_routerinfo();
  int orport_reachable = check_whether_orport_reachable();
  tor_addr_t addr;
  const or_options_t *options = get_options();
  if (!me)
    return;

  if (routerset_contains_router(options->ExcludeNodes, me, -1) &&
      options->StrictNodes) {
    /* If we've excluded ourself, and StrictNodes is set, we can't test
     * ourself. */
    if (test_or || test_dir) {
#define SELF_EXCLUDED_WARN_INTERVAL 3600
      static ratelim_t warning_limit=RATELIM_INIT(SELF_EXCLUDED_WARN_INTERVAL);
      char *msg;
      if ((msg = rate_limit_log(&warning_limit, approx_time()))) {
        log_warn(LD_CIRC, "Can't peform self-tests for this relay: we have "
                 "listed ourself in ExcludeNodes, and StrictNodes is set. "
                 "We cannot learn whether we are usable, and will not "
                 "be able to advertise ourself.%s", msg);
        tor_free(msg);
      }
    }
    return;
  }

  if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) {
    extend_info_t *ei;
    log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
             !orport_reachable ? "reachability" : "bandwidth",
             me->address, me->or_port);
    /* XXX IPv6 self testing IPv6 orports will need pref_addr */
    ei = extend_info_from_router(me, 0);
    circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
                            CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
    extend_info_free(ei);
  }

  tor_addr_from_ipv4h(&addr, me->addr);
  if (test_dir && !check_whether_dirport_reachable() &&
      !connection_get_by_type_addr_port_purpose(
                CONN_TYPE_DIR, &addr, me->dir_port,
                DIR_PURPOSE_FETCH_SERVERDESC)) {
    /* ask myself, via tor, for my server descriptor. */
    directory_initiate_command(me->address, &addr,
                               me->or_port, me->dir_port,
                               0, /* does not matter */
                               0, me->cache_info.identity_digest,
                               DIR_PURPOSE_FETCH_SERVERDESC,
                               ROUTER_PURPOSE_GENERAL,
                               1, "authority.z", NULL, 0, 0);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void dup_onion_keys ( crypto_pk_t **  key,
crypto_pk_t **  last 
)

Store a full copy of the current onion key into *key, and a full copy of the most recent onion key into *last.

Definition at line 112 of file router.c.

Here is the call graph for this function:

Here is the caller graph for this function:

const char* extend_info_describe ( const extend_info_t ei)

Return a human-readable description of the extend_info_t ri.

This function is not thread-safe. Each call to this function invalidates previous values returned by this function.

Definition at line 2647 of file router.c.

{
  static char buf[NODE_DESC_BUF_LEN];
  return extend_info_get_description(buf, ei);
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* extend_info_get_description ( char *  buf,
const extend_info_t ei 
)

Use buf (which must be at least NODE_DESC_BUF_LEN bytes long) to hold a human-readable description of ei.

Return a pointer to the front of buf.

Definition at line 2593 of file router.c.

{
  if (!ei)
    return "<null>";
  return format_node_description(buf,
                                 ei->identity_digest,
                                 0,
                                 ei->nickname,
                                 &ei->addr,
                                 0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int extrainfo_dump_to_string ( char **  s_out,
extrainfo_t extrainfo,
crypto_pk_t ident_key 
)

Write the contents of extrainfo and aggregated statistics to *s_out, signing them with ident_key.

Return 0 on success, negative on failure.

Definition at line 2287 of file router.c.

{
  const or_options_t *options = get_options();
  char identity[HEX_DIGEST_LEN+1];
  char published[ISO_TIME_LEN+1];
  char digest[DIGEST_LEN];
  char *bandwidth_usage;
  int result;
  static int write_stats_to_extrainfo = 1;
  char sig[DIROBJ_MAX_SIG_LEN+1];
  char *s, *pre, *contents, *cp, *s_dup = NULL;
  time_t now = time(NULL);
  smartlist_t *chunks = smartlist_new();
  extrainfo_t *ei_tmp = NULL;

  base16_encode(identity, sizeof(identity),
                extrainfo->cache_info.identity_digest, DIGEST_LEN);
  format_iso_time(published, extrainfo->cache_info.published_on);
  bandwidth_usage = rep_hist_get_bandwidth_lines();

  tor_asprintf(&pre, "extra-info %s %s\npublished %s\n%s",
               extrainfo->nickname, identity,
               published, bandwidth_usage);
  tor_free(bandwidth_usage);
  smartlist_add(chunks, pre);

  if (geoip_is_loaded()) {
    smartlist_add_asprintf(chunks, "geoip-db-digest %s\n", geoip_db_digest());
  }

  if (options->ExtraInfoStatistics && write_stats_to_extrainfo) {
    log_info(LD_GENERAL, "Adding stats to extra-info descriptor.");
    if (options->DirReqStatistics &&
        load_stats_file("stats"PATH_SEPARATOR"dirreq-stats",
                        "dirreq-stats-end", now, &contents) > 0) {
      smartlist_add(chunks, contents);
    }
    if (options->EntryStatistics &&
        load_stats_file("stats"PATH_SEPARATOR"entry-stats",
                        "entry-stats-end", now, &contents) > 0) {
      smartlist_add(chunks, contents);
    }
    if (options->CellStatistics &&
        load_stats_file("stats"PATH_SEPARATOR"buffer-stats",
                        "cell-stats-end", now, &contents) > 0) {
      smartlist_add(chunks, contents);
    }
    if (options->ExitPortStatistics &&
        load_stats_file("stats"PATH_SEPARATOR"exit-stats",
                        "exit-stats-end", now, &contents) > 0) {
      smartlist_add(chunks, contents);
    }
    if (options->ConnDirectionStatistics &&
        load_stats_file("stats"PATH_SEPARATOR"conn-stats",
                        "conn-bi-direct", now, &contents) > 0) {
      smartlist_add(chunks, contents);
    }
  }

  if (should_record_bridge_info(options) && write_stats_to_extrainfo) {
    const char *bridge_stats = geoip_get_bridge_stats_extrainfo(now);
    if (bridge_stats) {
      smartlist_add(chunks, tor_strdup(bridge_stats));
    }
  }

  smartlist_add(chunks, tor_strdup("router-signature\n"));
  s = smartlist_join_strings(chunks, "", 0, NULL);

  while (strlen(s) > MAX_EXTRAINFO_UPLOAD_SIZE - DIROBJ_MAX_SIG_LEN) {
    /* So long as there are at least two chunks (one for the initial
     * extra-info line and one for the router-signature), we can keep removing
     * things. */
    if (smartlist_len(chunks) > 2) {
      /* We remove the next-to-last element (remember, len-1 is the last
         element), since we need to keep the router-signature element. */
      int idx = smartlist_len(chunks) - 2;
      char *e = smartlist_get(chunks, idx);
      smartlist_del_keeporder(chunks, idx);
      log_warn(LD_GENERAL, "We just generated an extra-info descriptor "
                           "with statistics that exceeds the 50 KB "
                           "upload limit. Removing last added "
                           "statistics.");
      tor_free(e);
      tor_free(s);
      s = smartlist_join_strings(chunks, "", 0, NULL);
    } else {
      log_warn(LD_BUG, "We just generated an extra-info descriptors that "
                       "exceeds the 50 KB upload limit.");
      goto err;
    }
  }

  memset(sig, 0, sizeof(sig));
  if (router_get_extrainfo_hash(s, strlen(s), digest) < 0 ||
      router_append_dirobj_signature(sig, sizeof(sig), digest, DIGEST_LEN,
                                     ident_key) < 0) {
    log_warn(LD_BUG, "Could not append signature to extra-info "
                     "descriptor.");
    goto err;
  }
  smartlist_add(chunks, tor_strdup(sig));
  tor_free(s);
  s = smartlist_join_strings(chunks, "", 0, NULL);

  cp = s_dup = tor_strdup(s);
  ei_tmp = extrainfo_parse_entry_from_string(cp, NULL, 1, NULL);
  if (!ei_tmp) {
    if (write_stats_to_extrainfo) {
      log_warn(LD_GENERAL, "We just generated an extra-info descriptor "
                           "with statistics that we can't parse. Not "
                           "adding statistics to this or any future "
                           "extra-info descriptors.");
      write_stats_to_extrainfo = 0;
      result = extrainfo_dump_to_string(s_out, extrainfo, ident_key);
      goto done;
    } else {
      log_warn(LD_BUG, "We just generated an extrainfo descriptor we "
                       "can't parse.");
      goto err;
    }
  }

  *s_out = s;
  s = NULL; /* prevent free */
  result = 0;
  goto done;

 err:
  result = -1;

 done:
  tor_free(s);
  SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
  smartlist_free(chunks);
  tor_free(s_dup);
  extrainfo_free(ei_tmp);

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* format_node_description ( char *  buf,
const char *  id_digest,
int  is_named,
const char *  nickname,
const tor_addr_t addr,
uint32_t  addr32h 
)

Use buf (which must be at least NODE_DESC_BUF_LEN bytes long) to hold a human-readable description of a node with identity digest id_digest, named-status is_named, nickname nickname, and address addr or addr32h.

The nickname and addr fields are optional and may be set to NULL. The addr32h field is optional and may be set to 0.

Return a pointer to the front of buf.

Definition at line 2484 of file router.c.

{
  char *cp;

  if (!buf)
    return "<NULL BUFFER>";

  buf[0] = '$';
  base16_encode(buf+1, HEX_DIGEST_LEN+1, id_digest, DIGEST_LEN);
  cp = buf+1+HEX_DIGEST_LEN;
  if (nickname) {
    buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
    strlcpy(buf+1+HEX_DIGEST_LEN+1, nickname, MAX_NICKNAME_LEN+1);
    cp += strlen(cp);
  }
  if (addr32h || addr) {
    memcpy(cp, " at ", 4);
    cp += 4;
    if (addr) {
      tor_addr_to_str(cp, addr, TOR_ADDR_BUF_LEN, 0);
    } else {
      struct in_addr in;
      in.s_addr = htonl(addr32h);
      tor_inet_ntoa(&in, cp, INET_NTOA_BUF_LEN);
    }
  }
  return buf;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return the key certificate for this v3 (voting) authority, or NULL if we have no such certificate.

Definition at line 213 of file router.c.

Here is the caller graph for this function:

Return the v3 signing key for this v3 (voting) authority, or NULL if we have no such key.

Definition at line 221 of file router.c.

Here is the caller graph for this function:

If we're an authority, and we're using a legacy authority identity key for emergency migration purposes, return the certificate associated with that key.

Definition at line 230 of file router.c.

Here is the caller graph for this function:

If we're an authority, and we're using a legacy authority identity key for emergency migration purposes, return that key.

Definition at line 238 of file router.c.

{
  return legacy_signing_key;
}

Here is the caller graph for this function:

Return the current onion key.

Requires that the onion key has been loaded or generated.

Definition at line 102 of file router.c.

Here is the caller graph for this function:

time_t get_onion_key_set_at ( void  )

Return the time when the onion key was last set.

This is either the time when the process launched, or the time of the most recent key rotation since the process launched.

Definition at line 131 of file router.c.

{
  return onionkey_set_at;
}

Here is the caller graph for this function:

Returns the current server identity key; requires that the key has been set, and that we are running as a Tor server.

Definition at line 168 of file router.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Returns the current client identity key for use on outgoing TLS connections; requires that the key has been set.

Definition at line 196 of file router.c.

Here is the call graph for this function:

Here is the caller graph for this function:

crypto_pk_t* init_key_from_file ( const char *  fname,
int  generate,
int  severity 
)

Try to read an RSA key from fname.

If fname doesn't exist and generate is true, create a new RSA key and save it in fname. Return the read/created key, or NULL on error. Log all errors at level severity.

Definition at line 301 of file router.c.

{
  crypto_pk_t *prkey = NULL;

  if (!(prkey = crypto_pk_new())) {
    log(severity, LD_GENERAL,"Error constructing key");
    goto error;
  }

  switch (file_status(fname)) {
    case FN_DIR:
    case FN_ERROR:
      log(severity, LD_FS,"Can't read key from \"%s\"", fname);
      goto error;
    case FN_NOENT:
      if (generate) {
        if (!have_lockfile()) {
          if (try_locking(get_options(), 0)<0) {
            /* Make sure that --list-fingerprint only creates new keys
             * if there is no possibility for a deadlock. */
            log(severity, LD_FS, "Another Tor process has locked \"%s\". Not "
                "writing any new keys.", fname);
            /*XXXX The 'other process' might make a key in a second or two;
             * maybe we should wait for it. */
            goto error;
          }
        }
        log_info(LD_GENERAL, "No key found in \"%s\"; generating fresh key.",
                 fname);
        if (crypto_pk_generate_key(prkey)) {
          log(severity, LD_GENERAL,"Error generating onion key");
          goto error;
        }
        if (crypto_pk_check_key(prkey) <= 0) {
          log(severity, LD_GENERAL,"Generated key seems invalid");
          goto error;
        }
        log_info(LD_GENERAL, "Generated key seems valid");
        if (crypto_pk_write_private_key_to_filename(prkey, fname)) {
          log(severity, LD_FS,
              "Couldn't write generated key to \"%s\".", fname);
          goto error;
        }
      } else {
        log_info(LD_GENERAL, "No key found in \"%s\"", fname);
      }
      return prkey;
    case FN_FILE:
      if (crypto_pk_read_private_key_from_filename(prkey, fname)) {
        log(severity, LD_GENERAL,"Error loading private key.");
        goto error;
      }
      return prkey;
    default:
      tor_assert(0);
  }

 error:
  if (prkey)
    crypto_pk_free(prkey);
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int init_keys ( void  )

Initialize all OR private keys, and the TLS context, as necessary.

On OPs, this only initializes the tls context. Return 0 on success, or -1 if Tor should die.

Definition at line 504 of file router.c.

{
  char *keydir;
  char fingerprint[FINGERPRINT_LEN+1];
  /*nickname<space>fp\n\0 */
  char fingerprint_line[MAX_NICKNAME_LEN+FINGERPRINT_LEN+3];
  const char *mydesc;
  crypto_pk_t *prkey;
  char digest[DIGEST_LEN];
  char v3_digest[DIGEST_LEN];
  char *cp;
  const or_options_t *options = get_options();
  dirinfo_type_t type;
  time_t now = time(NULL);
  trusted_dir_server_t *ds;
  int v3_digest_set = 0;
  authority_cert_t *cert = NULL;

  if (!key_lock)
    key_lock = tor_mutex_new();

  /* There are a couple of paths that put us here before we've asked
   * openssl to initialize itself. */
  if (crypto_global_init(get_options()->HardwareAccel,
                         get_options()->AccelName,
                         get_options()->AccelDir)) {
    log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting.");
    return -1;
  }

  /* OP's don't need persistent keys; just make up an identity and
   * initialize the TLS context. */
  if (!server_mode(options)) {
    if (!(prkey = crypto_pk_new()))
      return -1;
    if (crypto_pk_generate_key(prkey)) {
      crypto_pk_free(prkey);
      return -1;
    }
    set_client_identity_key(prkey);
    /* Create a TLS context. */
    if (router_initialize_tls_context() < 0) {
      log_err(LD_GENERAL,"Error creating TLS context for Tor client.");
      return -1;
    }
    return 0;
  }
  /* Make sure DataDirectory exists, and is private. */
  if (check_private_dir(options->DataDirectory, CPD_CREATE, options->User)) {
    return -1;
  }
  /* Check the key directory. */
  keydir = get_datadir_fname("keys");
  if (check_private_dir(keydir, CPD_CREATE, options->User)) {
    tor_free(keydir);
    return -1;
  }
  tor_free(keydir);

  /* 1a. Read v3 directory authority key/cert information. */
  memset(v3_digest, 0, sizeof(v3_digest));
  if (authdir_mode_v3(options)) {
    if (init_v3_authority_keys()<0) {
      log_err(LD_GENERAL, "We're configured as a V3 authority, but we "
              "were unable to load our v3 authority keys and certificate! "
              "Use tor-gencert to generate them. Dying.");
      return -1;
    }
    cert = get_my_v3_authority_cert();
    if (cert) {
      crypto_pk_get_digest(get_my_v3_authority_cert()->identity_key,
                           v3_digest);
      v3_digest_set = 1;
    }
  }

  /* 1b. Read identity key. Make it if none is found. */
  keydir = get_datadir_fname2("keys", "secret_id_key");
  log_info(LD_GENERAL,"Reading/making identity key \"%s\"...",keydir);
  prkey = init_key_from_file(keydir, 1, LOG_ERR);
  tor_free(keydir);
  if (!prkey) return -1;
  set_server_identity_key(prkey);

  /* 1c. If we are configured as a bridge, generate a client key;
   * otherwise, set the server identity key as our client identity
   * key. */
  if (public_server_mode(options)) {
    set_client_identity_key(crypto_pk_dup_key(prkey)); /* set above */
  } else {
    if (!(prkey = crypto_pk_new()))
      return -1;
    if (crypto_pk_generate_key(prkey)) {
      crypto_pk_free(prkey);
      return -1;
    }
    set_client_identity_key(prkey);
  }

  /* 2. Read onion key.  Make it if none is found. */
  keydir = get_datadir_fname2("keys", "secret_onion_key");
  log_info(LD_GENERAL,"Reading/making onion key \"%s\"...",keydir);
  prkey = init_key_from_file(keydir, 1, LOG_ERR);
  tor_free(keydir);
  if (!prkey) return -1;
  set_onion_key(prkey);
  if (options->command == CMD_RUN_TOR) {
    /* only mess with the state file if we're actually running Tor */
    or_state_t *state = get_or_state();
    if (state->LastRotatedOnionKey > 100 && state->LastRotatedOnionKey < now) {
      /* We allow for some parsing slop, but we don't want to risk accepting
       * values in the distant future.  If we did, we might never rotate the
       * onion key. */
      onionkey_set_at = state->LastRotatedOnionKey;
    } else {
      /* We have no LastRotatedOnionKey set; either we just created the key
       * or it's a holdover from 0.1.2.4-alpha-dev or earlier.  In either case,
       * start the clock ticking now so that we will eventually rotate it even
       * if we don't stay up for a full MIN_ONION_KEY_LIFETIME. */
      state->LastRotatedOnionKey = onionkey_set_at = now;
      or_state_mark_dirty(state, options->AvoidDiskWrites ?
                                   time(NULL)+3600 : 0);
    }
  }

  keydir = get_datadir_fname2("keys", "secret_onion_key.old");
  if (!lastonionkey && file_status(keydir) == FN_FILE) {
    prkey = init_key_from_file(keydir, 1, LOG_ERR);
    if (prkey)
      lastonionkey = prkey;
  }
  tor_free(keydir);

  /* 3. Initialize link key and TLS context. */
  if (router_initialize_tls_context() < 0) {
    log_err(LD_GENERAL,"Error initializing TLS context");
    return -1;
  }

  /* 4. Build our router descriptor. */
  /* Must be called after keys are initialized. */
  mydesc = router_get_my_descriptor();
  if (authdir_mode_handles_descs(options, ROUTER_PURPOSE_GENERAL)) {
    const char *m = NULL;
    routerinfo_t *ri;
    /* We need to add our own fingerprint so it gets recognized. */
    if (dirserv_add_own_fingerprint(options->Nickname,
                                    get_server_identity_key())) {
      log_err(LD_GENERAL,"Error adding own fingerprint to approved set");
      return -1;
    }
    if (mydesc) {
      was_router_added_t added;
      ri = router_parse_entry_from_string(mydesc, NULL, 1, 0, NULL);
      if (!ri) {
        log_err(LD_GENERAL,"Generated a routerinfo we couldn't parse.");
        return -1;
      }
      added = dirserv_add_descriptor(ri, &m, "self");
      if (!WRA_WAS_ADDED(added)) {
        if (!WRA_WAS_OUTDATED(added)) {
          log_err(LD_GENERAL, "Unable to add own descriptor to directory: %s",
                  m?m:"<unknown error>");
          return -1;
        } else {
          /* If the descriptor was outdated, that's ok. This can happen
           * when some config options are toggled that affect workers, but
           * we don't really need new keys yet so the descriptor doesn't
           * change and the old one is still fresh. */
          log_info(LD_GENERAL, "Couldn't add own descriptor to directory "
                   "after key init: %s. This is usually not a problem.",
                   m?m:"<unknown error>");
        }
      }
    }
  }

  /* 5. Dump fingerprint to 'fingerprint' */
  keydir = get_datadir_fname("fingerprint");
  log_info(LD_GENERAL,"Dumping fingerprint to \"%s\"...",keydir);
  if (crypto_pk_get_fingerprint(get_server_identity_key(),
                                fingerprint, 0) < 0) {
    log_err(LD_GENERAL,"Error computing fingerprint");
    tor_free(keydir);
    return -1;
  }
  tor_assert(strlen(options->Nickname) <= MAX_NICKNAME_LEN);
  if (tor_snprintf(fingerprint_line, sizeof(fingerprint_line),
                   "%s %s\n",options->Nickname, fingerprint) < 0) {
    log_err(LD_GENERAL,"Error writing fingerprint line");
    tor_free(keydir);
    return -1;
  }
  /* Check whether we need to write the fingerprint file. */
  cp = NULL;
  if (file_status(keydir) == FN_FILE)
    cp = read_file_to_str(keydir, 0, NULL);
  if (!cp || strcmp(cp, fingerprint_line)) {
    if (write_str_to_file(keydir, fingerprint_line, 0)) {
      log_err(LD_FS, "Error writing fingerprint line to file");
      tor_free(keydir);
      tor_free(cp);
      return -1;
    }
  }
  tor_free(cp);
  tor_free(keydir);

  log(LOG_NOTICE, LD_GENERAL,
      "Your Tor server's identity key fingerprint is '%s %s'",
      options->Nickname, fingerprint);
  if (!authdir_mode(options))
    return 0;
  /* 6. [authdirserver only] load approved-routers file */
  if (dirserv_load_fingerprint_file() < 0) {
    log_err(LD_GENERAL,"Error loading fingerprints");
    return -1;
  }
  /* 6b. [authdirserver only] add own key to approved directories. */
  crypto_pk_get_digest(get_server_identity_key(), digest);
  type = ((options->V1AuthoritativeDir ? V1_DIRINFO : NO_DIRINFO) |
          (options->V2AuthoritativeDir ? V2_DIRINFO : NO_DIRINFO) |
          (options->V3AuthoritativeDir ?
               (V3_DIRINFO|MICRODESC_DIRINFO|EXTRAINFO_DIRINFO) : NO_DIRINFO) |
          (options->BridgeAuthoritativeDir ? BRIDGE_DIRINFO : NO_DIRINFO) |
          (options->HSAuthoritativeDir ? HIDSERV_DIRINFO : NO_DIRINFO));

  ds = router_get_trusteddirserver_by_digest(digest);
  if (!ds) {
    ds = add_trusted_dir_server(options->Nickname, NULL,
                                router_get_advertised_dir_port(options, 0),
                                router_get_advertised_or_port(options),
                                digest,
                                v3_digest,
                                type);
    if (!ds) {
      log_err(LD_GENERAL,"We want to be a directory authority, but we "
              "couldn't add ourselves to the authority list. Failing.");
      return -1;
    }
  }
  if (ds->type != type) {
    log_warn(LD_DIR,  "Configured authority type does not match authority "
             "type in DirServer list.  Adjusting. (%d v %d)",
             type, ds->type);
    ds->type = type;
  }
  if (v3_digest_set && (ds->type & V3_DIRINFO) &&
      tor_memneq(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) {
    log_warn(LD_DIR, "V3 identity key does not match identity declared in "
             "DirServer line.  Adjusting.");
    memcpy(ds->v3_identity_digest, v3_digest, DIGEST_LEN);
  }

  if (cert) { /* add my own cert to the list of known certs */
    log_info(LD_DIR, "adding my own v3 cert");
    if (trusted_dirs_load_certs_from_string(
                      cert->cache_info.signed_descriptor_body, 0, 0)<0) {
      log_warn(LD_DIR, "Unable to parse my own v3 cert! Failing.");
      return -1;
    }
  }

  return 0; /* success */
}

Here is the call graph for this function:

Here is the caller graph for this function:

int is_legal_hexdigest ( const char *  s)

Return true iff s is a legally valid hex-encoded identity-key digest.

Definition at line 2454 of file router.c.

{
  size_t len;
  tor_assert(s);
  if (s[0] == '$') s++;
  len = strlen(s);
  if (len > HEX_DIGEST_LEN) {
    if (s[HEX_DIGEST_LEN] == '=' ||
        s[HEX_DIGEST_LEN] == '~') {
      if (!is_legal_nickname(s+HEX_DIGEST_LEN+1))
        return 0;
    } else {
      return 0;
    }
  }
  return (len >= HEX_DIGEST_LEN &&
          strspn(s,HEX_CHARACTERS)==HEX_DIGEST_LEN);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int is_legal_nickname ( const char *  s)

Return true iff s is a legally valid server nickname.

Definition at line 2431 of file router.c.

{
  size_t len;
  tor_assert(s);
  len = strlen(s);
  return len > 0 && len <= MAX_NICKNAME_LEN &&
    strspn(s,LEGAL_NICKNAME_CHARACTERS) == len;
}

Here is the caller graph for this function:

int is_legal_nickname_or_hexdigest ( const char *  s)

Return true iff s is a legally valid server nickname or hex-encoded identity-key digest.

Definition at line 2443 of file router.c.

{
  if (*s!='$')
    return is_legal_nickname(s);
  else
    return is_legal_hexdigest(s);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void mark_my_descriptor_dirty ( const char *  reason)

Call when the current descriptor is out of date.

Definition at line 1778 of file router.c.

{
  const or_options_t *options = get_options();
  if (server_mode(options) && options->_PublishServerDescriptor)
    log_info(LD_OR, "Decided to publish new relay descriptor: %s", reason);
  desc_clean_since = 0;
  if (!desc_dirty_reason)
    desc_dirty_reason = reason;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Mark descriptor out of date if it's been "too long" since we last tried to upload one.

Definition at line 1741 of file router.c.

{
  networkstatus_t *ns;
  const routerstatus_t *rs;
  const char *retry_fast_reason = NULL; /* Set if we should retry frequently */
  const time_t slow_cutoff = now - FORCE_REGENERATE_DESCRIPTOR_INTERVAL;
  const time_t fast_cutoff = now - FAST_RETRY_DESCRIPTOR_INTERVAL;

  /* If it's already dirty, don't mark it. */
  if (! desc_clean_since)
    return;

  /* If it's older than FORCE_REGENERATE_DESCRIPTOR_INTERVAL, it's always
   * time to rebuild it. */
  if (desc_clean_since < slow_cutoff) {
    mark_my_descriptor_dirty("time for new descriptor");
    return;
  }
  /* Now we see whether we want to be retrying frequently or no.  The
   * rule here is that we'll retry frequently if we aren't listed in the
   * live consensus we have, or if the publication time of the
   * descriptor listed for us in the consensus is very old. */
  ns = networkstatus_get_live_consensus(now);
  if (ns) {
    rs = networkstatus_vote_find_entry(ns, server_identitykey_digest);
    if (rs == NULL)
      retry_fast_reason = "not listed in consensus";
    else if (rs->published_on < slow_cutoff)
      retry_fast_reason = "version listed in consensus is quite old";
  }

  if (retry_fast_reason && desc_clean_since < fast_cutoff)
    mark_my_descriptor_dirty(retry_fast_reason);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int net_is_disabled ( void  )

Return true iff our network is in some sense disabled: either we're hibernating, entering hibernation, or.

Definition at line 1017 of file router.c.

Here is the call graph for this function:

Here is the caller graph for this function:

const char* node_describe ( const node_t node)

Return a human-readable description of the node_t node.

This function is not thread-safe. Each call to this function invalidates previous values returned by this function.

Definition at line 2623 of file router.c.

{
  static char buf[NODE_DESC_BUF_LEN];
  return node_get_description(buf, node);
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* node_get_description ( char *  buf,
const node_t node 
)

Use buf (which must be at least NODE_DESC_BUF_LEN bytes long) to hold a human-readable description of node.

Return a pointer to the front of buf.

Definition at line 2543 of file router.c.

{
  const char *nickname = NULL;
  uint32_t addr32h = 0;
  int is_named = 0;

  if (!node)
    return "<null>";

  if (node->rs) {
    nickname = node->rs->nickname;
    is_named = node->rs->is_named;
    addr32h = node->rs->addr;
  } else if (node->ri) {
    nickname = node->ri->nickname;
    addr32h = node->ri->addr;
  }

  return format_node_description(buf,
                                 node->identity,
                                 is_named,
                                 nickname,
                                 NULL,
                                 addr32h);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int proxy_mode ( const or_options_t options)

Return true iff we are trying to proxy client connections.

Definition at line 1166 of file router.c.

{
  (void)options;
  SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) {
    if (p->type == CONN_TYPE_AP_LISTENER ||
        p->type == CONN_TYPE_AP_TRANS_LISTENER ||
        p->type == CONN_TYPE_AP_DNS_LISTENER ||
        p->type == CONN_TYPE_AP_NATD_LISTENER)
      return 1;
  } SMARTLIST_FOREACH_END(p);
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int public_server_mode ( const or_options_t options)

Return true iff we are trying to be a non-bridge server.

Definition at line 1124 of file router.c.

{
  if (!server_mode(options)) return 0;
  return (!options->BridgeRelay);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void rotate_onion_key ( void  )

Replace the previous onion key with the current onion key, and generate a new previous onion key.

Immediately after calling this function, the OR should:

  • schedule all previous cpuworkers to shut down after processing pending work. (This will cause fresh cpuworkers to be generated.)
  • generate and upload a fresh routerinfo.

Definition at line 251 of file router.c.

{
  char *fname, *fname_prev;
  crypto_pk_t *prkey;
  or_state_t *state = get_or_state();
  time_t now;
  fname = get_datadir_fname2("keys", "secret_onion_key");
  fname_prev = get_datadir_fname2("keys", "secret_onion_key.old");
  if (!(prkey = crypto_pk_new())) {
    log_err(LD_GENERAL,"Error constructing rotated onion key");
    goto error;
  }
  if (crypto_pk_generate_key(prkey)) {
    log_err(LD_BUG,"Error generating onion key");
    goto error;
  }
  if (file_status(fname) == FN_FILE) {
    if (replace_file(fname, fname_prev))
      goto error;
  }
  if (crypto_pk_write_private_key_to_filename(prkey, fname)) {
    log_err(LD_FS,"Couldn't write generated onion key to \"%s\".", fname);
    goto error;
  }
  log_info(LD_GENERAL, "Rotating onion key");
  tor_mutex_acquire(key_lock);
  crypto_pk_free(lastonionkey);
  lastonionkey = onionkey;
  onionkey = prkey;
  now = time(NULL);
  state->LastRotatedOnionKey = onionkey_set_at = now;
  tor_mutex_release(key_lock);
  mark_my_descriptor_dirty("rotated onion key");
  or_state_mark_dirty(state, get_options()->AvoidDiskWrites ? now+3600 : 0);
  goto done;
 error:
  log_warn(LD_GENERAL, "Couldn't rotate onion key.");
  if (prkey)
    crypto_pk_free(prkey);
 done:
  tor_free(fname);
  tor_free(fname_prev);
}

Here is the call graph for this function:

Here is the caller graph for this function:

OR only: Check whether my exit policy says to allow connection to conn.

Return 0 if we accept; non-0 if we reject.

Definition at line 1357 of file router.c.

{
  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 (tor_addr_is_null(&conn->_base.addr))
    return -1;

  /* XXXX IPv6 */
  if (tor_addr_family(&conn->_base.addr) != AF_INET)
    return -1;

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

Here is the call graph for this function:

Here is the caller graph for this function:

const char* router_describe ( const routerinfo_t ri)

Return a human-readable description of the routerinfo_t ri.

This function is not thread-safe. Each call to this function invalidates previous values returned by this function.

Definition at line 2611 of file router.c.

{
  static char buf[NODE_DESC_BUF_LEN];
  return router_get_description(buf, ri);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int router_digest_is_me ( const char *  digest)

Return true iff I'm a server and digest is equal to my server identity key digest.

Definition at line 1389 of file router.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Annotate that we found our DirPort reachable.

Definition at line 970 of file router.c.

{
  const routerinfo_t *me = router_get_my_routerinfo();
  if (!can_reach_dir_port && me) {
    log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable "
               "from the outside. Excellent.");
    can_reach_dir_port = 1;
    if (decide_to_advertise_dirport(get_options(), me->dir_port))
      mark_my_descriptor_dirty("DirPort found reachable");
    control_event_server_status(LOG_NOTICE,
                                "REACHABILITY_SUCCEEDED DIRADDRESS=%s:%d",
                                me->address, me->dir_port);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int router_dump_router_to_string ( char *  s,
size_t  maxlen,
routerinfo_t router,
crypto_pk_t ident_key 
)

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 s, using at most maxlen bytes.

Return -1 on failure, and the number of bytes used on success.

Definition at line 1973 of file router.c.

{
  char *onion_pkey; /* Onion key, PEM-encoded. */
  char *identity_pkey; /* Identity key, PEM-encoded. */
  char digest[DIGEST_LEN];
  char published[ISO_TIME_LEN+1];
  char fingerprint[FINGERPRINT_LEN+1];
  int has_extra_info_digest;
  char extra_info_digest[HEX_DIGEST_LEN+1];
  size_t onion_pkeylen, identity_pkeylen;
  size_t written;
  int result=0;
  addr_policy_t *tmpe;
  char *family_line;
  char *extra_or_address = NULL;
  const or_options_t *options = get_options();

  /* Make sure the identity key matches the one in the routerinfo. */
  if (crypto_pk_cmp_keys(ident_key, router->identity_pkey)) {
    log_warn(LD_BUG,"Tried to sign a router with a private key that didn't "
             "match router's public key!");
    return -1;
  }

  /* record our fingerprint, so we can include it in the descriptor */
  if (crypto_pk_get_fingerprint(router->identity_pkey, fingerprint, 1)<0) {
    log_err(LD_BUG,"Error computing fingerprint");
    return -1;
  }

  /* PEM-encode the onion key */
  if (crypto_pk_write_public_key_to_string(router->onion_pkey,
                                           &onion_pkey,&onion_pkeylen)<0) {
    log_warn(LD_BUG,"write onion_pkey to string failed!");
    return -1;
  }

  /* PEM-encode the identity key */
  if (crypto_pk_write_public_key_to_string(router->identity_pkey,
                                        &identity_pkey,&identity_pkeylen)<0) {
    log_warn(LD_BUG,"write identity_pkey to string failed!");
    tor_free(onion_pkey);
    return -1;
  }

  /* Encode the publication time. */
  format_iso_time(published, router->cache_info.published_on);

  if (router->declared_family && smartlist_len(router->declared_family)) {
    char *family = smartlist_join_strings(router->declared_family,
                                          " ", 0, NULL);
    tor_asprintf(&family_line, "family %s\n", family);
    tor_free(family);
  } else {
    family_line = tor_strdup("");
  }

  has_extra_info_digest =
    ! tor_digest_is_zero(router->cache_info.extra_info_digest);

  if (has_extra_info_digest) {
    base16_encode(extra_info_digest, sizeof(extra_info_digest),
                  router->cache_info.extra_info_digest, DIGEST_LEN);
  }

  if (router->ipv6_orport &&
      tor_addr_family(&router->ipv6_addr) == AF_INET6) {
    char addr[TOR_ADDR_BUF_LEN];
    const char *a;
    a = tor_addr_to_str(addr, &router->ipv6_addr, sizeof(addr), 1);
    if (a) {
      tor_asprintf(&extra_or_address,
                   "or-address %s:%d\n", a, router->ipv6_orport);
      log_debug(LD_OR, "My or-address line is <%s>", extra_or_address);
    }
  }

  /* Generate the easy portion of the router descriptor. */
  result = tor_snprintf(s, maxlen,
                    "router %s %s %d 0 %d\n"
                    "%s"
                    "platform %s\n"
                    "opt protocols Link 1 2 Circuit 1\n"
                    "published %s\n"
                    "opt fingerprint %s\n"
                    "uptime %ld\n"
                    "bandwidth %d %d %d\n"
                    "%s%s%s%s"
                    "onion-key\n%s"
                    "signing-key\n%s"
                    "%s%s%s%s",
    router->nickname,
    router->address,
    router->or_port,
    decide_to_advertise_dirport(options, router->dir_port),
    extra_or_address ? extra_or_address : "",
    router->platform,
    published,
    fingerprint,
    stats_n_seconds_working,
    (int) router->bandwidthrate,
    (int) router->bandwidthburst,
    (int) router->bandwidthcapacity,
    has_extra_info_digest ? "opt extra-info-digest " : "",
    has_extra_info_digest ? extra_info_digest : "",
    has_extra_info_digest ? "\n" : "",
    options->DownloadExtraInfo ? "opt caches-extra-info\n" : "",
    onion_pkey, identity_pkey,
    family_line,
    we_are_hibernating() ? "opt hibernating 1\n" : "",
    options->HidServDirectoryV2 ? "opt hidden-service-dir\n" : "",
    options->AllowSingleHopExits ? "opt allow-single-hop-exits\n" : "");

  tor_free(family_line);
  tor_free(onion_pkey);
  tor_free(identity_pkey);
  tor_free(extra_or_address);

  if (result < 0) {
    log_warn(LD_BUG,"descriptor snprintf #1 ran out of room!");
    return -1;
  }
  /* From now on, we use 'written' to remember the current length of 's'. */
  written = result;

  if (options->ContactInfo && strlen(options->ContactInfo)) {
    const char *ci = options->ContactInfo;
    if (strchr(ci, '\n') || strchr(ci, '\r'))
      ci = escaped(ci);
    result = tor_snprintf(s+written,maxlen-written, "contact %s\n", ci);
    if (result<0) {
      log_warn(LD_BUG,"descriptor snprintf #2 ran out of room!");
      return -1;
    }
    written += result;
  }

  /* Write the exit policy to the end of 's'. */
  if (!router->exit_policy || !smartlist_len(router->exit_policy)) {
    strlcat(s+written, "reject *:*\n", maxlen-written);
    written += strlen("reject *:*\n");
    tmpe = NULL;
  } else if (router->exit_policy) {
    int i;
    for (i = 0; i < smartlist_len(router->exit_policy); ++i) {
      tmpe = smartlist_get(router->exit_policy, i);
      result = policy_write_item(s+written, maxlen-written, tmpe, 1);
      if (result < 0) {
        log_warn(LD_BUG,"descriptor policy_write_item ran out of room!");
        return -1;
      }
      tor_assert(result == (int)strlen(s+written));
      written += result;
      if (written+2 > maxlen) {
        log_warn(LD_BUG,"descriptor policy_write_item ran out of room (2)!");
        return -1;
      }
      s[written++] = '\n';
    }
  }

  if (written + DIROBJ_MAX_SIG_LEN > maxlen) {
    /* Not enough room for signature. */
    log_warn(LD_BUG,"not enough room left in descriptor for signature!");
    return -1;
  }

  /* Sign the descriptor */
  strlcpy(s+written, "router-signature\n", maxlen-written);
  written += strlen(s+written);
  s[written] = '\0';
  if (router_get_router_hash(s, strlen(s), digest) < 0) {
    return -1;
  }

  note_crypto_pk_op(SIGN_RTR);
  if (router_append_dirobj_signature(s+written,maxlen-written,
                                     digest,DIGEST_LEN,ident_key)<0) {
    log_warn(LD_BUG, "Couldn't sign router descriptor");
    return -1;
  }
  written += strlen(s+written);

  if (written+2 > maxlen) {
    log_warn(LD_BUG,"Not enough room to finish descriptor.");
    return -1;
  }
  /* include a last '\n' */
  s[written] = '\n';
  s[written+1] = 0;

#ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING
  {
    char *s_dup;
    const char *cp;
    routerinfo_t *ri_tmp;
    cp = s_dup = tor_strdup(s);
    ri_tmp = router_parse_entry_from_string(cp, NULL, 1, 0, NULL);
    if (!ri_tmp) {
      log_err(LD_BUG,
              "We just generated a router descriptor we can't parse.");
      log_err(LD_BUG, "Descriptor was: <<%s>>", s);
      return -1;
    }
    tor_free(s_dup);
    routerinfo_free(ri_tmp);
  }
#endif

  return (int)written+1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int router_extrainfo_digest_is_me ( const char *  digest)

Return true iff I'm a server and digest is equal to my identity digest.

Definition at line 1398 of file router.c.

{
  extrainfo_t *ei = router_get_my_extrainfo();
  if (!ei)
    return 0;

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

Here is the call graph for this function:

int router_fingerprint_is_me ( const char *  fp)

Return true iff fp is a hex fingerprint of my identity digest.

Definition at line 1418 of file router.c.

{
  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;
}

Here is the call graph for this function:

void router_free_all ( void  )
uint16_t router_get_active_listener_port_by_type ( int  listener_type)

Return the port of the first active listener of type listener_type.

XXX not a very good interface. it's not reliable when there are multiple listeners.

Definition at line 1238 of file router.c.

{
  /* Iterate all connections, find one of the right kind and return
     the port. Not very sophisticated or fast, but effective. */
  const connection_t *c = connection_get_by_type(listener_type);
  if (c)
    return c->port;

  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

uint16_t router_get_advertised_dir_port ( const or_options_t options,
uint16_t  dirport 
)

Return the port that we should advertise as our DirPort; this is one of three possibilities: The one that is passed as dirport if the DirPort option is 0, or the one configured in the DirPort option, or the one we actually bound to if DirPort is "auto".

Definition at line 1273 of file router.c.

{
  int dirport_configured = get_primary_dir_port();
  (void)options;

  if (!dirport_configured)
    return dirport;

  if (dirport_configured == CFG_AUTO_PORT)
    return router_get_active_listener_port_by_type(CONN_TYPE_DIR_LISTENER);

  return dirport_configured;
}

Here is the call graph for this function:

Here is the caller graph for this function:

uint16_t router_get_advertised_or_port ( const or_options_t options)

Return the port that we should advertise as our ORPort; this is either the one configured in the ORPort option, or the one we actually bound to if ORPort is "auto".

Definition at line 1254 of file router.c.

{
  int port = get_primary_or_port();
  (void)options;

  /* If the port is in 'auto' mode, we have to use
     router_get_listener_port_by_type(). */
  if (port == CFG_AUTO_PORT)
    return router_get_active_listener_port_by_type(CONN_TYPE_OR_LISTENER);

  return port;
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* router_get_description ( char *  buf,
const routerinfo_t ri 
)

Use buf (which must be at least NODE_DESC_BUF_LEN bytes long) to hold a human-readable description of ri.

Return a pointer to the front of buf.

Definition at line 2525 of file router.c.

{
  if (!ri)
    return "<null>";
  return format_node_description(buf,
                                 ri->cache_info.identity_digest,
                                 router_is_named(ri),
                                 ri->nickname,
                                 NULL,
                                 ri->addr);
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* router_get_descriptor_gen_reason ( void  )

Return a human-readable string describing what triggered us to generate our current descriptor, or NULL if we don't know.

Definition at line 1472 of file router.c.

{
  return desc_gen_reason;
}

Here is the caller graph for this function:

const char* router_get_my_descriptor ( void  )

OR only: Return a signed server descriptor for this OR, rebuilding a fresh one if necessary.

Return NULL on error.

Definition at line 1444 of file router.c.

{
  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;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return the extrainfo document for this OR, or NULL if we have none.

Rebuilt it (and the server descriptor) if necessary.

Definition at line 1460 of file router.c.

{
  if (!server_mode(get_options()))
    return NULL;
  if (router_rebuild_descriptor(0))
    return NULL;
  return desc_extrainfo;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return a routerinfo for this OR, rebuilding a fresh one if necessary.

Return NULL on error, or if called on an OP.

Definition at line 1431 of file router.c.

{
  if (!server_mode(get_options()))
    return NULL;
  if (router_rebuild_descriptor(0))
    return NULL;
  return desc_routerinfo;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void router_get_pref_ipv6_orport ( const routerinfo_t router,
tor_addr_port_t ap_out 
)

Copy the preferred IPv6 OR port (IP address and TCP port) for router into *ap_out.

Definition at line 2224 of file router.c.

{
  tor_assert(ap_out != NULL);
  tor_addr_copy(&ap_out->addr, &router->ipv6_addr);
  ap_out->port = router->ipv6_orport;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void router_get_pref_orport ( const routerinfo_t router,
tor_addr_port_t ap_out 
)

Copy the preferred OR port (IP address and TCP port) for router into *addr_out.

Definition at line 2213 of file router.c.

{
  if (router_ipv6_preferred(router))
    router_get_pref_ipv6_orport(router, ap_out);
  else
    router_get_prim_orport(router, ap_out);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void router_get_prim_orport ( const routerinfo_t router,
tor_addr_port_t ap_out 
)

Copy the primary (IPv4) OR port (IP address and TCP port) for router into *ap_out.

Definition at line 2189 of file router.c.

{
  tor_assert(ap_out != NULL);
  tor_addr_from_ipv4h(&ap_out->addr, router->addr);
  ap_out->port = router->or_port;
}

Here is the caller graph for this function:

void router_get_verbose_nickname ( char *  buf,
const routerinfo_t router 
)

Set buf (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the verbose representation of the identity of router.

The format is: A dollar sign. The upper-case hexadecimal encoding of the SHA1 hash of router's identity. A "=" if the router is named; a "~" if it is not. The router's nickname.

Definition at line 2661 of file router.c.

{
  const char *good_digest = networkstatus_get_router_digest_by_nickname(
                                                         router->nickname);
  int is_named = good_digest && tor_memeq(good_digest,
                                        router->cache_info.identity_digest,
                                        DIGEST_LEN);
  buf[0] = '$';
  base16_encode(buf+1, HEX_DIGEST_LEN+1, router->cache_info.identity_digest,
                DIGEST_LEN);
  buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
  strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Set up Tor's TLS contexts, based on our configuration and keys.

Return 0 on success, and -1 on failure.

Definition at line 490 of file router.c.

Here is the call graph for this function:

Here is the caller graph for this function:

int router_ipv6_preferred ( const routerinfo_t router)

Return 1 if we prefer the IPv6 address and OR TCP port of router, else 0.

We prefer the IPv6 address if the router has one and i) the routerinfo_t says so or ii) the router has no IPv4 address.

Definition at line 2204 of file router.c.

{
  return (!tor_addr_is_null(&router->ipv6_addr)
          && (router->ipv6_preferred || router->addr == 0));
}

Here is the call graph for this function:

Here is the caller graph for this function:

int router_is_me ( const routerinfo_t router)

A wrapper around router_digest_is_me().

Definition at line 1411 of file router.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Return true iff my exit policy is reject *:*.

Return -1 if we don't have a descriptor

Definition at line 1378 of file router.c.

{
  if (!router_get_my_routerinfo()) /* make sure desc_routerinfo exists */
    return -1;

  return desc_routerinfo->policy_is_reject_star;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void router_new_address_suggestion ( const char *  suggestion,
const dir_connection_t d_conn 
)

A directory server d_conn told us our IP address is suggestion.

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.

Definition at line 1881 of file router.c.

{
  tor_addr_t addr;
  uint32_t cur = 0;             /* Current IPv4 address.  */
  const or_options_t *options = get_options();

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

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

  if (!server_mode(options)) {
    tor_addr_copy(&last_guessed_ip, &addr);
    return;
  }

  /* XXXX ipv6 */
  if (resolve_my_address(LOG_INFO, options, &cur, NULL) >= 0) {
    /* We're all set -- we already know our address. Great. */
    tor_addr_from_ipv4h(&last_guessed_ip, cur); /* store it in case we
                                                   need it later */
    return;
  }
  if (tor_addr_is_internal(&addr, 0)) {
    /* Don't believe anybody who says our IP is, say, 127.0.0.1. */
    return;
  }
  if (tor_addr_eq(&d_conn->_base.addr, &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 (!tor_addr_eq(&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,
                         d_conn->_base.address);
    ip_address_changed(0);
    tor_addr_copy(&last_guessed_ip, &addr); /* router_rebuild_descriptor()
                                               will fetch it */
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Annotate that we found our ORPort reachable.

Definition at line 952 of file router.c.

{
  const routerinfo_t *me = router_get_my_routerinfo();
  if (!can_reach_or_port && me) {
    log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from "
               "the outside. Excellent.%s",
               get_options()->_PublishServerDescriptor != NO_DIRINFO ?
                 " Publishing server descriptor." : "");
    can_reach_or_port = 1;
    mark_my_descriptor_dirty("ORPort found reachable");
    control_event_server_status(LOG_NOTICE,
                                "REACHABILITY_SUCCEEDED ORADDRESS=%s:%d",
                                me->address, me->or_port);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void router_perform_bandwidth_test ( int  num_circs,
time_t  now 
)

We have enough testing circuits open.

Send a bunch of "drop" cells down each of them, to exercise our bandwidth.

Definition at line 988 of file router.c.

{
  int num_cells = (int)(get_options()->BandwidthRate * 10 / CELL_NETWORK_SIZE);
  int max_cells = num_cells < CIRCWINDOW_START ?
                    num_cells : CIRCWINDOW_START;
  int cells_per_circuit = max_cells / num_circs;
  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 */
      }
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int router_pick_published_address ( const or_options_t options,
uint32_t *  addr 
)

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 *addr and return 0 on success, else return -1 if we have no guess.

Definition at line 1488 of file router.c.

{
  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;
    }
  }
  log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr32(*addr));
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

uint8_t router_purpose_from_string ( const char *  s)

Given a string, convert it to a router purpose.

Definition at line 2722 of file router.c.

{
  if (!strcmp(s, "general"))
    return ROUTER_PURPOSE_GENERAL;
  else if (!strcmp(s, "bridge"))
    return ROUTER_PURPOSE_BRIDGE;
  else if (!strcmp(s, "controller"))
    return ROUTER_PURPOSE_CONTROLLER;
  else
    return ROUTER_PURPOSE_UNKNOWN;
}

Here is the caller graph for this function:

const char* router_purpose_to_string ( uint8_t  p)

Given a router purpose, convert it to a string.

Don't call this on ROUTER_PURPOSE_UNKNOWN: The whole point of that value is that we don't know its string representation.

Definition at line 2707 of file router.c.

{
  switch (p)
    {
    case ROUTER_PURPOSE_GENERAL: return "general";
    case ROUTER_PURPOSE_BRIDGE: return "bridge";
    case ROUTER_PURPOSE_CONTROLLER: return "controller";
    default:
      tor_assert(0);
    }
  return NULL;
}

Here is the caller graph for this function:

int router_rebuild_descriptor ( int  force)

If force 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.

Definition at line 1508 of file router.c.

{
  routerinfo_t *ri;
  extrainfo_t *ei;
  uint32_t addr;
  char platform[256];
  int hibernating = we_are_hibernating();
  const or_options_t *options = get_options();

  if (desc_clean_since && !force)
    return 0;

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

  log_info(LD_OR, "Rebuilding relay descriptor%s", force ? " (forced)" : "");

  ri = tor_malloc_zero(sizeof(routerinfo_t));
  ri->cache_info.routerlist_index = -1;
  ri->address = tor_dup_ip(addr);
  ri->nickname = tor_strdup(options->Nickname);
  ri->addr = addr;
  ri->or_port = router_get_advertised_or_port(options);
  ri->dir_port = router_get_advertised_dir_port(options, 0);
  ri->cache_info.published_on = time(NULL);
  ri->onion_pkey = crypto_pk_dup_key(get_onion_key()); /* must invoke from
                                                        * main thread */
  if (options->BridgeRelay) {
    /* For now, only bridges advertise an ipv6 or-address.  And only one. */
    const port_cfg_t *ipv6_orport = NULL;
    SMARTLIST_FOREACH_BEGIN(get_configured_ports(), const port_cfg_t *, p) {
      if (p->type == CONN_TYPE_OR_LISTENER &&
          ! p->no_advertise &&
          ! p->ipv4_only &&
          tor_addr_family(&p->addr) == AF_INET6) {
        if (! tor_addr_is_internal(&p->addr, 0)) {
          ipv6_orport = p;
          break;
        } else {
          char addrbuf[TOR_ADDR_BUF_LEN];
          log_warn(LD_CONFIG,
                   "Unable to use configured IPv6 address \"%s\" in a "
                   "descriptor. Skipping it. "
                   "Try specifying a globally reachable address explicitly. ",
                   tor_addr_to_str(addrbuf, &p->addr, sizeof(addrbuf), 1));
        }
      }
    } SMARTLIST_FOREACH_END(p);
    if (ipv6_orport) {
      tor_addr_copy(&ri->ipv6_addr, &ipv6_orport->addr);
      ri->ipv6_orport = ipv6_orport->port;
    }
  }
  ri->identity_pkey = crypto_pk_dup_key(get_server_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 = get_effective_bwrate(options);

  /* and compute ri->bandwidthburst similarly */
  ri->bandwidthburst = get_effective_bwburst(options);

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

  if (dns_seems_to_be_broken() || has_dns_init_failed()) {
    /* DNS is screwed up; don't claim to be an exit. */
    policies_exit_policy_append_reject_star(&ri->exit_policy);
  } else {
    policies_parse_exit_policy(options->ExitPolicy, &ri->exit_policy,
                               options->ExitPolicyRejectPrivate,
                               ri->address, !options->BridgeRelay);
  }
  ri->policy_is_reject_star =
    policy_is_reject_star(ri->exit_policy);

#if 0
  /* XXXX NM NM I belive this is safe to remove */
  if (authdir_mode(options))
    ri->is_valid = ri->is_named = 1; /* believe in yourself */
#endif

  if (options->MyFamily && ! options->BridgeRelay) {
    smartlist_t *family;
    if (!warned_nonexistent_family)
      warned_nonexistent_family = smartlist_new();
    family = smartlist_new();
    ri->declared_family = smartlist_new();
    smartlist_split_string(family, options->MyFamily, ",",
      SPLIT_SKIP_SPACE|SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
    SMARTLIST_FOREACH_BEGIN(family, char *, name) {
       const node_t *member;
       if (!strcasecmp(name, options->Nickname))
         goto skip; /* Don't list ourself, that's redundant */
       else
         member = node_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_digest_is_me(member->identity)) {
         /* Don't list ourself in our own family; that's redundant */
         /* XXX shouldn't be possible */
       } else {
         char *fp = tor_malloc(HEX_DIGEST_LEN+2);
         fp[0] = '$';
         base16_encode(fp+1,HEX_DIGEST_LEN+1,
                       member->identity, DIGEST_LEN);
         smartlist_add(ri->declared_family, fp);
         if (smartlist_string_isin(warned_nonexistent_family, name))
           smartlist_string_remove(warned_nonexistent_family, name);
       }
    skip:
       tor_free(name);
    } SMARTLIST_FOREACH_END(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);
  if (extrainfo_dump_to_string(&ei->cache_info.signed_descriptor_body,
                               ei, get_server_identity_key()) < 0) {
    log_warn(LD_BUG, "Couldn't generate extra-info descriptor.");
    extrainfo_free(ei);
    ei = NULL;
  } else {
    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_len,
                              ei->cache_info.signed_descriptor_digest);
  }

  /* Now finish the router descriptor. */
  if (ei) {
    memcpy(ri->cache_info.extra_info_digest,
           ei->cache_info.signed_descriptor_digest,
           DIGEST_LEN);
  } else {
    /* ri was allocated with tor_malloc_zero, so there is no need to
     * zero ri->cache_info.extra_info_digest here. */
  }
  ri->cache_info.signed_descriptor_body = tor_malloc(8192);
  if (router_dump_router_to_string(ri->cache_info.signed_descriptor_body, 8192,
                                   ri, get_server_identity_key()) < 0) {
    log_warn(LD_BUG, "Couldn't generate router descriptor.");
    routerinfo_free(ri);
    extrainfo_free(ei);
    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) {
    /* Bridges shouldn't be able to send their descriptors unencrypted,
       anyway, since they don't have a DirPort, and always connect to the
       bridge authority anonymously.  But just in case they somehow think of
       sending them on an unencrypted connection, don't allow them to try. */
    ri->cache_info.send_unencrypted = ei->cache_info.send_unencrypted = 0;
  } else {
    ri->cache_info.send_unencrypted = ei->cache_info.send_unencrypted = 1;
  }

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

  if (ei) {
    tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei, NULL, NULL));
  }

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

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

Here is the caller graph for this function:

void router_reset_reachability ( void  )

Forget what we have learned about our reachability status.

Definition at line 781 of file router.c.

Here is the caller graph for this function:

void router_reset_warnings ( void  )

Forget that we have issued any router-related warnings, so that we'll warn again if we see the same errors.

Definition at line 2695 of file router.c.

Here is the call graph for this function:

Here is the caller graph for this function:

OR only: If force 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.

Definition at line 1311 of file router.c.

{
  const routerinfo_t *ri;
  extrainfo_t *ei;
  char *msg;
  size_t desc_len, extra_len = 0, total_len;
  dirinfo_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_DIRINFO)
    return;
  if (!force && !desc_needs_upload)
    return;

  log_info(LD_OR, "Uploading relay descriptor to directory authorities%s",
           force ? " (forced)" : "");

  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_DIRINFO) ?
                                 ROUTER_PURPOSE_BRIDGE :
                                 ROUTER_PURPOSE_GENERAL,
                               auth, msg, desc_len, extra_len);
  tor_free(msg);
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* routerstatus_describe ( const routerstatus_t rs)

Return a human-readable description of the routerstatus_t rs.

This function is not thread-safe. Each call to this function invalidates previous values returned by this function.

Definition at line 2635 of file router.c.

{
  static char buf[NODE_DESC_BUF_LEN];
  return routerstatus_get_description(buf, rs);
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* routerstatus_get_description ( char *  buf,
const routerstatus_t rs 
)

Use buf (which must be at least NODE_DESC_BUF_LEN bytes long) to hold a human-readable description of rs.

Return a pointer to the front of buf.

Definition at line 2575 of file router.c.

{
  if (!rs)
    return "<null>";
  return format_node_description(buf,
                                 rs->identity_digest,
                                 rs->is_named,
                                 rs->nickname,
                                 NULL,
                                 rs->addr);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void routerstatus_get_verbose_nickname ( char *  buf,
const routerstatus_t router 
)

Set buf (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the verbose representation of the identity of router.

The format is: A dollar sign. The upper-case hexadecimal encoding of the SHA1 hash of router's identity. A "=" if the router is named; a "~" if it is not. The router's nickname.

Definition at line 2683 of file router.c.

{
  buf[0] = '$';
  base16_encode(buf+1, HEX_DIGEST_LEN+1, router->identity_digest,
                DIGEST_LEN);
  buf[1+HEX_DIGEST_LEN] = router->is_named ? '=' : '~';
  strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
}

Here is the call graph for this function:

Return true iff the server identity key has been set.

Definition at line 178 of file router.c.

{
  return server_identitykey != NULL;
}

Here is the caller graph for this function:

int server_mode ( const or_options_t options)

Return true iff we are trying to be a server.

Definition at line 1115 of file router.c.

{
  if (options->ClientOnly) return 0;
  return (options->ORPort || options->ORListenAddress);
}

Set the current client identity key to k.

Definition at line 186 of file router.c.

Here is the call graph for this function:

Here is the caller graph for this function:

Set the current server identity key to k.

Definition at line 139 of file router.c.

Here is the call graph for this function:

Here is the caller graph for this function:

int should_refuse_unknown_exits ( const or_options_t options)

Return true iff the combination of options in options and parameters in the consensus mean that we don't want to allow exits from circuits we got from addresses not known to be servers.

Definition at line 1134 of file router.c.

{
  if (options->RefuseUnknownExits != -1) {
    return options->RefuseUnknownExits;
  } else {
    return networkstatus_get_param(NULL, "refuseunknownexits", 1, 0, 1);
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

If we're a v3 authority, check whether we have a certificate that's likely to expire soon.

Warn if we do, but not too often.

Definition at line 444 of file router.c.

{
  time_t now, expires;
  static time_t last_warned = 0;
  int badness, time_left, warn_interval;
  if (!authdir_mode_v3(get_options()) || !authority_key_certificate)
    return;

  now = time(NULL);
  expires = authority_key_certificate->expires;
  time_left = (int)( expires - now );
  if (time_left <= 0) {
    badness = LOG_ERR;
    warn_interval = 60*60;
  } else if (time_left <= 24*60*60) {
    badness = LOG_WARN;
    warn_interval = 60*60;
  } else if (time_left <= 24*60*60*7) {
    badness = LOG_WARN;
    warn_interval = 24*60*60;
  } else if (time_left <= 24*60*60*30) {
    badness = LOG_WARN;
    warn_interval = 24*60*60*5;
  } else {
    return;
  }

  if (last_warned + warn_interval > now)
    return;

  if (time_left <= 0) {
    log(badness, LD_DIR, "Your v3 authority certificate has expired."
        " Generate a new one NOW.");
  } else if (time_left <= 24*60*60) {
    log(badness, LD_DIR, "Your v3 authority certificate expires in %d hours;"
        " Generate a new one NOW.", time_left/(60*60));
  } else {
    log(badness, LD_DIR, "Your v3 authority certificate expires in %d days;"
        " Generate a new one soon.", time_left/(24*60*60));
  }
  last_warned = now;
}

Here is the call graph for this function:

Here is the caller graph for this function: