aboutsummaryrefslogtreecommitdiff
path: root/src/or/router.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/router.c')
-rw-r--r--src/or/router.c275
1 files changed, 190 insertions, 85 deletions
diff --git a/src/or/router.c b/src/or/router.c
index 8661e7a22..978078bf7 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -7,6 +7,23 @@
#define ROUTER_PRIVATE
#include "or.h"
+#include "circuitlist.h"
+#include "circuituse.h"
+#include "config.h"
+#include "connection.h"
+#include "control.h"
+#include "directory.h"
+#include "dirserv.h"
+#include "dns.h"
+#include "geoip.h"
+#include "hibernate.h"
+#include "main.h"
+#include "policies.h"
+#include "relay.h"
+#include "rephist.h"
+#include "router.h"
+#include "routerlist.h"
+#include "routerparse.h"
/**
* \file router.c
@@ -61,8 +78,7 @@ static void
set_onion_key(crypto_pk_env_t *k)
{
tor_mutex_acquire(key_lock);
- if (onionkey)
- crypto_free_pk_env(onionkey);
+ crypto_free_pk_env(onionkey);
onionkey = k;
onionkey_set_at = time(NULL);
tor_mutex_release(key_lock);
@@ -111,8 +127,7 @@ get_onion_key_set_at(void)
void
set_identity_key(crypto_pk_env_t *k)
{
- if (identitykey)
- crypto_free_pk_env(identitykey);
+ crypto_free_pk_env(identitykey);
identitykey = k;
crypto_pk_get_digest(identitykey, identitykey_digest);
}
@@ -201,8 +216,7 @@ rotate_onion_key(void)
}
log_info(LD_GENERAL, "Rotating onion key");
tor_mutex_acquire(key_lock);
- if (lastonionkey)
- crypto_free_pk_env(lastonionkey);
+ crypto_free_pk_env(lastonionkey);
lastonionkey = onionkey;
onionkey = prkey;
now = time(NULL);
@@ -331,10 +345,9 @@ load_authority_keyset(int legacy, crypto_pk_env_t **key_out,
goto done;
}
- if (*key_out)
- crypto_free_pk_env(*key_out);
- if (*cert_out)
- authority_cert_free(*cert_out);
+ crypto_free_pk_env(*key_out);
+ authority_cert_free(*cert_out);
+
*key_out = signing_key;
*cert_out = parsed;
r = 0;
@@ -344,10 +357,8 @@ load_authority_keyset(int legacy, crypto_pk_env_t **key_out,
done:
tor_free(fname);
tor_free(cert);
- if (signing_key)
- crypto_free_pk_env(signing_key);
- if (parsed)
- authority_cert_free(parsed);
+ crypto_free_pk_env(signing_key);
+ authority_cert_free(parsed);
return r;
}
@@ -442,7 +453,9 @@ init_keys(void)
key_lock = tor_mutex_new();
/* There are a couple of paths that put us here before */
- if (crypto_global_init(get_options()->HardwareAccel)) {
+ if (crypto_global_init(get_options()->HardwareAccel,
+ get_options()->AccelName,
+ get_options()->AccelDir)) {
log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting.");
return -1;
}
@@ -1243,6 +1256,7 @@ router_rebuild_descriptor(int force)
uint32_t addr;
char platform[256];
int hibernating = we_are_hibernating();
+ size_t ei_size;
or_options_t *options = get_options();
if (desc_clean_since && !force)
@@ -1285,7 +1299,7 @@ router_rebuild_descriptor(int force)
policies_parse_exit_policy(options->ExitPolicy, &ri->exit_policy,
options->ExitPolicyRejectPrivate,
- ri->address);
+ ri->address, !options->BridgeRelay);
if (desc_routerinfo) { /* inherit values */
ri->is_valid = desc_routerinfo->is_valid;
@@ -1356,9 +1370,10 @@ router_rebuild_descriptor(int force)
ei->cache_info.published_on = ri->cache_info.published_on;
memcpy(ei->cache_info.identity_digest, ri->cache_info.identity_digest,
DIGEST_LEN);
- ei->cache_info.signed_descriptor_body = tor_malloc(8192);
- if (extrainfo_dump_to_string(ei->cache_info.signed_descriptor_body, 8192,
- ei, get_identity_key()) < 0) {
+ ei_size = options->ExtraInfoStatistics ? MAX_EXTRAINFO_UPLOAD_SIZE : 8192;
+ ei->cache_info.signed_descriptor_body = tor_malloc(ei_size);
+ if (extrainfo_dump_to_string(ei->cache_info.signed_descriptor_body,
+ ei_size, ei, get_identity_key()) < 0) {
log_warn(LD_BUG, "Couldn't generate extra-info descriptor.");
routerinfo_free(ri);
extrainfo_free(ei);
@@ -1401,11 +1416,9 @@ router_rebuild_descriptor(int force)
tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei, NULL, NULL));
- if (desc_routerinfo)
- routerinfo_free(desc_routerinfo);
+ routerinfo_free(desc_routerinfo);
desc_routerinfo = ri;
- if (desc_extrainfo)
- extrainfo_free(desc_extrainfo);
+ extrainfo_free(desc_extrainfo);
desc_extrainfo = ei;
desc_clean_since = time(NULL);
@@ -1586,8 +1599,6 @@ router_guess_address_from_dir_headers(uint32_t *guess)
return -1;
}
-extern const char tor_svn_revision[]; /* from tor_main.c */
-
/** Set <b>platform</b> (max length <b>len</b>) to a NUL-terminated short
* string describing the version of Tor and the operating system we're
* currently running on.
@@ -1646,7 +1657,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
return -1;
}
- /* PEM-encode the identity key key */
+ /* 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!");
@@ -1767,7 +1778,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
note_crypto_pk_op(SIGN_RTR);
if (router_append_dirobj_signature(s+written,maxlen-written,
- digest,ident_key)<0) {
+ digest,DIGEST_LEN,ident_key)<0) {
log_warn(LD_BUG, "Couldn't sign router descriptor");
return -1;
}
@@ -1802,6 +1813,57 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
return (int)written+1;
}
+/** Load the contents of <b>filename</b>, find the last line starting with
+ * <b>end_line</b>, ensure that its timestamp is not more than 25 hours in
+ * the past or more than 1 hour in the future with respect to <b>now</b>,
+ * and write the file contents starting with that line to *<b>out</b>.
+ * Return 1 for success, 0 if the file does not exist, or -1 if the file
+ * does not contain a line matching these criteria or other failure. */
+static int
+load_stats_file(const char *filename, const char *end_line, time_t now,
+ char **out)
+{
+ int r = -1;
+ char *fname = get_datadir_fname(filename);
+ char *contents, *start = NULL, *tmp, timestr[ISO_TIME_LEN+1];
+ time_t written;
+ switch (file_status(fname)) {
+ case FN_FILE:
+ /* X022 Find an alternative to reading the whole file to memory. */
+ if ((contents = read_file_to_str(fname, 0, NULL))) {
+ tmp = strstr(contents, end_line);
+ /* Find last block starting with end_line */
+ while (tmp) {
+ start = tmp;
+ tmp = strstr(tmp + 1, end_line);
+ }
+ if (!start)
+ goto notfound;
+ if (strlen(start) < strlen(end_line) + 1 + sizeof(timestr))
+ goto notfound;
+ strlcpy(timestr, start + 1 + strlen(end_line), sizeof(timestr));
+ if (parse_iso_time(timestr, &written) < 0)
+ goto notfound;
+ if (written < now - (25*60*60) || written > now + (1*60*60))
+ goto notfound;
+ *out = tor_strdup(start);
+ r = 1;
+ }
+ notfound:
+ tor_free(contents);
+ break;
+ case FN_NOENT:
+ r = 0;
+ break;
+ case FN_ERROR:
+ case FN_DIR:
+ default:
+ break;
+ }
+ tor_free(fname);
+ return r;
+}
+
/** Write the contents of <b>extrainfo</b> to the <b>maxlen</b>-byte string
* <b>s</b>, signing them with <b>ident_key</b>. Return 0 on success,
* negative on failure. */
@@ -1816,6 +1878,8 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo,
char *bandwidth_usage;
int result;
size_t len;
+ static int write_stats_to_extrainfo = 1;
+ time_t now = time(NULL);
base16_encode(identity, sizeof(identity),
extrainfo->cache_info.identity_digest, DIGEST_LEN);
@@ -1827,23 +1891,79 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo,
"published %s\n%s",
extrainfo->nickname, identity,
published, bandwidth_usage);
+
tor_free(bandwidth_usage);
if (result<0)
return -1;
- if (should_record_bridge_info(options)) {
- char *geoip_summary = extrainfo_get_client_geoip_summary(time(NULL));
- if (geoip_summary) {
- char geoip_start[ISO_TIME_LEN+1];
- format_iso_time(geoip_start, geoip_get_history_start());
- result = tor_snprintf(s+strlen(s), maxlen-strlen(s),
- "geoip-start-time %s\n"
- "geoip-client-origins %s\n",
- geoip_start, geoip_summary);
- control_event_clients_seen(geoip_start, geoip_summary);
- tor_free(geoip_summary);
- if (result<0)
- return -1;
+ if (options->ExtraInfoStatistics && write_stats_to_extrainfo) {
+ char *contents = NULL;
+ 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) {
+ size_t pos = strlen(s);
+ if (strlcpy(s + pos, contents, maxlen - strlen(s)) !=
+ strlen(contents)) {
+ log_warn(LD_DIR, "Could not write dirreq-stats to extra-info "
+ "descriptor.");
+ s[pos] = '\0';
+ write_stats_to_extrainfo = 0;
+ }
+ tor_free(contents);
+ }
+ if (options->EntryStatistics &&
+ load_stats_file("stats"PATH_SEPARATOR"entry-stats",
+ "entry-stats-end", now, &contents) > 0) {
+ size_t pos = strlen(s);
+ if (strlcpy(s + pos, contents, maxlen - strlen(s)) !=
+ strlen(contents)) {
+ log_warn(LD_DIR, "Could not write entry-stats to extra-info "
+ "descriptor.");
+ s[pos] = '\0';
+ write_stats_to_extrainfo = 0;
+ }
+ tor_free(contents);
+ }
+ if (options->CellStatistics &&
+ load_stats_file("stats"PATH_SEPARATOR"buffer-stats",
+ "cell-stats-end", now, &contents) > 0) {
+ size_t pos = strlen(s);
+ if (strlcpy(s + pos, contents, maxlen - strlen(s)) !=
+ strlen(contents)) {
+ log_warn(LD_DIR, "Could not write buffer-stats to extra-info "
+ "descriptor.");
+ s[pos] = '\0';
+ write_stats_to_extrainfo = 0;
+ }
+ tor_free(contents);
+ }
+ if (options->ExitPortStatistics &&
+ load_stats_file("stats"PATH_SEPARATOR"exit-stats",
+ "exit-stats-end", now, &contents) > 0) {
+ size_t pos = strlen(s);
+ if (strlcpy(s + pos, contents, maxlen - strlen(s)) !=
+ strlen(contents)) {
+ log_warn(LD_DIR, "Could not write exit-stats to extra-info "
+ "descriptor.");
+ s[pos] = '\0';
+ write_stats_to_extrainfo = 0;
+ }
+ tor_free(contents);
+ }
+ }
+
+ if (should_record_bridge_info(options) && write_stats_to_extrainfo) {
+ const char *bridge_stats = geoip_get_bridge_stats_extrainfo(now);
+ if (bridge_stats) {
+ size_t pos = strlen(s);
+ if (strlcpy(s + pos, bridge_stats, maxlen - strlen(s)) !=
+ strlen(bridge_stats)) {
+ log_warn(LD_DIR, "Could not write bridge-stats to extra-info "
+ "descriptor.");
+ s[pos] = '\0';
+ write_stats_to_extrainfo = 0;
+ }
}
}
@@ -1852,10 +1972,10 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo,
len += strlen(s+len);
if (router_get_extrainfo_hash(s, digest)<0)
return -1;
- if (router_append_dirobj_signature(s+len, maxlen-len, digest, ident_key)<0)
+ if (router_append_dirobj_signature(s+len, maxlen-len, digest, DIGEST_LEN,
+ ident_key)<0)
return -1;
-#ifdef DEBUG_ROUTER_DUMP_ROUTER_TO_STRING
{
char *cp, *s_dup;
extrainfo_t *ei_tmp;
@@ -1871,31 +1991,26 @@ extrainfo_dump_to_string(char *s, size_t maxlen, extrainfo_t *extrainfo,
tor_free(s_dup);
extrainfo_free(ei_tmp);
}
-#endif
-
- return (int)strlen(s)+1;
-}
-/** Wrapper function for geoip_get_client_history(). It first discards
- * any items in the client history that are too old -- it dumps anything
- * more than 48 hours old, but it only considers whether to dump at most
- * once per 48 hours, so we aren't too precise to an observer (see also
- * r14780).
- */
-char *
-extrainfo_get_client_geoip_summary(time_t now)
-{
- static time_t last_purged_at = 0;
- int geoip_purge_interval = 48*60*60;
-#ifdef ENABLE_GEOIP_STATS
- if (get_options()->DirRecordUsageByCountry)
- geoip_purge_interval = get_options()->DirRecordUsageRetainIPs;
-#endif
- if (now > last_purged_at+geoip_purge_interval) {
- geoip_remove_old_clients(now-geoip_purge_interval);
- last_purged_at = now;
+ if (options->ExtraInfoStatistics && write_stats_to_extrainfo) {
+ char *cp, *s_dup;
+ extrainfo_t *ei_tmp;
+ cp = s_dup = tor_strdup(s);
+ ei_tmp = extrainfo_parse_entry_from_string(cp, NULL, 1, NULL);
+ if (!ei_tmp) {
+ 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. Descriptor "
+ "was:\n%s", s);
+ write_stats_to_extrainfo = 0;
+ extrainfo_dump_to_string(s, maxlen, extrainfo, ident_key);
+ }
+ tor_free(s_dup);
+ extrainfo_free(ei_tmp);
}
- return geoip_get_client_history(now, GEOIP_CLIENT_CONNECT);
+
+ return (int)strlen(s)+1;
}
/** Return true iff <b>s</b> is a legally valid server nickname. */
@@ -2022,26 +2137,16 @@ router_purpose_from_string(const char *s)
void
router_free_all(void)
{
- if (onionkey)
- crypto_free_pk_env(onionkey);
- if (lastonionkey)
- crypto_free_pk_env(lastonionkey);
- if (identitykey)
- crypto_free_pk_env(identitykey);
- if (key_lock)
- tor_mutex_free(key_lock);
- if (desc_routerinfo)
- routerinfo_free(desc_routerinfo);
- if (desc_extrainfo)
- extrainfo_free(desc_extrainfo);
- if (authority_signing_key)
- crypto_free_pk_env(authority_signing_key);
- if (authority_key_certificate)
- authority_cert_free(authority_key_certificate);
- if (legacy_signing_key)
- crypto_free_pk_env(legacy_signing_key);
- if (legacy_key_certificate)
- authority_cert_free(legacy_key_certificate);
+ crypto_free_pk_env(onionkey);
+ crypto_free_pk_env(lastonionkey);
+ crypto_free_pk_env(identitykey);
+ tor_mutex_free(key_lock);
+ routerinfo_free(desc_routerinfo);
+ extrainfo_free(desc_extrainfo);
+ crypto_free_pk_env(authority_signing_key);
+ authority_cert_free(authority_key_certificate);
+ crypto_free_pk_env(legacy_signing_key);
+ authority_cert_free(legacy_key_certificate);
if (warned_nonexistent_family) {
SMARTLIST_FOREACH(warned_nonexistent_family, char *, cp, tor_free(cp));