diff options
47 files changed, 665 insertions, 288 deletions
diff --git a/.gitignore b/.gitignore index 610965b858..26e9e3808a 100644 --- a/.gitignore +++ b/.gitignore @@ -144,6 +144,8 @@ # /src/test /src/test/Makefile /src/test/Makefile.in +/src/test/bench +/src/test/bench.exe /src/test/test /src/test/test-child /src/test/test.exe @@ -1,9 +1,29 @@ -Changes in version 0.2.3.8-alpha - 2011-11-?? +Changes in version 0.2.3.8-alpha - 2011-11-22 + Tor 0.2.3.8-alpha fixes some crash and assert bugs, including a + socketpair-related bug that has been bothering Windows users. It adds + support to serve microdescriptors to controllers, so Vidalia's network + map can resume listing relays (once Vidalia implements its side), + and adds better support for hardware AES acceleration. Finally, it + starts the process of adjusting the bandwidth cutoff for getting the + "Fast" flag from 20KB to (currently) 32KB -- preliminary results show + that tiny relays harm performance more than they help network capacity. + o Major bugfixes: + - Initialize Libevent with the EVENT_BASE_FLAG_NOLOCK flag enabled, so + that it doesn't attempt to allocate a socketpair. This could cause + some problems on Windows systems with overzealous firewalls. Fix for + bug 4457; workaround for Libevent versions 2.0.1-alpha through + 2.0.15-stable. - Correctly sanity-check that we don't underflow on a memory allocation (and then assert) for hidden service introduction point decryption. Bug discovered by Dan Rosenberg. Fixes bug 4410; bugfix on 0.2.1.5-alpha. + - Remove the artificially low cutoff of 20KB to guarantee the Fast + flag. In the past few years the average relay speed has picked + up, and while the "top 7/8 of the network get the Fast flag" and + "all relays with 20KB or more of capacity get the Fast flag" rules + used to have the same result, now the top 7/8 of the network has + a capacity more like 32KB. Bugfix on 0.2.1.14-rc. Fixes bug 4489. - Fix a rare assertion failure when checking whether a v0 hidden service descriptor has any usable introduction points left, and we don't have enough information to build a circuit to the first @@ -11,24 +31,120 @@ Changes in version 0.2.3.8-alpha - 2011-11-?? 0.2.3.x no longer uses v0 HS descriptors, but this assertion can trigger on (and crash) v0 HS authorities. Fixes bug 4411. Bugfix on 0.2.3.1-alpha; diagnosed by frosty_un. - - Don't crash when we, as the bridge authority, are asked for our own + - Make bridge authorities not crash when they are asked for their own descriptor. Bugfix on 0.2.3.7-alpha, reported by Lucky Green. + - When running as a client, do not print a misleading (and plain + wrong) log message that we're collecting "directory request" + statistics: clients don't collect statistics. Also don't create a + useless (because empty) stats file in the stats/ directory. Fixes + bug 4353; bugfix on 0.2.2.34 and 0.2.3.7-alpha. - o Minor bugfixes: + o Major features: + - Allow Tor controllers like Vidalia to obtain the microdescriptor + for a relay by identity digest or nickname. Previously, + microdescriptors were only available by their own digests, so a + controller would have to ask for and parse the whole microdescriptor + consensus in order to look up a single relay's microdesc. Fixes + bug 3832; bugfix on 0.2.3.1-alpha. + - Use OpenSSL's EVP interface for AES encryption, so that all AES + operations can use hardware acceleration (if present). Resolves + ticket 4442. + + o Minor bugfixes (on 0.2.2.x and earlier): + - Detect failure to initialize Libevent. This fix provides better + detection for future instances of bug 4457. + - Avoid frequent calls to the fairly expensive cull_wedged_cpuworkers + function. This was eating up hideously large amounts of time on some + busy servers. Fixes bug 4518; bugfix on 0.0.9.8. + - Don't warn about unused log_mutex in log.c when building with + --disable-threads using a recent GCC. Fixes bug 4437; bugfix on + 0.1.0.6-rc which introduced --disable-threads. + - Allow manual 'authenticate' commands to the controller interface + from netcat (nc) as well as telnet. We were rejecting them because + they didn't come with the expected whitespace at the end of the + command. Bugfix on 0.1.1.1-alpha; fixes bug 2893. + - Fix some (not actually triggerable) buffer size checks in usage of + tor_inet_ntop. Fixes bug 4434; bugfix on Tor 0.2.0.1-alpha. Patch + by Anders Sundman. + - Fix parsing of some corner-cases with tor_inet_pton(). Fixes + bug 4515; bugfix on 0.2.0.1-alpha; fix by Anders Sundman. + - When configuring, starting, or stopping an NT service, stop + immediately after the service configuration attempt has succeeded + or failed. Fixes bug 3963; bugfix on 0.2.0.7-alpha. + - When sending a NETINFO cell, include the original address + received for the other side, not its canonical address. Found + by "troll_un"; fixes bug 4349; bugfix on 0.2.0.10-alpha. + - Rename the bench_{aes,dmap} functions to test_*, so that tinytest + can pick them up when the tests aren't disabled. Bugfix on + 0.2.2.4-alpha which introduced tinytest. - Fix a memory leak when we check whether a hidden service descriptor has any usable introduction points left. Fixes bug 4424. Bugfix on 0.2.2.25-alpha. - Fix a memory leak in launch_direct_bridge_descriptor_fetch() that occurred when a client tried to fetch a descriptor for a bridge - in ExcludeNodes. Fixes #4383; bugfix on 0.2.2.25-alpha. + in ExcludeNodes. Fixes bug 4383; bugfix on 0.2.2.25-alpha. + + o Minor bugfixes (on 0.2.3.x): + - Make util unit tests build correctly with MSVC. Bugfix on + 0.2.3.3-alpha. Patch by Gisle Vanem. + - Successfully detect AUTH_CHALLENGE cells with no recognized + authentication type listed. Fixes bug 4367; bugfix on 0.2.3.6-alpha. + Found by frosty_un. + - If a relay receives an AUTH_CHALLENGE cell it can't answer, + it should still send a NETINFO cell to allow the connection to + become open. Fixes bug 4368; fix on 0.2.3.6-alpha; bug found by + "frosty". + - Log less loudly when we get an invalid authentication certificate + from a source other than a directory authority: it's not unusual + to see invalid certs because of clock skew. Fixes bug 4370; bugfix + on 0.2.3.6-alpha. + - Tolerate servers with more clock skew in their authentication + certificates than previously. Fixes bug 4371; bugfix on + 0.2.3.6-alpha. + - Fix a couple of compile warnings on Windows. Fixes bug 4469; bugfix + on 0.2.3.4-alpha and 0.2.3.6-alpha. + + o Minor features: + - Add two new config options for directory authorities: + AuthDirFastGuarantee sets a bandwidth threshold for guaranteeing the + Fast flag, and AuthDirGuardBWGuarantee sets a bandwidth threshold + that is always sufficient to satisfy the bandwidth requirement for + the Guard flag. Now it will be easier for researchers to simulate + Tor networks with different values. Resolves ticket 4484. + - When Tor ignores a hidden service specified in its configuration, + include the hidden service's directory in the warning message. + Previously, we would only tell the user that some hidden service + was ignored. Bugfix on 0.0.6; fixes bug 4426. + - When we fail to initialize Libevent, retry with IOCP disabled so we + don't need to turn on multi-threading support in Libevent, which in + turn requires a working socketpair(). This is a workaround for bug + 4457, which affects Libevent versions from 2.0.1-alpha through + 2.0.15-stable. + - Detect when we try to build on a platform that doesn't define + AF_UNSPEC to 0. We don't work there, so refuse to compile. + - Update to the November 1 2011 Maxmind GeoLite Country database. o Packaging changes: - - Make it easier to automate expert package builds on Windows + - Make it easier to automate expert package builds on Windows, by removing an absolute path from makensis.exe command. o Code simplifications and refactoring: - Remove some redundant #include directives throughout the code. Patch from Andrea Gelmini. + - Unconditionally use OpenSSL's AES implementation instead of our + old built-in one. OpenSSL's AES has been better for a while, and + relatively few servers should still be on any version of OpenSSL + that doesn't have good optimized assembly AES. + - Use the name "CERTS" consistently to refer to the new cell type; + we were calling it CERT in some places and CERTS in others. + + o Testing: + - Numerous new unit tests for functions in util.c and address.c by + Anders Sundman. + - The long-disabled benchmark tests are now split into their own + ./src/test/bench binary. + - The benchmark tests can now use more accurate timers than + gettimeofday() when such timers are available. Changes in version 0.2.3.7-alpha - 2011-10-30 diff --git a/changes/aes_hackery b/changes/aes_hackery deleted file mode 100644 index 739c8a0d66..0000000000 --- a/changes/aes_hackery +++ /dev/null @@ -1,11 +0,0 @@ - o Code simplification and refactoring: - - Unconditionally use OpenSSL's AES implementation instead of our - old built-in one. OpenSSL's AES has been better for a while, and - relatively few servers should still be on any version of OpenSSL - that doesn't have good optimized assembly AES. - - o Major features: - - Use OpenSSL's EVP interface for AES encryption, so that all - AES operations can use hardware acceleration (if present). - Resolves issue #4442. - diff --git a/changes/af_unspec b/changes/af_unspec deleted file mode 100644 index 19ef4b4ccf..0000000000 --- a/changes/af_unspec +++ /dev/null @@ -1,4 +0,0 @@ - o Minor features: - - Detect when we build on a platform that doesn't define AF_UNSPEC to 0. - We don't work there, so refuse to compile. - diff --git a/changes/bug2474 b/changes/bug2474 new file mode 100644 index 0000000000..02d3eb7ba9 --- /dev/null +++ b/changes/bug2474 @@ -0,0 +1,5 @@ + o Minor features + - Try to make the introductory warning message that Tor prints on + startup more useful for actually finding help and information. + Resolves bug2474. + diff --git a/changes/bug2893 b/changes/bug2893 deleted file mode 100644 index f6d235cf53..0000000000 --- a/changes/bug2893 +++ /dev/null @@ -1,5 +0,0 @@ - o Minor bugfixes: - - Allow manual 'authenticate' commands to the controller interface - from nc as well as telnet. We were rejecting them because they - didn't come with the expected whitespace at the end of the command. - Bugfix on 0.1.1.1-alpha; fixes bug 2893. diff --git a/changes/bug3832 b/changes/bug3832 deleted file mode 100644 index 230f0d797b..0000000000 --- a/changes/bug3832 +++ /dev/null @@ -1,9 +0,0 @@ - o Major features: - - - Allow Tor controllers like Vidalia to obtain the microdescriptor - for a relay by identity digest or nickname. Previously, - microdescriptors were only available by their own digests, so a - controller would have to ask for and parse the whole - microdescriptor consensus in order to look up a single relay's - microdesc. Fixes bug 3832; bugfix on 0.2.3.1-alpha. - diff --git a/changes/bug4230 b/changes/bug4230 new file mode 100644 index 0000000000..c1ba5847fc --- /dev/null +++ b/changes/bug4230 @@ -0,0 +1,5 @@ + o Minor bugfixes: + - Resolve an integer overflow bug in smartlist_ensure_capacity. + Fixes bug 4230; bugfix on Tor 0.1.0.1-rc. Based on a patch by + Mansour Moufid. + diff --git a/changes/bug4349 b/changes/bug4349 deleted file mode 100644 index 633916bdfd..0000000000 --- a/changes/bug4349 +++ /dev/null @@ -1,4 +0,0 @@ - o Minor bugfixes: - - When sending a NETINFO cell, include the original address - received for the other side, not its canonical address. Found - by "troll_un"; fixes bug 4349; bugfix on 0.2.0.10-alpha. diff --git a/changes/bug4367 b/changes/bug4367 deleted file mode 100644 index 77236d0e61..0000000000 --- a/changes/bug4367 +++ /dev/null @@ -1,5 +0,0 @@ - o Minor bugfixes: - - Successfully detect AUTH_CHALLENGE cells with no recognized - authentication type listed. Fixes bug 4367; bugfix on 0.2.3.6-alpha. - Found by frosty_un. - diff --git a/changes/bug4368 b/changes/bug4368 deleted file mode 100644 index 54b4882bc3..0000000000 --- a/changes/bug4368 +++ /dev/null @@ -1,4 +0,0 @@ - o Minor bugfixes: - - If a relay receives an AUTH_CHALLENGE it can't answer, it should - still send a NETINFO cell to allow the connection to become open. - Fixes bug 4368; fix on 0.2.3.6-alpha; bug found by "frosty". diff --git a/changes/bug4371 b/changes/bug4371 deleted file mode 100644 index 37e6faa840..0000000000 --- a/changes/bug4371 +++ /dev/null @@ -1,3 +0,0 @@ - o Minor bugfixes: - - Tolerate servers with more clock skew than previously. Fixes bug 4371; - bugfix on 0.2.3.6-alpha. diff --git a/changes/bug4426 b/changes/bug4426 deleted file mode 100644 index 1322243d09..0000000000 --- a/changes/bug4426 +++ /dev/null @@ -1,8 +0,0 @@ - o Minor features: - - - When Tor ignores a hidden service specified in its - configuration, include the hidden service's directory in the - warning message. Previously, we would only tell the user that - some hidden service was ignored. Bugfix on 0.0.6; fixes bug - 4426. - diff --git a/changes/bug4434 b/changes/bug4434 deleted file mode 100644 index d602088f41..0000000000 --- a/changes/bug4434 +++ /dev/null @@ -1,9 +0,0 @@ - o Minor bugfixes: - - Fix some (not actually triggerable) buffer size checks in usage of - tor_inet_ntop. Fixes bug 4434; bugfix on Tor 0.2.0.1-alpha. Patch - by Anders Sundman. - - o Testing: - - Numerous new unit tests for functions in util.c and address.c by - Anders Sundman. - diff --git a/changes/bug4437 b/changes/bug4437 deleted file mode 100644 index 985c670b15..0000000000 --- a/changes/bug4437 +++ /dev/null @@ -1,5 +0,0 @@ - o Minor bugfixes: - - Don't warn about unused log_mutex in log.c when building with - --disable-threads using a recent GCC. Fixes bug 4437; bugfix on - 0.1.0.6-rc which introduced --disable-threads. - diff --git a/changes/bug4457 b/changes/bug4457 deleted file mode 100644 index fe7c95ff80..0000000000 --- a/changes/bug4457 +++ /dev/null @@ -1,9 +0,0 @@ - o Minor bugfixes: - - Initialize Libevent with the EVENT_BASE_FLAG_NOLOCK flag enabled, so - that it doesn't attempt to allocate a socketpair. This could cause - some problems on windows systems with overzealous firewalls. Fix for - bug 4457; workaround for Libevent versions 2.0.1-alpha through - 2.0.15-stable. - - - Detect failure to initialize Libevent. Better detection for bug 4457. - diff --git a/changes/bug4457_master b/changes/bug4457_master deleted file mode 100644 index d394643b6d..0000000000 --- a/changes/bug4457_master +++ /dev/null @@ -1,6 +0,0 @@ - o Minor features: - - When we fail to initialize Libevent, retry with IOCP disabled so we - don't need to turn on multi-threading support in Libevent, which in - turn requires a working socketpair(). This is a workaround for bug - 4457, which affects Libevent versions from 2.0.1-alpha through - 2.0.15-stable. diff --git a/changes/bug4469 b/changes/bug4469 deleted file mode 100644 index e9e390ccfe..0000000000 --- a/changes/bug4469 +++ /dev/null @@ -1,4 +0,0 @@ - o Minor bugfixes: - - Fix a couple of compile warnings on Windows. Fixes bug 4469; bugfix - on 0.2.3.4-alpha and 0.2.3.6-alpha. - diff --git a/changes/bug4554 b/changes/bug4554 new file mode 100644 index 0000000000..e4754c29e9 --- /dev/null +++ b/changes/bug4554 @@ -0,0 +1,4 @@ + o Minor bugfixes: + - Fix a compile warning in tor_inet_pton(). Bugfix on 0.2.3.8-alpha; + fixes bug 4554. + diff --git a/changes/checkSpaces b/changes/checkSpaces new file mode 100644 index 0000000000..91f79ed0fa --- /dev/null +++ b/changes/checkSpaces @@ -0,0 +1,5 @@ + o Minor bugfixes: + - Prevent a false positive from the check-spaces script by disabling + the "whitespace between function name and (" check for functions + named 'op()'. + diff --git a/changes/fix-msvc b/changes/fix-msvc deleted file mode 100644 index 62f05476b9..0000000000 --- a/changes/fix-msvc +++ /dev/null @@ -1,4 +0,0 @@ - o Minor bugfixes: - - Make util unit tests build correctly with MSVC. Bugfix on - 0.2.3.3-alpha. Patch by Gisle Vanem. - diff --git a/changes/geoip-november2011 b/changes/geoip-november2011 deleted file mode 100644 index 3aa8dc05c2..0000000000 --- a/changes/geoip-november2011 +++ /dev/null @@ -1,3 +0,0 @@ - o Minor features: - - Update to the November 1 2011 Maxmind GeoLite Country database. - diff --git a/changes/test_bench b/changes/test_bench deleted file mode 100644 index 8ae895b116..0000000000 --- a/changes/test_bench +++ /dev/null @@ -1,5 +0,0 @@ - o Minor bugfixes: - - Rename the bench_{aes,dmap} functions to test_*, so that tinytest can - pick them up when the tests aren't disabled. Bugfix on 0.2.2.4-alpha - which introduced tinytest. - diff --git a/configure.in b/configure.in index 17f5c8d5e3..64d9d6db7b 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Copyright (c) 2007-2008, The Tor Project, Inc. dnl See LICENSE for licensing information AC_INIT -AM_INIT_AUTOMAKE(tor, 0.2.3.7-alpha) +AM_INIT_AUTOMAKE(tor, 0.2.3.8-alpha-dev) AM_CONFIG_HEADER(orconfig.h) AC_CANONICAL_HOST @@ -276,6 +276,7 @@ AC_SEARCH_LIBS(socket, [socket]) AC_SEARCH_LIBS(gethostbyname, [nsl]) AC_SEARCH_LIBS(dlopen, [dl]) AC_SEARCH_LIBS(inet_aton, [resolv]) +AC_SEARCH_LIBS([clock_gettime], [rt], [have_rt=yes]) if test "$enable_threads" = "yes"; then AC_SEARCH_LIBS(pthread_create, [pthread]) @@ -288,6 +289,7 @@ dnl exports strlcpy without defining it in a header. AC_CHECK_FUNCS( accept4 \ + clock_gettime \ flock \ ftime \ getaddrinfo \ @@ -363,9 +365,6 @@ dnl On Gnu/Linux or any place we require it, we'll add librt to the Libevent dnl linking for static builds. STATIC_LIBEVENT_FLAGS="" if test "$enable_static_libevent" = "yes"; then - dnl Determine if we have clock_gettime in librt - AC_SEARCH_LIBS([clock_gettime], [rt], - [have_rt=yes]) if test "$have_rt" = yes; then STATIC_LIBEVENT_FLAGS=" -lrt " fi diff --git a/contrib/checkSpace.pl b/contrib/checkSpace.pl index 6eb32e5620..a18df99b16 100755 --- a/contrib/checkSpace.pl +++ b/contrib/checkSpace.pl @@ -97,7 +97,7 @@ for $fn (@ARGV) { if ($1 ne "if" and $1 ne "while" and $1 ne "for" and $1 ne "switch" and $1 ne "return" and $1 ne "int" and $1 ne "elsif" and $1 ne "WINAPI" and $2 ne "WINAPI" and - $1 ne "void" and $1 ne "__attribute__") { + $1 ne "void" and $1 ne "__attribute__" and $1 ne "op") { print " fn ():$fn:$.\n"; } } diff --git a/contrib/tor-mingw.nsi.in b/contrib/tor-mingw.nsi.in index eadae39eef..8ea9f32b97 100644 --- a/contrib/tor-mingw.nsi.in +++ b/contrib/tor-mingw.nsi.in @@ -8,7 +8,7 @@ !include "LogicLib.nsh" !include "FileFunc.nsh" !insertmacro GetParameters -!define VERSION "0.2.3.7-alpha" +!define VERSION "0.2.3.8-alpha-dev" !define INSTALLER "tor-${VERSION}-win32.exe" !define WEBSITE "https://www.torproject.org/" !define LICENSE "LICENSE" diff --git a/doc/HACKING b/doc/HACKING index b0689d82c1..bc409dc0d0 100644 --- a/doc/HACKING +++ b/doc/HACKING @@ -473,7 +473,7 @@ git branches too. a while to see if anybody has problems building it. Try to get Sebastian or somebody to try building it on Windows. -6) Get at least two of weasel/arma/karsten to put the new version number +6) Get at least two of weasel/arma/sebastian to put the new version number in their approved versions list. 7) Sign the tarball, then sign and push the git tag: diff --git a/doc/tor.1.txt b/doc/tor.1.txt index b54735d383..f5be391052 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -1406,6 +1406,16 @@ DIRECTORY AUTHORITY SERVER OPTIONS Authoritative directories only. Like AuthDirMaxServersPerAddr, but applies to addresses shared with directory authorities. (Default: 5) +**AuthDirFastGuarantee** __N__ **bytes**|**KB**|**MB**|**GB**:: + Authoritative directories only. If non-zero, always vote the + Fast flag for any relay advertising this amount of capacity or + more. (Default: 100 KB) + +**AuthDirGuardBWGuarantee** __N__ **bytes**|**KB**|**MB**|**GB**:: + Authoritative directories only. If non-zero, this advertised capacity + or more is always sufficient to satisfy the bandwidth requirement + for the Guard flag. (Default: 250 KB) + **BridgePassword** __Password__:: If set, contains an HTTP authenticator that tells a bridge authority to serve all requested bridge information. Used for debugging. (Default: diff --git a/src/common/compat.c b/src/common/compat.c index ba49af757c..9a2c9d764b 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -1733,24 +1733,30 @@ tor_inet_pton(int af, const char *src, void *dst) return 0; if (TOR_ISXDIGIT(*src)) { char *next; + ssize_t len; long r = strtol(src, &next, 16); - if (next > 4+src) - return 0; - if (next == src) - return 0; - if (r<0 || r>65536) + tor_assert(next != NULL); + tor_assert(next != src); + + len = *next == '\0' ? eow - src : next - src; + if (len > 4) return 0; + if (len > 1 && !TOR_ISXDIGIT(src[1])) + return 0; /* 0x is not valid */ + tor_assert(r >= 0); + tor_assert(r < 65536); words[i++] = (uint16_t)r; setWords++; src = next; if (*src != ':' && src != eow) return 0; ++src; - } else if (*src == ':' && i > 0 && gapPos==-1) { + } else if (*src == ':' && i > 0 && gapPos == -1) { gapPos = i; ++src; - } else if (*src == ':' && i == 0 && src[1] == ':' && gapPos==-1) { + } else if (*src == ':' && i == 0 && src+1 < eow && src[1] == ':' && + gapPos == -1) { gapPos = i; src += 2; } else { diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c index 7a28c9bc9b..0cedef8d5e 100644 --- a/src/common/compat_libevent.c +++ b/src/common/compat_libevent.c @@ -243,8 +243,8 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg) * again. */ #if defined(MS_WINDOWS) && defined(USE_BUFFEREVENTS) if (torcfg->disable_iocp == 0) { - log_warn(LD_GENERAL, "Unable to initialize Libevent. Trying again with " - "IOCP disabled."); + log_warn(LD_GENERAL, "Unable to initialize Libevent. Trying again " + "with IOCP disabled."); } else #endif { @@ -254,7 +254,6 @@ tor_libevent_initialize(tor_libevent_cfg *torcfg) torcfg->disable_iocp = 1; goto retry; } - } #else the_event_base = event_init(); diff --git a/src/common/container.c b/src/common/container.c index 92bfd2ec89..31cc6c5a6c 100644 --- a/src/common/container.c +++ b/src/common/container.c @@ -62,13 +62,22 @@ smartlist_clear(smartlist_t *sl) static INLINE void smartlist_ensure_capacity(smartlist_t *sl, int size) { +#if SIZEOF_SIZE_T > SIZEOF_INT +#define MAX_CAPACITY (INT_MAX) +#else +#define MAX_CAPACITY (int)((SIZE_MAX / (sizeof(void*)))) +#endif if (size > sl->capacity) { - int higher = sl->capacity * 2; - while (size > higher) - higher *= 2; - tor_assert(higher > 0); /* detect overflow */ + int higher = sl->capacity; + if (PREDICT_UNLIKELY(size > MAX_CAPACITY/2)) { + tor_assert(size <= MAX_CAPACITY); + higher = MAX_CAPACITY; + } else { + while (size > higher) + higher *= 2; + } sl->capacity = higher; - sl->list = tor_realloc(sl->list, sizeof(void*)*sl->capacity); + sl->list = tor_realloc(sl->list, sizeof(void*)*((size_t)sl->capacity)); } } diff --git a/src/or/command.c b/src/or/command.c index a963d4210b..023f2bead5 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -49,7 +49,7 @@ uint64_t stats_n_netinfo_cells_processed = 0; /** How many CELL_VPADDING cells have we received, ever? */ uint64_t stats_n_vpadding_cells_processed = 0; /** How many CELL_CERTS cells have we received, ever? */ -uint64_t stats_n_cert_cells_processed = 0; +uint64_t stats_n_certs_cells_processed = 0; /** How many CELL_AUTH_CHALLENGE cells have we received, ever? */ uint64_t stats_n_auth_challenge_cells_processed = 0; /** How many CELL_AUTHENTICATE cells have we received, ever? */ @@ -63,7 +63,7 @@ static void command_process_destroy_cell(cell_t *cell, or_connection_t *conn); static void command_process_versions_cell(var_cell_t *cell, or_connection_t *conn); static void command_process_netinfo_cell(cell_t *cell, or_connection_t *conn); -static void command_process_cert_cell(var_cell_t *cell, +static void command_process_certs_cell(var_cell_t *cell, or_connection_t *conn); static void command_process_auth_challenge_cell(var_cell_t *cell, or_connection_t *conn); @@ -214,19 +214,19 @@ command_process_var_cell(var_cell_t *cell, or_connection_t *conn) #ifdef KEEP_TIMING_STATS /* how many of each cell have we seen so far this second? needs better * name. */ - static int num_versions=0, num_cert=0; + static int num_versions=0, num_certs=0; time_t now = time(NULL); if (now > current_second) { /* the second has rolled over */ /* print stats */ log_info(LD_OR, - "At end of second: %d versions (%d ms), %d cert (%d ms)", + "At end of second: %d versions (%d ms), %d certs (%d ms)", num_versions, versions_time/1000, - cert, cert_time/1000); + num_certs, certs_time/1000); - num_versions = num_cert = 0; - versions_time = cert_time = 0; + num_versions = num_certs = 0; + versions_time = certs_time = 0; /* remember which second it is, for next time */ current_second = now; @@ -293,9 +293,9 @@ command_process_var_cell(var_cell_t *cell, or_connection_t *conn) ++stats_n_vpadding_cells_processed; /* Do nothing */ break; - case CELL_CERT: - ++stats_n_cert_cells_processed; - PROCESS_CELL(cert, cell, conn); + case CELL_CERTS: + ++stats_n_certs_cells_processed; + PROCESS_CELL(certs, cell, conn); break; case CELL_AUTH_CHALLENGE: ++stats_n_auth_challenge_cells_processed; @@ -719,8 +719,8 @@ command_process_versions_cell(var_cell_t *cell, or_connection_t *conn) } } if (send_certs) { - if (connection_or_send_cert_cell(conn) < 0) { - log_warn(LD_OR, "Couldn't send cert cell"); + if (connection_or_send_certs_cell(conn) < 0) { + log_warn(LD_OR, "Couldn't send certs cell"); connection_mark_for_close(TO_CONN(conn)); return; } @@ -887,9 +887,9 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn) assert_connection_ok(TO_CONN(conn),time(NULL)); } -/** Process a CERT cell from an OR connection. +/** Process a CERTS cell from an OR connection. * - * If the other side should not have sent us a CERT cell, or the cell is + * If the other side should not have sent us a CERTS cell, or the cell is * malformed, or it is supposed to authenticate the TLS key but it doesn't, * then mark the connection. * @@ -899,12 +899,12 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn) * If it's the server side, wait for an AUTHENTICATE cell. */ static void -command_process_cert_cell(var_cell_t *cell, or_connection_t *conn) +command_process_certs_cell(var_cell_t *cell, or_connection_t *conn) { #define ERR(s) \ do { \ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ - "Received a bad CERT cell from %s:%d: %s", \ + "Received a bad CERTS cell from %s:%d: %s", \ safe_str(conn->_base.address), conn->_base.port, (s)); \ connection_mark_for_close(TO_CONN(conn)); \ goto err; \ @@ -921,7 +921,7 @@ command_process_cert_cell(var_cell_t *cell, or_connection_t *conn) ERR("We're not doing a v3 handshake!"); if (conn->link_proto < 3) ERR("We're not using link protocol >= 3"); - if (conn->handshake_state->received_cert_cell) + if (conn->handshake_state->received_certs_cell) ERR("We already got one"); if (conn->handshake_state->authenticated) { /* Should be unreachable, but let's make sure. */ @@ -951,7 +951,7 @@ command_process_cert_cell(var_cell_t *cell, or_connection_t *conn) tor_cert_t *cert = tor_cert_decode(ptr + 3, cert_len); if (!cert) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Received undecodable certificate in CERT cell from %s:%d", + "Received undecodable certificate in CERTS cell from %s:%d", safe_str(conn->_base.address), conn->_base.port); } else { if (cert_type == OR_CERT_TYPE_TLS_LINK) { @@ -985,15 +985,24 @@ command_process_cert_cell(var_cell_t *cell, or_connection_t *conn) } if (conn->handshake_state->started_here) { + int severity; if (! (id_cert && link_cert)) ERR("The certs we wanted were missing"); /* Okay. We should be able to check the certificates now. */ if (! tor_tls_cert_matches_key(conn->tls, link_cert)) { ERR("The link certificate didn't match the TLS public key"); } - if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, link_cert, id_cert, 0)) + /* Note that this warns more loudly about time and validity if we were + * _trying_ to connect to an authority, not necessarily if we _did_ connect + * to one. */ + if (router_digest_is_trusted_dir(conn->identity_digest)) + severity = LOG_WARN; + else + severity = LOG_PROTOCOL_WARN; + + if (! tor_tls_cert_is_valid(severity, link_cert, id_cert, 0)) ERR("The link certificate was not valid"); - if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, id_cert, id_cert, 1)) + if (! tor_tls_cert_is_valid(severity, id_cert, id_cert, 1)) ERR("The ID certificate was not valid"); conn->handshake_state->authenticated = 1; @@ -1041,7 +1050,7 @@ command_process_cert_cell(var_cell_t *cell, or_connection_t *conn) id_cert = auth_cert = NULL; } - conn->handshake_state->received_cert_cell = 1; + conn->handshake_state->received_certs_cell = 1; err: tor_cert_free(id_cert); tor_cert_free(link_cert); @@ -1055,7 +1064,7 @@ command_process_cert_cell(var_cell_t *cell, or_connection_t *conn) * originator of the connection), or it's ill-formed, or we aren't doing a v3 * handshake, mark the connection. If the cell is well-formed but we don't * want to authenticate, just drop it. If the cell is well-formed *and* we - * want to authenticate, send an AUTHENTICATE cell. */ + * want to authenticate, send an AUTHENTICATE cell and then a NETINFO cell. */ static void command_process_auth_challenge_cell(var_cell_t *cell, or_connection_t *conn) { @@ -1079,7 +1088,7 @@ command_process_auth_challenge_cell(var_cell_t *cell, or_connection_t *conn) ERR("We didn't originate this connection"); if (conn->handshake_state->received_auth_challenge) ERR("We already received one"); - if (! conn->handshake_state->received_cert_cell) + if (! conn->handshake_state->received_certs_cell) ERR("We haven't gotten a CERTS cell yet"); if (cell->payload_len < OR_AUTH_CHALLENGE_LEN + 2) ERR("It was too short"); @@ -1137,7 +1146,7 @@ command_process_auth_challenge_cell(var_cell_t *cell, or_connection_t *conn) * If it's ill-formed or we weren't supposed to get one or we're not doing a * v3 handshake, then mark the connection. If it does not authenticate the * other side of the connection successfully (because it isn't signed right, - * we didn't get a CERT cell, etc) mark the connection. Otherwise, accept + * we didn't get a CERTS cell, etc) mark the connection. Otherwise, accept * the identity of the router on the other side of the connection. */ static void @@ -1168,8 +1177,8 @@ command_process_authenticate_cell(var_cell_t *cell, or_connection_t *conn) /* Should be impossible given other checks */ ERR("The peer is already authenticated"); } - if (! conn->handshake_state->received_cert_cell) - ERR("We never got a cert cell"); + if (! conn->handshake_state->received_certs_cell) + ERR("We never got a certs cell"); if (conn->handshake_state->auth_cert == NULL) ERR("We never got an authentication certificate"); if (conn->handshake_state->id_cert == NULL) diff --git a/src/or/config.c b/src/or/config.c index 4710b5590b..ef9e4ecee4 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -184,6 +184,8 @@ static config_var_t _option_vars[] = { V(AuthDirBadDir, LINELIST, NULL), V(AuthDirBadExit, LINELIST, NULL), V(AuthDirInvalid, LINELIST, NULL), + V(AuthDirFastGuarantee, MEMUNIT, "100 KB"), + V(AuthDirGuardBWGuarantee, MEMUNIT, "250 KB"), V(AuthDirReject, LINELIST, NULL), V(AuthDirRejectUnlisted, BOOL, "0"), V(AuthDirListBadDirs, BOOL, "0"), @@ -1542,6 +1544,15 @@ options_act(const or_options_t *old_options) options->BridgeAuthoritativeDir) { time_t now = time(NULL); int print_notice = 0; + + /* If we aren't acting as a server, we can't collect stats anyway. */ + if (!server_mode(options)) { + options->CellStatistics = 0; + options->DirReqStatistics = 0; + options->EntryStatistics = 0; + options->ExitPortStatistics = 0; + } + if ((!old_options || !old_options->CellStatistics) && options->CellStatistics) { rep_hist_buffer_stats_init(now); @@ -3536,6 +3547,12 @@ options_validate(or_options_t *old_options, or_options_t *options, if (ensure_bandwidth_cap(&options->PerConnBWBurst, "PerConnBWBurst", msg) < 0) return -1; + if (ensure_bandwidth_cap(&options->AuthDirFastGuarantee, + "AuthDirFastGuarantee", msg) < 0) + return -1; + if (ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee, + "AuthDirGuardBWGuarantee", msg) < 0) + return -1; if (options->RelayBandwidthRate && !options->RelayBandwidthBurst) options->RelayBandwidthBurst = options->RelayBandwidthRate; diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 320d8cb501..cce99e4d65 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -1435,7 +1435,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, * side of <b>conn</b> is <b>peer_id</b>. For v1 and v2 handshakes, * this is right after we get a certificate chain in a TLS handshake * or renegotiation. For v3 handshakes, this is right after we get a - * certificate chain in a CERT cell. + * certificate chain in a CERTS cell. * * If we want any particular ID before, record the one we got. * @@ -1954,10 +1954,10 @@ connection_or_send_netinfo(or_connection_t *conn) return 0; } -/** Send a CERT cell on the connection <b>conn</b>. Return 0 on success, -1 +/** Send a CERTS cell on the connection <b>conn</b>. Return 0 on success, -1 * on failure. */ int -connection_or_send_cert_cell(or_connection_t *conn) +connection_or_send_certs_cell(or_connection_t *conn) { const tor_cert_t *link_cert = NULL, *id_cert = NULL; const uint8_t *link_encoded = NULL, *id_encoded = NULL; @@ -1981,7 +1981,7 @@ connection_or_send_cert_cell(or_connection_t *conn) 2 * ( 1 + 2 ) /* For each cert: 1 byte for type, 2 for length */ + link_len + id_len; cell = var_cell_new(cell_len); - cell->command = CELL_CERT; + cell->command = CELL_CERTS; cell->payload[0] = 2; pos = 1; diff --git a/src/or/connection_or.h b/src/or/connection_or.h index df009ab39e..62a15b1cf2 100644 --- a/src/or/connection_or.h +++ b/src/or/connection_or.h @@ -69,7 +69,7 @@ int connection_or_send_destroy(circid_t circ_id, or_connection_t *conn, int reason); int connection_or_send_versions(or_connection_t *conn, int v3_plus); int connection_or_send_netinfo(or_connection_t *conn); -int connection_or_send_cert_cell(or_connection_t *conn); +int connection_or_send_certs_cell(or_connection_t *conn); int connection_or_send_auth_challenge_cell(or_connection_t *conn); int connection_or_compute_authenticate_cell_body(or_connection_t *conn, uint8_t *out, size_t outlen, diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index bf8964c29c..914003790a 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -445,9 +445,19 @@ assign_onionskin_to_cpuworker(connection_t *cpuworker, { char qbuf[1]; char tag[TAG_LEN]; + time_t now = approx_time(); + static time_t last_culled_cpuworkers = 0; - cull_wedged_cpuworkers(); - spawn_enough_cpuworkers(); + /* Checking for wedged cpuworkers requires a linear search over all + * connections, so let's do it only once a minute. + */ +#define CULL_CPUWORKERS_INTERVAL 60 + + if (last_culled_cpuworkers + CULL_CPUWORKERS_INTERVAL <= now) { + cull_wedged_cpuworkers(); + spawn_enough_cpuworkers(); + last_culled_cpuworkers = now; + } if (1) { if (num_cpuworkers_busy == num_cpuworkers) { diff --git a/src/or/dirserv.c b/src/or/dirserv.c index e4cbcaaded..be62459b16 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1720,12 +1720,6 @@ should_generate_v2_networkstatus(void) /** If a router's MTBF is at least this value, then it is always stable. * See above. (Corresponds to about 7 days for current decay rates.) */ #define MTBF_TO_GUARANTEE_STABLE (60*60*24*5) -/** Similarly, we protect sufficiently fast nodes from being pushed - * out of the set of Fast nodes. */ -#define BANDWIDTH_TO_GUARANTEE_FAST ROUTER_REQUIRED_MIN_BANDWIDTH -/** Similarly, every node with sufficient bandwidth can be considered - * for Guard status. */ -#define BANDWIDTH_TO_GUARANTEE_GUARD (250*1024) /** Similarly, every node with at least this much weighted time known can be * considered familiar enough to be a guard. Corresponds to about 20 days for * current decay rates. @@ -1870,6 +1864,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl) long *tks; double *mtbfs, *wfus; time_t now = time(NULL); + const or_options_t *options = get_options(); /* initialize these all here, in case there are no routers */ stable_uptime = 0; @@ -1942,8 +1937,11 @@ dirserv_compute_performance_thresholds(routerlist_t *rl) if (guard_tk > TIME_KNOWN_TO_GUARANTEE_FAMILIAR) guard_tk = TIME_KNOWN_TO_GUARANTEE_FAMILIAR; - if (fast_bandwidth > BANDWIDTH_TO_GUARANTEE_FAST) - fast_bandwidth = BANDWIDTH_TO_GUARANTEE_FAST; + /* Protect sufficiently fast nodes from being pushed out of the set + * of Fast nodes. */ + if (options->AuthDirFastGuarantee && + fast_bandwidth > options->AuthDirFastGuarantee) + fast_bandwidth = (uint32_t)options->AuthDirFastGuarantee; /* Now that we have a time-known that 7/8 routers are known longer than, * fill wfus with the wfu of every such "familiar" router. */ @@ -2375,6 +2373,8 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, const or_options_t *options = get_options(); int unstable_version = !tor_version_as_new_as(ri->platform,"0.1.1.16-rc-cvs"); + uint32_t routerbw = router_get_advertised_bandwidth(ri); + memset(rs, 0, sizeof(routerstatus_t)); rs->is_authority = @@ -2400,10 +2400,10 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, rs->is_valid = node->is_valid; if (node->is_fast && - (router_get_advertised_bandwidth(ri) >= BANDWIDTH_TO_GUARANTEE_GUARD || - router_get_advertised_bandwidth(ri) >= - MIN(guard_bandwidth_including_exits, - guard_bandwidth_excluding_exits)) && + ((options->AuthDirGuardBWGuarantee && + routerbw >= options->AuthDirGuardBWGuarantee) || + routerbw >= MIN(guard_bandwidth_including_exits, + guard_bandwidth_excluding_exits)) && (options->GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays || is_router_version_good_for_possible_guard(ri->platform))) { long tk = rep_hist_get_weighted_time_known( diff --git a/src/or/main.c b/src/or/main.c index 9f6d307a3e..10b80a4dd9 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2265,14 +2265,24 @@ tor_init(int argc, char *argv[]) } quiet_level = quiet; - log(LOG_NOTICE, LD_GENERAL, "Tor v%s%s. This is experimental software. " - "Do not rely on it for strong anonymity. (Running on %s)", get_version(), + { + const char *version = get_version(); + log_notice(LD_GENERAL, "Tor v%s%s running on %s.", version, #ifdef USE_BUFFEREVENTS - " (with bufferevents)", + " (with bufferevents)", #else - "", + "", #endif - get_uname()); + get_uname()); + + log_notice(LD_GENERAL, "WARNING: Tor can't help you if you use it wrong. " + "Learn how to be safe at " + "https://www.torproject.org/download/download#warning"); + + if (strstr(version, "alpha") || strstr(version, "beta")) + log_notice(LD_GENERAL, "This version is not a stable Tor release. " + "Expect more bugs than usual."); + } if (network_init()<0) { log_err(LD_BUG,"Error initializing network; exiting."); diff --git a/src/or/ntmain.c b/src/or/ntmain.c index 4eb487e976..8d03ea8087 100644 --- a/src/or/ntmain.c +++ b/src/or/ntmain.c @@ -727,6 +727,7 @@ nt_service_parse_options(int argc, char **argv, int *should_exit) if ((argc >= 3) && (!strcmp(argv[1], "-service") || !strcmp(argv[1], "--service"))) { nt_service_loadlibrary(); + *should_exit = 1; if (!strcmp(argv[2], "install")) return nt_service_install(argc, argv); if (!strcmp(argv[2], "remove")) @@ -736,7 +737,6 @@ nt_service_parse_options(int argc, char **argv, int *should_exit) if (!strcmp(argv[2], "stop")) return nt_service_cmd_stop(); printf("Unrecognized service command '%s'\n", argv[2]); - *should_exit = 1; return 1; } if (argc >= 2) { diff --git a/src/or/or.h b/src/or/or.h index 7fb7e9cb22..f186eac7bd 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -826,7 +826,7 @@ typedef enum { #define CELL_RELAY_EARLY 9 #define CELL_VPADDING 128 -#define CELL_CERT 129 +#define CELL_CERTS 129 #define CELL_AUTH_CHALLENGE 130 #define CELL_AUTHENTICATE 131 @@ -1088,10 +1088,10 @@ typedef struct listener_connection_t { #define OR_AUTH_CHALLENGE_LEN 32 /** - * @name Certificate types for CERT cells. + * @name Certificate types for CERTS cells. * * These values are defined by the protocol, and affect how an X509 - * certificate in a CERT cell is interpreted and used. + * certificate in a CERTS cell is interpreted and used. * * @{ */ /** A certificate that authenticates a TLS link key. The subject key @@ -1137,8 +1137,8 @@ typedef struct or_handshake_state_t { unsigned int received_versions : 1; /** True iff we have received and processed an AUTH_CHALLENGE cell */ unsigned int received_auth_challenge : 1; - /** True iff we have received and processed a CERT cell. */ - unsigned int received_cert_cell : 1; + /** True iff we have received and processed a CERTS cell. */ + unsigned int received_certs_cell : 1; /** True iff we have received and processed an AUTHENTICATE cell */ unsigned int received_authenticate : 1; @@ -1171,7 +1171,7 @@ typedef struct or_handshake_state_t { crypto_digest_env_t *digest_received; /** @} */ - /** Certificates that a connection initiator sent us in a CERT cell; we're + /** Certificates that a connection initiator sent us in a CERTS cell; we're * holding on to them until we get an AUTHENTICATE cell. * * @{ @@ -3162,6 +3162,14 @@ typedef struct { * exploitation of CVE-2011-2768 against their clients? */ int GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays; + /** If non-zero, always vote the Fast flag for any relay advertising + * this amount of capacity or more. */ + uint64_t AuthDirFastGuarantee; + + /** If non-zero, this advertised capacity or more is always sufficient + * to satisfy the bandwidth requirement for the Guard flag. */ + uint64_t AuthDirGuardBWGuarantee; + char *AccountingStart; /**< How long is the accounting interval, and when * does it start? */ uint64_t AccountingMax; /**< How many bytes do we allow per accounting diff --git a/src/or/relay.c b/src/or/relay.c index 51a29a20ee..ac3114bda5 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -11,6 +11,7 @@ **/ #include <math.h> +#define RELAY_PRIVATE #include "or.h" #include "buffers.h" #include "circuitbuild.h" @@ -33,9 +34,6 @@ #include "routerlist.h" #include "routerparse.h" -static int relay_crypt(circuit_t *circ, cell_t *cell, - cell_direction_t cell_direction, - crypt_path_t **layer_hint, char *recognized); static edge_connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction, crypt_path_t *layer_hint); @@ -297,7 +295,7 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, * Return -1 to indicate that we should mark the circuit for close, * else return 0. */ -static int +int relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction, crypt_path_t **layer_hint, char *recognized) { diff --git a/src/or/relay.h b/src/or/relay.h index 7fce8edcaf..1cd4008bb9 100644 --- a/src/or/relay.h +++ b/src/or/relay.h @@ -66,5 +66,10 @@ void circuit_clear_cell_queue(circuit_t *circ, or_connection_t *orconn); void tor_gettimeofday_cache_clear(void); +#ifdef RELAY_PRIVATE +int relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction, + crypt_path_t **layer_hint, char *recognized); +#endif + #endif diff --git a/src/test/Makefile.am b/src/test/Makefile.am index 301452b4ec..ffe1f942e7 100644 --- a/src/test/Makefile.am +++ b/src/test/Makefile.am @@ -1,6 +1,6 @@ TESTS = test -noinst_PROGRAMS = test test-child +noinst_PROGRAMS = test test-child bench AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ -DLOCALSTATEDIR="\"$(localstatedir)\"" \ @@ -23,6 +23,9 @@ test_SOURCES = \ test_util.c \ tinytest.c +bench_SOURCES = \ + bench.c + test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ test_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \ @@ -30,6 +33,13 @@ test_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \ @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ @TOR_LIB_WS32@ @TOR_LIB_GDI@ +bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ + @TOR_LDFLAGS_libevent@ +bench_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \ + ../common/libor-event.a \ + @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ + @TOR_LIB_WS32@ @TOR_LIB_GDI@ + noinst_HEADERS = \ tinytest.h \ tinytest_macros.h \ diff --git a/src/test/bench.c b/src/test/bench.c new file mode 100644 index 0000000000..ff2794e7c7 --- /dev/null +++ b/src/test/bench.c @@ -0,0 +1,327 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2011, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/* Ordinarily defined in tor_main.c; this bit is just here to provide one + * since we're not linking to tor_main.c */ +const char tor_git_revision[] = ""; + +/** + * \file bench.c + * \brief Benchmarks for lower level Tor modules. + **/ + +#include "orconfig.h" + +#define RELAY_PRIVATE + +#include "or.h" +#include "relay.h" + +#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) +static uint64_t nanostart; +static inline uint64_t +timespec_to_nsec(const struct timespec *ts) +{ + return ((uint64_t)ts->tv_sec)*1000000000 + ts->tv_nsec; +} + +static void +reset_perftime(void) +{ + struct timespec ts; + int r; + r = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); + tor_assert(r == 0); + nanostart = timespec_to_nsec(&ts); +} + +static uint64_t +perftime(void) +{ + struct timespec ts; + int r; + r = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); + tor_assert(r == 0); + return timespec_to_nsec(&ts) - nanostart; +} + +#else +static struct timeval tv_start = { 0, 0 }; +static void +reset_perftime(void) +{ + tor_gettimeofday(&tv_start); +} +static uint64_t +perftime(void) +{ + struct timeval now, out; + tor_gettimeofday(&now); + timersub(&now, &tv_start, &out); + return ((uint64_t)out.tv_sec)*1000000000 + out.tv_usec*1000; +} +#endif + +#define NANOCOUNT(start,end,iters) \ + ( ((double)((end)-(start))) / (iters) ) + +/** Run AES performance benchmarks. */ +static void +bench_aes(void) +{ + int len, i; + char *b1, *b2; + crypto_cipher_env_t *c; + uint64_t start, end; + const int bytes_per_iter = (1<<24); + reset_perftime(); + c = crypto_new_cipher_env(); + crypto_cipher_generate_key(c); + crypto_cipher_encrypt_init_cipher(c); + for (len = 1; len <= 8192; len *= 2) { + int iters = bytes_per_iter / len; + b1 = tor_malloc_zero(len); + b2 = tor_malloc_zero(len); + start = perftime(); + for (i = 0; i < iters; ++i) { + crypto_cipher_encrypt(c, b1, b2, len); + } + end = perftime(); + tor_free(b1); + tor_free(b2); + printf("%d bytes: %.2f nsec per byte\n", len, + NANOCOUNT(start, end, iters*len)); + } + crypto_free_cipher_env(c); +} + +static void +bench_cell_aes(void) +{ + uint64_t start, end; + const int len = 509; + const int iters = (1<<16); + const int max_misalign = 15; + char *b = tor_malloc(len+max_misalign); + crypto_cipher_env_t *c; + int i, misalign; + + c = crypto_new_cipher_env(); + crypto_cipher_generate_key(c); + crypto_cipher_encrypt_init_cipher(c); + + reset_perftime(); + for (misalign = 0; misalign <= max_misalign; ++misalign) { + start = perftime(); + for (i = 0; i < iters; ++i) { + crypto_cipher_crypt_inplace(c, b+misalign, len); + } + end = perftime(); + printf("%d bytes, misaligned by %d: %.2f nsec per byte\n", len, misalign, + NANOCOUNT(start, end, iters*len)); + } + + crypto_free_cipher_env(c); + tor_free(b); +} + +/** Run digestmap_t performance benchmarks. */ +static void +bench_dmap(void) +{ + smartlist_t *sl = smartlist_create(); + smartlist_t *sl2 = smartlist_create(); + uint64_t start, end, pt2, pt3, pt4; + int iters = 8192; + const int elts = 4000; + const int fpostests = 100000; + char d[20]; + int i,n=0, fp = 0; + digestmap_t *dm = digestmap_new(); + digestset_t *ds = digestset_new(elts); + + for (i = 0; i < elts; ++i) { + crypto_rand(d, 20); + smartlist_add(sl, tor_memdup(d, 20)); + } + for (i = 0; i < elts; ++i) { + crypto_rand(d, 20); + smartlist_add(sl2, tor_memdup(d, 20)); + } + printf("nbits=%d\n", ds->mask+1); + + reset_perftime(); + + start = perftime(); + for (i = 0; i < iters; ++i) { + SMARTLIST_FOREACH(sl, const char *, cp, digestmap_set(dm, cp, (void*)1)); + } + pt2 = perftime(); + printf("digestmap_set: %.2f ns per element\n", + NANOCOUNT(start, pt2, iters*elts)); + + for (i = 0; i < iters; ++i) { + SMARTLIST_FOREACH(sl, const char *, cp, digestmap_get(dm, cp)); + SMARTLIST_FOREACH(sl2, const char *, cp, digestmap_get(dm, cp)); + } + pt3 = perftime(); + printf("digestmap_get: %.2f ns per element\n", + NANOCOUNT(pt2, pt3, iters*elts*2)); + + for (i = 0; i < iters; ++i) { + SMARTLIST_FOREACH(sl, const char *, cp, digestset_add(ds, cp)); + } + pt4 = perftime(); + printf("digestset_add: %.2f ns per element\n", + NANOCOUNT(pt3, pt4, iters*elts)); + + for (i = 0; i < iters; ++i) { + SMARTLIST_FOREACH(sl, const char *, cp, n += digestset_isin(ds, cp)); + SMARTLIST_FOREACH(sl2, const char *, cp, n += digestset_isin(ds, cp)); + } + end = perftime(); + printf("digestset_isin: %.2f ns per element.\n", + NANOCOUNT(pt4, end, iters*elts*2)); + /* We need to use this, or else the whole loop gets optimized out. */ + printf("Hits == %d\n", n); + + for (i = 0; i < fpostests; ++i) { + crypto_rand(d, 20); + if (digestset_isin(ds, d)) ++fp; + } + printf("False positive rate on digestset: %.2f%%\n", + (fp/(double)fpostests)*100); + + digestmap_free(dm, NULL); + digestset_free(ds); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp)); + smartlist_free(sl); + smartlist_free(sl2); +} + +static void +bench_cell_ops(void) +{ + const int iters = 1<<16; + int i; + + /* benchmarks for cell ops at relay. */ + or_circuit_t *or_circ = tor_malloc_zero(sizeof(or_circuit_t)); + cell_t *cell = tor_malloc(sizeof(cell_t)); + int outbound; + uint64_t start, end; + + crypto_rand((char*)cell->payload, sizeof(cell->payload)); + + /* Mock-up or_circuit_t */ + or_circ->_base.magic = OR_CIRCUIT_MAGIC; + or_circ->_base.purpose = CIRCUIT_PURPOSE_OR; + + /* Initialize crypto */ + or_circ->p_crypto = crypto_new_cipher_env(); + crypto_cipher_generate_key(or_circ->p_crypto); + crypto_cipher_encrypt_init_cipher(or_circ->p_crypto); + or_circ->n_crypto = crypto_new_cipher_env(); + crypto_cipher_generate_key(or_circ->n_crypto); + crypto_cipher_encrypt_init_cipher(or_circ->n_crypto); + or_circ->p_digest = crypto_new_digest_env(); + or_circ->n_digest = crypto_new_digest_env(); + + reset_perftime(); + + for (outbound = 0; outbound <= 1; ++outbound) { + cell_direction_t d = outbound ? CELL_DIRECTION_OUT : CELL_DIRECTION_IN; + start = perftime(); + for (i = 0; i < iters; ++i) { + char recognized = 0; + crypt_path_t *layer_hint = NULL; + relay_crypt(TO_CIRCUIT(or_circ), cell, d, &layer_hint, &recognized); + } + end = perftime(); + printf("%sbound cells: %.2f ns per cell. (%.2f ns per byte of payload)\n", + outbound?"Out":" In", + NANOCOUNT(start,end,iters), + NANOCOUNT(start,end,iters*CELL_PAYLOAD_SIZE)); + } + + crypto_free_digest_env(or_circ->p_digest); + crypto_free_digest_env(or_circ->n_digest); + crypto_free_cipher_env(or_circ->p_crypto); + crypto_free_cipher_env(or_circ->n_crypto); + tor_free(or_circ); + tor_free(cell); +} + +typedef void (*bench_fn)(void); + +typedef struct benchmark_t { + const char *name; + bench_fn fn; + int enabled; +} benchmark_t; + +#define ENT(s) { #s , bench_##s, 0 } + +static struct benchmark_t benchmarks[] = { + ENT(dmap), + ENT(aes), + ENT(cell_aes), + ENT(cell_ops), + {NULL,NULL,0} +}; + +static benchmark_t * +find_benchmark(const char *name) +{ + benchmark_t *b; + for (b = benchmarks; b->name; ++b) { + if (!strcmp(name, b->name)) { + return b; + } + } + return NULL; +} + +/** Main entry point for benchmark code: parse the command line, and run + * some benchmarks. */ +int +main(int argc, const char **argv) +{ + int i; + int list=0, n_enabled=0; + benchmark_t *b; + + tor_threads_init(); + + for (i = 1; i < argc; ++i) { + if (!strcmp(argv[i], "--list")) { + list = 1; + } else { + benchmark_t *b = find_benchmark(argv[i]); + ++n_enabled; + if (b) { + b->enabled = 1; + } else { + printf("No such benchmark as %s\n", argv[i]); + } + } + } + + reset_perftime(); + + crypto_seed_rng(1); + + for (b = benchmarks; b->name; ++b) { + if (b->enabled || n_enabled == 0) { + printf("===== %s =====\n", b->name); + if (!list) + b->fn(); + } + } + + return 0; +} + diff --git a/src/test/test.c b/src/test/test.c index 185bf5a30c..d4edf1484b 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1265,102 +1265,6 @@ test_policies(void) } } -/** Run AES performance benchmarks. */ -static void -test_bench_aes(void) -{ - int len, i; - char *b1, *b2; - crypto_cipher_env_t *c; - struct timeval start, end; - const int iters = 100000; - uint64_t nsec; - c = crypto_new_cipher_env(); - crypto_cipher_generate_key(c); - crypto_cipher_encrypt_init_cipher(c); - for (len = 1; len <= 8192; len *= 2) { - b1 = tor_malloc_zero(len); - b2 = tor_malloc_zero(len); - tor_gettimeofday(&start); - for (i = 0; i < iters; ++i) { - crypto_cipher_encrypt(c, b1, b2, len); - } - tor_gettimeofday(&end); - tor_free(b1); - tor_free(b2); - nsec = (uint64_t) tv_udiff(&start,&end); - nsec *= 1000; - nsec /= (iters*len); - printf("%d bytes: "U64_FORMAT" nsec per byte\n", len, - U64_PRINTF_ARG(nsec)); - } - crypto_free_cipher_env(c); -} - -/** Run digestmap_t performance benchmarks. */ -static void -test_bench_dmap(void) -{ - smartlist_t *sl = smartlist_create(); - smartlist_t *sl2 = smartlist_create(); - struct timeval start, end, pt2, pt3, pt4; - const int iters = 10000; - const int elts = 4000; - const int fpostests = 1000000; - char d[20]; - int i,n=0, fp = 0; - digestmap_t *dm = digestmap_new(); - digestset_t *ds = digestset_new(elts); - - for (i = 0; i < elts; ++i) { - crypto_rand(d, 20); - smartlist_add(sl, tor_memdup(d, 20)); - } - for (i = 0; i < elts; ++i) { - crypto_rand(d, 20); - smartlist_add(sl2, tor_memdup(d, 20)); - } - printf("nbits=%d\n", ds->mask+1); - - tor_gettimeofday(&start); - for (i = 0; i < iters; ++i) { - SMARTLIST_FOREACH(sl, const char *, cp, digestmap_set(dm, cp, (void*)1)); - } - tor_gettimeofday(&pt2); - for (i = 0; i < iters; ++i) { - SMARTLIST_FOREACH(sl, const char *, cp, digestmap_get(dm, cp)); - SMARTLIST_FOREACH(sl2, const char *, cp, digestmap_get(dm, cp)); - } - tor_gettimeofday(&pt3); - for (i = 0; i < iters; ++i) { - SMARTLIST_FOREACH(sl, const char *, cp, digestset_add(ds, cp)); - } - tor_gettimeofday(&pt4); - for (i = 0; i < iters; ++i) { - SMARTLIST_FOREACH(sl, const char *, cp, n += digestset_isin(ds, cp)); - SMARTLIST_FOREACH(sl2, const char *, cp, n += digestset_isin(ds, cp)); - } - tor_gettimeofday(&end); - - for (i = 0; i < fpostests; ++i) { - crypto_rand(d, 20); - if (digestset_isin(ds, d)) ++fp; - } - - printf("%ld\n",(unsigned long)tv_udiff(&start, &pt2)); - printf("%ld\n",(unsigned long)tv_udiff(&pt2, &pt3)); - printf("%ld\n",(unsigned long)tv_udiff(&pt3, &pt4)); - printf("%ld\n",(unsigned long)tv_udiff(&pt4, &end)); - printf("-- %d\n", n); - printf("++ %f\n", fp/(double)fpostests); - digestmap_free(dm, NULL); - digestset_free(ds); - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp)); - smartlist_free(sl); - smartlist_free(sl2); -} - /** Test encoding and parsing of rendezvous service descriptors. */ static void test_rend_fns(void) @@ -1913,8 +1817,6 @@ static struct testcase_t test_array[] = { ENT(geoip), FORK(stats), - DISABLED(bench_aes), - DISABLED(bench_dmap), END_OF_TESTCASES }; diff --git a/src/test/test_addr.c b/src/test/test_addr.c index b14ddb3d70..9d8e1fe8c5 100644 --- a/src/test/test_addr.c +++ b/src/test/test_addr.c @@ -186,7 +186,6 @@ test_addr_ip6_helpers(void) struct sockaddr_in *sin; struct sockaddr_in6 *sin6; - // struct in_addr b1, b2; /* Test tor_inet_ntop and tor_inet_pton: IPv6 */ { const char *ip = "2001::1234"; @@ -302,12 +301,23 @@ test_addr_ip6_helpers(void) test_ntop6_reduces("1000:0001:0000:0007:0000:0000:0000:0000", "1000:1:0:7::"); + /* Bad af param */ + test_eq(tor_inet_pton(AF_UNSPEC, 0, 0), -1); + /* === Test pton: invalid in6. */ test_pton6_bad("foobar."); + test_pton6_bad("-1::"); + test_pton6_bad("00001::"); + test_pton6_bad("10000::"); + test_pton6_bad("::10000"); test_pton6_bad("55555::"); test_pton6_bad("9:-60::"); + test_pton6_bad("9:+60::"); + test_pton6_bad("9|60::"); + test_pton6_bad("0x60::"); + test_pton6_bad("::0x60"); + test_pton6_bad("9:0x60::"); test_pton6_bad("1:2:33333:4:0002:3::"); - //test_pton6_bad("1:2:3333:4:00002:3::");// BAD, but glibc doesn't say so. test_pton6_bad("1:2:3333:4:fish:3::"); test_pton6_bad("1:2:3:4:5:6:7:8:9"); test_pton6_bad("1:2:3:4:5:6:7"); @@ -315,8 +325,14 @@ test_addr_ip6_helpers(void) test_pton6_bad("1:2:3:4:5:6:1.2.3"); test_pton6_bad("::1.2.3"); test_pton6_bad("::1.2.3.4.5"); + test_pton6_bad("::ffff:0xff.0.0.0"); + test_pton6_bad("::ffff:ff.0.0.0"); + test_pton6_bad("::ffff:256.0.0.0"); + test_pton6_bad("::ffff:-1.0.0.0"); test_pton6_bad("99"); test_pton6_bad(""); + test_pton6_bad("."); + test_pton6_bad(":"); test_pton6_bad("1::2::3:4"); test_pton6_bad("a:::b:c"); test_pton6_bad(":::a:b:c"); @@ -325,6 +341,9 @@ test_addr_ip6_helpers(void) /* test internal checking */ test_external_ip("fbff:ffff::2:7", 0); test_internal_ip("fc01::2:7", 0); + test_internal_ip("fc01::02:7", 0); + test_internal_ip("fc01::002:7", 0); + test_internal_ip("fc01::0002:7", 0); test_internal_ip("fdff:ffff::f:f", 0); test_external_ip("fe00::3:f", 0); diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h index 7460d4fb94..34d7c75b01 100644 --- a/src/win32/orconfig.h +++ b/src/win32/orconfig.h @@ -234,7 +234,7 @@ #define USING_TWOS_COMPLEMENT /* Version number of package */ -#define VERSION "0.2.3.7-alpha" +#define VERSION "0.2.3.8-alpha-dev" |