aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/common/gen_linux_syscalls.pl37
-rwxr-xr-xsrc/common/gen_server_ciphers.py115
-rw-r--r--src/common/get_mozilla_ciphers.py210
-rw-r--r--src/common/linux_syscalls.inc2
-rw-r--r--src/ext/README7
-rw-r--r--src/or/circuitbuild.c4
-rw-r--r--src/or/circuitbuild.h4
-rw-r--r--src/or/circuitlist.c10
-rw-r--r--src/or/circuituse.c58
-rw-r--r--src/or/circuituse.h1
-rw-r--r--src/or/directory.c16
-rw-r--r--src/or/dirvote.c9
-rw-r--r--src/or/dirvote.h6
-rw-r--r--src/or/rephist.c122
-rw-r--r--src/or/rephist.h1
-rw-r--r--src/or/status.c3
-rw-r--r--src/test/bench.c23
-rw-r--r--src/test/test_buffers.c48
-rw-r--r--src/test/test_cell_formats.c44
-rw-r--r--src/test/test_circuitlist.c77
-rw-r--r--src/test/test_microdesc.c107
21 files changed, 398 insertions, 506 deletions
diff --git a/src/common/gen_linux_syscalls.pl b/src/common/gen_linux_syscalls.pl
deleted file mode 100755
index 3c64098a0..000000000
--- a/src/common/gen_linux_syscalls.pl
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-my %syscalls = ();
-
-while (<>) {
- if (/^#define (__NR_\w+) /) {
- $syscalls{$1} = 1;
- }
-}
-
-print <<EOL;
-/* Automatically generated with
- gen_sandbox_syscalls.pl /usr/include/asm/unistd*.h
- Do not edit.
- */
-static const struct {
- int syscall_num; const char *syscall_name;
-} SYSCALLS_BY_NUMBER[] = {
-EOL
-
-for my $k (sort keys %syscalls) {
- my $name = $k;
- $name =~ s/^__NR_//;
- print <<EOL;
-#ifdef $k
- { $k, "$name" },
-#endif
-EOL
-
-}
-
-print <<EOL
- {0, NULL}
-};
-
-EOL
diff --git a/src/common/gen_server_ciphers.py b/src/common/gen_server_ciphers.py
deleted file mode 100755
index 97ed9d046..000000000
--- a/src/common/gen_server_ciphers.py
+++ /dev/null
@@ -1,115 +0,0 @@
-#!/usr/bin/python
-# Copyright 2014, The Tor Project, Inc
-# See LICENSE for licensing information
-
-# This script parses openssl headers to find ciphersuite names, determines
-# which ones we should be willing to use as a server, and sorts them according
-# to preference rules.
-#
-# Run it on all the files in your openssl include directory.
-
-import re
-import sys
-
-EPHEMERAL_INDICATORS = [ "_EDH_", "_DHE_", "_ECDHE_" ]
-BAD_STUFF = [ "_DES_40_", "MD5", "_RC4_", "_DES_64_",
- "_SEED_", "_CAMELLIA_", "_NULL" ]
-
-# these never get #ifdeffed.
-MANDATORY = [
- "TLS1_TXT_DHE_RSA_WITH_AES_256_SHA",
- "TLS1_TXT_DHE_RSA_WITH_AES_128_SHA",
- "SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA",
-]
-
-def find_ciphers(filename):
- with open(filename) as f:
- for line in f:
- m = re.search(r'(?:SSL3|TLS1)_TXT_\w+', line)
- if m:
- yield m.group(0)
-
-def usable_cipher(ciph):
- ephemeral = False
- for e in EPHEMERAL_INDICATORS:
- if e in ciph:
- ephemeral = True
- if not ephemeral:
- return False
-
- if "_RSA_" not in ciph:
- return False
-
- for b in BAD_STUFF:
- if b in ciph:
- return False
- return True
-
-# All fields we sort on, in order of priority.
-FIELDS = [ 'cipher', 'fwsec', 'mode', 'digest', 'bitlength' ]
-# Map from sorted fields to recognized value in descending order of goodness
-FIELD_VALS = { 'cipher' : [ 'AES', 'DES'],
- 'fwsec' : [ 'ECDHE', 'DHE' ],
- 'mode' : [ 'GCM', 'CBC' ],
- 'digest' : [ 'SHA384', 'SHA256', 'SHA' ],
- 'bitlength' : [ '256', '128', '192' ],
-}
-
-class Ciphersuite(object):
- def __init__(self, name, fwsec, cipher, bitlength, mode, digest):
- self.name = name
- self.fwsec = fwsec
- self.cipher = cipher
- self.bitlength = bitlength
- self.mode = mode
- self.digest = digest
-
- for f in FIELDS:
- assert(getattr(self, f) in FIELD_VALS[f])
-
- def sort_key(self):
- return tuple(FIELD_VALS[f].index(getattr(self,f)) for f in FIELDS)
-
-
-def parse_cipher(ciph):
- m = re.match('(?:TLS1|SSL3)_TXT_(EDH|DHE|ECDHE)_RSA(?:_WITH)?_(AES|DES)_(256|128|192)(|_CBC|_CBC3|_GCM)_(SHA|SHA256|SHA384)$', ciph)
-
- if not m:
- print "/* Couldn't parse %s ! */"%ciph
- return None
-
- fwsec, cipher, bits, mode, digest = m.groups()
- if fwsec == 'EDH':
- fwsec = 'DHE'
-
- if mode in [ '_CBC3', '_CBC', '' ]:
- mode = 'CBC'
- elif mode == '_GCM':
- mode = 'GCM'
-
- return Ciphersuite(ciph, fwsec, cipher, bits, mode, digest)
-
-ALL_CIPHERS = []
-
-for fname in sys.argv[1:]:
- ALL_CIPHERS += (parse_cipher(c)
- for c in find_ciphers(fname)
- if usable_cipher(c) )
-
-ALL_CIPHERS.sort(key=Ciphersuite.sort_key)
-
-for c in ALL_CIPHERS:
- if c is ALL_CIPHERS[-1]:
- colon = ';'
- else:
- colon = ' ":"'
-
- if c.name in MANDATORY:
- print " /* Required */"
- print ' %s%s'%(c.name,colon)
- else:
- print "#ifdef %s"%c.name
- print ' %s%s'%(c.name,colon)
- print "#endif"
-
-
diff --git a/src/common/get_mozilla_ciphers.py b/src/common/get_mozilla_ciphers.py
deleted file mode 100644
index 0636eb365..000000000
--- a/src/common/get_mozilla_ciphers.py
+++ /dev/null
@@ -1,210 +0,0 @@
-#!/usr/bin/python
-# coding=utf-8
-# Copyright 2011, The Tor Project, Inc
-# original version by Arturo Filastò
-# See LICENSE for licensing information
-
-# This script parses Firefox and OpenSSL sources, and uses this information
-# to generate a ciphers.inc file.
-#
-# It takes two arguments: the location of a firefox source directory, and the
-# location of an openssl source directory.
-
-import os
-import re
-import sys
-
-if len(sys.argv) != 3:
- print >>sys.stderr, "Syntax: get_mozilla_ciphers.py <firefox-source-dir> <openssl-source-dir>"
- sys.exit(1)
-
-ff_root = sys.argv[1]
-ossl_root = sys.argv[2]
-
-def ff(s):
- return os.path.join(ff_root, s)
-def ossl(s):
- return os.path.join(ossl_root, s)
-
-#####
-# Read the cpp file to understand what Ciphers map to what name :
-# Make "ciphers" a map from name used in the javascript to a cipher macro name
-fileA = open(ff('security/manager/ssl/src/nsNSSComponent.cpp'),'r')
-
-# The input format is a file containing exactly one section of the form:
-# static CipherPref CipherPrefs[] = {
-# {"name", MACRO_NAME}, // comment
-# ...
-# {NULL, 0}
-# }
-
-inCipherSection = False
-cipherLines = []
-for line in fileA:
- if line.startswith('static const CipherPref sCipherPrefs[]'):
- # Get the starting boundary of the Cipher Preferences
- inCipherSection = True
- elif inCipherSection:
- line = line.strip()
- if line.startswith('{ nullptr, 0}'):
- # At the ending boundary of the Cipher Prefs
- break
- else:
- cipherLines.append(line)
-fileA.close()
-
-# Parse the lines and put them into a dict
-ciphers = {}
-cipher_pref = {}
-key_pending = None
-for line in cipherLines:
- m = re.search(r'^{\s*\"([^\"]+)\",\s*(\S+)\s*(?:,\s*(true|false))?\s*}', line)
- if m:
- assert not key_pending
- key,value,enabled = m.groups()
- if enabled == 'true':
- ciphers[key] = value
- cipher_pref[value] = key
- continue
- m = re.search(r'^{\s*\"([^\"]+)\",', line)
- if m:
- assert not key_pending
- key_pending = m.group(1)
- continue
- m = re.search(r'^\s*(\S+)(?:,\s*(true|false))?\s*}', line)
- if m:
- assert key_pending
- key = key_pending
- value,enabled = m.groups()
- key_pending = None
- if enabled == 'true':
- ciphers[key] = value
- cipher_pref[value] = key
-
-####
-# Now find the correct order for the ciphers
-fileC = open(ff('security/nss/lib/ssl/ssl3con.c'), 'r')
-firefox_ciphers = []
-inEnum=False
-for line in fileC:
- if not inEnum:
- if "ssl3CipherSuiteCfg cipherSuites[" in line:
- inEnum = True
- continue
-
- if line.startswith("};"):
- break
-
- m = re.match(r'^\s*\{\s*([A-Z_0-9]+),', line)
- if m:
- firefox_ciphers.append(m.group(1))
-
-fileC.close()
-
-#####
-# Read the JS file to understand what ciphers are enabled. The format is
-# pref("name", true/false);
-# Build a map enabled_ciphers from javascript name to "true" or "false",
-# and an (unordered!) list of the macro names for those ciphers that are
-# enabled.
-fileB = open(ff('netwerk/base/public/security-prefs.js'), 'r')
-
-enabled_ciphers = {}
-for line in fileB:
- m = re.match(r'pref\(\"([^\"]+)\"\s*,\s*(\S*)\s*\)', line)
- if not m:
- continue
- key, val = m.groups()
- if key.startswith("security.ssl3"):
- enabled_ciphers[key] = val
-fileB.close()
-
-used_ciphers = []
-for k, v in enabled_ciphers.items():
- if v == "true":
- used_ciphers.append(ciphers[k])
-
-#oSSLinclude = ('/usr/include/openssl/ssl3.h', '/usr/include/openssl/ssl.h',
-# '/usr/include/openssl/ssl2.h', '/usr/include/openssl/ssl23.h',
-# '/usr/include/openssl/tls1.h')
-oSSLinclude = ('ssl/ssl3.h', 'ssl/ssl.h',
- 'ssl/ssl2.h', 'ssl/ssl23.h',
- 'ssl/tls1.h')
-
-#####
-# This reads the hex code for the ciphers that are used by firefox.
-# sslProtoD is set to a map from macro name to macro value in sslproto.h;
-# cipher_codes is set to an (unordered!) list of these hex values.
-sslProto = open(ff('security/nss/lib/ssl/sslproto.h'), 'r')
-sslProtoD = {}
-
-for line in sslProto:
- m = re.match('#define\s+(\S+)\s+(\S+)', line)
- if m:
- key, value = m.groups()
- sslProtoD[key] = value
-sslProto.close()
-
-cipher_codes = []
-for x in used_ciphers:
- cipher_codes.append(sslProtoD[x].lower())
-
-####
-# Now read through all the openssl include files, and try to find the openssl
-# macro names for those files.
-openssl_macro_by_hex = {}
-all_openssl_macros = {}
-for fl in oSSLinclude:
- fp = open(ossl(fl), 'r')
- for line in fp.readlines():
- m = re.match('#define\s+(\S+)\s+(\S+)', line)
- if m:
- value,key = m.groups()
- if key.startswith('0x') and "_CK_" in value:
- key = key.replace('0x0300','0x').lower()
- #print "%s %s" % (key, value)
- openssl_macro_by_hex[key] = value
- all_openssl_macros[value]=key
- fp.close()
-
-# Now generate the output.
-print """\
-/* This is an include file used to define the list of ciphers clients should
- * advertise. Before including it, you should define the CIPHER and XCIPHER
- * macros.
- *
- * This file was automatically generated by get_mozilla_ciphers.py.
- */"""
-# Go in order by the order in CipherPrefs
-for firefox_macro in firefox_ciphers:
-
- try:
- js_cipher_name = cipher_pref[firefox_macro]
- except KeyError:
- # This one has no javascript preference.
- continue
-
- # The cipher needs to be enabled in security-prefs.js
- if enabled_ciphers.get(js_cipher_name, 'false') != 'true':
- continue
-
- hexval = sslProtoD[firefox_macro].lower()
-
- try:
- openssl_macro = openssl_macro_by_hex[hexval.lower()]
- openssl_macro = openssl_macro.replace("_CK_", "_TXT_")
- if openssl_macro not in all_openssl_macros:
- raise KeyError()
- format = {'hex':hexval, 'macro':openssl_macro, 'note':""}
- except KeyError:
- # openssl doesn't have a macro for this.
- format = {'hex':hexval, 'macro':firefox_macro,
- 'note':"/* No openssl macro found for "+hexval+" */\n"}
-
- res = """\
-%(note)s#ifdef %(macro)s
- CIPHER(%(hex)s, %(macro)s)
-#else
- XCIPHER(%(hex)s, %(macro)s)
-#endif""" % format
- print res
diff --git a/src/common/linux_syscalls.inc b/src/common/linux_syscalls.inc
index 912735660..cf47c7380 100644
--- a/src/common/linux_syscalls.inc
+++ b/src/common/linux_syscalls.inc
@@ -1,5 +1,5 @@
/* Automatically generated with
- gen_sandbox_syscalls.pl /usr/include/asm/unistd*.h
+ gen_linux_syscalls.pl /usr/include/asm/unistd*.h
Do not edit.
*/
static const struct {
diff --git a/src/ext/README b/src/ext/README
index 58ba7f699..5d5a6e151 100644
--- a/src/ext/README
+++ b/src/ext/README
@@ -42,3 +42,10 @@ curve25519_donna/*.c
A copy of Adam Langley's curve25519-donna mostly-portable
implementations of curve25519.
+
+csiphash.c
+siphash.h
+
+ Marek Majkowski's implementation of siphash 2-4, a secure keyed
+ hash algorithm to avoid collision-based DoS attacks against hash
+ tables.
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index cd92326b3..9d06759de 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -9,6 +9,8 @@
* \brief The actual details of building circuits.
**/
+#define CIRCUITBUILD_PRIVATE
+
#include "or.h"
#include "channel.h"
#include "circpathbias.h"
@@ -83,7 +85,7 @@ channel_connect_for_circuit(const tor_addr_t *addr, uint16_t port,
*
* Return it, or 0 if can't get a unique circ_id.
*/
-static circid_t
+STATIC circid_t
get_unique_circ_id_by_chan(channel_t *chan)
{
/* This number is chosen somewhat arbitrarily; see comment below for more
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index ebcb22c45..71caea94e 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -58,5 +58,9 @@ const char *build_state_get_exit_nickname(cpath_build_state_t *state);
const node_t *choose_good_entry_server(uint8_t purpose,
cpath_build_state_t *state);
+#ifdef CIRCUITBUILD_PRIVATE
+STATIC circid_t get_unique_circ_id_by_chan(channel_t *chan);
+#endif
+
#endif
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 90fc93f3a..e5ed9c04f 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -76,7 +76,15 @@ chan_circid_entries_eq_(chan_circid_circuit_map_t *a,
static INLINE unsigned int
chan_circid_entry_hash_(chan_circid_circuit_map_t *a)
{
- return ((unsigned)a->circ_id) ^ (unsigned)(uintptr_t)(a->chan);
+ /* Try to squeze the siphash input into 8 bytes to save any extra siphash
+ * rounds. This hash function is in the critical path. */
+ uintptr_t chan = (uintptr_t) (void*) a->chan;
+ uint32_t array[2];
+ array[0] = a->circ_id;
+ /* The low bits of the channel pointer are uninteresting, since the channel
+ * is a pretty big structure. */
+ array[1] = (uint32_t) (chan >> 6);
+ return (unsigned) siphash24g(array, sizeof(array));
}
/** Map from [chan,circid] to circuit. */
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index d10430668..9d2decf57 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -783,6 +783,64 @@ circuit_expire_building(void)
}
}
+/**
+ * As a diagnostic for bug 8387, log information about how many one-hop
+ * circuits we have around that have been there for at least <b>age</b>
+ * seconds. Log a few of them.
+ */
+void
+circuit_log_ancient_one_hop_circuits(int age)
+{
+#define MAX_ANCIENT_ONEHOP_CIRCUITS_TO_LOG 10
+ time_t cutoff = time(NULL) - age;
+ int n_found = 0;
+ smartlist_t *log_these = smartlist_new();
+ const circuit_t *circ;
+
+ TOR_LIST_FOREACH(circ, circuit_get_global_list(), head) {
+ const origin_circuit_t *ocirc;
+ if (! CIRCUIT_IS_ORIGIN(circ))
+ continue;
+ if (circ->timestamp_created.tv_sec >= cutoff)
+ continue;
+ ocirc = CONST_TO_ORIGIN_CIRCUIT(circ);
+
+ if (ocirc->build_state && ocirc->build_state->onehop_tunnel) {
+ ++n_found;
+
+ if (smartlist_len(log_these) < MAX_ANCIENT_ONEHOP_CIRCUITS_TO_LOG)
+ smartlist_add(log_these, (origin_circuit_t*) ocirc);
+ }
+ }
+
+ if (n_found == 0)
+ goto done;
+
+ log_notice(LD_HEARTBEAT,
+ "Diagnostic for issue 8387: Found %d one-hop circuits more "
+ "than %d seconds old! Logging %d...",
+ n_found, age, smartlist_len(log_these));
+
+ SMARTLIST_FOREACH_BEGIN(log_these, const origin_circuit_t *, ocirc) {
+ char created[ISO_TIME_LEN+1];
+ circ = TO_CIRCUIT(ocirc);
+ format_local_iso_time(created,
+ circ->timestamp_created.tv_sec);
+
+ log_notice(LD_HEARTBEAT, " #%d created at %s. %s, %s. %s for close. "
+ "%s for new conns.",
+ ocirc_sl_idx,
+ created,
+ circuit_state_to_string(circ->state),
+ circuit_purpose_to_string(circ->purpose),
+ circ->marked_for_close ? "Marked" : "Not marked",
+ ocirc->unusable_for_new_conns ? "Not usable" : "usable");
+ } SMARTLIST_FOREACH_END(ocirc);
+
+ done:
+ smartlist_free(log_these);
+}
+
/** Remove any elements in <b>needed_ports</b> that are handled by an
* open or in-progress circuit.
*/
diff --git a/src/or/circuituse.h b/src/or/circuituse.h
index 11e5a6416..f228a6758 100644
--- a/src/or/circuituse.h
+++ b/src/or/circuituse.h
@@ -16,6 +16,7 @@ void circuit_expire_building(void);
void circuit_remove_handled_ports(smartlist_t *needed_ports);
int circuit_stream_is_being_handled(entry_connection_t *conn, uint16_t port,
int min);
+void circuit_log_ancient_one_hop_circuits(int age);
#if 0
int circuit_conforms_to_options(const origin_circuit_t *circ,
const or_options_t *options);
diff --git a/src/or/directory.c b/src/or/directory.c
index 76cb8fa0b..428fd01be 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -3065,22 +3065,6 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
goto done;
}
- if (!strcmp(url,"/tor/dbg-stability.txt")) {
- const char *stability;
- size_t len;
- if (options->BridgeAuthoritativeDir ||
- ! authdir_mode_tests_reachability(options) ||
- ! (stability = rep_hist_get_router_stability_doc(time(NULL)))) {
- write_http_status_line(conn, 404, "Not found.");
- goto done;
- }
-
- len = strlen(stability);
- write_http_response_header(conn, len, 0, 0);
- connection_write_to_buf(stability, len, TO_CONN(conn));
- goto done;
- }
-
#if defined(EXPORTMALLINFO) && defined(HAVE_MALLOC_H) && defined(HAVE_MALLINFO)
#define ADD_MALLINFO_LINE(x) do { \
smartlist_add_asprintf(lines, "%s %d\n", #x, mi.x); \
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index 4d3ee9cdb..c7be343ca 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -3588,6 +3588,12 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method)
tor_free(p6);
}
+ if (consensus_method >= MIN_METHOD_FOR_ID_HASH_IN_MD) {
+ char idbuf[BASE64_DIGEST_LEN+1];
+ digest_to_base64(idbuf, ri->cache_info.identity_digest);
+ smartlist_add_asprintf(chunks, "id rsa1024 %s\n", idbuf);
+ }
+
output = smartlist_join_strings(chunks, "", 0, NULL);
{
@@ -3657,7 +3663,8 @@ static const struct consensus_method_range_t {
{MIN_METHOD_FOR_MICRODESC, MIN_METHOD_FOR_A_LINES - 1},
{MIN_METHOD_FOR_A_LINES, MIN_METHOD_FOR_P6_LINES - 1},
{MIN_METHOD_FOR_P6_LINES, MIN_METHOD_FOR_NTOR_KEY - 1},
- {MIN_METHOD_FOR_NTOR_KEY, MAX_SUPPORTED_CONSENSUS_METHOD},
+ {MIN_METHOD_FOR_NTOR_KEY, MIN_METHOD_FOR_ID_HASH_IN_MD - 1},
+ {MIN_METHOD_FOR_ID_HASH_IN_MD, MAX_SUPPORTED_CONSENSUS_METHOD},
{-1, -1}
};
diff --git a/src/or/dirvote.h b/src/or/dirvote.h
index 3a4951a95..4c57e4366 100644
--- a/src/or/dirvote.h
+++ b/src/or/dirvote.h
@@ -22,7 +22,7 @@
#define MIN_VOTE_INTERVAL 300
/** The highest consensus method that we currently support. */
-#define MAX_SUPPORTED_CONSENSUS_METHOD 17
+#define MAX_SUPPORTED_CONSENSUS_METHOD 18
/** Lowest consensus method that contains a 'directory-footer' marker */
#define MIN_METHOD_FOR_FOOTER 9
@@ -61,6 +61,10 @@
* Unmeasured=1 flag for unmeasured bandwidths */
#define MIN_METHOD_TO_CLIP_UNMEASURED_BW 17
+/** Lowest consensus method where authorities may include an "id" line in
+ * microdescriptors. */
+#define MIN_METHOD_FOR_ID_HASH_IN_MD 18
+
/** Default bandwidth to clip unmeasured bandwidths to using method >=
* MIN_METHOD_TO_CLIP_UNMEASURED_BW */
#define DEFAULT_MAX_UNMEASURED_BW_KB 20
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 70be39e23..a0f24e18f 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -879,126 +879,6 @@ rep_hist_record_mtbf_data(time_t now, int missing_means_down)
return -1;
}
-/** Format the current tracked status of the router in <b>hist</b> at time
- * <b>now</b> for analysis; return it in a newly allocated string. */
-static char *
-rep_hist_format_router_status(or_history_t *hist, time_t now)
-{
- char sor_buf[ISO_TIME_LEN+1];
- char sod_buf[ISO_TIME_LEN+1];
- double wfu;
- double mtbf;
- int up = 0, down = 0;
- char *cp = NULL;
-
- if (hist->start_of_run) {
- format_iso_time(sor_buf, hist->start_of_run);
- up = 1;
- }
- if (hist->start_of_downtime) {
- format_iso_time(sod_buf, hist->start_of_downtime);
- down = 1;
- }
-
- wfu = get_weighted_fractional_uptime(hist, now);
- mtbf = get_stability(hist, now);
- tor_asprintf(&cp,
- "%s%s%s"
- "%s%s%s"
- "wfu %0.3f\n"
- " weighted-time %lu\n"
- " weighted-uptime %lu\n"
- "mtbf %0.1f\n"
- " weighted-run-length %lu\n"
- " total-run-weights %f\n",
- up?"uptime-started ":"", up?sor_buf:"", up?" UTC\n":"",
- down?"downtime-started ":"", down?sod_buf:"", down?" UTC\n":"",
- wfu,
- hist->total_weighted_time,
- hist->weighted_uptime,
- mtbf,
- hist->weighted_run_length,
- hist->total_run_weights
- );
- return cp;
-}
-
-/** The last stability analysis document that we created, or NULL if we never
- * have created one. */
-static char *last_stability_doc = NULL;
-/** The last time we created a stability analysis document, or 0 if we never
- * have created one. */
-static time_t built_last_stability_doc_at = 0;
-/** Shortest allowable time between building two stability documents. */
-#define MAX_STABILITY_DOC_BUILD_RATE (3*60)
-
-/** Return a pointer to a NUL-terminated document describing our view of the
- * stability of the routers we've been tracking. Return NULL on failure. */
-const char *
-rep_hist_get_router_stability_doc(time_t now)
-{
- char *result;
- smartlist_t *chunks;
- if (built_last_stability_doc_at + MAX_STABILITY_DOC_BUILD_RATE > now)
- return last_stability_doc;
-
- if (!history_map)
- return NULL;
-
- tor_free(last_stability_doc);
- chunks = smartlist_new();
-
- if (rep_hist_have_measured_enough_stability()) {
- smartlist_add(chunks, tor_strdup("we-have-enough-measurements\n"));
- } else {
- smartlist_add(chunks, tor_strdup("we-do-not-have-enough-measurements\n"));
- }
-
- DIGESTMAP_FOREACH(history_map, id, or_history_t *, hist) {
- const node_t *node;
- char dbuf[BASE64_DIGEST_LEN+1];
- char *info;
- digest_to_base64(dbuf, id);
- node = node_get_by_id(id);
- if (node) {
- char ip[INET_NTOA_BUF_LEN+1];
- char tbuf[ISO_TIME_LEN+1];
- time_t published = node_get_published_on(node);
- node_get_address_string(node,ip,sizeof(ip));
- if (published > 0)
- format_iso_time(tbuf, published);
- else
- strlcpy(tbuf, "???", sizeof(tbuf));
- smartlist_add_asprintf(chunks,
- "router %s %s %s\n"
- "published %s\n"
- "relevant-flags %s%s%s\n"
- "declared-uptime %ld\n",
- dbuf, node_get_nickname(node), ip,
- tbuf,
- node->is_running ? "Running " : "",
- node->is_valid ? "Valid " : "",
- node->ri && node->ri->is_hibernating ? "Hibernating " : "",
- node_get_declared_uptime(node));
- } else {
- smartlist_add_asprintf(chunks,
- "router %s {no descriptor}\n", dbuf);
- }
- info = rep_hist_format_router_status(hist, now);
- if (info)
- smartlist_add(chunks, info);
-
- } DIGESTMAP_FOREACH_END;
-
- result = smartlist_join_strings(chunks, "", 0, NULL);
- SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
- smartlist_free(chunks);
-
- last_stability_doc = result;
- built_last_stability_doc_at = time(NULL);
- return result;
-}
-
/** Helper: return the first j >= i such that !strcmpstart(sl[j], prefix) and
* such that no line sl[k] with i <= k < j starts with "R ". Return -1 if no
* such line exists. */
@@ -3041,11 +2921,9 @@ rep_hist_free_all(void)
tor_free(write_array);
tor_free(dir_read_array);
tor_free(dir_write_array);
- tor_free(last_stability_doc);
tor_free(exit_bytes_read);
tor_free(exit_bytes_written);
tor_free(exit_streams);
- built_last_stability_doc_at = 0;
predicted_ports_free();
bidi_map_free();
diff --git a/src/or/rephist.h b/src/or/rephist.h
index df01ae6cb..cd6231e6e 100644
--- a/src/or/rephist.h
+++ b/src/or/rephist.h
@@ -47,7 +47,6 @@ double rep_hist_get_stability(const char *id, time_t when);
double rep_hist_get_weighted_fractional_uptime(const char *id, time_t when);
long rep_hist_get_weighted_time_known(const char *id, time_t when);
int rep_hist_have_measured_enough_stability(void);
-const char *rep_hist_get_router_stability_doc(time_t now);
void rep_hist_note_used_port(time_t now, uint16_t port);
smartlist_t *rep_hist_get_predicted_ports(time_t now);
diff --git a/src/or/status.c b/src/or/status.c
index 7e2afbce8..afaa9de84 100644
--- a/src/or/status.c
+++ b/src/or/status.c
@@ -9,6 +9,7 @@
#define STATUS_PRIVATE
#include "or.h"
+#include "circuituse.h"
#include "config.h"
#include "status.h"
#include "nodelist.h"
@@ -135,6 +136,8 @@ log_heartbeat(time_t now)
if (public_server_mode(options))
rep_hist_log_circuit_handshake_stats(now);
+ circuit_log_ancient_one_hop_circuits(1800);
+
tor_free(uptime);
tor_free(bw_sent);
tor_free(bw_rcvd);
diff --git a/src/test/bench.c b/src/test/bench.c
index c9cc101b7..f6c33626f 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -338,6 +338,28 @@ bench_dmap(void)
}
static void
+bench_siphash(void)
+{
+ char buf[128];
+ int lens[] = { 7, 8, 15, 16, 20, 32, 111, 128, -1 };
+ int i, j;
+ uint64_t start, end;
+ const int N = 300000;
+ crypto_rand(buf, sizeof(buf));
+
+ for (i = 0; lens[i] > 0; ++i) {
+ reset_perftime();
+ start = perftime();
+ for (j = 0; j < N; ++j) {
+ siphash24g(buf, lens[i]);
+ }
+ end = perftime();
+ printf("siphash24g(%d): %.2f ns per call\n",
+ lens[i], NANOCOUNT(start,end,N));
+ }
+}
+
+static void
bench_cell_ops(void)
{
const int iters = 1<<16;
@@ -487,6 +509,7 @@ typedef struct benchmark_t {
static struct benchmark_t benchmarks[] = {
ENT(dmap),
+ ENT(siphash),
ENT(aes),
ENT(onion_TAP),
#ifdef CURVE25519_ENABLED
diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c
index cff2db1ba..e86ec8ea8 100644
--- a/src/test/test_buffers.c
+++ b/src/test/test_buffers.c
@@ -597,6 +597,53 @@ test_buffer_time_tracking(void *arg)
buf_free(buf2);
}
+static void
+test_buffers_zlib(void *arg)
+{
+ char *msg = NULL;
+ char *contents = NULL;
+ char *expanded = NULL;
+ buf_t *buf = NULL;
+ tor_zlib_state_t *zlib_state = NULL;
+ size_t out_len, in_len;
+
+ (void) arg;
+
+ buf = buf_new_with_capacity(128); /* will round up */
+ zlib_state = tor_zlib_new(1, ZLIB_METHOD);
+
+ msg = tor_malloc(512);
+ crypto_rand(msg, 512);
+ tt_int_op(write_to_buf_zlib(buf, zlib_state, msg, 128, 0), ==, 0);
+ tt_int_op(write_to_buf_zlib(buf, zlib_state, msg+128, 128, 0), ==, 0);
+ tt_int_op(write_to_buf_zlib(buf, zlib_state, msg+256, 256, 0), ==, 0);
+ tt_int_op(write_to_buf_zlib(buf, zlib_state, "all done", 9, 1), ==, 0);
+
+ in_len = buf_datalen(buf);
+ contents = tor_malloc(in_len);
+
+ tt_int_op(fetch_from_buf(contents, in_len, buf), ==, 0);
+
+ tt_int_op(0, ==, tor_gzip_uncompress(&expanded, &out_len,
+ contents, in_len,
+ ZLIB_METHOD, 1,
+ LOG_WARN));
+
+ tt_int_op(out_len, >=, 128);
+ tt_mem_op(msg, ==, expanded, 128);
+ tt_int_op(out_len, >=, 512);
+ tt_mem_op(msg, ==, expanded, 512);
+ tt_int_op(out_len, ==, 512+9);
+ tt_mem_op("all done", ==, expanded+512, 9);
+
+ done:
+ buf_free(buf);
+ tor_zlib_free(zlib_state);
+ tor_free(contents);
+ tor_free(expanded);
+ tor_free(msg);
+}
+
struct testcase_t buffer_tests[] = {
{ "basic", test_buffers_basic, TT_FORK, NULL, NULL },
{ "copy", test_buffer_copy, TT_FORK, NULL, NULL },
@@ -605,6 +652,7 @@ struct testcase_t buffer_tests[] = {
{ "allocation_tracking", test_buffer_allocation_tracking, TT_FORK,
NULL, NULL },
{ "time_tracking", test_buffer_time_tracking, TT_FORK, NULL, NULL },
+ { "zlib", test_buffers_zlib, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c
index b0eb2fca2..d7f60680c 100644
--- a/src/test/test_cell_formats.c
+++ b/src/test/test_cell_formats.c
@@ -8,7 +8,9 @@
#define CONNECTION_EDGE_PRIVATE
#define RELAY_PRIVATE
#include "or.h"
+#include "channel.h"
#include "connection_edge.h"
+#include "connection_or.h"
#include "onion.h"
#include "onion_tap.h"
#include "onion_fast.h"
@@ -1212,6 +1214,47 @@ test_cfmt_resolved_cells(void *arg)
#undef CLEAR_CELL
}
+static void
+test_cfmt_is_destroy(void *arg)
+{
+ cell_t cell;
+ packed_cell_t packed;
+ circid_t circid = 0;
+ channel_t *chan;
+ (void)arg;
+
+ chan = tor_malloc_zero(sizeof(channel_t));
+
+ memset(&cell, 0xff, sizeof(cell));
+ cell.circ_id = 3003;
+ cell.command = CELL_RELAY;
+
+ cell_pack(&packed, &cell, 0);
+ chan->wide_circ_ids = 0;
+ tt_assert(! packed_cell_is_destroy(chan, &packed, &circid));
+ tt_int_op(circid, ==, 0);
+
+ cell_pack(&packed, &cell, 1);
+ chan->wide_circ_ids = 1;
+ tt_assert(! packed_cell_is_destroy(chan, &packed, &circid));
+ tt_int_op(circid, ==, 0);
+
+ cell.command = CELL_DESTROY;
+
+ cell_pack(&packed, &cell, 0);
+ chan->wide_circ_ids = 0;
+ tt_assert(packed_cell_is_destroy(chan, &packed, &circid));
+ tt_int_op(circid, ==, 3003);
+
+ circid = 0;
+ cell_pack(&packed, &cell, 1);
+ chan->wide_circ_ids = 1;
+ tt_assert(packed_cell_is_destroy(chan, &packed, &circid));
+
+ done:
+ tor_free(chan);
+}
+
#define TEST(name, flags) \
{ #name, test_cfmt_ ## name, flags, 0, NULL }
@@ -1224,6 +1267,7 @@ struct testcase_t cell_format_tests[] = {
TEST(extend_cells, 0),
TEST(extended_cells, 0),
TEST(resolved_cells, 0),
+ TEST(is_destroy, 0),
END_OF_TESTCASES
};
diff --git a/src/test/test_circuitlist.c b/src/test/test_circuitlist.c
index ad8d0ac3a..7b7d4153e 100644
--- a/src/test/test_circuitlist.c
+++ b/src/test/test_circuitlist.c
@@ -2,9 +2,11 @@
/* See LICENSE for licensing information */
#define TOR_CHANNEL_INTERNAL_
+#define CIRCUITBUILD_PRIVATE
#define CIRCUITLIST_PRIVATE
#include "or.h"
#include "channel.h"
+#include "circuitbuild.h"
#include "circuitlist.h"
#include "test.h"
@@ -257,9 +259,84 @@ test_rend_token_maps(void *arg)
circuit_free(TO_CIRCUIT(c4));
}
+static void
+test_pick_circid(void *arg)
+{
+ bitarray_t *ba = NULL;
+ channel_t *chan1, *chan2;
+ circid_t circid;
+ int i;
+ (void) arg;
+
+ chan1 = tor_malloc_zero(sizeof(channel_t));
+ chan2 = tor_malloc_zero(sizeof(channel_t));
+ chan2->wide_circ_ids = 1;
+
+ chan1->circ_id_type = CIRC_ID_TYPE_NEITHER;
+ tt_int_op(0, ==, get_unique_circ_id_by_chan(chan1));
+
+ /* Basic tests, with no collisions */
+ chan1->circ_id_type = CIRC_ID_TYPE_LOWER;
+ for (i = 0; i < 50; ++i) {
+ circid = get_unique_circ_id_by_chan(chan1);
+ tt_uint_op(0, <, circid);
+ tt_uint_op(circid, <, (1<<15));
+ }
+ chan1->circ_id_type = CIRC_ID_TYPE_HIGHER;
+ for (i = 0; i < 50; ++i) {
+ circid = get_unique_circ_id_by_chan(chan1);
+ tt_uint_op((1<<15), <, circid);
+ tt_uint_op(circid, <, (1<<16));
+ }
+
+ chan2->circ_id_type = CIRC_ID_TYPE_LOWER;
+ for (i = 0; i < 50; ++i) {
+ circid = get_unique_circ_id_by_chan(chan2);
+ tt_uint_op(0, <, circid);
+ tt_uint_op(circid, <, (1u<<31));
+ }
+ chan2->circ_id_type = CIRC_ID_TYPE_HIGHER;
+ for (i = 0; i < 50; ++i) {
+ circid = get_unique_circ_id_by_chan(chan2);
+ tt_uint_op((1u<<31), <, circid);
+ }
+
+ /* Now make sure that we can behave well when we are full up on circuits */
+ chan1->circ_id_type = CIRC_ID_TYPE_LOWER;
+ chan2->circ_id_type = CIRC_ID_TYPE_LOWER;
+ chan1->wide_circ_ids = chan2->wide_circ_ids = 0;
+ ba = bitarray_init_zero((1<<15));
+ for (i = 0; i < (1<<15); ++i) {
+ circid = get_unique_circ_id_by_chan(chan1);
+ if (circid == 0) {
+ tt_int_op(i, >, (1<<14));
+ break;
+ }
+ tt_uint_op(circid, <, (1<<15));
+ tt_assert(! bitarray_is_set(ba, circid));
+ bitarray_set(ba, circid);
+ channel_mark_circid_unusable(chan1, circid);
+ }
+ tt_int_op(i, <, (1<<15));
+ /* Make sure that being full on chan1 does not interfere with chan2 */
+ for (i = 0; i < 100; ++i) {
+ circid = get_unique_circ_id_by_chan(chan2);
+ tt_uint_op(circid, >, 0);
+ tt_uint_op(circid, <, (1<<15));
+ channel_mark_circid_unusable(chan2, circid);
+ }
+
+ done:
+ tor_free(chan1);
+ tor_free(chan2);
+ bitarray_free(ba);
+ circuit_free_all();
+}
+
struct testcase_t circuitlist_tests[] = {
{ "maps", test_clist_maps, TT_FORK, NULL, NULL },
{ "rend_token_maps", test_rend_token_maps, TT_FORK, NULL, NULL },
+ { "pick_circid", test_pick_circid, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
index 298248493..78f4823b8 100644
--- a/src/test/test_microdesc.c
+++ b/src/test/test_microdesc.c
@@ -5,7 +5,10 @@
#include "or.h"
#include "config.h"
+#include "dirvote.h"
#include "microdesc.h"
+#include "routerlist.h"
+#include "routerparse.h"
#include "test.h"
@@ -285,9 +288,113 @@ test_md_cache_broken(void *data)
microdesc_free_all();
}
+/* Generated by chutney. */
+static const char test_ri[] =
+ "router test005r 127.0.0.1 5005 0 7005\n"
+ "platform Tor 0.2.5.4-alpha-dev on Linux\n"
+ "protocols Link 1 2 Circuit 1\n"
+ "published 2014-05-06 22:57:55\n"
+ "fingerprint 09DE 3BA2 48C2 1C3F 3760 6CD3 8460 43A6 D5EC F59E\n"
+ "uptime 0\n"
+ "bandwidth 1073741824 1073741824 0\n"
+ "extra-info-digest 361F9428F9FA4DD854C03DDBCC159D0D9FA996C9\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n"
+ "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n"
+ "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "signing-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANbGUC4802Ke6C3nOVxN0U0HhIRrs32cQFEL4v+UUMJPgjbistHBvOax\n"
+ "CWVR/sMXM2kKJeGThJ9ZUs2p9dDG4WHPUXgkMqzTTEeeFa7pQKU0brgbmLaJq0Pi\n"
+ "mxmqC5RkTHa5bQvq6QlSFprAEoovV27cWqBM9jVdV9hyc//6kwPzAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "hidden-service-dir\n"
+ "ntor-onion-key Gg73xH7+kTfT6bi1uNVx9gwQdQas9pROIfmc4NpAdC4=\n"
+ "reject *:25\n"
+ "reject *:119\n"
+ "reject *:135-139\n"
+ "reject *:445\n"
+ "reject *:563\n"
+ "reject *:1214\n"
+ "reject *:4661-4666\n"
+ "reject *:6346-6429\n"
+ "reject *:6699\n"
+ "reject *:6881-6999\n"
+ "accept *:*\n"
+ "router-signature\n"
+ "-----BEGIN SIGNATURE-----\n"
+ "ImzX5PF2vRCrG1YzGToyjoxYhgh1vtHEDjmP+tIS/iil1DSnHZNpHSuHp0L1jE9S\n"
+ "yZyrtKaqpBE/aecAM3j4CWCn/ipnAAQkHcyRLin1bYvqBtRzyopVCRlUhF+uWrLq\n"
+ "t0xkIE39ss/EwmQr7iIgkdVH4oRIMsjYnFFJBG26nYY=\n"
+ "-----END SIGNATURE-----\n";
+
+static const char test_md_8[] =
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n"
+ "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n"
+ "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n";
+
+static const char test_md_16[] =
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n"
+ "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n"
+ "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key Gg73xH7+kTfT6bi1uNVx9gwQdQas9pROIfmc4NpAdC4=\n"
+ "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n";
+
+static const char test_md_18[] =
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBANBJz8Vldl12aFeSMPLiA4nOetLDN0oxU8bB1SDhO7Uu2zdWYVYAF5J0\n"
+ "st7WvrVy/jA9v/fsezNAPskBanecHRSkdMTpkcgRPMHE7CTGEwIy1Yp1X4bPgDlC\n"
+ "VCnbs5Pcts5HnWEYNK7qHDAUn+IlmjOO+pTUY8uyq+GQVz6H9wFlAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "ntor-onion-key Gg73xH7+kTfT6bi1uNVx9gwQdQas9pROIfmc4NpAdC4=\n"
+ "p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
+ "id rsa1024 Cd47okjCHD83YGzThGBDptXs9Z4\n";
+
+static void
+test_md_generate(void *arg)
+{
+ routerinfo_t *ri;
+ microdesc_t *md = NULL;
+ (void)arg;
+
+ ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL);
+ tt_assert(ri);
+ md = dirvote_create_microdescriptor(ri, 8);
+ tt_str_op(md->body, ==, test_md_8);
+
+ /* XXXX test family lines. */
+ /* XXXX test method 14 for A lines. */
+ /* XXXX test method 15 for P6 lines. */
+
+ microdesc_free(md);
+ md = NULL;
+ md = dirvote_create_microdescriptor(ri, 16);
+ tt_str_op(md->body, ==, test_md_16);
+
+ microdesc_free(md);
+ md = NULL;
+ md = dirvote_create_microdescriptor(ri, 18);
+ tt_str_op(md->body, ==, test_md_18);
+
+ done:
+ microdesc_free(md);
+ routerinfo_free(ri);
+}
+
struct testcase_t microdesc_tests[] = {
{ "cache", test_md_cache, TT_FORK, NULL, NULL },
{ "broken_cache", test_md_cache_broken, TT_FORK, NULL, NULL },
+ { "generate", test_md_generate, 0, NULL, NULL },
END_OF_TESTCASES
};