aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore15
-rw-r--r--ChangeLog1857
-rw-r--r--INSTALL31
-rw-r--r--Makefile.am24
-rw-r--r--Makefile.nmake5
-rw-r--r--ReleaseNotes1271
-rwxr-xr-xautogen.sh4
-rw-r--r--changes/abandon-rend-circs-on-newnym8
-rw-r--r--changes/bug1297a16
-rw-r--r--changes/bug1297b8
-rw-r--r--changes/bug134513
-rw-r--r--changes/bug13524
-rw-r--r--changes/bug18106
-rw-r--r--changes/bug23558
-rw-r--r--changes/bug2355_revert7
-rw-r--r--changes/bug24304
-rw-r--r--changes/bug25034
-rw-r--r--changes/bug25743
-rw-r--r--changes/bug2732-simple7
-rw-r--r--changes/bug274810
-rw-r--r--changes/bug27525
-rw-r--r--changes/bug2792_checkdir8
-rw-r--r--changes/bug28505
-rw-r--r--changes/bug29725
-rw-r--r--changes/bug30194
-rw-r--r--changes/bug30226
-rw-r--r--changes/bug30264
-rw-r--r--changes/bug30456
-rw-r--r--changes/bug3122_memcmp7
-rw-r--r--changes/bug31356
-rw-r--r--changes/bug31757
-rw-r--r--changes/bug31984
-rw-r--r--changes/bug32006
-rw-r--r--changes/bug32074
-rw-r--r--changes/bug32086
-rw-r--r--changes/bug32134
-rw-r--r--changes/bug32164
-rw-r--r--changes/bug32283
-rw-r--r--changes/bug32524
-rw-r--r--changes/bug32704
-rw-r--r--changes/bug32895
-rw-r--r--changes/bug33069
-rw-r--r--changes/bug330913
-rw-r--r--changes/bug33187
-rw-r--r--changes/bug33217
-rw-r--r--changes/bug333511
-rw-r--r--changes/bug33694
-rw-r--r--changes/bug33935
-rw-r--r--changes/bug3465-0226
-rw-r--r--changes/bug35365
-rw-r--r--changes/bug35774
-rw-r--r--changes/bug360715
-rw-r--r--changes/bug36434
-rw-r--r--changes/bug37327
-rw-r--r--changes/bug37476
-rw-r--r--changes/bug3825a8
-rw-r--r--changes/bug40943
-rw-r--r--changes/bug42015
-rw-r--r--changes/check-fetched-rend-desc-service-id7
-rw-r--r--changes/check-public-key-exponents5
-rw-r--r--changes/cid_4285
-rw-r--r--changes/cid_4505
-rw-r--r--changes/coverity_maint9
-rw-r--r--changes/dirvote_null_deref4
-rw-r--r--changes/dont-warn-about-rfc1918-socksport-addrs7
-rw-r--r--changes/exit-policy-default-is-not-a-prefix5
-rw-r--r--changes/feature30496
-rw-r--r--changes/feature307614
-rw-r--r--changes/fix-connection_printf_to_buf15
-rw-r--r--changes/fmt_addr4
-rw-r--r--changes/geoip-august20113
-rw-r--r--changes/geoip-july20113
-rw-r--r--changes/geoip-june20113
-rw-r--r--changes/geoip-may20113
-rw-r--r--changes/md_cache_replace6
-rw-r--r--changes/mdesc_null_deref5
-rw-r--r--changes/memleak_rendcache4
-rw-r--r--changes/msvc_lround4
-rw-r--r--changes/windows_85
-rw-r--r--configure.in276
-rw-r--r--contrib/Makefile.am15
-rwxr-xr-xcontrib/findMergedChanges.pl70
-rwxr-xr-xcontrib/make-signature.sh79
-rw-r--r--contrib/tor-mingw.nsi.in2
-rw-r--r--doc/HACKING9
-rw-r--r--doc/Makefile.am24
-rwxr-xr-xdoc/asciidoc-helper.sh3
-rw-r--r--doc/tor-fw-helper.1.txt68
-rw-r--r--doc/tor.1.txt201
-rw-r--r--src/common/Makefile.am46
-rw-r--r--src/common/Makefile.nmake20
-rw-r--r--src/common/OpenBSD_malloc_Linux.c2
-rw-r--r--src/common/address.c15
-rw-r--r--src/common/address.h3
-rw-r--r--src/common/aes.c19
-rw-r--r--src/common/compat.c112
-rw-r--r--src/common/compat.h13
-rw-r--r--src/common/compat_libevent.c106
-rw-r--r--src/common/compat_libevent.h22
-rw-r--r--src/common/container.c1
-rw-r--r--src/common/crypto.c10
-rw-r--r--src/common/crypto.h3
-rw-r--r--src/common/log.c31
-rw-r--r--src/common/mempool.c2
-rw-r--r--src/common/torgzip.c7
-rw-r--r--src/common/torint.h9
-rw-r--r--src/common/torlog.h5
-rw-r--r--src/common/tortls.c431
-rw-r--r--src/common/tortls.h16
-rw-r--r--src/common/util.c1212
-rw-r--r--src/common/util.h84
-rw-r--r--src/config/geoip5974
-rw-r--r--src/or/Makefile.am115
-rw-r--r--src/or/Makefile.nmake28
-rw-r--r--src/or/buffers.c832
-rw-r--r--src/or/buffers.h38
-rw-r--r--src/or/circuitbuild.c1046
-rw-r--r--src/or/circuitbuild.h55
-rw-r--r--src/or/circuitlist.c64
-rw-r--r--src/or/circuituse.c360
-rw-r--r--src/or/circuituse.h12
-rw-r--r--src/or/command.c12
-rw-r--r--src/or/config.c1692
-rw-r--r--src/or/config.h29
-rw-r--r--src/or/connection.c1598
-rw-r--r--src/or/connection.h70
-rw-r--r--src/or/connection_edge.c874
-rw-r--r--src/or/connection_edge.h40
-rw-r--r--src/or/connection_or.c437
-rw-r--r--src/or/connection_or.h6
-rw-r--r--src/or/control.c452
-rw-r--r--src/or/control.h6
-rw-r--r--src/or/cpuworker.c9
-rw-r--r--src/or/directory.c454
-rw-r--r--src/or/directory.h9
-rw-r--r--src/or/dirserv.c338
-rw-r--r--src/or/dirserv.h35
-rw-r--r--src/or/dirvote.c29
-rw-r--r--src/or/dirvote.h7
-rw-r--r--src/or/dns.c10
-rw-r--r--src/or/dnsserv.c73
-rw-r--r--src/or/dnsserv.h4
-rw-r--r--src/or/eventdns.c10
-rw-r--r--src/or/geoip.c340
-rw-r--r--src/or/geoip.h10
-rw-r--r--src/or/hibernate.c10
-rw-r--r--src/or/hibernate.h4
-rw-r--r--src/or/main.c482
-rw-r--r--src/or/main.h12
-rw-r--r--src/or/microdesc.c297
-rw-r--r--src/or/microdesc.h18
-rw-r--r--src/or/networkstatus.c467
-rw-r--r--src/or/networkstatus.h40
-rw-r--r--src/or/nodelist.c758
-rw-r--r--src/or/nodelist.h60
-rw-r--r--src/or/ntmain.c1
-rw-r--r--src/or/or.h731
-rw-r--r--src/or/policies.c245
-rw-r--r--src/or/policies.h22
-rw-r--r--src/or/relay.c221
-rw-r--r--src/or/relay.h4
-rw-r--r--src/or/rendclient.c244
-rw-r--r--src/or/rendclient.h15
-rw-r--r--src/or/rendcommon.c9
-rw-r--r--src/or/rendcommon.h4
-rw-r--r--src/or/rendservice.c99
-rw-r--r--src/or/rendservice.h2
-rw-r--r--src/or/rephist.c595
-rw-r--r--src/or/rephist.h12
-rw-r--r--src/or/router.c288
-rw-r--r--src/or/router.h43
-rw-r--r--src/or/routerlist.c1380
-rw-r--r--src/or/routerlist.h104
-rw-r--r--src/or/routerparse.c136
-rw-r--r--src/or/status.c115
-rw-r--r--src/or/status.h10
-rw-r--r--src/or/transports.c1048
-rw-r--r--src/or/transports.h105
-rw-r--r--src/test/Makefile.am18
-rw-r--r--src/test/test-child.c40
-rw-r--r--src/test/test.c793
-rw-r--r--src/test/test.h3
-rw-r--r--src/test/test_addr.c4
-rw-r--r--src/test/test_crypto.c24
-rw-r--r--src/test/test_dir.c18
-rw-r--r--src/test/test_microdesc.c233
-rw-r--r--src/test/test_pt.c147
-rw-r--r--src/test/test_util.c474
-rw-r--r--src/test/tinytest.c17
-rw-r--r--src/test/tinytest_demo.c14
-rw-r--r--src/test/tinytest_macros.h39
-rw-r--r--src/tools/Makefile.am18
-rw-r--r--src/tools/tor-fw-helper/Makefile.am38
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper-natpmp.c233
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper-natpmp.h47
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper-upnp.c189
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper-upnp.h43
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper.c396
-rw-r--r--src/tools/tor-fw-helper/tor-fw-helper.h57
-rw-r--r--src/win32/orconfig.h11
200 files changed, 25414 insertions, 6660 deletions
diff --git a/.gitignore b/.gitignore
index 673bb7871..610965b85 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,6 +29,7 @@
/aclocal.m4
/autom4te.cache
/build-stamp
+/compile
/configure
/Doxyfile
/orconfig.h
@@ -87,6 +88,11 @@
/doc/tor.html
/doc/tor.html.in
/doc/tor.1.xml
+/doc/tor-fw-helper.1
+/doc/tor-fw-helper.1.in
+/doc/tor-fw-helper.html
+/doc/tor-fw-helper.html.in
+/doc/tor-fw-helper.1.xml
/doc/tor-gencert.1
/doc/tor-gencert.1.in
/doc/tor-gencert.html
@@ -139,6 +145,9 @@
/src/test/Makefile
/src/test/Makefile.in
/src/test/test
+/src/test/test-child
+/src/test/test.exe
+/src/test/test-child.exe
# /src/tools/
@@ -151,6 +160,12 @@
/src/tools/Makefile
/src/tools/Makefile.in
+# /src/tools/tor-fw-helper/
+/src/tools/tor-fw-helper/tor-fw-helper
+/src/tools/tor-fw-helper/tor-fw-helper.exe
+/src/tools/tor-fw-helper/Makefile
+/src/tools/tor-fw-helper/Makefile.in
+
# /src/win32/
/src/win32/Makefile
/src/win32/Makefile.in
diff --git a/ChangeLog b/ChangeLog
index b87449ab6..264077564 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,1832 @@
+Changes in version 0.2.3.5-alpha - 2011-09-28
+ Tor 0.2.3.5-alpha fixes two bugs that make it possible to enumerate
+ bridge relays; fixes an assertion error that many users started hitting
+ today; and adds the ability to refill token buckets more often than
+ once per second, allowing significant performance improvements.
+
+ o Security fixes:
+ - Bridge relays now do their directory fetches inside Tor TLS
+ connections, like all the other clients do, rather than connecting
+ directly to the DirPort like public relays do. Removes another
+ avenue for enumerating bridges. Fixes bug 4115; bugfix on 0.2.0.35.
+ - Bridges relays now build circuits for themselves in a more similar
+ way to how clients build them. Removes another avenue for
+ enumerating bridges. Fixes bug 4124; bugfix on 0.2.0.3-alpha,
+ when bridges were introduced.
+
+ o Major bugfixes:
+ - Fix an "Assertion md->held_by_node == 1 failed" error that could
+ occur when the same microdescriptor was referenced by two node_t
+ objects at once. Fix for bug 4118; bugfix on Tor 0.2.3.1-alpha.
+
+ o Major features (networking):
+ - Add a new TokenBucketRefillInterval option to refill token buckets
+ more frequently than once per second. This should improve network
+ performance, alleviate queueing problems, and make traffic less
+ bursty. Implements proposal 183; closes ticket 3630. Design by
+ Florian Tschorsch and Björn Scheuermann; implementation by
+ Florian Tschorsch.
+
+ o Minor bugfixes:
+ - Change an integer overflow check in the OpenBSD_Malloc code so
+ that GCC is less likely to eliminate it as impossible. Patch
+ from Mansour Moufid. Fixes bug 4059.
+
+ o Minor bugfixes (usability):
+ - Downgrade log messages about circuit timeout calibration from
+ "notice" to "info": they don't require or suggest any human
+ intervention. Patch from Tom Lowenthal. Fixes bug 4063;
+ bugfix on 0.2.2.14-alpha.
+
+ o Minor features (diagnostics):
+ - When the system call to create a listener socket fails, log the
+ error message explaining why. This may help diagnose bug 4027.
+
+
+Changes in version 0.2.3.4-alpha - 2011-09-13
+ Tor 0.2.3.4-alpha includes the fixes from 0.2.2.33, including a slight
+ tweak to Tor's TLS handshake that makes relays and bridges that run
+ this new version reachable from Iran again. It also fixes a few new
+ bugs in 0.2.3.x, and teaches relays to recognize when they're not
+ listed in the network consensus and republish.
+
+ o Major bugfixes (also part of 0.2.2.33):
+ - Avoid an assertion failure when reloading a configuration with
+ TrackExitHosts changes. Found and fixed by 'laruldan'. Fixes bug
+ 3923; bugfix on 0.2.2.25-alpha.
+
+ o Minor features (security, also part of 0.2.2.33):
+ - Check for replays of the public-key encrypted portion of an
+ INTRODUCE1 cell, in addition to the current check for replays of
+ the g^x value. This prevents a possible class of active attacks
+ by an attacker who controls both an introduction point and a
+ rendezvous point, and who uses the malleability of AES-CTR to
+ alter the encrypted g^x portion of the INTRODUCE1 cell. We think
+ that these attacks is infeasible (requiring the attacker to send
+ on the order of zettabytes of altered cells in a short interval),
+ but we'd rather block them off in case there are any classes of
+ this attack that we missed. Reported by Willem Pinckaers.
+
+ o Minor features (also part of 0.2.2.33):
+ - Adjust the expiration time on our SSL session certificates to
+ better match SSL certs seen in the wild. Resolves ticket 4014.
+ - Change the default required uptime for a relay to be accepted as
+ a HSDir (hidden service directory) from 24 hours to 25 hours.
+ Improves on 0.2.0.10-alpha; resolves ticket 2649.
+ - Add a VoteOnHidServDirectoriesV2 config option to allow directory
+ authorities to abstain from voting on assignment of the HSDir
+ consensus flag. Related to bug 2649.
+ - Update to the September 6 2011 Maxmind GeoLite Country database.
+
+ o Minor bugfixes (also part of 0.2.2.33):
+ - Demote the 'replay detected' log message emitted when a hidden
+ service receives the same Diffie-Hellman public key in two different
+ INTRODUCE2 cells to info level. A normal Tor client can cause that
+ log message during its normal operation. Bugfix on 0.2.1.6-alpha;
+ fixes part of bug 2442.
+ - Demote the 'INTRODUCE2 cell is too {old,new}' log message to info
+ level. There is nothing that a hidden service's operator can do
+ to fix its clients' clocks. Bugfix on 0.2.1.6-alpha; fixes part
+ of bug 2442.
+ - Clarify a log message specifying the characters permitted in
+ HiddenServiceAuthorizeClient client names. Previously, the log
+ message said that "[A-Za-z0-9+-_]" were permitted; that could have
+ given the impression that every ASCII character between "+" and "_"
+ was permitted. Now we say "[A-Za-z0-9+_-]". Bugfix on 0.2.1.5-alpha.
+
+ o Build fixes (also part of 0.2.2.33):
+ - Clean up some code issues that prevented Tor from building on older
+ BSDs. Fixes bug 3894; reported by "grarpamp".
+ - Search for a platform-specific version of "ar" when cross-compiling.
+ Should fix builds on iOS. Resolves bug 3909, found by Marco Bonetti.
+
+ o Major bugfixes:
+ - Fix a bug where the SocksPort option (for example) would get
+ ignored and replaced by the default if a SocksListenAddress
+ option was set. Bugfix on 0.2.3.3-alpha; fixes bug 3936. Fix by
+ Fabian Keil.
+
+ o Major features:
+ - Relays now try regenerating and uploading their descriptor more
+ frequently if they are not listed in the consensus, or if the
+ version of their descriptor listed in the consensus is too
+ old. This fix should prevent situations where a server declines
+ to re-publish itself because it has done so too recently, even
+ though the authorities decided not to list its recent-enough
+ descriptor. Fix for bug 3327.
+
+ o Minor features:
+ - Relays now include a reason for regenerating their descriptors
+ in an HTTP header when uploading to the authorities. This will
+ make it easier to debug descriptor-upload issues in the future.
+ - When starting as root and then changing our UID via the User
+ control option, and we have a ControlSocket configured, make sure
+ that the ControlSocket is owned by the same account that Tor will
+ run under. Implements ticket 3421; fix by Jérémy Bobbio.
+
+ o Minor bugfixes:
+ - Abort if tor_vasprintf fails in connection_printf_to_buf (a
+ utility function used in the control-port code). This shouldn't
+ ever happen unless Tor is completely out of memory, but if it did
+ happen and Tor somehow recovered from it, Tor could have sent a log
+ message to a control port in the middle of a reply to a controller
+ command. Fixes part of bug 3428; bugfix on 0.1.2.3-alpha.
+ - Make 'FetchUselessDescriptors' cause all descriptor types and
+ all consensus types (including microdescriptors) to get fetched.
+ Fixes bug 3851; bugfix on 0.2.3.1-alpha.
+
+ o Code refactoring:
+ - Make a new "entry connection" struct as an internal subtype of "edge
+ connection", to simplify the code and make exit connections smaller.
+
+
+Changes in version 0.2.2.33 - 2011-09-13
+ Tor 0.2.2.33 fixes several bugs, and includes a slight tweak to Tor's
+ TLS handshake that makes relays and bridges that run this new version
+ reachable from Iran again.
+
+ o Major bugfixes:
+ - Avoid an assertion failure when reloading a configuration with
+ TrackExitHosts changes. Found and fixed by 'laruldan'. Fixes bug
+ 3923; bugfix on 0.2.2.25-alpha.
+
+ o Minor features (security):
+ - Check for replays of the public-key encrypted portion of an
+ INTRODUCE1 cell, in addition to the current check for replays of
+ the g^x value. This prevents a possible class of active attacks
+ by an attacker who controls both an introduction point and a
+ rendezvous point, and who uses the malleability of AES-CTR to
+ alter the encrypted g^x portion of the INTRODUCE1 cell. We think
+ that these attacks are infeasible (requiring the attacker to send
+ on the order of zettabytes of altered cells in a short interval),
+ but we'd rather block them off in case there are any classes of
+ this attack that we missed. Reported by Willem Pinckaers.
+
+ o Minor features:
+ - Adjust the expiration time on our SSL session certificates to
+ better match SSL certs seen in the wild. Resolves ticket 4014.
+ - Change the default required uptime for a relay to be accepted as
+ a HSDir (hidden service directory) from 24 hours to 25 hours.
+ Improves on 0.2.0.10-alpha; resolves ticket 2649.
+ - Add a VoteOnHidServDirectoriesV2 config option to allow directory
+ authorities to abstain from voting on assignment of the HSDir
+ consensus flag. Related to bug 2649.
+ - Update to the September 6 2011 Maxmind GeoLite Country database.
+
+ o Minor bugfixes (documentation and log messages):
+ - Correct the man page to explain that HashedControlPassword and
+ CookieAuthentication can both be set, in which case either method
+ is sufficient to authenticate to Tor. Bugfix on 0.2.0.7-alpha,
+ when we decided to allow these config options to both be set. Issue
+ raised by bug 3898.
+ - Demote the 'replay detected' log message emitted when a hidden
+ service receives the same Diffie-Hellman public key in two different
+ INTRODUCE2 cells to info level. A normal Tor client can cause that
+ log message during its normal operation. Bugfix on 0.2.1.6-alpha;
+ fixes part of bug 2442.
+ - Demote the 'INTRODUCE2 cell is too {old,new}' log message to info
+ level. There is nothing that a hidden service's operator can do
+ to fix its clients' clocks. Bugfix on 0.2.1.6-alpha; fixes part
+ of bug 2442.
+ - Clarify a log message specifying the characters permitted in
+ HiddenServiceAuthorizeClient client names. Previously, the log
+ message said that "[A-Za-z0-9+-_]" were permitted; that could have
+ given the impression that every ASCII character between "+" and "_"
+ was permitted. Now we say "[A-Za-z0-9+_-]". Bugfix on 0.2.1.5-alpha.
+
+ o Build fixes:
+ - Provide a substitute implementation of lround() for MSVC, which
+ apparently lacks it. Patch from Gisle Vanem.
+ - Clean up some code issues that prevented Tor from building on older
+ BSDs. Fixes bug 3894; reported by "grarpamp".
+ - Search for a platform-specific version of "ar" when cross-compiling.
+ Should fix builds on iOS. Resolves bug 3909, found by Marco Bonetti.
+
+
+Changes in version 0.2.3.3-alpha - 2011-09-01
+ Tor 0.2.3.3-alpha adds a new "stream isolation" feature to improve Tor's
+ security, and provides client-side support for the microdescriptor
+ and optimistic data features introduced earlier in the 0.2.3.x
+ series. It also includes numerous critical bugfixes in the (optional)
+ bufferevent-based networking backend.
+
+ o Major features (stream isolation):
+ - You can now configure Tor so that streams from different
+ applications are isolated on different circuits, to prevent an
+ attacker who sees your streams as they leave an exit node from
+ linking your sessions to one another. To do this, choose some way
+ to distinguish the applications: have them connect to different
+ SocksPorts, or have one of them use SOCKS4 while the other uses
+ SOCKS5, or have them pass different authentication strings to the
+ SOCKS proxy. Then, use the new SocksPort syntax to configure the
+ degree of isolation you need. This implements Proposal 171.
+ - There's a new syntax for specifying multiple client ports (such as
+ SOCKSPort, TransPort, DNSPort, NATDPort): you can now just declare
+ multiple *Port entries with full addr:port syntax on each.
+ The old *ListenAddress format is still supported, but you can't
+ mix it with the new *Port syntax.
+
+ o Major features (other):
+ - Enable microdescriptor fetching by default for clients. This allows
+ clients to download a much smaller amount of directory information.
+ To disable it (and go back to the old-style consensus and
+ descriptors), set "UseMicrodescriptors 0" in your torrc file.
+ - Tor's firewall-helper feature, introduced in 0.2.3.1-alpha (see the
+ "PortForwarding" config option), now supports Windows.
+ - When using an exit relay running 0.2.3.x, clients can now
+ "optimistically" send data before the exit relay reports that
+ the stream has opened. This saves a round trip when starting
+ connections where the client speaks first (such as web browsing).
+ This behavior is controlled by a consensus parameter (currently
+ disabled). To turn it on or off manually, use the "OptimisticData"
+ torrc option. Implements proposal 181; code by Ian Goldberg.
+
+ o Major bugfixes (bufferevents, fixes on 0.2.3.1-alpha):
+ - When using IOCP on Windows, we need to enable Libevent windows
+ threading support.
+ - The IOCP backend now works even when the user has not specified
+ the (internal, debugging-only) _UseFilteringSSLBufferevents option.
+ Fixes part of bug 3752.
+ - Correctly record the bytes we've read and written when using
+ bufferevents, so that we can include them in our bandwidth history
+ and advertised bandwidth. Fixes bug 3803.
+ - Apply rate-limiting only at the bottom of a chain of filtering
+ bufferevents. This prevents us from filling up internal read
+ buffers and violating rate-limits when filtering bufferevents
+ are enabled. Fixes part of bug 3804.
+ - Add high-watermarks to the output buffers for filtered
+ bufferevents. This prevents us from filling up internal write
+ buffers and wasting CPU cycles when filtering bufferevents are
+ enabled. Fixes part of bug 3804.
+ - Correctly notice when data has been written from a bufferevent
+ without flushing it completely. Fixes bug 3805.
+ - Fix a bug where server-side tunneled bufferevent-based directory
+ streams would get closed prematurely. Fixes bug 3814.
+ - Fix a use-after-free error with per-connection rate-limiting
+ buckets. Fixes bug 3888.
+
+ o Major bugfixes (also part of 0.2.2.31-rc):
+ - If we're configured to write our ControlPorts to disk, only write
+ them after switching UID and creating the data directory. This way,
+ we don't fail when starting up with a nonexistent DataDirectory
+ and a ControlPortWriteToFile setting based on that directory. Fixes
+ bug 3747; bugfix on Tor 0.2.2.26-beta.
+
+ o Minor features:
+ - Added a new CONF_CHANGED event so that controllers can be notified
+ of any configuration changes made by other controllers, or by the
+ user. Implements ticket 1692.
+ - Use evbuffer_copyout() in inspect_evbuffer(). This fixes a memory
+ leak when using bufferevents, and lets Libevent worry about how to
+ best copy data out of a buffer.
+ - Replace files in stats/ rather than appending to them. Now that we
+ include statistics in extra-info descriptors, it makes no sense to
+ keep old statistics forever. Implements ticket 2930.
+
+ o Minor features (build compatibility):
+ - Limited, experimental support for building with nmake and MSVC.
+ - Provide a substitute implementation of lround() for MSVC, which
+ apparently lacks it. Patch from Gisle Vanem.
+
+ o Minor features (also part of 0.2.2.31-rc):
+ - Update to the August 2 2011 Maxmind GeoLite Country database.
+
+ o Minor bugfixes (on 0.2.3.x-alpha):
+ - Fix a spurious warning when parsing SOCKS requests with
+ bufferevents enabled. Fixes bug 3615; bugfix on 0.2.3.2-alpha.
+ - Get rid of a harmless warning that could happen on relays running
+ with bufferevents. The warning was caused by someone doing an http
+ request to a relay's orport. Also don't warn for a few related
+ non-errors. Fixes bug 3700; bugfix on 0.2.3.1-alpha.
+
+ o Minor bugfixes (on 2.2.x and earlier):
+ - Correct the man page to explain that HashedControlPassword and
+ CookieAuthentication can both be set, in which case either method
+ is sufficient to authenticate to Tor. Bugfix on 0.2.0.7-alpha,
+ when we decided to allow these config options to both be set. Issue
+ raised by bug 3898.
+ - The "--quiet" and "--hush" options now apply not only to Tor's
+ behavior before logs are configured, but also to Tor's behavior in
+ the absense of configured logs. Fixes bug 3550; bugfix on
+ 0.2.0.10-alpha.
+
+ o Minor bugfixes (also part of 0.2.2.31-rc):
+ - Write several files in text mode, on OSes that distinguish text
+ mode from binary mode (namely, Windows). These files are:
+ 'buffer-stats', 'dirreq-stats', and 'entry-stats' on relays
+ that collect those statistics; 'client_keys' and 'hostname' for
+ hidden services that use authentication; and (in the tor-gencert
+ utility) newly generated identity and signing keys. Previously,
+ we wouldn't specify text mode or binary mode, leading to an
+ assertion failure. Fixes bug 3607. Bugfix on 0.2.1.1-alpha (when
+ the DirRecordUsageByCountry option which would have triggered
+ the assertion failure was added), although this assertion failure
+ would have occurred in tor-gencert on Windows in 0.2.0.1-alpha.
+ - Selectively disable deprecation warnings on OS X because Lion
+ started deprecating the shipped copy of openssl. Fixes bug 3643.
+ - Remove an extra pair of quotation marks around the error
+ message in control-port STATUS_GENERAL BUG events. Bugfix on
+ 0.1.2.6-alpha; fixes bug 3732.
+ - When unable to format an address as a string, report its value
+ as "???" rather than reusing the last formatted address. Bugfix
+ on 0.2.1.5-alpha.
+
+ o Code simplifications and refactoring:
+ - Rewrite the listener-selection logic so that parsing which ports
+ we want to listen on is now separate from binding to the ports
+ we want.
+
+ o Build changes:
+ - Building Tor with bufferevent support now requires Libevent
+ 2.0.13-stable or later. Previous versions of Libevent had bugs in
+ SSL-related bufferevents and related issues that would make Tor
+ work badly with bufferevents. Requiring 2.0.13-stable also allows
+ Tor with bufferevents to take advantage of Libevent APIs
+ introduced after 2.0.8-rc.
+
+
+Changes in version 0.2.2.32 - 2011-08-27
+ The Tor 0.2.2 release series is dedicated to the memory of Andreas
+ Pfitzmann (1958-2010), a pioneer in anonymity and privacy research,
+ a founder of the PETS community, a leader in our field, a mentor,
+ and a friend. He left us with these words: "I had the possibility
+ to contribute to this world that is not as it should be. I hope I
+ could help in some areas to make the world a better place, and that
+ I could also encourage other people to be engaged in improving the
+ world. Please, stay engaged. This world needs you, your love, your
+ initiative -- now I cannot be part of that anymore."
+
+ Tor 0.2.2.32, the first stable release in the 0.2.2 branch, is finally
+ ready. More than two years in the making, this release features improved
+ client performance and hidden service reliability, better compatibility
+ for Android, correct behavior for bridges that listen on more than
+ one address, more extensible and flexible directory object handling,
+ better reporting of network statistics, improved code security, and
+ many many other features and bugfixes.
+
+
+Changes in version 0.2.2.31-rc - 2011-08-17
+ Tor 0.2.2.31-rc is the second and hopefully final release candidate
+ for the Tor 0.2.2.x series.
+
+ o Major bugfixes:
+ - Remove an extra pair of quotation marks around the error
+ message in control-port STATUS_GENERAL BUG events. Bugfix on
+ 0.1.2.6-alpha; fixes bug 3732.
+ - If we're configured to write our ControlPorts to disk, only write
+ them after switching UID and creating the data directory. This way,
+ we don't fail when starting up with a nonexistent DataDirectory
+ and a ControlPortWriteToFile setting based on that directory. Fixes
+ bug 3747; bugfix on Tor 0.2.2.26-beta.
+
+ o Minor features:
+ - Update to the August 2 2011 Maxmind GeoLite Country database.
+
+ o Minor bugfixes:
+ - Allow GETINFO fingerprint to return a fingerprint even when
+ we have not yet built a router descriptor. Fixes bug 3577;
+ bugfix on 0.2.0.1-alpha.
+ - Write several files in text mode, on OSes that distinguish text
+ mode from binary mode (namely, Windows). These files are:
+ 'buffer-stats', 'dirreq-stats', and 'entry-stats' on relays
+ that collect those statistics; 'client_keys' and 'hostname' for
+ hidden services that use authentication; and (in the tor-gencert
+ utility) newly generated identity and signing keys. Previously,
+ we wouldn't specify text mode or binary mode, leading to an
+ assertion failure. Fixes bug 3607. Bugfix on 0.2.1.1-alpha (when
+ the DirRecordUsageByCountry option which would have triggered
+ the assertion failure was added), although this assertion failure
+ would have occurred in tor-gencert on Windows in 0.2.0.1-alpha.
+ - Selectively disable deprecation warnings on OS X because Lion
+ started deprecating the shipped copy of openssl. Fixes bug 3643.
+ - When unable to format an address as a string, report its value
+ as "???" rather than reusing the last formatted address. Bugfix
+ on 0.2.1.5-alpha.
+
+
+Changes in version 0.2.3.2-alpha - 2011-07-18
+ Tor 0.2.3.2-alpha introduces two new experimental features:
+ microdescriptors and pluggable transports. It also continues cleaning
+ up a variety of recently introduced features.
+
+ o Major features:
+ - Clients can now use microdescriptors instead of regular descriptors
+ to build circuits. Microdescriptors are authority-generated
+ summaries of regular descriptors' contents, designed to change
+ very rarely (see proposal 158 for details). This feature is
+ designed to save bandwidth, especially for clients on slow internet
+ connections. It's off by default for now, since nearly no caches
+ support it, but it will be on-by-default for clients in a future
+ version. You can use the UseMicrodescriptors option to turn it on.
+ - Tor clients using bridges can now be configured to use a separate
+ 'transport' proxy for each bridge. This approach helps to resist
+ censorship by allowing bridges to use protocol obfuscation
+ plugins. It implements part of proposal 180. Implements ticket 2841.
+ - While we're trying to bootstrap, record how many TLS connections
+ fail in each state, and report which states saw the most failures
+ in response to any bootstrap failures. This feature may speed up
+ diagnosis of censorship events. Implements ticket 3116.
+
+ o Major bugfixes (on 0.2.3.1-alpha):
+ - When configuring a large set of nodes in EntryNodes (as with
+ 'EntryNodes {cc}' or 'EntryNodes 1.1.1.1/16'), choose only a
+ random subset to be guards, and choose them in random
+ order. Fixes bug 2798.
+ - Tor could crash when remembering a consensus in a non-used consensus
+ flavor without having a current consensus set. Fixes bug 3361.
+ - Comparing an unknown address to a microdescriptor's shortened exit
+ policy would always give a "rejected" result. Fixes bug 3599.
+ - Using microdescriptors as a client no longer prevents Tor from
+ uploading and downloading hidden service descriptors. Fixes
+ bug 3601.
+
+ o Minor features:
+ - Allow nameservers with IPv6 address. Resolves bug 2574.
+ - Accept attempts to include a password authenticator in the
+ handshake, as supported by SOCKS5. This handles SOCKS clients that
+ don't know how to omit a password when authenticating. Resolves
+ bug 1666.
+ - When configuring a large set of nodes in EntryNodes, and there are
+ enough of them listed as Guard so that we don't need to consider
+ the non-guard entries, prefer the ones listed with the Guard flag.
+ - Check for and recover from inconsistency in the microdescriptor
+ cache. This will make it harder for us to accidentally free a
+ microdescriptor without removing it from the appropriate data
+ structures. Fixes issue 3135; issue noted by "wanoskarnet".
+ - Log SSL state transitions at log level DEBUG, log domain
+ HANDSHAKE. This can be useful for debugging censorship events.
+ Implements ticket 3264.
+ - Add port 6523 (Gobby) to LongLivedPorts. Patch by intrigeri;
+ implements ticket 3439.
+
+ o Minor bugfixes (on 0.2.3.1-alpha):
+ - Do not free all general-purpose regular descriptors just
+ because microdescriptor use is enabled. Fixes bug 3113.
+ - Correctly link libevent_openssl when --enable-static-libevent
+ is passed to configure. Fixes bug 3118.
+ - Bridges should not complain during their heartbeat log messages that
+ they are unlisted in the consensus: that's more or less the point
+ of being a bridge. Fixes bug 3183.
+ - Report a SIGNAL event to controllers when acting on a delayed
+ SIGNAL NEWNYM command. Previously, we would report a SIGNAL
+ event to the controller if we acted on a SIGNAL NEWNYM command
+ immediately, and otherwise not report a SIGNAL event for the
+ command at all. Fixes bug 3349.
+ - Fix a crash when handling the SIGNAL controller command or
+ reporting ERR-level status events with bufferevents enabled. Found
+ by Robert Ransom. Fixes bug 3367.
+ - Always ship the tor-fw-helper manpage in our release tarballs.
+ Fixes bug 3389. Reported by Stephen Walker.
+ - Fix a class of double-mark-for-close bugs when bufferevents
+ are enabled. Fixes bug 3403.
+ - Update tor-fw-helper to support libnatpmp-20110618. Fixes bug 3434.
+ - Add SIGNAL to the list returned by the 'GETINFO events/names'
+ control-port command. Fixes part of bug 3465.
+ - Prevent using negative indices during unit test runs when read_all()
+ fails. Spotted by coverity.
+ - Fix a rare memory leak when checking the nodelist without it being
+ present. Found by coverity.
+ - Only try to download a microdescriptor-flavored consensus from
+ a directory cache that provides them.
+
+ o Minor bugfixes (on 0.2.2.x and earlier):
+ - Assert that hidden-service-related operations are not performed
+ using single-hop circuits. Previously, Tor would assert that
+ client-side streams are not attached to single-hop circuits,
+ but not that other sensitive operations on the client and service
+ side are not performed using single-hop circuits. Fixes bug 3332;
+ bugfix on 0.0.6.
+ - Don't publish a new relay descriptor when we reload our onion key,
+ unless the onion key has actually changed. Fixes bug 3263 and
+ resolves another cause of bug 1810. Bugfix on 0.1.1.11-alpha.
+ - Allow GETINFO fingerprint to return a fingerprint even when
+ we have not yet built a router descriptor. Fixes bug 3577;
+ bugfix on 0.2.0.1-alpha.
+ - Make 'tor --digests' list hashes of all Tor source files. Bugfix
+ on 0.2.2.4-alpha; fixes bug 3427.
+
+ o Code simplification and refactoring:
+ - Use tor_sscanf() in place of scanf() in more places through the
+ code. This makes us a little more locale-independent, and
+ should help shut up code-analysis tools that can't tell
+ a safe sscanf string from a dangerous one.
+ - Use tt_assert(), not tor_assert(), for checking for test failures.
+ This makes the unit tests more able to go on in the event that
+ one of them fails.
+ - Split connection_about_to_close() into separate functions for each
+ connection type.
+
+ o Build changes:
+ - On Windows, we now define the _WIN32_WINNT macros only if they
+ are not already defined. This lets the person building Tor decide,
+ if they want, to require a later version of Windows.
+
+
+Changes in version 0.2.2.30-rc - 2011-07-07
+ Tor 0.2.2.30-rc is the first release candidate for the Tor 0.2.2.x
+ series. It fixes a few smaller bugs, but generally appears stable.
+ Please test it and let us know whether it is!
+
+ o Minor bugfixes:
+ - Send a SUCCEEDED stream event to the controller when a reverse
+ resolve succeeded. Fixes bug 3536; bugfix on 0.0.8pre1. Issue
+ discovered by katmagic.
+ - Always NUL-terminate the sun_path field of a sockaddr_un before
+ passing it to the kernel. (Not a security issue: kernels are
+ smart enough to reject bad sockaddr_uns.) Found by Coverity;
+ CID #428. Bugfix on Tor 0.2.0.3-alpha.
+ - Don't stack-allocate the list of supplementary GIDs when we're
+ about to log them. Stack-allocating NGROUPS_MAX gid_t elements
+ could take up to 256K, which is way too much stack. Found by
+ Coverity; CID #450. Bugfix on 0.2.1.7-alpha.
+ - Add BUILDTIMEOUT_SET to the list returned by the 'GETINFO
+ events/names' control-port command. Bugfix on 0.2.2.9-alpha;
+ fixes part of bug 3465.
+ - Fix a memory leak when receiving a descriptor for a hidden
+ service we didn't ask for. Found by Coverity; CID #30. Bugfix
+ on 0.2.2.26-beta.
+
+ o Minor features:
+ - Update to the July 1 2011 Maxmind GeoLite Country database.
+
+
+Changes in version 0.2.2.29-beta - 2011-06-20
+ Tor 0.2.2.29-beta reverts an accidental behavior change for users who
+ have bridge lines in their torrc but don't want to use them; gets
+ us closer to having the control socket feature working on Debian;
+ and fixes a variety of smaller bugs.
+
+ o Major bugfixes:
+ - Revert the UseBridges option to its behavior before 0.2.2.28-beta.
+ When we changed the default behavior to "use bridges if any
+ are listed in the torrc", we surprised users who had bridges
+ in their torrc files but who didn't actually want to use them.
+ Partial resolution for bug 3354.
+
+ o Privacy fixes:
+ - Don't attach new streams to old rendezvous circuits after SIGNAL
+ NEWNYM. Previously, we would keep using an existing rendezvous
+ circuit if it remained open (i.e. if it were kept open by a
+ long-lived stream, or if a new stream were attached to it before
+ Tor could notice that it was old and no longer in use). Bugfix on
+ 0.1.1.15-rc; fixes bug 3375.
+
+ o Minor bugfixes:
+ - Fix a bug when using ControlSocketsGroupWritable with User. The
+ directory's group would be checked against the current group, not
+ the configured group. Patch by Jérémy Bobbio. Fixes bug 3393;
+ bugfix on 0.2.2.26-beta.
+ - Make connection_printf_to_buf()'s behaviour sane. Its callers
+ expect it to emit a CRLF iff the format string ends with CRLF;
+ it actually emitted a CRLF iff (a) the format string ended with
+ CRLF or (b) the resulting string was over 1023 characters long or
+ (c) the format string did not end with CRLF *and* the resulting
+ string was 1021 characters long or longer. Bugfix on 0.1.1.9-alpha;
+ fixes part of bug 3407.
+ - Make send_control_event_impl()'s behaviour sane. Its callers
+ expect it to always emit a CRLF at the end of the string; it
+ might have emitted extra control characters as well. Bugfix on
+ 0.1.1.9-alpha; fixes another part of bug 3407.
+ - Make crypto_rand_int() check the value of its input correctly.
+ Previously, it accepted values up to UINT_MAX, but could return a
+ negative number if given a value above INT_MAX+1. Found by George
+ Kadianakis. Fixes bug 3306; bugfix on 0.2.2pre14.
+ - Avoid a segfault when reading a malformed circuit build state
+ with more than INT_MAX entries. Found by wanoskarnet. Bugfix on
+ 0.2.2.4-alpha.
+ - When asked about a DNS record type we don't support via a
+ client DNSPort, reply with NOTIMPL rather than an empty
+ reply. Patch by intrigeri. Fixes bug 3369; bugfix on 2.0.1-alpha.
+ - Fix a rare memory leak during stats writing. Found by coverity.
+
+ o Minor features:
+ - Update to the June 1 2011 Maxmind GeoLite Country database.
+
+ o Code simplifications and refactoring:
+ - Remove some dead code as indicated by coverity.
+ - Remove a few dead assignments during router parsing. Found by
+ coverity.
+ - Add some forgotten return value checks during unit tests. Found
+ by coverity.
+ - Don't use 1-bit wide signed bit fields. Found by coverity.
+
+
+Changes in version 0.2.2.28-beta - 2011-06-04
+ Tor 0.2.2.28-beta makes great progress towards a new stable release: we
+ fixed a big bug in whether relays stay in the consensus consistently,
+ we moved closer to handling bridges and hidden services correctly,
+ and we started the process of better handling the dreaded "my Vidalia
+ died, and now my Tor demands a password when I try to reconnect to it"
+ usability issue.
+
+ o Major bugfixes:
+ - Don't decide to make a new descriptor when receiving a HUP signal.
+ This bug has caused a lot of 0.2.2.x relays to disappear from the
+ consensus periodically. Fixes the most common case of triggering
+ bug 1810; bugfix on 0.2.2.7-alpha.
+ - Actually allow nameservers with IPv6 addresses. Fixes bug 2574.
+ - Don't try to build descriptors if "ORPort auto" is set and we
+ don't know our actual ORPort yet. Fix for bug 3216; bugfix on
+ 0.2.2.26-beta.
+ - Resolve a crash that occurred when setting BridgeRelay to 1 with
+ accounting enabled. Fixes bug 3228; bugfix on 0.2.2.18-alpha.
+ - Apply circuit timeouts to opened hidden-service-related circuits
+ based on the correct start time. Previously, we would apply the
+ circuit build timeout based on time since the circuit's creation;
+ it was supposed to be applied based on time since the circuit
+ entered its current state. Bugfix on 0.0.6; fixes part of bug 1297.
+ - Use the same circuit timeout for client-side introduction
+ circuits as for other four-hop circuits, rather than the timeout
+ for single-hop directory-fetch circuits; the shorter timeout may
+ have been appropriate with the static circuit build timeout in
+ 0.2.1.x and earlier, but caused many hidden service access attempts
+ to fail with the adaptive CBT introduced in 0.2.2.2-alpha. Bugfix
+ on 0.2.2.2-alpha; fixes another part of bug 1297.
+ - In ticket 2511 we fixed a case where you could use an unconfigured
+ bridge if you had configured it as a bridge the last time you ran
+ Tor. Now fix another edge case: if you had configured it as a bridge
+ but then switched to a different bridge via the controller, you
+ would still be willing to use the old one. Bugfix on 0.2.0.1-alpha;
+ fixes bug 3321.
+
+ o Major features:
+ - Add an __OwningControllerProcess configuration option and a
+ TAKEOWNERSHIP control-port command. Now a Tor controller can ensure
+ that when it exits, Tor will shut down. Implements feature 3049.
+ - If "UseBridges 1" is set and no bridges are configured, Tor will
+ now refuse to build any circuits until some bridges are set.
+ If "UseBridges auto" is set, Tor will use bridges if they are
+ configured and we are not running as a server, but otherwise will
+ make circuits as usual. The new default is "auto". Patch by anonym,
+ so the Tails LiveCD can stop automatically revealing you as a Tor
+ user on startup.
+
+ o Minor bugfixes:
+ - Fix warnings from GCC 4.6's "-Wunused-but-set-variable" option.
+ - Remove a trailing asterisk from "exit-policy/default" in the
+ output of the control port command "GETINFO info/names". Bugfix
+ on 0.1.2.5-alpha.
+ - Use a wide type to hold sockets when built for 64-bit Windows builds.
+ Fixes bug 3270.
+ - Warn when the user configures two HiddenServiceDir lines that point
+ to the same directory. Bugfix on 0.0.6 (the version introducing
+ HiddenServiceDir); fixes bug 3289.
+ - Remove dead code from rend_cache_lookup_v2_desc_as_dir. Fixes
+ part of bug 2748; bugfix on 0.2.0.10-alpha.
+ - Log malformed requests for rendezvous descriptors as protocol
+ warnings, not warnings. Also, use a more informative log message
+ in case someone sees it at log level warning without prior
+ info-level messages. Fixes the other part of bug 2748; bugfix
+ on 0.2.0.10-alpha.
+ - Clear the table recording the time of the last request for each
+ hidden service descriptor from each HS directory on SIGNAL NEWNYM.
+ Previously, we would clear our HS descriptor cache on SIGNAL
+ NEWNYM, but if we had previously retrieved a descriptor (or tried
+ to) from every directory responsible for it, we would refuse to
+ fetch it again for up to 15 minutes. Bugfix on 0.2.2.25-alpha;
+ fixes bug 3309.
+ - Fix a log message that said "bits" while displaying a value in
+ bytes. Found by wanoskarnet. Fixes bug 3318; bugfix on
+ 0.2.0.1-alpha.
+ - When checking for 1024-bit keys, check for 1024 bits, not 128
+ bytes. This allows Tor to correctly discard keys of length 1017
+ through 1023. Bugfix on 0.0.9pre5.
+
+ o Minor features:
+ - Relays now log the reason for publishing a new relay descriptor,
+ so we have a better chance of hunting down instances of bug 1810.
+ Resolves ticket 3252.
+ - Revise most log messages that refer to nodes by nickname to
+ instead use the "$key=nickname at address" format. This should be
+ more useful, especially since nicknames are less and less likely
+ to be unique. Resolves ticket 3045.
+ - Log (at info level) when purging pieces of hidden-service-client
+ state because of SIGNAL NEWNYM.
+
+ o Removed options:
+ - Remove undocumented option "-F" from tor-resolve: it hasn't done
+ anything since 0.2.1.16-rc.
+
+
+Changes in version 0.2.2.27-beta - 2011-05-18
+ Tor 0.2.2.27-beta fixes a bridge-related stability bug in the previous
+ release, and also adds a few more general bugfixes.
+
+ o Major bugfixes:
+ - Fix a crash bug when changing bridges in a running Tor process.
+ Fixes bug 3213; bugfix on 0.2.2.26-beta.
+ - When the controller configures a new bridge, don't wait 10 to 60
+ seconds before trying to fetch its descriptor. Bugfix on
+ 0.2.0.3-alpha; fixes bug 3198 (suggested by 2355).
+
+ o Minor bugfixes:
+ - Require that onion keys have exponent 65537 in microdescriptors too.
+ Fixes more of bug 3207; bugfix on 0.2.2.26-beta.
+ - Tor used to limit HttpProxyAuthenticator values to 48 characters.
+ Changed the limit to 512 characters by removing base64 newlines.
+ Fixes bug 2752. Fix by Michael Yakubovich.
+ - When a client starts or stops using bridges, never use a circuit
+ that was built before the configuration change. This behavior could
+ put at risk a user who uses bridges to ensure that her traffic
+ only goes to the chosen addresses. Bugfix on 0.2.0.3-alpha; fixes
+ bug 3200.
+
+
+Changes in version 0.2.2.26-beta - 2011-05-17
+ Tor 0.2.2.26-beta fixes a variety of potential privacy problems. It
+ also introduces a new "socksport auto" approach that should make it
+ easier to run multiple Tors on the same system, and does a lot of
+ cleanup to get us closer to a release candidate.
+
+ o Security/privacy fixes:
+ - Replace all potentially sensitive memory comparison operations
+ with versions whose runtime does not depend on the data being
+ compared. This will help resist a class of attacks where an
+ adversary can use variations in timing information to learn
+ sensitive data. Fix for one case of bug 3122. (Safe memcmp
+ implementation by Robert Ransom based partially on code by DJB.)
+ - When receiving a hidden service descriptor, check that it is for
+ the hidden service we wanted. Previously, Tor would store any
+ hidden service descriptors that a directory gave it, whether it
+ wanted them or not. This wouldn't have let an attacker impersonate
+ a hidden service, but it did let directories pre-seed a client
+ with descriptors that it didn't want. Bugfix on 0.0.6.
+ - On SIGHUP, do not clear out all TrackHostExits mappings, client
+ DNS cache entries, and virtual address mappings: that's what
+ NEWNYM is for. Fixes bug 1345; bugfix on 0.1.0.1-rc.
+
+ o Major features:
+ - The options SocksPort, ControlPort, and so on now all accept a
+ value "auto" that opens a socket on an OS-selected port. A
+ new ControlPortWriteToFile option tells Tor to write its
+ actual control port or ports to a chosen file. If the option
+ ControlPortFileGroupReadable is set, the file is created as
+ group-readable. Now users can run two Tor clients on the same
+ system without needing to manually mess with parameters. Resolves
+ part of ticket 3076.
+ - Set SO_REUSEADDR on all sockets, not just listeners. This should
+ help busy exit nodes avoid running out of useable ports just
+ because all the ports have been used in the near past. Resolves
+ issue 2850.
+
+ o Minor features:
+ - New "GETINFO net/listeners/(type)" controller command to return
+ a list of addresses and ports that are bound for listeners for a
+ given connection type. This is useful when the user has configured
+ "SocksPort auto" and the controller needs to know which port got
+ chosen. Resolves another part of ticket 3076.
+ - Add a new ControlSocketsGroupWritable configuration option: when
+ it is turned on, ControlSockets are group-writeable by the default
+ group of the current user. Patch by Jérémy Bobbio; implements
+ ticket 2972.
+ - Tor now refuses to create a ControlSocket in a directory that is
+ world-readable (or group-readable if ControlSocketsGroupWritable
+ is 0). This is necessary because some operating systems do not
+ enforce permissions on an AF_UNIX sockets. Permissions on the
+ directory holding the socket, however, seems to work everywhere.
+ - Rate-limit a warning about failures to download v2 networkstatus
+ documents. Resolves part of bug 1352.
+ - Backport code from 0.2.3.x that allows directory authorities to
+ clean their microdescriptor caches. Needed to resolve bug 2230.
+ - When an HTTPS proxy reports "403 Forbidden", we now explain
+ what it means rather than calling it an unexpected status code.
+ Closes bug 2503. Patch from Michael Yakubovich.
+ - Update to the May 1 2011 Maxmind GeoLite Country database.
+
+ o Minor bugfixes:
+ - Authorities now clean their microdesc cache periodically and when
+ reading from disk initially, not only when adding new descriptors.
+ This prevents a bug where we could lose microdescriptors. Bugfix
+ on 0.2.2.6-alpha. Fixes bug 2230.
+ - Do not crash when our configuration file becomes unreadable, for
+ example due to a permissions change, between when we start up
+ and when a controller calls SAVECONF. Fixes bug 3135; bugfix
+ on 0.0.9pre6.
+ - Avoid a bug that would keep us from replacing a microdescriptor
+ cache on Windows. (We would try to replace the file while still
+ holding it open. That's fine on Unix, but Windows doesn't let us
+ do that.) Bugfix on 0.2.2.6-alpha; bug found by wanoskarnet.
+ - Add missing explanations for the authority-related torrc options
+ RephistTrackTime, BridgePassword, and V3AuthUseLegacyKey in the
+ man page. Resolves issue 2379.
+ - As an authority, do not upload our own vote or signature set to
+ ourself. It would tell us nothing new, and as of 0.2.2.24-alpha,
+ it would get flagged as a duplicate. Resolves bug 3026.
+ - Accept hidden service descriptors if we think we might be a hidden
+ service directory, regardless of what our consensus says. This
+ helps robustness, since clients and hidden services can sometimes
+ have a more up-to-date view of the network consensus than we do,
+ and if they think that the directory authorities list us a HSDir,
+ we might actually be one. Related to bug 2732; bugfix on
+ 0.2.0.10-alpha.
+ - When a controller changes TrackHostExits, remove mappings for
+ hosts that should no longer have their exits tracked. Bugfix on
+ 0.1.0.1-rc.
+ - When a controller changes VirtualAddrNetwork, remove any mappings
+ for hosts that were automapped to the old network. Bugfix on
+ 0.1.1.19-rc.
+ - When a controller changes one of the AutomapHosts* options, remove
+ any mappings for hosts that should no longer be automapped. Bugfix
+ on 0.2.0.1-alpha.
+ - Do not reset the bridge descriptor download status every time we
+ re-parse our configuration or get a configuration change. Fixes
+ bug 3019; bugfix on 0.2.0.3-alpha.
+
+ o Minor bugfixes (code cleanup):
+ - When loading the microdesc journal, remember its current size.
+ In 0.2.2, this helps prevent the microdesc journal from growing
+ without limit on authorities (who are the only ones to use it in
+ 0.2.2). Fixes a part of bug 2230; bugfix on 0.2.2.6-alpha.
+ Fix posted by "cypherpunks."
+ - The microdesc journal is supposed to get rebuilt only if it is
+ at least _half_ the length of the store, not _twice_ the length
+ of the store. Bugfix on 0.2.2.6-alpha; fixes part of bug 2230.
+ - Fix a potential null-pointer dereference while computing a
+ consensus. Bugfix on tor-0.2.0.3-alpha, found with the help of
+ clang's analyzer.
+ - Avoid a possible null-pointer dereference when rebuilding the mdesc
+ cache without actually having any descriptors to cache. Bugfix on
+ 0.2.2.6-alpha. Issue discovered using clang's static analyzer.
+ - If we fail to compute the identity digest of a v3 legacy keypair,
+ warn, and don't use a buffer-full of junk instead. Bugfix on
+ 0.2.1.1-alpha; fixes bug 3106.
+ - Resolve an untriggerable issue in smartlist_string_num_isin(),
+ where if the function had ever in the future been used to check
+ for the presence of a too-large number, it would have given an
+ incorrect result. (Fortunately, we only used it for 16-bit
+ values.) Fixes bug 3175; bugfix on 0.1.0.1-rc.
+ - Require that introduction point keys and onion handshake keys
+ have a public exponent of 65537. Starts to fix bug 3207; bugfix
+ on 0.2.0.10-alpha.
+
+ o Removed features:
+ - Caches no longer download and serve v2 networkstatus documents
+ unless FetchV2Networkstatus flag is set: these documents haven't
+ haven't been used by clients or relays since 0.2.0.x. Resolves
+ bug 3022.
+
+
+Changes in version 0.2.3.1-alpha - 2011-05-05
+ Tor 0.2.3.1-alpha adds some new experimental features, including support
+ for an improved network IO backend, IOCP networking on Windows,
+ microdescriptor caching, "fast-start" support for streams, and automatic
+ home router configuration. There are also numerous internal improvements
+ to try to make the code easier for developers to work with.
+
+ This is the first alpha release in a new series, so expect there to be
+ bugs. Users who would rather test out a more stable branch should
+ stay with 0.2.2.x for now.
+
+ o Major features:
+ - Tor can now optionally build with the "bufferevents" buffered IO
+ backend provided by Libevent 2. To use this feature, make sure you
+ have the latest possible version of Libevent, and pass the
+ --enable-bufferevents flag to configure when building Tor from
+ source. This feature will make our networking code more flexible,
+ let us stack layers on each other, and let us use more efficient
+ zero-copy transports where available.
+ - As an experimental feature, Tor can use IOCP for networking on Windows.
+ Once this code is tuned and optimized, it promises much better
+ performance than the select-based backend we've used in the past. To
+ try this feature, you must build Tor with Libevent 2, configure Tor
+ with the "bufferevents" buffered IO backend, and add "DisableIOCP 0" to
+ your torrc. There are known bugs here: only try this if you can help
+ debug it as it breaks.
+ - The EntryNodes option can now include country codes like {de} or IP
+ addresses or network masks. Previously we had disallowed these options
+ because we didn't have an efficient way to keep the list up to
+ date. Fixes bug 1982, but see bug 2798 for an unresolved issue here.
+ - Exit nodes now accept and queue data on not-yet-connected streams.
+ Previously, the client wasn't allowed to send data until the stream was
+ connected, which slowed down all connections. This change will enable
+ clients to perform a "fast-start" on streams and send data without
+ having to wait for a confirmation that the stream has opened. (Patch
+ from Ian Goldberg; implements the server side of Proposal 174.)
+ - Tor now has initial support for automatic port mapping on the many
+ home routers that support NAT-PMP or UPnP. (Not yet supported on
+ Windows). To build the support code, you'll need to have libnatpnp
+ library and/or the libminiupnpc library, and you'll need to enable the
+ feature specifically by passing "--enable-upnp" and/or
+ "--enable-natpnp" to configure. To turn it on, use the new
+ PortForwarding option.
+ - Caches now download, cache, and serve multiple "flavors" of the
+ consensus, including a flavor that describes microdescriptors.
+ - Caches now download, cache, and serve microdescriptors -- small
+ summaries of router descriptors that are authenticated by all of the
+ directory authorities. Once enough caches are running this code,
+ clients will be able to save significant amounts of directory bandwidth
+ by downloading microdescriptors instead of router descriptors.
+
+ o Minor features:
+ - Make logging resolution configurable with a new LogTimeGranularity
+ option, and change the default from 1 millisecond to 1 second.
+ Implements enhancement 1668.
+ - We log which torrc file we're using on startup. Implements ticket
+ 2444.
+ - Ordinarily, Tor does not count traffic from private addresses (like
+ 127.0.0.1 or 10.0.0.1) when calculating rate limits or accounting.
+ There is now a new option, CountPrivateBandwidth, to disable this
+ behavior. Patch from Daniel Cagara.
+ - New --enable-static-tor configure option for building Tor as
+ statically as possible. Idea, general hackery and thoughts from
+ Alexei Czeskis, John Gilmore, Jacob Appelbaum. Implements ticket
+ 2702.
+ - If you set the NumCPUs option to 0, Tor will now try to detect how
+ many CPUs you have. This is the new default behavior.
+ - Turn on directory request statistics by default and include them in
+ extra-info descriptors. Don't break if we have no GeoIP database.
+ - Relays that set "ConnDirectionStatistics 1" write statistics on the
+ bidirectional use of connections to disk every 24 hours.
+ - Add a GeoIP file digest to the extra-info descriptor. Implements
+ enhancement 1883.
+ - The NodeFamily option -- which let you declare that you want to
+ consider nodes to be part of a family whether they list themselves
+ that way or not -- now allows IP address ranges and country codes.
+ - Add a new 'Heartbeat' log message type to periodically log a message
+ describing Tor's status at level Notice. This feature is meant for
+ operators who log at notice, and want to make sure that their Tor
+ server is still working. Implementation by George Kadianakis.
+
+ o Minor bugfixes (on 0.2.2.25-alpha):
+ - When loading the microdesc journal, remember its current size.
+ In 0.2.2, this helps prevent the microdesc journal from growing
+ without limit on authorities (who are the only ones to use it in
+ 0.2.2). Fixes a part of bug 2230; bugfix on 0.2.2.6-alpha.
+ Fix posted by "cypherpunks."
+ - The microdesc journal is supposed to get rebuilt only if it is
+ at least _half_ the length of the store, not _twice_ the length
+ of the store. Bugfix on 0.2.2.6-alpha; fixes part of bug 2230.
+ - If as an authority we fail to compute the identity digest of a v3
+ legacy keypair, warn, and don't use a buffer-full of junk instead.
+ Bugfix on 0.2.1.1-alpha; fixes bug 3106.
+ - Authorities now clean their microdesc cache periodically and when
+ reading from disk initially, not only when adding new descriptors.
+ This prevents a bug where we could lose microdescriptors. Bugfix
+ on 0.2.2.6-alpha.
+
+ o Minor features (controller):
+ - Add a new SIGNAL event to the controller interface so that
+ controllers can be notified when Tor handles a signal. Resolves
+ issue 1955. Patch by John Brooks.
+ - Add a new GETINFO option to get total bytes read and written. Patch
+ from pipe, revised by atagar. Resolves ticket 2345.
+ - Implement some GETINFO controller fields to provide information about
+ the Tor process's pid, euid, username, and resource limits.
+
+ o Build changes:
+ - Our build system requires automake 1.6 or later to create the
+ Makefile.in files. Previously, you could have used 1.4.
+ This only affects developers and people building Tor from git;
+ people who build Tor from the source distribution without changing
+ the Makefile.am files should be fine.
+ - Our autogen.sh script uses autoreconf to launch autoconf, automake, and
+ so on. This is more robust against some of the failure modes
+ associated with running the autotools pieces on their own.
+
+ o Minor packaging issues:
+ - On OpenSUSE, create the /var/run/tor directory on startup if it is not
+ already created. Patch from Andreas Stieger. Fixes bug 2573.
+
+ o Code simplifications and refactoring:
+ - A major revision to our internal node-selecting and listing logic.
+ Tor already had at least two major ways to look at the question of
+ "which Tor servers do we know about": a list of router descriptors,
+ and a list of entries in the current consensus. With
+ microdescriptors, we're adding a third. Having so many systems
+ without an abstraction layer over them was hurting the codebase.
+ Now, we have a new "node_t" abstraction that presents a consistent
+ interface to a client's view of a Tor node, and holds (nearly) all
+ of the mutable state formerly in routerinfo_t and routerstatus_t.
+ - The helper programs tor-gencert, tor-resolve, and tor-checkkey
+ no longer link against Libevent: they never used it, but
+ our library structure used to force them to link it.
+
+ o Removed features:
+ - Remove some old code to work around even older versions of Tor that
+ used forked processes to handle DNS requests. Such versions of Tor
+ are no longer in use as servers.
+
+ o Documentation fixes:
+ - Correct a broken faq link in the INSTALL file. Fixes bug 2307.
+ - Add missing documentation for the authority-related torrc options
+ RephistTrackTime, BridgePassword, and V3AuthUseLegacyKey. Resolves
+ issue 2379.
+
+
+Changes in version 0.2.2.25-alpha - 2011-04-29
+ Tor 0.2.2.25-alpha fixes many bugs: hidden service clients are more
+ robust, routers no longer overreport their bandwidth, Win7 should crash
+ a little less, and NEWNYM (as used by Vidalia's "new identity" button)
+ now prevents hidden service-related activity from being linkable. It
+ provides more information to Vidalia so you can see if your bridge is
+ working. Also, 0.2.2.25-alpha revamps the Entry/Exit/ExcludeNodes and
+ StrictNodes configuration options to make them more reliable, more
+ understandable, and more regularly applied. If you use those options,
+ please see the revised documentation for them in the manual page.
+
+ o Major bugfixes:
+ - Relays were publishing grossly inflated bandwidth values because
+ they were writing their state files wrong--now they write the
+ correct value. Also, resume reading bandwidth history from the
+ state file correctly. Fixes bug 2704; bugfix on 0.2.2.23-alpha.
+ - Improve hidden service robustness: When we find that we have
+ extended a hidden service's introduction circuit to a relay not
+ listed as an introduction point in the HS descriptor we currently
+ have, retry with an introduction point from the current
+ descriptor. Previously we would just give up. Fixes bugs 1024 and
+ 1930; bugfix on 0.2.0.10-alpha.
+ - Clients now stop trying to use an exit node associated with a given
+ destination by TrackHostExits if they fail to reach that exit node.
+ Fixes bug 2999. Bugfix on 0.2.0.20-rc.
+ - Fix crash bug on platforms where gmtime and localtime can return
+ NULL. Windows 7 users were running into this one. Fixes part of bug
+ 2077. Bugfix on all versions of Tor. Found by boboper.
+
+ o Security and stability fixes:
+ - Don't double-free a parsable, but invalid, microdescriptor, even if
+ it is followed in the blob we're parsing by an unparsable
+ microdescriptor. Fixes an issue reported in a comment on bug 2954.
+ Bugfix on 0.2.2.6-alpha; fix by "cypherpunks".
+ - If the Nickname configuration option isn't given, Tor would pick a
+ nickname based on the local hostname as the nickname for a relay.
+ Because nicknames are not very important in today's Tor and the
+ "Unnamed" nickname has been implemented, this is now problematic
+ behavior: It leaks information about the hostname without being
+ useful at all. Fixes bug 2979; bugfix on 0.1.2.2-alpha, which
+ introduced the Unnamed nickname. Reported by tagnaq.
+ - Fix an uncommon assertion failure when running with DNSPort under
+ heavy load. Fixes bug 2933; bugfix on 0.2.0.1-alpha.
+ - Avoid linkability based on cached hidden service descriptors: forget
+ all hidden service descriptors cached as a client when processing a
+ SIGNAL NEWNYM command. Fixes bug 3000; bugfix on 0.0.6.
+
+ o Major features:
+ - Export GeoIP information on bridge usage to controllers even if we
+ have not yet been running for 24 hours. Now Vidalia bridge operators
+ can get more accurate and immediate feedback about their
+ contributions to the network.
+
+ o Major features and bugfixes (node selection):
+ - Revise and reconcile the meaning of the ExitNodes, EntryNodes,
+ ExcludeEntryNodes, ExcludeExitNodes, ExcludeNodes, and StrictNodes
+ options. Previously, we had been ambiguous in describing what
+ counted as an "exit" node, and what operations exactly "StrictNodes
+ 0" would permit. This created confusion when people saw nodes built
+ through unexpected circuits, and made it hard to tell real bugs from
+ surprises. Now the intended behavior is:
+ . "Exit", in the context of ExitNodes and ExcludeExitNodes, means
+ a node that delivers user traffic outside the Tor network.
+ . "Entry", in the context of EntryNodes, means a node used as the
+ first hop of a multihop circuit. It doesn't include direct
+ connections to directory servers.
+ . "ExcludeNodes" applies to all nodes.
+ . "StrictNodes" changes the behavior of ExcludeNodes only. When
+ StrictNodes is set, Tor should avoid all nodes listed in
+ ExcludeNodes, even when it will make user requests fail. When
+ StrictNodes is *not* set, then Tor should follow ExcludeNodes
+ whenever it can, except when it must use an excluded node to
+ perform self-tests, connect to a hidden service, provide a
+ hidden service, fulfill a .exit request, upload directory
+ information, or fetch directory information.
+ Collectively, the changes to implement the behavior fix bug 1090.
+ - ExcludeNodes now takes precedence over EntryNodes and ExitNodes: if
+ a node is listed in both, it's treated as excluded.
+ - ExcludeNodes now applies to directory nodes -- as a preference if
+ StrictNodes is 0, or an absolute requirement if StrictNodes is 1.
+ Don't exclude all the directory authorities and set StrictNodes to 1
+ unless you really want your Tor to break.
+ - ExcludeNodes and ExcludeExitNodes now override exit enclaving.
+ - ExcludeExitNodes now overrides .exit requests.
+ - We don't use bridges listed in ExcludeNodes.
+ - When StrictNodes is 1:
+ . We now apply ExcludeNodes to hidden service introduction points
+ and to rendezvous points selected by hidden service users. This
+ can make your hidden service less reliable: use it with caution!
+ . If we have used ExcludeNodes on ourself, do not try relay
+ reachability self-tests.
+ . If we have excluded all the directory authorities, we will not
+ even try to upload our descriptor if we're a relay.
+ . Do not honor .exit requests to an excluded node.
+ - Remove a misfeature that caused us to ignore the Fast/Stable flags
+ when ExitNodes is set. Bugfix on 0.2.2.7-alpha.
+ - When the set of permitted nodes changes, we now remove any mappings
+ introduced via TrackExitHosts to now-excluded nodes. Bugfix on
+ 0.1.0.1-rc.
+ - We never cannibalize a circuit that had excluded nodes on it, even
+ if StrictNodes is 0. Bugfix on 0.1.0.1-rc.
+ - Revert a change where we would be laxer about attaching streams to
+ circuits than when building the circuits. This was meant to prevent
+ a set of bugs where streams were never attachable, but our improved
+ code here should make this unnecessary. Bugfix on 0.2.2.7-alpha.
+ - Keep track of how many times we launch a new circuit to handle a
+ given stream. Too many launches could indicate an inconsistency
+ between our "launch a circuit to handle this stream" logic and our
+ "attach this stream to one of the available circuits" logic.
+ - Improve log messages related to excluded nodes.
+
+ o Minor bugfixes:
+ - Fix a spurious warning when moving from a short month to a long
+ month on relays with month-based BandwidthAccounting. Bugfix on
+ 0.2.2.17-alpha; fixes bug 3020.
+ - When a client finds that an origin circuit has run out of 16-bit
+ stream IDs, we now mark it as unusable for new streams. Previously,
+ we would try to close the entire circuit. Bugfix on 0.0.6.
+ - Add a forgotten cast that caused a compile warning on OS X 10.6.
+ Bugfix on 0.2.2.24-alpha.
+ - Be more careful about reporting the correct error from a failed
+ connect() system call. Under some circumstances, it was possible to
+ look at an incorrect value for errno when sending the end reason.
+ Bugfix on 0.1.0.1-rc.
+ - Correctly handle an "impossible" overflow cases in connection byte
+ counting, where we write or read more than 4GB on an edge connection
+ in a single second. Bugfix on 0.1.2.8-beta.
+ - Correct the warning displayed when a rendezvous descriptor exceeds
+ the maximum size. Fixes bug 2750; bugfix on 0.2.1.5-alpha. Found by
+ John Brooks.
+ - Clients and hidden services now use HSDir-flagged relays for hidden
+ service descriptor downloads and uploads even if the relays have no
+ DirPort set and the client has disabled TunnelDirConns. This will
+ eventually allow us to give the HSDir flag to relays with no
+ DirPort. Fixes bug 2722; bugfix on 0.2.1.6-alpha.
+ - Downgrade "no current certificates known for authority" message from
+ Notice to Info. Fixes bug 2899; bugfix on 0.2.0.10-alpha.
+ - Make the SIGNAL DUMP control-port command work on FreeBSD. Fixes bug
+ 2917. Bugfix on 0.1.1.1-alpha.
+ - Only limit the lengths of single HS descriptors, even when multiple
+ HS descriptors are published to an HSDir relay in a single POST
+ operation. Fixes bug 2948; bugfix on 0.2.1.5-alpha. Found by hsdir.
+ - Write the current time into the LastWritten line in our state file,
+ rather than the time from the previous write attempt. Also, stop
+ trying to use a time of -1 in our log statements. Fixes bug 3039;
+ bugfix on 0.2.2.14-alpha.
+ - Be more consistent in our treatment of file system paths. "~" should
+ get expanded to the user's home directory in the Log config option.
+ Fixes bug 2971; bugfix on 0.2.0.1-alpha, which introduced the
+ feature for the -f and --DataDirectory options.
+
+ o Minor features:
+ - Make sure every relay writes a state file at least every 12 hours.
+ Previously, a relay could go for weeks without writing its state
+ file, and on a crash could lose its bandwidth history, capacity
+ estimates, client country statistics, and so on. Addresses bug 3012.
+ - Send END_STREAM_REASON_NOROUTE in response to EHOSTUNREACH errors.
+ Clients before 0.2.1.27 didn't handle NOROUTE correctly, but such
+ clients are already deprecated because of security bugs.
+ - Don't allow v0 hidden service authorities to act as clients.
+ Required by fix for bug 3000.
+ - Ignore SIGNAL NEWNYM commands on relay-only Tor instances. Required
+ by fix for bug 3000.
+ - Ensure that no empty [dirreq-](read|write)-history lines are added
+ to an extrainfo document. Implements ticket 2497.
+
+ o Code simplification and refactoring:
+ - Remove workaround code to handle directory responses from servers
+ that had bug 539 (they would send HTTP status 503 responses _and_
+ send a body too). Since only server versions before
+ 0.2.0.16-alpha/0.1.2.19 were affected, there is no longer reason to
+ keep the workaround in place.
+ - Remove the old 'fuzzy time' logic. It was supposed to be used for
+ handling calculations where we have a known amount of clock skew and
+ an allowed amount of unknown skew. But we only used it in three
+ places, and we never adjusted the known/unknown skew values. This is
+ still something we might want to do someday, but if we do, we'll
+ want to do it differently.
+ - Avoid signed/unsigned comparisons by making SIZE_T_CEILING unsigned.
+ None of the cases where we did this before were wrong, but by making
+ this change we avoid warnings. Fixes bug 2475; bugfix on 0.2.1.28.
+ - Use GetTempDir to find the proper temporary directory location on
+ Windows when generating temporary files for the unit tests. Patch by
+ Gisle Vanem.
+
+
+Changes in version 0.2.2.24-alpha - 2011-04-08
+ Tor 0.2.2.24-alpha fixes a variety of bugs, including a big bug that
+ prevented Tor clients from effectively using "multihomed" bridges,
+ that is, bridges that listen on multiple ports or IP addresses so users
+ can continue to use some of their addresses even if others get blocked.
+
+ o Major bugfixes:
+ - Fix a bug where bridge users who configure the non-canonical
+ address of a bridge automatically switch to its canonical
+ address. If a bridge listens at more than one address, it should be
+ able to advertise those addresses independently and any non-blocked
+ addresses should continue to work. Bugfix on Tor 0.2.0.x. Fixes
+ bug 2510.
+ - If you configured Tor to use bridge A, and then quit and
+ configured Tor to use bridge B instead, it would happily continue
+ to use bridge A if it's still reachable. While this behavior is
+ a feature if your goal is connectivity, in some scenarios it's a
+ dangerous bug. Bugfix on Tor 0.2.0.1-alpha; fixes bug 2511.
+ - Directory authorities now use data collected from their own
+ uptime observations when choosing whether to assign the HSDir flag
+ to relays, instead of trusting the uptime value the relay reports in
+ its descriptor. This change helps prevent an attack where a small
+ set of nodes with frequently-changing identity keys can blackhole
+ a hidden service. (Only authorities need upgrade; others will be
+ fine once they do.) Bugfix on 0.2.0.10-alpha; fixes bug 2709.
+
+ o Minor bugfixes:
+ - When we restart our relay, we might get a successful connection
+ from the outside before we've started our reachability tests,
+ triggering a warning: "ORPort found reachable, but I have no
+ routerinfo yet. Failing to inform controller of success." This
+ bug was harmless unless Tor is running under a controller
+ like Vidalia, in which case the controller would never get a
+ REACHABILITY_SUCCEEDED status event. Bugfix on 0.1.2.6-alpha;
+ fixes bug 1172.
+ - Make directory authorities more accurate at recording when
+ relays that have failed several reachability tests became
+ unreachable, so we can provide more accuracy at assigning Stable,
+ Guard, HSDir, etc flags. Bugfix on 0.2.0.6-alpha. Resolves bug 2716.
+ - Fix an issue that prevented static linking of libevent on
+ some platforms (notably Linux). Fixes bug 2698; bugfix on
+ versions 0.2.1.23/0.2.2.8-alpha (the versions introducing
+ the --with-static-libevent configure option).
+ - We now ask the other side of a stream (the client or the exit)
+ for more data on that stream when the amount of queued data on
+ that stream dips low enough. Previously, we wouldn't ask the
+ other side for more data until either it sent us more data (which
+ it wasn't supposed to do if it had exhausted its window!) or we
+ had completely flushed all our queued data. This flow control fix
+ should improve throughput. Fixes bug 2756; bugfix on the earliest
+ released versions of Tor (svn commit r152).
+ - Avoid a double-mark-for-free warning when failing to attach a
+ transparent proxy connection. (We thought we had fixed this in
+ 0.2.2.23-alpha, but it turns out our fix was checking the wrong
+ connection.) Fixes bug 2757; bugfix on 0.1.2.1-alpha (the original
+ bug) and 0.2.2.23-alpha (the incorrect fix).
+ - When warning about missing zlib development packages during compile,
+ give the correct package names. Bugfix on 0.2.0.1-alpha.
+
+ o Minor features:
+ - Directory authorities now log the source of a rejected POSTed v3
+ networkstatus vote.
+ - Make compilation with clang possible when using
+ --enable-gcc-warnings by removing two warning options that clang
+ hasn't implemented yet and by fixing a few warnings. Implements
+ ticket 2696.
+ - When expiring circuits, use microsecond timers rather than
+ one-second timers. This can avoid an unpleasant situation where a
+ circuit is launched near the end of one second and expired right
+ near the beginning of the next, and prevent fluctuations in circuit
+ timeout values.
+ - Use computed circuit-build timeouts to decide when to launch
+ parallel introduction circuits for hidden services. (Previously,
+ we would retry after 15 seconds.)
+ - Update to the April 1 2011 Maxmind GeoLite Country database.
+
+ o Packaging fixes:
+ - Create the /var/run/tor directory on startup on OpenSUSE if it is
+ not already created. Patch from Andreas Stieger. Fixes bug 2573.
+
+ o Documentation changes:
+ - Modernize the doxygen configuration file slightly. Fixes bug 2707.
+ - Resolve all doxygen warnings except those for missing documentation.
+ Fixes bug 2705.
+ - Add doxygen documentation for more functions, fields, and types.
+
+
+Changes in version 0.2.2.23-alpha - 2011-03-08
+ Tor 0.2.2.23-alpha lets relays record their bandwidth history so when
+ they restart they don't lose their bandwidth capacity estimate. This
+ release also fixes a diverse set of user-facing bugs, ranging from
+ relays overrunning their rate limiting to clients falsely warning about
+ clock skew to bridge descriptor leaks by our bridge directory authority.
+
+ o Major bugfixes:
+ - Stop sending a CLOCK_SKEW controller status event whenever
+ we fetch directory information from a relay that has a wrong clock.
+ Instead, only inform the controller when it's a trusted authority
+ that claims our clock is wrong. Bugfix on 0.1.2.6-alpha; fixes
+ the rest of bug 1074.
+ - Fix an assert in parsing router descriptors containing IPv6
+ addresses. This one took down the directory authorities when
+ somebody tried some experimental code. Bugfix on 0.2.1.3-alpha.
+ - Make the bridge directory authority refuse to answer directory
+ requests for "all" descriptors. It used to include bridge
+ descriptors in its answer, which was a major information leak.
+ Found by "piebeer". Bugfix on 0.2.0.3-alpha.
+ - If relays set RelayBandwidthBurst but not RelayBandwidthRate,
+ Tor would ignore their RelayBandwidthBurst setting,
+ potentially using more bandwidth than expected. Bugfix on
+ 0.2.0.1-alpha. Reported by Paul Wouters. Fixes bug 2470.
+ - Ignore and warn if the user mistakenly sets "PublishServerDescriptor
+ hidserv" in her torrc. The 'hidserv' argument never controlled
+ publication of hidden service descriptors. Bugfix on 0.2.0.1-alpha.
+
+ o Major features:
+ - Relays now save observed peak bandwidth throughput rates to their
+ state file (along with total usage, which was already saved)
+ so that they can determine their correct estimated bandwidth on
+ restart. Resolves bug 1863, where Tor relays would reset their
+ estimated bandwidth to 0 after restarting.
+ - Directory authorities now take changes in router IP address and
+ ORPort into account when determining router stability. Previously,
+ if a router changed its IP or ORPort, the authorities would not
+ treat it as having any downtime for the purposes of stability
+ calculation, whereas clients would experience downtime since the
+ change could take a while to propagate to them. Resolves issue 1035.
+ - Enable Address Space Layout Randomization (ASLR) and Data Execution
+ Prevention (DEP) by default on Windows to make it harder for
+ attackers to exploit vulnerabilities. Patch from John Brooks.
+
+ o Minor bugfixes (on 0.2.1.x and earlier):
+ - Fix a rare crash bug that could occur when a client was configured
+ with a large number of bridges. Fixes bug 2629; bugfix on
+ 0.2.1.2-alpha. Bugfix by trac user "shitlei".
+ - Avoid a double mark-for-free warning when failing to attach a
+ transparent proxy connection. Bugfix on 0.1.2.1-alpha. Fixes
+ bug 2279.
+ - Correctly detect failure to allocate an OpenSSL BIO. Fixes bug 2378;
+ found by "cypherpunks". This bug was introduced before the first
+ Tor release, in svn commit r110.
+ - Country codes aren't supported in EntryNodes until 0.2.3.x, so
+ don't mention them in the manpage. Fixes bug 2450; issue
+ spotted by keb and G-Lo.
+ - Fix a bug in bandwidth history state parsing that could have been
+ triggered if a future version of Tor ever changed the timing
+ granularity at which bandwidth history is measured. Bugfix on
+ Tor 0.1.1.11-alpha.
+ - When a relay decides that its DNS is too broken for it to serve
+ as an exit server, it advertised itself as a non-exit, but
+ continued to act as an exit. This could create accidental
+ partitioning opportunities for users. Instead, if a relay is
+ going to advertise reject *:* as its exit policy, it should
+ really act with exit policy "reject *:*". Fixes bug 2366.
+ Bugfix on Tor 0.1.2.5-alpha. Bugfix by user "postman" on trac.
+ - In the special case where you configure a public exit relay as your
+ bridge, Tor would be willing to use that exit relay as the last
+ hop in your circuit as well. Now we fail that circuit instead.
+ Bugfix on 0.2.0.12-alpha. Fixes bug 2403. Reported by "piebeer".
+ - Fix a bug with our locking implementation on Windows that couldn't
+ correctly detect when a file was already locked. Fixes bug 2504,
+ bugfix on 0.2.1.6-alpha.
+ - Fix IPv6-related connect() failures on some platforms (BSD, OS X).
+ Bugfix on 0.2.0.3-alpha; fixes first part of bug 2660. Patch by
+ "piebeer".
+ - Set target port in get_interface_address6() correctly. Bugfix
+ on 0.1.1.4-alpha and 0.2.0.3-alpha; fixes second part of bug 2660.
+ - Directory authorities are now more robust to hops back in time
+ when calculating router stability. Previously, if a run of uptime
+ or downtime appeared to be negative, the calculation could give
+ incorrect results. Bugfix on 0.2.0.6-alpha; noticed when fixing
+ bug 1035.
+ - Fix an assert that got triggered when using the TestingTorNetwork
+ configuration option and then issuing a GETINFO config-text control
+ command. Fixes bug 2250; bugfix on 0.2.1.2-alpha.
+
+ o Minor bugfixes (on 0.2.2.x):
+ - Clients should not weight BadExit nodes as Exits in their node
+ selection. Similarly, directory authorities should not count BadExit
+ bandwidth as Exit bandwidth when computing bandwidth-weights.
+ Bugfix on 0.2.2.10-alpha; fixes bug 2203.
+ - Correctly clear our dir_read/dir_write history when there is an
+ error parsing any bw history value from the state file. Bugfix on
+ Tor 0.2.2.15-alpha.
+ - Resolve a bug in verifying signatures of directory objects
+ with digests longer than SHA1. Bugfix on 0.2.2.20-alpha.
+ Fixes bug 2409. Found by "piebeer".
+ - Bridge authorities no longer crash on SIGHUP when they try to
+ publish their relay descriptor to themselves. Fixes bug 2572. Bugfix
+ on 0.2.2.22-alpha.
+
+ o Minor features:
+ - Log less aggressively about circuit timeout changes, and improve
+ some other circuit timeout messages. Resolves bug 2004.
+ - Log a little more clearly about the times at which we're no longer
+ accepting new connections. Resolves bug 2181.
+ - Reject attempts at the client side to open connections to private
+ IP addresses (like 127.0.0.1, 10.0.0.1, and so on) with
+ a randomly chosen exit node. Attempts to do so are always
+ ill-defined, generally prevented by exit policies, and usually
+ in error. This will also help to detect loops in transparent
+ proxy configurations. You can disable this feature by setting
+ "ClientRejectInternalAddresses 0" in your torrc.
+ - Always treat failure to allocate an RSA key as an unrecoverable
+ allocation error.
+ - Update to the March 1 2011 Maxmind GeoLite Country database.
+
+ o Minor features (log subsystem):
+ - Add documentation for configuring logging at different severities in
+ different log domains. We've had this feature since 0.2.1.1-alpha,
+ but for some reason it never made it into the manpage. Fixes
+ bug 2215.
+ - Make it simpler to specify "All log domains except for A and B".
+ Previously you needed to say "[*,~A,~B]". Now you can just say
+ "[~A,~B]".
+ - Add a "LogMessageDomains 1" option to include the domains of log
+ messages along with the messages. Without this, there's no way
+ to use log domains without reading the source or doing a lot
+ of guessing.
+
+ o Packaging changes:
+ - Stop shipping the Tor specs files and development proposal documents
+ in the tarball. They are now in a separate git repository at
+ git://git.torproject.org/torspec.git
+
+
+Changes in version 0.2.1.30 - 2011-02-23
+ Tor 0.2.1.30 fixes a variety of less critical bugs. The main other
+ change is a slight tweak to Tor's TLS handshake that makes relays
+ and bridges that run this new version reachable from Iran again.
+ We don't expect this tweak will win the arms race long-term, but it
+ buys us time until we roll out a better solution.
+
+ o Major bugfixes:
+ - Stop sending a CLOCK_SKEW controller status event whenever
+ we fetch directory information from a relay that has a wrong clock.
+ Instead, only inform the controller when it's a trusted authority
+ that claims our clock is wrong. Bugfix on 0.1.2.6-alpha; fixes
+ the rest of bug 1074.
+ - Fix a bounds-checking error that could allow an attacker to
+ remotely crash a directory authority. Bugfix on 0.2.1.5-alpha.
+ Found by "piebeer".
+ - If relays set RelayBandwidthBurst but not RelayBandwidthRate,
+ Tor would ignore their RelayBandwidthBurst setting,
+ potentially using more bandwidth than expected. Bugfix on
+ 0.2.0.1-alpha. Reported by Paul Wouters. Fixes bug 2470.
+ - Ignore and warn if the user mistakenly sets "PublishServerDescriptor
+ hidserv" in her torrc. The 'hidserv' argument never controlled
+ publication of hidden service descriptors. Bugfix on 0.2.0.1-alpha.
+
+ o Minor features:
+ - Adjust our TLS Diffie-Hellman parameters to match those used by
+ Apache's mod_ssl.
+ - Update to the February 1 2011 Maxmind GeoLite Country database.
+
+ o Minor bugfixes:
+ - Check for and reject overly long directory certificates and
+ directory tokens before they have a chance to hit any assertions.
+ Bugfix on 0.2.1.28. Found by "doorss".
+ - Bring the logic that gathers routerinfos and assesses the
+ acceptability of circuits into line. This prevents a Tor OP from
+ getting locked in a cycle of choosing its local OR as an exit for a
+ path (due to a .exit request) and then rejecting the circuit because
+ its OR is not listed yet. It also prevents Tor clients from using an
+ OR running in the same instance as an exit (due to a .exit request)
+ if the OR does not meet the same requirements expected of an OR
+ running elsewhere. Fixes bug 1859; bugfix on 0.1.0.1-rc.
+
+ o Packaging changes:
+ - Stop shipping the Tor specs files and development proposal documents
+ in the tarball. They are now in a separate git repository at
+ git://git.torproject.org/torspec.git
+ - Do not include Git version tags as though they are SVN tags when
+ generating a tarball from inside a repository that has switched
+ between branches. Bugfix on 0.2.1.15-rc; fixes bug 2402.
+
+
+Changes in version 0.2.2.22-alpha - 2011-01-25
+ Tor 0.2.2.22-alpha fixes a few more less-critical security issues. The
+ main other change is a slight tweak to Tor's TLS handshake that makes
+ relays and bridges that run this new version reachable from Iran again.
+ We don't expect this tweak will win the arms race long-term, but it
+ will buy us a bit more time until we roll out a better solution.
+
+ o Major bugfixes:
+ - Fix a bounds-checking error that could allow an attacker to
+ remotely crash a directory authority. Bugfix on 0.2.1.5-alpha.
+ Found by "piebeer".
+ - Don't assert when changing from bridge to relay or vice versa
+ via the controller. The assert happened because we didn't properly
+ initialize our keys in this case. Bugfix on 0.2.2.18-alpha; fixes
+ bug 2433. Reported by bastik.
+
+ o Minor features:
+ - Adjust our TLS Diffie-Hellman parameters to match those used by
+ Apache's mod_ssl.
+ - Provide a log message stating which geoip file we're parsing
+ instead of just stating that we're parsing the geoip file.
+ Implements ticket 2432.
+
+ o Minor bugfixes:
+ - Check for and reject overly long directory certificates and
+ directory tokens before they have a chance to hit any assertions.
+ Bugfix on 0.2.1.28 / 0.2.2.20-alpha. Found by "doorss".
+
+
+Changes in version 0.2.2.21-alpha - 2011-01-15
+ Tor 0.2.2.21-alpha includes all the patches from Tor 0.2.1.29, which
+ continues our recent code security audit work. The main fix resolves
+ a remote heap overflow vulnerability that can allow remote code
+ execution (CVE-2011-0427). Other fixes address a variety of assert
+ and crash bugs, most of which we think are hard to exploit remotely.
+
+ o Major bugfixes (security), also included in 0.2.1.29:
+ - Fix a heap overflow bug where an adversary could cause heap
+ corruption. This bug probably allows remote code execution
+ attacks. Reported by "debuger". Fixes CVE-2011-0427. Bugfix on
+ 0.1.2.10-rc.
+ - Prevent a denial-of-service attack by disallowing any
+ zlib-compressed data whose compression factor is implausibly
+ high. Fixes part of bug 2324; reported by "doorss".
+ - Zero out a few more keys in memory before freeing them. Fixes
+ bug 2384 and part of bug 2385. These key instances found by
+ "cypherpunks", based on Andrew Case's report about being able
+ to find sensitive data in Tor's memory space if you have enough
+ permissions. Bugfix on 0.0.2pre9.
+
+ o Major bugfixes (crashes), also included in 0.2.1.29:
+ - Prevent calls to Libevent from inside Libevent log handlers.
+ This had potential to cause a nasty set of crashes, especially
+ if running Libevent with debug logging enabled, and running
+ Tor with a controller watching for low-severity log messages.
+ Bugfix on 0.1.0.2-rc. Fixes bug 2190.
+ - Add a check for SIZE_T_MAX to tor_realloc() to try to avoid
+ underflow errors there too. Fixes the other part of bug 2324.
+ - Fix a bug where we would assert if we ever had a
+ cached-descriptors.new file (or another file read directly into
+ memory) of exactly SIZE_T_CEILING bytes. Fixes bug 2326; bugfix
+ on 0.2.1.25. Found by doorss.
+ - Fix some potential asserts and parsing issues with grossly
+ malformed router caches. Fixes bug 2352; bugfix on Tor 0.2.1.27.
+ Found by doorss.
+
+ o Minor bugfixes (other), also included in 0.2.1.29:
+ - Fix a bug with handling misformed replies to reverse DNS lookup
+ requests in DNSPort. Bugfix on Tor 0.2.0.1-alpha. Related to a
+ bug reported by doorss.
+ - Fix compilation on mingw when a pthreads compatibility library
+ has been installed. (We don't want to use it, so we shouldn't
+ be including pthread.h.) Fixes bug 2313; bugfix on 0.1.0.1-rc.
+ - Fix a bug where we would declare that we had run out of virtual
+ addresses when the address space was only half-exhausted. Bugfix
+ on 0.1.2.1-alpha.
+ - Correctly handle the case where AutomapHostsOnResolve is set but
+ no virtual addresses are available. Fixes bug 2328; bugfix on
+ 0.1.2.1-alpha. Bug found by doorss.
+ - Correctly handle wrapping around when we run out of virtual
+ address space. Found by cypherpunks; bugfix on 0.2.0.5-alpha.
+
+ o Minor features, also included in 0.2.1.29:
+ - Update to the January 1 2011 Maxmind GeoLite Country database.
+ - Introduce output size checks on all of our decryption functions.
+
+ o Build changes, also included in 0.2.1.29:
+ - Tor does not build packages correctly with Automake 1.6 and earlier;
+ added a check to Makefile.am to make sure that we're building with
+ Automake 1.7 or later.
+ - The 0.2.1.28 tarball was missing src/common/OpenBSD_malloc_Linux.c
+ because we built it with a too-old version of automake. Thus that
+ release broke ./configure --enable-openbsd-malloc, which is popular
+ among really fast exit relays on Linux.
+
+ o Major bugfixes, new in 0.2.2.21-alpha:
+ - Prevent crash/heap corruption when the cbtnummodes consensus
+ parameter is set to 0 or large values. Fixes bug 2317; bugfix
+ on 0.2.2.14-alpha.
+
+ o Major features, new in 0.2.2.21-alpha:
+ - Introduce minimum/maximum values that clients will believe
+ from the consensus. Now we'll have a better chance to avoid crashes
+ or worse when a consensus param has a weird value.
+
+ o Minor features, new in 0.2.2.21-alpha:
+ - Make sure to disable DirPort if running as a bridge. DirPorts aren't
+ used on bridges, and it makes bridge scanning somewhat easier.
+ - If writing the state file to disk fails, wait up to an hour before
+ retrying again, rather than trying again each second. Fixes bug
+ 2346; bugfix on Tor 0.1.1.3-alpha.
+ - Make Libevent log messages get delivered to controllers later,
+ and not from inside the Libevent log handler. This prevents unsafe
+ reentrant Libevent calls while still letting the log messages
+ get through.
+ - Detect platforms that brokenly use a signed size_t, and refuse to
+ build there. Found and analyzed by doorss and rransom.
+ - Fix a bunch of compile warnings revealed by mingw with gcc 4.5.
+ Resolves bug 2314.
+
+ o Minor bugfixes, new in 0.2.2.21-alpha:
+ - Handle SOCKS messages longer than 128 bytes long correctly, rather
+ than waiting forever for them to finish. Fixes bug 2330; bugfix
+ on 0.2.0.16-alpha. Found by doorss.
+ - Add assertions to check for overflow in arguments to
+ base32_encode() and base32_decode(); fix a signed-unsigned
+ comparison there too. These bugs are not actually reachable in Tor,
+ but it's good to prevent future errors too. Found by doorss.
+ - Correctly detect failures to create DNS requests when using Libevent
+ versions before v2. (Before Libevent 2, we used our own evdns
+ implementation. Its return values for Libevent's evdns_resolve_*()
+ functions are not consistent with those from Libevent.) Fixes bug
+ 2363; bugfix on 0.2.2.6-alpha. Found by "lodger".
+
+ o Documentation, new in 0.2.2.21-alpha:
+ - Document the default socks host and port (127.0.0.1:9050) for
+ tor-resolve.
+
+
+Changes in version 0.2.1.29 - 2011-01-15
+ Tor 0.2.1.29 continues our recent code security audit work. The main
+ fix resolves a remote heap overflow vulnerability that can allow remote
+ code execution. Other fixes address a variety of assert and crash bugs,
+ most of which we think are hard to exploit remotely.
+
+ o Major bugfixes (security):
+ - Fix a heap overflow bug where an adversary could cause heap
+ corruption. This bug probably allows remote code execution
+ attacks. Reported by "debuger". Fixes CVE-2011-0427. Bugfix on
+ 0.1.2.10-rc.
+ - Prevent a denial-of-service attack by disallowing any
+ zlib-compressed data whose compression factor is implausibly
+ high. Fixes part of bug 2324; reported by "doorss".
+ - Zero out a few more keys in memory before freeing them. Fixes
+ bug 2384 and part of bug 2385. These key instances found by
+ "cypherpunks", based on Andrew Case's report about being able
+ to find sensitive data in Tor's memory space if you have enough
+ permissions. Bugfix on 0.0.2pre9.
+
+ o Major bugfixes (crashes):
+ - Prevent calls to Libevent from inside Libevent log handlers.
+ This had potential to cause a nasty set of crashes, especially
+ if running Libevent with debug logging enabled, and running
+ Tor with a controller watching for low-severity log messages.
+ Bugfix on 0.1.0.2-rc. Fixes bug 2190.
+ - Add a check for SIZE_T_MAX to tor_realloc() to try to avoid
+ underflow errors there too. Fixes the other part of bug 2324.
+ - Fix a bug where we would assert if we ever had a
+ cached-descriptors.new file (or another file read directly into
+ memory) of exactly SIZE_T_CEILING bytes. Fixes bug 2326; bugfix
+ on 0.2.1.25. Found by doorss.
+ - Fix some potential asserts and parsing issues with grossly
+ malformed router caches. Fixes bug 2352; bugfix on Tor 0.2.1.27.
+ Found by doorss.
+
+ o Minor bugfixes (other):
+ - Fix a bug with handling misformed replies to reverse DNS lookup
+ requests in DNSPort. Bugfix on Tor 0.2.0.1-alpha. Related to a
+ bug reported by doorss.
+ - Fix compilation on mingw when a pthreads compatibility library
+ has been installed. (We don't want to use it, so we shouldn't
+ be including pthread.h.) Fixes bug 2313; bugfix on 0.1.0.1-rc.
+ - Fix a bug where we would declare that we had run out of virtual
+ addresses when the address space was only half-exhausted. Bugfix
+ on 0.1.2.1-alpha.
+ - Correctly handle the case where AutomapHostsOnResolve is set but
+ no virtual addresses are available. Fixes bug 2328; bugfix on
+ 0.1.2.1-alpha. Bug found by doorss.
+ - Correctly handle wrapping around to when we run out of virtual
+ address space. Found by cypherpunks, bugfix on 0.2.0.5-alpha.
+ - The 0.2.1.28 tarball was missing src/common/OpenBSD_malloc_Linux.c
+ because we built it with a too-old version of automake. Thus that
+ release broke ./configure --enable-openbsd-malloc, which is popular
+ among really fast exit relays on Linux.
+
+ o Minor features:
+ - Update to the January 1 2011 Maxmind GeoLite Country database.
+ - Introduce output size checks on all of our decryption functions.
+
+ o Build changes:
+ - Tor does not build packages correctly with Automake 1.6 and earlier;
+ added a check to Makefile.am to make sure that we're building with
+ Automake 1.7 or later.
+
+
+Changes in version 0.2.2.20-alpha - 2010-12-17
+ Tor 0.2.2.20-alpha does some code cleanup to reduce the risk of remotely
+ exploitable bugs. We also fix a variety of other significant bugs,
+ change the IP address for one of our directory authorities, and update
+ the minimum version that Tor relays must run to join the network.
+
+ o Major bugfixes:
+ - Fix a remotely exploitable bug that could be used to crash instances
+ of Tor remotely by overflowing on the heap. Remote-code execution
+ hasn't been confirmed, but can't be ruled out. Everyone should
+ upgrade. Bugfix on the 0.1.1 series and later.
+ - Fix a bug that could break accounting on 64-bit systems with large
+ time_t values, making them hibernate for impossibly long intervals.
+ Fixes bug 2146. Bugfix on 0.0.9pre6; fix by boboper.
+ - Fix a logic error in directory_fetches_from_authorities() that
+ would cause all _non_-exits refusing single-hop-like circuits
+ to fetch from authorities, when we wanted to have _exits_ fetch
+ from authorities. Fixes more of 2097. Bugfix on 0.2.2.16-alpha;
+ fix by boboper.
+ - Fix a stream fairness bug that would cause newer streams on a given
+ circuit to get preference when reading bytes from the origin or
+ destination. Fixes bug 2210. Fix by Mashael AlSabah. This bug was
+ introduced before the first Tor release, in svn revision r152.
+
+ o Directory authority changes:
+ - Change IP address and ports for gabelmoo (v3 directory authority).
+
+ o Minor bugfixes:
+ - Avoid crashes when AccountingMax is set on clients. Fixes bug 2235.
+ Bugfix on 0.2.2.18-alpha. Diagnosed by boboper.
+ - Fix an off-by-one error in calculating some controller command
+ argument lengths. Fortunately, this mistake is harmless since
+ the controller code does redundant NUL termination too. Found by
+ boboper. Bugfix on 0.1.1.1-alpha.
+ - Do not dereference NULL if a bridge fails to build its
+ extra-info descriptor. Found by an anonymous commenter on
+ Trac. Bugfix on 0.2.2.19-alpha.
+
+ o Minor features:
+ - Update to the December 1 2010 Maxmind GeoLite Country database.
+ - Directory authorities now reject relays running any versions of
+ Tor between 0.2.1.3-alpha and 0.2.1.18 inclusive; they have
+ known bugs that keep RELAY_EARLY cells from working on rendezvous
+ circuits. Followup to fix for bug 2081.
+ - Directory authorities now reject relays running any version of Tor
+ older than 0.2.0.26-rc. That version is the earliest that fetches
+ current directory information correctly. Fixes bug 2156.
+ - Report only the top 10 ports in exit-port stats in order not to
+ exceed the maximum extra-info descriptor length of 50 KB. Implements
+ task 2196.
+
+
+Changes in version 0.2.1.28 - 2010-12-17
+ Tor 0.2.1.28 does some code cleanup to reduce the risk of remotely
+ exploitable bugs. We also took this opportunity to change the IP address
+ for one of our directory authorities, and to update the geoip database
+ we ship.
+
+ o Major bugfixes:
+ - Fix a remotely exploitable bug that could be used to crash instances
+ of Tor remotely by overflowing on the heap. Remote-code execution
+ hasn't been confirmed, but can't be ruled out. Everyone should
+ upgrade. Bugfix on the 0.1.1 series and later.
+
+ o Directory authority changes:
+ - Change IP address and ports for gabelmoo (v3 directory authority).
+
+ o Minor features:
+ - Update to the December 1 2010 Maxmind GeoLite Country database.
+
+
+Changes in version 0.2.1.27 - 2010-11-23
+ Yet another OpenSSL security patch broke its compatibility with Tor:
+ Tor 0.2.1.27 makes relays work with openssl 0.9.8p and 1.0.0.b. We
+ also took this opportunity to fix several crash bugs, integrate a new
+ directory authority, and update the bundled GeoIP database.
+
+ o Major bugfixes:
+ - Resolve an incompatibility with OpenSSL 0.9.8p and OpenSSL 1.0.0b:
+ No longer set the tlsext_host_name extension on server SSL objects;
+ but continue to set it on client SSL objects. Our goal in setting
+ it was to imitate a browser, not a vhosting server. Fixes bug 2204;
+ bugfix on 0.2.1.1-alpha.
+ - Do not log messages to the controller while shrinking buffer
+ freelists. Doing so would sometimes make the controller connection
+ try to allocate a buffer chunk, which would mess up the internals
+ of the freelist and cause an assertion failure. Fixes bug 1125;
+ fixed by Robert Ransom. Bugfix on 0.2.0.16-alpha.
+ - Learn our external IP address when we're a relay or bridge, even if
+ we set PublishServerDescriptor to 0. Bugfix on 0.2.0.3-alpha,
+ where we introduced bridge relays that don't need to publish to
+ be useful. Fixes bug 2050.
+ - Do even more to reject (and not just ignore) annotations on
+ router descriptors received anywhere but from the cache. Previously
+ we would ignore such annotations at first, but cache them to disk
+ anyway. Bugfix on 0.2.0.8-alpha. Found by piebeer.
+ - When you're using bridges and your network goes away and your
+ bridges get marked as down, recover when you attempt a new socks
+ connection (if the network is back), rather than waiting up to an
+ hour to try fetching new descriptors for your bridges. Bugfix on
+ 0.2.0.3-alpha; fixes bug 1981.
+
+ o Major features:
+ - Move to the November 2010 Maxmind GeoLite country db (rather
+ than the June 2009 ip-to-country GeoIP db) for our statistics that
+ count how many users relays are seeing from each country. Now we'll
+ have more accurate data, especially for many African countries.
+
+ o New directory authorities:
+ - Set up maatuska (run by Linus Nordberg) as the eighth v3 directory
+ authority.
+
+ o Minor bugfixes:
+ - Fix an assertion failure that could occur in directory caches or
+ bridge users when using a very short voting interval on a testing
+ network. Diagnosed by Robert Hogan. Fixes bug 1141; bugfix on
+ 0.2.0.8-alpha.
+ - Enforce multiplicity rules when parsing annotations. Bugfix on
+ 0.2.0.8-alpha. Found by piebeer.
+ - Allow handshaking OR connections to take a full KeepalivePeriod
+ seconds to handshake. Previously, we would close them after
+ IDLE_OR_CONN_TIMEOUT (180) seconds, the same timeout as if they
+ were open. Bugfix on 0.2.1.26; fixes bug 1840. Thanks to mingw-san
+ for analysis help.
+ - When building with --enable-gcc-warnings on OpenBSD, disable
+ warnings in system headers. This makes --enable-gcc-warnings
+ pass on OpenBSD 4.8.
+
+ o Minor features:
+ - Exit nodes didn't recognize EHOSTUNREACH as a plausible error code,
+ and so sent back END_STREAM_REASON_MISC. Clients now recognize a new
+ stream ending reason for this case: END_STREAM_REASON_NOROUTE.
+ Servers can start sending this code when enough clients recognize
+ it. Bugfix on 0.1.0.1-rc; fixes part of bug 1793.
+ - Build correctly on mingw with more recent versions of OpenSSL 0.9.8.
+ Patch from mingw-san.
+
+ o Removed files:
+ - Remove the old debian/ directory from the main Tor distribution.
+ The official Tor-for-debian git repository lives at the URL
+ https://git.torproject.org/debian/tor.git
+ - Stop shipping the old doc/website/ directory in the tarball. We
+ changed the website format in late 2010, and what we shipped in
+ 0.2.1.26 really wasn't that useful anyway.
+
+
Changes in version 0.2.2.19-alpha - 2010-11-22
Yet another OpenSSL security patch broke its compatibility with Tor:
Tor 0.2.2.19-alpha makes relays work with OpenSSL 0.9.8p and 1.0.0.b.
@@ -543,9 +2372,10 @@ Changes in version 0.2.2.14-alpha - 2010-07-12
o Minor features:
- New config option "WarnUnsafeSocks 0" disables the warning that
- occurs whenever Tor receives only an IP address instead of a
- hostname. Setups that do DNS locally over Tor are fine, and we
- shouldn't spam the logs in that case.
+ occurs whenever Tor receives a socks handshake using a version of
+ the socks protocol that can only provide an IP address (rather
+ than a hostname). Setups that do DNS locally over Tor are fine,
+ and we shouldn't spam the logs in that case.
- Convert the HACKING file to asciidoc, and add a few new sections
to it, explaining how we use Git, how we make changelogs, and
what should go in a patch.
@@ -1307,8 +3137,9 @@ Changes in version 0.2.2.5-alpha - 2009-10-11
o Major bugfixes:
- Make the tarball compile again. Oops. Bugfix on 0.2.2.4-alpha.
- o New directory authorities:
- - Move dizum to an alternate IP address.
+ o Directory authorities:
+ - Temporarily (just for this release) move dizum to an alternate
+ IP address.
Changes in version 0.2.2.4-alpha - 2009-10-10
@@ -1478,8 +3309,8 @@ Changes in version 0.2.2.1-alpha - 2009-08-26
oldest-bug prize.
o New options for gathering stats safely:
- - Directories that set "DirReqStatistics 1" write statistics on
- directory request to disk every 24 hours. As compared to the
+ - Directory mirrors that set "DirReqStatistics 1" write statistics
+ about directory requests to disk every 24 hours. As compared to the
--enable-geoip-stats flag in 0.2.1.x, there are a few improvements:
1) stats are written to disk exactly every 24 hours; 2) estimated
shares of v2 and v3 requests are determined as mean values, not at
@@ -1517,9 +3348,9 @@ Changes in version 0.2.2.1-alpha - 2009-08-26
the git commit (when we're building from a git checkout).
o Minor bugfixes:
- - If any the v3 certs we download are unparseable, we should actually
- notice the failure so we don't retry indefinitely. Bugfix on
- 0.2.0.x; reported by "rotator".
+ - If any of the v3 certs we download are unparseable, we should
+ actually notice the failure so we don't retry indefinitely. Bugfix
+ on 0.2.0.x; reported by "rotator".
- If the cached cert file is unparseable, warn but don't exit.
- Fix possible segmentation fault on directory authorities. Bugfix on
0.2.1.14-rc.
@@ -4195,7 +6026,7 @@ Changes in version 0.2.0.10-alpha - 2007-11-10
- New --quiet command-line option to suppress the default console log.
Good in combination with --hash-password.
- Authorities send back an X-Descriptor-Not-New header in response to
- an accepted-but-discarded descriptor upload. Partially implements
+ an accepted-but-discarded descriptor upload. Partially implements
fix for bug 535.
- Make the log message for "tls error. breaking." more useful.
- Better log messages about certificate downloads, to attempt to
@@ -5359,7 +7190,7 @@ Changes in version 0.2.0.1-alpha - 2007-06-01
o Minor bugfixes (logging):
- When we hit an EOF on a log (probably because we're shutting down),
don't try to remove the log from the list: just mark it as
- unusable. (Bulletproofs against bug 222.)
+ unusable. (Bulletproofs against bug 222.)
o Minor bugfixes (other):
- In the exitlist script, only consider the most recently published
@@ -5369,7 +7200,7 @@ Changes in version 0.2.0.1-alpha - 2007-06-01
connections to that address. (Resolves bug 405.)
- Stop allowing hibernating servers to be "stable" or "fast".
- On Windows, we were preventing other processes from reading
- cached-routers while Tor was running. (Reported by janbar)
+ cached-routers while Tor was running. (Reported by janbar)
- Make the NodeFamilies config option work. (Reported by
lodger -- it has never actually worked, even though we added it
in Oct 2004.)
diff --git a/INSTALL b/INSTALL
index f05bb3907..ddb790b0b 100644
--- a/INSTALL
+++ b/INSTALL
@@ -3,7 +3,7 @@ Most users who realize that INSTALL files still exist should simply
follow the directions at
https://www.torproject.org/docs/tor-doc-unix
-If you got the source from Subversion, run "./autogen.sh", which will
+If you got the source from git, run "./autogen.sh", which will
run the various auto* programs. Then you can run ./configure, and
refer to the above instructions.
@@ -21,5 +21,32 @@ If it doesn't build for you:
For example, "setenv LD_LIBRARY_PATH /usr/athena/lib".
Lastly, check out
- http://wiki.noreply.org/noreply/TheOnionRouter/TorFAQ#ItDoesntWork
+ https://www.torproject.org/docs/faq#DoesntWork
+
+How to do static builds of tor:
+
+Tor supports linking each of the libraries it needs statically. Use the
+--enable-static-X ./configure option in conjunction with the --with-X-dir
+option for libevent, zlib, and openssl. For this to work sanely, libevent
+should be built with --disable-shared --enable-static --with-pic, and
+OpenSSL should be built with no-shared no-dso.
+
+If you need to build tor so that system libraries are also statically linked,
+use the --enable-static-tor ./configure option. This won't work on OS X
+unless you build the required crt0.o yourself. It is also incompatible with
+the --enable-gcc-hardening option.
+
+An example of how to build a mostly static tor:
+./configure --enable-static-libevent \
+ --enable-static-openssl \
+ --enable-static-zlib \
+ --with-libevent-dir=/tmp/static-tor/libevent-1.4.14b-stable \
+ --with-openssl-dir=/tmp/static-tor/openssl-0.9.8r/ \
+ --with-zlib-dir=/tmp/static-tor/zlib-1.2.5
+
+An example of how to build an entirely static tor:
+./configure --enable-static-tor \
+ --with-libevent-dir=/tmp/static-tor/libevent-1.4.14b-stable \
+ --with-openssl-dir=/tmp/static-tor/openssl-0.9.8r/ \
+ --with-zlib-dir=/tmp/static-tor/zlib-1.2.5
diff --git a/Makefile.am b/Makefile.am
index 5f1592618..cd0d8833c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,15 +3,23 @@
# Copyright (c) 2007-2011, The Tor Project, Inc.
# See LICENSE for licensing information
+# "foreign" means we don't follow GNU package layout standards
+# 1.7 means we require automake vesion 1.7
AUTOMAKE_OPTIONS = foreign 1.7
- # else it keeps trying to put COPYING back in
SUBDIRS = src doc contrib
DIST_SUBDIRS = src doc contrib
-EXTRA_DIST = INSTALL README LICENSE ChangeLog \
- ReleaseNotes tor.spec tor.spec.in
+EXTRA_DIST = \
+ ChangeLog \
+ INSTALL \
+ LICENSE \
+ Makefile.nmake \
+ README \
+ ReleaseNotes \
+ tor.spec \
+ tor.spec.in
#install-data-local:
# $(INSTALL) -m 755 -d $(LOCALSTATEDIR)/lib/tor
@@ -47,9 +55,13 @@ test: all
check-spaces:
./contrib/checkSpace.pl -C \
src/common/*.h \
- src/common/[^asO]*.c src/common/address.c \
- src/or/[^e]*.[ch] src/or/eventdns_tor.h \
- src/test/test*.[ch] src/tools/*.[ch]
+ src/common/[^asO]*.c \
+ src/common/address.c \
+ src/or/[^e]*.[ch] \
+ src/or/eventdns_tor.h \
+ src/test/test*.[ch] \
+ src/tools/*.[ch] \
+ src/tools/tor-fw-helper/*.[ch]
check-docs:
./contrib/checkOptionDocs.pl
diff --git a/Makefile.nmake b/Makefile.nmake
new file mode 100644
index 000000000..425f1ec26
--- /dev/null
+++ b/Makefile.nmake
@@ -0,0 +1,5 @@
+all:
+ cd src/common
+ $(MAKE) /F Makefile.nmake
+ cd ../../src/or
+ $(MAKE) /F Makefile.nmake
diff --git a/ReleaseNotes b/ReleaseNotes
index 7ba473e90..0f9299ec3 100644
--- a/ReleaseNotes
+++ b/ReleaseNotes
@@ -3,6 +3,1275 @@ This document summarizes new features and bugfixes in each stable release
of Tor. If you want to see more detailed descriptions of the changes in
each development snapshot, see the ChangeLog file.
+Changes in version 0.2.2.33 - 2011-09-13
+ Tor 0.2.2.33 fixes several bugs, and includes a slight tweak to Tor's
+ TLS handshake that makes relays and bridges that run this new version
+ reachable from Iran again.
+
+ o Major bugfixes:
+ - Avoid an assertion failure when reloading a configuration with
+ TrackExitHosts changes. Found and fixed by 'laruldan'. Fixes bug
+ 3923; bugfix on 0.2.2.25-alpha.
+
+ o Minor features (security):
+ - Check for replays of the public-key encrypted portion of an
+ INTRODUCE1 cell, in addition to the current check for replays of
+ the g^x value. This prevents a possible class of active attacks
+ by an attacker who controls both an introduction point and a
+ rendezvous point, and who uses the malleability of AES-CTR to
+ alter the encrypted g^x portion of the INTRODUCE1 cell. We think
+ that these attacks are infeasible (requiring the attacker to send
+ on the order of zettabytes of altered cells in a short interval),
+ but we'd rather block them off in case there are any classes of
+ this attack that we missed. Reported by Willem Pinckaers.
+
+ o Minor features:
+ - Adjust the expiration time on our SSL session certificates to
+ better match SSL certs seen in the wild. Resolves ticket 4014.
+ - Change the default required uptime for a relay to be accepted as
+ a HSDir (hidden service directory) from 24 hours to 25 hours.
+ Improves on 0.2.0.10-alpha; resolves ticket 2649.
+ - Add a VoteOnHidServDirectoriesV2 config option to allow directory
+ authorities to abstain from voting on assignment of the HSDir
+ consensus flag. Related to bug 2649.
+ - Update to the September 6 2011 Maxmind GeoLite Country database.
+
+ o Minor bugfixes (documentation and log messages):
+ - Correct the man page to explain that HashedControlPassword and
+ CookieAuthentication can both be set, in which case either method
+ is sufficient to authenticate to Tor. Bugfix on 0.2.0.7-alpha,
+ when we decided to allow these config options to both be set. Issue
+ raised by bug 3898.
+ - Demote the 'replay detected' log message emitted when a hidden
+ service receives the same Diffie-Hellman public key in two different
+ INTRODUCE2 cells to info level. A normal Tor client can cause that
+ log message during its normal operation. Bugfix on 0.2.1.6-alpha;
+ fixes part of bug 2442.
+ - Demote the 'INTRODUCE2 cell is too {old,new}' log message to info
+ level. There is nothing that a hidden service's operator can do
+ to fix its clients' clocks. Bugfix on 0.2.1.6-alpha; fixes part
+ of bug 2442.
+ - Clarify a log message specifying the characters permitted in
+ HiddenServiceAuthorizeClient client names. Previously, the log
+ message said that "[A-Za-z0-9+-_]" were permitted; that could have
+ given the impression that every ASCII character between "+" and "_"
+ was permitted. Now we say "[A-Za-z0-9+_-]". Bugfix on 0.2.1.5-alpha.
+
+ o Build fixes:
+ - Provide a substitute implementation of lround() for MSVC, which
+ apparently lacks it. Patch from Gisle Vanem.
+ - Clean up some code issues that prevented Tor from building on older
+ BSDs. Fixes bug 3894; reported by "grarpamp".
+ - Search for a platform-specific version of "ar" when cross-compiling.
+ Should fix builds on iOS. Resolves bug 3909, found by Marco Bonetti.
+
+
+Changes in version 0.2.2.32 - 2011-08-27
+ The Tor 0.2.2 release series is dedicated to the memory of Andreas
+ Pfitzmann (1958-2010), a pioneer in anonymity and privacy research,
+ a founder of the PETS community, a leader in our field, a mentor,
+ and a friend. He left us with these words: "I had the possibility
+ to contribute to this world that is not as it should be. I hope I
+ could help in some areas to make the world a better place, and that
+ I could also encourage other people to be engaged in improving the
+ world. Please, stay engaged. This world needs you, your love, your
+ initiative -- now I cannot be part of that anymore."
+
+ Tor 0.2.2.32, the first stable release in the 0.2.2 branch, is finally
+ ready. More than two years in the making, this release features improved
+ client performance and hidden service reliability, better compatibility
+ for Android, correct behavior for bridges that listen on more than
+ one address, more extensible and flexible directory object handling,
+ better reporting of network statistics, improved code security, and
+ many many other features and bugfixes.
+
+ o Major features (client performance):
+ - When choosing which cells to relay first, relays now favor circuits
+ that have been quiet recently, to provide lower latency for
+ low-volume circuits. By default, relays enable or disable this
+ feature based on a setting in the consensus. They can override
+ this default by using the new "CircuitPriorityHalflife" config
+ option. Design and code by Ian Goldberg, Can Tang, and Chris
+ Alexander.
+ - Directory authorities now compute consensus weightings that instruct
+ clients how to weight relays flagged as Guard, Exit, Guard+Exit,
+ and no flag. Clients use these weightings to distribute network load
+ more evenly across these different relay types. The weightings are
+ in the consensus so we can change them globally in the future. Extra
+ thanks to "outofwords" for finding some nasty security bugs in
+ the first implementation of this feature.
+
+ o Major features (client performance, circuit build timeout):
+ - Tor now tracks how long it takes to build client-side circuits
+ over time, and adapts its timeout to local network performance.
+ Since a circuit that takes a long time to build will also provide
+ bad performance, we get significant latency improvements by
+ discarding the slowest 20% of circuits. Specifically, Tor creates
+ circuits more aggressively than usual until it has enough data
+ points for a good timeout estimate. Implements proposal 151.
+ - Circuit build timeout constants can be controlled by consensus
+ parameters. We set good defaults for these parameters based on
+ experimentation on broadband and simulated high-latency links.
+ - Circuit build time learning can be disabled via consensus parameter
+ or by the client via a LearnCircuitBuildTimeout config option. We
+ also automatically disable circuit build time calculation if either
+ AuthoritativeDirectory is set, or if we fail to write our state
+ file. Implements ticket 1296.
+
+ o Major features (relays use their capacity better):
+ - Set SO_REUSEADDR socket option on all sockets, not just
+ listeners. This should help busy exit nodes avoid running out of
+ useable ports just because all the ports have been used in the
+ near past. Resolves issue 2850.
+ - Relays now save observed peak bandwidth throughput rates to their
+ state file (along with total usage, which was already saved),
+ so that they can determine their correct estimated bandwidth on
+ restart. Resolves bug 1863, where Tor relays would reset their
+ estimated bandwidth to 0 after restarting.
+ - Lower the maximum weighted-fractional-uptime cutoff to 98%. This
+ should give us approximately 40-50% more Guard-flagged nodes,
+ improving the anonymity the Tor network can provide and also
+ decreasing the dropoff in throughput that relays experience when
+ they first get the Guard flag.
+ - Directory authorities now take changes in router IP address and
+ ORPort into account when determining router stability. Previously,
+ if a router changed its IP or ORPort, the authorities would not
+ treat it as having any downtime for the purposes of stability
+ calculation, whereas clients would experience downtime since the
+ change would take a while to propagate to them. Resolves issue 1035.
+ - New AccelName and AccelDir options add support for dynamic OpenSSL
+ hardware crypto acceleration engines.
+
+ o Major features (relays control their load better):
+ - Exit relays now try harder to block exit attempts from unknown
+ relays, to make it harder for people to use them as one-hop proxies
+ a la tortunnel. Controlled by the refuseunknownexits consensus
+ parameter (currently enabled), or you can override it on your
+ relay with the RefuseUnknownExits torrc option. Resolves bug 1751;
+ based on a variant of proposal 163.
+ - Add separate per-conn write limiting to go with the per-conn read
+ limiting. We added a global write limit in Tor 0.1.2.5-alpha,
+ but never per-conn write limits.
+ - New consensus params "bwconnrate" and "bwconnburst" to let us
+ rate-limit client connections as they enter the network. It's
+ controlled in the consensus so we can turn it on and off for
+ experiments. It's starting out off. Based on proposal 163.
+
+ o Major features (controllers):
+ - Export GeoIP information on bridge usage to controllers even if we
+ have not yet been running for 24 hours. Now Vidalia bridge operators
+ can get more accurate and immediate feedback about their
+ contributions to the network.
+ - Add an __OwningControllerProcess configuration option and a
+ TAKEOWNERSHIP control-port command. Now a Tor controller can ensure
+ that when it exits, Tor will shut down. Implements feature 3049.
+
+ o Major features (directory authorities):
+ - Directory authorities now create, vote on, and serve multiple
+ parallel formats of directory data as part of their voting process.
+ Partially implements Proposal 162: "Publish the consensus in
+ multiple flavors".
+ - Directory authorities now agree on and publish small summaries
+ of router information that clients can use in place of regular
+ server descriptors. This transition will allow Tor 0.2.3 clients
+ to use far less bandwidth for downloading information about the
+ network. Begins the implementation of Proposal 158: "Clients
+ download consensus + microdescriptors".
+ - The directory voting system is now extensible to use multiple hash
+ algorithms for signatures and resource selection. Newer formats
+ are signed with SHA256, with a possibility for moving to a better
+ hash algorithm in the future.
+ - Directory authorities can now vote on arbitary integer values as
+ part of the consensus process. This is designed to help set
+ network-wide parameters. Implements proposal 167.
+
+ o Major features and bugfixes (node selection):
+ - Revise and reconcile the meaning of the ExitNodes, EntryNodes,
+ ExcludeEntryNodes, ExcludeExitNodes, ExcludeNodes, and Strict*Nodes
+ options. Previously, we had been ambiguous in describing what
+ counted as an "exit" node, and what operations exactly "StrictNodes
+ 0" would permit. This created confusion when people saw nodes built
+ through unexpected circuits, and made it hard to tell real bugs from
+ surprises. Now the intended behavior is:
+ . "Exit", in the context of ExitNodes and ExcludeExitNodes, means
+ a node that delivers user traffic outside the Tor network.
+ . "Entry", in the context of EntryNodes, means a node used as the
+ first hop of a multihop circuit. It doesn't include direct
+ connections to directory servers.
+ . "ExcludeNodes" applies to all nodes.
+ . "StrictNodes" changes the behavior of ExcludeNodes only. When
+ StrictNodes is set, Tor should avoid all nodes listed in
+ ExcludeNodes, even when it will make user requests fail. When
+ StrictNodes is *not* set, then Tor should follow ExcludeNodes
+ whenever it can, except when it must use an excluded node to
+ perform self-tests, connect to a hidden service, provide a
+ hidden service, fulfill a .exit request, upload directory
+ information, or fetch directory information.
+ Collectively, the changes to implement the behavior fix bug 1090.
+ - If EntryNodes, ExitNodes, ExcludeNodes, or ExcludeExitNodes
+ change during a config reload, mark and discard all our origin
+ circuits. This fix should address edge cases where we change the
+ config options and but then choose a circuit that we created before
+ the change.
+ - Make EntryNodes config option much more aggressive even when
+ StrictNodes is not set. Before it would prepend your requested
+ entrynodes to your list of guard nodes, but feel free to use others
+ after that. Now it chooses only from your EntryNodes if any of
+ those are available, and only falls back to others if a) they're
+ all down and b) StrictNodes is not set.
+ - Now we refresh your entry guards from EntryNodes at each consensus
+ fetch -- rather than just at startup and then they slowly rot as
+ the network changes.
+ - Add support for the country code "{??}" in torrc options like
+ ExcludeNodes, to indicate all routers of unknown country. Closes
+ bug 1094.
+ - ExcludeNodes now takes precedence over EntryNodes and ExitNodes: if
+ a node is listed in both, it's treated as excluded.
+ - ExcludeNodes now applies to directory nodes -- as a preference if
+ StrictNodes is 0, or an absolute requirement if StrictNodes is 1.
+ Don't exclude all the directory authorities and set StrictNodes to 1
+ unless you really want your Tor to break.
+ - ExcludeNodes and ExcludeExitNodes now override exit enclaving.
+ - ExcludeExitNodes now overrides .exit requests.
+ - We don't use bridges listed in ExcludeNodes.
+ - When StrictNodes is 1:
+ . We now apply ExcludeNodes to hidden service introduction points
+ and to rendezvous points selected by hidden service users. This
+ can make your hidden service less reliable: use it with caution!
+ . If we have used ExcludeNodes on ourself, do not try relay
+ reachability self-tests.
+ . If we have excluded all the directory authorities, we will not
+ even try to upload our descriptor if we're a relay.
+ . Do not honor .exit requests to an excluded node.
+ - When the set of permitted nodes changes, we now remove any mappings
+ introduced via TrackExitHosts to now-excluded nodes. Bugfix on
+ 0.1.0.1-rc.
+ - We never cannibalize a circuit that had excluded nodes on it, even
+ if StrictNodes is 0. Bugfix on 0.1.0.1-rc.
+ - Improve log messages related to excluded nodes.
+
+ o Major features (misc):
+ - Numerous changes, bugfixes, and workarounds from Nathan Freitas
+ to help Tor build correctly for Android phones.
+ - The options SocksPort, ControlPort, and so on now all accept a
+ value "auto" that opens a socket on an OS-selected port. A
+ new ControlPortWriteToFile option tells Tor to write its
+ actual control port or ports to a chosen file. If the option
+ ControlPortFileGroupReadable is set, the file is created as
+ group-readable. Now users can run two Tor clients on the same
+ system without needing to manually mess with parameters. Resolves
+ part of ticket 3076.
+ - Tor now supports tunneling all of its outgoing connections over
+ a SOCKS proxy, using the SOCKS4Proxy and/or SOCKS5Proxy
+ configuration options. Code by Christopher Davis.
+
+ o Code security improvements:
+ - Replace all potentially sensitive memory comparison operations
+ with versions whose runtime does not depend on the data being
+ compared. This will help resist a class of attacks where an
+ adversary can use variations in timing information to learn
+ sensitive data. Fix for one case of bug 3122. (Safe memcmp
+ implementation by Robert Ransom based partially on code by DJB.)
+ - Enable Address Space Layout Randomization (ASLR) and Data Execution
+ Prevention (DEP) by default on Windows to make it harder for
+ attackers to exploit vulnerabilities. Patch from John Brooks.
+ - New "--enable-gcc-hardening" ./configure flag (off by default)
+ to turn on gcc compile time hardening options. It ensures
+ that signed ints have defined behavior (-fwrapv), enables
+ -D_FORTIFY_SOURCE=2 (requiring -O2), adds stack smashing protection
+ with canaries (-fstack-protector-all), turns on ASLR protection if
+ supported by the kernel (-fPIE, -pie), and adds additional security
+ related warnings. Verified to work on Mac OS X and Debian Lenny.
+ - New "--enable-linker-hardening" ./configure flag (off by default)
+ to turn on ELF specific hardening features (relro, now). This does
+ not work with Mac OS X or any other non-ELF binary format.
+ - Always search the Windows system directory for system DLLs, and
+ nowhere else. Bugfix on 0.1.1.23; fixes bug 1954.
+ - New DisableAllSwap option. If set to 1, Tor will attempt to lock all
+ current and future memory pages via mlockall(). On supported
+ platforms (modern Linux and probably BSD but not Windows or OS X),
+ this should effectively disable any and all attempts to page out
+ memory. This option requires that you start your Tor as root --
+ if you use DisableAllSwap, please consider using the User option
+ to properly reduce the privileges of your Tor.
+
+ o Major bugfixes (crashes):
+ - Fix crash bug on platforms where gmtime and localtime can return
+ NULL. Windows 7 users were running into this one. Fixes part of bug
+ 2077. Bugfix on all versions of Tor. Found by boboper.
+ - Introduce minimum/maximum values that clients will believe
+ from the consensus. Now we'll have a better chance to avoid crashes
+ or worse when a consensus param has a weird value.
+ - Fix a rare crash bug that could occur when a client was configured
+ with a large number of bridges. Fixes bug 2629; bugfix on
+ 0.2.1.2-alpha. Bugfix by trac user "shitlei".
+ - Do not crash when our configuration file becomes unreadable, for
+ example due to a permissions change, between when we start up
+ and when a controller calls SAVECONF. Fixes bug 3135; bugfix
+ on 0.0.9pre6.
+ - If we're in the pathological case where there's no exit bandwidth
+ but there is non-exit bandwidth, or no guard bandwidth but there
+ is non-guard bandwidth, don't crash during path selection. Bugfix
+ on 0.2.0.3-alpha.
+ - Fix a crash bug when trying to initialize the evdns module in
+ Libevent 2. Bugfix on 0.2.1.16-rc.
+
+ o Major bugfixes (stability):
+ - Fix an assert in parsing router descriptors containing IPv6
+ addresses. This one took down the directory authorities when
+ somebody tried some experimental code. Bugfix on 0.2.1.3-alpha.
+ - Fix an uncommon assertion failure when running with DNSPort under
+ heavy load. Fixes bug 2933; bugfix on 0.2.0.1-alpha.
+ - Treat an unset $HOME like an empty $HOME rather than triggering an
+ assert. Bugfix on 0.0.8pre1; fixes bug 1522.
+ - More gracefully handle corrupt state files, removing asserts
+ in favor of saving a backup and resetting state.
+ - Instead of giving an assertion failure on an internal mismatch
+ on estimated freelist size, just log a BUG warning and try later.
+ Mitigates but does not fix bug 1125.
+ - Fix an assert that got triggered when using the TestingTorNetwork
+ configuration option and then issuing a GETINFO config-text control
+ command. Fixes bug 2250; bugfix on 0.2.1.2-alpha.
+ - If the cached cert file is unparseable, warn but don't exit.
+
+ o Privacy fixes (relays/bridges):
+ - Don't list Windows capabilities in relay descriptors. We never made
+ use of them, and maybe it's a bad idea to publish them. Bugfix
+ on 0.1.1.8-alpha.
+ - If the Nickname configuration option isn't given, Tor would pick a
+ nickname based on the local hostname as the nickname for a relay.
+ Because nicknames are not very important in today's Tor and the
+ "Unnamed" nickname has been implemented, this is now problematic
+ behavior: It leaks information about the hostname without being
+ useful at all. Fixes bug 2979; bugfix on 0.1.2.2-alpha, which
+ introduced the Unnamed nickname. Reported by tagnaq.
+ - Maintain separate TLS contexts and certificates for incoming and
+ outgoing connections in bridge relays. Previously we would use the
+ same TLS contexts and certs for incoming and outgoing connections.
+ Bugfix on 0.2.0.3-alpha; addresses bug 988.
+ - Maintain separate identity keys for incoming and outgoing TLS
+ contexts in bridge relays. Previously we would use the same
+ identity keys for incoming and outgoing TLS contexts. Bugfix on
+ 0.2.0.3-alpha; addresses the other half of bug 988.
+ - Make the bridge directory authority refuse to answer directory
+ requests for "all descriptors". It used to include bridge
+ descriptors in its answer, which was a major information leak.
+ Found by "piebeer". Bugfix on 0.2.0.3-alpha.
+
+ o Privacy fixes (clients):
+ - When receiving a hidden service descriptor, check that it is for
+ the hidden service we wanted. Previously, Tor would store any
+ hidden service descriptors that a directory gave it, whether it
+ wanted them or not. This wouldn't have let an attacker impersonate
+ a hidden service, but it did let directories pre-seed a client
+ with descriptors that it didn't want. Bugfix on 0.0.6.
+ - Start the process of disabling ".exit" address notation, since it
+ can be used for a variety of esoteric application-level attacks
+ on users. To reenable it, set "AllowDotExit 1" in your torrc. Fix
+ on 0.0.9rc5.
+ - Reject attempts at the client side to open connections to private
+ IP addresses (like 127.0.0.1, 10.0.0.1, and so on) with
+ a randomly chosen exit node. Attempts to do so are always
+ ill-defined, generally prevented by exit policies, and usually
+ in error. This will also help to detect loops in transparent
+ proxy configurations. You can disable this feature by setting
+ "ClientRejectInternalAddresses 0" in your torrc.
+ - Log a notice when we get a new control connection. Now it's easier
+ for security-conscious users to recognize when a local application
+ is knocking on their controller door. Suggested by bug 1196.
+
+ o Privacy fixes (newnym):
+ - Avoid linkability based on cached hidden service descriptors: forget
+ all hidden service descriptors cached as a client when processing a
+ SIGNAL NEWNYM command. Fixes bug 3000; bugfix on 0.0.6.
+ - On SIGHUP, do not clear out all TrackHostExits mappings, client
+ DNS cache entries, and virtual address mappings: that's what
+ NEWNYM is for. Fixes bug 1345; bugfix on 0.1.0.1-rc.
+ - Don't attach new streams to old rendezvous circuits after SIGNAL
+ NEWNYM. Previously, we would keep using an existing rendezvous
+ circuit if it remained open (i.e. if it were kept open by a
+ long-lived stream, or if a new stream were attached to it before
+ Tor could notice that it was old and no longer in use). Bugfix on
+ 0.1.1.15-rc; fixes bug 3375.
+
+ o Major bugfixes (relay bandwidth accounting):
+ - Fix a bug that could break accounting on 64-bit systems with large
+ time_t values, making them hibernate for impossibly long intervals.
+ Fixes bug 2146. Bugfix on 0.0.9pre6; fix by boboper.
+ - Fix a bug in bandwidth accounting that could make us use twice
+ the intended bandwidth when our interval start changes due to
+ daylight saving time. Now we tolerate skew in stored vs computed
+ interval starts: if the start of the period changes by no more than
+ 50% of the period's duration, we remember bytes that we transferred
+ in the old period. Fixes bug 1511; bugfix on 0.0.9pre5.
+
+ o Major bugfixes (bridges):
+ - Bridges now use "reject *:*" as their default exit policy. Bugfix
+ on 0.2.0.3-alpha. Fixes bug 1113.
+ - If you configure your bridge with a known identity fingerprint,
+ and the bridge authority is unreachable (as it is in at least
+ one country now), fall back to directly requesting the descriptor
+ from the bridge. Finishes the feature started in 0.2.0.10-alpha;
+ closes bug 1138.
+ - Fix a bug where bridge users who configure the non-canonical
+ address of a bridge automatically switch to its canonical
+ address. If a bridge listens at more than one address, it
+ should be able to advertise those addresses independently and
+ any non-blocked addresses should continue to work. Bugfix on Tor
+ 0.2.0.3-alpha. Fixes bug 2510.
+ - If you configure Tor to use bridge A, and then quit and
+ configure Tor to use bridge B instead (or if you change Tor
+ to use bridge B via the controller), it would happily continue
+ to use bridge A if it's still reachable. While this behavior is
+ a feature if your goal is connectivity, in some scenarios it's a
+ dangerous bug. Bugfix on Tor 0.2.0.1-alpha; fixes bug 2511.
+ - When the controller configures a new bridge, don't wait 10 to 60
+ seconds before trying to fetch its descriptor. Bugfix on
+ 0.2.0.3-alpha; fixes bug 3198 (suggested by 2355).
+
+ o Major bugfixes (directory authorities):
+ - Many relays have been falling out of the consensus lately because
+ not enough authorities know about their descriptor for them to get
+ a majority of votes. When we deprecated the v2 directory protocol,
+ we got rid of the only way that v3 authorities can hear from each
+ other about other descriptors. Now authorities examine every v3
+ vote for new descriptors, and fetch them from that authority. Bugfix
+ on 0.2.1.23.
+ - Authorities could be tricked into giving out the Exit flag to relays
+ that didn't allow exiting to any ports. This bug could screw
+ with load balancing and stats. Bugfix on 0.1.1.6-alpha; fixes bug
+ 1238. Bug discovered by Martin Kowalczyk.
+ - If all authorities restart at once right before a consensus vote,
+ nobody will vote about "Running", and clients will get a consensus
+ with no usable relays. Instead, authorities refuse to build a
+ consensus if this happens. Bugfix on 0.2.0.10-alpha; fixes bug 1066.
+
+ o Major bugfixes (stream-level fairness):
+ - When receiving a circuit-level SENDME for a blocked circuit, try
+ to package cells fairly from all the streams that had previously
+ been blocked on that circuit. Previously, we had started with the
+ oldest stream, and allowed each stream to potentially exhaust
+ the circuit's package window. This gave older streams on any
+ given circuit priority over newer ones. Fixes bug 1937. Detected
+ originally by Camilo Viecco. This bug was introduced before the
+ first Tor release, in svn commit r152: it is the new winner of
+ the longest-lived bug prize.
+ - Fix a stream fairness bug that would cause newer streams on a given
+ circuit to get preference when reading bytes from the origin or
+ destination. Fixes bug 2210. Fix by Mashael AlSabah. This bug was
+ introduced before the first Tor release, in svn revision r152.
+ - When the exit relay got a circuit-level sendme cell, it started
+ reading on the exit streams, even if had 500 cells queued in the
+ circuit queue already, so the circuit queue just grew and grew in
+ some cases. We fix this by not re-enabling reading on receipt of a
+ sendme cell when the cell queue is blocked. Fixes bug 1653. Bugfix
+ on 0.2.0.1-alpha. Detected by Mashael AlSabah. Original patch by
+ "yetonetime".
+ - Newly created streams were allowed to read cells onto circuits,
+ even if the circuit's cell queue was blocked and waiting to drain.
+ This created potential unfairness, as older streams would be
+ blocked, but newer streams would gladly fill the queue completely.
+ We add code to detect this situation and prevent any stream from
+ getting more than one free cell. Bugfix on 0.2.0.1-alpha. Partially
+ fixes bug 1298.
+
+ o Major bugfixes (hidden services):
+ - Apply circuit timeouts to opened hidden-service-related circuits
+ based on the correct start time. Previously, we would apply the
+ circuit build timeout based on time since the circuit's creation;
+ it was supposed to be applied based on time since the circuit
+ entered its current state. Bugfix on 0.0.6; fixes part of bug 1297.
+ - Improve hidden service robustness: When we find that we have
+ extended a hidden service's introduction circuit to a relay not
+ listed as an introduction point in the HS descriptor we currently
+ have, retry with an introduction point from the current
+ descriptor. Previously we would just give up. Fixes bugs 1024 and
+ 1930; bugfix on 0.2.0.10-alpha.
+ - Directory authorities now use data collected from their own
+ uptime observations when choosing whether to assign the HSDir flag
+ to relays, instead of trusting the uptime value the relay reports in
+ its descriptor. This change helps prevent an attack where a small
+ set of nodes with frequently-changing identity keys can blackhole
+ a hidden service. (Only authorities need upgrade; others will be
+ fine once they do.) Bugfix on 0.2.0.10-alpha; fixes bug 2709.
+ - Stop assigning the HSDir flag to relays that disable their
+ DirPort (and thus will refuse to answer directory requests). This
+ fix should dramatically improve the reachability of hidden services:
+ hidden services and hidden service clients pick six HSDir relays
+ to store and retrieve the hidden service descriptor, and currently
+ about half of the HSDir relays will refuse to work. Bugfix on
+ 0.2.0.10-alpha; fixes part of bug 1693.
+
+ o Major bugfixes (misc):
+ - Clients now stop trying to use an exit node associated with a given
+ destination by TrackHostExits if they fail to reach that exit node.
+ Fixes bug 2999. Bugfix on 0.2.0.20-rc.
+ - Fix a regression that caused Tor to rebind its ports if it receives
+ SIGHUP while hibernating. Bugfix in 0.1.1.6-alpha; closes bug 919.
+ - Remove an extra pair of quotation marks around the error
+ message in control-port STATUS_GENERAL BUG events. Bugfix on
+ 0.1.2.6-alpha; fixes bug 3732.
+
+ o Minor features (relays):
+ - Ensure that no empty [dirreq-](read|write)-history lines are added
+ to an extrainfo document. Implements ticket 2497.
+ - When bandwidth accounting is enabled, be more generous with how
+ much bandwidth we'll use up before entering "soft hibernation".
+ Previously, we'd refuse new connections and circuits once we'd
+ used up 95% of our allotment. Now, we use up 95% of our allotment,
+ AND make sure that we have no more than 500MB (or 3 hours of
+ expected traffic, whichever is lower) remaining before we enter
+ soft hibernation.
+ - Relays now log the reason for publishing a new relay descriptor,
+ so we have a better chance of hunting down instances of bug 1810.
+ Resolves ticket 3252.
+ - Log a little more clearly about the times at which we're no longer
+ accepting new connections (e.g. due to hibernating). Resolves
+ bug 2181.
+ - When AllowSingleHopExits is set, print a warning to explain to the
+ relay operator why most clients are avoiding her relay.
+ - Send END_STREAM_REASON_NOROUTE in response to EHOSTUNREACH errors.
+ Clients before 0.2.1.27 didn't handle NOROUTE correctly, but such
+ clients are already deprecated because of security bugs.
+
+ o Minor features (network statistics):
+ - Directory mirrors that set "DirReqStatistics 1" write statistics
+ about directory requests to disk every 24 hours. As compared to the
+ "--enable-geoip-stats" ./configure flag in 0.2.1.x, there are a few
+ improvements: 1) stats are written to disk exactly every 24 hours;
+ 2) estimated shares of v2 and v3 requests are determined as mean
+ values, not at the end of a measurement period; 3) unresolved
+ requests are listed with country code '??'; 4) directories also
+ measure download times.
+ - Exit nodes that set "ExitPortStatistics 1" write statistics on the
+ number of exit streams and transferred bytes per port to disk every
+ 24 hours.
+ - Relays that set "CellStatistics 1" write statistics on how long
+ cells spend in their circuit queues to disk every 24 hours.
+ - Entry nodes that set "EntryStatistics 1" write statistics on the
+ rough number and origins of connecting clients to disk every 24
+ hours.
+ - Relays that write any of the above statistics to disk and set
+ "ExtraInfoStatistics 1" include the past 24 hours of statistics in
+ their extra-info documents. Implements proposal 166.
+
+ o Minor features (GeoIP and statistics):
+ - Provide a log message stating which geoip file we're parsing
+ instead of just stating that we're parsing the geoip file.
+ Implements ticket 2432.
+ - Make sure every relay writes a state file at least every 12 hours.
+ Previously, a relay could go for weeks without writing its state
+ file, and on a crash could lose its bandwidth history, capacity
+ estimates, client country statistics, and so on. Addresses bug 3012.
+ - Relays report the number of bytes spent on answering directory
+ requests in extra-info descriptors similar to {read,write}-history.
+ Implements enhancement 1790.
+ - Report only the top 10 ports in exit-port stats in order not to
+ exceed the maximum extra-info descriptor length of 50 KB. Implements
+ task 2196.
+ - If writing the state file to disk fails, wait up to an hour before
+ retrying again, rather than trying again each second. Fixes bug
+ 2346; bugfix on Tor 0.1.1.3-alpha.
+ - Delay geoip stats collection by bridges for 6 hours, not 2 hours,
+ when we switch from being a public relay to a bridge. Otherwise
+ there will still be clients that see the relay in their consensus,
+ and the stats will end up wrong. Bugfix on 0.2.1.15-rc; fixes
+ bug 932.
+ - Update to the August 2 2011 Maxmind GeoLite Country database.
+
+ o Minor features (clients):
+ - When expiring circuits, use microsecond timers rather than
+ one-second timers. This can avoid an unpleasant situation where a
+ circuit is launched near the end of one second and expired right
+ near the beginning of the next, and prevent fluctuations in circuit
+ timeout values.
+ - If we've configured EntryNodes and our network goes away and/or all
+ our entrynodes get marked down, optimistically retry them all when
+ a new socks application request appears. Fixes bug 1882.
+ - Always perform router selections using weighted relay bandwidth,
+ even if we don't need a high capacity circuit at the time. Non-fast
+ circuits now only differ from fast ones in that they can use relays
+ not marked with the Fast flag. This "feature" could turn out to
+ be a horrible bug; we should investigate more before it goes into
+ a stable release.
+ - When we run out of directory information such that we can't build
+ circuits, but then get enough that we can build circuits, log when
+ we actually construct a circuit, so the user has a better chance of
+ knowing what's going on. Fixes bug 1362.
+ - Log SSL state transitions at debug level during handshake, and
+ include SSL states in error messages. This may help debug future
+ SSL handshake issues.
+
+ o Minor features (directory authorities):
+ - When a router changes IP address or port, authorities now launch
+ a new reachability test for it. Implements ticket 1899.
+ - Directory authorities now reject relays running any versions of
+ Tor between 0.2.1.3-alpha and 0.2.1.18 inclusive; they have
+ known bugs that keep RELAY_EARLY cells from working on rendezvous
+ circuits. Followup to fix for bug 2081.
+ - Directory authorities now reject relays running any version of Tor
+ older than 0.2.0.26-rc. That version is the earliest that fetches
+ current directory information correctly. Fixes bug 2156.
+ - Directory authorities now do an immediate reachability check as soon
+ as they hear about a new relay. This change should slightly reduce
+ the time between setting up a relay and getting listed as running
+ in the consensus. It should also improve the time between setting
+ up a bridge and seeing use by bridge users.
+ - Directory authorities no longer launch a TLS connection to every
+ relay as they startup. Now that we have 2k+ descriptors cached,
+ the resulting network hiccup is becoming a burden. Besides,
+ authorities already avoid voting about Running for the first half
+ hour of their uptime.
+ - Directory authorities now log the source of a rejected POSTed v3
+ networkstatus vote, so we can track failures better.
+ - Backport code from 0.2.3.x that allows directory authorities to
+ clean their microdescriptor caches. Needed to resolve bug 2230.
+
+ o Minor features (hidden services):
+ - Use computed circuit-build timeouts to decide when to launch
+ parallel introduction circuits for hidden services. (Previously,
+ we would retry after 15 seconds.)
+ - Don't allow v0 hidden service authorities to act as clients.
+ Required by fix for bug 3000.
+ - Ignore SIGNAL NEWNYM commands on relay-only Tor instances. Required
+ by fix for bug 3000.
+ - Make hidden services work better in private Tor networks by not
+ requiring any uptime to join the hidden service descriptor
+ DHT. Implements ticket 2088.
+ - Log (at info level) when purging pieces of hidden-service-client
+ state because of SIGNAL NEWNYM.
+
+ o Minor features (controller interface):
+ - New "GETINFO net/listeners/(type)" controller command to return
+ a list of addresses and ports that are bound for listeners for a
+ given connection type. This is useful when the user has configured
+ "SocksPort auto" and the controller needs to know which port got
+ chosen. Resolves another part of ticket 3076.
+ - Have the controller interface give a more useful message than
+ "Internal Error" in response to failed GETINFO requests.
+ - Add a TIMEOUT_RATE keyword to the BUILDTIMEOUT_SET control port
+ event, to give information on the current rate of circuit timeouts
+ over our stored history.
+ - The 'EXTENDCIRCUIT' control port command can now be used with
+ a circ id of 0 and no path. This feature will cause Tor to build
+ a new 'fast' general purpose circuit using its own path selection
+ algorithms.
+ - Added a BUILDTIMEOUT_SET controller event to describe changes
+ to the circuit build timeout.
+ - New controller command "getinfo config-text". It returns the
+ contents that Tor would write if you send it a SAVECONF command,
+ so the controller can write the file to disk itself.
+
+ o Minor features (controller protocol):
+ - Add a new ControlSocketsGroupWritable configuration option: when
+ it is turned on, ControlSockets are group-writeable by the default
+ group of the current user. Patch by Jérémy Bobbio; implements
+ ticket 2972.
+ - Tor now refuses to create a ControlSocket in a directory that is
+ world-readable (or group-readable if ControlSocketsGroupWritable
+ is 0). This is necessary because some operating systems do not
+ enforce permissions on an AF_UNIX sockets. Permissions on the
+ directory holding the socket, however, seems to work everywhere.
+ - Warn when CookieAuthFileGroupReadable is set but CookieAuthFile is
+ not. This would lead to a cookie that is still not group readable.
+ Closes bug 1843. Suggested by katmagic.
+ - Future-proof the controller protocol a bit by ignoring keyword
+ arguments we do not recognize.
+
+ o Minor features (more useful logging):
+ - Revise most log messages that refer to nodes by nickname to
+ instead use the "$key=nickname at address" format. This should be
+ more useful, especially since nicknames are less and less likely
+ to be unique. Resolves ticket 3045.
+ - When an HTTPS proxy reports "403 Forbidden", we now explain
+ what it means rather than calling it an unexpected status code.
+ Closes bug 2503. Patch from Michael Yakubovich.
+ - Rate-limit a warning about failures to download v2 networkstatus
+ documents. Resolves part of bug 1352.
+ - Rate-limit the "your application is giving Tor only an IP address"
+ warning. Addresses bug 2000; bugfix on 0.0.8pre2.
+ - Rate-limit "Failed to hand off onionskin" warnings.
+ - When logging a rate-limited warning, we now mention how many messages
+ got suppressed since the last warning.
+ - Make the formerly ugly "2 unknown, 7 missing key, 0 good, 0 bad,
+ 2 no signature, 4 required" messages about consensus signatures
+ easier to read, and make sure they get logged at the same severity
+ as the messages explaining which keys are which. Fixes bug 1290.
+ - Don't warn when we have a consensus that we can't verify because
+ of missing certificates, unless those certificates are ones
+ that we have been trying and failing to download. Fixes bug 1145.
+
+ o Minor features (log domains):
+ - Add documentation for configuring logging at different severities in
+ different log domains. We've had this feature since 0.2.1.1-alpha,
+ but for some reason it never made it into the manpage. Fixes
+ bug 2215.
+ - Make it simpler to specify "All log domains except for A and B".
+ Previously you needed to say "[*,~A,~B]". Now you can just say
+ "[~A,~B]".
+ - Add a "LogMessageDomains 1" option to include the domains of log
+ messages along with the messages. Without this, there's no way
+ to use log domains without reading the source or doing a lot
+ of guessing.
+ - Add a new "Handshake" log domain for activities that happen
+ during the TLS handshake.
+
+ o Minor features (build process):
+ - Make compilation with clang possible when using
+ "--enable-gcc-warnings" by removing two warning options that clang
+ hasn't implemented yet and by fixing a few warnings. Resolves
+ ticket 2696.
+ - Detect platforms that brokenly use a signed size_t, and refuse to
+ build there. Found and analyzed by doorss and rransom.
+ - Fix a bunch of compile warnings revealed by mingw with gcc 4.5.
+ Resolves bug 2314.
+ - Add support for statically linking zlib by specifying
+ "--enable-static-zlib", to go with our support for statically
+ linking openssl and libevent. Resolves bug 1358.
+ - Instead of adding the svn revision to the Tor version string, report
+ the git commit (when we're building from a git checkout).
+ - Rename the "log.h" header to "torlog.h" so as to conflict with fewer
+ system headers.
+ - New --digests command-line switch to output the digests of the
+ source files Tor was built with.
+ - Generate our manpage and HTML documentation using Asciidoc. This
+ change should make it easier to maintain the documentation, and
+ produce nicer HTML. The build process fails if asciidoc cannot
+ be found and building with asciidoc isn't disabled (via the
+ "--disable-asciidoc" argument to ./configure. Skipping the manpage
+ speeds up the build considerably.
+
+ o Minor features (options / torrc):
+ - Warn when the same option is provided more than once in a torrc
+ file, on the command line, or in a single SETCONF statement, and
+ the option is one that only accepts a single line. Closes bug 1384.
+ - Warn when the user configures two HiddenServiceDir lines that point
+ to the same directory. Bugfix on 0.0.6 (the version introducing
+ HiddenServiceDir); fixes bug 3289.
+ - Add new "perconnbwrate" and "perconnbwburst" consensus params to
+ do individual connection-level rate limiting of clients. The torrc
+ config options with the same names trump the consensus params, if
+ both are present. Replaces the old "bwconnrate" and "bwconnburst"
+ consensus params which were broken from 0.2.2.7-alpha through
+ 0.2.2.14-alpha. Closes bug 1947.
+ - New config option "WarnUnsafeSocks 0" disables the warning that
+ occurs whenever Tor receives a socks handshake using a version of
+ the socks protocol that can only provide an IP address (rather
+ than a hostname). Setups that do DNS locally over Tor are fine,
+ and we shouldn't spam the logs in that case.
+ - New config option "CircuitStreamTimeout" to override our internal
+ timeout schedule for how many seconds until we detach a stream from
+ a circuit and try a new circuit. If your network is particularly
+ slow, you might want to set this to a number like 60.
+ - New options for SafeLogging to allow scrubbing only log messages
+ generated while acting as a relay. Specify "SafeLogging relay" if
+ you want to ensure that only messages known to originate from
+ client use of the Tor process will be logged unsafely.
+ - Time and memory units in the configuration file can now be set to
+ fractional units. For example, "2.5 GB" is now a valid value for
+ AccountingMax.
+ - Support line continuations in the torrc config file. If a line
+ ends with a single backslash character, the newline is ignored, and
+ the configuration value is treated as continuing on the next line.
+ Resolves bug 1929.
+
+ o Minor features (unit tests):
+ - Revise our unit tests to use the "tinytest" framework, so we
+ can run tests in their own processes, have smarter setup/teardown
+ code, and so on. The unit test code has moved to its own
+ subdirectory, and has been split into multiple modules.
+ - Add a unit test for cross-platform directory-listing code.
+ - Add some forgotten return value checks during unit tests. Found
+ by coverity.
+ - Use GetTempDir to find the proper temporary directory location on
+ Windows when generating temporary files for the unit tests. Patch
+ by Gisle Vanem.
+
+ o Minor features (misc):
+ - The "torify" script now uses torsocks where available.
+ - Make Libevent log messages get delivered to controllers later,
+ and not from inside the Libevent log handler. This prevents unsafe
+ reentrant Libevent calls while still letting the log messages
+ get through.
+ - Certain Tor clients (such as those behind check.torproject.org) may
+ want to fetch the consensus in an extra early manner. To enable this
+ a user may now set FetchDirInfoExtraEarly to 1. This also depends on
+ setting FetchDirInfoEarly to 1. Previous behavior will stay the same
+ as only certain clients who must have this information sooner should
+ set this option.
+ - Expand homedirs passed to tor-checkkey. This should silence a
+ coverity complaint about passing a user-supplied string into
+ open() without checking it.
+ - Make sure to disable DirPort if running as a bridge. DirPorts aren't
+ used on bridges, and it makes bridge scanning somewhat easier.
+ - Create the /var/run/tor directory on startup on OpenSUSE if it is
+ not already created. Patch from Andreas Stieger. Fixes bug 2573.
+
+ o Minor bugfixes (relays):
+ - When a relay decides that its DNS is too broken for it to serve
+ as an exit server, it advertised itself as a non-exit, but
+ continued to act as an exit. This could create accidental
+ partitioning opportunities for users. Instead, if a relay is
+ going to advertise reject *:* as its exit policy, it should
+ really act with exit policy "reject *:*". Fixes bug 2366.
+ Bugfix on Tor 0.1.2.5-alpha. Bugfix by user "postman" on trac.
+ - Publish a router descriptor even if generating an extra-info
+ descriptor fails. Previously we would not publish a router
+ descriptor without an extra-info descriptor; this can cause fast
+ exit relays collecting exit-port statistics to drop from the
+ consensus. Bugfix on 0.1.2.9-rc; fixes bug 2195.
+ - When we're trying to guess whether we know our IP address as
+ a relay, we would log various ways that we failed to guess
+ our address, but never log that we ended up guessing it
+ successfully. Now add a log line to help confused and anxious
+ relay operators. Bugfix on 0.1.2.1-alpha; fixes bug 1534.
+ - For bandwidth accounting, calculate our expected bandwidth rate
+ based on the time during which we were active and not in
+ soft-hibernation during the last interval. Previously, we were
+ also considering the time spent in soft-hibernation. If this
+ was a long time, we would wind up underestimating our bandwidth
+ by a lot, and skewing our wakeup time towards the start of the
+ accounting interval. Fixes bug 1789. Bugfix on 0.0.9pre5.
+ - Demote a confusing TLS warning that relay operators might get when
+ someone tries to talk to their ORPort. It is not the operator's
+ fault, nor can they do anything about it. Fixes bug 1364; bugfix
+ on 0.2.0.14-alpha.
+ - Change "Application request when we're believed to be offline."
+ notice to "Application request when we haven't used client
+ functionality lately.", to clarify that it's not an error. Bugfix
+ on 0.0.9.3; fixes bug 1222.
+
+ o Minor bugfixes (bridges):
+ - When a client starts or stops using bridges, never use a circuit
+ that was built before the configuration change. This behavior could
+ put at risk a user who uses bridges to ensure that her traffic
+ only goes to the chosen addresses. Bugfix on 0.2.0.3-alpha; fixes
+ bug 3200.
+ - Do not reset the bridge descriptor download status every time we
+ re-parse our configuration or get a configuration change. Fixes
+ bug 3019; bugfix on 0.2.0.3-alpha.
+ - Users couldn't configure a regular relay to be their bridge. It
+ didn't work because when Tor fetched the bridge descriptor, it found
+ that it already had it, and didn't realize that the purpose of the
+ descriptor had changed. Now we replace routers with a purpose other
+ than bridge with bridge descriptors when fetching them. Bugfix on
+ 0.1.1.9-alpha. Fixes bug 1776.
+ - In the special case where you configure a public exit relay as your
+ bridge, Tor would be willing to use that exit relay as the last
+ hop in your circuit as well. Now we fail that circuit instead.
+ Bugfix on 0.2.0.12-alpha. Fixes bug 2403. Reported by "piebeer".
+
+ o Minor bugfixes (clients):
+ - We now ask the other side of a stream (the client or the exit)
+ for more data on that stream when the amount of queued data on
+ that stream dips low enough. Previously, we wouldn't ask the
+ other side for more data until either it sent us more data (which
+ it wasn't supposed to do if it had exhausted its window!) or we
+ had completely flushed all our queued data. This flow control fix
+ should improve throughput. Fixes bug 2756; bugfix on the earliest
+ released versions of Tor (svn commit r152).
+ - When a client finds that an origin circuit has run out of 16-bit
+ stream IDs, we now mark it as unusable for new streams. Previously,
+ we would try to close the entire circuit. Bugfix on 0.0.6.
+ - Make it explicit that we don't cannibalize one-hop circuits. This
+ happens in the wild, but doesn't turn out to be a problem because
+ we fortunately don't use those circuits. Many thanks to outofwords
+ for the initial analysis and to swissknife who confirmed that
+ two-hop circuits are actually created.
+ - Resolve an edge case in path weighting that could make us misweight
+ our relay selection. Fixes bug 1203; bugfix on 0.0.8rc1.
+ - Make the DNSPort option work with libevent 2.x. Don't alter the
+ behaviour for libevent 1.x. Fixes bug 1143. Found by SwissTorExit.
+
+ o Minor bugfixes (directory authorities):
+ - Make directory authorities more accurate at recording when
+ relays that have failed several reachability tests became
+ unreachable, so we can provide more accuracy at assigning Stable,
+ Guard, HSDir, etc flags. Bugfix on 0.2.0.6-alpha. Resolves bug 2716.
+ - Directory authorities are now more robust to hops back in time
+ when calculating router stability. Previously, if a run of uptime
+ or downtime appeared to be negative, the calculation could give
+ incorrect results. Bugfix on 0.2.0.6-alpha; noticed when fixing
+ bug 1035.
+ - Directory authorities will now attempt to download consensuses
+ if their own efforts to make a live consensus have failed. This
+ change means authorities that restart will fetch a valid
+ consensus, and it means authorities that didn't agree with the
+ current consensus will still fetch and serve it if it has enough
+ signatures. Bugfix on 0.2.0.9-alpha; fixes bug 1300.
+ - Never vote for a server as "Running" if we have a descriptor for
+ it claiming to be hibernating, and that descriptor was published
+ more recently than our last contact with the server. Bugfix on
+ 0.2.0.3-alpha; fixes bug 911.
+ - Directory authorities no longer change their opinion of, or vote on,
+ whether a router is Running, unless they have themselves been
+ online long enough to have some idea. Bugfix on 0.2.0.6-alpha.
+ Fixes bug 1023.
+
+ o Minor bugfixes (hidden services):
+ - Log malformed requests for rendezvous descriptors as protocol
+ warnings, not warnings. Also, use a more informative log message
+ in case someone sees it at log level warning without prior
+ info-level messages. Fixes bug 2748; bugfix on 0.2.0.10-alpha.
+ - Accept hidden service descriptors if we think we might be a hidden
+ service directory, regardless of what our consensus says. This
+ helps robustness, since clients and hidden services can sometimes
+ have a more up-to-date view of the network consensus than we do,
+ and if they think that the directory authorities list us a HSDir,
+ we might actually be one. Related to bug 2732; bugfix on
+ 0.2.0.10-alpha.
+ - Correct the warning displayed when a rendezvous descriptor exceeds
+ the maximum size. Fixes bug 2750; bugfix on 0.2.1.5-alpha. Found by
+ John Brooks.
+ - Clients and hidden services now use HSDir-flagged relays for hidden
+ service descriptor downloads and uploads even if the relays have no
+ DirPort set and the client has disabled TunnelDirConns. This will
+ eventually allow us to give the HSDir flag to relays with no
+ DirPort. Fixes bug 2722; bugfix on 0.2.1.6-alpha.
+ - Only limit the lengths of single HS descriptors, even when multiple
+ HS descriptors are published to an HSDir relay in a single POST
+ operation. Fixes bug 2948; bugfix on 0.2.1.5-alpha. Found by hsdir.
+
+ o Minor bugfixes (controllers):
+ - Allow GETINFO fingerprint to return a fingerprint even when
+ we have not yet built a router descriptor. Fixes bug 3577;
+ bugfix on 0.2.0.1-alpha.
+ - Send a SUCCEEDED stream event to the controller when a reverse
+ resolve succeeded. Fixes bug 3536; bugfix on 0.0.8pre1. Issue
+ discovered by katmagic.
+ - Remove a trailing asterisk from "exit-policy/default" in the
+ output of the control port command "GETINFO info/names". Bugfix
+ on 0.1.2.5-alpha.
+ - Make the SIGNAL DUMP controller command work on FreeBSD. Fixes bug
+ 2917. Bugfix on 0.1.1.1-alpha.
+ - When we restart our relay, we might get a successful connection
+ from the outside before we've started our reachability tests,
+ triggering a warning: "ORPort found reachable, but I have no
+ routerinfo yet. Failing to inform controller of success." This
+ bug was harmless unless Tor is running under a controller
+ like Vidalia, in which case the controller would never get a
+ REACHABILITY_SUCCEEDED status event. Bugfix on 0.1.2.6-alpha;
+ fixes bug 1172.
+ - When a controller changes TrackHostExits, remove mappings for
+ hosts that should no longer have their exits tracked. Bugfix on
+ 0.1.0.1-rc.
+ - When a controller changes VirtualAddrNetwork, remove any mappings
+ for hosts that were automapped to the old network. Bugfix on
+ 0.1.1.19-rc.
+ - When a controller changes one of the AutomapHosts* options, remove
+ any mappings for hosts that should no longer be automapped. Bugfix
+ on 0.2.0.1-alpha.
+ - Fix an off-by-one error in calculating some controller command
+ argument lengths. Fortunately, this mistake is harmless since
+ the controller code does redundant NUL termination too. Found by
+ boboper. Bugfix on 0.1.1.1-alpha.
+ - Fix a bug in the controller interface where "GETINFO ns/asdaskljkl"
+ would return "551 Internal error" rather than "552 Unrecognized key
+ ns/asdaskljkl". Bugfix on 0.1.2.3-alpha.
+ - Don't spam the controller with events when we have no file
+ descriptors available. Bugfix on 0.2.1.5-alpha. (Rate-limiting
+ for log messages was already solved from bug 748.)
+ - Emit a GUARD DROPPED controller event for a case we missed.
+ - Ensure DNS requests launched by "RESOLVE" commands from the
+ controller respect the __LeaveStreamsUnattached setconf options. The
+ same goes for requests launched via DNSPort or transparent
+ proxying. Bugfix on 0.2.0.1-alpha; fixes bug 1525.
+
+ o Minor bugfixes (config options):
+ - Tor used to limit HttpProxyAuthenticator values to 48 characters.
+ Change the limit to 512 characters by removing base64 newlines.
+ Fixes bug 2752. Fix by Michael Yakubovich.
+ - Complain if PublishServerDescriptor is given multiple arguments that
+ include 0 or 1. This configuration will be rejected in the future.
+ Bugfix on 0.2.0.1-alpha; closes bug 1107.
+ - Disallow BridgeRelay 1 and ORPort 0 at once in the configuration.
+ Bugfix on 0.2.0.13-alpha; closes bug 928.
+
+ o Minor bugfixes (log subsystem fixes):
+ - When unable to format an address as a string, report its value
+ as "???" rather than reusing the last formatted address. Bugfix
+ on 0.2.1.5-alpha.
+ - Be more consistent in our treatment of file system paths. "~" should
+ get expanded to the user's home directory in the Log config option.
+ Fixes bug 2971; bugfix on 0.2.0.1-alpha, which introduced the
+ feature for the -f and --DataDirectory options.
+
+ o Minor bugfixes (memory management):
+ - Don't stack-allocate the list of supplementary GIDs when we're
+ about to log them. Stack-allocating NGROUPS_MAX gid_t elements
+ could take up to 256K, which is way too much stack. Found by
+ Coverity; CID #450. Bugfix on 0.2.1.7-alpha.
+ - Save a couple bytes in memory allocation every time we escape
+ certain characters in a string. Patch from Florian Zumbiehl.
+
+ o Minor bugfixes (protocol correctness):
+ - When checking for 1024-bit keys, check for 1024 bits, not 128
+ bytes. This allows Tor to correctly discard keys of length 1017
+ through 1023. Bugfix on 0.0.9pre5.
+ - Require that introduction point keys and onion handshake keys
+ have a public exponent of 65537. Starts to fix bug 3207; bugfix
+ on 0.2.0.10-alpha.
+ - Handle SOCKS messages longer than 128 bytes long correctly, rather
+ than waiting forever for them to finish. Fixes bug 2330; bugfix
+ on 0.2.0.16-alpha. Found by doorss.
+ - Never relay a cell for a circuit we have already destroyed.
+ Between marking a circuit as closeable and finally closing it,
+ it may have been possible for a few queued cells to get relayed,
+ even though they would have been immediately dropped by the next
+ OR in the circuit. Fixes bug 1184; bugfix on 0.2.0.1-alpha.
+ - Never queue a cell for a circuit that's already been marked
+ for close.
+ - Fix a spec conformance issue: the network-status-version token
+ must be the first token in a v3 consensus or vote. Discovered by
+ "parakeep". Bugfix on 0.2.0.3-alpha.
+ - A networkstatus vote must contain exactly one signature. Spec
+ conformance issue. Bugfix on 0.2.0.3-alpha.
+ - When asked about a DNS record type we don't support via a
+ client DNSPort, reply with NOTIMPL rather than an empty
+ reply. Patch by intrigeri. Fixes bug 3369; bugfix on 2.0.1-alpha.
+ - Make more fields in the controller protocol case-insensitive, since
+ control-spec.txt said they were.
+
+ o Minor bugfixes (log messages):
+ - Fix a log message that said "bits" while displaying a value in
+ bytes. Found by wanoskarnet. Fixes bug 3318; bugfix on
+ 0.2.0.1-alpha.
+ - Downgrade "no current certificates known for authority" message from
+ Notice to Info. Fixes bug 2899; bugfix on 0.2.0.10-alpha.
+ - Correctly describe errors that occur when generating a TLS object.
+ Previously we would attribute them to a failure while generating a
+ TLS context. Patch by Robert Ransom. Bugfix on 0.1.0.4-rc; fixes
+ bug 1994.
+ - Fix an instance where a Tor directory mirror might accidentally
+ log the IP address of a misbehaving Tor client. Bugfix on
+ 0.1.0.1-rc.
+ - Stop logging at severity 'warn' when some other Tor client tries
+ to establish a circuit with us using weak DH keys. It's a protocol
+ violation, but that doesn't mean ordinary users need to hear about
+ it. Fixes the bug part of bug 1114. Bugfix on 0.1.0.13.
+ - If your relay can't keep up with the number of incoming create
+ cells, it would log one warning per failure into your logs. Limit
+ warnings to 1 per minute. Bugfix on 0.0.2pre10; fixes bug 1042.
+
+ o Minor bugfixes (build fixes):
+ - Fix warnings from GCC 4.6's "-Wunused-but-set-variable" option.
+ - When warning about missing zlib development packages during compile,
+ give the correct package names. Bugfix on 0.2.0.1-alpha.
+ - Fix warnings that newer versions of autoconf produce during
+ ./autogen.sh. These warnings appear to be harmless in our case,
+ but they were extremely verbose. Fixes bug 2020.
+ - Squash a compile warning on OpenBSD. Reported by Tas; fixes
+ bug 1848.
+
+ o Minor bugfixes (portability):
+ - Write several files in text mode, on OSes that distinguish text
+ mode from binary mode (namely, Windows). These files are:
+ 'buffer-stats', 'dirreq-stats', and 'entry-stats' on relays
+ that collect those statistics; 'client_keys' and 'hostname' for
+ hidden services that use authentication; and (in the tor-gencert
+ utility) newly generated identity and signing keys. Previously,
+ we wouldn't specify text mode or binary mode, leading to an
+ assertion failure. Fixes bug 3607. Bugfix on 0.2.1.1-alpha (when
+ the DirRecordUsageByCountry option which would have triggered
+ the assertion failure was added), although this assertion failure
+ would have occurred in tor-gencert on Windows in 0.2.0.1-alpha.
+ - Selectively disable deprecation warnings on OS X because Lion
+ started deprecating the shipped copy of openssl. Fixes bug 3643.
+ - Use a wide type to hold sockets when built for 64-bit Windows.
+ Fixes bug 3270.
+ - Fix an issue that prevented static linking of libevent on
+ some platforms (notably Linux). Fixes bug 2698; bugfix on 0.2.1.23,
+ where we introduced the "--with-static-libevent" configure option.
+ - Fix a bug with our locking implementation on Windows that couldn't
+ correctly detect when a file was already locked. Fixes bug 2504,
+ bugfix on 0.2.1.6-alpha.
+ - Build correctly on OSX with zlib 1.2.4 and higher with all warnings
+ enabled.
+ - Fix IPv6-related connect() failures on some platforms (BSD, OS X).
+ Bugfix on 0.2.0.3-alpha; fixes first part of bug 2660. Patch by
+ "piebeer".
+
+ o Minor bugfixes (code correctness):
+ - Always NUL-terminate the sun_path field of a sockaddr_un before
+ passing it to the kernel. (Not a security issue: kernels are
+ smart enough to reject bad sockaddr_uns.) Found by Coverity;
+ CID #428. Bugfix on Tor 0.2.0.3-alpha.
+ - Make connection_printf_to_buf()'s behaviour sane. Its callers
+ expect it to emit a CRLF iff the format string ends with CRLF;
+ it actually emitted a CRLF iff (a) the format string ended with
+ CRLF or (b) the resulting string was over 1023 characters long or
+ (c) the format string did not end with CRLF *and* the resulting
+ string was 1021 characters long or longer. Bugfix on 0.1.1.9-alpha;
+ fixes part of bug 3407.
+ - Make send_control_event_impl()'s behaviour sane. Its callers
+ expect it to always emit a CRLF at the end of the string; it
+ might have emitted extra control characters as well. Bugfix on
+ 0.1.1.9-alpha; fixes another part of bug 3407.
+ - Make crypto_rand_int() check the value of its input correctly.
+ Previously, it accepted values up to UINT_MAX, but could return a
+ negative number if given a value above INT_MAX+1. Found by George
+ Kadianakis. Fixes bug 3306; bugfix on 0.2.2pre14.
+ - Fix a potential null-pointer dereference while computing a
+ consensus. Bugfix on tor-0.2.0.3-alpha, found with the help of
+ clang's analyzer.
+ - If we fail to compute the identity digest of a v3 legacy keypair,
+ warn, and don't use a buffer-full of junk instead. Bugfix on
+ 0.2.1.1-alpha; fixes bug 3106.
+ - Resolve an untriggerable issue in smartlist_string_num_isin(),
+ where if the function had ever in the future been used to check
+ for the presence of a too-large number, it would have given an
+ incorrect result. (Fortunately, we only used it for 16-bit
+ values.) Fixes bug 3175; bugfix on 0.1.0.1-rc.
+ - Be more careful about reporting the correct error from a failed
+ connect() system call. Under some circumstances, it was possible to
+ look at an incorrect value for errno when sending the end reason.
+ Bugfix on 0.1.0.1-rc.
+ - Correctly handle an "impossible" overflow cases in connection byte
+ counting, where we write or read more than 4GB on an edge connection
+ in a single second. Bugfix on 0.1.2.8-beta.
+ - Avoid a double mark-for-free warning when failing to attach a
+ transparent proxy connection. Bugfix on 0.1.2.1-alpha. Fixes
+ bug 2279.
+ - Correctly detect failure to allocate an OpenSSL BIO. Fixes bug 2378;
+ found by "cypherpunks". This bug was introduced before the first
+ Tor release, in svn commit r110.
+ - Fix a bug in bandwidth history state parsing that could have been
+ triggered if a future version of Tor ever changed the timing
+ granularity at which bandwidth history is measured. Bugfix on
+ Tor 0.1.1.11-alpha.
+ - Add assertions to check for overflow in arguments to
+ base32_encode() and base32_decode(); fix a signed-unsigned
+ comparison there too. These bugs are not actually reachable in Tor,
+ but it's good to prevent future errors too. Found by doorss.
+ - Avoid a bogus overlapped memcpy in tor_addr_copy(). Reported by
+ "memcpyfail".
+ - Set target port in get_interface_address6() correctly. Bugfix
+ on 0.1.1.4-alpha and 0.2.0.3-alpha; fixes second part of bug 2660.
+ - Fix an impossible-to-actually-trigger buffer overflow in relay
+ descriptor generation. Bugfix on 0.1.0.15.
+ - Fix numerous small code-flaws found by Coverity Scan Rung 3.
+
+ o Minor bugfixes (code improvements):
+ - After we free an internal connection structure, overwrite it
+ with a different memory value than we use for overwriting a freed
+ internal circuit structure. Should help with debugging. Suggested
+ by bug 1055.
+ - If OpenSSL fails to make a duplicate of a private or public key, log
+ an error message and try to exit cleanly. May help with debugging
+ if bug 1209 ever remanifests.
+ - Some options used different conventions for uppercasing of acronyms
+ when comparing manpage and source. Fix those in favor of the
+ manpage, as it makes sense to capitalize acronyms.
+ - Take a first step towards making or.h smaller by splitting out
+ function definitions for all source files in src/or/. Leave
+ structures and defines in or.h for now.
+ - Remove a few dead assignments during router parsing. Found by
+ coverity.
+ - Don't use 1-bit wide signed bit fields. Found by coverity.
+ - Avoid signed/unsigned comparisons by making SIZE_T_CEILING unsigned.
+ None of the cases where we did this before were wrong, but by making
+ this change we avoid warnings. Fixes bug 2475; bugfix on 0.2.1.28.
+ - The memarea code now uses a sentinel value at the end of each area
+ to make sure nothing writes beyond the end of an area. This might
+ help debug some conceivable causes of bug 930.
+ - Always treat failure to allocate an RSA key as an unrecoverable
+ allocation error.
+ - Add some more defensive programming for architectures that can't
+ handle unaligned integer accesses. We don't know of any actual bugs
+ right now, but that's the best time to fix them. Fixes bug 1943.
+
+ o Minor bugfixes (misc):
+ - Fix a rare bug in rend_fn unit tests: we would fail a test when
+ a randomly generated port is 0. Diagnosed by Matt Edman. Bugfix
+ on 0.2.0.10-alpha; fixes bug 1808.
+ - Where available, use Libevent 2.0's periodic timers so that our
+ once-per-second cleanup code gets called even more closely to
+ once per second than it would otherwise. Fixes bug 943.
+ - Ignore OutboundBindAddress when connecting to localhost.
+ Connections to localhost need to come _from_ localhost, or else
+ local servers (like DNS and outgoing HTTP/SOCKS proxies) will often
+ refuse to listen.
+ - Update our OpenSSL 0.9.8l fix so that it works with OpenSSL 0.9.8m
+ too.
+ - If any of the v3 certs we download are unparseable, we should
+ actually notice the failure so we don't retry indefinitely. Bugfix
+ on 0.2.0.x; reported by "rotator".
+ - When Tor fails to parse a descriptor of any kind, dump it to disk.
+ Might help diagnosing bug 1051.
+ - Make our 'torify' script more portable; if we have only one of
+ 'torsocks' or 'tsocks' installed, don't complain to the user;
+ and explain our warning about tsocks better.
+ - Fix some urls in the exit notice file and make it XHTML1.1 strict
+ compliant. Based on a patch from Christian Kujau.
+
+ o Documentation changes:
+ - Modernize the doxygen configuration file slightly. Fixes bug 2707.
+ - Resolve all doxygen warnings except those for missing documentation.
+ Fixes bug 2705.
+ - Add doxygen documentation for more functions, fields, and types.
+ - Convert the HACKING file to asciidoc, and add a few new sections
+ to it, explaining how we use Git, how we make changelogs, and
+ what should go in a patch.
+ - Document the default socks host and port (127.0.0.1:9050) for
+ tor-resolve.
+ - Removed some unnecessary files from the source distribution. The
+ AUTHORS file has now been merged into the people page on the
+ website. The roadmaps and design doc can now be found in the
+ projects directory in svn.
+
+ o Deprecated and removed features (config):
+ - Remove the torrc.complete file. It hasn't been kept up to date
+ and users will have better luck checking out the manpage.
+ - Remove the HSAuthorityRecordStats option that version 0 hidden
+ service authorities could use to track statistics of overall v0
+ hidden service usage.
+ - Remove the obsolete "NoPublish" option; it has been flagged
+ as obsolete and has produced a warning since 0.1.1.18-rc.
+ - Caches no longer download and serve v2 networkstatus documents
+ unless FetchV2Networkstatus flag is set: these documents haven't
+ haven't been used by clients or relays since 0.2.0.x. Resolves
+ bug 3022.
+
+ o Deprecated and removed features (controller):
+ - The controller no longer accepts the old obsolete "addr-mappings/"
+ or "unregistered-servers-" GETINFO values.
+ - The EXTENDED_EVENTS and VERBOSE_NAMES controller features are now
+ always on; using them is necessary for correct forward-compatible
+ controllers.
+
+ o Deprecated and removed features (misc):
+ - Hidden services no longer publish version 0 descriptors, and clients
+ do not request or use version 0 descriptors. However, the old hidden
+ service authorities still accept and serve version 0 descriptors
+ when contacted by older hidden services/clients.
+ - Remove undocumented option "-F" from tor-resolve: it hasn't done
+ anything since 0.2.1.16-rc.
+ - Remove everything related to building the expert bundle for OS X.
+ It has confused many users, doesn't work right on OS X 10.6,
+ and is hard to get rid of once installed. Resolves bug 1274.
+ - Remove support for .noconnect style addresses. Nobody was using
+ them, and they provided another avenue for detecting Tor users
+ via application-level web tricks.
+ - When we fixed bug 1038 we had to put in a restriction not to send
+ RELAY_EARLY cells on rend circuits. This was necessary as long
+ as relays using Tor 0.2.1.3-alpha through 0.2.1.18-alpha were
+ active. Now remove this obsolete check. Resolves bug 2081.
+ - Remove workaround code to handle directory responses from servers
+ that had bug 539 (they would send HTTP status 503 responses _and_
+ send a body too). Since only server versions before
+ 0.2.0.16-alpha/0.1.2.19 were affected, there is no longer reason to
+ keep the workaround in place.
+ - Remove the old 'fuzzy time' logic. It was supposed to be used for
+ handling calculations where we have a known amount of clock skew and
+ an allowed amount of unknown skew. But we only used it in three
+ places, and we never adjusted the known/unknown skew values. This is
+ still something we might want to do someday, but if we do, we'll
+ want to do it differently.
+ - Remove the "--enable-iphone" option to ./configure. According to
+ reports from Marco Bonetti, Tor builds fine without any special
+ tweaking on recent iPhone SDK versions.
+
+
Changes in version 0.2.1.30 - 2011-02-23
Tor 0.2.1.30 fixes a variety of less critical bugs. The main other
change is a slight tweak to Tor's TLS handshake that makes relays
@@ -1972,6 +3241,8 @@ Changes in version 0.2.0.30 - 2008-07-15
warning "-Wshorten-64-to-32" is available.
- Support compilation to target iPhone; patch from cjacker huang.
To build for iPhone, pass the --enable-iphone option to configure.
+ - Port Tor to build and run correctly on Windows CE systems, using
+ the wcecompat library. Contributed by Valerio Lupi.
- Detect non-ASCII platforms (if any still exist) and refuse to
build there: some of our code assumes that 'A' is 65 and so on.
- Clear up some MIPSPro compiler warnings.
diff --git a/autogen.sh b/autogen.sh
index eb9395c71..0592f16c2 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,5 +1,9 @@
#!/bin/sh
+if [ -x "`which autoreconf 2>/dev/null`" ] ; then
+ exec autoreconf -ivf
+fi
+
set -e
# Run this to generate all the initial makefiles, etc.
diff --git a/changes/abandon-rend-circs-on-newnym b/changes/abandon-rend-circs-on-newnym
deleted file mode 100644
index 67cb2dce2..000000000
--- a/changes/abandon-rend-circs-on-newnym
+++ /dev/null
@@ -1,8 +0,0 @@
- o Security fixes:
- - Don't attach new streams to old rendezvous circuits after SIGNAL
- NEWNYM. Previously, we would keep using an existing rendezvous
- circuit if it remained open (i.e. if it were kept open by a
- long-lived stream or if a new stream were attached to it before
- Tor could notice that it was old and no longer in use and close
- it). Bugfix on 0.1.1.15-rc; fixes bug 3375.
-
diff --git a/changes/bug1297a b/changes/bug1297a
deleted file mode 100644
index 140b94e3b..000000000
--- a/changes/bug1297a
+++ /dev/null
@@ -1,16 +0,0 @@
- o Major bugfixes:
- - Apply circuit timeouts to opened hidden-service-related circuits
- based on the correct start time. Previously, we would apply the
- circuit build timeout based on time since the circuit's
- creation; it was supposed to be applied based on time since the
- circuit entered its current state. Bugfix on 0.0.6; fixes part
- of bug 1297.
- - Use the same circuit timeout for client-side introduction
- circuits as for other four-hop circuits. Previously,
- client-side introduction circuits were closed after the same
- timeout as single-hop directory-fetch circuits; this was
- appropriate with the static circuit build timeout in 0.2.1.x and
- earlier, but caused many hidden service access attempts to fail
- with the adaptive CBT introduced in 0.2.2.2-alpha. Bugfix on
- 0.2.2.2-alpha; fixes another part of bug 1297.
-
diff --git a/changes/bug1297b b/changes/bug1297b
new file mode 100644
index 000000000..6b0169d82
--- /dev/null
+++ b/changes/bug1297b
@@ -0,0 +1,8 @@
+ o Minor bugfixes:
+
+ - When one of a hidden service's introduction points times out,
+ consider trying it again during the next attempt to connect to
+ the HS. Previously, we would not try it again unless a newly
+ fetched descriptor contained it. Required by fixes for bugs
+ 1297 and 3825.
+
diff --git a/changes/bug1345 b/changes/bug1345
deleted file mode 100644
index 0c9375a35..000000000
--- a/changes/bug1345
+++ /dev/null
@@ -1,13 +0,0 @@
- o Minor bugfixes:
- - On SIGHUP, do not clear out all TrackHostExits mappings, client DNS
- cache entries, and virtual address mappings: that's what NEWNYM is
- for. Bugfix on Tor 0.1.0.1-rc; fixes bug 1345.
- - When TrackHostExits is changed from a controller, remove any
- mappings for hosts that should no longer have their exits tracked.
- Bugfix on Tor 0.1.0.1-rc.
- - When VirtualAddrNetwork option is changed from a controller,
- remove any mappings for hosts that were automapped to
- that network. Bugfix on 0.1.1.19-rc.
- - When one of the AutomapHosts* options is changed from a
- controller, remove any mappings for hosts that should no longer be
- automapped. Bugfix on 0.2.0.1-alpha.
diff --git a/changes/bug1352 b/changes/bug1352
deleted file mode 100644
index bde019240..000000000
--- a/changes/bug1352
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features
- - Rate-limit a warning about failures to download v2 networkstatus
- documents. Resolves part of bug 1352.
-
diff --git a/changes/bug1810 b/changes/bug1810
deleted file mode 100644
index 11e561f7c..000000000
--- a/changes/bug1810
+++ /dev/null
@@ -1,6 +0,0 @@
- o Major bugfixes:
- - Don't decide to make a new descriptor when receiving a HUP signal.
- This bug has caused a lot of relays to disappear from the consensus
- periodically. Fixes the most common case of triggering bug 1810;
- bugfix on 0.2.2.7-alpha.
-
diff --git a/changes/bug2355 b/changes/bug2355
deleted file mode 100644
index ee0ae4b96..000000000
--- a/changes/bug2355
+++ /dev/null
@@ -1,8 +0,0 @@
- o Major features:
- - If "UseBridges 1" is set and no bridges are configured, Tor will
- now refuse to build any circuits until some bridges are set.
- If "UseBridges auto" is set, Tor will use bridges if they are
- configured and we are not running as a server, but otherwise
- will make circuits as usual. The new default is "auto". Patch
- by anonym.
-
diff --git a/changes/bug2355_revert b/changes/bug2355_revert
deleted file mode 100644
index 2ded40ad8..000000000
--- a/changes/bug2355_revert
+++ /dev/null
@@ -1,7 +0,0 @@
- o Minor bugfixes:
- - Revert the UseBridges option to its behavior before 0.2.2.28-beta.
- When we changed the default behavior to "use bridges if any are
- listed in the torrc", we broke a number of users who had bridges
- in their torrc files but who didn't actually want to use them.
- Partial resolution for bug 3354.
-
diff --git a/changes/bug2430 b/changes/bug2430
new file mode 100644
index 000000000..3908856b3
--- /dev/null
+++ b/changes/bug2430
@@ -0,0 +1,4 @@
+ o Minor bugfixes:
+ - Fix a bug in configure.in that kept it from building a configure
+ script with autoconf versions earlier than 2.61. Fixes bug 2430;
+ bugfix on 0.2.3.1-alpha.
diff --git a/changes/bug2503 b/changes/bug2503
deleted file mode 100644
index 50b8bf50c..000000000
--- a/changes/bug2503
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features:
- - When an HTTPS proxy reports "403 Forbidden", we now explain
- what it means rather than calling it an unexpected status code.
- Closes bug 2503. Patch from "mikey".
diff --git a/changes/bug2574 b/changes/bug2574
deleted file mode 100644
index 5cf2daebf..000000000
--- a/changes/bug2574
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor features:
- - Allow nameservers with IPv6 address. Fixes bug 2574.
-
diff --git a/changes/bug2732-simple b/changes/bug2732-simple
deleted file mode 100644
index 367836152..000000000
--- a/changes/bug2732-simple
+++ /dev/null
@@ -1,7 +0,0 @@
- o Minor bugfixes
- - Do not reject hidden service descriptors simply because we don't
- think we have not been assigned the HSDir flag. Clients and
- hidden services can have a more up-to-date view of the network
- consensus, and if they think that the directory authorities
- list us a HSDir, we might actually be one. Related to bug 2732;
- bugfix on 0.2.0.10-alpha.
diff --git a/changes/bug2748 b/changes/bug2748
deleted file mode 100644
index b522560a9..000000000
--- a/changes/bug2748
+++ /dev/null
@@ -1,10 +0,0 @@
- o Minor bugfixes
- - Remove dead code from rend_cache_lookup_v2_desc_as_dir. Fixes
- part of bug 2748; bugfix on 0.2.0.10-alpha.
- - Log malformed requests for rendezvous descriptors as protocol
- warnings, not warnings. Also, use a more informative log
- message in case someone sees it at log level warning without
- prior info-level messages. Fixes the other part of bug 2748;
- bugfix on 0.2.0.10-alpha.
-
-
diff --git a/changes/bug2752 b/changes/bug2752
deleted file mode 100644
index b872d3374..000000000
--- a/changes/bug2752
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor features:
- - Tor used to limit HttpProxyAuthenticator values to 48 characters.
- Changed the limit to 512 characters by removing base64 newlines.
- Fixes bug 2752. Fix by Michael Yakubovich.
-
diff --git a/changes/bug2792_checkdir b/changes/bug2792_checkdir
deleted file mode 100644
index 10de1deb2..000000000
--- a/changes/bug2792_checkdir
+++ /dev/null
@@ -1,8 +0,0 @@
- o Minor features:
- - Tor now refuses to create a ControlSocket in a directory that is
- world-readable (or group-readable if ControlSocketsGroupWritable
- is 0). This is necessary because some operating systems do not
- check the permissions on an AF_UNIX socket when programs try to
- connect to it. Checking permissions on the directory holding
- the socket, however, seems to work everywhere.
-
diff --git a/changes/bug2850 b/changes/bug2850
deleted file mode 100644
index 77ccbfa25..000000000
--- a/changes/bug2850
+++ /dev/null
@@ -1,5 +0,0 @@
- - Minor features
- o Set SO_REUSEADDR on all sockets, not just listeners. This should
- help busy exit nodes avoid running out of useable ports just because
- all the ports have been used in the near past. Resolves issue 2850.
-
diff --git a/changes/bug2972 b/changes/bug2972
deleted file mode 100644
index 26afcca42..000000000
--- a/changes/bug2972
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor features:
- - Allow ControlSockets to be group-writable when the
- ControlSocksGroupWritable configuration option is turned on. Patch
- by Jérémy Bobbio; implements ticket 2972.
-
diff --git a/changes/bug3019 b/changes/bug3019
deleted file mode 100644
index 4df709fb3..000000000
--- a/changes/bug3019
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes:
- - Do not reset the bridge descriptor download status every time we
- re-parse our configuration or get a configuration change. Fixes
- bug 3019; bugfix on Tor 0.2.0.3-alpha.
diff --git a/changes/bug3022 b/changes/bug3022
deleted file mode 100644
index 9472e6d19..000000000
--- a/changes/bug3022
+++ /dev/null
@@ -1,6 +0,0 @@
- o Removed features
- - Caches no longer download and serve v2 networkstatus documents
- unless FetchV2Networkstatus flag is set: these documents haven't
- haven't been used by clients or relays since 0.2.0.x. Resolves
- bug 3022.
-
diff --git a/changes/bug3026 b/changes/bug3026
deleted file mode 100644
index c0c0a3860..000000000
--- a/changes/bug3026
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes (directory authority)
- - Do not upload our own vote or signature set to ourself. It would
- tell us nothing new. Also, as of Tor 0.2.2.24-alpha, we started
- to warn about receiving duplicate votes. Resolves bug 3026.
diff --git a/changes/bug3045 b/changes/bug3045
deleted file mode 100644
index 1cbcabaff..000000000
--- a/changes/bug3045
+++ /dev/null
@@ -1,6 +0,0 @@
- o Minor features:
- - Revise most log messages that refer to nodes by nickname to
- instead use the "$key=nickname at address" format. This should be
- more useful, especially since nicknames are less and less likely
- to be unique. Fixes bug 3045.
-
diff --git a/changes/bug3122_memcmp b/changes/bug3122_memcmp
deleted file mode 100644
index a04947674..000000000
--- a/changes/bug3122_memcmp
+++ /dev/null
@@ -1,7 +0,0 @@
- o Security fixes
- - Replace all potentially sensitive memory comparison operations
- with versions whose runtime does not depend on the data being
- compared. This will help resist a class of attacks where an
- adversary can use variations in timing information to learn
- sensitive data. Fix for one case of bug 3122. (Safe memcmp
- implementation by Robert Ransom based partially on code by DJB.)
diff --git a/changes/bug3135 b/changes/bug3135
deleted file mode 100644
index d76112348..000000000
--- a/changes/bug3135
+++ /dev/null
@@ -1,6 +0,0 @@
- o Minor bugfixes
- - Do not crash when our configuration file becomes unreadable
- (usually due to a permissions change) between when we start
- up and when a controller calls SAVECONF. Fixes bug 3135;
- bugfix on 0.0.9pre6.
-
diff --git a/changes/bug3175 b/changes/bug3175
deleted file mode 100644
index 3360fbce0..000000000
--- a/changes/bug3175
+++ /dev/null
@@ -1,7 +0,0 @@
- o Minor bugfixes:
- - Resolve an untriggerable issue in smartlist_string_num_isin(),
- where if the function had ever in the future been used to check
- for the presence of a too-large number, it would have given an
- incorrect result. (Fortunately, we only used it for 16-bit
- values.) Fixes bug 3175; bugfix on Tor 0.1.0.1-rc.
-
diff --git a/changes/bug3198 b/changes/bug3198
deleted file mode 100644
index 29c16852e..000000000
--- a/changes/bug3198
+++ /dev/null
@@ -1,4 +0,0 @@
- o Major bugfixes:
- - When we configure a new bridge via the controller, don't wait up
- to ten seconds before trying to fetch its descriptor. Bugfix on
- 0.2.0.3-alpha; fixes bug 3198 (suggested by 2355).
diff --git a/changes/bug3200 b/changes/bug3200
deleted file mode 100644
index a80d51633..000000000
--- a/changes/bug3200
+++ /dev/null
@@ -1,6 +0,0 @@
- o Minor bugfixes:
- - When a client starts or stops using bridges, never use a circuit
- that was built before the configuration change. This behavior could
- put at risk a user who uses bridges to ensure that her traffic
- only goes to the chosen addresses. Bugfix on 0.2.0.3-alpha; fixes
- bug 3200.
diff --git a/changes/bug3207 b/changes/bug3207
deleted file mode 100644
index 65a7dac1a..000000000
--- a/changes/bug3207
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes:
- - Require that onion keys have exponent 65537 in microdescriptors too.
- Fixes part of bug 3207; bugfix on 0.2.2.25-alpha
-
diff --git a/changes/bug3208 b/changes/bug3208
deleted file mode 100644
index fd737ba69..000000000
--- a/changes/bug3208
+++ /dev/null
@@ -1,6 +0,0 @@
- o Removed options:
- - Remove undocumented option "-F" from tor-resolve: it hasn't done
- anything since 0.2.1.16-rc.
-
- o Minor bugfixes:
- - Fix warnings from GCC 4.6's "-Wunused-but-set-variable" option.
diff --git a/changes/bug3213 b/changes/bug3213
deleted file mode 100644
index ab7de2d62..000000000
--- a/changes/bug3213
+++ /dev/null
@@ -1,4 +0,0 @@
- o Major bugfixes:
- - Fix a crash bug when changing bridges in a running Tor process.
- Fixes bug 3213; bugfix on 0.2.2.26-beta.
-
diff --git a/changes/bug3216 b/changes/bug3216
deleted file mode 100644
index 599b5e162..000000000
--- a/changes/bug3216
+++ /dev/null
@@ -1,4 +0,0 @@
- o Major bugfixes:
- - Don't try to build descriptors if "ORPort auto" is set and we
- don't know our actual ORPort yet. Fix for bug 3216; bugfix on
- 0.2.2.26-beta.
diff --git a/changes/bug3228 b/changes/bug3228
deleted file mode 100644
index 4aca810d3..000000000
--- a/changes/bug3228
+++ /dev/null
@@ -1,3 +0,0 @@
- o Major bugfixes:
- - Resolve a crash that occured when setting BridgeRelay to 1 with
- accounting enabled. Fixes bug 3228; bugfix on 0.2.2.18-alpha.
diff --git a/changes/bug3252 b/changes/bug3252
deleted file mode 100644
index f85f633fb..000000000
--- a/changes/bug3252
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor features:
- - Relays now log the reason for publishing a new relay descriptor,
- so we have a better chance of hunting down the root cause of bug
- 1810. Resolves ticket 3252.
diff --git a/changes/bug3270 b/changes/bug3270
deleted file mode 100644
index b37bb983c..000000000
--- a/changes/bug3270
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes
- - Use a wide type to hold sockets when built for 64-bit Windows builds.
- Fixes bug 3270.
-
diff --git a/changes/bug3289 b/changes/bug3289
deleted file mode 100644
index c469796d6..000000000
--- a/changes/bug3289
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes:
- - Warn when the user configures two HiddenServiceDir lines that point
- to the same directory. Bugfix on 0.0.6 (the version introducing
- HiddenServiceDir); fixes bug 3289.
-
diff --git a/changes/bug3306 b/changes/bug3306
deleted file mode 100644
index f868a24af..000000000
--- a/changes/bug3306
+++ /dev/null
@@ -1,9 +0,0 @@
- o Minor bugfixes:
- - Make our crypto_rand_int() function check the value of its input
- correctly. Previously, it accepted values up to UINT_MAX, but
- could return a negative number if given a value above INT_MAX+1.
- Found by George Kadianakis. Fixes bug 3306; bugfix on 0.2.2pre14.
-
- - Avoid a segfault when reading a malformed circuit build state
- with more than INT_MAX entries. Found by wanoskarnet. Bugfix on
- 0.2.2.4-alpha.
diff --git a/changes/bug3309 b/changes/bug3309
deleted file mode 100644
index 104056d8e..000000000
--- a/changes/bug3309
+++ /dev/null
@@ -1,13 +0,0 @@
- o Minor bugfixes:
- - Clear the table recording the time of the last request for each
- hidden service descriptor from each HS directory on SIGNAL
- NEWNYM. Previously, we would clear our HS descriptor cache on
- SIGNAL NEWNYM, but if we had previously retrieved a descriptor
- (or tried to) from every directory responsible for it, we would
- refuse to fetch it again for up to 15 minutes. Bugfix on
- 0.2.2.25-alpha; fixes bug 3309.
-
- o Minor features:
- - Log (at info level) when purging pieces of hidden-service-client
- state on SIGNAL NEWNYM.
-
diff --git a/changes/bug3318 b/changes/bug3318
deleted file mode 100644
index 8a3c27825..000000000
--- a/changes/bug3318
+++ /dev/null
@@ -1,7 +0,0 @@
- o Minor bugfixes:
- - Fix a log message that said "bits" while displaying a value in
- bytes. Found by wanoskarnet. Fixes bug 3318; bugfix on
- 0.2.0.1-alpha.
- - When checking for 1024-bit keys, check for 1024 bits, not 128
- bytes. This allows Tor to correctly discard keys of length
- 1017 through 1023. Bugfix on 0.0.9pre5.
diff --git a/changes/bug3321 b/changes/bug3321
deleted file mode 100644
index 3605efce2..000000000
--- a/changes/bug3321
+++ /dev/null
@@ -1,7 +0,0 @@
- o Minor bugfixes:
- - In bug 2511 we fixed a case where you could use an unconfigured
- bridge if you had configured it as a bridge the last time you ran
- Tor. Now fix another edge case: if you had configured it as a bridge
- but then switched to a different bridge via the controller, you
- would still be willing to use the old one. Bugfix on 0.2.0.1-alpha;
- fixes bug 3321.
diff --git a/changes/bug3335 b/changes/bug3335
new file mode 100644
index 000000000..7e1e89866
--- /dev/null
+++ b/changes/bug3335
@@ -0,0 +1,11 @@
+ o Major bugfixes:
+
+ - When an attempt to connect to a hidden service ends, consider
+ refetching its hidden service descriptors from each of the HSDir
+ relays responsible for them immediately. Previously, we would
+ not consider refetching the service's descriptors from each
+ HSDir for 15 minutes after the last fetch; this behaviour was
+ inconvenient if the hidden service was not running during the
+ first attempt, for example. Bugfix on 0.2.0.18-alpha; fixes bug
+ 3335.
+
diff --git a/changes/bug3369 b/changes/bug3369
deleted file mode 100644
index 9c0d0e699..000000000
--- a/changes/bug3369
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes:
- - When asked about a DNS record type we don't support via a
- client DNSPort, reply with NOTIMPL rather than an empty
- reply. Patch by intrigeri. Fixes bug 3369; bugfix on 2.0.1-alpha.
diff --git a/changes/bug3393 b/changes/bug3393
deleted file mode 100644
index 677bcb7be..000000000
--- a/changes/bug3393
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes:
- - Fix a bug when using ControlSocketsGroupWritable with User. The
- directory's group would be checked against the current group, not
- the configured group. Patch by Jérémy Bobbio. Fixes bug3393; bugfix
- on Tor 0.2.2.26-beta. \ No newline at end of file
diff --git a/changes/bug3465-022 b/changes/bug3465-022
deleted file mode 100644
index 2d226162a..000000000
--- a/changes/bug3465-022
+++ /dev/null
@@ -1,6 +0,0 @@
- o Minor bugfixes:
-
- - Add BUILDTIMEOUT_SET to the list returned by the 'GETINFO
- events/names' control-port command. Bugfix on 0.2.2.9-alpha;
- fixes part of bug 3465.
-
diff --git a/changes/bug3536 b/changes/bug3536
deleted file mode 100644
index d3cec131b..000000000
--- a/changes/bug3536
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes:
- - Send a SUCCEEDED stream event to the controller when a reverse
- resolve succeeded. Fixes bug 3536; bugfix on 0.0.8pre1. Issue
- discovered by katmagic.
-
diff --git a/changes/bug3577 b/changes/bug3577
deleted file mode 100644
index 633527275..000000000
--- a/changes/bug3577
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes:
- - Allow GETINFO fingerprint to return a fingerprint even when
- we have not yet built a router descriptor. Fixes bug 3577;
- bugfix on 0.2.0.1-alpha.
diff --git a/changes/bug3607 b/changes/bug3607
deleted file mode 100644
index 5ece21934..000000000
--- a/changes/bug3607
+++ /dev/null
@@ -1,15 +0,0 @@
- o Minor bugfixes:
-
- - Write several files in text mode, on OSes that distinguish text
- mode from binary mode (namely, Windows). These files are:
- buffer-stats, dirreq-stats, and entry-stats on relays that collect
- those statistics; client_keys and hostname files for hidden
- services that use authentication; and (in the tor-gencert utility)
- newly generated identity and signing keys. Previously, we
- wouldn't specify text mode or binary mode, leading to an assertion
- failure. Fixes bug 3607. Bugfix on 0.2.1.1-alpha (when the
- DirRecordUsageByCountry option which would have triggered the
- assertion failure was added), although this assertion failure
- would have occurred in tor-gencert on Windows in 0.2.0.1-alpha.
-
-
diff --git a/changes/bug3643 b/changes/bug3643
deleted file mode 100644
index 86bd920ca..000000000
--- a/changes/bug3643
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes:
- - Selectively disable deprecation warnings on OS X because Lion started
- deprecating the shipped copy of openssl. Fixes bug 3643.
-
diff --git a/changes/bug3732 b/changes/bug3732
deleted file mode 100644
index 7a71d1aef..000000000
--- a/changes/bug3732
+++ /dev/null
@@ -1,7 +0,0 @@
- o Major bugfixes:
-
- - Remove an extra pair of quotation marks around the error
- message in control-port STATUS_GENERAL BUG events. Bugfix on
- 0.1.2.6-alpha; fixes bug 3732.
-
-
diff --git a/changes/bug3747 b/changes/bug3747
deleted file mode 100644
index 052dab1bd..000000000
--- a/changes/bug3747
+++ /dev/null
@@ -1,6 +0,0 @@
- o Major bugfixes:
- - Write control ports to disk only after switching UID and
- creating the data directory. This way, we don't fail when
- starting up with a nonexistant DataDirectory and a
- ControlPortWriteToFile setting based on that directory. Fixes
- bug 3747; bugfix on Tor 0.2.2.26-beta. \ No newline at end of file
diff --git a/changes/bug3825a b/changes/bug3825a
new file mode 100644
index 000000000..6606e36ef
--- /dev/null
+++ b/changes/bug3825a
@@ -0,0 +1,8 @@
+ o Major bugfixes:
+
+ - When one of a hidden service's introduction points appears to be
+ unreachable, stop trying it. Previously, we would keep trying
+ to build circuits to the introduction point until we lost the
+ descriptor, usually because the user gave up and restarted Tor.
+ Partly fixes bug 3825.
+
diff --git a/changes/bug4094 b/changes/bug4094
new file mode 100644
index 000000000..9c40d41db
--- /dev/null
+++ b/changes/bug4094
@@ -0,0 +1,3 @@
+ o Minor bugfixes:
+ - Rephrase the log message emitted if the TestSocks check is
+ successful. Patch from Fabian Keil; fixes bug 4094.
diff --git a/changes/bug4201 b/changes/bug4201
new file mode 100644
index 000000000..6f7d715af
--- /dev/null
+++ b/changes/bug4201
@@ -0,0 +1,5 @@
+ o Minor bugfixes:
+ - Bridges now skip DNS self-tests, to act a little more stealthily.
+ Fixes bug 4201; bugfix on 0.2.0.3-alpha, which first introduced
+ bridges. Patch by "warms0x".
+
diff --git a/changes/check-fetched-rend-desc-service-id b/changes/check-fetched-rend-desc-service-id
deleted file mode 100644
index 2f37c3021..000000000
--- a/changes/check-fetched-rend-desc-service-id
+++ /dev/null
@@ -1,7 +0,0 @@
- o Security fixes:
- - When fetching a hidden service descriptor, check that it is for
- the hidden service we were trying to connect to, in order to
- stop a directory from pre-seeding a client with a descriptor for
- a hidden service that they didn't want. Bugfix on 0.0.6.
-
-
diff --git a/changes/check-public-key-exponents b/changes/check-public-key-exponents
deleted file mode 100644
index a8d00673b..000000000
--- a/changes/check-public-key-exponents
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes:
- - Require that introduction point keys and onion keys have public
- exponent 65537. Bugfix on 0.2.0.10-alpha.
-
-
diff --git a/changes/cid_428 b/changes/cid_428
deleted file mode 100644
index cb0fc8c2b..000000000
--- a/changes/cid_428
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes:
- - Always NUL-terminate the sun_path field of a sockaddr_un before
- passing it to the kernel. (Not a security issue: kernels are
- smart enough to reject bad sockaddr_uns.) Found by Coverity; CID
- # 428. Bugfix on Tor 0.2.0.3-alpha.
diff --git a/changes/cid_450 b/changes/cid_450
deleted file mode 100644
index 2045fca23..000000000
--- a/changes/cid_450
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes:
- - Don't stack-allocate the list of supplementary GIDs when we're
- about to log them. Stack-allocating NGROUPS_MAX gid_t elements
- could take up to 256K, which is way too much stack. Found by
- Coverity; CID #450. Bugfix on 0.2.1.7-alpha.
diff --git a/changes/coverity_maint b/changes/coverity_maint
deleted file mode 100644
index e7be90a48..000000000
--- a/changes/coverity_maint
+++ /dev/null
@@ -1,9 +0,0 @@
- o Code simplifications and refactoring:
- - Remove some dead code as indicated by coverity.
- - Remove a few dead assignments during router parsing. Found by coverity.
- o Minor bugfixes:
- - Add some forgotten return value checks during unit tests. Found
- by coverity.
- - Don't use 1-bit wide signed bit fields. Found by coverity.
- - Fix a rare memory leak during stats writing. Found by coverity.
-
diff --git a/changes/dirvote_null_deref b/changes/dirvote_null_deref
deleted file mode 100644
index 65dc519f5..000000000
--- a/changes/dirvote_null_deref
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes:
- - Fix a potential null-pointer dereference while computing a consensus.
- Bugfix on tor-0.2.0.3-alpha, found with the help of clang's analyzer.
-
diff --git a/changes/dont-warn-about-rfc1918-socksport-addrs b/changes/dont-warn-about-rfc1918-socksport-addrs
new file mode 100644
index 000000000..94825994c
--- /dev/null
+++ b/changes/dont-warn-about-rfc1918-socksport-addrs
@@ -0,0 +1,7 @@
+ o Minor bugfixes:
+
+ - Don't warn users that they are exposing a client port to the
+ Internet if they have specified an RFC1918 address. Previously,
+ we would warn if the user had specified any non-loopback
+ address. Bugfix on 0.2.3.3-alpha. Fixes bug 4018; reported by Tas.
+
diff --git a/changes/exit-policy-default-is-not-a-prefix b/changes/exit-policy-default-is-not-a-prefix
deleted file mode 100644
index 6eb1e8df9..000000000
--- a/changes/exit-policy-default-is-not-a-prefix
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes:
- - Remove a trailing asterisk from "exit-policy/default" in the
- output of the control port command "GETINFO info/names". Bugfix
- on 0.1.2.5-alpha.
-
diff --git a/changes/feature3049 b/changes/feature3049
deleted file mode 100644
index 7960a1f47..000000000
--- a/changes/feature3049
+++ /dev/null
@@ -1,6 +0,0 @@
- o Major features:
- - Add an __OwningControllerProcess configuration option and a
- TAKEOWNERSHIP control-port command, so that a Tor controller can
- ensure that when it exits, Tor will shut down. Implements
- feature 3049.
-
diff --git a/changes/feature3076 b/changes/feature3076
deleted file mode 100644
index a3dcec874..000000000
--- a/changes/feature3076
+++ /dev/null
@@ -1,14 +0,0 @@
- o Minor features
- - The options SocksPort, ControlPort, and so on now all accept an
- optional value "auto" that opens a socket on an OS-selected port.
- o Minor features (controller)
- - GETINFO net/listeners/(type) now returns a list of the addresses
- and ports that are bound for listeners for a given connection
- type. This is useful for if the user has selected SocksPort
- "auto", and you need to know which port got chosen.
- - There is a ControlPortWriteToFile option that tells Tor to write
- its actual control port or ports to a chosen file. If the option
- ControlPortFileGroupReadable is set, the file is created as
- group-readable.
-
-
diff --git a/changes/fix-connection_printf_to_buf b/changes/fix-connection_printf_to_buf
deleted file mode 100644
index e191eac8a..000000000
--- a/changes/fix-connection_printf_to_buf
+++ /dev/null
@@ -1,15 +0,0 @@
- * Code simplifications and refactoring:
-
- - Make connection_printf_to_buf's behaviour sane. Its callers
- expect it to emit a CRLF iff the format string ends with CRLF;
- it actually emits a CRLF iff (a) the format string ends with
- CRLF or (b) the resulting string is over 1023 characters long or
- (c) the format string does not end with CRLF ''and'' the
- resulting string is 1021 characters long or longer. Bugfix on
- 0.1.1.9-alpha; fixes part of bug 3407.
-
- - Make send_control_event_impl's behaviour sane. Its callers
- expect it to always emit a CRLF at the end of the string; it
- might emit extra control characters as well. Bugfix on
- 0.1.1.9-alpha; fixes another part of bug 3407.
-
diff --git a/changes/fmt_addr b/changes/fmt_addr
deleted file mode 100644
index b88c9e1bf..000000000
--- a/changes/fmt_addr
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes:
- - When unable to format an address as a string, report its value
- as "???" rather than reusing the last formatted address. Bugfix
- on 0.2.1.5-alpha.
diff --git a/changes/geoip-august2011 b/changes/geoip-august2011
deleted file mode 100644
index 6de8b0f29..000000000
--- a/changes/geoip-august2011
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor features:
- - Update to the August 2 2011 Maxmind GeoLite Country database.
-
diff --git a/changes/geoip-july2011 b/changes/geoip-july2011
deleted file mode 100644
index 7a9f119be..000000000
--- a/changes/geoip-july2011
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor features:
- - Update to the July 1 2011 Maxmind GeoLite Country database.
-
diff --git a/changes/geoip-june2011 b/changes/geoip-june2011
deleted file mode 100644
index 8cf011b72..000000000
--- a/changes/geoip-june2011
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor features:
- - Update to the June 1 2011 Maxmind GeoLite Country database.
-
diff --git a/changes/geoip-may2011 b/changes/geoip-may2011
deleted file mode 100644
index c908f24b4..000000000
--- a/changes/geoip-may2011
+++ /dev/null
@@ -1,3 +0,0 @@
- o Minor features:
- - Update to the May 1 2011 Maxmind GeoLite Country database.
-
diff --git a/changes/md_cache_replace b/changes/md_cache_replace
deleted file mode 100644
index 88e029c00..000000000
--- a/changes/md_cache_replace
+++ /dev/null
@@ -1,6 +0,0 @@
- o Minor bugfixes
- - Avoid a bug that would keep us from replacing a microdescriptor
- cache on Windows. (We would try to replace the file while still
- holding it open. That's fine on Unix, but Windows doesn't let us
- do that.) Bugfix on 0.2.2.6-alpha; bug found by wanoskarnet.
-
diff --git a/changes/mdesc_null_deref b/changes/mdesc_null_deref
deleted file mode 100644
index 30f028053..000000000
--- a/changes/mdesc_null_deref
+++ /dev/null
@@ -1,5 +0,0 @@
- o Minor bugfixes:
- - Avoid a possible null-pointer dereference when rebuilding the mdesc
- cache without actually having any descriptors to cache. Bugfix on
- 0.2.2.6-alpha. Issue discovered using clang's static analyzer.
-
diff --git a/changes/memleak_rendcache b/changes/memleak_rendcache
deleted file mode 100644
index 93b1f6141..000000000
--- a/changes/memleak_rendcache
+++ /dev/null
@@ -1,4 +0,0 @@
- o Minor bugfixes:
- - Fix a memory leak when receiving a descriptor for a hidden
- service we didn't ask for. Found by Coverity; CID#30. Bugfix on
- 0.2.2.26-beta.
diff --git a/changes/msvc_lround b/changes/msvc_lround
deleted file mode 100644
index e4aea9535..000000000
--- a/changes/msvc_lround
+++ /dev/null
@@ -1,4 +0,0 @@
- o Build fixes:
- - Provide a substitute implementation of lround() for MSVC, which
- apparently lacks it. Patch from Gisle Vanem.
-
diff --git a/changes/windows_8 b/changes/windows_8
new file mode 100644
index 000000000..405e4fa15
--- /dev/null
+++ b/changes/windows_8
@@ -0,0 +1,5 @@
+ o Minor bugfixes:
+ - The next version of Windows will be called Windows 8, and it has a major
+ version of 6, minor version of 2. Correctly identify that version instead
+ of calling it "Very recent version". Fixes bug 4153; reported by funkstar.
+
diff --git a/configure.in b/configure.in
index 4e8429845..d86109360 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.2.19-alpha)
+AM_INIT_AUTOMAKE(tor, 0.2.3.5-alpha)
AM_CONFIG_HEADER(orconfig.h)
AC_CANONICAL_HOST
@@ -32,6 +32,15 @@ AC_ARG_ENABLE(static-libevent,
AS_HELP_STRING(--enable-static-libevent, Link against a static libevent library. Requires --with-libevent-dir))
AC_ARG_ENABLE(static-zlib,
AS_HELP_STRING(--enable-static-zlib, Link against a static zlib library. Requires --with-zlib-dir))
+AC_ARG_ENABLE(static-tor,
+ AS_HELP_STRING(--enable-static-tor, Create an entirely static Tor binary. Requires --with-openssl-dir and --with-libevent-dir and --with-zlib-dir))
+
+if test "$enable_static_tor" = "yes"; then
+ enable_static_libevent="yes";
+ enable_static_openssl="yes";
+ enable_static_zlib="yes";
+ CFLAGS="$CFLAGS -static"
+fi
if test x$enable_buf_freelists != xno; then
AC_DEFINE(ENABLE_BUF_FREELISTS, 1,
@@ -59,6 +68,24 @@ AC_ARG_ENABLE(asciidoc,
*) AC_MSG_ERROR(bad value for --disable-asciidoc) ;;
esac], [asciidoc=true])
+# By default, we're not ready to ship a NAT-PMP aware Tor
+AC_ARG_ENABLE(nat-pmp,
+ AS_HELP_STRING(--enable-nat-pmp, enable NAT-PMP support),
+ [case "${enableval}" in
+ yes) natpmp=true ;;
+ no) natpmp=false ;;
+ * ) AC_MSG_ERROR(bad value for --enable-nat-pmp) ;;
+ esac], [natpmp=false])
+
+# By default, we're not ready to ship a UPnP aware Tor
+AC_ARG_ENABLE(upnp,
+ AS_HELP_STRING(--enable-upnp, enable UPnP support),
+ [case "${enableval}" in
+ yes) upnp=true ;;
+ no) upnp=false ;;
+ * ) AC_MSG_ERROR(bad value for --enable-upnp) ;;
+ esac], [upnp=false])
+
AC_ARG_ENABLE(threads,
AS_HELP_STRING(--disable-threads, disable multi-threading support))
@@ -118,6 +145,15 @@ if test "$enable_local_appdata" = "yes"; then
[Defined if we default to host local appdata paths on Windows])
fi
+AC_ARG_ENABLE(bufferevents,
+ AS_HELP_STRING(--enable-bufferevents, use Libevent's buffered IO.))
+
+dnl check for the correct "ar" when cross-compiling
+AN_MAKEVAR([AR], [AC_PROG_AR])
+AN_PROGRAM([ar], [AC_PROG_AR])
+AC_DEFUN([AC_PROG_AR], [AC_CHECK_TOOL([AR], [ar], [ar])])
+AC_PROG_AR
+
AC_PROG_CC
AC_PROG_CPP
AC_PROG_MAKE_SET
@@ -132,6 +168,33 @@ AC_PATH_PROG([A2X], [a2x], none)
AM_CONDITIONAL(USE_ASCIIDOC, test x$asciidoc = xtrue)
+AM_CONDITIONAL(USE_FW_HELPER, test x$natpmp = xtrue || test x$upnp = xtrue)
+AM_CONDITIONAL(NAT_PMP, test x$natpmp = xtrue)
+AM_CONDITIONAL(MINIUPNPC, test x$upnp = xtrue)
+AM_PROG_CC_C_O
+
+ifdef([AC_C_FLEXIBLE_ARRAY_MEMBER], [
+AC_C_FLEXIBLE_ARRAY_MEMBER
+], [
+ dnl Maybe we've got an old autoconf...
+ AC_CACHE_CHECK([for flexible array members],
+ tor_cv_c_flexarray,
+ [AC_COMPILE_IFELSE(
+ AC_LANG_PROGRAM([
+ struct abc { int a; char b[]; };
+], [
+ struct abc *def = malloc(sizeof(struct abc)+sizeof(char));
+ def->b[0] = 33;
+]),
+ [tor_cv_c_flexarray=yes],
+ [tor_cv_c_flexarray=no])])
+ if test $tor_cv_flexarray = yes ; then
+ AC_DEFINE([FLEXIBLE_ARRAY_MEMBER], [], [Define to nothing if C supports flexible array members, and to 1 if it does not.])
+ else
+ AC_DEFINE([FLEXIBLE_ARRAY_MEMBER], [1], [Define to nothing if C supports flexible array members, and to 1 if it does not.])
+ fi
+])
+
AC_PATH_PROG([SHA1SUM], [sha1sum], none)
AC_PATH_PROG([OPENSSL], [openssl], none)
@@ -223,7 +286,30 @@ dnl -------------------------------------------------------------------
dnl Check for functions before libevent, since libevent-1.2 apparently
dnl exports strlcpy without defining it in a header.
-AC_CHECK_FUNCS(gettimeofday ftime socketpair uname inet_aton strptime getrlimit strlcat strlcpy strtoull getaddrinfo localtime_r gmtime_r memmem strtok_r writev readv flock prctl vasprintf)
+AC_CHECK_FUNCS(
+ accept4 \
+ flock \
+ ftime \
+ getaddrinfo \
+ getrlimit \
+ gettimeofday \
+ gmtime_r \
+ inet_aton \
+ localtime_r \
+ lround \
+ memmem \
+ prctl \
+ rint \
+ socketpair \
+ strlcat \
+ strlcpy \
+ strptime \
+ strtok_r \
+ strtoull \
+ sysconf \
+ uname \
+ vasprintf \
+)
using_custom_malloc=no
if test x$enable_openbsd_malloc = xyes ; then
@@ -247,6 +333,7 @@ dnl Where do you live, libevent? And how do we call you?
if test "$bwin32" = true; then
TOR_LIB_WS32=-lws2_32
+ TOR_LIB_IPHLPAPI=-liphlpapi
# Some of the cargo-cults recommend -lwsock32 as well, but I don't
# think it's actually necessary.
TOR_LIB_GDI=-lgdi32
@@ -256,6 +343,7 @@ else
fi
AC_SUBST(TOR_LIB_WS32)
AC_SUBST(TOR_LIB_GDI)
+AC_SUBST(TOR_LIB_IPHLPAPI)
dnl We need to do this before we try our disgusting hack below.
AC_CHECK_HEADERS([sys/types.h])
@@ -314,7 +402,7 @@ AC_CHECK_MEMBERS([struct event.min_heap_idx], , ,
[#include <event.h>
])
-AC_CHECK_HEADERS(event2/event.h event2/dns.h)
+AC_CHECK_HEADERS(event2/event.h event2/dns.h event2/bufferevent_ssl.h)
LIBS="$save_LIBS"
LDFLAGS="$save_LDFLAGS"
@@ -332,8 +420,61 @@ if test "$enable_static_libevent" = "yes"; then
else
TOR_LIBEVENT_LIBS="-levent"
fi
-AC_SUBST(TOR_LIBEVENT_LIBS)
+dnl This isn't the best test for Libevent 2.0.3-alpha. Once it's released,
+dnl we can do much better.
+if test "$enable_bufferevents" = "yes" ; then
+ if test "$ac_cv_header_event2_bufferevent_ssl_h" != "yes" ; then
+ AC_MSG_ERROR([You've asked for bufferevent support, but you're using a version of Libevent without SSL support. This won't work. We need Libevent 2.0.8-rc or later, and you don't seem to even have Libevent 2.0.3-alpha.])
+ else
+
+ CPPFLAGS="$CPPFLAGS $TOR_CPPFLAGS_libevent"
+
+ # Check for the right version. First see if version detection works.
+ AC_MSG_CHECKING([whether we can detect the Libevent version])
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+#include <event2/event.h>
+#if !defined(LIBEVENT_VERSION_NUMBER) || LIBEVENT_VERSION_NUMBER < 10
+#error
+int x = y(zz);
+#else
+int x = 1;
+#endif
+ ])], [event_version_number_works=yes; AC_MSG_RESULT([yes]) ],
+ [event_version_number_works=no; AC_MSG_RESULT([no])])
+ if test "$event_version_number_works" != 'yes'; then
+ AC_MSG_WARN([Version detection on Libevent seems broken. Your Libevent installation is probably screwed up or very old.])
+ else
+ AC_MSG_CHECKING([whether Libevent is new enough for bufferevents])
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+#include <event2/event.h>
+#if !defined(LIBEVENT_VERSION_NUMBER) || LIBEVENT_VERSION_NUMBER < 0x02000d00
+#error
+int x = y(zz);
+#else
+int x = 1;
+#endif
+ ])], [ AC_MSG_RESULT([yes]) ],
+ [ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([Libevent does not seem new enough to support bufferevents. We require 2.0.13-stable or later]) ] )
+ fi
+ fi
+fi
+
+LIBS="$save_LIBS"
+LDFLAGS="$save_LDFLAGS"
+CPPFLAGS="$save_CPPFLAGS"
+
+AM_CONDITIONAL(USE_BUFFEREVENTS, test "$enable_bufferevents" = "yes")
+if test "$enable_bufferevents" = "yes"; then
+ AC_DEFINE(USE_BUFFEREVENTS, 1, [Defined if we're going to use Libevent's buffered IO API])
+ if test "$enable_static_libevent" = "yes"; then
+ TOR_LIBEVENT_LIBS="$TOR_LIBDIR_libevent/libevent_openssl.a $TOR_LIBEVENT_LIBS"
+ else
+ TOR_LIBEVENT_LIBS="-levent_openssl $TOR_LIBEVENT_LIBS"
+ fi
+fi
+AC_SUBST(TOR_LIBEVENT_LIBS)
dnl ------------------------------------------------------
dnl Where do you live, openssl? And how do we call you?
@@ -401,15 +542,94 @@ AC_SUBST(TOR_ZLIB_LIBS)
dnl Make sure to enable support for large off_t if available.
-AC_SYS_LARGEFILE
-AC_CHECK_HEADERS(unistd.h string.h signal.h sys/stat.h sys/types.h fcntl.h sys/fcntl.h sys/time.h errno.h assert.h time.h, , AC_MSG_WARN(Some headers were not found, compilation may fail. If compilation succeeds, please send your orconfig.h to the developers so we can fix this warning.))
+dnl ------------------------------------------------------
+dnl Where do you live, libnatpmp? And how do we call you?
+dnl There are no packages for Debian or Redhat as of this patch
+
+if test "$natpmp" = "true"; then
+ AC_DEFINE(NAT_PMP, 1, [Define to 1 if we are building with nat-pmp.])
+ TOR_SEARCH_LIBRARY(libnatpmp, $trylibnatpmpdir, [-lnatpmp],
+ [#include <natpmp.h>],
+ [#include <natpmp.h>],
+ [ int r;
+ natpmp_t natpmp;
+ natpmpresp_t response;
+ r = initnatpmp(&natpmp, 0, 0);],
+ [printf("initnatpmp() returned %d (%s)\n", r, r?"FAILED":"SUCCESS");
+ exit(0);],
+ [--with-libnatpmp-dir],
+ [/usr/lib/])
+fi
+
-AC_CHECK_HEADERS(netdb.h sys/ioctl.h sys/socket.h arpa/inet.h netinet/in.h pwd.h grp.h sys/un.h sys/uio.h)
+dnl ------------------------------------------------------
+dnl Where do you live, libminiupnpc? And how do we call you?
+dnl There are no packages for Debian or Redhat as of this patch
+
+if test "$upnp" = "true"; then
+ AC_DEFINE(MINIUPNPC, 1, [Define to 1 if we are building with UPnP.])
+ TOR_SEARCH_LIBRARY(libminiupnpc, $trylibminiupnpcdir, [-lminiupnpc $TOR_LIB_WS32 $TOR_LIB_IPHLPAPI],
+ [#include <miniupnpc/miniwget.h>
+ #include <miniupnpc/miniupnpc.h>
+ #include <miniupnpc/upnpcommands.h>],
+ [void upnpDiscover(int delay, const char * multicastif,
+ const char * minissdpdsock, int sameport);],
+ [upnpDiscover(1, 0, 0, 0); exit(0);],
+ [--with-libminiupnpc-dir],
+ [/usr/lib/])
+fi
+
+AC_SYS_LARGEFILE
+
+AC_CHECK_HEADERS(
+ assert.h \
+ errno.h \
+ fcntl.h \
+ signal.h \
+ string.h \
+ sys/fcntl.h \
+ sys/stat.h \
+ sys/time.h \
+ sys/types.h \
+ time.h \
+ unistd.h
+ , , AC_MSG_WARN(Some headers were not found, compilation may fail. If compilation succeeds, please send your orconfig.h to the developers so we can fix this warning.))
dnl These headers are not essential
-AC_CHECK_HEADERS(stdint.h sys/types.h inttypes.h sys/param.h sys/wait.h limits.h sys/limits.h netinet/in.h arpa/inet.h machine/limits.h syslog.h sys/time.h sys/resource.h inttypes.h utime.h sys/utime.h sys/mman.h netinet/in6.h malloc.h sys/syslimits.h malloc/malloc.h linux/types.h sys/file.h malloc_np.h sys/prctl.h)
+AC_CHECK_HEADERS(
+ arpa/inet.h \
+ grp.h \
+ inttypes.h \
+ limits.h \
+ linux/types.h \
+ machine/limits.h \
+ malloc.h \
+ malloc/malloc.h \
+ malloc_np.h \
+ netdb.h \
+ netinet/in.h \
+ netinet/in6.h \
+ pwd.h \
+ stdint.h \
+ sys/file.h \
+ sys/ioctl.h \
+ sys/limits.h \
+ sys/mman.h \
+ sys/param.h \
+ sys/prctl.h \
+ sys/resource.h \
+ sys/socket.h \
+ sys/syslimits.h \
+ sys/time.h \
+ sys/types.h \
+ sys/un.h \
+ sys/utime.h \
+ sys/wait.h \
+ syslog.h \
+ utime.h
+)
TOR_CHECK_PROTOTYPE(malloc_good_size, HAVE_MALLOC_GOOD_SIZE_PROTOTYPE,
[#ifdef HAVE_MALLOC_H
@@ -866,6 +1086,13 @@ if test "x$exec_prefix" = "xNONE"; then
exec_prefix=$prefix
fi
+if test "x$BUILDDIR" = "x"; then
+ BUILDDIR=`pwd`
+fi
+AC_SUBST(BUILDDIR)
+AH_TEMPLATE([BUILDDIR],[tor's build directory])
+AC_DEFINE_UNQUOTED(BUILDDIR,"$BUILDDIR")
+
if test "x$CONFDIR" = "x"; then
CONFDIR=`eval echo $sysconfdir/tor`
fi
@@ -954,7 +1181,12 @@ if test x$enable_gcc_warnings = xyes || test x$enable_gcc_warnings_advisory = xy
CFLAGS="$CFLAGS -Wno-system-headers" ;;
esac
- CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2 -Wwrite-strings -Wmissing-declarations -Wredundant-decls -Wnested-externs -Wbad-function-cast -Wswitch-enum"
+ CFLAGS="$CFLAGS -W -Wfloat-equal -Wundef -Wpointer-arith"
+ CFLAGS="$CFLAGS -Wstrict-prototypes -Wmissing-prototypes -Wwrite-strings"
+ CFLAGS="$CFLAGS -Wredundant-decls -Wchar-subscripts -Wcomment -Wformat=2"
+ CFLAGS="$CFLAGS -Wwrite-strings -Wmissing-declarations -Wredundant-decls"
+ CFLAGS="$CFLAGS -Wnested-externs -Wbad-function-cast -Wswitch-enum"
+
if test x$enable_gcc_warnings = xyes; then
CFLAGS="$CFLAGS -Werror"
fi
@@ -966,7 +1198,7 @@ if test x$enable_gcc_warnings = xyes || test x$enable_gcc_warnings_advisory = xy
CFLAGS="$CFLAGS -Winit-self -Wmissing-field-initializers -Wdeclaration-after-statement -Wold-style-definition"
fi
- if test x$have_gcc42 = xyes ; then
+ if test x$have_gcc42 = xyes ; then
# These warnings break gcc 4.0.2 and work on gcc 4.2
# XXXX020 See if any of these work with earlier versions.
CFLAGS="$CFLAGS -Waddress -Wmissing-noreturn -Wstrict-overflow=1"
@@ -999,7 +1231,29 @@ fi
CPPFLAGS="$CPPFLAGS $TOR_CPPFLAGS_libevent $TOR_CPPFLAGS_openssl $TOR_CPPFLAGS_zlib"
-AC_CONFIG_FILES([Makefile tor.spec Doxyfile contrib/tor.sh contrib/torctl contrib/torify contrib/tor.logrotate contrib/Makefile src/config/torrc.sample src/Makefile doc/Makefile src/config/Makefile src/common/Makefile src/or/Makefile src/test/Makefile src/win32/Makefile src/tools/Makefile contrib/suse/Makefile contrib/suse/tor.sh])
+AC_CONFIG_FILES([
+ Doxyfile
+ Makefile
+ contrib/Makefile
+ contrib/suse/Makefile
+ contrib/suse/tor.sh
+ contrib/tor.logrotate
+ contrib/tor.sh
+ contrib/torctl
+ contrib/torify
+ doc/Makefile
+ src/Makefile
+ src/common/Makefile
+ src/config/Makefile
+ src/config/torrc.sample
+ src/or/Makefile
+ src/test/Makefile
+ src/tools/Makefile
+ src/tools/tor-fw-helper/Makefile
+ src/win32/Makefile
+ tor.spec
+])
+
AC_OUTPUT
if test -x /usr/bin/perl && test -x ./contrib/updateVersions.pl ; then
diff --git a/contrib/Makefile.am b/contrib/Makefile.am
index 5aae2c819..795c351f3 100644
--- a/contrib/Makefile.am
+++ b/contrib/Makefile.am
@@ -3,7 +3,20 @@ DIST_SUBDIRS = suse
confdir = $(sysconfdir)/tor
-EXTRA_DIST = exitlist tor-tsocks.conf tor.nsi.in tor.sh torctl rc.subr cross.sh tor-mingw.nsi.in package_nsis-mingw.sh tor.ico tor-ctrl.sh linux-tor-prio.sh tor-exit-notice.html
+EXTRA_DIST = \
+ cross.sh \
+ exitlist \
+ linux-tor-prio.sh \
+ package_nsis-mingw.sh \
+ rc.subr \
+ tor-ctrl.sh \
+ tor-exit-notice.html \
+ tor-mingw.nsi.in \
+ tor-tsocks.conf \
+ tor.ico \
+ tor.nsi.in \
+ tor.sh \
+ torctl
conf_DATA = tor-tsocks.conf
diff --git a/contrib/findMergedChanges.pl b/contrib/findMergedChanges.pl
new file mode 100755
index 000000000..46e070f94
--- /dev/null
+++ b/contrib/findMergedChanges.pl
@@ -0,0 +1,70 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+sub nChanges {
+ my ($branches, $fname) = @_;
+ local *F;
+ # requires perl 5.8. Avoids shell issues if we ever get a changes
+ # file named by the parents of Little Johnny Tables.
+ open F, "-|", "git", "log", "--pretty=format:%H", $branches, "--", $fname
+ or die "$!";
+ my @changes = <F>;
+ return scalar @changes
+}
+
+my $look_for_type = "merged";
+
+if (! @ARGV) {
+ print <<EOF
+Usage:
+ findMergedChanges.pl [--merged/--unmerged/--weird/--list] changes/*
+
+A change is "merged" if it has ever been merged to release-0.2.2 and it has had
+no subsequent changes in master.
+
+A change is "unmerged" if it has never been merged to release-0.2.2 and it
+has had changes in master.
+
+A change is "weird" if it has been merged to release-0.2.2 and it *has* had
+subsequent changes in master.
+
+Suggested application:
+ findMergedChanges.pl --merged changes/* | xargs -n 1 git rm
+
+EOF
+}
+
+my $target_branch = "origin/release-0.2.2";
+
+while (@ARGV and $ARGV[0] =~ /^--/) {
+ my $flag = shift @ARGV;
+ if ($flag =~ /^--(weird|merged|unmerged|list)/) {
+ $look_for_type = $1;
+ } elsif ($flag =~ /^--branch=(\S+)/) {
+ $target_branch = $1;
+ } else {
+ die "Unrecognized flag $flag";
+ }
+}
+
+for my $changefile (@ARGV) {
+ my $n_merged = nChanges($target_branch, $changefile);
+ my $n_postmerged = nChanges("${target_branch}..origin/master", $changefile);
+ my $type;
+
+ if ($n_merged != 0 and $n_postmerged == 0) {
+ $type = "merged";
+ } elsif ($n_merged == 0 and $n_postmerged != 0) {
+ $type = "unmerged";
+ } else {
+ $type = "weird";
+ }
+
+ if ($type eq $look_for_type) {
+ print "$changefile\n";
+ } elsif ($look_for_type eq 'list') {
+ printf "% 8s: %s\n", $type, $changefile;
+ }
+}
diff --git a/contrib/make-signature.sh b/contrib/make-signature.sh
new file mode 100755
index 000000000..4aba08b75
--- /dev/null
+++ b/contrib/make-signature.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+
+set -eu
+
+if test "$1" = "" ; then
+ echo "I need a package as an argument."
+ exit 1
+fi
+
+PACKAGEFILE=$1
+
+if test ! -f "$PACKAGEFILE" ; then
+ echo "$PACKAGEFILE is not a file."
+ exit 1
+fi
+
+DIGESTNAME=sha256
+DIGESTOUTPUT=`gpg --print-md $DIGESTNAME $PACKAGEFILE`
+
+RAWDIGEST=`gpg --print-md $DIGESTNAME $PACKAGEFILE | sed -e 's/^[^ ]*: //' `
+
+# These regexes are a little fragile, but I think they work for us.
+VERSION=`echo $PACKAGEFILE | sed -e 's/^[a-z\-]*//' -e 's/\.[\.a-z]*$//' `
+PACKAGE=`echo $PACKAGEFILE | sed -e 's/-[0-9].*//'`
+SIGFILE_UNSIGNED="$PACKAGE-$VERSION-signature"
+SIGNATUREFILE="$SIGFILE_UNSIGNED.asc"
+
+cat >$SIGFILE_UNSIGNED <<EOF
+This is the signature file for "$PACKAGEFILE",
+which contains version "$VERSION" of "$PACKAGE".
+
+Here's how to check this signature.
+
+1) Make sure that this is really a signature file, and not a forgery,
+ with:
+
+ "gpg --verify $SIGNATUREFILE"
+
+ The key should be one of the keys that signs the Tor release; the
+ official Tor website has more information on those.
+
+ If this step fails, then either you are missing the correct key, or
+ this signature file was not really signed by a Tor packager.
+ Beware!
+
+2) Make sure that the package you wanted is indeed "$PACKAGE", and that
+ its version you wanted is indeed "$VERSION". If you wanted a
+ different package, or a different version, this signature file is
+ not the right one!
+
+3) Now that you're sure you have the right signature file, make sure
+ that you got the right package. Check its $DIGESTNAME digest with
+
+ "gpg --print-md $DIGESTNAME $PACKAGEFILE"
+
+ The output should match this, exactly:
+
+$DIGESTOUTPUT
+
+ Make sure that every part of the output matches: don't just check the
+ first few characters. If the digest does not match, you do not have
+ the right package file. It could even be a forgery.
+
+Frequently asked questions:
+
+Q: Why not just sign the package file, like you used to do?
+A: GPG signatures authenticate file contents, but not file names. If
+ somebody gave you a renamed file with a matching renamed signature
+ file, the signature would still be given as "valid".
+
+--
+FILENAME: $PACKAGEFILE
+PACKAGE: $PACKAGE
+VERSION: $VERSION
+DIGESTALG: $DIGESTNAME
+DIGEST: $RAWDIGEST
+EOF
+
+gpg --clearsign $SIGFILE_UNSIGNED
diff --git a/contrib/tor-mingw.nsi.in b/contrib/tor-mingw.nsi.in
index a44961b02..e1fdc1af7 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.2.19-alpha"
+!define VERSION "0.2.3.5-alpha"
!define INSTALLER "tor-${VERSION}-win32.exe"
!define WEBSITE "https://www.torproject.org/"
!define LICENSE "LICENSE"
diff --git a/doc/HACKING b/doc/HACKING
index 9747f2265..b0689d82c 100644
--- a/doc/HACKING
+++ b/doc/HACKING
@@ -426,10 +426,10 @@ interesting and understandable.
first entry or two and the last entry most interesting: they're
the ones that skimmers tend to read.
- 2.4) Clean them up
+ 2.4) Clean them up:
Standard idioms:
- "Fixes bug 9999; Bugfix on 0.3.3.3-alpha."
+ "Fixes bug 9999; bugfix on 0.3.3.3-alpha."
One period after a space.
@@ -446,6 +446,11 @@ interesting and understandable.
Present and imperative tense: not past.
+ Try not to let any given section be longer than about a page. Break up
+ long sections into subsections by some sort of common subtopic. This
+ guideline is especially important when organizing Release Notes for
+ new stable releases.
+
If a given changes stanza showed up in a different release (e.g.
maint-0.2.1), be sure to make the stanzas identical (so people can
distinguish if these are the same change).
diff --git a/doc/Makefile.am b/doc/Makefile.am
index bc3d8df47..d8d9fbefc 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -12,15 +12,21 @@
# part of the source distribution, so that people without asciidoc can
# just use the .1 and .html files.
+regular_mans = tor tor-gencert tor-resolve torify
+all_mans = $(regular_mans) tor-fw-helper
+
if USE_ASCIIDOC
-asciidoc_files = tor tor-gencert tor-resolve torify
-html_in = $(asciidoc_files:=.html.in)
-man_in = $(asciidoc_files:=.1.in)
-txt_in = $(asciidoc_files:=.1.txt)
-nodist_man_MANS = $(asciidoc_files:=.1)
-doc_DATA = $(asciidoc_files:=.html)
+if USE_FW_HELPER
+nodist_man_MANS = $(all_mans:=.1)
+doc_DATA = $(all_mans:=.html)
+else
+nodist_man_MANS = $(regular_mans:=.1)
+doc_DATA = $(regular_mans:=.html)
+endif
+html_in = $(all_mans:=.html.in)
+man_in = $(all_mans:=.1.in)
+txt_in = $(all_mans:=.1.txt)
else
-asciidoc_files =
html_in =
man_in =
txt_in =
@@ -46,6 +52,7 @@ tor.html.in : tor.1.txt
torify.html.in : torify.1.txt
tor-gencert.html.in : tor-gencert.1.txt
tor-resolve.html.in : tor-resolve.1.txt
+tor-fw-helper.html.in : tor-fw-helper.1.txt
# Generate the manpage from asciidoc, but don't do
# machine-specific replacements yet
@@ -56,6 +63,7 @@ tor.1.in : tor.1.txt
torify.1.in : torify.1.txt
tor-gencert.1.in : tor-gencert.1.txt
tor-resolve.1.in : tor-resolve.1.txt
+tor-fw-helper.1.in : tor-fw-helper.1.txt
# use ../config.status to swap all machine-specific magic strings
# in the asciidoc with their replacements.
@@ -69,10 +77,12 @@ tor.1 : tor.1.in
torify.1 : torify.1.in
tor-gencert.1 : tor-gencert.1.in
tor-resolve.1 : tor-resolve.1.in
+tor-fw-helper.1 : tor-fw-helper.1.in
tor.html : tor.html.in
torify.html : torify.html.in
tor-gencert.html : tor-gencert.html.in
tor-resolve.html : tor-resolve.html.in
+tor-fw-helper.html : tor-fw-helper.html.in
CLEANFILES = $(asciidoc_product) config.log
DISTCLEANFILES = $(html_in) $(man_in)
diff --git a/doc/asciidoc-helper.sh b/doc/asciidoc-helper.sh
index 00f8b8d07..33e1360a7 100755
--- a/doc/asciidoc-helper.sh
+++ b/doc/asciidoc-helper.sh
@@ -17,6 +17,7 @@ output=$3
if [ "$1" = "html" ]; then
input=${output%%.html.in}.1.txt
base=${output%%.html.in}
+
if [ "$2" != none ]; then
"$2" -d manpage -o $output $input;
else
@@ -32,7 +33,7 @@ if [ "$1" = "html" ]; then
elif [ "$1" = "man" ]; then
input=${output%%.1.in}.1.txt
base=${output%%.1.in}
-
+
if test "$2" = none; then
echo "==================================";
echo;
diff --git a/doc/tor-fw-helper.1.txt b/doc/tor-fw-helper.1.txt
new file mode 100644
index 000000000..49b091038
--- /dev/null
+++ b/doc/tor-fw-helper.1.txt
@@ -0,0 +1,68 @@
+// Copyright (c) The Tor Project, Inc.
+// See LICENSE for licensing information
+// This is an asciidoc file used to generate the manpage/html reference.
+// Learn asciidoc on http://www.methods.co.nz/asciidoc/userguide.html
+tor-fw-helper(1)
+================
+Jacob Appelbaum
+
+NAME
+----
+tor-fw-helper - Manage upstream firewall/NAT devices
+
+SYNOPSIS
+--------
+**tor-fw-helper** [-h|--help] [-T|--test] [-v|--verbose] [-g|--fetch-public-ip]
+ -i|--internal-or-port __TCP port__ [-e|--external-or-port _TCP port_]
+ [-d|--internal-dir-port _TCP port_] [-p|--external-dir-port _TCP port_]
+
+DESCRIPTION
+-----------
+**tor-fw-helper** currently supports Apple's NAT-PMP protocol and the UPnP
+standard for TCP port mapping. It is written as the reference implementation of
+tor-fw-helper-spec.txt and conforms to that loose plugin API. If your network
+supports either NAT-PMP or UPnP, tor-fw-helper will attempt to automatically
+map the required TCP ports for Tor's Or and Dir ports. +
+
+OPTIONS
+-------
+**-h** or **--help**::
+ Display help text and exit.
+
+**-v**::
+ Display verbose output.
+
+**-T** or **--test**::
+ Display test information and print the test information in
+ tor-fw-helper.log
+
+**-g** or **--fetch-public-ip**::
+ Fetch the the public ip address for each supported NAT helper method.
+
+**-i** or **--internal-or-port** __port__::
+ Inform **tor-fw-helper** of your internal OR port. This is the only
+ required argument.
+
+**-e** or **--external-or-port** __port__::
+ Inform **tor-fw-helper** of your external OR port.
+
+**-d** or **--internal-dir-port** __port__::
+ Inform **tor-fw-helper** of your internal Dir port.
+
+**-p** or **--external-dir-port** __port__::
+ Inform **tor-fw-helper** of your external Dir port.
+
+BUGS
+----
+This probably doesn't run on Windows. That's not a big issue, since we don't
+really want to deal with Windows before October 2010 anyway.
+
+SEE ALSO
+--------
+**tor**(1) +
+
+See also the "tor-fw-helper-spec.txt" file, distributed with Tor.
+
+AUTHORS
+-------
+ Jacob Appelbaum <jacob@torproject.org>, Steven J. Murdoch <Steven.Murdoch@cl.cam.ac.uk>
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index bfc976651..0ef61cb7d 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -148,10 +148,11 @@ Other options can be specified either on the command-line (--option
**ControlPort** __PORT__|**auto**::
If set, Tor will accept connections on this port and allow those
connections to control the Tor process using the Tor Control Protocol
- (described in control-spec.txt). Note: unless you also specify one of
- **HashedControlPassword** or **CookieAuthentication**, setting this
- option will
- cause Tor to allow any process on the local host to control it. This
+ (described in control-spec.txt). Note: unless you also specify one or
+ more of **HashedControlPassword** or **CookieAuthentication**,
+ setting this option will cause Tor to allow any process on the local
+ host to control it. (Setting both authentication methods means either
+ method is sufficient to authenticate to Tor.) This
option is required for many Tor controllers; most use the value of 9051.
Set it to "auto" to have Tor pick a port for you. (Default: 0).
@@ -173,15 +174,15 @@ Other options can be specified either on the command-line (--option
the control socket readable and writable by the default GID. (Default: 0)
**HashedControlPassword** __hashed_password__::
- Don't allow any connections on the control port except when the other
- process knows the password whose one-way hash is __hashed_password__. You
+ Allow connections on the control port if they present
+ the password whose one-way hash is __hashed_password__. You
can compute the hash of a password by running "tor --hash-password
__password__". You can provide several acceptable passwords by using more
than one HashedControlPassword line.
**CookieAuthentication** **0**|**1**::
- If this option is set to 1, don't allow any connections on the control port
- except when the connecting process knows the contents of a file named
+ If this option is set to 1, allow connections on the control port
+ when the connecting process knows the contents of a file named
"control_auth_cookie", which Tor will create in its data directory. This
authentication method should only be used on systems with good filesystem
security. (Default: 0)
@@ -388,6 +389,13 @@ Other options can be specified either on the command-line (--option
on Windows; instead you should use the --service command-line option.
(Default: 0)
+**LogTimeGranularity** __NUM__::
+ Set the resolution of timestamps in Tor's logs to NUM milliseconds.
+ NUM must be positive and either a divisor or a multiple of 1 second.
+ Note that this option only controls the granularity written by Tor to
+ a file or console log. Tor does not (for example) "batch up" log
+ messages to affect times logged by a controller, times attached to
+ syslog messages, or the mtime fields on log files. (Default: 1 second)
**SafeLogging** **0**|**1**|**relay**::
Tor can scrub potentially sensitive strings from log messages (e.g.
@@ -442,11 +450,22 @@ Other options can be specified either on the command-line (--option
networkstatus. This is an advanced option; you generally shouldn't have
to mess with it. (Default: not set.)
+**DisableIOCP** **0**|**1**::
+ If Tor was built to use the Libevent's "bufferevents" networking code
+ and you're running on Windows, setting this option to 1 will tell Libevent
+ not to use the Windows IOCP networking API. (Default: 1)
+
+**CountPrivateBandwidth** **0**|**1**::
+ If this option is set, then Tor's rate-limiting applies not only to
+ remote connections, but also to connections to private addresses like
+ 127.0.0.1 or 10.0.0.1. This is mostly useful for debugging
+ rate-limiting. (Default: 0)
+
CLIENT OPTIONS
--------------
The following options are useful only for clients (that is, if
-**SocksPort** is non-zero):
+**SocksPort**, **TransPort**, **DNSPort**, or **NATDPort** is non-zero):
**AllowInvalidNodes** **entry**|**exit**|**middle**|**introduction**|**rendezvous**|**...**::
If some Tor servers are obviously not working right, the directory
@@ -530,7 +549,6 @@ The following options are useful only for clients (that is, if
node listed in ExcludeNodes is automatically considered to be part of this
list too. See also the caveats on the "ExitNodes" option below.
-
**ExitNodes** __node__,__node__,__...__::
A list of identity fingerprints, nicknames, country codes and address
patterns of nodes to use as exit node---that is, a
@@ -555,9 +573,9 @@ The following options are useful only for clients (that is, if
this option.
**EntryNodes** __node__,__node__,__...__::
- A list of identity fingerprints and nicknames of nodes
- to use for the first hop in your normal circuits. (Country codes and
- address patterns are not yet supported.) Normal circuits include all
+ A list of identity fingerprints, nicknames, and country codes of nodes
+ to use for the first hop in your normal circuits.
+ Normal circuits include all
circuits except for direct connections to directory servers. The Bridge
option overrides this option; if you have configured bridges and
UseBridges is 1, the Bridges are used as your entry nodes. +
@@ -634,7 +652,7 @@ The following options are useful only for clients (that is, if
(e.g. chat and interactive shells). Circuits for streams that use these
ports will contain only high-uptime nodes, to reduce the chance that a node
will go down before the stream is finished. (Default: 21, 22, 706, 1863,
- 5050, 5190, 5222, 5223, 6667, 6697, 8300)
+ 5050, 5190, 5222, 5223, 6523, 6667, 6697, 8300)
**MapAddress** __address__ __newaddress__::
When a request for address arrives to Tor, it will rewrite it to newaddress
@@ -657,24 +675,57 @@ The following options are useful only for clients (that is, if
constitute a "family" of similar or co-administered servers, so never use
any two of them in the same circuit. Defining a NodeFamily is only needed
when a server doesn't list the family itself (with MyFamily). This option
- can be used multiple times.
+ can be used multiple times. In addition to nodes, you can also list
+ IP address and ranges and country codes in {curly braces}.
**EnforceDistinctSubnets** **0**|**1**::
If 1, Tor will not put two servers whose IP addresses are "too close" on
the same circuit. Currently, two addresses are "too close" if they lie in
the same /16 range. (Default: 1)
-**SocksPort** __PORT__|**auto**::
- Advertise this port to listen for connections from Socks-speaking
+**SOCKSPort** \['address':]__port__|**auto** [_isolation flags_]::
+ Open this port to listen for connections from SOCKS-speaking
applications. Set this to 0 if you don't want to allow application
connections via SOCKS. Set it to "auto" to have Tor pick a port for
- you. (Default: 9050)
-
-**SocksListenAddress** __IP__[:__PORT__]::
+ you. This directive can be specified multiple times to bind
+ to multiple addresses/ports. (Default: 9050) +
+ +
+ The _isolation flags_ arguments give Tor rules for which streams
+ received on this SOCKSPort are allowed to share circuits with one
+ another. Recognized isolation flags are:
+ **IsolateClientAddr**;;
+ Don't share a circuits with streams from a different
+ client address. (On by default and strongly recommended;
+ you can disable it with **NoIsolateClientAddr**.)
+ **IsolateSOCKSAuth**;;
+ Don't share a circuits with streams for which different
+ SOCKS authentication was provided. (On by default;
+ you can disable it with **NoIsolateSOCKSAuth**.)
+ **IsolateClientProtocol**;;
+ Don't share circuits with streams using a different protocol.
+ (SOCKS 4, SOCKS 5, TransPort connections, NATDPort connections,
+ and DNSPort requests are all considered to be different protocols.)
+ **IsolateDestPort**;;
+ Don't share a circuits with streams targetting a different
+ destination port.
+ **IsolateDestAddr**;;
+ Don't share a circuits with streams targetting a different
+ destination address.
+ **SessionGroup=**__INT__;;
+ If no other isolation rules would prevent it, allow streams
+ on this port to share circuits with streams from every other
+ port with the same session group. (By default, streams received
+ on different ports are always isolated from one another.)
+
+**SOCKSListenAddress** __IP__[:__PORT__]::
Bind to this address to listen for connections from Socks-speaking
applications. (Default: 127.0.0.1) You can also specify a port (e.g.
192.168.0.1:9100). This directive can be specified multiple times to bind
- to multiple addresses/ports.
+ to multiple addresses/ports. (DEPRECATED: As of 0.2.3.x-alpha, you can
+ now use multiple SOCKSPort entries, and provide addresses for SOCKSPort
+ entries, so SOCKSListenAddress no longer has a purpose. For backward
+ compatibility, SOCKSListenAddress is only allowed when SOCKSPort is just
+ a port number.)
**SocksPolicy** __policy__,__policy__,__...__::
Set an entrance policy for this server, to limit who can connect to the
@@ -686,6 +737,13 @@ The following options are useful only for clients (that is, if
unattached waiting for an appropriate circuit, before we fail it. (Default:
2 minutes.)
+**TokenBucketRefillInterval** __NUM__ [**msec**|**second**]::
+ Set the refill interval of Tor's token bucket to NUM milliseconds.
+ NUM must be between 1 and 1000, inclusive. Note that the configured
+ bandwidth limits are still expressed in bytes per second: this
+ option only affects the frequency with which Tor checks to see whether
+ previously exhausted connections may read again. (Default: 100 msec.)
+
**TrackHostExits** __host__,__.domain__,__...__::
For each value in the comma separated list, Tor will track recent
connections to hosts that match this value and attempt to reuse the same
@@ -777,28 +835,44 @@ The following options are useful only for clients (that is, if
operating as a relay, and it will never use the public key step if it
doesn't yet know the onion key of the first hop. (Default: 1)
-**TransPort** __PORT__|**auto**::
- If non-zero, enables transparent proxy support on __PORT__ (by convention,
- 9040). Requires OS support for transparent proxies, such as BSDs' pf or
+**TransPort** \['address':]__port__|**auto** [_isolation flags_]::
+ Open this port to listen for transparent proxy connections. Set this to
+ 0 if you don't want to allow transparent proxy connections. Set the port
+ to "auto" to have Tor pick a port for you. This directive can be
+ specified multiple times to bind to multiple addresses/ports. See
+ SOCKSPort for an explanation of isolation flags. +
+ +
+ TransPort requires OS support for transparent proxies, such as BSDs' pf or
Linux's IPTables. If you're planning to use Tor as a transparent proxy for
a network, you'll want to examine and change VirtualAddrNetwork from the
default setting. You'll also want to set the TransListenAddress option for
- the network you'd like to proxy. Set it to "auto" to have Tor pick a
- port for you. (Default: 0).
+ the network you'd like to proxy. (Default: 0).
**TransListenAddress** __IP__[:__PORT__]::
Bind to this address to listen for transparent proxy connections. (Default:
127.0.0.1). This is useful for exporting a transparent proxy server to an
- entire network.
-
-**NATDPort** __PORT__|**auto**::
- Allow old versions of ipfw (as included in old versions of FreeBSD, etc.)
- to send connections through Tor using the NATD protocol. This option is
- only for people who cannot use TransPort. Set it to "auto" to have Tor
- pick a port for you. (Default: 0)
+ entire network. (DEPRECATED: As of 0.2.3.x-alpha, you can
+ now use multiple TransPort entries, and provide addresses for TransPort
+ entries, so TransListenAddress no longer has a purpose. For backward
+ compatibility, TransListenAddress is only allowed when TransPort is just
+ a port number.)
+
+**NATDPort** \['address':]__port__|**auto** [_isolation flags_]::
+ Open this port to listen for connections from old versions of ipfw (as
+ included in old versions of FreeBSD, etc) using the NATD protocol.
+ Use 0 if you don't want to allow NATD connections. Set the port
+ to "auto" to have Tor pick a port for you. This directive can be
+ specified multiple times to bind to multiple addresses/ports. See
+ SOCKSPort for an explanation of isolation flags. +
+ +
+ This option is only for people who cannot use TransPort. (Default: 0)
**NATDListenAddress** __IP__[:__PORT__]::
- Bind to this address to listen for NATD connections. (Default: 127.0.0.1).
+ Bind to this address to listen for NATD connections. (DEPRECATED: As of
+ 0.2.3.x-alpha, you can now use multiple NATDPort entries, and provide
+ addresses for NATDPort entries, so NATDListenAddress no longer has a
+ purpose. For backward compatibility, NATDListenAddress is only allowed
+ when NATDPort is just a port number.)
**AutomapHostsOnResolve** **0**|**1**::
When this option is enabled, and we get a request to resolve an address
@@ -811,13 +885,19 @@ The following options are useful only for clients (that is, if
A comma-separated list of suffixes to use with **AutomapHostsOnResolve**.
The "." suffix is equivalent to "all addresses." (Default: .exit,.onion).
-**DNSPort** __PORT__|**auto**::
- If non-zero, Tor listens for UDP DNS requests on this port and resolves
- them anonymously. Set it to "auto" to have Tor pick a port for
- you. (Default: 0).
+**DNSPort** \['address':]__port__|**auto** [_isolation flags_]::
+ If non-zero, open this port to listen for UDP DNS requests, and resolve
+ them anonymously. Set the port to "auto" to have Tor pick a port for
+ you. This directive can be specified multiple times to bind to multiple
+ addresses/ports. See SOCKSPort for an explanation of isolation
+ flags. (Default: 0).
**DNSListenAddress** __IP__[:__PORT__]::
- Bind to this address to listen for DNS connections. (Default: 127.0.0.1).
+ Bind to this address to listen for DNS connections. (DEPRECATED: As of
+ 0.2.3.x-alpha, you can now use multiple DNSPort entries, and provide
+ addresses for DNSPort entries, so DNSListenAddress no longer has a
+ purpose. For backward compatibility, DNSListenAddress is only allowed
+ when DNSPort is just a port number.)
**ClientDNSRejectInternalAddresses** **0**|**1**::
If true, Tor does not believe any anonymously retrieved DNS answer that
@@ -858,6 +938,16 @@ The following options are useful only for clients (that is, if
that have the **AllowSingleHopExits** option turned on to build
one-hop Tor connections. (Default: 0)
+**OptimisticData** **0**|**1**|**auto**::
+ When this option is set, and Tor is using an exit node that supports
+ the feature, it will try optimistically to send data to the exit node
+ without waiting for the exit node to report whether the connection
+ succeeded. This can save a round-trip time for protocols like HTTP
+ where the client talks first. If OptimisticData is set to **auto**,
+ Tor will look at the UseOptimisticData parameter in the networkstatus.
+ (Default: auto)
+
+
SERVER OPTIONS
--------------
@@ -964,7 +1054,9 @@ is non-zero):
characters inclusive, and must contain only the characters [a-zA-Z0-9].
**NumCPUs** __num__::
- How many processes to use at once for decrypting onionskins. (Default: 1)
+ How many processes to use at once for decrypting onionskins and other
+ parallelizable operations. If this is set to 0, Tor will try to detect
+ how many CPUs you have, defaulting to 1 if it can't tell. (Default: 0)
**ORPort** __PORT__|**auto**::
Advertise this port to listen for connections from Tor clients and
@@ -977,6 +1069,18 @@ is non-zero):
specified in ORPort. (Default: 0.0.0.0) This directive can be specified
multiple times to bind to multiple addresses/ports.
+**PortForwarding** **0**|**1**::
+ Attempt to automatically forward the DirPort and ORPort on a NAT router
+ connecting this Tor server to the Internet. If set, Tor will try both
+ NAT-PMP (common on Apple routers) and UPnP (common on routers from other
+ manufacturers). (Default: 0)
+
+**PortForwardingHelper** __filename__|__pathname__::
+ If PortForwarding is set, use this executable to configure the forwarding.
+ If set to a filename, the system path will be searched for the executable.
+ If set to a path, only the specified path will be executed.
+ (Default: tor-fw-helper)
+
**PublishServerDescriptor** **0**|**1**|**v1**|**v2**|**v3**|**bridge**,**...**::
This option specifies which descriptors Tor will publish when acting as
a relay. You can
@@ -996,6 +1100,11 @@ is non-zero):
seconds, we exit. If we get a second SIGINT, we exit immedi-
ately. (Default: 30 seconds)
+**HeartbeatPeriod** __N__ **minutes**|**hours**|**days**|**weeks**::
+ Log a heartbeat message every **HeartbeatPeriod** seconds. This is
+ a log level __info__ message, designed to let you know your Tor
+ server is still alive and doing useful things. Settings this
+ to 0 will disable the heartbeat. (Default: 6 hours)
**AccountingMax** __N__ **bytes**|**KB**|**MB**|**GB**|**TB**::
Never send more than the specified number of bytes in a given accounting
@@ -1104,6 +1213,10 @@ is non-zero):
When this option is enabled, Tor writes statistics on the number of relayed
bytes and opened stream per exit port to disk every 24 hours. (Default: 0)
+**ConnDirectionStatistics** **0**|**1**::
+ When this option is enabled, Tor writes statistics on the bidirectional use
+ of connections to disk every 24 hours. (Default: 0)
+
**ExtraInfoStatistics** **0**|**1**::
When this option is enabled, Tor includes previously gathered statistics in
its extra-info documents that it uploads to the directory authorities.
@@ -1179,7 +1292,7 @@ if DirPort is non-zero):
**MinUptimeHidServDirectoryV2** __N__ **seconds**|**minutes**|**hours**|**days**|**weeks**::
Minimum uptime of a v2 hidden service directory to be accepted as such by
- authoritative directories. (Default: 24 hours)
+ authoritative directories. (Default: 25 hours)
**DirPort** __PORT__|**auto**::
If this option is nonzero, advertise the directory service on this port.
@@ -1331,6 +1444,11 @@ DIRECTORY AUTHORITY SERVER OPTIONS
that fine-grained information about nodes can be discarded when it hasn't
changed for a given amount of time. (Default: 24 hours)
+**VoteOnHidServDirectoriesV2** **0**|**1**::
+ When this option is set in addition to **AuthoritativeDirectory**, Tor
+ votes on whether to accept relays as hidden service directories.
+ (Default: 1)
+
HIDDEN SERVICE OPTIONS
----------------------
@@ -1396,6 +1514,7 @@ The following options are used for running a testing Tor network.
AuthDirMaxServersPerAuthAddr 0
ClientDNSRejectInternalAddresses 0
ClientRejectInternalAddresses 0
+ CountPrivateBandwidth 1
ExitPolicyRejectPrivate 0
V3AuthVotingInterval 5 minutes
V3AuthVoteDelay 20 seconds
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 6952591d6..2244fe58d 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -1,7 +1,7 @@
noinst_LIBRARIES = libor.a libor-crypto.a libor-event.a
-EXTRA_DIST = common_sha1.i sha256.c
+EXTRA_DIST = common_sha1.i sha256.c Makefile.nmake
#CFLAGS = -Wall -Wpointer-arith -O2
@@ -11,12 +11,48 @@ else
libor_extra_source=
endif
-libor_a_SOURCES = address.c log.c util.c compat.c container.c mempool.c \
- memarea.c di_ops.c procmon.c util_codedigest.c $(libor_extra_source)
-libor_crypto_a_SOURCES = crypto.c aes.c tortls.c torgzip.c
+libor_a_SOURCES = \
+ address.c \
+ compat.c \
+ container.c \
+ di_ops.c \
+ log.c \
+ memarea.c \
+ mempool.c \
+ procmon.c \
+ util.c \
+ util_codedigest.c \
+ $(libor_extra_source)
+
+libor_crypto_a_SOURCES = \
+ aes.c \
+ crypto.c \
+ torgzip.c \
+ tortls.c
+
libor_event_a_SOURCES = compat_libevent.c
-noinst_HEADERS = address.h torlog.h crypto.h util.h compat.h aes.h torint.h tortls.h strlcpy.c strlcat.c torgzip.h container.h ht.h mempool.h memarea.h ciphers.inc compat_libevent.h tortls_states.h di_ops.h procmon.h
+noinst_HEADERS = \
+ address.h \
+ aes.h \
+ ciphers.inc \
+ compat.h \
+ compat_libevent.h \
+ container.h \
+ crypto.h \
+ di_ops.h \
+ ht.h \
+ memarea.h \
+ mempool.h \
+ procmon.h \
+ strlcat.c \
+ strlcpy.c \
+ torgzip.h \
+ torint.h \
+ torlog.h \
+ tortls.h \
+ tortls_states.h \
+ util.h
common_sha1.i: $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS)
if test "@SHA1SUM@" != none; then \
diff --git a/src/common/Makefile.nmake b/src/common/Makefile.nmake
new file mode 100644
index 000000000..c8b598866
--- /dev/null
+++ b/src/common/Makefile.nmake
@@ -0,0 +1,20 @@
+all: libor.lib libor-crypto.lib libor-event.lib
+
+CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include
+
+LIBOR_OBJECTS = address.obj compat.obj container.obj di_ops.obj \
+ log.obj memarea.obj mempool.obj procmon.obj util.obj \
+ util_codedigest.obj
+
+LIBOR_CRYPTO_OBJECTS = aes.obj crypto.obj torgzip.obj tortls.obj
+
+LIBOR_EVENT_OBJECTS = compat_libevent.obj
+
+libor.lib: $(LIBOR_OBJECTS)
+ lib $(LIBOR_OBJECTS) /out:libor.lib
+
+libor-crypto.lib: $(LIBOR_CRYPTO_OBJECTS)
+ lib $(LIBOR_CRYPTO_OBJECTS) /out:libor-crypto.lib
+
+libor-event.lib: $(LIBOR_EVENT_OBJECTS)
+ lib $(LIBOR_EVENT_OBJECTS) /out:libor-event.lib
diff --git a/src/common/OpenBSD_malloc_Linux.c b/src/common/OpenBSD_malloc_Linux.c
index 19dac7765..445135c6b 100644
--- a/src/common/OpenBSD_malloc_Linux.c
+++ b/src/common/OpenBSD_malloc_Linux.c
@@ -1236,7 +1236,7 @@ imalloc(size_t size)
ptralloc = 1;
size = malloc_pagesize;
}
- if ((size + malloc_pagesize) < size) { /* Check for overflow */
+ if (size > SIZE_MAX - malloc_pagesize) { /* Check for overflow */
result = NULL;
errno = ENOMEM;
} else if (size <= malloc_maxsize)
diff --git a/src/common/address.c b/src/common/address.c
index 7fc730105..26a59e923 100644
--- a/src/common/address.c
+++ b/src/common/address.c
@@ -343,7 +343,7 @@ tor_addr_is_internal(const tor_addr_t *addr, int for_listening)
* brackets.
*/
const char *
-tor_addr_to_str(char *dest, const tor_addr_t *addr, int len, int decorate)
+tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len, int decorate)
{
const char *ptr;
tor_assert(addr && dest);
@@ -964,6 +964,19 @@ fmt_addr(const tor_addr_t *addr)
return "???";
}
+/** Like fmt_addr(), but takes <b>addr</b> as a host-order IPv4
+ * addresses. Also not thread-safe, also clobbers its return buffer on
+ * repeated calls. */
+const char *
+fmt_addr32(uint32_t addr)
+{
+ static char buf[INET_NTOA_BUF_LEN];
+ struct in_addr in;
+ in.s_addr = htonl(addr);
+ tor_inet_ntoa(&in, buf, sizeof(buf));
+ return buf;
+}
+
/** Convert the string in <b>src</b> to a tor_addr_t <b>addr</b>. The string
* may be an IPv4 address, an IPv6 address, or an IPv6 address surrounded by
* square brackets.
diff --git a/src/common/address.h b/src/common/address.h
index 9a7656f69..e41e4c2ba 100644
--- a/src/common/address.h
+++ b/src/common/address.h
@@ -127,6 +127,7 @@ tor_addr_eq_ipv4h(const tor_addr_t *a, uint32_t u)
int tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr_out);
char *tor_dup_addr(const tor_addr_t *addr) ATTR_MALLOC;
const char *fmt_addr(const tor_addr_t *addr);
+const char * fmt_addr32(uint32_t addr);
int get_interface_address6(int severity, sa_family_t family, tor_addr_t *addr);
/** Flag to specify how to do a comparison between addresses. In an "exact"
@@ -163,7 +164,7 @@ int tor_addr_port_parse(const char *s, tor_addr_t *addr_out,
int tor_addr_parse_mask_ports(const char *s,
tor_addr_t *addr_out, maskbits_t *mask_out,
uint16_t *port_min_out, uint16_t *port_max_out);
-const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, int len,
+const char * tor_addr_to_str(char *dest, const tor_addr_t *addr, size_t len,
int decorate);
int tor_addr_from_str(tor_addr_t *addr, const char *src);
void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src);
diff --git a/src/common/aes.c b/src/common/aes.c
index c2fdeb594..81091e9f0 100644
--- a/src/common/aes.c
+++ b/src/common/aes.c
@@ -291,11 +291,20 @@ void
aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len,
char *output)
{
-
- /* XXXX This function is up to 5% of our runtime in some profiles;
- * we should look into unrolling some of the loops; taking advantage
- * of alignment, using a bigger buffer, and so on. Not till after 0.1.2.x,
- * though. */
+ /* This function alone is up to 5% of our runtime in some profiles; anything
+ * we could do to make it faster would be great.
+ *
+ * Experimenting suggests that unrolling the inner loop into a switch
+ * statement doesn't help. What does seem to help is making the input and
+ * output buffers word aligned, and never crypting anything besides an
+ * integer number of words at a time -- it shaves maybe 4-5% of the per-byte
+ * encryption time measured by bench_aes. We can't do that with the current
+ * Tor protocol, though: Tor really likes to crypt things in 509-byte
+ * chunks.
+ *
+ * If we were really ambitous, we'd force len to be a multiple of the block
+ * size, and shave maybe another 4-5% off.
+ */
int c = cipher->pos;
if (PREDICT_UNLIKELY(!len)) return;
diff --git a/src/common/compat.c b/src/common/compat.c
index 80b4907b8..2cf7f463c 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -103,6 +103,35 @@
#include "strlcat.c"
#endif
+/** As open(path, flags, mode), but return an fd with the close-on-exec mode
+ * set. */
+int
+tor_open_cloexec(const char *path, int flags, unsigned mode)
+{
+#ifdef O_CLOEXEC
+ return open(path, flags|O_CLOEXEC, mode);
+#else
+ int fd = open(path, flags, mode);
+#ifdef FD_CLOEXEC
+ if (fd >= 0)
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+ return fd;
+#endif
+}
+
+/** DOCDOC */
+FILE *
+tor_fopen_cloexec(const char *path, const char *mode)
+{
+ FILE *result = fopen(path, mode);
+#ifdef FD_CLOEXEC
+ if (result != NULL)
+ fcntl(fileno(result), F_SETFD, FD_CLOEXEC);
+#endif
+ return result;
+}
+
#ifdef HAVE_SYS_MMAN_H
/** Try to create a memory mapping for <b>filename</b> and return it. On
* failure, return NULL. Sets errno properly, using ERANGE to mean
@@ -118,7 +147,7 @@ tor_mmap_file(const char *filename)
tor_assert(filename);
- fd = open(filename, O_RDONLY, 0);
+ fd = tor_open_cloexec(filename, O_RDONLY, 0);
if (fd<0) {
int save_errno = errno;
int severity = (errno == ENOENT) ? LOG_INFO : LOG_WARN;
@@ -695,7 +724,7 @@ tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
*locked_out = 0;
log_info(LD_FS, "Locking \"%s\"", filename);
- fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
+ fd = tor_open_cloexec(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
if (fd < 0) {
log_warn(LD_FS,"Couldn't open \"%s\" for locking: %s", filename,
strerror(errno));
@@ -922,8 +951,16 @@ mark_socket_open(tor_socket_t s)
tor_socket_t
tor_open_socket(int domain, int type, int protocol)
{
- tor_socket_t s = socket(domain, type, protocol);
+ tor_socket_t s;
+#ifdef SOCK_CLOEXEC
+#define LINUX_CLOEXEC_OPEN_SOCKET
+ type |= SOCK_CLOEXEC;
+#endif
+ s = socket(domain, type, protocol);
if (SOCKET_OK(s)) {
+#if !defined(LINUX_CLOEXEC_OPEN_SOCKET) && defined(FD_CLOEXEC)
+ fcntl(s, F_SETFD, FD_CLOEXEC);
+#endif
socket_accounting_lock();
++n_sockets_open;
mark_socket_open(s);
@@ -936,8 +973,17 @@ tor_open_socket(int domain, int type, int protocol)
tor_socket_t
tor_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *len)
{
- tor_socket_t s = accept(sockfd, addr, len);
+ tor_socket_t s;
+#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC)
+#define LINUX_CLOEXEC_ACCEPT
+ s = accept4(sockfd, addr, len, SOCK_CLOEXEC);
+#else
+ s = accept(sockfd, addr, len);
+#endif
if (SOCKET_OK(s)) {
+#if !defined(LINUX_CLOEXEC_ACCEPT) && defined(FD_CLOEXEC)
+ fcntl(s, F_SETFD, FD_CLOEXEC);
+#endif
socket_accounting_lock();
++n_sockets_open;
mark_socket_open(s);
@@ -993,8 +1039,17 @@ tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
//don't use win32 socketpairs (they are always bad)
#if defined(HAVE_SOCKETPAIR) && !defined(MS_WINDOWS)
int r;
+#ifdef SOCK_CLOEXEC
+ type |= SOCK_CLOEXEC;
+#endif
r = socketpair(family, type, protocol, fd);
if (r == 0) {
+#if !defined(SOCK_CLOEXEC) && defined(FD_CLOEXEC)
+ if (fd[0] >= 0)
+ fcntl(fd[0], F_SETFD, FD_CLOEXEC);
+ if (fd[1] >= 0)
+ fcntl(fd[1], F_SETFD, FD_CLOEXEC);
+#endif
socket_accounting_lock();
if (fd[0] >= 0) {
++n_sockets_open;
@@ -1806,6 +1861,7 @@ get_uname(void)
static struct {
unsigned major; unsigned minor; const char *version;
} win_version_table[] = {
+ { 6, 2, "Windows 8" },
{ 6, 1, "Windows 7" },
{ 6, 0, "Windows Vista" },
{ 5, 2, "Windows Server 2003" },
@@ -1862,7 +1918,7 @@ get_uname(void)
plat, extra);
} else {
if (info.dwMajorVersion > 6 ||
- (info.dwMajorVersion==6 && info.dwMinorVersion>1))
+ (info.dwMajorVersion==6 && info.dwMinorVersion>2))
tor_snprintf(uname_result, sizeof(uname_result),
"Very recent version of Windows [major=%d,minor=%d] %s",
(int)info.dwMajorVersion,(int)info.dwMinorVersion,
@@ -1994,6 +2050,52 @@ spawn_exit(void)
#endif
}
+/** Implementation logic for compute_num_cpus(). */
+static int
+compute_num_cpus_impl(void)
+{
+#ifdef MS_WINDOWS
+ SYSTEM_INFO info;
+ memset(&info, 0, sizeof(info));
+ GetSystemInfo(&info);
+ if (info.dwNumberOfProcessors >= 1 && info.dwNumberOfProcessors < INT_MAX)
+ return (int)info.dwNumberOfProcessors;
+ else
+ return -1;
+#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF)
+ long cpus = sysconf(_SC_NPROCESSORS_CONF);
+ if (cpus >= 1 && cpus < INT_MAX)
+ return (int)cpus;
+ else
+ return -1;
+#else
+ return -1;
+#endif
+}
+
+#define MAX_DETECTABLE_CPUS 16
+
+/** Return how many CPUs we are running with. We assume that nobody is
+ * using hot-swappable CPUs, so we don't recompute this after the first
+ * time. Return -1 if we don't know how to tell the number of CPUs on this
+ * system.
+ */
+int
+compute_num_cpus(void)
+{
+ static int num_cpus = -2;
+ if (num_cpus == -2) {
+ num_cpus = compute_num_cpus_impl();
+ tor_assert(num_cpus != -2);
+ if (num_cpus > MAX_DETECTABLE_CPUS)
+ log_notice(LD_GENERAL, "Wow! I detected that you have %d CPUs. I "
+ "will not autodetect any more than %d, though. If you "
+ "want to configure more, set NumCPUs in your torrc",
+ num_cpus, MAX_DETECTABLE_CPUS);
+ }
+ return num_cpus;
+}
+
/** Set *timeval to the current time of day. On error, log and terminate.
* (Same as gettimeofday(timeval,NULL), but never returns -1.)
*/
diff --git a/src/common/compat.h b/src/common/compat.h
index eb79b0444..8e271ba90 100644
--- a/src/common/compat.h
+++ b/src/common/compat.h
@@ -9,8 +9,12 @@
#include "orconfig.h"
#include "torint.h"
#ifdef MS_WINDOWS
+#ifndef WIN32_WINNT
#define WIN32_WINNT 0x400
+#endif
+#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x400
+#endif
#define WIN32_LEAN_AND_MEAN
#if defined(_MSC_VER) && (_MSC_VER < 1300)
#include <winsock.h>
@@ -51,6 +55,8 @@
#include <netinet6/in6.h>
#endif
+#include <stdio.h>
+
#if defined (WINCE)
#include <fcntl.h>
#include <io.h>
@@ -367,6 +373,9 @@ struct tm *tor_gmtime_r(const time_t *timep, struct tm *result);
#endif
/* ===== File compatibility */
+int tor_open_cloexec(const char *path, int flags, unsigned mode);
+FILE *tor_fopen_cloexec(const char *path, const char *mode);
+
int replace_file(const char *from, const char *to);
int touch_file(const char *fname);
@@ -392,7 +401,7 @@ typedef int socklen_t;
#ifdef MS_WINDOWS
#define tor_socket_t intptr_t
-#define SOCKET_OK(s) ((s) != INVALID_SOCKET)
+#define SOCKET_OK(s) ((unsigned)(s) != INVALID_SOCKET)
#else
#define tor_socket_t int
#define SOCKET_OK(s) ((s) >= 0)
@@ -577,6 +586,8 @@ void spawn_exit(void) ATTR_NORETURN;
#undef TOR_IS_MULTITHREADED
#endif
+int compute_num_cpus(void);
+
/* Because we use threads instead of processes on most platforms (Windows,
* Linux, etc), we need locking for them. On platforms with poor thread
* support or broken gethostbyname_r, these functions are no-ops. */
diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c
index 6d89be804..320173870 100644
--- a/src/common/compat_libevent.c
+++ b/src/common/compat_libevent.c
@@ -19,6 +19,10 @@
#ifdef HAVE_EVENT2_EVENT_H
#include <event2/event.h>
+#include <event2/thread.h>
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent.h>
+#endif
#else
#include <event.h>
#endif
@@ -163,11 +167,24 @@ struct event_base *the_event_base = NULL;
#endif
#endif
+#ifdef USE_BUFFEREVENTS
+static int using_iocp_bufferevents = 0;
+static void tor_libevent_set_tick_timeout(int msec_per_tick);
+
+int
+tor_libevent_using_iocp_bufferevents(void)
+{
+ return using_iocp_bufferevents;
+}
+#endif
+
/** Initialize the Libevent library and set up the event base. */
void
-tor_libevent_initialize(void)
+tor_libevent_initialize(tor_libevent_cfg *torcfg)
{
tor_assert(the_event_base == NULL);
+ /* some paths below don't use torcfg, so avoid unused variable warnings */
+ (void)torcfg;
#ifdef __APPLE__
if (MACOSX_KQUEUE_IS_BROKEN ||
@@ -177,7 +194,32 @@ tor_libevent_initialize(void)
#endif
#ifdef HAVE_EVENT2_EVENT_H
- the_event_base = event_base_new();
+ {
+ struct event_config *cfg = event_config_new();
+
+#if defined(MS_WINDOWS) && defined(USE_BUFFEREVENTS)
+ if (! torcfg->disable_iocp) {
+ evthread_use_windows_threads();
+ event_config_set_flag(cfg, EVENT_BASE_FLAG_STARTUP_IOCP);
+ using_iocp_bufferevents = 1;
+ }
+#endif
+
+#if defined(LIBEVENT_VERSION_NUMBER) && LIBEVENT_VERSION_NUMBER >= V(2,0,7)
+ if (torcfg->num_cpus > 0)
+ event_config_set_num_cpus_hint(cfg, torcfg->num_cpus);
+#endif
+
+#if LIBEVENT_VERSION_NUMBER >= V(2,0,9)
+ /* We can enable changelist support with epoll, since we don't give
+ * Libevent any dup'd fds. This lets us avoid some syscalls. */
+ event_config_set_flag(cfg, EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST);
+#endif
+
+ the_event_base = event_base_new_with_config(cfg);
+
+ event_config_free(cfg);
+ }
#else
the_event_base = event_init();
#endif
@@ -195,6 +237,10 @@ tor_libevent_initialize(void)
"You have a *VERY* old version of libevent. It is likely to be buggy; "
"please build Tor with a more recent version.");
#endif
+
+#ifdef USE_BUFFEREVENTS
+ tor_libevent_set_tick_timeout(torcfg->msec_per_tick);
+#endif
}
/** Return the current Libevent event base that we're set up to use. */
@@ -240,7 +286,7 @@ tor_decode_libevent_version(const char *v)
/* Try the new preferred "1.4.11-stable" format.
* Also accept "1.4.14b-stable". */
- fields = sscanf(v, "%u.%u.%u%c%c", &major, &minor, &patchlevel, &c, &e);
+ fields = tor_sscanf(v, "%u.%u.%u%c%c", &major, &minor, &patchlevel, &c, &e);
if (fields == 3 ||
((fields == 4 || fields == 5 ) && (c == '-' || c == '_')) ||
(fields == 5 && TOR_ISALPHA(c) && (e == '-' || e == '_'))) {
@@ -248,7 +294,7 @@ tor_decode_libevent_version(const char *v)
}
/* Try the old "1.3e" format. */
- fields = sscanf(v, "%u.%u%c%c", &major, &minor, &c, &extra);
+ fields = tor_sscanf(v, "%u.%u%c%c", &major, &minor, &c, &extra);
if (fields == 3 && TOR_ISALPHA(c)) {
return V_OLD(major, minor, c);
} else if (fields == 2) {
@@ -552,3 +598,55 @@ periodic_timer_free(periodic_timer_t *timer)
tor_free(timer);
}
+#ifdef USE_BUFFEREVENTS
+static const struct timeval *one_tick = NULL;
+/**
+ * Return a special timeout to be passed whenever libevent's O(1) timeout
+ * implementation should be used. Only use this when the timer is supposed
+ * to fire after msec_per_tick ticks have elapsed.
+*/
+const struct timeval *
+tor_libevent_get_one_tick_timeout(void)
+{
+ tor_assert(one_tick);
+ return one_tick;
+}
+
+/** Initialize the common timeout that we'll use to refill the buckets every
+ * time a tick elapses. */
+static void
+tor_libevent_set_tick_timeout(int msec_per_tick)
+{
+ struct event_base *base = tor_libevent_get_base();
+ struct timeval tv;
+
+ tor_assert(! one_tick);
+ tv.tv_sec = msec_per_tick / 1000;
+ tv.tv_usec = (msec_per_tick % 1000) * 1000;
+ one_tick = event_base_init_common_timeout(base, &tv);
+}
+
+static struct bufferevent *
+tor_get_root_bufferevent(struct bufferevent *bev)
+{
+ struct bufferevent *u;
+ while ((u = bufferevent_get_underlying(bev)) != NULL)
+ bev = u;
+ return bev;
+}
+
+int
+tor_set_bufferevent_rate_limit(struct bufferevent *bev,
+ struct ev_token_bucket_cfg *cfg)
+{
+ return bufferevent_set_rate_limit(tor_get_root_bufferevent(bev), cfg);
+}
+
+int
+tor_add_bufferevent_to_rate_limit_group(struct bufferevent *bev,
+ struct bufferevent_rate_limit_group *g)
+{
+ return bufferevent_add_to_rate_limit_group(tor_get_root_bufferevent(bev), g);
+}
+#endif
+
diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h
index 89b256396..024729717 100644
--- a/src/common/compat_libevent.h
+++ b/src/common/compat_libevent.h
@@ -8,6 +8,11 @@
struct event;
struct event_base;
+#ifdef USE_BUFFEREVENTS
+struct bufferevent;
+struct ev_token_bucket_cfg;
+struct bufferevent_rate_limit_group;
+#endif
#ifdef HAVE_EVENT2_EVENT_H
#include <event2/util.h>
@@ -54,7 +59,13 @@ struct timeval;
int tor_event_base_loopexit(struct event_base *base, struct timeval *tv);
#endif
-void tor_libevent_initialize(void);
+typedef struct tor_libevent_cfg {
+ int disable_iocp;
+ int num_cpus;
+ int msec_per_tick;
+} tor_libevent_cfg;
+
+void tor_libevent_initialize(tor_libevent_cfg *cfg);
struct event_base *tor_libevent_get_base(void);
const char *tor_libevent_get_method(void);
void tor_check_libevent_version(const char *m, int server,
@@ -62,5 +73,14 @@ void tor_check_libevent_version(const char *m, int server,
void tor_check_libevent_header_compatibility(void);
const char *tor_libevent_get_version_str(void);
+#ifdef USE_BUFFEREVENTS
+const struct timeval *tor_libevent_get_one_tick_timeout(void);
+int tor_libevent_using_iocp_bufferevents(void);
+int tor_set_bufferevent_rate_limit(struct bufferevent *bev,
+ struct ev_token_bucket_cfg *cfg);
+int tor_add_bufferevent_to_rate_limit_group(struct bufferevent *bev,
+ struct bufferevent_rate_limit_group *g);
+#endif
+
#endif
diff --git a/src/common/container.c b/src/common/container.c
index 1515c387a..92bfd2ec8 100644
--- a/src/common/container.c
+++ b/src/common/container.c
@@ -287,7 +287,6 @@ smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2)
/** Remove the <b>idx</b>th element of sl; if idx is not the last
* element, swap the last element of sl into the <b>idx</b>th space.
- * Return the old value of the <b>idx</b>th element.
*/
void
smartlist_del(smartlist_t *sl, int idx)
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 851f11bf3..9ad7575a7 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -13,8 +13,12 @@
#include "orconfig.h"
#ifdef MS_WINDOWS
+#ifndef WIN32_WINNT
#define WIN32_WINNT 0x400
+#endif
+#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x400
+#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <wincrypt.h>
@@ -948,7 +952,7 @@ crypto_pk_public_checksig_digest(crypto_pk_env_t *env, const char *data,
log_warn(LD_BUG, "couldn't compute digest");
return -1;
}
- buflen = crypto_pk_keysize(env)+1;
+ buflen = crypto_pk_keysize(env);
buf = tor_malloc(buflen);
r = crypto_pk_public_checksig(env,buf,buflen,sig,siglen);
if (r != DIGEST_LEN) {
@@ -1133,8 +1137,8 @@ crypto_pk_private_hybrid_decrypt(crypto_pk_env_t *env,
warnOnFailure);
}
- buf = tor_malloc(pkeylen+1);
- outlen = crypto_pk_private_decrypt(env,buf,pkeylen+1,from,pkeylen,padding,
+ buf = tor_malloc(pkeylen);
+ outlen = crypto_pk_private_decrypt(env,buf,pkeylen,from,pkeylen,padding,
warnOnFailure);
if (outlen<0) {
log_fn(warnOnFailure?LOG_WARN:LOG_DEBUG, LD_CRYPTO,
diff --git a/src/common/crypto.h b/src/common/crypto.h
index 1a8c81f83..9b4eee622 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -245,7 +245,8 @@ void secret_to_key(char *key_out, size_t key_out_len, const char *secret,
size_t secret_len, const char *s2k_specifier);
#ifdef CRYPTO_PRIVATE
-/* Prototypes for private functions only used by tortls.c and crypto.c */
+/* Prototypes for private functions only used by tortls.c, crypto.c, and the
+ * unit tests. */
struct rsa_st;
struct evp_pkey_st;
struct dh_st;
diff --git a/src/common/log.c b/src/common/log.c
index ac98f1353..97400623e 100644
--- a/src/common/log.c
+++ b/src/common/log.c
@@ -154,6 +154,17 @@ log_set_application_name(const char *name)
appname = name ? tor_strdup(name) : NULL;
}
+/** Log time granularity in milliseconds. */
+static int log_time_granularity = 1;
+
+/** Define log time granularity for all logs to be <b>granularity_msec</b>
+ * milliseconds. */
+void
+set_log_time_granularity(int granularity_msec)
+{
+ log_time_granularity = granularity_msec;
+}
+
/** Helper: Write the standard prefix for log lines to a
* <b>buf_len</b> character buffer in <b>buf</b>.
*/
@@ -164,14 +175,22 @@ _log_prefix(char *buf, size_t buf_len, int severity)
struct timeval now;
struct tm tm;
size_t n;
- int r;
+ int r, ms;
tor_gettimeofday(&now);
t = (time_t)now.tv_sec;
+ ms = (int)now.tv_usec / 1000;
+ if (log_time_granularity >= 1000) {
+ t -= t % (log_time_granularity / 1000);
+ ms = 0;
+ } else {
+ ms -= ((int)now.tv_usec / 1000) % log_time_granularity;
+ }
n = strftime(buf, buf_len, "%b %d %H:%M:%S", tor_localtime_r(&t, &tm));
- r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ",
- (int)now.tv_usec / 1000, sev_to_string(severity));
+ r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ", ms,
+ sev_to_string(severity));
+
if (r<0)
return buf_len-1;
else
@@ -703,7 +722,7 @@ change_callback_log_severity(int loglevelMin, int loglevelMax,
UNLOCK_LOGS();
}
-/** If there are any log messages that were genered with LD_NOCB waiting to
+/** If there are any log messages that were generated with LD_NOCB waiting to
* be sent to callback-based loggers, send them now. */
void
flush_pending_log_callbacks(void)
@@ -803,7 +822,7 @@ add_file_log(const log_severity_list_t *severity, const char *filename)
int fd;
logfile_t *lf;
- fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0644);
+ fd = tor_open_cloexec(filename, O_WRONLY|O_CREAT|O_APPEND, 0644);
if (fd<0)
return -1;
if (tor_fd_seekend(fd)<0)
@@ -880,7 +899,7 @@ log_level_to_string(int level)
static const char *domain_list[] = {
"GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM",
"HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV",
- "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", NULL
+ "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", NULL
};
/** Return a bitmask for the log domain for which <b>domain</b> is the name,
diff --git a/src/common/mempool.c b/src/common/mempool.c
index c44492318..30d778804 100644
--- a/src/common/mempool.c
+++ b/src/common/mempool.c
@@ -137,7 +137,7 @@ struct mp_chunk_t {
int capacity; /**< Number of items that can be fit into this chunk. */
size_t mem_size; /**< Number of usable bytes in mem. */
char *next_mem; /**< Pointer into part of <b>mem</b> not yet carved up. */
- char mem[1]; /**< Storage for this chunk. (Not actual size.) */
+ char mem[FLEXIBLE_ARRAY_MEMBER]; /**< Storage for this chunk. */
};
/** Number of extra bytes needed beyond mem_size to allocate a chunk. */
diff --git a/src/common/torgzip.c b/src/common/torgzip.c
index 2937c67de..62e4a0703 100644
--- a/src/common/torgzip.c
+++ b/src/common/torgzip.c
@@ -14,11 +14,12 @@
#include <stdio.h>
#include <assert.h>
#include <string.h>
+#include "torint.h"
+
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
-#include "torint.h"
#include "util.h"
#include "torlog.h"
#include "torgzip.h"
@@ -43,11 +44,7 @@
#define off64_t int64_t
#endif
-#ifdef _MSC_VER
-#include "..\..\contrib\zlib\zlib.h"
-#else
#include <zlib.h>
-#endif
/** Set to 1 if zlib is a version that supports gzip; set to 0 if it doesn't;
* set to -1 if we haven't checked yet. */
diff --git a/src/common/torint.h b/src/common/torint.h
index 0b5c29adc..af975471f 100644
--- a/src/common/torint.h
+++ b/src/common/torint.h
@@ -111,6 +111,15 @@ typedef signed int int32_t;
typedef unsigned int uint32_t;
#define HAVE_UINT32_T
#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX 0xffffu
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX 0x7fff
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-INT16_MAX-1)
+#endif
#ifndef UINT32_MAX
#define UINT32_MAX 0xffffffffu
#endif
diff --git a/src/common/torlog.h b/src/common/torlog.h
index 541a0d173..4c5729ef5 100644
--- a/src/common/torlog.h
+++ b/src/common/torlog.h
@@ -92,8 +92,10 @@
#define LD_HIST (1u<<18)
/** OR handshaking */
#define LD_HANDSHAKE (1u<<19)
+/** Heartbeat messages */
+#define LD_HEARTBEAT (1u<<20)
/** Number of logging domains in the code. */
-#define N_LOGGING_DOMAINS 20
+#define N_LOGGING_DOMAINS 21
/** This log message is not safe to send to a callback-based logger
* immediately. Used as a flag, not a log domain. */
@@ -145,6 +147,7 @@ void change_callback_log_severity(int loglevelMin, int loglevelMax,
log_callback cb);
void flush_pending_log_callbacks(void);
void log_set_application_name(const char *name);
+void set_log_time_granularity(int granularity_msec);
void tor_log(int severity, log_domain_mask_t domain, const char *format, ...)
CHECK_PRINTF(3,4);
diff --git a/src/common/tortls.c b/src/common/tortls.c
index 10f4440cb..1bb9c74ef 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -22,8 +22,12 @@
#include <assert.h>
#ifdef MS_WINDOWS /*wrkard for dtls1.h >= 0.9.8m of "#include <winsock.h>"*/
+ #ifndef WIN32_WINNT
#define WIN32_WINNT 0x400
+ #endif
+ #ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x400
+ #endif
#define WIN32_LEAN_AND_MEAN
#if defined(_MSC_VER) && (_MSC_VER < 1300)
#include <winsock.h>
@@ -44,14 +48,21 @@
#error "We require OpenSSL >= 0.9.7"
#endif
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent_ssl.h>
+#include <event2/buffer.h>
+#include <event2/event.h>
+#include "compat_libevent.h"
+#endif
+
#define CRYPTO_PRIVATE /* to import prototypes from crypto.h */
+#define TORTLS_PRIVATE
#include "crypto.h"
#include "tortls.h"
#include "util.h"
#include "torlog.h"
#include "container.h"
-#include "ht.h"
#include <string.h>
/* Enable the "v2" TLS handshake.
@@ -97,11 +108,13 @@ typedef struct tor_tls_context_t {
crypto_pk_env_t *key;
} tor_tls_context_t;
+#define TOR_TLS_MAGIC 0x71571571
+
/** Holds a SSL object and its associated data. Members are only
* accessed from within tortls.c.
*/
struct tor_tls_t {
- HT_ENTRY(tor_tls_t) node;
+ uint32_t magic;
tor_tls_context_t *context; /** A link to the context object for this tls. */
SSL *ssl; /**< An OpenSSL SSL object. */
int socket; /**< The underlying file descriptor for this TLS connection. */
@@ -109,6 +122,7 @@ struct tor_tls_t {
enum {
TOR_TLS_ST_HANDSHAKE, TOR_TLS_ST_OPEN, TOR_TLS_ST_GOTCLOSE,
TOR_TLS_ST_SENTCLOSE, TOR_TLS_ST_CLOSED, TOR_TLS_ST_RENEGOTIATE,
+ TOR_TLS_ST_BUFFEREVENT
} state : 3; /**< The current SSL state, depending on which operations have
* completed successfully. */
unsigned int isServer:1; /**< True iff this is a server-side connection */
@@ -117,8 +131,10 @@ struct tor_tls_t {
* of the connection protocol (client sends
* different cipher list, server sends only
* one certificate). */
- /** True iff we should call negotiated_callback when we're done reading. */
+ /** True iff we should call negotiated_callback when we're done reading. */
unsigned int got_renegotiate:1;
+ /** Incremented every time we start the server side of a handshake. */
+ uint8_t server_handshake_count;
size_t wantwrite_n; /**< 0 normally, >0 if we returned wantwrite last
* time. */
/** Last values retrieved from BIO_number_read()/write(); see
@@ -143,42 +159,29 @@ static SSL_CIPHER *CLIENT_CIPHER_DUMMIES = NULL;
static STACK_OF(SSL_CIPHER) *CLIENT_CIPHER_STACK = NULL;
#endif
-/** Helper: compare tor_tls_t objects by its SSL. */
-static INLINE int
-tor_tls_entries_eq(const tor_tls_t *a, const tor_tls_t *b)
-{
- return a->ssl == b->ssl;
-}
+/** The ex_data index in which we store a pointer to an SSL object's
+ * corresponding tor_tls_t object. */
+static int tor_tls_object_ex_data_index = -1;
-/** Helper: return a hash value for a tor_tls_t by its SSL. */
-static INLINE unsigned int
-tor_tls_entry_hash(const tor_tls_t *a)
+/** Helper: Allocate tor_tls_object_ex_data_index. */
+static void
+tor_tls_allocate_tor_tls_object_ex_data_index(void)
{
-#if SIZEOF_INT == SIZEOF_VOID_P
- return ((unsigned int)(uintptr_t)a->ssl);
-#else
- return (unsigned int) ((((uint64_t)a->ssl)>>2) & UINT_MAX);
-#endif
+ if (tor_tls_object_ex_data_index == -1) {
+ tor_tls_object_ex_data_index =
+ SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+ tor_assert(tor_tls_object_ex_data_index != -1);
+ }
}
-/** Map from SSL* pointers to tor_tls_t objects using those pointers.
- */
-static HT_HEAD(tlsmap, tor_tls_t) tlsmap_root = HT_INITIALIZER();
-
-HT_PROTOTYPE(tlsmap, tor_tls_t, node, tor_tls_entry_hash,
- tor_tls_entries_eq)
-HT_GENERATE(tlsmap, tor_tls_t, node, tor_tls_entry_hash,
- tor_tls_entries_eq, 0.6, malloc, realloc, free)
-
/** Helper: given a SSL* pointer, return the tor_tls_t object using that
* pointer. */
static INLINE tor_tls_t *
tor_tls_get_by_ssl(const SSL *ssl)
{
- tor_tls_t search, *result;
- memset(&search, 0, sizeof(search));
- search.ssl = (SSL*)ssl;
- result = HT_FIND(tlsmap, &tlsmap_root, &search);
+ tor_tls_t *result = SSL_get_ex_data(ssl, tor_tls_object_ex_data_index);
+ if (result)
+ tor_assert(result->magic == TOR_TLS_MAGIC);
return result;
}
@@ -189,7 +192,7 @@ static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa,
const char *cname,
const char *cname_sign,
unsigned int lifetime);
-static void tor_tls_unblock_renegotiation(tor_tls_t *tls);
+
static int tor_tls_context_init_one(tor_tls_context_t **ppcontext,
crypto_pk_env_t *identity,
unsigned int key_lifetime);
@@ -200,6 +203,7 @@ static tor_tls_context_t *tor_tls_context_new(crypto_pk_env_t *identity,
* to touch them. */
static tor_tls_context_t *server_tls_context = NULL;
static tor_tls_context_t *client_tls_context = NULL;
+
/** True iff tor_tls_init() has been called. */
static int tls_library_is_initialized = 0;
@@ -223,36 +227,96 @@ ssl_state_to_string(int ssl_state)
return buf;
}
+/** Write a description of the current state of <b>tls</b> into the
+ * <b>sz</b>-byte buffer at <b>buf</b>. */
+void
+tor_tls_get_state_description(tor_tls_t *tls, char *buf, size_t sz)
+{
+ const char *ssl_state;
+ const char *tortls_state;
+
+ if (PREDICT_UNLIKELY(!tls || !tls->ssl)) {
+ strlcpy(buf, "(No SSL object)", sz);
+ return;
+ }
+
+ ssl_state = ssl_state_to_string(tls->ssl->state);
+ switch (tls->state) {
+#define CASE(st) case TOR_TLS_ST_##st: tortls_state = " in "#st ; break
+ CASE(HANDSHAKE);
+ CASE(OPEN);
+ CASE(GOTCLOSE);
+ CASE(SENTCLOSE);
+ CASE(CLOSED);
+ CASE(RENEGOTIATE);
+#undef CASE
+ case TOR_TLS_ST_BUFFEREVENT:
+ tortls_state = "";
+ break;
+ default:
+ tortls_state = " in unknown TLS state";
+ break;
+ }
+
+ tor_snprintf(buf, sz, "%s%s", ssl_state, tortls_state);
+}
+
+void
+tor_tls_log_one_error(tor_tls_t *tls, unsigned long err,
+ int severity, int domain, const char *doing)
+{
+ const char *state = NULL, *addr;
+ const char *msg, *lib, *func;
+ int st;
+
+ st = (tls && tls->ssl) ? tls->ssl->state : -1;
+ state = (st>=0)?ssl_state_to_string(st):"---";
+
+ addr = tls ? tls->address : NULL;
+
+ /* Some errors are known-benign, meaning they are the fault of the other
+ * side of the connection. The caller doesn't know this, so override the
+ * priority for those cases. */
+ switch (ERR_GET_REASON(err)) {
+ case SSL_R_HTTP_REQUEST:
+ case SSL_R_HTTPS_PROXY_REQUEST:
+ case SSL_R_RECORD_LENGTH_MISMATCH:
+ case SSL_R_RECORD_TOO_LARGE:
+ case SSL_R_UNKNOWN_PROTOCOL:
+ case SSL_R_UNSUPPORTED_PROTOCOL:
+ severity = LOG_INFO;
+ break;
+ default:
+ break;
+ }
+
+ msg = (const char*)ERR_reason_error_string(err);
+ lib = (const char*)ERR_lib_error_string(err);
+ func = (const char*)ERR_func_error_string(err);
+ if (!msg) msg = "(null)";
+ if (!lib) lib = "(null)";
+ if (!func) func = "(null)";
+ if (doing) {
+ log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)",
+ doing, addr?" with ":"", addr?addr:"",
+ msg, lib, func, state);
+ } else {
+ log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)",
+ addr?" with ":"", addr?addr:"",
+ msg, lib, func, state);
+ }
+}
+
/** Log all pending tls errors at level <b>severity</b>. Use
* <b>doing</b> to describe our current activities.
*/
static void
tls_log_errors(tor_tls_t *tls, int severity, int domain, const char *doing)
{
- const char *state = NULL;
- int st;
unsigned long err;
- const char *msg, *lib, *func, *addr;
- addr = tls ? tls->address : NULL;
- st = (tls && tls->ssl) ? tls->ssl->state : -1;
+
while ((err = ERR_get_error()) != 0) {
- msg = (const char*)ERR_reason_error_string(err);
- lib = (const char*)ERR_lib_error_string(err);
- func = (const char*)ERR_func_error_string(err);
- if (!state)
- state = (st>=0)?ssl_state_to_string(st):"---";
- if (!msg) msg = "(null)";
- if (!lib) lib = "(null)";
- if (!func) func = "(null)";
- if (doing) {
- log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)",
- doing, addr?" with ":"", addr?addr:"",
- msg, lib, func, state);
- } else {
- log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)",
- addr?" with ":"", addr?addr:"",
- msg, lib, func, state);
- }
+ tor_tls_log_one_error(tls, err, severity, domain, doing);
}
}
@@ -427,6 +491,8 @@ tor_tls_init(void)
SSLeay_version(SSLEAY_VERSION), version);
}
+ tor_tls_allocate_tor_tls_object_ex_data_index();
+
tls_library_is_initialized = 1;
}
}
@@ -445,10 +511,6 @@ tor_tls_free_all(void)
client_tls_context = NULL;
tor_tls_context_decref(ctx);
}
- if (!HT_EMPTY(&tlsmap_root)) {
- log_warn(LD_MM, "Still have entries in the tlsmap at shutdown.");
- }
- HT_CLEAR(tlsmap, &tlsmap_root);
#ifdef V2_HANDSHAKE_CLIENT
if (CLIENT_CIPHER_DUMMIES)
tor_free(CLIENT_CIPHER_DUMMIES);
@@ -892,6 +954,13 @@ tor_tls_client_is_using_v2_ciphers(const SSL *ssl, const char *address)
return 1;
}
+static void
+tor_tls_debug_state_callback(const SSL *ssl, int type, int val)
+{
+ log_debug(LD_HANDSHAKE, "SSL %p is now in state %s [type=%d,val=%d].",
+ ssl, ssl_state_to_string(ssl->state), type, val);
+}
+
/** Invoked when we're accepting a connection on <b>ssl</b>, and the connection
* changes state. We use this:
* <ul><li>To alter the state of the handshake partway through, so we
@@ -903,6 +972,9 @@ tor_tls_server_info_callback(const SSL *ssl, int type, int val)
{
tor_tls_t *tls;
(void) val;
+
+ tor_tls_debug_state_callback(ssl, type, val);
+
if (type != SSL_CB_ACCEPT_LOOP)
return;
if (ssl->state != SSL3_ST_SW_SRVR_HELLO_A)
@@ -913,8 +985,11 @@ tor_tls_server_info_callback(const SSL *ssl, int type, int val)
/* Check whether we're watching for renegotiates. If so, this is one! */
if (tls->negotiated_callback)
tls->got_renegotiate = 1;
+ if (tls->server_handshake_count < 127) /*avoid any overflow possibility*/
+ ++tls->server_handshake_count;
} else {
log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
+ return;
}
/* Now check the cipher list. */
@@ -931,6 +1006,10 @@ tor_tls_server_info_callback(const SSL *ssl, int type, int val)
if (tls) {
tls->wasV2Handshake = 1;
+#ifdef USE_BUFFEREVENTS
+ if (use_unsafe_renegotiation_flag)
+ tls->ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
+#endif
} else {
log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!");
}
@@ -1018,6 +1097,7 @@ tor_tls_new(int sock, int isServer)
tor_tls_t *result = tor_malloc_zero(sizeof(tor_tls_t));
tor_tls_context_t *context = isServer ? server_tls_context :
client_tls_context;
+ result->magic = TOR_TLS_MAGIC;
tor_assert(context); /* make sure somebody made it first */
if (!(result->ssl = SSL_new(context->ctx))) {
@@ -1058,7 +1138,14 @@ tor_tls_new(int sock, int isServer)
tor_free(result);
return NULL;
}
- HT_INSERT(tlsmap, &tlsmap_root, result);
+ {
+ int set_worked =
+ SSL_set_ex_data(result->ssl, tor_tls_object_ex_data_index, result);
+ if (!set_worked) {
+ log_warn(LD_BUG,
+ "Couldn't set the tls for an SSL*; connection will fail");
+ }
+ }
SSL_set_bio(result->ssl, bio, bio);
tor_tls_context_incref(context);
result->context = context;
@@ -1074,8 +1161,11 @@ tor_tls_new(int sock, int isServer)
#ifdef V2_HANDSHAKE_SERVER
if (isServer) {
SSL_set_info_callback(result->ssl, tor_tls_server_info_callback);
- }
+ } else
#endif
+ {
+ SSL_set_info_callback(result->ssl, tor_tls_debug_state_callback);
+ }
/* Not expected to get called. */
tls_log_errors(NULL, LOG_WARN, LD_NET, "creating tor_tls_t object");
@@ -1109,7 +1199,7 @@ tor_tls_set_renegotiate_callback(tor_tls_t *tls,
if (cb) {
SSL_set_info_callback(tls->ssl, tor_tls_server_info_callback);
} else {
- SSL_set_info_callback(tls->ssl, NULL);
+ SSL_set_info_callback(tls->ssl, tor_tls_debug_state_callback);
}
#endif
}
@@ -1117,7 +1207,7 @@ tor_tls_set_renegotiate_callback(tor_tls_t *tls,
/** If this version of openssl requires it, turn on renegotiation on
* <b>tls</b>.
*/
-static void
+void
tor_tls_unblock_renegotiation(tor_tls_t *tls)
{
/* Yes, we know what we are doing here. No, we do not treat a renegotiation
@@ -1141,6 +1231,19 @@ tor_tls_block_renegotiation(tor_tls_t *tls)
tls->ssl->s3->flags &= ~SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
}
+void
+tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls)
+{
+ if (use_unsafe_renegotiation_flag) {
+ tor_assert(0 != (tls->ssl->s3->flags &
+ SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
+ }
+ if (use_unsafe_renegotiation_op) {
+ long options = SSL_get_options(tls->ssl);
+ tor_assert(0 != (options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
+ }
+}
+
/** Return whether this tls initiated the connect (client) or
* received it (server). */
int
@@ -1156,14 +1259,9 @@ tor_tls_is_server(tor_tls_t *tls)
void
tor_tls_free(tor_tls_t *tls)
{
- tor_tls_t *removed;
if (!tls)
return;
tor_assert(tls->ssl);
- removed = HT_REMOVE(tlsmap, &tlsmap_root, tls);
- if (!removed) {
- log_warn(LD_BUG, "Freeing a TLS that was not in the ssl->tls map.");
- }
#ifdef SSL_set_tlsext_host_name
SSL_set_tlsext_host_name(tls->ssl, NULL);
#endif
@@ -1173,6 +1271,7 @@ tor_tls_free(tor_tls_t *tls)
if (tls->context)
tor_tls_context_decref(tls->context);
tor_free(tls->address);
+ tls->magic = 0x99999999;
tor_free(tls);
}
@@ -1285,56 +1384,86 @@ tor_tls_handshake(tor_tls_t *tls)
}
if (r == TOR_TLS_DONE) {
tls->state = TOR_TLS_ST_OPEN;
- if (tls->isServer) {
- SSL_set_info_callback(tls->ssl, NULL);
- SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb);
- /* There doesn't seem to be a clear OpenSSL API to clear mode flags. */
- tls->ssl->mode &= ~SSL_MODE_NO_AUTO_CHAIN;
+ return tor_tls_finish_handshake(tls);
+ }
+ return r;
+}
+
+/** Perform the final part of the intial TLS handshake on <b>tls</b>. This
+ * should be called for the first handshake only: it determines whether the v1
+ * or the v2 handshake was used, and adjusts things for the renegotiation
+ * handshake as appropriate.
+ *
+ * tor_tls_handshake() calls this on its own; you only need to call this if
+ * bufferevent is doing the handshake for you.
+ */
+int
+tor_tls_finish_handshake(tor_tls_t *tls)
+{
+ int r = TOR_TLS_DONE;
+ if (tls->isServer) {
+ SSL_set_info_callback(tls->ssl, NULL);
+ SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb);
+ /* There doesn't seem to be a clear OpenSSL API to clear mode flags. */
+ tls->ssl->mode &= ~SSL_MODE_NO_AUTO_CHAIN;
#ifdef V2_HANDSHAKE_SERVER
- if (tor_tls_client_is_using_v2_ciphers(tls->ssl, ADDR(tls))) {
- /* This check is redundant, but back when we did it in the callback,
- * we might have not been able to look up the tor_tls_t if the code
- * was buggy. Fixing that. */
- if (!tls->wasV2Handshake) {
- log_warn(LD_BUG, "For some reason, wasV2Handshake didn't"
- " get set. Fixing that.");
- }
- tls->wasV2Handshake = 1;
- log_debug(LD_HANDSHAKE,
- "Completed V2 TLS handshake with client; waiting "
- "for renegotiation.");
- } else {
- tls->wasV2Handshake = 0;
+ if (tor_tls_client_is_using_v2_ciphers(tls->ssl, ADDR(tls))) {
+ /* This check is redundant, but back when we did it in the callback,
+ * we might have not been able to look up the tor_tls_t if the code
+ * was buggy. Fixing that. */
+ if (!tls->wasV2Handshake) {
+ log_warn(LD_BUG, "For some reason, wasV2Handshake didn't"
+ " get set. Fixing that.");
}
-#endif
+ tls->wasV2Handshake = 1;
+ log_debug(LD_HANDSHAKE, "Completed V2 TLS handshake with client; waiting"
+ " for renegotiation.");
} else {
+ tls->wasV2Handshake = 0;
+ }
+#endif
+ } else {
#ifdef V2_HANDSHAKE_CLIENT
- /* If we got no ID cert, we're a v2 handshake. */
- X509 *cert = SSL_get_peer_certificate(tls->ssl);
- STACK_OF(X509) *chain = SSL_get_peer_cert_chain(tls->ssl);
- int n_certs = sk_X509_num(chain);
- if (n_certs > 1 || (n_certs == 1 && cert != sk_X509_value(chain, 0))) {
- log_debug(LD_HANDSHAKE, "Server sent back multiple certificates; it "
- "looks like a v1 handshake on %p", tls);
- tls->wasV2Handshake = 0;
- } else {
- log_debug(LD_HANDSHAKE,
- "Server sent back a single certificate; looks like "
- "a v2 handshake on %p.", tls);
- tls->wasV2Handshake = 1;
- }
- if (cert)
- X509_free(cert);
+ /* If we got no ID cert, we're a v2 handshake. */
+ X509 *cert = SSL_get_peer_certificate(tls->ssl);
+ STACK_OF(X509) *chain = SSL_get_peer_cert_chain(tls->ssl);
+ int n_certs = sk_X509_num(chain);
+ if (n_certs > 1 || (n_certs == 1 && cert != sk_X509_value(chain, 0))) {
+ log_debug(LD_HANDSHAKE, "Server sent back multiple certificates; it "
+ "looks like a v1 handshake on %p", tls);
+ tls->wasV2Handshake = 0;
+ } else {
+ log_debug(LD_HANDSHAKE,
+ "Server sent back a single certificate; looks like "
+ "a v2 handshake on %p.", tls);
+ tls->wasV2Handshake = 1;
+ }
+ if (cert)
+ X509_free(cert);
#endif
- if (SSL_set_cipher_list(tls->ssl, SERVER_CIPHER_LIST) == 0) {
- tls_log_errors(NULL, LOG_WARN, LD_HANDSHAKE, "re-setting ciphers");
- r = TOR_TLS_ERROR_MISC;
- }
+ if (SSL_set_cipher_list(tls->ssl, SERVER_CIPHER_LIST) == 0) {
+ tls_log_errors(NULL, LOG_WARN, LD_HANDSHAKE, "re-setting ciphers");
+ r = TOR_TLS_ERROR_MISC;
}
}
return r;
}
+#ifdef USE_BUFFEREVENTS
+/** Put <b>tls</b>, which must be a client connection, into renegotiation
+ * mode. */
+int
+tor_tls_start_renegotiating(tor_tls_t *tls)
+{
+ int r = SSL_renegotiate(tls->ssl);
+ if (r <= 0) {
+ return tor_tls_get_error(tls, r, 0, "renegotiating", LOG_WARN,
+ LD_HANDSHAKE);
+ }
+ return 0;
+}
+#endif
+
/** Client only: Renegotiate a TLS session. When finished, returns
* TOR_TLS_DONE. On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD, or
* TOR_TLS_WANTWRITE.
@@ -1551,6 +1680,8 @@ tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_env_t **identity_key)
log_fn(severity,LD_PROTOCOL,"No distinct identity certificate found");
goto done;
}
+ tls_log_errors(tls, severity, LD_HANDSHAKE, "before verifying certificate");
+
if (!(id_pkey = X509_get_pubkey(id_cert)) ||
X509_verify(cert, id_pkey) <= 0) {
log_fn(severity,LD_PROTOCOL,"X509_verify on cert and pkey returned <= 0");
@@ -1700,6 +1831,22 @@ tor_tls_used_v1_handshake(tor_tls_t *tls)
return 1;
}
+/** Return the number of server handshakes that we've noticed doing on
+ * <b>tls</b>. */
+int
+tor_tls_get_num_server_handshakes(tor_tls_t *tls)
+{
+ return tls->server_handshake_count;
+}
+
+/** Return true iff the server TLS connection <b>tls</b> got the renegotiation
+ * request it was waiting for. */
+int
+tor_tls_server_got_renegotiate(tor_tls_t *tls)
+{
+ return tls->got_renegotiate;
+}
+
/** Examine the amount of memory used and available for buffers in <b>tls</b>.
* Set *<b>rbuf_capacity</b> to the amount of storage allocated for the read
* buffer and *<b>rbuf_bytes</b> to the amount actually used.
@@ -1722,3 +1869,75 @@ tor_tls_get_buffer_sizes(tor_tls_t *tls,
*wbuf_bytes = tls->ssl->s3->wbuf.left;
}
+#ifdef USE_BUFFEREVENTS
+/** Construct and return an TLS-encrypting bufferevent to send data over
+ * <b>socket</b>, which must match the socket of the underlying bufferevent
+ * <b>bufev_in</b>. The TLS object <b>tls</b> is used for encryption.
+ *
+ * This function will either create a filtering bufferevent that wraps around
+ * <b>bufev_in</b>, or it will free bufev_in and return a new bufferevent that
+ * uses the <b>tls</b> to talk to the network directly. Do not use
+ * <b>bufev_in</b> after calling this function.
+ *
+ * The connection will start out doing a server handshake if <b>receiving</b>
+ * is strue, and a client handshake otherwise.
+ *
+ * Returns NULL on failure.
+ */
+struct bufferevent *
+tor_tls_init_bufferevent(tor_tls_t *tls, struct bufferevent *bufev_in,
+ evutil_socket_t socket, int receiving,
+ int filter)
+{
+ struct bufferevent *out;
+ const enum bufferevent_ssl_state state = receiving ?
+ BUFFEREVENT_SSL_ACCEPTING : BUFFEREVENT_SSL_CONNECTING;
+
+ if (filter || tor_libevent_using_iocp_bufferevents()) {
+ /* Grab an extra reference to the SSL, since BEV_OPT_CLOSE_ON_FREE
+ means that the SSL will get freed too.
+
+ This increment makes our SSL usage not-threadsafe, BTW. We should
+ see if we're allowed to use CRYPTO_add from outside openssl. */
+ tls->ssl->references += 1;
+ out = bufferevent_openssl_filter_new(tor_libevent_get_base(),
+ bufev_in,
+ tls->ssl,
+ state,
+ BEV_OPT_DEFER_CALLBACKS|
+ BEV_OPT_CLOSE_ON_FREE);
+ /* Tell the underlying bufferevent when to accept more data from the SSL
+ filter (only when it's got less than 32K to write), and when to notify
+ the SSL filter that it could write more (when it drops under 24K). */
+ bufferevent_setwatermark(bufev_in, EV_WRITE, 24*1024, 32*1024);
+ } else {
+ if (bufev_in) {
+ evutil_socket_t s = bufferevent_getfd(bufev_in);
+ tor_assert(s == -1 || s == socket);
+ tor_assert(evbuffer_get_length(bufferevent_get_input(bufev_in)) == 0);
+ tor_assert(evbuffer_get_length(bufferevent_get_output(bufev_in)) == 0);
+ tor_assert(BIO_number_read(SSL_get_rbio(tls->ssl)) == 0);
+ tor_assert(BIO_number_written(SSL_get_rbio(tls->ssl)) == 0);
+ bufferevent_free(bufev_in);
+ }
+
+ /* Current versions (as of 2.0.x) of Libevent need to defer
+ * bufferevent_openssl callbacks, or else our callback functions will
+ * get called reentrantly, which is bad for us.
+ */
+ out = bufferevent_openssl_socket_new(tor_libevent_get_base(),
+ socket,
+ tls->ssl,
+ state,
+ BEV_OPT_DEFER_CALLBACKS);
+ }
+ tls->state = TOR_TLS_ST_BUFFEREVENT;
+
+ /* Unblock _after_ creating the bufferevent, since accept/connect tend to
+ * clear flags. */
+ tor_tls_unblock_renegotiation(tls);
+
+ return out;
+}
+#endif
+
diff --git a/src/common/tortls.h b/src/common/tortls.h
index 55fee81ae..9b8108b42 100644
--- a/src/common/tortls.h
+++ b/src/common/tortls.h
@@ -48,6 +48,7 @@ typedef struct tor_tls_t tor_tls_t;
#define TOR_TLS_IS_ERROR(rv) ((rv) < TOR_TLS_CLOSE)
const char *tor_tls_err_to_string(int err);
+void tor_tls_get_state_description(tor_tls_t *tls, char *buf, size_t sz);
void tor_tls_free_all(void);
int tor_tls_context_init(int is_public_server,
@@ -67,8 +68,11 @@ int tor_tls_check_lifetime(tor_tls_t *tls, int tolerance);
int tor_tls_read(tor_tls_t *tls, char *cp, size_t len);
int tor_tls_write(tor_tls_t *tls, const char *cp, size_t n);
int tor_tls_handshake(tor_tls_t *tls);
+int tor_tls_finish_handshake(tor_tls_t *tls);
int tor_tls_renegotiate(tor_tls_t *tls);
+void tor_tls_unblock_renegotiation(tor_tls_t *tls);
void tor_tls_block_renegotiation(tor_tls_t *tls);
+void tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls);
int tor_tls_shutdown(tor_tls_t *tls);
int tor_tls_get_pending_bytes(tor_tls_t *tls);
size_t tor_tls_get_forced_write_size(tor_tls_t *tls);
@@ -81,12 +85,24 @@ void tor_tls_get_buffer_sizes(tor_tls_t *tls,
size_t *wbuf_capacity, size_t *wbuf_bytes);
int tor_tls_used_v1_handshake(tor_tls_t *tls);
+int tor_tls_get_num_server_handshakes(tor_tls_t *tls);
+int tor_tls_server_got_renegotiate(tor_tls_t *tls);
/* Log and abort if there are unhandled TLS errors in OpenSSL's error stack.
*/
#define check_no_tls_errors() _check_no_tls_errors(__FILE__,__LINE__)
void _check_no_tls_errors(const char *fname, int line);
+void tor_tls_log_one_error(tor_tls_t *tls, unsigned long err,
+ int severity, int domain, const char *doing);
+
+#ifdef USE_BUFFEREVENTS
+int tor_tls_start_renegotiating(tor_tls_t *tls);
+struct bufferevent *tor_tls_init_bufferevent(tor_tls_t *tls,
+ struct bufferevent *bufev_in,
+ evutil_socket_t socket, int receiving,
+ int filter);
+#endif
#endif
diff --git a/src/common/util.c b/src/common/util.c
index ee0acbbb0..a3716e434 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -14,6 +14,10 @@
#define _GNU_SOURCE
#include "orconfig.h"
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#define UTIL_PRIVATE
#include "util.h"
#include "torlog.h"
#undef log
@@ -27,6 +31,7 @@
#include <direct.h>
#include <process.h>
#include <tchar.h>
+#include <Winbase.h>
#else
#include <dirent.h>
#include <pwd.h>
@@ -42,6 +47,7 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
+#include <signal.h>
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
@@ -67,9 +73,6 @@
#ifdef HAVE_SYS_FCNTL_H
#include <sys/fcntl.h>
#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
#ifdef HAVE_TIME_H
#include <time.h>
#endif
@@ -87,6 +90,9 @@
#ifdef HAVE_MALLOC_NP_H
#include <malloc_np.h>
#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
/* =====
* Memory management
@@ -334,10 +340,12 @@ tor_mathlog(double d)
long
tor_lround(double d)
{
-#ifdef _MSC_VER
- return (long)(d > 0 ? d + 0.5 : ceil(d - 0.5));
-#else
+#if defined(HAVE_LROUND)
return lround(d);
+#elif defined(HAVE_RINT)
+ return (long)rint(d);
+#else
+ return (long)(d > 0 ? d + 0.5 : ceil(d - 0.5));
#endif
}
@@ -415,6 +423,32 @@ round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor)
return number;
}
+/** Return the number of bits set in <b>v</b>. */
+int
+n_bits_set_u8(uint8_t v)
+{
+ static const int nybble_table[] = {
+ 0, /* 0000 */
+ 1, /* 0001 */
+ 1, /* 0010 */
+ 2, /* 0011 */
+ 1, /* 0100 */
+ 2, /* 0101 */
+ 2, /* 0110 */
+ 3, /* 0111 */
+ 1, /* 1000 */
+ 2, /* 1001 */
+ 2, /* 1010 */
+ 3, /* 1011 */
+ 2, /* 1100 */
+ 3, /* 1101 */
+ 3, /* 1110 */
+ 4, /* 1111 */
+ };
+
+ return nybble_table[v & 15] + nybble_table[v>>4];
+}
+
/* =====
* String manipulation
* ===== */
@@ -498,6 +532,23 @@ tor_strisnonupper(const char *s)
return 1;
}
+/** As strcmp, except that either string may be NULL. The NULL string is
+ * considered to be before any non-NULL string. */
+int
+strcmp_opt(const char *s1, const char *s2)
+{
+ if (!s1) {
+ if (!s2)
+ return 0;
+ else
+ return -1;
+ } else if (!s2) {
+ return 1;
+ } else {
+ return strcmp(s1, s2);
+ }
+}
+
/** Compares the first strlen(s2) characters of s1 with s2. Returns as for
* strcmp.
*/
@@ -720,6 +771,34 @@ find_str_at_start_of_line(const char *haystack, const char *needle)
return NULL;
}
+/** Returns true if <b>string</b> could be a C identifier.
+ A C identifier must begin with a letter or an underscore and the
+ rest of its characters can be letters, numbers or underscores. No
+ length limit is imposed. */
+int
+string_is_C_identifier(const char *string)
+{
+ size_t iter;
+ size_t length = strlen(string);
+ if (!length)
+ return 0;
+
+ for (iter = 0; iter < length ; iter++) {
+ if (iter == 0) {
+ if (!(TOR_ISALPHA(string[iter]) ||
+ string[iter] == '_'))
+ return 0;
+ } else {
+ if (!(TOR_ISALPHA(string[iter]) ||
+ TOR_ISDIGIT(string[iter]) ||
+ string[iter] == '_'))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
/** Return true iff the 'len' bytes at 'mem' are all zero. */
int
tor_mem_is_zero(const char *mem, size_t len)
@@ -956,7 +1035,7 @@ esc_for_log(const char *s)
char *result, *outp;
size_t len = 3;
if (!s) {
- return tor_strdup("");
+ return tor_strdup("(null)");
}
for (cp = s; *cp; ++cp) {
@@ -1696,6 +1775,8 @@ check_private_dir(const char *dirname, cpd_check_t check,
struct passwd *pw = NULL;
uid_t running_uid;
gid_t running_gid;
+#else
+ (void)effective_user;
#endif
tor_assert(dirname);
@@ -1895,7 +1976,7 @@ start_writing_to_file(const char *fname, int open_flags, int mode,
if (open_flags & O_BINARY)
new_file->binary = 1;
- new_file->fd = open(open_name, open_flags, mode);
+ new_file->fd = tor_open_cloexec(open_name, open_flags, mode);
if (new_file->fd < 0) {
log_warn(LD_FS, "Couldn't open \"%s\" (%s) for writing: %s",
open_name, fname, strerror(errno));
@@ -2116,7 +2197,7 @@ read_file_to_str(const char *filename, int flags, struct stat *stat_out)
tor_assert(filename);
- fd = open(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0);
+ fd = tor_open_cloexec(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0);
if (fd<0) {
int severity = LOG_WARN;
int save_errno = errno;
@@ -2502,18 +2583,21 @@ digit_to_num(char d)
* success, store the result in <b>out</b>, advance bufp to the next
* character, and return 0. On failure, return -1. */
static int
-scan_unsigned(const char **bufp, unsigned *out, int width)
+scan_unsigned(const char **bufp, unsigned *out, int width, int base)
{
unsigned result = 0;
int scanned_so_far = 0;
+ const int hex = base==16;
+ tor_assert(base == 10 || base == 16);
if (!bufp || !*bufp || !out)
return -1;
if (width<0)
width=MAX_SCANF_WIDTH;
- while (**bufp && TOR_ISDIGIT(**bufp) && scanned_so_far < width) {
- int digit = digit_to_num(*(*bufp)++);
- unsigned new_result = result * 10 + digit;
+ while (**bufp && (hex?TOR_ISXDIGIT(**bufp):TOR_ISDIGIT(**bufp))
+ && scanned_so_far < width) {
+ int digit = hex?hex_decode_digit(*(*bufp)++):digit_to_num(*(*bufp)++);
+ unsigned new_result = result * base + digit;
if (new_result > UINT32_MAX || new_result < result)
return -1; /* over/underflow. */
result = new_result;
@@ -2575,11 +2659,12 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap)
if (!width) /* No zero-width things. */
return -1;
}
- if (*pattern == 'u') {
+ if (*pattern == 'u' || *pattern == 'x') {
unsigned *u = va_arg(ap, unsigned *);
+ const int base = (*pattern == 'u') ? 10 : 16;
if (!*buf)
return n_matched;
- if (scan_unsigned(&buf, u, width)<0)
+ if (scan_unsigned(&buf, u, width, base)<0)
return n_matched;
++pattern;
++n_matched;
@@ -2616,9 +2701,9 @@ tor_vsscanf(const char *buf, const char *pattern, va_list ap)
/** Minimal sscanf replacement: parse <b>buf</b> according to <b>pattern</b>
* and store the results in the corresponding argument fields. Differs from
- * sscanf in that it: Only handles %u and %Ns. Does not handle arbitrarily
- * long widths. %u does not consume any space. Is locale-independent.
- * Returns -1 on malformed patterns.
+ * sscanf in that it: Only handles %u and %x and %Ns. Does not handle
+ * arbitrarily long widths. %u and %x do not consume any space. Is
+ * locale-independent. Returns -1 on malformed patterns.
*
* (As with other locale-independent functions, we need this to parse data that
* is in ASCII without worrying that the C library's locale-handling will make
@@ -2635,6 +2720,30 @@ tor_sscanf(const char *buf, const char *pattern, ...)
return r;
}
+/** Append the string produced by tor_asprintf(<b>pattern</b>, <b>...</b>)
+ * to <b>sl</b>. */
+void
+smartlist_asprintf_add(struct smartlist_t *sl, const char *pattern, ...)
+{
+ va_list ap;
+ va_start(ap, pattern);
+ smartlist_vasprintf_add(sl, pattern, ap);
+ va_end(ap);
+}
+
+/** va_list-based backend of smartlist_asprintf_add. */
+void
+smartlist_vasprintf_add(struct smartlist_t *sl, const char *pattern,
+ va_list args)
+{
+ char *str = NULL;
+
+ tor_vasprintf(&str, pattern, args);
+ tor_assert(str != NULL);
+
+ smartlist_add(sl, str);
+}
+
/** Return a new list containing the filenames in the directory <b>dirname</b>.
* Return NULL on error or if <b>dirname</b> is not a directory.
*/
@@ -2812,7 +2921,7 @@ finish_daemon(const char *desired_cwd)
exit(1);
}
- nullfd = open("/dev/null", O_RDWR);
+ nullfd = tor_open_cloexec("/dev/null", O_RDWR, 0);
if (nullfd < 0) {
log_err(LD_GENERAL,"/dev/null can't be opened. Exiting.");
exit(1);
@@ -2883,3 +2992,1068 @@ load_windows_system_library(const TCHAR *library_name)
}
#endif
+/** Format a single argument for being put on a Windows command line.
+ * Returns a newly allocated string */
+static char *
+format_win_cmdline_argument(const char *arg)
+{
+ char *formatted_arg;
+ char need_quotes;
+ const char *c;
+ int i;
+ int bs_counter = 0;
+ /* Backslash we can point to when one is inserted into the string */
+ const char backslash = '\\';
+
+ /* Smartlist of *char */
+ smartlist_t *arg_chars;
+ arg_chars = smartlist_create();
+
+ /* Quote string if it contains whitespace or is empty */
+ need_quotes = (strchr(arg, ' ') || strchr(arg, '\t') || '\0' == arg[0]);
+
+ /* Build up smartlist of *chars */
+ for (c=arg; *c != '\0'; c++) {
+ if ('"' == *c) {
+ /* Double up backslashes preceding a quote */
+ for (i=0; i<(bs_counter*2); i++)
+ smartlist_add(arg_chars, (void*)&backslash);
+ bs_counter = 0;
+ /* Escape the quote */
+ smartlist_add(arg_chars, (void*)&backslash);
+ smartlist_add(arg_chars, (void*)c);
+ } else if ('\\' == *c) {
+ /* Count backslashes until we know whether to double up */
+ bs_counter++;
+ } else {
+ /* Don't double up slashes preceding a non-quote */
+ for (i=0; i<bs_counter; i++)
+ smartlist_add(arg_chars, (void*)&backslash);
+ bs_counter = 0;
+ smartlist_add(arg_chars, (void*)c);
+ }
+ }
+ /* Don't double up trailing backslashes */
+ for (i=0; i<bs_counter; i++)
+ smartlist_add(arg_chars, (void*)&backslash);
+
+ /* Allocate space for argument, quotes (if needed), and terminator */
+ formatted_arg = tor_malloc(sizeof(char) *
+ (smartlist_len(arg_chars) + (need_quotes?2:0) + 1));
+
+ /* Add leading quote */
+ i=0;
+ if (need_quotes)
+ formatted_arg[i++] = '"';
+
+ /* Add characters */
+ SMARTLIST_FOREACH(arg_chars, char*, c,
+ {
+ formatted_arg[i++] = *c;
+ });
+
+ /* Add trailing quote */
+ if (need_quotes)
+ formatted_arg[i++] = '"';
+ formatted_arg[i] = '\0';
+
+ smartlist_free(arg_chars);
+ return formatted_arg;
+}
+
+/** Format a command line for use on Windows, which takes the command as a
+ * string rather than string array. Follows the rules from "Parsing C++
+ * Command-Line Arguments" in MSDN. Algorithm based on list2cmdline in the
+ * Python subprocess module. Returns a newly allocated string */
+char *
+tor_join_win_cmdline(const char *argv[])
+{
+ smartlist_t *argv_list;
+ char *joined_argv;
+ int i;
+
+ /* Format each argument and put the result in a smartlist */
+ argv_list = smartlist_create();
+ for (i=0; argv[i] != NULL; i++) {
+ smartlist_add(argv_list, (void *)format_win_cmdline_argument(argv[i]));
+ }
+
+ /* Join the arguments with whitespace */
+ joined_argv = smartlist_join_strings(argv_list, " ", 0, NULL);
+
+ /* Free the newly allocated arguments, and the smartlist */
+ SMARTLIST_FOREACH(argv_list, char *, arg,
+ {
+ tor_free(arg);
+ });
+ smartlist_free(argv_list);
+
+ return joined_argv;
+}
+
+/** Format <b>child_state</b> and <b>saved_errno</b> as a hex string placed in
+ * <b>hex_errno</b>. Called between fork and _exit, so must be signal-handler
+ * safe.
+ *
+ * <b>hex_errno</b> must have at least HEX_ERRNO_SIZE bytes available.
+ *
+ * The format of <b>hex_errno</b> is: "CHILD_STATE/ERRNO\n", left-padded
+ * with spaces. Note that there is no trailing \0. CHILD_STATE indicates where
+ * in the processs of starting the child process did the failure occur (see
+ * CHILD_STATE_* macros for definition), and SAVED_ERRNO is the value of
+ * errno when the failure occurred.
+ */
+
+void
+format_helper_exit_status(unsigned char child_state, int saved_errno,
+ char *hex_errno)
+{
+ unsigned int unsigned_errno;
+ char *cur;
+ size_t i;
+
+ /* Fill hex_errno with spaces, and a trailing newline (memset may
+ not be signal handler safe, so we can't use it) */
+ for (i = 0; i < (HEX_ERRNO_SIZE - 1); i++)
+ hex_errno[i] = ' ';
+ hex_errno[HEX_ERRNO_SIZE - 1] = '\n';
+
+ /* Convert errno to be unsigned for hex conversion */
+ if (saved_errno < 0) {
+ unsigned_errno = (unsigned int) -saved_errno;
+ } else {
+ unsigned_errno = (unsigned int) saved_errno;
+ }
+
+ /* Convert errno to hex (start before \n) */
+ cur = hex_errno + HEX_ERRNO_SIZE - 2;
+
+ /* Check for overflow on first iteration of the loop */
+ if (cur < hex_errno)
+ return;
+
+ do {
+ *cur-- = "0123456789ABCDEF"[unsigned_errno % 16];
+ unsigned_errno /= 16;
+ } while (unsigned_errno != 0 && cur >= hex_errno);
+
+ /* Prepend the minus sign if errno was negative */
+ if (saved_errno < 0 && cur >= hex_errno)
+ *cur-- = '-';
+
+ /* Leave a gap */
+ if (cur >= hex_errno)
+ *cur-- = '/';
+
+ /* Check for overflow on first iteration of the loop */
+ if (cur < hex_errno)
+ return;
+
+ /* Convert child_state to hex */
+ do {
+ *cur-- = "0123456789ABCDEF"[child_state % 16];
+ child_state /= 16;
+ } while (child_state != 0 && cur >= hex_errno);
+}
+
+/* Maximum number of file descriptors, if we cannot get it via sysconf() */
+#define DEFAULT_MAX_FD 256
+
+/** Terminate process running at PID <b>pid</b>.
+ * Code borrowed from Python's os.kill. */
+int
+tor_terminate_process(pid_t pid)
+{
+#ifdef MS_WINDOWS
+ HANDLE handle;
+ /* If the signal is outside of what GenerateConsoleCtrlEvent can use,
+ attempt to open and terminate the process. */
+ handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
+ if (!handle)
+ return -1;
+
+ if (!TerminateProcess(handle, 0))
+ return -1;
+ else
+ return 0;
+#else /* Unix */
+ return kill(pid, SIGTERM);
+#endif
+}
+
+#define CHILD_STATE_INIT 0
+#define CHILD_STATE_PIPE 1
+#define CHILD_STATE_MAXFD 2
+#define CHILD_STATE_FORK 3
+#define CHILD_STATE_DUPOUT 4
+#define CHILD_STATE_DUPERR 5
+#define CHILD_STATE_REDIRECT 6
+#define CHILD_STATE_CLOSEFD 7
+#define CHILD_STATE_EXEC 8
+#define CHILD_STATE_FAILEXEC 9
+
+/** Start a program in the background. If <b>filename</b> contains a '/', then
+ * it will be treated as an absolute or relative path. Otherwise, on
+ * non-Windows systems, the system path will be searched for <b>filename</b>.
+ * On Windows, only the current directory will be searched. Here, to search the
+ * system path (as well as the application directory, current working
+ * directory, and system directories), set filename to NULL.
+ *
+ * The strings in <b>argv</b> will be passed as the command line arguments of
+ * the child program (following convention, argv[0] should normally be the
+ * filename of the executable, and this must be the case if <b>filename</b> is
+ * NULL). The last element of argv must be NULL. A handle to the child process
+ * will be returned in process_handle (which must be non-NULL). Read
+ * process_handle.status to find out if the process was successfully launched.
+ * For convenience, process_handle.status is returned by this function.
+ *
+ * Some parts of this code are based on the POSIX subprocess module from
+ * Python, and example code from
+ * http://msdn.microsoft.com/en-us/library/ms682499%28v=vs.85%29.aspx.
+ */
+int
+tor_spawn_background(const char *const filename, const char **argv,
+ const char **envp,
+ process_handle_t *process_handle)
+{
+#ifdef MS_WINDOWS
+ HANDLE stdout_pipe_read = NULL;
+ HANDLE stdout_pipe_write = NULL;
+ HANDLE stderr_pipe_read = NULL;
+ HANDLE stderr_pipe_write = NULL;
+
+ STARTUPINFO siStartInfo;
+ BOOL retval = FALSE;
+
+ SECURITY_ATTRIBUTES saAttr;
+ char *joined_argv;
+
+ /* process_handle must not be NULL */
+ tor_assert(process_handle != NULL);
+
+ saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+ saAttr.bInheritHandle = TRUE;
+ /* TODO: should we set explicit security attributes? (#2046, comment 5) */
+ saAttr.lpSecurityDescriptor = NULL;
+
+ /* Assume failure to start process */
+ memset(process_handle, 0, sizeof(process_handle_t));
+ process_handle->status = PROCESS_STATUS_ERROR;
+
+ /* Set up pipe for stdout */
+ if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, &saAttr, 0)) {
+ log_warn(LD_GENERAL,
+ "Failed to create pipe for stdout communication with child process: %s",
+ format_win32_error(GetLastError()));
+ return process_handle->status;
+ }
+ if (!SetHandleInformation(stdout_pipe_read, HANDLE_FLAG_INHERIT, 0)) {
+ log_warn(LD_GENERAL,
+ "Failed to configure pipe for stdout communication with child "
+ "process: %s", format_win32_error(GetLastError()));
+ return process_handle->status;
+ }
+
+ /* Set up pipe for stderr */
+ if (!CreatePipe(&stderr_pipe_read, &stderr_pipe_write, &saAttr, 0)) {
+ log_warn(LD_GENERAL,
+ "Failed to create pipe for stderr communication with child process: %s",
+ format_win32_error(GetLastError()));
+ return process_handle->status;
+ }
+ if (!SetHandleInformation(stderr_pipe_read, HANDLE_FLAG_INHERIT, 0)) {
+ log_warn(LD_GENERAL,
+ "Failed to configure pipe for stderr communication with child "
+ "process: %s", format_win32_error(GetLastError()));
+ return process_handle->status;
+ }
+
+ /* Create the child process */
+
+ /* Windows expects argv to be a whitespace delimited string, so join argv up
+ */
+ joined_argv = tor_join_win_cmdline(argv);
+
+ ZeroMemory(&(process_handle->pid), sizeof(PROCESS_INFORMATION));
+ ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
+ siStartInfo.cb = sizeof(STARTUPINFO);
+ siStartInfo.hStdError = stderr_pipe_write;
+ siStartInfo.hStdOutput = stdout_pipe_write;
+ siStartInfo.hStdInput = NULL;
+ siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
+
+ /* Create the child process */
+
+ retval = CreateProcess(filename, // module name
+ joined_argv, // command line
+ /* TODO: should we set explicit security attributes? (#2046, comment 5) */
+ NULL, // process security attributes
+ NULL, // primary thread security attributes
+ TRUE, // handles are inherited
+ /*(TODO: set CREATE_NEW CONSOLE/PROCESS_GROUP to make GetExitCodeProcess()
+ * work?) */
+ 0, // creation flags
+ NULL, // use parent's environment
+ NULL, // use parent's current directory
+ &siStartInfo, // STARTUPINFO pointer
+ &(process_handle->pid)); // receives PROCESS_INFORMATION
+
+ tor_free(joined_argv);
+
+ if (!retval) {
+ log_warn(LD_GENERAL,
+ "Failed to create child process %s: %s", filename?filename:argv[0],
+ format_win32_error(GetLastError()));
+ } else {
+ /* TODO: Close hProcess and hThread in process_handle->pid? */
+ process_handle->stdout_pipe = stdout_pipe_read;
+ process_handle->stderr_pipe = stderr_pipe_read;
+ process_handle->status = PROCESS_STATUS_RUNNING;
+ }
+
+ /* TODO: Close pipes on exit */
+
+ return process_handle->status;
+#else // MS_WINDOWS
+ pid_t pid;
+ int stdout_pipe[2];
+ int stderr_pipe[2];
+ int fd, retval;
+ ssize_t nbytes;
+
+ const char *error_message = SPAWN_ERROR_MESSAGE;
+ size_t error_message_length;
+
+ /* Represents where in the process of spawning the program is;
+ this is used for printing out the error message */
+ unsigned char child_state = CHILD_STATE_INIT;
+
+ char hex_errno[HEX_ERRNO_SIZE];
+
+ static int max_fd = -1;
+
+ /* Assume failure to start */
+ memset(process_handle, 0, sizeof(process_handle_t));
+ process_handle->status = PROCESS_STATUS_ERROR;
+
+ /* We do the strlen here because strlen() is not signal handler safe,
+ and we are not allowed to use unsafe functions between fork and exec */
+ error_message_length = strlen(error_message);
+
+ child_state = CHILD_STATE_PIPE;
+
+ /* Set up pipe for redirecting stdout and stderr of child */
+ retval = pipe(stdout_pipe);
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to set up pipe for stdout communication with child process: %s",
+ strerror(errno));
+ return process_handle->status;
+ }
+
+ retval = pipe(stderr_pipe);
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to set up pipe for stderr communication with child process: %s",
+ strerror(errno));
+ return process_handle->status;
+ }
+
+ child_state = CHILD_STATE_MAXFD;
+
+#ifdef _SC_OPEN_MAX
+ if (-1 != max_fd) {
+ max_fd = (int) sysconf(_SC_OPEN_MAX);
+ if (max_fd == -1)
+ max_fd = DEFAULT_MAX_FD;
+ log_warn(LD_GENERAL,
+ "Cannot find maximum file descriptor, assuming %d", max_fd);
+ }
+#else
+ max_fd = DEFAULT_MAX_FD;
+#endif
+
+ child_state = CHILD_STATE_FORK;
+
+ pid = fork();
+ if (0 == pid) {
+ /* In child */
+
+ child_state = CHILD_STATE_DUPOUT;
+
+ /* Link child stdout to the write end of the pipe */
+ retval = dup2(stdout_pipe[1], STDOUT_FILENO);
+ if (-1 == retval)
+ goto error;
+
+ child_state = CHILD_STATE_DUPERR;
+
+ /* Link child stderr to the write end of the pipe */
+ retval = dup2(stderr_pipe[1], STDERR_FILENO);
+ if (-1 == retval)
+ goto error;
+
+ child_state = CHILD_STATE_REDIRECT;
+
+ /* Link stdin to /dev/null */
+ fd = open("/dev/null", O_RDONLY); /* NOT cloexec, obviously. */
+ if (fd != -1)
+ dup2(fd, STDIN_FILENO);
+ else
+ goto error;
+
+ child_state = CHILD_STATE_CLOSEFD;
+
+ close(stderr_pipe[0]);
+ close(stderr_pipe[1]);
+ close(stdout_pipe[0]);
+ close(stdout_pipe[1]);
+ close(fd);
+
+ /* Close all other fds, including the read end of the pipe */
+ /* XXX: We should now be doing enough FD_CLOEXEC setting to make
+ * this needless. */
+ for (fd = STDERR_FILENO + 1; fd < max_fd; fd++) {
+ close(fd);
+ }
+
+ child_state = CHILD_STATE_EXEC;
+
+ /* Call the requested program. We need the cast because
+ execvp doesn't define argv as const, even though it
+ does not modify the arguments */
+ if (envp)
+ execve(filename, (char *const *) argv, (char*const*)envp);
+ else
+ execvp(filename, (char *const *) argv);
+
+ /* If we got here, the exec or open(/dev/null) failed */
+
+ child_state = CHILD_STATE_FAILEXEC;
+
+ error:
+ /* XXX: are we leaking fds from the pipe? */
+
+ format_helper_exit_status(child_state, errno, hex_errno);
+
+ /* Write the error message. GCC requires that we check the return
+ value, but there is nothing we can do if it fails */
+ /* TODO: Don't use STDOUT, use a pipe set up just for this purpose */
+ nbytes = write(STDOUT_FILENO, error_message, error_message_length);
+ nbytes = write(STDOUT_FILENO, hex_errno, sizeof(hex_errno));
+
+ (void) nbytes;
+
+ _exit(255);
+ /* Never reached, but avoids compiler warning */
+ return process_handle->status;
+ }
+
+ /* In parent */
+
+ if (-1 == pid) {
+ log_warn(LD_GENERAL, "Failed to fork child process: %s", strerror(errno));
+ close(stdout_pipe[0]);
+ close(stdout_pipe[1]);
+ close(stderr_pipe[0]);
+ close(stderr_pipe[1]);
+ return process_handle->status;
+ }
+
+ process_handle->pid = pid;
+
+ /* TODO: If the child process forked but failed to exec, waitpid it */
+
+ /* Return read end of the pipes to caller, and close write end */
+ process_handle->stdout_pipe = stdout_pipe[0];
+ retval = close(stdout_pipe[1]);
+
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to close write end of stdout pipe in parent process: %s",
+ strerror(errno));
+ }
+
+ process_handle->stderr_pipe = stderr_pipe[0];
+ retval = close(stderr_pipe[1]);
+
+ if (-1 == retval) {
+ log_warn(LD_GENERAL,
+ "Failed to close write end of stderr pipe in parent process: %s",
+ strerror(errno));
+ }
+
+ process_handle->status = PROCESS_STATUS_RUNNING;
+ /* Set stdout/stderr pipes to be non-blocking */
+ fcntl(process_handle->stdout_pipe, F_SETFL, O_NONBLOCK);
+ fcntl(process_handle->stderr_pipe, F_SETFL, O_NONBLOCK);
+ /* Open the buffered IO streams */
+ process_handle->stdout_handle = fdopen(process_handle->stdout_pipe, "r");
+ process_handle->stderr_handle = fdopen(process_handle->stderr_pipe, "r");
+
+ return process_handle->status;
+#endif // MS_WINDOWS
+}
+
+/** Get the exit code of a process specified by <b>process_handle</b> and store
+ * it in <b>exit_code</b>, if set to a non-NULL value. If <b>block</b> is set
+ * to true, the call will block until the process has exited. Otherwise if
+ * the process is still running, the function will return
+ * PROCESS_EXIT_RUNNING, and exit_code will be left unchanged. Returns
+ * PROCESS_EXIT_EXITED if the process did exit. If there is a failure,
+ * PROCESS_EXIT_ERROR will be returned and the contents of exit_code (if
+ * non-NULL) will be undefined. N.B. Under *nix operating systems, this will
+ * probably not work in Tor, because waitpid() is called in main.c to reap any
+ * terminated child processes.*/
+int
+tor_get_exit_code(const process_handle_t process_handle,
+ int block, int *exit_code)
+{
+#ifdef MS_WINDOWS
+ DWORD retval;
+ BOOL success;
+
+ if (block) {
+ /* Wait for the process to exit */
+ retval = WaitForSingleObject(process_handle.pid.hProcess, INFINITE);
+ if (retval != WAIT_OBJECT_0) {
+ log_warn(LD_GENERAL, "WaitForSingleObject() failed (%d): %s",
+ (int)retval, format_win32_error(GetLastError()));
+ return PROCESS_EXIT_ERROR;
+ }
+ } else {
+ retval = WaitForSingleObject(process_handle.pid.hProcess, 0);
+ if (WAIT_TIMEOUT == retval) {
+ /* Process has not exited */
+ return PROCESS_EXIT_RUNNING;
+ } else if (retval != WAIT_OBJECT_0) {
+ log_warn(LD_GENERAL, "WaitForSingleObject() failed (%d): %s",
+ (int)retval, format_win32_error(GetLastError()));
+ return PROCESS_EXIT_ERROR;
+ }
+ }
+
+ if (exit_code != NULL) {
+ success = GetExitCodeProcess(process_handle.pid.hProcess,
+ (PDWORD)exit_code);
+ if (!success) {
+ log_warn(LD_GENERAL, "GetExitCodeProcess() failed: %s",
+ format_win32_error(GetLastError()));
+ return PROCESS_EXIT_ERROR;
+ }
+ }
+#else
+ int stat_loc;
+ int retval;
+
+ retval = waitpid(process_handle.pid, &stat_loc, block?0:WNOHANG);
+ if (!block && 0 == retval) {
+ /* Process has not exited */
+ return PROCESS_EXIT_RUNNING;
+ } else if (retval != process_handle.pid) {
+ log_warn(LD_GENERAL, "waitpid() failed for PID %d: %s", process_handle.pid,
+ strerror(errno));
+ return PROCESS_EXIT_ERROR;
+ }
+
+ if (!WIFEXITED(stat_loc)) {
+ log_warn(LD_GENERAL, "Process %d did not exit normally",
+ process_handle.pid);
+ return PROCESS_EXIT_ERROR;
+ }
+
+ if (exit_code != NULL)
+ *exit_code = WEXITSTATUS(stat_loc);
+#endif // MS_WINDOWS
+
+ return PROCESS_EXIT_EXITED;
+}
+
+#ifdef MS_WINDOWS
+/** Read from a handle <b>h</b> into <b>buf</b>, up to <b>count</b> bytes. If
+ * <b>hProcess</b> is NULL, the function will return immediately if there is
+ * nothing more to read. Otherwise <b>hProcess</b> should be set to the handle
+ * to the process owning the <b>h</b>. In this case, the function will exit
+ * only once the process has exited, or <b>count</b> bytes are read. Returns
+ * the number of bytes read, or -1 on error. */
+ssize_t
+tor_read_all_handle(HANDLE h, char *buf, size_t count,
+ const process_handle_t *process)
+{
+ size_t numread = 0;
+ BOOL retval;
+ DWORD byte_count;
+ BOOL process_exited = FALSE;
+
+ if (count > SIZE_T_CEILING || count > SSIZE_T_MAX)
+ return -1;
+
+ while (numread != count) {
+ /* Check if there is anything to read */
+ retval = PeekNamedPipe(h, NULL, 0, NULL, &byte_count, NULL);
+ if (!retval) {
+ log_warn(LD_GENERAL,
+ "Failed to peek from handle: %s",
+ format_win32_error(GetLastError()));
+ return -1;
+ } else if (0 == byte_count) {
+ /* Nothing available: process exited or it is busy */
+
+ /* Exit if we don't know whether the process is running */
+ if (NULL == process)
+ break;
+
+ /* The process exited and there's nothing left to read from it */
+ if (process_exited)
+ break;
+
+ /* If process is not running, check for output one more time in case
+ it wrote something after the peek was performed. Otherwise keep on
+ waiting for output */
+ tor_assert(process != NULL);
+ byte_count = WaitForSingleObject(process->pid.hProcess, 0);
+ if (WAIT_TIMEOUT != byte_count)
+ process_exited = TRUE;
+
+ continue;
+ }
+
+ /* There is data to read; read it */
+ retval = ReadFile(h, buf+numread, count-numread, &byte_count, NULL);
+ tor_assert(byte_count + numread <= count);
+ if (!retval) {
+ log_warn(LD_GENERAL, "Failed to read from handle: %s",
+ format_win32_error(GetLastError()));
+ return -1;
+ } else if (0 == byte_count) {
+ /* End of file */
+ break;
+ }
+ numread += byte_count;
+ }
+ return (ssize_t)numread;
+}
+#else
+/** Read from a handle <b>h</b> into <b>buf</b>, up to <b>count</b> bytes. If
+ * <b>process</b> is NULL, the function will return immediately if there is
+ * nothing more to read. Otherwise data will be read until end of file, or
+ * <b>count</b> bytes are read. Returns the number of bytes read, or -1 on
+ * error. Sets <b>eof</b> to true if <b>eof</b> is not NULL and the end of the
+ * file has been reached. */
+ssize_t
+tor_read_all_handle(FILE *h, char *buf, size_t count,
+ const process_handle_t *process,
+ int *eof)
+{
+ size_t numread = 0;
+ char *retval;
+
+ if (eof)
+ *eof = 0;
+
+ if (count > SIZE_T_CEILING || count > SSIZE_T_MAX)
+ return -1;
+
+ while (numread != count) {
+ /* Use fgets because that is what we use in log_from_pipe() */
+ retval = fgets(buf+numread, (int)(count-numread), h);
+ if (NULL == retval) {
+ if (feof(h)) {
+ log_debug(LD_GENERAL, "fgets() reached end of file");
+ fclose(h);
+ if (eof)
+ *eof = 1;
+ break;
+ } else {
+ if (EAGAIN == errno) {
+ if (process)
+ continue;
+ else
+ break;
+ } else {
+ log_warn(LD_GENERAL, "fgets() from handle failed: %s",
+ strerror(errno));
+ fclose(h);
+ return -1;
+ }
+ }
+ }
+ tor_assert(retval != NULL);
+ tor_assert(strlen(retval) + numread <= count);
+ numread += strlen(retval);
+ }
+
+ log_debug(LD_GENERAL, "fgets() read %d bytes from handle", (int)numread);
+ return (ssize_t)numread;
+}
+#endif
+
+/** Read from stdout of a process until the process exits. */
+ssize_t
+tor_read_all_from_process_stdout(const process_handle_t *process_handle,
+ char *buf, size_t count)
+{
+#ifdef MS_WINDOWS
+ return tor_read_all_handle(process_handle->stdout_pipe, buf, count,
+ process_handle);
+#else
+ return tor_read_all_handle(process_handle->stdout_handle, buf, count,
+ process_handle, NULL);
+#endif
+}
+
+/** Read from stdout of a process until the process exits. */
+ssize_t
+tor_read_all_from_process_stderr(const process_handle_t *process_handle,
+ char *buf, size_t count)
+{
+#ifdef MS_WINDOWS
+ return tor_read_all_handle(process_handle->stderr_pipe, buf, count,
+ process_handle);
+#else
+ return tor_read_all_handle(process_handle->stderr_handle, buf, count,
+ process_handle, NULL);
+#endif
+}
+
+/** Split buf into lines, and add to smartlist. The buffer <b>buf</b> will be
+ * modified. The resulting smartlist will consist of pointers to buf, so there
+ * is no need to free the contents of sl. <b>buf</b> must be a NUL-terminated
+ * string. <b>len</b> should be set to the length of the buffer excluding the
+ * NUL. Non-printable characters (including NUL) will be replaced with "." */
+int
+tor_split_lines(smartlist_t *sl, char *buf, int len)
+{
+ /* Index in buf of the start of the current line */
+ int start = 0;
+ /* Index in buf of the current character being processed */
+ int cur = 0;
+ /* Are we currently in a line */
+ char in_line = 0;
+
+ /* Loop over string */
+ while (cur < len) {
+ /* Loop until end of line or end of string */
+ for (; cur < len; cur++) {
+ if (in_line) {
+ if ('\r' == buf[cur] || '\n' == buf[cur]) {
+ /* End of line */
+ buf[cur] = '\0';
+ /* Point cur to the next line */
+ cur++;
+ /* Line starts at start and ends with a nul */
+ break;
+ } else {
+ if (!TOR_ISPRINT(buf[cur]))
+ buf[cur] = '.';
+ }
+ } else {
+ if ('\r' == buf[cur] || '\n' == buf[cur]) {
+ /* Skip leading vertical space */
+ ;
+ } else {
+ in_line = 1;
+ start = cur;
+ if (!TOR_ISPRINT(buf[cur]))
+ buf[cur] = '.';
+ }
+ }
+ }
+ /* We are at the end of the line or end of string. If in_line is true there
+ * is a line which starts at buf+start and ends at a NUL. cur points to
+ * the character after the NUL. */
+ if (in_line)
+ smartlist_add(sl, (void *)(buf+start));
+ in_line = 0;
+ }
+ return smartlist_len(sl);
+}
+
+#ifdef MS_WINDOWS
+/** Read from stream, and send lines to log at the specified log level.
+ * Returns -1 if there is a error reading, and 0 otherwise.
+ * If the generated stream is flushed more often than on new lines, or
+ * a read exceeds 256 bytes, lines will be truncated. This should be fixed,
+ * along with the corresponding problem on *nix (see bug #2045).
+ */
+static int
+log_from_handle(HANDLE *pipe, int severity)
+{
+ char buf[256];
+ int pos;
+ smartlist_t *lines;
+
+ pos = tor_read_all_handle(pipe, buf, sizeof(buf) - 1, NULL);
+ if (pos < 0) {
+ /* Error */
+ log_warn(LD_GENERAL, "Failed to read data from subprocess");
+ return -1;
+ }
+
+ if (0 == pos) {
+ /* There's nothing to read (process is busy or has exited) */
+ log_debug(LD_GENERAL, "Subprocess had nothing to say");
+ return 0;
+ }
+
+ /* End with a null even if there isn't a \r\n at the end */
+ /* TODO: What if this is a partial line? */
+ buf[pos] = '\0';
+ log_debug(LD_GENERAL, "Subprocess had %d bytes to say", pos);
+
+ /* Split up the buffer */
+ lines = smartlist_create();
+ tor_split_lines(lines, buf, pos);
+
+ /* Log each line */
+ SMARTLIST_FOREACH(lines, char *, line,
+ {
+ log_fn(severity, LD_GENERAL, "Port forwarding helper says: %s", line);
+ });
+ smartlist_free(lines);
+
+ return 0;
+}
+
+#else
+
+/** Read from stream, and send lines to log at the specified log level.
+ * Returns 1 if stream is closed normally, -1 if there is a error reading, and
+ * 0 otherwise. Handles lines from tor-fw-helper and
+ * tor_spawn_background() specially.
+ */
+static int
+log_from_pipe(FILE *stream, int severity, const char *executable,
+ int *child_status)
+{
+ char buf[256];
+ enum stream_status r;
+
+ for (;;) {
+ r = get_string_from_pipe(stream, buf, sizeof(buf) - 1);
+
+ if (r == IO_STREAM_CLOSED) {
+ fclose(stream);
+ return 1;
+ } else if (r == IO_STREAM_EAGAIN) {
+ return 0;
+ } else if (r == IO_STREAM_TERM) {
+ fclose(stream);
+ return -1;
+ }
+
+ tor_assert(r == IO_STREAM_OKAY);
+
+ /* Check if buf starts with SPAWN_ERROR_MESSAGE */
+ if (strcmpstart(buf, SPAWN_ERROR_MESSAGE) == 0) {
+ /* Parse error message */
+ int retval, child_state, saved_errno;
+ retval = tor_sscanf(buf, SPAWN_ERROR_MESSAGE "%x/%x",
+ &child_state, &saved_errno);
+ if (retval == 2) {
+ log_warn(LD_GENERAL,
+ "Failed to start child process \"%s\" in state %d: %s",
+ executable, child_state, strerror(saved_errno));
+ if (child_status)
+ *child_status = 1;
+ } else {
+ /* Failed to parse message from child process, log it as a
+ warning */
+ log_warn(LD_GENERAL,
+ "Unexpected message from port forwarding helper \"%s\": %s",
+ executable, buf);
+ }
+ } else {
+ log_fn(severity, LD_GENERAL, "Port forwarding helper says: %s", buf);
+ }
+ }
+
+ /* We should never get here */
+ return -1;
+}
+#endif
+
+/** Reads from <b>stream</b> and stores input in <b>buf_out</b> making
+ * sure it's below <b>count</b> bytes.
+ * If the string has a trailing newline, we strip it off.
+ *
+ * This function is specifically created to handle input from managed
+ * proxies, according to the pluggable transports spec. Make sure it
+ * fits your needs before using it.
+ *
+ * Returns:
+ * IO_STREAM_CLOSED: If the stream is closed.
+ * IO_STREAM_EAGAIN: If there is nothing to read and we should check back
+ * later.
+ * IO_STREAM_TERM: If something is wrong with the stream.
+ * IO_STREAM_OKAY: If everything went okay and we got a string
+ * in <b>buf_out</b>. */
+enum stream_status
+get_string_from_pipe(FILE *stream, char *buf_out, size_t count)
+{
+ char *retval;
+ size_t len;
+
+ retval = fgets(buf_out, count, stream);
+
+ if (!retval) {
+ if (feof(stream)) {
+ /* Program has closed stream (probably it exited) */
+ /* TODO: check error */
+ return IO_STREAM_CLOSED;
+ } else {
+ if (EAGAIN == errno) {
+ /* Nothing more to read, try again next time */
+ return IO_STREAM_EAGAIN;
+ } else {
+ /* There was a problem, abandon this child process */
+ return IO_STREAM_TERM;
+ }
+ }
+ } else {
+ len = strlen(buf_out);
+ tor_assert(len>0);
+
+ if (buf_out[len - 1] == '\n') {
+ /* Remove the trailing newline */
+ buf_out[len - 1] = '\0';
+ } else {
+ /* No newline; check whether we overflowed the buffer */
+ if (!feof(stream))
+ log_info(LD_GENERAL,
+ "Line from stream was truncated: %s", buf_out);
+ /* TODO: What to do with this error? */
+ }
+
+ return IO_STREAM_OKAY;
+ }
+
+ /* We should never get here */
+ return IO_STREAM_TERM;
+}
+
+void
+tor_check_port_forwarding(const char *filename, int dir_port, int or_port,
+ time_t now)
+{
+/* When fw-helper succeeds, how long do we wait until running it again */
+#define TIME_TO_EXEC_FWHELPER_SUCCESS 300
+/* When fw-helper failed to start, how long do we wait until running it again
+ */
+#define TIME_TO_EXEC_FWHELPER_FAIL 60
+
+ /* Static variables are initialized to zero, so child_handle.status=0
+ * which corresponds to it not running on startup */
+ static process_handle_t child_handle;
+
+ static time_t time_to_run_helper = 0;
+ int stdout_status, stderr_status, retval;
+ const char *argv[10];
+ char s_dirport[6], s_orport[6];
+
+ tor_assert(filename);
+
+ /* Set up command line for tor-fw-helper */
+ snprintf(s_dirport, sizeof s_dirport, "%d", dir_port);
+ snprintf(s_orport, sizeof s_orport, "%d", or_port);
+
+ /* TODO: Allow different internal and external ports */
+ argv[0] = filename;
+ argv[1] = "--internal-or-port";
+ argv[2] = s_orport;
+ argv[3] = "--external-or-port";
+ argv[4] = s_orport;
+ argv[5] = "--internal-dir-port";
+ argv[6] = s_dirport;
+ argv[7] = "--external-dir-port";
+ argv[8] = s_dirport;
+ argv[9] = NULL;
+
+ /* Start the child, if it is not already running */
+ if (child_handle.status != PROCESS_STATUS_RUNNING &&
+ time_to_run_helper < now) {
+ /* Assume tor-fw-helper will succeed, start it later*/
+ time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_SUCCESS;
+
+#ifdef MS_WINDOWS
+ /* Passing NULL as lpApplicationName makes Windows search for the .exe */
+ tor_spawn_background(NULL, argv, NULL &child_handle);
+#else
+ tor_spawn_background(filename, argv, NULL, &child_handle);
+#endif
+ if (PROCESS_STATUS_ERROR == child_handle.status) {
+ log_warn(LD_GENERAL, "Failed to start port forwarding helper %s",
+ filename);
+ time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_FAIL;
+ return;
+ }
+#ifdef MS_WINDOWS
+ log_info(LD_GENERAL,
+ "Started port forwarding helper (%s)", filename);
+#else
+ log_info(LD_GENERAL,
+ "Started port forwarding helper (%s) with pid %d", filename,
+ child_handle.pid);
+#endif
+ }
+
+ /* If child is running, read from its stdout and stderr) */
+ if (PROCESS_STATUS_RUNNING == child_handle.status) {
+ /* Read from stdout/stderr and log result */
+ retval = 0;
+#ifdef MS_WINDOWS
+ stdout_status = log_from_handle(child_handle.stdout_pipe, LOG_INFO);
+ stderr_status = log_from_handle(child_handle.stderr_pipe, LOG_WARN);
+ /* If we got this far (on Windows), the process started */
+ retval = 0;
+#else
+ stdout_status = log_from_pipe(child_handle.stdout_handle,
+ LOG_INFO, filename, &retval);
+ stderr_status = log_from_pipe(child_handle.stderr_handle,
+ LOG_WARN, filename, &retval);
+#endif
+ if (retval) {
+ /* There was a problem in the child process */
+ time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_FAIL;
+ }
+
+ /* Combine the two statuses in order of severity */
+ if (-1 == stdout_status || -1 == stderr_status)
+ /* There was a failure */
+ retval = -1;
+#ifdef MS_WINDOWS
+ else if (tor_get_exit_code(child_handle, 0, NULL) !=
+ PROCESS_EXIT_RUNNING) {
+ /* process has exited or there was an error */
+ /* TODO: Do something with the process return value */
+ /* TODO: What if the process output something since
+ * between log_from_handle and tor_get_exit_code? */
+ retval = 1;
+ }
+#else
+ else if (1 == stdout_status || 1 == stderr_status)
+ /* stdout or stderr was closed, the process probably
+ * exited. It will be reaped by waitpid() in main.c */
+ /* TODO: Do something with the process return value */
+ retval = 1;
+#endif
+ else
+ /* Both are fine */
+ retval = 0;
+
+ /* If either pipe indicates a failure, act on it */
+ if (0 != retval) {
+ if (1 == retval) {
+ log_info(LD_GENERAL, "Port forwarding helper terminated");
+ child_handle.status = PROCESS_STATUS_NOTRUNNING;
+ } else {
+ log_warn(LD_GENERAL, "Failed to read from port forwarding helper");
+ child_handle.status = PROCESS_STATUS_ERROR;
+ }
+
+ /* TODO: The child might not actually be finished (maybe it failed or
+ closed stdout/stderr), so maybe we shouldn't start another? */
+ }
+ }
+}
+
diff --git a/src/common/util.h b/src/common/util.h
index b9db25ca7..77ed1ca5e 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -160,6 +160,7 @@ uint64_t round_to_power_of_2(uint64_t u64);
unsigned round_to_next_multiple_of(unsigned number, unsigned divisor);
uint32_t round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor);
uint64_t round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor);
+int n_bits_set_u8(uint8_t v);
/* Compute the CEIL of <b>a</b> divided by <b>b</b>, for nonnegative <b>a</b>
* and positive <b>b</b>. Works on integer types only. Not defined if a+b can
@@ -174,6 +175,7 @@ void tor_strlower(char *s) ATTR_NONNULL((1));
void tor_strupper(char *s) ATTR_NONNULL((1));
int tor_strisprint(const char *s) ATTR_PURE ATTR_NONNULL((1));
int tor_strisnonupper(const char *s) ATTR_PURE ATTR_NONNULL((1));
+int strcmp_opt(const char *s1, const char *s2) ATTR_PURE;
int strcmpstart(const char *s1, const char *s2) ATTR_PURE ATTR_NONNULL((1,2));
int strcmp_len(const char *s1, const char *s2, size_t len)
ATTR_PURE ATTR_NONNULL((1,2));
@@ -203,6 +205,8 @@ const char *find_whitespace(const char *s) ATTR_PURE;
const char *find_whitespace_eos(const char *s, const char *eos) ATTR_PURE;
const char *find_str_at_start_of_line(const char *haystack, const char *needle)
ATTR_PURE;
+int string_is_C_identifier(const char *string);
+
int tor_mem_is_zero(const char *mem, size_t len) ATTR_PURE;
int tor_digest_is_zero(const char *digest) ATTR_PURE;
int tor_digest256_is_zero(const char *digest) ATTR_PURE;
@@ -218,6 +222,11 @@ int tor_sscanf(const char *buf, const char *pattern, ...)
#endif
;
+void smartlist_asprintf_add(struct smartlist_t *sl, const char *pattern, ...)
+ CHECK_PRINTF(2, 3);
+void smartlist_vasprintf_add(struct smartlist_t *sl, const char *pattern,
+ va_list args);
+
int hex_decode_digit(char c);
void base16_encode(char *dest, size_t destlen, const char *src, size_t srclen);
int base16_decode(char *dest, size_t destlen, const char *src, size_t srclen);
@@ -279,6 +288,16 @@ char *rate_limit_log(ratelim_t *lim, time_t now);
ssize_t write_all(tor_socket_t fd, const char *buf, size_t count,int isSocket);
ssize_t read_all(tor_socket_t fd, char *buf, size_t count, int isSocket);
+/** Status of an I/O stream. */
+enum stream_status {
+ IO_STREAM_OKAY,
+ IO_STREAM_EAGAIN,
+ IO_STREAM_TERM,
+ IO_STREAM_CLOSED
+};
+
+enum stream_status get_string_from_pipe(FILE *stream, char *buf, size_t count);
+
/** Return values from file_status(); see that function's documentation
* for details. */
typedef enum { FN_ERROR, FN_NOENT, FN_FILE, FN_DIR } file_status_t;
@@ -337,10 +356,75 @@ void start_daemon(void);
void finish_daemon(const char *desired_cwd);
void write_pidfile(char *filename);
+/* Port forwarding */
+void tor_check_port_forwarding(const char *filename,
+ int dir_port, int or_port, time_t now);
+
+int tor_terminate_process(pid_t pid);
+typedef struct process_handle_s process_handle_t;
+int tor_spawn_background(const char *const filename, const char **argv,
+ const char **envp, process_handle_t *process_handle);
+
+#define SPAWN_ERROR_MESSAGE "ERR: Failed to spawn background process - code "
+
#ifdef MS_WINDOWS
HANDLE load_windows_system_library(const TCHAR *library_name);
#endif
+#ifdef UTIL_PRIVATE
+/* Prototypes for private functions only used by util.c (and unit tests) */
+
+/* Values of process_handle_t.status. PROCESS_STATUS_NOTRUNNING must be
+ * 0 because tor_check_port_forwarding depends on this being the initial
+ * statue of the static instance of process_handle_t */
+#define PROCESS_STATUS_NOTRUNNING 0
+#define PROCESS_STATUS_RUNNING 1
+#define PROCESS_STATUS_ERROR -1
+struct process_handle_s {
+ int status;
+#ifdef MS_WINDOWS
+ HANDLE stdout_pipe;
+ HANDLE stderr_pipe;
+ PROCESS_INFORMATION pid;
+#else
+ int stdout_pipe;
+ int stderr_pipe;
+ FILE *stdout_handle;
+ FILE *stderr_handle;
+ pid_t pid;
+#endif // MS_WINDOWS
+};
+
+/* Return values of tor_get_exit_code() */
+#define PROCESS_EXIT_RUNNING 1
+#define PROCESS_EXIT_EXITED 0
+#define PROCESS_EXIT_ERROR -1
+int tor_get_exit_code(const process_handle_t process_handle,
+ int block, int *exit_code);
+int tor_split_lines(struct smartlist_t *sl, char *buf, int len);
+#ifdef MS_WINDOWS
+ssize_t tor_read_all_handle(HANDLE h, char *buf, size_t count,
+ const process_handle_t *process);
+#else
+ssize_t tor_read_all_handle(FILE *h, char *buf, size_t count,
+ const process_handle_t *process,
+ int *eof);
+#endif
+ssize_t tor_read_all_from_process_stdout(
+ const process_handle_t *process_handle, char *buf, size_t count);
+ssize_t tor_read_all_from_process_stderr(
+ const process_handle_t *process_handle, char *buf, size_t count);
+char *tor_join_win_cmdline(const char *argv[]);
+
+void format_helper_exit_status(unsigned char child_state,
+ int saved_errno, char *hex_errno);
+
+/* Space for hex values of child state, a slash, saved_errno (with
+ leading minus) and newline (no null) */
+#define HEX_ERRNO_SIZE (sizeof(char) * 2 + 1 + \
+ 1 + sizeof(int) * 2 + 1)
+#endif
+
const char *libor_get_digests(void);
#endif
diff --git a/src/config/geoip b/src/config/geoip
index 1cd6ecd35..8043d8ebf 100644
--- a/src/config/geoip
+++ b/src/config/geoip
@@ -1,4 +1,4 @@
-# Last updated based on August 2 2011 Maxmind GeoLite Country
+# Last updated based on September 6 2011 Maxmind GeoLite Country
# wget http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
# cut -d, -f3-5 < GeoIPCountryWhois.csv|sed 's/"//g' > geoip
16777216,16777471,AU
@@ -79,13 +79,19 @@
34636800,34637311,DE
34637312,34646527,EU
34646528,34647551,DE
-34647552,34664447,EU
+34647552,34648575,EU
+34648576,34649087,GR
+34649088,34659327,EU
+34659328,34660351,GR
+34660352,34664447,EU
34664448,34668543,DE
34668544,34673663,EU
34673664,34674687,DE
34674688,34733055,EU
34733056,34734079,DE
-34734080,34803711,EU
+34734080,34754559,EU
+34754560,34758655,GR
+34758656,34803711,EU
34803712,34807807,IT
34807808,34861055,EU
34861056,34865151,DE
@@ -129,7 +135,9 @@
35055872,35056127,NL
35056128,35069951,EU
35069952,35074047,SE
-35074048,35127295,EU
+35074048,35090431,EU
+35090432,35094527,GR
+35094528,35127295,EU
35127296,35651583,GB
35651584,36700159,IT
36700160,36962303,AE
@@ -222,7 +230,9 @@
201620304,201620311,CA
201620312,201636503,US
201636504,201636511,PR
-201636512,201674095,US
+201636512,201673767,US
+201673768,201673775,CA
+201673776,201674095,US
201674096,201674111,CA
201674112,201745663,US
201745664,201745671,PR
@@ -238,9 +248,7 @@
202385408,202385919,PR
202385920,202517983,US
202517984,202517991,PR
-202517992,202621343,US
-202621344,202621351,PR
-202621352,202621431,US
+202517992,202621431,US
202621432,202621439,PR
202621440,202621479,US
202621480,202621487,PR
@@ -292,8 +300,8 @@
203658752,203658831,VI
203658832,203658847,US
203658848,203658911,PR
-203658912,203658927,VI
-203658928,203658951,PR
+203658912,203658935,VI
+203658936,203658951,PR
203658952,203658967,US
203658968,203658991,VI
203658992,203659007,PR
@@ -317,9 +325,10 @@
204047120,204047231,PR
204047232,204047247,VI
204047248,204047255,US
-204047256,204047263,PR
+204047256,204047263,VI
204047264,204047279,US
-204047280,204047303,VI
+204047280,204047295,VI
+204047296,204047303,US
204047304,204047311,PR
204047312,204047335,VI
204047336,204047359,US
@@ -336,11 +345,11 @@
204047552,204047559,VI
204047560,204047567,PR
204047568,204047591,VI
-204047592,204047999,PR
-204048000,204048007,VI
+204047592,204048007,PR
204048008,204048015,US
204048016,204048031,VI
-204048032,204048055,PR
+204048032,204048047,PR
+204048048,204048055,VI
204048056,204048063,US
204048064,204048127,VI
204048128,204048383,PR
@@ -376,17 +385,15 @@
209845144,209845151,DE
209845152,209867103,US
209867104,209867111,CA
-209867112,209965359,US
-209965360,209965367,PR
-209965368,209988527,US
+209867112,209988527,US
209988528,209988535,VI
209988536,210022479,US
210022480,210022487,PR
210022488,210439559,US
210439560,210439567,PR
-210439568,210784255,US
-210784256,210784383,BO
-210784384,210785023,US
+210439568,210458623,US
+210458624,210458631,PR
+210458632,210785023,US
210785024,210785575,BO
210785576,210785583,US
210785584,210785599,BO
@@ -400,9 +407,7 @@
211126784,211126911,PR
211126912,211129607,US
211129608,211129615,PR
-211129616,211313647,US
-211313648,211313655,PR
-211313656,211363751,US
+211129616,211363751,US
211363752,211363759,PR
211363760,211368655,US
211368656,211368663,PR
@@ -412,12 +417,7 @@
211410120,211410135,PR
211410136,211536367,US
211536368,211536375,PR
-211536376,211595575,US
-211595576,211595583,VI
-211595584,211595615,US
-211595616,211595623,VI
-211595624,211595639,PR
-211595640,211596823,US
+211536376,211596823,US
211596824,211596831,VI
211596832,211597055,US
211597056,211597071,VI
@@ -472,7 +472,9 @@
212787200,212788223,PR
212788224,212788479,US
212788480,212788607,VI
-212788608,212788631,US
+212788608,212788615,US
+212788616,212788623,VI
+212788624,212788631,US
212788632,212788647,VI
212788648,212788655,PR
212788656,212788663,VI
@@ -481,16 +483,14 @@
212788800,212788807,US
212788808,212788815,VI
212788816,212788823,PR
-212788824,212788863,US
+212788824,212788847,US
+212788848,212788863,VI
212788864,212789007,PR
212789008,212789039,US
-212789040,212789055,VI
-212789056,212789063,PR
-212789064,212789079,VI
+212789040,212789079,VI
212789080,212789087,US
212789088,212789095,VI
-212789096,212789111,US
-212789112,212789119,PR
+212789096,212789119,US
212789120,212789127,VI
212789128,212789135,US
212789136,212789143,PR
@@ -509,23 +509,25 @@
212791480,212791807,PR
212791808,212791815,US
212791816,212791839,VI
-212791840,212792191,US
+212791840,212791935,US
+212791936,212792063,VI
+212792064,212792191,US
212792192,212792199,PR
-212792200,212792239,VI
-212792240,212792263,PR
-212792264,212792271,US
+212792200,212792207,VI
+212792208,212792215,PR
+212792216,212792231,VI
+212792232,212792239,US
+212792240,212792247,PR
+212792248,212792271,US
212792272,212792279,VI
212792280,212792287,US
212792288,212792319,PR
212792320,212793103,US
-212793104,212793111,VI
+212793104,212793111,PR
212793112,212793119,US
212793120,212793127,VI
-212793128,212793135,PR
-212793136,212793143,VI
-212793144,212793167,US
-212793168,212793175,VI
-212793176,212793199,US
+212793128,212793143,PR
+212793144,212793199,US
212793200,212793207,VI
212793208,212793215,PR
212793216,212793311,US
@@ -615,9 +617,11 @@
214187808,214187815,PR
214187816,214187823,US
214187824,214187831,PR
-214187832,214187887,US
-214187888,214187895,PR
-214187896,214188031,VI
+214187832,214187839,US
+214187840,214187855,PR
+214187856,214187887,US
+214187888,214187903,PR
+214187904,214188031,VI
214188032,214237247,US
214237248,214237311,PR
214237312,214249471,US
@@ -629,8 +633,8 @@
214698008,214698015,PR
214698016,214698023,US
214698024,214698031,PR
-214698032,214698095,VI
-214698096,214698103,PR
+214698032,214698087,VI
+214698088,214698103,PR
214698104,214698135,VI
214698136,214698143,PR
214698144,214698159,VI
@@ -641,16 +645,17 @@
214698272,214698279,US
214698280,214698319,VI
214698320,214698335,PR
-214698336,214698343,US
-214698344,214698351,VI
-214698352,214698359,US
+214698336,214698351,US
+214698352,214698359,VI
214698360,214698367,PR
-214698368,214698375,VI
-214698376,214698383,US
+214698368,214698383,US
214698384,214698639,PR
214698640,214698655,VI
-214698656,214699231,PR
-214699232,214699295,VI
+214698656,214698919,PR
+214698920,214698927,VI
+214698928,214699231,PR
+214699232,214699263,US
+214699264,214699295,VI
214699296,214699303,US
214699304,214699311,VI
214699312,214699335,PR
@@ -665,7 +670,9 @@
214700008,214700015,PR
214700016,214858655,US
214858656,214858671,NL
-214858672,216417663,US
+214858672,215001095,US
+215001096,215001103,VI
+215001104,216417663,US
216417664,216417727,PR
216417728,216627287,US
216627288,216627295,PR
@@ -810,7 +817,8 @@
408518656,408535039,US
408535040,408551423,CA
408551424,408719359,US
-408719360,408723455,VC
+408719360,408721407,LC
+408721408,408723455,VC
408723456,409337855,US
409337856,409354239,CA
409370624,409731071,US
@@ -996,7 +1004,6 @@
459292672,459293695,NZ
459293696,459297791,JP
459297792,459298815,IN
-459298816,459299839,PK
459300864,459309055,SG
459309056,459325439,KR
459325440,459333631,AU
@@ -1205,6 +1212,7 @@
520318976,520323071,ES
520323072,520325119,CH
520325120,520327167,FR
+520327168,520329215,DE
520329216,520331263,SE
520331264,520339455,IT
520339456,520343551,UA
@@ -1223,6 +1231,7 @@
520500480,520500735,DE
520500736,520501759,IT
520501760,520503295,GB
+520503296,520505343,PL
520505344,520507391,GB
520507392,520511487,TR
520511488,520519679,UA
@@ -1230,6 +1239,7 @@
520552448,520554495,NL
520554496,520556543,GB
520556544,520560639,FI
+520560640,520562687,TR
520562688,520564735,PL
520564736,520566783,IE
520566784,520568831,CH
@@ -1250,7 +1260,9 @@
520761344,520763391,IT
520763392,520765439,CZ
520765440,520781823,RU
-520781824,520822783,CH
+520781824,520822271,CH
+520822272,520822527,DE
+520822528,520822783,CH
520822784,520824831,IT
520824832,520826879,RO
520826880,520828927,QA
@@ -1294,6 +1306,7 @@
521101312,521103359,IT
521103360,521105407,GB
521105408,521107455,IS
+521107456,521109503,FI
521109504,521142271,SI
521142272,521404415,DE
521404416,521535487,NL
@@ -1305,9 +1318,13 @@
521545728,521547775,GB
521547776,521551871,AL
521551872,521553919,DE
-521555968,521558015,NL
+521553920,521555967,GB
+521555968,521556031,US
+521556032,521558015,NL
521558016,521560063,CY
521560064,521562111,PL
+521562112,521562879,DE
+521562880,521564159,GB
521564160,521566207,GR
521566208,521568255,LU
521568256,521601023,PT
@@ -1386,7 +1403,10 @@
522027008,522059775,RU
522059776,522125311,CZ
522125312,522133503,MD
-522133504,522135551,NL
+522133504,522134783,NL
+522134784,522134911,GB
+522134912,522135551,NL
+522135552,522137599,IT
522137600,522141695,CH
522141696,522143743,RU
522143744,522145791,CZ
@@ -1531,7 +1551,7 @@
528748544,528752639,CZ
528752640,528760831,RO
528760832,528762879,PL
-528762880,528764927,RU
+528762880,528764927,AM
528764928,528769023,RO
528769024,528793599,RU
528793600,528795647,RO
@@ -1548,6 +1568,8 @@
528838656,528840703,UA
528840704,528842751,RU
528842752,528859135,CH
+528859136,528861183,RO
+528861184,528863231,RU
528863232,528867327,KZ
528867328,528887807,RU
528887808,528891903,PL
@@ -1571,7 +1593,7 @@
528990208,528994303,PL
528994304,528996351,UZ
528996352,528998399,LT
-529002496,529006591,RU
+528998400,529006591,RU
529006592,529268735,NL
529268736,529530879,TR
529530880,529596415,UA
@@ -1619,6 +1641,7 @@
531103744,531169279,IL
531169280,531177471,KZ
531177472,531179519,GB
+531179520,531181567,FR
531181568,531183615,GB
531183616,531185663,NL
531185664,531193855,TR
@@ -1646,6 +1669,7 @@
531276800,531277311,GB
531277312,531277823,US
531277824,531279871,RU
+531279872,531281919,CZ
531281920,531283967,RU
531283968,531292159,DE
531292160,531333119,AZ
@@ -1663,6 +1687,7 @@
531341312,531349503,KZ
531349504,531351551,RU
531351552,531355647,NL
+531355648,531357695,IR
531357696,531361791,HU
531361792,531365887,CH
531365888,531366399,DE
@@ -1683,7 +1708,11 @@
531425280,531425325,FR
531425326,531425327,GB
531425328,531425391,FR
-531425392,531431423,GB
+531425392,531426303,GB
+531426304,531426431,FR
+531426432,531426559,GB
+531426560,531426623,FR
+531426624,531431423,GB
531431424,531496959,RO
531496960,531628031,PL
531628032,531660799,TR
@@ -1692,6 +1721,7 @@
531695616,531697663,LT
531697664,531699711,GB
531699712,531701759,CZ
+531701760,531703807,NL
531703808,531705855,IT
531705856,531707903,ES
531707904,531709951,GR
@@ -1747,6 +1777,7 @@
532414464,532676607,IT
532676608,532692991,GE
532692992,532701183,CZ
+532701184,532703231,GB
532703232,532704511,RU
532704512,532704767,IN
532704768,532705279,RU
@@ -1762,7 +1793,9 @@
532742144,532742655,GB
532742656,532742783,CN
532742784,532742911,GB
-532742912,532743935,CN
+532742912,532743735,CN
+532743736,532743743,AZ
+532743744,532743935,CN
532743936,532744095,GB
532744096,532744127,CN
532744128,532744191,GB
@@ -1816,26 +1849,208 @@
532807680,533200895,IT
533200896,533233663,TR
533233664,533250047,IE
-533250048,533262335,RU
+533250048,533254143,RU
+533254144,533256191,NL
+533256192,533262335,RU
533262336,533264383,ES
533264384,533266431,RU
-533266432,533266687,NL
-533266688,533266943,DE
-533266944,533267199,NL
-533267200,533267455,AX
-533267456,533267711,AL
-533267712,533267967,AD
-533267968,533268223,AM
-533268224,533268479,AT
-533268480,533268735,AZ
-533268736,533268991,BH
-533268992,533269247,BY
-533269248,533269503,BE
-533269504,533269759,BA
-533269760,533270015,BG
-533270016,533270271,HR
-533270272,533270527,CY
-533270528,533270783,CZ
+533266432,533266435,US
+533266436,533266439,CN
+533266440,533266443,JP
+533266444,533266447,DE
+533266448,533266451,FR
+533266452,533266455,GB
+533266456,533266459,BR
+533266460,533266463,IT
+533266464,533266467,CA
+533266468,533266471,IN
+533266472,533266475,RU
+533266476,533266479,ES
+533266480,533266483,AU
+533266484,533266487,MX
+533266488,533266491,KR
+533266492,533266495,NL
+533266496,533266499,TR
+533266500,533266503,ID
+533266504,533266507,CH
+533266508,533266511,PL
+533266512,533266515,BE
+533266516,533266519,SE
+533266520,533266523,SA
+533266524,533266527,TW
+533266528,533266531,SJ
+533266532,533266535,AT
+533266536,533266539,AR
+533266540,533266543,ZA
+533266544,533266547,IR
+533266548,533266551,TH
+533266552,533266555,DK
+533266556,533266559,GR
+533266560,533266563,AE
+533266564,533266567,VE
+533266568,533266571,CO
+533266572,533266575,FI
+533266576,533266579,MV
+533266580,533266583,PT
+533266584,533266587,HK
+533266588,533266591,SG
+533266592,533266595,EG
+533266596,533266599,NG
+533266600,533266603,IL
+533266604,533266607,IE
+533266608,533266611,CL
+533266612,533266615,CZ
+533266616,533266619,PH
+533266620,533266623,PK
+533266624,533266627,RO
+533266628,533266631,DZ
+533266632,533266635,PE
+533266636,533266639,NZ
+533266640,533266643,KZ
+533266644,533266647,UA
+533266648,533266651,KW
+533266652,533266655,QA
+533266656,533266687,DE
+533266688,533266691,HU
+533266692,533266695,BD
+533266696,533266699,VN
+533266700,533266703,MA
+533266704,533266707,SK
+533266708,533266711,AO
+533266712,533266715,IQ
+533266716,533266719,LY
+533266720,533266723,SD
+533266724,533266727,EC
+533266728,533266731,HR
+533266732,533266735,SY
+533266736,533266739,OM
+533266740,533266743,BY
+533266744,533266747,LU
+533266748,533266751,AZ
+533266752,533266755,DO
+533266756,533266759,LK
+533266760,533266763,SI
+533266764,533266767,FR
+533266768,533266771,BG
+533266772,533266775,TN
+533266776,533266779,GT
+533266780,533266783,UY
+533266784,533266787,LB
+533266788,533266791,UZ
+533266792,533266795,RS
+533266796,533266799,LT
+533266800,533266803,MM
+533266804,533266807,CR
+533266808,533266811,KE
+533266812,533266815,ET
+533266816,533266819,YE
+533266820,533266823,PA
+533266824,533266827,JO
+533266828,533266831,LV
+533266832,533266835,CY
+533266836,533266839,TZ
+533266840,533266843,CI
+533266844,533266847,CM
+533266848,533266851,SV
+533266852,533266855,BH
+533266856,533266859,TT
+533266860,533266863,EE
+533266864,533266867,BO
+533266868,533266871,GH
+533266872,533266875,PY
+533266876,533266879,UG
+533266880,533266883,AF
+533266884,533266887,BA
+533266888,533266891,ZM
+533266892,533266895,HN
+533266896,533266899,NP
+533266900,533266903,GQ
+533266904,533266907,JM
+533266908,533266911,IS
+533266912,533266943,DE
+533266944,533266947,SN
+533266948,533266951,CD
+533266952,533266955,GA
+533266956,533266959,US
+533266960,533266963,BN
+533266964,533266967,CG
+533266968,533266971,AL
+533266972,533266975,NA
+533266976,533266979,KH
+533266980,533266983,GE
+533266984,533266987,MK
+533266988,533266991,MU
+533266992,533266995,ML
+533266996,533266999,AM
+533267000,533267003,PG
+533267004,533267007,BF
+533267008,533267011,MG
+533267012,533267015,MT
+533267016,533267019,TD
+533267020,533267023,BS
+533267024,533267027,HT
+533267028,533267031,BJ
+533267032,533267035,NI
+533267036,533267039,LS
+533267040,533267043,MN
+533267044,533267047,RW
+533267048,533267051,NE
+533267052,533267055,TJ
+533267056,533267059,ZW
+533267060,533267063,MD
+533267064,533267067,MW
+533267068,533267071,KG
+533267072,533267075,GN
+533267076,533267079,BB
+533267080,533267083,ME
+533267084,533267087,MR
+533267088,533267091,SR
+533267092,533267095,SZ
+533267096,533267099,FJ
+533267100,533267103,TG
+533267104,533267107,ER
+533267108,533267111,GY
+533267112,533267115,CF
+533267116,533267119,SL
+533267120,533267123,LS
+533267124,533267127,CV
+533267128,533267131,BI
+533267132,533267135,MV
+533267136,533267139,BZ
+533267140,533267143,BT
+533267144,533267147,DJ
+533267148,533267151,AG
+533267152,533267155,GM
+533267156,533267159,LC
+533267160,533267163,LR
+533267164,533267167,SC
+533267168,533267199,DE
+533267200,533267423,US
+533267424,533267455,DE
+533267456,533267679,CN
+533267680,533267711,DE
+533267712,533267935,JP
+533267936,533268223,DE
+533268224,533268447,FR
+533268448,533268479,DE
+533268480,533268703,GB
+533268704,533268735,DE
+533268736,533268959,BR
+533268960,533268991,DE
+533268992,533269215,IT
+533269216,533269247,DE
+533269248,533269471,CA
+533269472,533269503,DE
+533269504,533269727,IN
+533269728,533269759,DE
+533269760,533269983,ES
+533269984,533270015,DE
+533270016,533270239,AU
+533270240,533270271,DE
+533270272,533270495,KR
+533270496,533270527,DE
+533270528,533270751,NL
+533270752,533270783,DE
533270784,533271039,DK
533271040,533271295,EE
533271296,533271551,FO
@@ -2041,6 +2256,7 @@
533331968,533397503,UA
533397504,533463039,KW
533463040,533479423,RU
+533479424,533481471,DE
533481472,533483519,NO
533483520,533485567,FR
533485568,533487615,LU
@@ -2069,15 +2285,15 @@
533819392,533823487,DE
533823488,533823743,CD
533823744,533825535,BE
-533827584,533831679,IS
+533825536,533831679,IS
533831680,533835775,DE
533835776,533837823,SE
533837824,533839871,DE
533839872,533856255,IS
533856256,533858303,FR
533858304,533860351,HU
-533860352,533860863,DE
-533860864,533862399,NL
+533860352,533861375,DE
+533861376,533862399,NL
533862400,533864447,GB
533864448,533889023,TR
533889024,533891071,GB
@@ -2100,7 +2316,12 @@
533970944,533987327,SE
533987328,534118399,DE
534118400,534151167,KW
-534151168,534183935,DE
+534151168,534157759,DE
+534157760,534157823,US
+534157824,534175743,DE
+534175744,534179839,NL
+534179840,534181887,US
+534181888,534183935,DE
534183936,534249471,RO
534249472,534253567,GB
534253568,534257407,FR
@@ -2121,6 +2342,16 @@
534308864,534310911,IE
534310912,534315007,IT
534315008,534347775,HR
+534347776,534355967,GB
+534355968,534364159,GR
+534364160,534366207,FI
+534366208,534368255,IT
+534368256,534370303,IR
+534370304,534372351,AT
+534372352,534374399,KW
+534374400,534376447,FR
+534376448,534378495,IE
+534378496,534380543,FR
534380544,534511615,AE
534511616,534544383,DE
534544384,534546431,RO
@@ -2138,7 +2369,7 @@
534663168,534675455,ES
534675456,534691839,GB
534691840,534693887,FR
-534693888,534695935,GB
+534693888,534700031,GB
534700032,534708223,JO
534708224,534740991,TR
534740992,534749183,BA
@@ -2150,7 +2381,9 @@
534767616,534769663,HU
534769664,534773759,IT
534773760,536870911,DE
-536870912,539624567,US
+536870912,539623999,US
+539624000,539624031,NL
+539624032,539624567,US
539624568,539624575,IE
539624576,539624703,US
539624704,539624735,GB
@@ -2299,7 +2532,9 @@
604504064,605028351,JP
605028352,606412799,CN
606412800,606413823,HK
-606413824,606420991,CN
+606413824,606414335,CN
+606414336,606414591,AU
+606414592,606420991,CN
606420992,606437375,ID
606437376,606470143,KH
606470144,606601215,KR
@@ -2445,6 +2680,8 @@
692936704,692940799,ZA
692940800,692942847,MA
692942848,692944895,GA
+692944896,692946943,MZ
+692946944,692948991,EG
692969472,692971519,TZ
692973568,692975615,MZ
692975616,692977663,EG
@@ -2509,7 +2746,6 @@
693045248,693046271,KE
693046272,693047295,ZW
693047296,693049343,ZA
-693049344,693050367,SD
693050368,693051391,ZW
693051392,693052415,BW
693052416,693054463,ZA
@@ -2524,6 +2760,8 @@
693064704,693065727,GH
693065728,693066751,MW
693066752,693067775,ZA
+693068800,693069823,TZ
+693069824,693071871,ZA
693101568,693102591,KE
693102592,693103615,CD
693103616,693104639,GN
@@ -2652,7 +2890,7 @@
700408832,700409855,CM
700409856,700410879,LR
700410880,700411903,NG
-700411904,700412927,KE
+700411904,700412927,ZA
700412928,700413951,ZM
700413952,700414975,SC
700414976,700432383,ZA
@@ -3045,9 +3283,9 @@
772837376,772839423,KZ
772839424,772841471,CH
772841472,772843519,GB
-772843520,772844287,IT
-772844288,772844799,US
-772844800,772845567,IT
+772843520,772844799,IT
+772844800,772845311,US
+772845312,772845567,IT
772845568,772847615,RU
772847616,772849663,GB
772849664,772851711,BG
@@ -3109,7 +3347,6 @@
772950016,772952063,ES
772952064,772954111,GB
772954112,772958207,FR
-772958208,772960255,PL
772960256,772962303,GB
772962304,772966399,FR
772966400,772968447,IT
@@ -3172,7 +3409,9 @@
773064448,773064703,US
773064704,773065088,TR
773065089,773065215,US
-773065216,773066751,TR
+773065216,773065584,TR
+773065585,773065590,GB
+773065591,773066751,TR
773066752,773070847,AT
773070848,773071231,DE
773071232,773071263,NA
@@ -3202,16 +3441,20 @@
773148672,773152767,IR
773152768,773153791,SE
773153792,773154815,US
-773154816,773156863,SE
+773154816,773155583,SE
+773155584,773155839,US
+773155840,773156863,SE
773156864,773157887,FR
773157888,773158911,DE
773158912,773160447,FR
773160448,773160959,ES
773160960,773165055,FR
773165056,773166591,NL
-773166592,773167103,US
-773167104,773167615,NL
-773167616,773169151,US
+773166592,773167359,US
+773167360,773167615,NL
+773167616,773168639,US
+773168640,773168671,NL
+773168672,773169151,US
773169152,773171343,NL
773171344,773171359,BE
773171360,773172223,NL
@@ -3238,9 +3481,7 @@
773234688,773238783,PL
773238784,773242879,NL
773242880,773246975,FR
-773246976,773247871,EE
-773247872,773247999,US
-773248000,773251071,EE
+773246976,773251071,EE
773251072,773255167,AZ
773255168,773259263,RU
773259264,773263359,SI
@@ -3282,10 +3523,12 @@
773621760,773623807,PS
773623808,773625855,SE
773625856,773627903,IS
+773627904,773629951,ES
773629952,773631999,FR
773632000,773634047,CY
773634048,773636095,DE
773636096,773638143,UA
+773638144,773640191,CH
773640192,773642239,ES
773642240,773644287,HU
773644288,773646335,RU
@@ -3309,13 +3552,11 @@
773672960,773675007,SA
773675008,773677055,GB
773677056,773679103,DE
-773679104,773679135,IT
-773679136,773679327,A2
-773679328,773679359,IT
+773679104,773679359,IT
773679360,773679423,GB
-773679424,773679615,A2
-773679616,773680191,IT
-773680192,773681151,A2
+773679424,773680383,IT
+773680384,773680639,A2
+773680640,773681151,IT
773681152,773683199,RU
773683200,773684223,FR
773684224,773684239,GB
@@ -3348,7 +3589,9 @@
773730304,773732351,GB
773732352,773734399,DE
773734400,773736447,CZ
-773736448,773740543,DE
+773736448,773739071,DE
+773739072,773739079,AT
+773739080,773740543,DE
773740544,773742591,CZ
773742592,773744639,GB
773744640,773746687,ES
@@ -3363,23 +3606,30 @@
773763072,773765119,TR
773765120,773767167,NL
773767168,773769215,GB
+773769216,773771263,FR
773771264,773773311,DK
773773312,773775359,IT
773775360,773777407,IQ
773777408,773779455,CZ
-773781504,773783551,IT
+773779456,773783551,IT
773783552,773785599,RU
773785600,773787647,NL
773787648,773789695,DK
773789696,773791743,RU
773791744,773793791,PL
-773793792,773795839,FR
+773793792,773794527,FR
+773794528,773794535,GB
+773794536,773794543,IT
+773794544,773794551,ES
+773794552,773794559,DE
+773794560,773795839,FR
773795840,773797887,NL
773797888,773799935,ES
773799936,773800447,GB
773800448,773800703,CY
773800704,773800959,GB
-773800960,773801727,CY
+773800960,773801215,SG
+773801216,773801727,US
773801728,773801983,GB
773801984,773804031,IQ
773804032,773806079,GB
@@ -3421,7 +3671,9 @@
773980160,773988351,GB
773988352,774003199,ES
774003200,774003263,TR
-774003264,774003711,ES
+774003264,774003327,ES
+774003328,774003391,TR
+774003392,774003711,ES
774003712,774004223,BE
774004224,774004479,ES
774004480,774004511,BE
@@ -3432,7 +3684,9 @@
774029312,774037503,RO
774037504,774045695,SK
774045696,774053887,FR
-774053888,774055935,DE
+774053888,774055679,DE
+774055680,774055807,BZ
+774055808,774055935,DE
774055936,774057983,US
774057984,774058359,DE
774058360,774058367,HR
@@ -3542,10 +3796,10 @@
774161439,774161448,MK
774161449,774161458,PS
774161459,774161468,UZ
-774161469,774161478,BD
-774161479,774161488,KP
+774161469,774161478,MS
+774161479,774161488,US
774161489,774161498,MN
-774161499,774161518,VA
+774161499,774161518,US
774161519,774161528,TW
774161529,774161538,DO
774161539,774161548,PY
@@ -3556,20 +3810,20 @@
774161589,774161598,TC
774161599,774161608,US
774161609,774161618,LI
-774161619,774161628,AE
+774161619,774161628,US
774161629,774161638,PA
774161639,774161648,RU
774161649,774161658,HK
774161659,774161664,VA
-774161665,774161674,CY
+774161665,774161674,US
774161675,774161684,CL
-774161685,774161694,NI
+774161685,774161694,GR
774161695,774161704,AG
774161705,774161714,AM
-774161715,774161724,IR
+774161715,774161724,GB
774161725,774161734,RO
774161735,774161744,UA
-774161745,774161754,NP
+774161745,774161754,AU
774161755,774161764,PG
774161765,774161774,ZA
774161775,774161784,SN
@@ -3603,10 +3857,10 @@
774161976,774161980,US
774161981,774161985,GB
774161986,774161990,IQ
-774161991,774161995,AF
+774161991,774161995,LT
774161996,774162000,ER
774162001,774162005,KE
-774162006,774162010,MG
+774162006,774162010,DE
774162011,774162015,TN
774162016,774162020,TT
774162021,774162025,BO
@@ -3617,7 +3871,7 @@
774162046,774162050,HR
774162051,774162055,ME
774162056,774162060,SY
-774162061,774162065,YE
+774162061,774162065,US
774162066,774162070,HT
774162071,774162075,EC
774162076,774162080,SH
@@ -3626,11 +3880,11 @@
774162091,774162095,VN
774162096,774162100,FM
774162101,774162105,US
-774162106,774162110,LY
+774162106,774162110,GB
774162111,774162115,SO
774162116,774162120,FI
774162121,774162125,DZ
-774162126,774162130,CD
+774162126,774162130,MO
774162131,774162135,MR
774162136,774162140,CM
774162141,774162145,SV
@@ -3681,7 +3935,9 @@
774162643,774162687,US
774162688,774162688,VA
774162689,774162718,US
-774162719,774168575,VA
+774162719,774162943,VA
+774162944,774163199,CH
+774163200,774168575,VA
774168576,774176767,PL
774176768,774184959,IT
774184960,774193151,GB
@@ -3762,11 +4018,9 @@
774219680,774219687,PK
774219688,774219711,GB
774219712,774219727,BE
-774219728,774219743,RU
-774219744,774219751,GB
+774219728,774219751,GB
774219752,774219759,PK
-774219760,774219775,RU
-774219776,774219839,CN
+774219760,774219839,CN
774219840,774219847,UA
774219848,774219855,CN
774219856,774219863,GB
@@ -3781,14 +4035,15 @@
774219992,774219999,RU
774220000,774220007,GB
774220008,774220015,CN
-774220016,774220159,GB
+774220016,774220023,GB
+774220024,774220031,PK
+774220032,774220159,GB
774220160,774220191,US
774220192,774220207,GB
774220208,774220223,CN
774220224,774220287,GB
774220288,774220543,CN
-774220544,774220799,GB
-774220800,774221055,PK
+774220544,774221055,GB
774221056,774221311,US
774221312,774221567,CN
774221568,774221823,US
@@ -3796,7 +4051,7 @@
774222080,774222335,US
774222336,774222495,GB
774222496,774222511,FI
-774222512,774222527,HK
+774222512,774222527,CN
774222528,774222591,GB
774222592,774222655,CN
774222656,774222687,BE
@@ -3804,7 +4059,7 @@
774222720,774222783,CN
774222784,774222799,GB
774222800,774222815,UA
-774222816,774222847,GB
+774222816,774222847,CN
774222848,774222863,UA
774222864,774222879,IT
774222880,774222895,US
@@ -3863,8 +4118,7 @@
774224104,774224111,RU
774224112,774224119,CN
774224120,774224127,IN
-774224128,774224159,BE
-774224160,774224191,GB
+774224128,774224191,GB
774224192,774224223,US
774224224,774224255,LT
774224256,774224383,GB
@@ -3874,9 +4128,7 @@
774224416,774224423,TW
774224424,774224431,GB
774224432,774224439,CN
-774224440,774224447,GB
-774224448,774224511,CN
-774224512,774224767,GB
+774224440,774224767,GB
774224768,774224831,CN
774224832,774224847,UA
774224848,774224967,GB
@@ -3967,8 +4219,7 @@
774750208,774782975,RU
774782976,774799359,UA
774799360,774815743,RU
-774815744,774830079,NO
-774830080,774832127,SE
+774815744,774832127,NO
774832128,774848511,RU
774848512,774864895,BG
774864896,774881279,CZ
@@ -4084,7 +4335,14 @@
778666160,778666175,PL
778666176,778666207,FR
778666208,778666239,PL
-778666240,778666367,FR
+778666240,778666247,GB
+778666248,778666259,FR
+778666260,778666263,PL
+778666264,778666271,CH
+778666272,778666295,FR
+778666296,778666299,ES
+778666300,778666303,GB
+778666304,778666367,FR
778666368,778666371,PL
778666372,778666375,GB
778666376,778666383,FR
@@ -4124,7 +4382,7 @@
778667480,778667483,GB
778667484,778667487,NL
778667488,778667491,PL
-778667492,778667495,FR
+778667492,778667495,CH
778667496,778667499,DE
778667500,778667503,GB
778667504,778667839,FR
@@ -4220,7 +4478,7 @@
778669760,778669767,DE
778669768,778669771,GB
778669772,778669775,PL
-778669776,778669791,FR
+778669776,778669791,ES
778669792,778669807,DE
778669808,778669823,FR
778669824,778669855,ES
@@ -4287,7 +4545,8 @@
778671120,778671127,DE
778671128,778671135,PT
778671136,778671167,BE
-778671168,778671203,FR
+778671168,778671183,FI
+778671184,778671203,FR
778671204,778671211,PL
778671212,778671231,FR
778671232,778671239,GB
@@ -4363,7 +4622,13 @@
778673084,778673087,PT
778673088,778673119,FR
778673120,778673151,ES
-778673152,778673215,FR
+778673152,778673191,FR
+778673192,778673195,ES
+778673196,778673199,GB
+778673200,778673203,CZ
+778673204,778673207,IE
+778673208,778673211,DE
+778673212,778673215,ES
778673216,778673247,FI
778673248,778673263,FR
778673264,778673279,IT
@@ -4381,7 +4646,14 @@
778673824,778673839,ES
778673840,778673843,FR
778673844,778673855,DE
-778673856,778673919,FR
+778673856,778673879,FR
+778673880,778673883,CZ
+778673884,778673887,FI
+778673888,778673903,FR
+778673904,778673907,DE
+778673908,778673911,CH
+778673912,778673915,FR
+778673916,778673919,ES
778673920,778674175,NL
778674176,778674367,FR
778674368,778674387,DE
@@ -4399,7 +4671,9 @@
778674464,778674471,CH
778674472,778674475,BE
778674476,778674479,CH
-778674480,778674495,FR
+778674480,778674487,FR
+778674488,778674491,CZ
+778674492,778674495,PL
778674496,778674499,CZ
778674500,778674503,DE
778674504,778674507,PL
@@ -4485,7 +4759,7 @@
778676096,778676099,DE
778676100,778676103,CZ
778676104,778676111,GB
-778676112,778676127,DE
+778676112,778676127,IT
778676128,778676131,ES
778676132,778676135,CZ
778676136,778676139,DE
@@ -4524,7 +4798,11 @@
778676672,778676687,FR
778676688,778676691,ES
778676692,778676703,PL
-778676704,778676735,FR
+778676704,778676719,FR
+778676720,778676723,GB
+778676724,778676727,PT
+778676728,778676731,PL
+778676732,778676735,IT
778676736,778676743,PL
778676744,778676747,CH
778676748,778676751,CZ
@@ -4533,11 +4811,13 @@
778676772,778676775,ES
778676776,778676779,PL
778676780,778676799,FR
-778676800,778676815,IE
+778676800,778676803,GB
+778676804,778676807,IT
+778676808,778676811,FI
+778676812,778676815,IE
778676816,778676823,LT
778676824,778676827,GB
-778676828,778676831,FR
-778676832,778676847,ES
+778676828,778676847,FR
778676848,778676851,NL
778676852,778676855,LT
778676856,778676859,FR
@@ -4545,11 +4825,16 @@
778676864,778676991,PL
778676992,778676999,FR
778677000,778677003,PL
-778677004,778677075,FR
+778677004,778677023,FR
+778677024,778677055,DE
+778677056,778677075,FR
778677076,778677079,DE
778677080,778677083,IT
-778677084,778677119,DE
-778677120,778677151,FR
+778677084,778677123,DE
+778677124,778677127,GB
+778677128,778677131,FR
+778677132,778677135,BE
+778677136,778677151,FR
778677152,778677167,DE
778677168,778677175,CZ
778677176,778677183,NL
@@ -4624,7 +4909,8 @@
778678864,778678871,PL
778678872,778678875,ES
778678876,778678879,NL
-778678880,778678903,FR
+778678880,778678895,FR
+778678896,778678903,GB
778678904,778678911,PL
778678912,778678919,FR
778678920,778678927,ES
@@ -4646,12 +4932,14 @@
778679200,778679215,FR
778679216,778679231,PT
778679232,778679263,ES
-778679264,778679271,FR
+778679264,778679267,IT
+778679268,778679271,FR
778679272,778679279,PL
778679280,778679295,PT
778679296,778679495,FR
778679496,778679519,PL
-778679520,778679527,FR
+778679520,778679523,LT
+778679524,778679527,PL
778679528,778679531,DE
778679532,778679535,GB
778679536,778679551,ES
@@ -4680,7 +4968,10 @@
778680152,778680155,ES
778680156,778680159,BE
778680160,778680175,PT
-778680176,778680207,PL
+778680176,778680183,ES
+778680184,778680199,IT
+778680200,778680203,NL
+778680204,778680207,PL
778680208,778680227,FR
778680228,778680231,IE
778680232,778680239,GB
@@ -4699,7 +4990,9 @@
778680576,778680639,NL
778680640,778680647,DE
778680648,778680671,ES
-778680672,778680687,LT
+778680672,778680679,FR
+778680680,778680683,PL
+778680684,778680687,DE
778680688,778680767,FR
778680768,778680831,BE
778680832,778680895,IT
@@ -4710,9 +5003,9 @@
778681152,778681215,PL
778681216,778681235,FR
778681236,778681239,ES
-778681240,778681247,FR
-778681248,778681263,GB
-778681264,778681279,FR
+778681240,778681251,FR
+778681252,778681255,DE
+778681256,778681279,FR
778681280,778681295,DE
778681296,778681311,IE
778681312,778681315,NL
@@ -4735,8 +5028,8 @@
778681472,778681475,DE
778681476,778681479,PT
778681480,778681503,FR
-778681504,778681519,GB
-778681520,778681523,PL
+778681504,778681519,PL
+778681520,778681523,ES
778681524,778681527,FR
778681528,778681531,PL
778681532,778681535,CH
@@ -4755,7 +5048,7 @@
778681680,778681703,FR
778681704,778681707,IE
778681708,778681711,ES
-778681712,778681727,PL
+778681712,778681727,FR
778681728,778682111,GB
778682112,778682115,IT
778682116,778682119,PL
@@ -4770,9 +5063,7 @@
778682208,778682239,FR
778682240,778682243,BE
778682244,778682247,DE
-778682248,778682271,FR
-778682272,778682287,PL
-778682288,778682295,FR
+778682248,778682295,FR
778682296,778682303,PL
778682304,778682331,FR
778682332,778682335,NL
@@ -4785,9 +5076,9 @@
778690640,778690655,IT
778690656,778690687,PT
778690688,778690703,PL
-778690704,778690719,FR
-778690720,778690735,PL
-778690736,778690751,FR
+778690704,778690723,FR
+778690724,778690727,GB
+778690728,778690751,FR
778690752,778690783,DE
778690784,778690815,FR
778690816,778690879,ES
@@ -4807,8 +5098,7 @@
778691044,778691047,ES
778691048,778691051,PL
778691052,778691055,PT
-778691056,778691343,FR
-778691344,778691359,IT
+778691056,778691359,FR
778691360,778691583,PT
778691584,778691743,FR
778691744,778691747,PL
@@ -4820,9 +5110,12 @@
778691840,778691855,CH
778691856,778691975,FR
778691976,778691983,ES
-778691984,778692015,PL
+778691984,778691987,BE
+778691988,778691991,IT
+778691992,778691999,FR
+778692000,778692015,PL
778692016,778692031,IE
-778692032,778692039,FR
+778692032,778692039,DE
778692040,778692063,PL
778692064,778692095,CH
778692096,778692099,PL
@@ -4833,7 +5126,8 @@
778692116,778692127,FR
778692128,778692143,NL
778692144,778692159,DE
-778692160,778692207,GB
+778692160,778692191,FR
+778692192,778692207,GB
778692208,778692615,FR
778692616,778692619,PL
778692620,778692623,IE
@@ -4842,11 +5136,13 @@
778692652,778692671,PL
778692672,778692679,DE
778692680,778692683,ES
-778692684,778692687,FR
-778692688,778692703,GB
+778692684,778692703,FR
778692704,778692723,PL
778692724,778692735,FR
-778692736,778692751,NL
+778692736,778692739,ES
+778692740,778692743,PL
+778692744,778692747,PT
+778692748,778692751,ES
778692752,778692767,FR
778692768,778692783,FI
778692784,778692787,GB
@@ -4865,8 +5161,10 @@
778692892,778692895,GB
778692896,778692911,FR
778692912,778692927,NL
-778692928,778692959,FR
-778692960,778692975,GB
+778692928,778692959,DE
+778692960,778692967,FR
+778692968,778692971,LT
+778692972,778692975,PT
778692976,778692983,DE
778692984,778692991,FR
778692992,778693023,GB
@@ -4885,7 +5183,7 @@
778693088,778693091,IE
778693092,778693095,FR
778693096,778693103,IE
-778693104,778693119,IT
+778693104,778693119,FR
778693120,778693151,BE
778693152,778693167,GB
778693168,778693171,CZ
@@ -4906,7 +5204,9 @@
778693408,778693439,PT
778693440,778693455,FR
778693456,778693459,DE
-778693460,778693535,FR
+778693460,778693511,FR
+778693512,778693515,CZ
+778693516,778693535,FR
778693536,778693567,NL
778693568,778693599,BE
778693600,778693631,NL
@@ -4920,7 +5220,270 @@
778693824,778693839,PT
778693840,778693855,ES
778693856,778693887,DE
-778693888,778698751,FR
+778693888,778693919,PT
+778693920,778693927,CH
+778693928,778693931,PL
+778693932,778693935,DE
+778693936,778693951,GB
+778693952,778693967,FR
+778693968,778693971,ES
+778693972,778693975,PL
+778693976,778693983,GB
+778693984,778694015,IE
+778694016,778694143,FR
+778694144,778694147,DE
+778694148,778694159,PL
+778694160,778694175,FI
+778694176,778694187,GB
+778694188,778694191,ES
+778694192,778694195,BE
+778694196,778694199,PL
+778694200,778694203,IT
+778694204,778694291,FR
+778694292,778694295,DE
+778694296,778694299,FR
+778694300,778694335,PL
+778694336,778694351,IT
+778694352,778694415,FR
+778694416,778694463,IT
+778694464,778694479,GB
+778694480,778694511,IT
+778694512,778694527,CZ
+778694528,778694543,PL
+778694544,778694555,DE
+778694556,778694559,FR
+778694560,778694563,PL
+778694564,778694567,DE
+778694568,778694571,PT
+778694572,778694575,BE
+778694576,778694591,PT
+778694592,778694623,FR
+778694624,778694627,DE
+778694628,778694639,FR
+778694640,778694643,PL
+778694644,778694647,PT
+778694648,778694687,FR
+778694688,778694703,GB
+778694704,778694719,FR
+778694720,778694783,IT
+778694784,778694815,FR
+778694816,778694847,GB
+778694848,778694911,FR
+778694912,778694943,GB
+778694944,778694959,FR
+778694960,778694975,ES
+778694976,778695007,GB
+778695008,778695039,ES
+778695040,778695167,GB
+778695168,778695183,FR
+778695184,778695191,GB
+778695192,778695203,PL
+778695204,778695207,ES
+778695208,778695215,FR
+778695216,778695231,DE
+778695232,778695295,NL
+778695296,778695327,PT
+778695328,778695331,IE
+778695332,778695335,GB
+778695336,778695339,PL
+778695340,778695343,FR
+778695344,778695351,LT
+778695352,778695383,FR
+778695384,778695399,DE
+778695400,778695415,GB
+778695416,778695423,IT
+778695424,778695431,PT
+778695432,778695439,ES
+778695440,778695447,FI
+778695448,778695455,NL
+778695456,778695471,FR
+778695472,778695475,PL
+778695476,778695479,NL
+778695480,778695487,FR
+778695488,778695503,BE
+778695504,778695519,FR
+778695520,778695535,GB
+778695536,778695551,FR
+778695552,778695567,GB
+778695568,778695575,PL
+778695576,778695579,ES
+778695580,778695583,FI
+778695584,778695615,PL
+778695616,778695623,DE
+778695624,778695627,CZ
+778695628,778695663,FR
+778695664,778695679,NL
+778695680,778695711,PT
+778695712,778695763,FR
+778695764,778695767,PL
+778695768,778695775,ES
+778695776,778695795,FR
+778695796,778695799,ES
+778695800,778695807,FR
+778695808,778695823,ES
+778695824,778695839,FR
+778695840,778695903,DE
+778695904,778695911,FI
+778695912,778695919,FR
+778695920,778695923,PL
+778695924,778695927,CZ
+778695928,778695931,FI
+778695932,778695943,ES
+778695944,778695951,FI
+778695952,778695967,DE
+778695968,778695971,ES
+778695972,778695975,PL
+778695976,778695983,FR
+778695984,778695987,PL
+778695988,778695991,FR
+778695992,778695995,GB
+778695996,778695999,BE
+778696000,778696015,FR
+778696016,778696019,PL
+778696020,778696023,ES
+778696024,778696027,DE
+778696028,778696031,GB
+778696032,778696063,PL
+778696064,778696099,FR
+778696100,778696103,GB
+778696104,778696107,FR
+778696108,778696111,DE
+778696112,778696127,FR
+778696128,778696159,DE
+778696160,778696175,GB
+778696176,778696183,DE
+778696184,778696187,NL
+778696188,778696199,FR
+778696200,778696203,IT
+778696204,778696207,ES
+778696208,778696223,FR
+778696224,778696255,IE
+778696256,778696263,IT
+778696264,778696287,ES
+778696288,778696335,DE
+778696336,778696339,PL
+778696340,778696343,IT
+778696344,778696347,CH
+778696348,778696351,PL
+778696352,778696383,ES
+778696384,778696415,IE
+778696416,778696419,FR
+778696420,778696423,NL
+778696424,778696479,FR
+778696480,778696495,IT
+778696496,778696499,ES
+778696500,778696503,FR
+778696504,778696511,IT
+778696512,778696543,DE
+778696544,778696559,FR
+778696560,778696567,DE
+778696568,778696575,ES
+778696576,778696591,GB
+778696592,778696639,IE
+778696640,778696643,ES
+778696644,778696647,NL
+778696648,778696655,FR
+778696656,778696671,NL
+778696672,778696687,FR
+778696688,778696691,BE
+778696692,778696695,FI
+778696696,778696699,FR
+778696700,778696703,GB
+778696704,778696959,FR
+778696960,778696975,IT
+778696976,778696991,GB
+778696992,778696995,NL
+778696996,778696999,ES
+778697000,778697015,FR
+778697016,778697019,PL
+778697020,778697023,ES
+778697024,778697055,DE
+778697056,778697059,PL
+778697060,778697063,FR
+778697064,778697067,PL
+778697068,778697071,FR
+778697072,778697087,IT
+778697088,778697095,IE
+778697096,778697099,FR
+778697100,778697103,PL
+778697104,778697151,IE
+778697152,778697167,GB
+778697168,778697171,FR
+778697172,778697175,DE
+778697176,778697179,PL
+778697180,778697183,GB
+778697184,778697343,FR
+778697344,778697375,DE
+778697376,778697387,FR
+778697388,778697391,ES
+778697392,778697407,FR
+778697408,778697415,PT
+778697416,778697423,BE
+778697424,778697435,FR
+778697436,778697439,GB
+778697440,778697455,FR
+778697456,778697459,IT
+778697460,778697463,CZ
+778697464,778697467,NL
+778697468,778697471,PL
+778697472,778697679,FR
+778697680,778697683,PL
+778697684,778697687,FR
+778697688,778697695,ES
+778697696,778697727,FR
+778697728,778697791,FI
+778697792,778697807,ES
+778697808,778697811,GB
+778697812,778697815,PL
+778697816,778697819,FR
+778697820,778697823,IT
+778697824,778697951,PT
+778697952,778697955,DE
+778697956,778697959,IE
+778697960,778697967,ES
+778697968,778697975,FR
+778697976,778697979,BE
+778697980,778697983,FI
+778697984,778698239,NL
+778698240,778698247,GB
+778698248,778698251,ES
+778698252,778698255,PL
+778698256,778698287,FR
+778698288,778698295,FI
+778698296,778698303,IE
+778698304,778698399,FR
+778698400,778698447,IE
+778698448,778698451,NL
+778698452,778698455,PL
+778698456,778698459,CZ
+778698460,778698463,PL
+778698464,778698467,GB
+778698468,778698471,PL
+778698472,778698479,IT
+778698480,778698495,FR
+778698496,778698499,GB
+778698500,778698503,FR
+778698504,778698511,CH
+778698512,778698519,FI
+778698520,778698527,FR
+778698528,778698531,IT
+778698532,778698535,CH
+778698536,778698539,PL
+778698540,778698543,IT
+778698544,778698555,PL
+778698556,778698643,FR
+778698644,778698647,PL
+778698648,778698655,ES
+778698656,778698667,FR
+778698668,778698671,ES
+778698672,778698687,IE
+778698688,778698695,LT
+778698696,778698703,FR
+778698704,778698707,DE
+778698708,778698711,ES
+778698712,778698715,NL
+778698716,778698719,ES
+778698720,778698751,FR
778698752,778764287,TR
778764288,778829823,HU
778829824,778895359,RO
@@ -5271,7 +5834,6 @@
781711360,781713407,UA
781713408,781844479,SA
781844480,781975551,TR
-781975552,782106623,GB
782106624,782254079,RU
782254080,782270463,UA
782270464,782319615,RU
@@ -5302,14 +5864,17 @@
782664704,782664704,GB
782664705,782665471,NL
782665472,782666495,US
-782666496,782667007,GB
+782666496,782666751,GB
+782666752,782667007,US
782667008,782667519,RU
782667520,782667775,LU
-782667776,782668287,FR
+782667776,782668031,GB
+782668032,782668287,FR
782668288,782668799,RU
782668800,782669567,NL
-782669568,782671615,DE
-782671616,782680063,GB
+782669568,782669823,GB
+782669824,782671871,DE
+782671872,782680063,GB
782680064,782696447,RU
782696448,782712831,DE
782712832,782729215,RU
@@ -5561,9 +6126,7 @@
786747392,786751487,SK
786751488,786755583,PL
786755584,786759679,IT
-786759680,786771711,DE
-786771712,786771775,AT
-786771776,786771967,DE
+786759680,786771967,DE
786771968,786776063,UA
786776064,786780159,RU
786780160,786784255,IT
@@ -5572,7 +6135,9 @@
786792448,786796543,RU
786796544,786800639,PL
786800640,786801023,US
-786801024,786804735,UA
+786801024,786801151,UA
+786801152,786801663,US
+786801664,786804735,UA
786804736,786808831,RU
786808832,786812927,BG
786812928,786817023,RU
@@ -5605,6 +6170,7 @@
786939904,786941951,FI
786941952,786943999,CH
786944000,786946047,RU
+786946048,786948095,FR
786948096,786950143,UA
786950144,786952191,DE
786952192,786952703,NE
@@ -5633,7 +6199,15 @@
787054592,787070975,IT
787070976,787087359,RU
787087360,787095551,TR
-787095552,787103743,EU
+787095552,787095567,EU
+787095568,787095599,CH
+787095600,787095807,EU
+787095808,787096063,CH
+787096064,787096575,EU
+787096576,787098367,CH
+787098368,787099647,EU
+787099648,787102975,CH
+787102976,787103743,EU
787103744,787111935,HR
787111936,787120127,CZ
787120128,787128319,ES
@@ -5740,7 +6314,9 @@
787843072,787845119,GR
787845120,787847167,CH
787847168,787849215,SE
-787849216,787851263,TR
+787849216,787850496,TR
+787850497,787850751,NL
+787850752,787851263,TR
787851264,787853311,RU
787853312,787855359,DE
787855360,787857407,CH
@@ -5861,8 +6437,7 @@
788455424,788457471,FR
788457472,788459519,IT
788459520,788461567,RU
-788461568,788463615,JE
-788463616,788465663,GB
+788461568,788465663,GB
788465664,788467711,CZ
788467712,788469759,NO
788469760,788471807,NL
@@ -5884,8 +6459,12 @@
788502528,788504575,IE
788504576,788506623,FR
788506624,788508671,CH
-788508672,788509199,FR
-788509200,788509695,AT
+788508672,788509207,FR
+788509208,788509231,AT
+788509232,788509247,FR
+788509248,788509439,AT
+788509440,788509631,FR
+788509632,788509695,AT
788509696,788509951,FR
788509952,788510719,AT
788510720,788512767,ES
@@ -6042,8 +6621,12 @@
839095808,839096063,CA
839096064,839101695,US
839101696,839102207,CA
-839102208,839112447,US
-839112448,839112703,CA
+839102208,839103231,US
+839103232,839103487,CA
+839103488,839104255,US
+839104256,839104511,CA
+839104512,839112191,US
+839112192,839112703,CA
839112704,839113215,US
839113216,839113471,CA
839113472,840269823,US
@@ -6079,13 +6662,21 @@
842542408,842542415,US
842542416,842542423,NZ
842542424,842542431,JO
-842542432,843055103,US
+842542432,842565975,US
+842565976,842565979,AU
+842565980,842566015,US
+842566016,842566019,BR
+842566020,842597639,US
+842597640,842597647,GT
+842597648,842598703,US
+842598704,842598719,CZ
+842598720,843055103,US
843055104,843644927,CA
843644928,844890111,US
844890112,844988415,CA
844988416,845283327,US
845283328,845545471,CA
-845545472,846462975,US
+845545472,846725119,US
847249408,855638015,US
855638016,872415231,GB
872415232,889192447,US
@@ -6624,7 +7215,9 @@
1040471488,1040471519,NL
1040471520,1040472575,EU
1040472576,1040472831,DE
-1040472832,1040474111,EU
+1040472832,1040473071,EU
+1040473072,1040473087,DE
+1040473088,1040474111,EU
1040474112,1040482303,CZ
1040482304,1040515071,BE
1040515072,1040547839,GB
@@ -6740,8 +7333,8 @@
1041701720,1041701727,GB
1041701728,1041701863,FR
1041701864,1041701871,GB
-1041701872,1041701903,FR
-1041701904,1041701919,GB
+1041701872,1041701911,FR
+1041701912,1041701919,GB
1041701920,1041701967,FR
1041701968,1041701975,GB
1041701976,1041702167,FR
@@ -6766,9 +7359,13 @@
1041704160,1041704175,GB
1041704176,1041704207,FR
1041704208,1041704215,GB
-1041704216,1041704255,FR
-1041704256,1041704263,GB
-1041704264,1041704407,FR
+1041704216,1041704247,FR
+1041704248,1041704263,GB
+1041704264,1041704319,FR
+1041704320,1041704335,GB
+1041704336,1041704351,FR
+1041704352,1041704383,GB
+1041704384,1041704407,FR
1041704408,1041704431,GB
1041704432,1041704439,FR
1041704440,1041704455,GB
@@ -6966,9 +7563,7 @@
1041714512,1041714519,GB
1041714520,1041714655,FR
1041714656,1041714687,GB
-1041714688,1041714775,FR
-1041714776,1041714783,GB
-1041714784,1041714815,FR
+1041714688,1041714815,FR
1041714816,1041714847,GB
1041714848,1041714855,FR
1041714856,1041714879,GB
@@ -6992,7 +7587,9 @@
1041715584,1041715615,GB
1041715616,1041715631,FR
1041715632,1041715647,GB
-1041715648,1041715767,FR
+1041715648,1041715727,FR
+1041715728,1041715735,GB
+1041715736,1041715767,FR
1041715768,1041715791,GB
1041715792,1041715807,FR
1041715808,1041715823,GB
@@ -7136,9 +7733,7 @@
1041722704,1041722711,GB
1041722712,1041722743,FR
1041722744,1041722751,GB
-1041722752,1041722951,FR
-1041722952,1041722959,GB
-1041722960,1041722983,FR
+1041722752,1041722983,FR
1041722984,1041723007,GB
1041723008,1041723047,FR
1041723048,1041723135,GB
@@ -7423,8 +8018,8 @@
1041741064,1041741087,GB
1041741088,1041741135,FR
1041741136,1041741151,GB
-1041741152,1041741239,FR
-1041741240,1041741263,GB
+1041741152,1041741231,FR
+1041741232,1041741263,GB
1041741264,1041741279,FR
1041741280,1041741295,GB
1041741296,1041741567,FR
@@ -7485,7 +8080,9 @@
1041743832,1041743847,GB
1041743848,1041743863,FR
1041743864,1041743871,GB
-1041743872,1041744287,FR
+1041743872,1041744263,FR
+1041744264,1041744271,GB
+1041744272,1041744287,FR
1041744288,1041744295,GB
1041744296,1041744311,FR
1041744312,1041744327,GB
@@ -7832,7 +8429,8 @@
1042892976,1042892983,CH
1042892984,1042892991,NL
1042892992,1042893007,FR
-1042893008,1042893055,NL
+1042893008,1042893039,NL
+1042893040,1042893055,DE
1042893056,1042893087,GB
1042893088,1042893135,NL
1042893136,1042893143,DE
@@ -7864,7 +8462,9 @@
1042896128,1042896255,GB
1042896256,1042900479,NL
1042900480,1042900735,GB
-1042900736,1042939903,NL
+1042900736,1042915375,NL
+1042915376,1042915391,DE
+1042915392,1042939903,NL
1042939904,1043070975,ES
1043070976,1043079167,CZ
1043079168,1043087359,DE
@@ -7883,7 +8483,9 @@
1043356032,1043357695,DE
1043357696,1043365887,CH
1043365888,1043398655,PT
-1043398656,1043464311,GB
+1043398656,1043464191,GB
+1043464192,1043464255,NL
+1043464256,1043464311,GB
1043464312,1043464351,NL
1043464352,1043464383,GB
1043464384,1043464799,NL
@@ -8038,8 +8640,8 @@
1043477504,1043477759,GB
1043477760,1043478179,DE
1043478180,1043478271,GB
-1043478272,1043478511,DE
-1043478512,1043478527,GB
+1043478272,1043478287,DE
+1043478288,1043478527,GB
1043478528,1043478623,DE
1043478624,1043478639,GB
1043478640,1043478655,DE
@@ -8257,7 +8859,9 @@
1043898624,1043898751,TZ
1043898752,1043899391,A2
1043899392,1043899647,CG
-1043899648,1043910143,A2
+1043899648,1043907071,A2
+1043907072,1043907327,NG
+1043907328,1043910143,A2
1043910144,1043910399,TZ
1043910400,1043912703,A2
1043912704,1043913215,ZM
@@ -8626,7 +9230,9 @@
1044592656,1044592671,GB
1044592672,1044592703,DE
1044592704,1044592831,GB
-1044592832,1044594431,DE
+1044592832,1044593151,DE
+1044593152,1044593663,GB
+1044593664,1044594431,DE
1044594432,1044625407,GB
1044625408,1044625463,DE
1044625464,1044625471,GB
@@ -8634,24 +9240,23 @@
1044625536,1044625663,GB
1044625664,1044625679,DE
1044625680,1044627455,GB
-1044627456,1044628479,DE
-1044628480,1044629503,GB
+1044627456,1044628223,DE
+1044628224,1044629503,GB
1044629504,1044629759,DE
1044629760,1044631551,GB
1044631552,1044631903,DE
1044631904,1044631951,GB
1044631952,1044631967,DE
1044631968,1044632063,GB
-1044632064,1044633855,DE
-1044633856,1044634111,GB
-1044634112,1044634367,DE
-1044634368,1044634623,GB
+1044632064,1044633087,DE
+1044633088,1044633343,GB
+1044633344,1044633855,DE
+1044633856,1044634623,GB
1044634624,1044634879,DE
-1044634880,1044635135,GB
-1044635136,1044635391,DE
-1044635392,1044635647,GB
+1044634880,1044635647,GB
1044635648,1044636159,US
-1044636160,1044638207,DE
+1044636160,1044636415,GB
+1044636416,1044638207,DE
1044638208,1044638223,GB
1044638224,1044638239,DE
1044638240,1044638463,GB
@@ -8847,7 +9452,9 @@
1044933864,1044933871,GB
1044933872,1044933919,BE
1044933920,1044933935,GB
-1044933936,1044934191,BE
+1044933936,1044934111,BE
+1044934112,1044934119,GB
+1044934120,1044934191,BE
1044934192,1044934199,GB
1044934200,1044934239,BE
1044934240,1044934247,GB
@@ -8892,8 +9499,8 @@
1044935752,1044935839,BE
1044935840,1044935847,GB
1044935848,1044935851,BE
-1044935852,1044935863,GB
-1044935864,1044935879,BE
+1044935852,1044935871,GB
+1044935872,1044935879,BE
1044935880,1044935887,GB
1044935888,1044935903,BE
1044935904,1044936095,GB
@@ -8917,7 +9524,9 @@
1044936496,1044936503,GB
1044936504,1044936711,BE
1044936712,1044936719,GB
-1044936720,1044937183,BE
+1044936720,1044936847,BE
+1044936848,1044936863,GB
+1044936864,1044937183,BE
1044937184,1044937187,GB
1044937188,1044937287,BE
1044937288,1044937311,GB
@@ -9015,8 +9624,7 @@
1045160960,1045160991,TR
1045160992,1045161023,DE
1045161024,1045161055,AT
-1045161056,1045161087,US
-1045161088,1045161119,DE
+1045161056,1045161119,DE
1045161120,1045161151,SC
1045161152,1045168127,DE
1045168128,1045233663,RU
@@ -9121,8 +9729,8 @@
1045743232,1045743251,GB
1045743252,1045743263,SE
1045743264,1045743299,GB
-1045743300,1045743647,SE
-1045743648,1045743871,GB
+1045743300,1045743623,SE
+1045743624,1045743871,GB
1045743872,1045744007,SE
1045744008,1045744015,GB
1045744016,1045744031,SE
@@ -9332,8 +9940,8 @@
1046485496,1046485503,GB
1046485504,1046486055,DE
1046486056,1046486063,GB
-1046486064,1046486159,DE
-1046486160,1046486175,GB
+1046486064,1046486151,DE
+1046486152,1046486175,GB
1046486176,1046486183,DE
1046486184,1046486191,GB
1046486192,1046486375,DE
@@ -9363,7 +9971,9 @@
1046493088,1046493095,DE
1046493096,1046493103,GB
1046493104,1046493391,DE
-1046493392,1046493471,GB
+1046493392,1046493399,GB
+1046493400,1046493407,DE
+1046493408,1046493471,GB
1046493472,1046493487,DE
1046493488,1046493511,GB
1046493512,1046493519,DE
@@ -9620,7 +10230,9 @@
1046544384,1046560767,IT
1046560768,1046570591,ES
1046570592,1046570607,CH
-1046570608,1046572007,ES
+1046570608,1046571815,ES
+1046571816,1046571823,FR
+1046571824,1046572007,ES
1046572008,1046572015,DK
1046572016,1046585343,ES
1046585344,1046609919,NO
@@ -9774,7 +10386,9 @@
1047340800,1047341055,NO
1047341056,1047343871,SE
1047343872,1047344127,NO
-1047344128,1047346431,SE
+1047344128,1047346351,SE
+1047346352,1047346359,FI
+1047346360,1047346431,SE
1047346432,1047346687,FI
1047346688,1047347199,SE
1047347200,1047363583,DE
@@ -10040,7 +10654,11 @@
1048604688,1048604751,UA
1048604752,1048604759,EE
1048604760,1048604927,UA
-1048604928,1048605079,LT
+1048604928,1048604945,LT
+1048604946,1048604947,UA
+1048604948,1048604991,LT
+1048604992,1048605055,UA
+1048605056,1048605079,LT
1048605080,1048605087,UA
1048605088,1048605095,LT
1048605096,1048605103,UA
@@ -12501,9 +13119,7 @@
1053312912,1053312927,EU
1053312928,1053312959,DK
1053312960,1053313023,EU
-1053313024,1053313343,GB
-1053313344,1053313407,EU
-1053313408,1053313471,GB
+1053313024,1053313471,GB
1053313472,1053313479,EU
1053313480,1053313671,GB
1053313672,1053313679,EU
@@ -12532,7 +13148,9 @@
1053319168,1053320191,DE
1053320192,1053320223,EU
1053320224,1053320319,DE
-1053320320,1053326335,EU
+1053320320,1053320447,EU
+1053320448,1053320703,DE
+1053320704,1053326335,EU
1053326336,1053326399,BE
1053326400,1053326431,EU
1053326432,1053326447,GB
@@ -12642,8 +13260,8 @@
1053350360,1053350375,EU
1053350376,1053350391,IE
1053350392,1053350399,EU
-1053350400,1053350479,BE
-1053350480,1053350655,EU
+1053350400,1053350487,BE
+1053350488,1053350655,EU
1053350656,1053350911,BE
1053350912,1053351935,EU
1053351936,1053352191,IL
@@ -12695,6 +13313,7 @@
1053687808,1053702635,DE
1053702636,1053702639,GB
1053702640,1053753343,DE
+1053753344,1053818879,NL
1053818880,1053819391,DE
1053819392,1053819423,EU
1053819424,1053819439,DE
@@ -12966,9 +13585,7 @@
1054943232,1054943487,PL
1054943488,1054949807,DE
1054949808,1054949815,ES
-1054949816,1054963255,DE
-1054963256,1054963263,ES
-1054963264,1054969031,DE
+1054949816,1054969031,DE
1054969032,1054969039,AT
1054969040,1054978815,DE
1054978816,1054979071,FR
@@ -13387,7 +14004,8 @@
1065519360,1065519487,CA
1065519488,1065520895,US
1065520896,1065520911,CA
-1065520912,1065583423,US
+1065520912,1065520927,IT
+1065520928,1065583423,US
1065583424,1065583439,HK
1065583440,1065611263,US
1065611264,1065615359,PR
@@ -14132,7 +14750,9 @@
1075601280,1075601295,CA
1075601296,1075609599,US
1075609600,1075613695,TT
-1075613696,1075744767,US
+1075613696,1075744511,US
+1075744512,1075744639,NL
+1075744640,1075744767,US
1075744768,1075748863,A2
1075748864,1075855359,US
1075855360,1075871743,DO
@@ -16276,8 +16896,8 @@
1078285664,1078285695,CA
1078285696,1078285703,MX
1078285704,1078285711,US
-1078285712,1078285919,CA
-1078285920,1078285943,US
+1078285712,1078285935,CA
+1078285936,1078285943,US
1078285944,1078285951,CA
1078285952,1078286015,US
1078286016,1078286047,CA
@@ -16772,18 +17392,24 @@
1079410944,1079411199,CA
1079411200,1079411455,US
1079411456,1079411711,PK
-1079411712,1079413311,CA
+1079411712,1079412735,CA
+1079412736,1079413247,US
+1079413248,1079413311,CA
1079413312,1079413343,US
1079413344,1079413535,CA
1079413536,1079413567,US
-1079413568,1079414783,CA
+1079413568,1079414271,CA
+1079414272,1079414527,US
+1079414528,1079414783,CA
1079414784,1079415039,US
1079415040,1079415295,HN
1079415296,1079415807,CA
1079415808,1079416319,US
1079416320,1079421951,CA
1079421952,1079422207,US
-1079422208,1079425023,CA
+1079422208,1079422239,CA
+1079422240,1079422271,US
+1079422272,1079425023,CA
1079425024,1079425279,US
1079425280,1079425535,CA
1079425536,1079425551,US
@@ -17306,13 +17932,26 @@
1081612016,1081612023,IN
1081612024,1081612159,US
1081612160,1081612191,IN
-1081612192,1081612663,US
+1081612192,1081612655,US
+1081612656,1081612663,CA
1081612664,1081612671,IN
-1081612672,1081616831,US
+1081612672,1081613351,US
+1081613352,1081613359,CA
+1081613360,1081613399,US
+1081613400,1081613407,CA
+1081613408,1081613447,US
+1081613448,1081613455,CA
+1081613456,1081613543,US
+1081613544,1081613551,CA
+1081613552,1081616831,US
1081616832,1081616839,GB
1081616840,1081618951,US
1081618952,1081618959,GB
-1081618960,1081803287,US
+1081618960,1081619775,US
+1081619776,1081619791,CA
+1081619792,1081625775,US
+1081625776,1081625783,CA
+1081625784,1081803287,US
1081803288,1081803295,PR
1081803296,1081803895,US
1081803896,1081803903,PR
@@ -20648,8 +21287,7 @@
1118476896,1118477535,CA
1118477536,1118477543,US
1118477544,1118478335,CA
-1118478336,1118502911,US
-1118507008,1118511103,US
+1118478336,1118511103,US
1118511104,1118519295,CA
1118519296,1118527487,US
1118527488,1118531583,CA
@@ -20698,7 +21336,7 @@
1118795808,1118795895,US
1118795896,1118795903,CY
1118795904,1118796543,US
-1118796544,1118796799,CY
+1118796544,1118796799,GB
1118796800,1118797063,US
1118797064,1118797071,CR
1118797072,1118961663,US
@@ -21584,7 +22222,7 @@
1120911360,1120914415,CA
1120914416,1120914431,AT
1120914432,1120918623,CA
-1120918624,1120918639,US
+1120918624,1120918639,NA
1120918640,1120919551,CA
1120919552,1121005567,US
1121005568,1121009663,CA
@@ -22222,7 +22860,9 @@
1123584384,1123588063,US
1123588064,1123588095,CY
1123588096,1123588351,DE
-1123588352,1123590143,US
+1123588352,1123589631,US
+1123589632,1123589887,DE
+1123589888,1123590143,US
1123590144,1123598335,VI
1123598336,1123651583,US
1123651584,1123655679,JM
@@ -22591,7 +23231,9 @@
1125623296,1125623551,IN
1125623552,1125628671,US
1125628672,1125628703,NZ
-1125628704,1125642674,US
+1125628704,1125642301,US
+1125642302,1125642303,IN
+1125642304,1125642674,US
1125642675,1125642694,BO
1125642695,1126009343,US
1126009344,1126009599,AR
@@ -23475,8 +24117,8 @@
1137376464,1137376479,US
1137376480,1137376511,CA
1137376512,1137376639,US
-1137376640,1137376671,CA
-1137376672,1137377311,US
+1137376640,1137376703,CA
+1137376704,1137377311,US
1137377312,1137377327,DE
1137377328,1137383455,US
1137383456,1137383471,DE
@@ -23489,7 +24131,9 @@
1137524736,1137541119,CA
1137541120,1137623039,US
1137623040,1137639423,PR
-1137639424,1137704967,US
+1137639424,1137692671,US
+1137692672,1137696767,A1
+1137696768,1137704967,US
1137704968,1137705287,CA
1137705288,1137705295,US
1137705296,1137705383,CA
@@ -23908,9 +24552,7 @@
1138417696,1138417727,DE
1138417728,1138421759,US
1138421760,1138421791,DE
-1138421792,1138422783,US
-1138422784,1138423039,PA
-1138423040,1138425855,US
+1138421792,1138425855,US
1138425856,1138427519,KN
1138427520,1138427647,US
1138427648,1138429951,KN
@@ -24020,7 +24662,11 @@
1138655459,1138655486,CA
1138655487,1138655503,US
1138655504,1138655521,MX
-1138655522,1138655609,US
+1138655522,1138655581,US
+1138655582,1138655583,MX
+1138655584,1138655587,US
+1138655588,1138655589,MX
+1138655590,1138655609,US
1138655610,1138655617,MX
1138655618,1138655629,US
1138655630,1138655637,EG
@@ -24082,7 +24728,9 @@
1138658498,1138658525,PK
1138658526,1138659081,US
1138659082,1138659207,ES
-1138659208,1138659369,US
+1138659208,1138659307,US
+1138659308,1138659315,EG
+1138659316,1138659369,US
1138659370,1138659401,GB
1138659402,1138659465,US
1138659466,1138659497,GB
@@ -24097,7 +24745,8 @@
1138659706,1138659713,CA
1138659714,1138659723,US
1138659724,1138659731,ID
-1138659732,1138659789,US
+1138659732,1138659781,US
+1138659782,1138659789,NZ
1138659790,1138659797,ID
1138659798,1138659805,US
1138659806,1138659813,ID
@@ -24285,7 +24934,7 @@
1139195136,1139195391,GB
1139195392,1139195775,US
1139195776,1139195903,CA
-1139195904,1139261439,US
+1139195904,1139265535,US
1139265536,1139269631,CA
1139269632,1142187775,US
1142187776,1142187783,PR
@@ -24359,7 +25008,9 @@
1145413632,1145421823,US
1145421824,1145430015,CA
1145430016,1145475071,US
-1145475072,1145479167,CA
+1145475072,1145476887,CA
+1145476888,1145476895,US
+1145476896,1145479167,CA
1145479168,1145483583,US
1145483584,1145483591,VG
1145483592,1145484031,US
@@ -25085,8 +25736,8 @@
1159262728,1159262731,DE
1159262732,1159262735,RU
1159262736,1159262743,US
-1159262744,1159262747,RU
-1159262748,1159266935,US
+1159262744,1159262751,RU
+1159262752,1159266935,US
1159266936,1159266943,PR
1159266944,1159269119,US
1159269120,1159269375,AR
@@ -25308,7 +25959,9 @@
1160017160,1160019967,CA
1160019968,1160364031,US
1160364032,1160368127,CA
-1160368128,1160397007,US
+1160368128,1160393727,US
+1160393728,1160396799,CA
+1160396800,1160397007,US
1160397008,1160397023,GB
1160397024,1160405631,US
1160405632,1160406015,DO
@@ -25809,9 +26462,13 @@
1161632632,1161632639,GB
1161632640,1161632655,US
1161632656,1161632663,GB
-1161632664,1161632719,US
+1161632664,1161632687,US
+1161632688,1161632703,GB
+1161632704,1161632719,US
1161632720,1161632735,GB
-1161632736,1161633023,US
+1161632736,1161632943,US
+1161632944,1161632959,CA
+1161632960,1161633023,US
1161633024,1161633055,CA
1161633056,1161633215,US
1161633216,1161633231,EE
@@ -25906,8 +26563,7 @@
1161639688,1161639695,KW
1161639696,1161639703,US
1161639704,1161639711,BZ
-1161639712,1161639719,PL
-1161639720,1161639727,US
+1161639712,1161639727,US
1161639728,1161639743,GB
1161639744,1161639831,US
1161639832,1161639839,AR
@@ -26645,18 +27301,8 @@
1163581568,1163581583,CA
1163581584,1163581615,US
1163581616,1163581631,CA
-1163581632,1163581703,US
-1163581704,1163581799,CA
-1163581800,1163581807,US
-1163581808,1163581839,CA
-1163581840,1163581895,US
-1163581896,1163581903,CA
-1163581904,1163581907,US
-1163581908,1163581915,CA
-1163581916,1163581919,US
-1163581920,1163581943,CA
-1163581944,1163581951,US
-1163581952,1163581983,CA
+1163581632,1163581695,US
+1163581696,1163581983,CA
1163581984,1163582015,US
1163582016,1163582111,CA
1163582112,1163582127,US
@@ -26714,10 +27360,14 @@
1167324048,1167324055,CA
1167324056,1167324287,US
1167324288,1167324295,GB
-1167324296,1167325935,US
+1167324296,1167325727,US
+1167325728,1167325735,CA
+1167325736,1167325935,US
1167325936,1167325951,CA
1167325952,1167326207,US
-1167326208,1167326271,IN
+1167326208,1167326231,IN
+1167326232,1167326239,CA
+1167326240,1167326271,IN
1167326272,1167326303,US
1167326304,1167326335,IN
1167326336,1167326367,SI
@@ -26727,7 +27377,9 @@
1167326440,1167326447,IN
1167326448,1167326983,US
1167326984,1167326991,IN
-1167326992,1167327111,US
+1167326992,1167327023,US
+1167327024,1167327031,CA
+1167327032,1167327111,US
1167327112,1167327119,IN
1167327120,1167327207,US
1167327208,1167327215,IN
@@ -26761,7 +27413,9 @@
1168394512,1168394751,CA
1168394752,1168420863,US
1168420864,1168424959,CA
-1168424960,1168474111,US
+1168424960,1168453631,US
+1168453632,1168457727,A1
+1168457728,1168474111,US
1168474112,1168506879,CA
1168508928,1168510975,US
1168510976,1168515071,CA
@@ -27119,10 +27773,8 @@
1176620512,1176620743,CA
1176620744,1176620783,US
1176620784,1176620863,CA
-1176620864,1176620895,US
-1176620896,1176620911,CA
-1176620912,1176620927,US
-1176620928,1176620967,CA
+1176620864,1176620879,US
+1176620880,1176620967,CA
1176620968,1176620975,US
1176620976,1176620991,CA
1176620992,1176620999,US
@@ -27137,7 +27789,11 @@
1176621888,1176622047,CA
1176622048,1176622079,US
1176622080,1176622335,GB
-1176622336,1176622591,US
+1176622336,1176622367,US
+1176622368,1176622431,CA
+1176622432,1176622527,US
+1176622528,1176622559,CA
+1176622560,1176622591,US
1176622592,1176623359,CA
1176623360,1176623487,US
1176623488,1176623567,CA
@@ -31672,8 +32328,8 @@
1296247808,1296247871,US
1296247872,1296247999,FR
1296248000,1296248063,IE
-1296248064,1296248127,FR
-1296248128,1296248255,IE
+1296248064,1296248191,FR
+1296248192,1296248255,IE
1296248256,1296248318,BE
1296248319,1296248319,FR
1296248320,1296248383,BE
@@ -31707,7 +32363,8 @@
1296251360,1296251391,DE
1296251392,1296251775,NL
1296251776,1296251903,DE
-1296251904,1296251935,FR
+1296251904,1296251919,IR
+1296251920,1296251935,BE
1296251936,1296251967,US
1296251968,1296252015,NL
1296252016,1296252039,US
@@ -32004,7 +32661,7 @@
1296754688,1296756735,DE
1296756736,1296758783,FR
1296758784,1296760831,RS
-1296762880,1296764927,RU
+1296760832,1296764927,RU
1296764928,1296769023,AT
1296769024,1296771071,TR
1296771072,1296773119,LT
@@ -32195,7 +32852,6 @@
1298110464,1298112511,ES
1298112512,1298114559,IE
1298114560,1298116607,IT
-1298116608,1298118655,RU
1298118656,1298120703,AM
1298120704,1298122751,CZ
1298122752,1298124799,RU
@@ -32203,6 +32859,7 @@
1298126848,1298127615,SA
1298127616,1298128127,IR
1298128128,1298128895,SA
+1298128896,1298130943,NL
1298130944,1298132991,BG
1298132992,1298135039,FI
1298135040,1298137087,NL
@@ -32612,7 +33269,7 @@
1308086272,1308088319,RU
1308088320,1308090367,UA
1308090368,1308092415,SK
-1308092416,1308094463,RU
+1308092416,1308096511,RU
1308096512,1308098559,RS
1308098560,1308360703,NL
1308360704,1308622847,PL
@@ -32822,7 +33479,7 @@
1310257152,1310259199,FR
1310259200,1310261247,GB
1310261248,1310277631,UA
-1310294016,1310310399,RU
+1310277632,1310310399,RU
1310310400,1310326783,GB
1310326784,1310343167,NO
1310343168,1310359551,IT
@@ -32888,8 +33545,8 @@
1311263616,1311263679,FR
1311263680,1311263871,CH
1311263872,1311263999,FR
-1311264000,1311264095,CH
-1311264096,1311264767,FR
+1311264000,1311264111,CH
+1311264112,1311264767,FR
1311264768,1311266815,RU
1311266816,1311268863,FR
1311268864,1311270911,BE
@@ -33154,6 +33811,8 @@
1315774424,1315774431,NA
1315774432,1315774463,UA
1315774464,1315778559,RU
+1315778560,1315780607,AZ
+1315780608,1315782655,DE
1315782656,1315786751,AM
1315786752,1315790592,FR
1315790593,1315790593,IT
@@ -33219,19 +33878,21 @@
1317115136,1317115391,IE
1317115392,1317118207,GB
1317118208,1317118463,IN
-1317118464,1317119103,GB
-1317119104,1317119167,IT
-1317119168,1317126399,GB
+1317118464,1317126399,GB
1317126400,1317126655,US
1317126656,1317129279,GB
1317129280,1317129343,CA
1317129344,1317129471,GB
1317129472,1317129727,IT
-1317129728,1317135615,GB
+1317129728,1317133055,GB
+1317133056,1317133183,LV
+1317133184,1317135615,GB
1317135616,1317135871,DE
1317135872,1317136895,GB
1317136896,1317137151,EE
-1317137152,1317137663,GB
+1317137152,1317137183,GB
+1317137184,1317137215,CH
+1317137216,1317137663,GB
1317137664,1317137919,SE
1317137920,1317140095,GB
1317140096,1317140223,US
@@ -33289,6 +33950,7 @@
1317650096,1317650135,IE
1317650136,1317650143,GB
1317650144,1317650431,IE
+1317650432,1317666815,PT
1317666816,1317666823,IQ
1317666824,1317666831,CD
1317666832,1317666839,A2
@@ -33330,8 +33992,7 @@
1317667352,1317667359,AO
1317667360,1317667367,A2
1317667368,1317667375,NG
-1317667376,1317667407,A2
-1317667408,1317667423,NG
+1317667376,1317667423,A2
1317667424,1317667431,TD
1317667432,1317667439,GH
1317667440,1317667455,A2
@@ -33459,7 +34120,7 @@
1317670480,1317670511,A2
1317670512,1317670519,CI
1317670520,1317670543,NG
-1317670544,1317670551,IQ
+1317670544,1317670551,A2
1317670552,1317670559,UG
1317670560,1317670567,NG
1317670568,1317670575,A2
@@ -33491,15 +34152,17 @@
1317670864,1317670879,A2
1317670880,1317670887,NG
1317670888,1317670896,A2
-1317670897,1317670911,NG
-1317670912,1317671175,A2
+1317670897,1317670903,NG
+1317670904,1317671175,A2
1317671176,1317671191,NG
1317671192,1317671239,A2
1317671240,1317671247,CI
1317671248,1317671255,A2
1317671256,1317671263,CI
1317671264,1317671279,A2
-1317671280,1317671303,NG
+1317671280,1317671287,NG
+1317671288,1317671295,A2
+1317671296,1317671303,NG
1317671304,1317671319,A2
1317671320,1317671327,NG
1317671328,1317671335,A2
@@ -33517,8 +34180,8 @@
1317671448,1317671487,NG
1317671488,1317671527,A2
1317671528,1317671535,NG
-1317671536,1317671543,A2
-1317671544,1317671551,GH
+1317671536,1317671543,LR
+1317671544,1317671551,A2
1317671552,1317671567,NG
1317671568,1317671583,A2
1317671584,1317671591,NG
@@ -33530,9 +34193,7 @@
1317671680,1317671687,LR
1317671688,1317671719,A2
1317671720,1317671727,NG
-1317671728,1317671759,A2
-1317671760,1317671767,IQ
-1317671768,1317671783,A2
+1317671728,1317671783,A2
1317671784,1317671807,NG
1317671808,1317671823,CI
1317671824,1317671831,NG
@@ -33570,8 +34231,7 @@
1317672760,1317672767,NG
1317672768,1317672815,A2
1317672816,1317672823,BW
-1317672824,1317672831,NG
-1317672832,1317672839,A2
+1317672824,1317672839,A2
1317672840,1317672847,NG
1317672848,1317672863,A2
1317672864,1317672871,NG
@@ -33582,7 +34242,9 @@
1317672936,1317672943,NG
1317672944,1317672951,UG
1317672952,1317672959,A2
-1317672960,1317673247,NG
+1317672960,1317673231,NG
+1317673232,1317673239,A2
+1317673240,1317673247,NG
1317673248,1317673263,A2
1317673264,1317673271,UG
1317673272,1317673279,A2
@@ -33606,8 +34268,8 @@
1317673496,1317673527,NG
1317673528,1317673535,A2
1317673536,1317673551,ZW
-1317673552,1317673559,A2
-1317673560,1317673575,NG
+1317673552,1317673567,A2
+1317673568,1317673575,NG
1317673576,1317673583,CD
1317673584,1317673607,A2
1317673608,1317673615,NG
@@ -33697,9 +34359,7 @@
1317674952,1317674959,NG
1317674960,1317674967,GH
1317674968,1317674983,NG
-1317674984,1317674999,A2
-1317675000,1317675007,NG
-1317675008,1317675031,A2
+1317674984,1317675031,A2
1317675032,1317675039,NG
1317675040,1317675055,A2
1317675056,1317675063,NG
@@ -33716,9 +34376,7 @@
1317675320,1317675351,A2
1317675352,1317675359,IQ
1317675360,1317675367,NG
-1317675368,1317675407,A2
-1317675408,1317675415,NG
-1317675416,1317675423,A2
+1317675368,1317675423,A2
1317675424,1317675439,NG
1317675440,1317675447,A2
1317675448,1317675455,NG
@@ -33772,7 +34430,7 @@
1317675976,1317675983,A2
1317675984,1317675991,ML
1317675992,1317675999,NG
-1317676000,1317676007,GN
+1317676000,1317676007,A2
1317676008,1317676015,GH
1317676016,1317676023,SD
1317676024,1317676031,GQ
@@ -33780,7 +34438,7 @@
1317676040,1317676055,A2
1317676056,1317676063,NG
1317676064,1317676071,GH
-1317676072,1317676079,A2
+1317676072,1317676079,NG
1317676080,1317676087,AO
1317676088,1317676095,NG
1317676096,1317676103,CM
@@ -33805,7 +34463,7 @@
1317676272,1317676279,A2
1317676280,1317676287,NG
1317676288,1317676543,LR
-1317676544,1317676551,A2
+1317676544,1317676551,NG
1317676552,1317676559,AO
1317676560,1317676567,NG
1317676568,1317676575,LR
@@ -33836,7 +34494,9 @@
1317676864,1317676871,TG
1317676872,1317676879,NG
1317676880,1317676903,A2
-1317676904,1317676927,NG
+1317676904,1317676911,NG
+1317676912,1317676919,A2
+1317676920,1317676927,NG
1317676928,1317676943,A2
1317676944,1317676951,CM
1317676952,1317676983,A2
@@ -33857,13 +34517,13 @@
1317677128,1317677135,NG
1317677136,1317677191,A2
1317677192,1317677199,SD
-1317677200,1317677207,A2
-1317677208,1317677215,NG
+1317677200,1317677215,NG
1317677216,1317677231,A2
1317677232,1317677239,UG
1317677240,1317677247,A2
1317677248,1317677271,NG
-1317677272,1317677303,A2
+1317677272,1317677279,FR
+1317677280,1317677303,A2
1317677304,1317677311,NG
1317677312,1317677319,CD
1317677320,1317677327,AO
@@ -33947,8 +34607,8 @@
1317678464,1317678479,A2
1317678480,1317678487,CD
1317678488,1317678495,ML
-1317678496,1317678543,A2
-1317678544,1317678551,CD
+1317678496,1317678535,A2
+1317678536,1317678551,CD
1317678552,1317678559,ML
1317678560,1317678567,NG
1317678568,1317678575,CD
@@ -33964,7 +34624,8 @@
1317679672,1317679687,NG
1317679688,1317679695,A2
1317679696,1317679703,LU
-1317679704,1317679727,NG
+1317679704,1317679719,NG
+1317679720,1317679727,A2
1317679728,1317679735,GN
1317679736,1317679743,NG
1317679744,1317679751,AO
@@ -33975,11 +34636,13 @@
1317679816,1317679831,NG
1317679832,1317679839,A2
1317679840,1317679847,NG
-1317679848,1317679855,A2
-1317679856,1317679863,NG
-1317679864,1317681183,A2
-1317681184,1317681191,NG
-1317681192,1317683199,A2
+1317679848,1317679863,A2
+1317679864,1317679871,NG
+1317679872,1317681175,A2
+1317681176,1317681191,NG
+1317681192,1317681279,A2
+1317681280,1317681287,NG
+1317681288,1317683199,A2
1317683200,1317683839,DE
1317683840,1317683855,CH
1317683856,1317683863,DE
@@ -34064,7 +34727,10 @@
1317928960,1317945343,BG
1317945344,1317965047,AT
1317965048,1317965055,DE
-1317965056,1317978111,AT
+1317965056,1317977407,AT
+1317977408,1317977415,MT
+1317977416,1317978111,AT
+1317978112,1317994495,RU
1317994496,1317995519,NL
1317995520,1317996095,DE
1317996096,1317996287,NL
@@ -34074,7 +34740,9 @@
1318000384,1318000447,NL
1318000448,1318002175,DE
1318002176,1318002431,NL
-1318002432,1318005631,DE
+1318002432,1318003711,DE
+1318003712,1318003967,NL
+1318003968,1318005631,DE
1318005632,1318005759,NL
1318005760,1318006271,DE
1318006272,1318006783,NL
@@ -34122,16 +34790,14 @@
1318708624,1318708627,GB
1318708628,1318708639,FR
1318708640,1318708647,GB
-1318708648,1318708723,FR
-1318708724,1318708727,GB
-1318708728,1318708735,FR
+1318708648,1318708735,FR
1318708736,1318708991,GB
1318708992,1318711647,FR
1318711648,1318711663,IT
-1318711664,1318712975,FR
-1318712976,1318712991,GB
+1318711664,1318712983,FR
+1318712984,1318712991,GB
1318712992,1318713855,FR
-1318713856,1318714111,CH
+1318713856,1318714111,GB
1318714112,1318715390,FR
1318715391,1318715391,GB
1318715392,1318723583,BG
@@ -34232,7 +34898,6 @@
1331832832,1331834879,IT
1331834880,1331836927,BY
1331836928,1331838975,FR
-1331838976,1331841023,GR
1331841024,1331843071,CZ
1331843072,1331845119,GB
1331845120,1331847167,RU
@@ -34282,9 +34947,10 @@
1331937280,1331937407,PL
1331937408,1331937471,GB
1331937472,1331937519,NG
-1331937520,1331937535,GB
+1331937520,1331937535,LB
1331937536,1331937567,SM
-1331937568,1331937583,US
+1331937568,1331937575,NG
+1331937576,1331937583,GB
1331937584,1331937599,ZA
1331937600,1331937663,GB
1331937664,1331937727,DE
@@ -34298,7 +34964,9 @@
1331938168,1331938175,KW
1331938176,1331938191,GB
1331938192,1331938207,AE
-1331938208,1331938319,GB
+1331938208,1331938271,GB
+1331938272,1331938303,QA
+1331938304,1331938319,GB
1331938320,1331938335,AE
1331938336,1331938375,GB
1331938376,1331938383,AE
@@ -34314,12 +34982,11 @@
1331938912,1331938927,NG
1331938928,1331938935,RU
1331938936,1331938943,NG
-1331938944,1331938958,US
-1331938959,1331938959,GB
-1331938960,1331938967,US
+1331938944,1331938967,US
1331938968,1331938983,GB
1331938984,1331938999,NG
-1331939000,1331939327,GB
+1331939000,1331939007,QA
+1331939008,1331939327,GB
1331939328,1331941375,BE
1331941376,1331943423,ES
1331943424,1331945471,RU
@@ -34513,7 +35180,9 @@
1334726144,1334726655,NL
1334726656,1334729983,RU
1334729984,1334730027,KZ
-1334730028,1334730239,RU
+1334730028,1334730031,RU
+1334730032,1334730043,KZ
+1334730044,1334730239,RU
1334730240,1334730431,KZ
1334730432,1334730439,RU
1334730440,1334730443,KZ
@@ -34598,6 +35267,7 @@
1336614912,1336616959,GB
1336616960,1336619007,ES
1336619008,1336621055,AL
+1336621056,1336623103,DE
1336623104,1336625151,BE
1336625152,1336625823,IE
1336625824,1336625839,GB
@@ -34644,7 +35314,9 @@
1336852480,1336868863,FR
1336868864,1336885247,RU
1336885248,1336901631,RS
-1336901632,1336911103,IR
+1336901632,1336910528,IR
+1336910529,1336910560,SE
+1336910561,1336911103,IR
1336911104,1336911359,SE
1336911360,1336911749,IR
1336911750,1336911759,AE
@@ -34765,7 +35437,9 @@
1346500640,1346500735,IM
1346500736,1346500767,GB
1346500768,1346500863,IM
-1346500864,1346501231,GB
+1346500864,1346501135,GB
+1346501136,1346501151,IM
+1346501152,1346501231,GB
1346501232,1346501247,IM
1346501248,1346501343,GB
1346501344,1346501375,IM
@@ -34867,7 +35541,11 @@
1346703484,1346703487,US
1346703488,1346703503,GB
1346703504,1346703511,US
-1346703512,1346703871,GB
+1346703512,1346703567,GB
+1346703568,1346703571,US
+1346703572,1346703603,GB
+1346703604,1346703607,US
+1346703608,1346703871,GB
1346703872,1346704127,LI
1346704128,1346704383,GB
1346704384,1346704447,US
@@ -34989,7 +35667,6 @@
1347117056,1347121151,FI
1347121152,1347125247,CH
1347125248,1347129343,RU
-1347129344,1347133439,GB
1347133440,1347141631,EG
1347141632,1347145727,CH
1347145728,1347146239,GB
@@ -35074,7 +35751,9 @@
1347250784,1347252223,SE
1347252224,1347255903,HU
1347255904,1347255919,SC
-1347255920,1347256319,HU
+1347255920,1347256271,HU
+1347256272,1347256287,SC
+1347256288,1347256319,HU
1347256320,1347260415,FO
1347260416,1347264511,MK
1347264512,1347268607,RU
@@ -35082,7 +35761,9 @@
1347272704,1347276799,MT
1347276800,1347278831,DE
1347278832,1347278847,BR
-1347278848,1347280895,DE
+1347278848,1347280543,DE
+1347280544,1347280575,MY
+1347280576,1347280895,DE
1347280896,1347284991,FR
1347284992,1347286271,GB
1347286272,1347286335,BN
@@ -35190,17 +35871,7 @@
1347379200,1347383295,NL
1347383296,1347384111,EE
1347384112,1347384115,FI
-1347384116,1347384703,EE
-1347384704,1347384831,US
-1347384832,1347385063,EE
-1347385064,1347385071,RU
-1347385072,1347385599,EE
-1347385600,1347385855,US
-1347385856,1347386559,EE
-1347386560,1347386567,RU
-1347386568,1347386655,EE
-1347386656,1347386671,US
-1347386672,1347386751,EE
+1347384116,1347386751,EE
1347386752,1347386815,MY
1347386816,1347387011,EE
1347387012,1347387015,DE
@@ -35223,7 +35894,9 @@
1347420792,1347420799,US
1347420800,1347420831,DK
1347420832,1347420847,US
-1347420848,1347420991,DK
+1347420848,1347420887,DK
+1347420888,1347420895,PT
+1347420896,1347420991,DK
1347420992,1347421007,CH
1347421008,1347423775,DK
1347423776,1347423807,NO
@@ -35366,9 +36039,7 @@
1347756032,1347760127,NL
1347760128,1347764223,HU
1347764224,1347772415,GB
-1347772416,1347775953,MT
-1347775954,1347775954,GB
-1347775955,1347776511,MT
+1347772416,1347776511,MT
1347776512,1347780607,SE
1347780608,1347784703,NL
1347784704,1347788799,RU
@@ -35879,8 +36550,8 @@
1353268224,1353268479,GB
1353268480,1353268599,BE
1353268600,1353268607,GB
-1353268608,1353269247,BE
-1353269248,1353270527,GB
+1353268608,1353269215,BE
+1353269216,1353270527,GB
1353270528,1353270783,IE
1353270784,1353271295,GB
1353271296,1353271423,IE
@@ -35892,8 +36563,8 @@
1353272040,1353272047,GB
1353272048,1353272055,ES
1353272056,1353272063,GB
-1353272064,1353272191,ES
-1353272192,1353272207,GB
+1353272064,1353272199,ES
+1353272200,1353272207,GB
1353272208,1353272245,ES
1353272246,1353272247,GB
1353272248,1353272691,ES
@@ -35917,11 +36588,17 @@
1353275016,1353275391,ES
1353275392,1353277439,GB
1353277440,1353279487,CH
-1353279488,1353279743,IT
+1353279488,1353279575,IT
+1353279576,1353279591,GB
+1353279592,1353279615,IT
+1353279616,1353279623,GB
+1353279624,1353279743,IT
1353279744,1353279751,GB
1353279752,1353279759,IT
1353279760,1353279763,GB
-1353279764,1353280119,IT
+1353279764,1353280039,IT
+1353280040,1353280047,GB
+1353280048,1353280119,IT
1353280120,1353280127,GB
1353280128,1353280143,IT
1353280144,1353280151,GB
@@ -35933,9 +36610,7 @@
1353280288,1353280295,GB
1353280296,1353280463,IT
1353280464,1353280479,GB
-1353280480,1353280671,IT
-1353280672,1353280679,GB
-1353280680,1353281023,IT
+1353280480,1353281023,IT
1353281024,1353281535,BE
1353281536,1353282047,GB
1353282048,1353282103,IT
@@ -35952,9 +36627,7 @@
1353287360,1353287679,GB
1353287680,1353288031,IE
1353288032,1353288063,GB
-1353288064,1353288127,IE
-1353288128,1353288143,GB
-1353288144,1353288151,IE
+1353288064,1353288151,IE
1353288152,1353288159,GB
1353288160,1353288167,IE
1353288168,1353288191,GB
@@ -35980,7 +36653,10 @@
1353288992,1353288999,GB
1353289000,1353289023,IE
1353289024,1353289031,NL
-1353289032,1353289087,GB
+1353289032,1353289047,IE
+1353289048,1353289055,GB
+1353289056,1353289083,IE
+1353289084,1353289087,GB
1353289088,1353289247,IE
1353289248,1353289255,GB
1353289256,1353289279,IE
@@ -36024,7 +36700,9 @@
1353299648,1353299839,GB
1353299840,1353299847,SE
1353299848,1353299863,GB
-1353299864,1353299951,SE
+1353299864,1353299919,SE
+1353299920,1353299927,GB
+1353299928,1353299951,SE
1353299952,1353299967,GB
1353299968,1353300079,SE
1353300080,1353300095,PT
@@ -36055,24 +36733,18 @@
1353310488,1353310599,ES
1353310600,1353310607,DE
1353310608,1353310719,ES
-1353310720,1353311071,IT
-1353311072,1353311079,GB
-1353311080,1353311135,IT
+1353310720,1353311135,IT
1353311136,1353311143,GB
-1353311144,1353311151,IT
-1353311152,1353311167,GB
-1353311168,1353311175,IT
+1353311144,1353311175,IT
1353311176,1353311183,ES
1353311184,1353311214,IT
-1353311215,1353311223,GB
-1353311224,1353311231,IT
-1353311232,1353312255,GB
+1353311215,1353312255,GB
1353312256,1353312767,CH
-1353312768,1353312775,IT
-1353312776,1353312783,GB
-1353312784,1353312815,IT
+1353312768,1353312815,IT
1353312816,1353312823,GB
-1353312824,1353312999,IT
+1353312824,1353312879,IT
+1353312880,1353312887,GB
+1353312888,1353312999,IT
1353313000,1353313007,GB
1353313008,1353313191,IT
1353313192,1353313199,GB
@@ -36276,7 +36948,7 @@
1357321472,1357321503,ES
1357321504,1357321727,EU
1357321728,1357321983,CY
-1357321984,1357322239,SO
+1357321984,1357322239,EU
1357322240,1357322751,DE
1357322752,1357323263,BH
1357323264,1357323519,ES
@@ -36489,17 +37161,18 @@
1357883520,1357883535,EU
1357883536,1357883543,FR
1357883544,1357883583,EU
-1357883584,1357883727,FR
+1357883584,1357883711,FR
+1357883712,1357883719,EU
+1357883720,1357883727,FR
1357883728,1357883743,DE
1357883744,1357883759,IT
1357883760,1357883775,FR
1357883776,1357883807,RU
-1357883808,1357883839,EU
-1357883840,1357883903,FR
-1357883904,1357883999,EU
+1357883808,1357883839,GB
+1357883840,1357883999,EU
1357884000,1357884031,FR
1357884032,1357884095,RU
-1357884096,1357884159,EU
+1357884096,1357884159,SE
1357884160,1357884415,GB
1357884416,1357884423,FR
1357884424,1357884427,BE
@@ -36536,7 +37209,8 @@
1357890944,1357891327,NL
1357891328,1357891391,EU
1357891392,1357891399,NL
-1357891400,1357891455,EU
+1357891400,1357891423,EU
+1357891424,1357891455,DE
1357891456,1357891583,SE
1357891584,1357891647,EU
1357891648,1357891679,NL
@@ -36562,10 +37236,13 @@
1357893440,1357893471,IT
1357893472,1357893503,PL
1357893504,1357893631,DE
-1357893632,1357897855,EU
+1357893632,1357897343,EU
+1357897344,1357897375,HU
+1357897376,1357897855,EU
1357897856,1357898495,DE
1357898496,1357898751,EU
-1357898752,1357899019,DE
+1357898752,1357899015,DE
+1357899016,1357899019,EU
1357899020,1357899023,NL
1357899024,1357899039,DE
1357899040,1357899047,EU
@@ -36771,8 +37448,12 @@
1358232912,1358233599,DE
1358233600,1358237695,ES
1358237696,1358239231,FR
-1358239232,1358239743,CH
-1358239744,1358241791,FR
+1358239232,1358239487,CH
+1358239488,1358239743,FR
+1358239744,1358239999,CH
+1358240000,1358240255,FR
+1358240256,1358240319,CH
+1358240320,1358241791,FR
1358241792,1358241823,BE
1358241824,1358241951,FR
1358241952,1358241983,BE
@@ -36982,7 +37663,9 @@
1358668068,1358668071,GB
1358668072,1358668271,PT
1358668272,1358668279,ES
-1358668280,1358668359,PT
+1358668280,1358668287,PT
+1358668288,1358668319,GB
+1358668320,1358668359,PT
1358668360,1358668367,GB
1358668368,1358668463,PT
1358668464,1358668479,ES
@@ -37006,7 +37689,9 @@
1358670192,1358670943,PT
1358670944,1358670951,FR
1358670952,1358671047,PT
-1358671048,1358671103,GB
+1358671048,1358671055,ES
+1358671056,1358671071,PT
+1358671072,1358671103,GB
1358671104,1358671415,PT
1358671416,1358671423,GB
1358671424,1358671431,PT
@@ -37052,7 +37737,9 @@
1358734344,1358734347,NL
1358734348,1358734715,SE
1358734716,1358734719,NL
-1358734720,1358734975,SE
+1358734720,1358734727,SE
+1358734728,1358734731,US
+1358734732,1358734975,SE
1358734976,1358734979,NL
1358734980,1358735139,SE
1358735140,1358735143,NL
@@ -37064,7 +37751,9 @@
1358735712,1358735715,FR
1358735716,1358735743,SE
1358735744,1358735751,FR
-1358735752,1358736927,SE
+1358735752,1358736071,SE
+1358736072,1358736075,US
+1358736076,1358736927,SE
1358736928,1358736943,NL
1358736944,1358737383,SE
1358737384,1358737387,NL
@@ -37295,7 +37984,7 @@
1359003648,1359020031,CZ
1359020032,1359036415,FR
1359036416,1359052799,GB
-1359069184,1359101951,RU
+1359052800,1359101951,RU
1359101952,1359118335,GB
1359118336,1359118591,DE
1359118592,1359118719,NL
@@ -37448,6 +38137,7 @@
1360060416,1360064511,LT
1360064512,1360068607,GE
1360068608,1360072703,RU
+1360072704,1360076799,CH
1360076800,1360084991,NL
1360084992,1360089087,GB
1360089088,1360093183,AZ
@@ -37529,8 +38219,10 @@
1360282240,1360282751,NL
1360282752,1360282783,GB
1360282784,1360285183,NL
-1360285184,1360285247,ES
-1360285248,1360285695,NL
+1360285184,1360285335,ES
+1360285336,1360285343,NL
+1360285344,1360285375,ES
+1360285376,1360285695,NL
1360285696,1360289791,DE
1360289792,1360293887,RU
1360293888,1360302079,DE
@@ -37575,9 +38267,7 @@
1360441344,1360445439,HU
1360445440,1360453631,RU
1360453632,1360457727,DE
-1360457728,1360459103,FI
-1360459104,1360459135,IL
-1360459136,1360461823,FI
+1360457728,1360461823,FI
1360461824,1360465919,RU
1360465920,1360470015,UA
1360470016,1360474111,FR
@@ -37746,7 +38436,11 @@
1360961536,1360965631,UA
1360965632,1360977919,RU
1360977920,1360986111,CZ
-1360986112,1360990207,GB
+1360986112,1360987935,GB
+1360987936,1360987983,SK
+1360987984,1360988055,GB
+1360988056,1360988063,SK
+1360988064,1360990207,GB
1360990208,1360990463,CZ
1360990464,1360994303,GB
1360994304,1360998399,CZ
@@ -38090,6 +38784,7 @@
1361038320,1361038335,US
1361038336,1361039359,NL
1361039360,1361043455,PL
+1361043456,1361051647,IR
1361051648,1362100223,ES
1362100224,1362395135,FR
1362395136,1362395183,CH
@@ -38285,17 +38980,18 @@
1365004288,1365008383,FR
1365008384,1365012479,CH
1365012480,1365012735,FR
-1365012736,1365013503,DE
+1365012736,1365013503,US
1365013504,1365013631,FR
-1365013632,1365015551,DE
+1365013632,1365015551,US
1365015552,1365015839,FR
-1365015840,1365015927,DE
+1365015840,1365015919,US
+1365015920,1365015927,DE
1365015928,1365015935,ES
-1365015936,1365016063,DE
+1365015936,1365016063,US
1365016064,1365016079,FR
-1365016080,1365016095,DE
+1365016080,1365016095,US
1365016096,1365016111,FR
-1365016112,1365016575,DE
+1365016112,1365016575,US
1365016576,1365020671,ES
1365020672,1365024767,CZ
1365024768,1365027839,DE
@@ -38651,7 +39347,18 @@
1369559040,1369563135,RU
1369563136,1369567231,PL
1369567232,1369571327,BG
-1369571328,1369636863,DE
+1369636864,1369638911,IR
+1369638912,1369640959,PL
+1369640960,1369655295,RU
+1369655296,1369657343,LV
+1369657344,1369659391,RU
+1369659392,1369661439,UA
+1369661440,1369665535,RU
+1369665536,1369669631,RO
+1369669632,1369677823,UA
+1369677824,1369686015,RU
+1369686016,1369690111,PL
+1369690112,1369694207,UA
1369702400,1369833471,BE
1369833472,1369964543,NO
1369964544,1369997311,GB
@@ -38984,9 +39691,7 @@
1382091312,1382091327,MC
1382091328,1382091375,FR
1382091376,1382091391,MC
-1382091392,1382091775,FR
-1382091776,1382092031,MC
-1382092032,1382092367,FR
+1382091392,1382092367,FR
1382092368,1382092399,MC
1382092400,1382092815,FR
1382092816,1382092831,MC
@@ -39028,7 +39733,9 @@
1382179248,1382179279,GB
1382179280,1382182547,DE
1382182548,1382182551,CH
-1382182552,1382182799,DE
+1382182552,1382182655,DE
+1382182656,1382182687,US
+1382182688,1382182799,DE
1382182800,1382182831,GB
1382182832,1382182895,DE
1382182896,1382182911,GB
@@ -39129,8 +39836,8 @@
1383097344,1383098111,GB
1383098112,1383098367,DE
1383098368,1383098879,GB
-1383098880,1383099151,DE
-1383099152,1383099391,GB
+1383098880,1383099159,DE
+1383099160,1383099391,GB
1383099392,1383099679,DE
1383099680,1383099687,GB
1383099688,1383099695,DE
@@ -39150,6 +39857,9 @@
1383104024,1383104255,GB
1383104256,1383104511,FR
1383104512,1383112703,JE
+1383112704,1383114751,LB
+1383114752,1383116799,GB
+1383116800,1383120895,RU
1383120896,1383129031,IT
1383129032,1383129039,ES
1383129040,1383129087,IT
@@ -39234,6 +39944,9 @@
1383440384,1383448575,RU
1383448576,1383456767,RS
1383456768,1383464959,UA
+1383464960,1383469055,BA
+1383469056,1383471103,UA
+1383471104,1383473151,SE
1383473152,1383481343,DE
1383481344,1383481599,GB
1383481600,1383481615,US
@@ -39245,9 +39958,7 @@
1383481776,1383481791,SA
1383481792,1383482367,GB
1383482368,1383482879,NL
-1383482880,1383483375,GB
-1383483376,1383483383,US
-1383483384,1383483887,GB
+1383482880,1383483887,GB
1383483888,1383483903,JP
1383483904,1383485375,GB
1383485376,1383485407,US
@@ -39345,9 +40056,7 @@
1384794128,1384794143,CH
1384794144,1384794271,FR
1384794272,1384794287,CH
-1384794288,1384794815,FR
-1384794816,1384794847,BE
-1384794848,1384794879,FR
+1384794288,1384794879,FR
1384794880,1384795135,CH
1384795136,1384795279,FR
1384795280,1384795327,BE
@@ -39491,6 +40200,7 @@
1385480192,1385488383,NL
1385488384,1385496575,GB
1385496576,1385504767,SI
+1385504768,1385512959,IT
1385512960,1385521151,DE
1385521152,1385529343,AT
1385529344,1385537535,RU
@@ -39540,8 +40250,8 @@
1385567088,1385567103,FR
1385567104,1385567135,EU
1385567136,1385567155,FR
-1385567156,1385567167,EU
-1385567168,1385567215,FR
+1385567156,1385567159,EU
+1385567160,1385567215,FR
1385567216,1385567223,EU
1385567224,1385567227,FR
1385567228,1385567231,EU
@@ -39644,7 +40354,9 @@
1388389168,1388389567,IT
1388389568,1388389631,NG
1388389632,1388389927,IT
-1388389928,1388390015,NG
+1388389928,1388389935,NG
+1388389936,1388389943,IT
+1388389944,1388390015,NG
1388390016,1388390143,IT
1388390144,1388394495,NG
1388394496,1388396031,IT
@@ -39764,7 +40476,8 @@
1388711936,1388712191,RU
1388712192,1388712703,LT
1388712704,1388713215,LB
-1388713216,1388713727,RU
+1388713216,1388713471,SE
+1388713472,1388713727,RU
1388713728,1388713983,LT
1388713984,1388714751,RU
1388714752,1388715007,IQ
@@ -39957,7 +40670,9 @@
1389199616,1389199647,IR
1389199648,1389200383,A2
1389200384,1389200639,AE
-1389200640,1389203551,A2
+1389200640,1389201919,A2
+1389201920,1389202175,AF
+1389202176,1389203551,A2
1389203552,1389203567,LB
1389203568,1389203743,A2
1389203744,1389203775,IQ
@@ -40283,7 +40998,11 @@
1389564416,1389564671,IT
1389564672,1389565183,DE
1389565184,1389565695,IT
-1389565696,1389576191,DE
+1389565696,1389568767,DE
+1389568768,1389569023,IT
+1389569024,1389569279,DE
+1389569280,1389569535,US
+1389569536,1389576191,DE
1389576192,1389592575,GB
1389592576,1389608959,GE
1389608960,1389625343,DK
@@ -40365,6 +41084,7 @@
1398886400,1398888447,CH
1398888448,1398890495,GB
1398890496,1398892543,DK
+1398892544,1398894591,RU
1398894592,1398896639,DE
1398896640,1398898687,CH
1398898688,1398931455,ES
@@ -40539,8 +41259,15 @@
1401544704,1401546751,GB
1401546752,1401548799,IT
1401548800,1401550847,FR
-1401550848,1401551103,JE
-1401551104,1401552895,GB
+1401550848,1401550879,GB
+1401550880,1401550911,JE
+1401550912,1401550935,GB
+1401550936,1401550975,JE
+1401550976,1401550983,GB
+1401550984,1401551015,JE
+1401551016,1401551023,GB
+1401551024,1401551071,JE
+1401551072,1401552895,GB
1401552896,1401554943,NL
1401554944,1401556991,IE
1401556992,1401563135,GB
@@ -41040,11 +41767,7 @@
1403994112,1404010495,AT
1404010496,1404026879,PL
1404026880,1404043263,ES
-1404043264,1404045311,EE
-1404045312,1404047359,SE
-1404047360,1404048383,EE
-1404048384,1404049407,SE
-1404049408,1404051455,EE
+1404043264,1404051455,EE
1404051456,1404059647,KZ
1404059648,1404076031,NO
1404076032,1404084223,DE
@@ -41336,7 +42059,8 @@
1407517184,1407517311,GB
1407517312,1407517383,A2
1407517384,1407517391,CD
-1407517392,1407517431,A2
+1407517392,1407517423,A2
+1407517424,1407517431,US
1407517432,1407517439,NG
1407517440,1407517695,A2
1407517696,1407517887,NG
@@ -41359,7 +42083,7 @@
1407518176,1407518183,A2
1407518184,1407518199,NG
1407518200,1407518207,AE
-1407518208,1407518215,ZW
+1407518208,1407518215,LR
1407518216,1407518231,A2
1407518232,1407518255,NG
1407518256,1407518263,CD
@@ -41410,7 +42134,7 @@
1407519760,1407519767,CD
1407519768,1407519775,GN
1407519776,1407519783,CG
-1407519784,1407519791,IQ
+1407519784,1407519791,A2
1407519792,1407519799,NG
1407519800,1407519815,A2
1407519816,1407519823,NG
@@ -41423,15 +42147,16 @@
1407519872,1407519879,IL
1407519880,1407519887,NG
1407519888,1407519895,CD
-1407519896,1407519903,GN
+1407519896,1407519903,A2
1407519904,1407519911,NG
-1407519912,1407519919,GN
-1407519920,1407519943,A2
+1407519912,1407519943,A2
1407519944,1407519959,CD
1407519960,1407519967,GB
1407519968,1407519983,NG
1407519984,1407519991,SD
-1407519992,1407520023,NG
+1407519992,1407520007,NG
+1407520008,1407520015,A2
+1407520016,1407520023,NG
1407520024,1407520031,A2
1407520032,1407520039,GN
1407520040,1407520047,A2
@@ -41481,10 +42206,10 @@
1407520600,1407520607,A2
1407520608,1407520615,AO
1407520616,1407520623,A2
-1407520624,1407520655,NG
+1407520624,1407520647,NG
+1407520648,1407520655,ML
1407520656,1407520663,GA
-1407520664,1407520671,CD
-1407520672,1407520687,A2
+1407520664,1407520687,A2
1407520688,1407520695,NG
1407520696,1407520711,A2
1407520712,1407520719,NG
@@ -41534,7 +42259,7 @@
1407521112,1407521119,SL
1407521120,1407521127,A2
1407521128,1407521135,NG
-1407521136,1407521143,CD
+1407521136,1407521143,A2
1407521144,1407521151,ZM
1407521152,1407521159,NG
1407521160,1407521167,ZW
@@ -41556,7 +42281,9 @@
1407521712,1407521727,NG
1407521728,1407521735,A2
1407521736,1407521751,NG
-1407521752,1407521783,A2
+1407521752,1407521759,A2
+1407521760,1407521767,NG
+1407521768,1407521783,A2
1407521784,1407521791,NG
1407521792,1407522319,A2
1407522320,1407522327,TG
@@ -41628,8 +42355,7 @@
1407522912,1407522919,CG
1407522920,1407522927,A2
1407522928,1407522935,GR
-1407522936,1407522943,A2
-1407522944,1407522951,CD
+1407522936,1407522951,A2
1407522952,1407522967,ZW
1407522968,1407522975,MU
1407522976,1407522983,CD
@@ -41643,7 +42369,8 @@
1407523056,1407523063,MU
1407523064,1407523071,A2
1407523072,1407523079,CD
-1407523080,1407523088,NG
+1407523080,1407523087,A2
+1407523088,1407523088,NG
1407523089,1407523103,A2
1407523104,1407523111,UG
1407523112,1407523119,ZW
@@ -41655,8 +42382,7 @@
1407523168,1407523175,A2
1407523176,1407523183,UG
1407523184,1407523191,NG
-1407523192,1407523199,A2
-1407523200,1407523207,NG
+1407523192,1407523207,A2
1407523208,1407523215,SD
1407523216,1407523223,BI
1407523224,1407523247,AO
@@ -41685,8 +42411,13 @@
1407523616,1407523623,A2
1407523624,1407523655,IQ
1407523656,1407523663,A2
-1407523664,1407523711,IQ
-1407523712,1407523839,A2
+1407523664,1407523719,IQ
+1407523720,1407523743,A2
+1407523744,1407523751,IQ
+1407523752,1407523791,A2
+1407523792,1407523799,IQ
+1407523800,1407523831,A2
+1407523832,1407523839,IQ
1407523840,1407524351,MW
1407524352,1407524607,GB
1407524608,1407524615,ZW
@@ -41722,7 +42453,8 @@
1407524896,1407524903,LR
1407524904,1407524911,A2
1407524912,1407524919,ZW
-1407524920,1407524935,A2
+1407524920,1407524927,ZA
+1407524928,1407524935,A2
1407524936,1407524943,GR
1407524944,1407524951,ZW
1407524952,1407524959,UG
@@ -41740,8 +42472,7 @@
1407525048,1407525055,NG
1407525056,1407525063,ZA
1407525064,1407525071,SO
-1407525072,1407525079,NG
-1407525080,1407525087,A2
+1407525072,1407525087,A2
1407525088,1407525095,MW
1407525096,1407525103,ZW
1407525104,1407525111,NG
@@ -41779,7 +42510,8 @@
1407525512,1407525543,A2
1407525544,1407525551,KE
1407525552,1407525559,VG
-1407525560,1407525575,A2
+1407525560,1407525567,A2
+1407525568,1407525575,CD
1407525576,1407525583,LR
1407525584,1407525607,A2
1407525608,1407525615,CD
@@ -41789,9 +42521,13 @@
1407525640,1407525679,IQ
1407525680,1407525695,A2
1407525696,1407525703,IQ
-1407525704,1407525751,A2
+1407525704,1407525719,A2
+1407525720,1407525727,IQ
+1407525728,1407525751,A2
1407525752,1407525759,IQ
-1407525760,1407526711,A2
+1407525760,1407525775,A2
+1407525776,1407525783,IQ
+1407525784,1407526711,A2
1407526712,1407526719,GN
1407526720,1407528959,A2
1407528960,1407528991,SO
@@ -41815,14 +42551,14 @@
1407531568,1407531575,CD
1407531576,1407531583,A2
1407531584,1407531591,CD
-1407531592,1407531607,A2
+1407531592,1407531599,A2
+1407531600,1407531607,LY
1407531608,1407531615,CD
1407531616,1407531623,A2
1407531624,1407531631,CD
1407531632,1407531639,ZM
1407531640,1407531647,CD
-1407531648,1407531655,A2
-1407531656,1407531663,CD
+1407531648,1407531663,A2
1407531664,1407531671,MZ
1407531672,1407531687,CD
1407531688,1407531703,A2
@@ -41833,7 +42569,8 @@
1407531752,1407531759,GQ
1407531760,1407531767,ZW
1407531768,1407531775,SD
-1407531776,1407532551,A2
+1407531776,1407532543,A2
+1407532544,1407532551,SO
1407532552,1407532559,AO
1407532560,1407532583,A2
1407532584,1407532591,ZW
@@ -41864,18 +42601,18 @@
1407533728,1407533735,A2
1407533736,1407533743,GN
1407533744,1407533751,NG
-1407533752,1407533759,A2
+1407533752,1407533759,SL
1407533760,1407533767,NG
1407533768,1407533775,A2
1407533776,1407533783,NG
1407533784,1407533815,A2
1407533816,1407533823,NG
-1407533824,1407533919,A2
+1407533824,1407533831,LR
+1407533832,1407533919,A2
1407533920,1407533927,BF
1407533928,1407534079,A2
1407534080,1407534335,AE
-1407534336,1407534343,CM
-1407534344,1407534359,A2
+1407534336,1407534359,A2
1407534360,1407534383,NG
1407534384,1407534391,GR
1407534392,1407534399,AO
@@ -41919,7 +42656,7 @@
1407535816,1407535823,NG
1407535824,1407535847,A2
1407535848,1407535855,CD
-1407535856,1407535863,SD
+1407535856,1407535863,GB
1407535864,1407536127,A2
1407536128,1407536639,GA
1407536640,1407536895,CD
@@ -41951,14 +42688,16 @@
1407537208,1407537215,BE
1407537216,1407537239,A2
1407537240,1407537255,NG
-1407537256,1407537287,A2
+1407537256,1407537263,A2
+1407537264,1407537279,CM
+1407537280,1407537287,A2
1407537288,1407537303,UG
1407537304,1407537311,LR
1407537312,1407537319,A2
1407537320,1407537327,NG
1407537328,1407537343,A2
-1407537344,1407537351,NG
-1407537352,1407537367,A2
+1407537344,1407537359,NG
+1407537360,1407537367,A2
1407537368,1407537383,NG
1407537384,1407537431,A2
1407537432,1407537439,NG
@@ -41976,8 +42715,8 @@
1407537576,1407537591,NG
1407537592,1407537607,A2
1407537608,1407537615,CM
-1407537616,1407537623,A2
-1407537624,1407537639,NG
+1407537616,1407537631,A2
+1407537632,1407537639,NG
1407537640,1407537679,A2
1407537680,1407537687,IQ
1407537688,1407537703,A2
@@ -41999,13 +42738,14 @@
1407537968,1407537975,NG
1407537976,1407537983,A2
1407537984,1407537991,NG
-1407537992,1407537999,IQ
+1407537992,1407537999,A2
1407538000,1407538023,NG
1407538024,1407538031,A2
1407538032,1407538039,NG
1407538040,1407538047,CD
1407538048,1407538055,NG
-1407538056,1407538071,LU
+1407538056,1407538063,A2
+1407538064,1407538071,LU
1407538072,1407538079,A2
1407538080,1407538087,LR
1407538088,1407538095,AO
@@ -42072,24 +42812,23 @@
1407539720,1407539727,A2
1407539728,1407539735,GR
1407539736,1407539743,NG
-1407539744,1407539759,A2
-1407539760,1407539767,GH
+1407539744,1407539767,A2
1407539768,1407539775,GR
1407539776,1407539783,A2
1407539784,1407539791,GR
1407539792,1407539799,NG
1407539800,1407539823,A2
-1407539824,1407539839,NG
-1407539840,1407539847,A2
+1407539824,1407539831,NG
+1407539832,1407539847,A2
1407539848,1407539855,NG
1407539856,1407539863,CD
1407539864,1407539879,NG
-1407539880,1407539895,A2
+1407539880,1407539887,A2
+1407539888,1407539895,NG
1407539896,1407539903,CD
1407539904,1407539911,A2
1407539912,1407539927,NG
-1407539928,1407539935,GN
-1407539936,1407539943,A2
+1407539928,1407539943,A2
1407539944,1407539951,CD
1407539952,1407539959,LR
1407539960,1407539967,A2
@@ -42138,18 +42877,22 @@
1407540496,1407540503,NG
1407540504,1407540551,A2
1407540552,1407540559,NG
-1407540560,1407540591,A2
+1407540560,1407540567,CD
+1407540568,1407540591,A2
1407540592,1407540599,GN
1407540600,1407540607,A2
1407540608,1407540615,CD
1407540616,1407540623,SD
1407540624,1407540655,A2
1407540656,1407540663,CD
-1407540664,1407540767,A2
+1407540664,1407540695,A2
+1407540696,1407540703,NG
+1407540704,1407540767,A2
1407540768,1407540775,NG
1407540776,1407540991,A2
1407540992,1407540999,CD
-1407541000,1407541031,A2
+1407541000,1407541023,A2
+1407541024,1407541031,LR
1407541032,1407541039,NG
1407541040,1407541047,A2
1407541048,1407541055,NG
@@ -42196,8 +42939,8 @@
1407542768,1407542775,GA
1407542776,1407542791,A2
1407542792,1407542799,NG
-1407542800,1407542831,A2
-1407542832,1407542863,NG
+1407542800,1407542847,A2
+1407542848,1407542863,NG
1407542864,1407542903,A2
1407542904,1407542911,CD
1407542912,1407543039,AT
@@ -42220,25 +42963,23 @@
1407545928,1407545935,A2
1407545936,1407545943,ZA
1407545944,1407545951,A2
-1407545952,1407545959,NG
+1407545952,1407545959,BJ
1407545960,1407545967,A2
1407545968,1407545975,GQ
1407545976,1407545983,A2
1407545984,1407545991,MU
1407545992,1407545999,GN
-1407546000,1407546023,A2
+1407546000,1407546007,CF
+1407546008,1407546023,A2
1407546024,1407546047,NG
1407546048,1407546055,A2
1407546056,1407546063,NG
1407546064,1407546071,ML
1407546072,1407546367,A2
1407546368,1407546495,AE
-1407546496,1407546799,A2
-1407546800,1407546815,GH
-1407546816,1407546863,A2
+1407546496,1407546863,A2
1407546864,1407546879,LR
-1407546880,1407547135,ZW
-1407547136,1407547143,A2
+1407546880,1407547143,A2
1407547144,1407547151,GH
1407547152,1407547167,A2
1407547168,1407547175,NG
@@ -42285,7 +43026,7 @@
1407548952,1407548959,NG
1407548960,1407548967,A2
1407548968,1407548975,CM
-1407548976,1407548983,NG
+1407548976,1407548983,A2
1407548984,1407548991,CD
1407548992,1407549039,A2
1407549040,1407549047,NG
@@ -42305,13 +43046,11 @@
1407549440,1407582207,RU
1407582208,1407614975,PL
1407614976,1407680511,ES
-1407680512,1407680687,FR
-1407680688,1407680703,GB
-1407680704,1407680735,FR
-1407680736,1407681023,GB
-1407681024,1407681103,ES
-1407681104,1407681119,GB
-1407681120,1407681291,ES
+1407680512,1407680695,FR
+1407680696,1407680703,GB
+1407680704,1407680831,FR
+1407680832,1407681023,GB
+1407681024,1407681291,ES
1407681292,1407681295,GB
1407681296,1407681535,ES
1407681536,1407681639,FR
@@ -42323,7 +43062,9 @@
1407682880,1407682911,FI
1407682912,1407687423,GB
1407687424,1407687679,ES
-1407687680,1407695215,GB
+1407687680,1407693159,GB
+1407693160,1407693167,ES
+1407693168,1407695215,GB
1407695216,1407695223,ES
1407695224,1407700271,GB
1407700272,1407700287,DE
@@ -42354,8 +43095,8 @@
1407705792,1407706367,GB
1407706368,1407706423,FR
1407706424,1407706431,GB
-1407706432,1407706479,FR
-1407706480,1407707703,GB
+1407706432,1407706559,FR
+1407706560,1407707703,GB
1407707704,1407707839,CH
1407707840,1407707903,GB
1407707904,1407707935,CH
@@ -42374,8 +43115,8 @@
1407712832,1407712895,GB
1407712896,1407712911,DE
1407712912,1407712919,GB
-1407712920,1407712927,DE
-1407712928,1407712975,GB
+1407712920,1407712959,DE
+1407712960,1407712975,GB
1407712976,1407713239,DE
1407713240,1407713247,GB
1407713248,1407713279,DE
@@ -42840,11 +43581,9 @@
1410753352,1410753367,AQ
1410753368,1410753391,DE
1410753392,1410753399,NL
-1410753400,1410753791,AQ
-1410753792,1410754303,US
-1410754304,1410754559,AQ
-1410754560,1410754567,US
-1410754568,1410754831,AQ
+1410753400,1410754623,AQ
+1410754624,1410754631,CN
+1410754632,1410754831,AQ
1410754832,1410754855,DE
1410754856,1410754859,AQ
1410754860,1410754867,DE
@@ -42854,13 +43593,7 @@
1410755068,1410755071,DE
1410755072,1410755327,AQ
1410755328,1410755583,DE
-1410755584,1410756863,US
-1410756864,1410757119,AQ
-1410757120,1410758143,US
-1410758144,1410758399,AQ
-1410758400,1410758655,US
-1410758656,1410759679,AQ
-1410759680,1410760191,US
+1410755584,1410760191,AQ
1410760192,1410760447,DE
1410760448,1410760455,CN
1410760456,1410760471,AQ
@@ -43088,9 +43821,7 @@
1412677632,1412685823,RU
1412685824,1412686239,IE
1412686240,1412686335,BB
-1412686336,1412686591,IE
-1412686592,1412686847,GB
-1412686848,1412689315,IE
+1412686336,1412689315,IE
1412689316,1412689343,GB
1412689344,1412690191,IE
1412690192,1412690199,GB
@@ -43383,7 +44114,9 @@
1424614400,1424614415,FR
1424614416,1424614431,IT
1424614432,1424614439,GB
-1424614440,1424614655,IT
+1424614440,1424614495,IT
+1424614496,1424614527,GB
+1424614528,1424614655,IT
1424614656,1424614911,FR
1424614912,1424615167,RO
1424615168,1424615679,GB
@@ -43405,8 +44138,8 @@
1424616704,1424616959,US
1424616960,1424617215,FR
1424617216,1424617231,IT
-1424617232,1424617239,GB
-1424617240,1424617351,IT
+1424617232,1424617247,GB
+1424617248,1424617351,IT
1424617352,1424617391,GB
1424617392,1424617395,IT
1424617396,1424617399,GB
@@ -43419,9 +44152,11 @@
1424617456,1424617463,IT
1424617464,1424617471,GB
1424617472,1424617727,US
-1424617728,1424618039,IT
-1424618040,1424618047,GB
-1424618048,1424618239,IT
+1424617728,1424618031,IT
+1424618032,1424618047,GB
+1424618048,1424618191,IT
+1424618192,1424618207,GB
+1424618208,1424618239,IT
1424618240,1424618495,NL
1424618496,1424618751,GB
1424618752,1424618927,FR
@@ -43505,6 +44240,7 @@
1424850944,1424883711,LV
1424883712,1424916479,DK
1424916480,1424949247,BG
+1424949248,1424982015,RO
1424982016,1425014783,FI
1425014784,1425031167,LT
1425031168,1425047551,FI
@@ -43608,7 +44344,8 @@
1425478144,1425478655,GB
1425478656,1425484799,RO
1425484800,1425485311,GB
-1425485312,1425506303,RO
+1425485312,1425485823,AE
+1425485824,1425506303,RO
1425506304,1425522687,NO
1425522688,1425539071,IT
1425539072,1425801215,FI
@@ -43621,7 +44358,9 @@
1425899520,1425915903,IT
1425915904,1425932287,FI
1425932288,1425948671,GR
-1425948672,1425965055,DE
+1425948672,1425949183,DE
+1425949184,1425949191,NL
+1425949192,1425965055,DE
1425965056,1425965100,ES
1425965101,1425965112,FR
1425965113,1425965116,ZA
@@ -44004,16 +44743,19 @@
1427728896,1427728927,RU
1427728928,1427728959,IL
1427728960,1427728991,RU
-1427728992,1427729055,DE
+1427728992,1427729023,DE
+1427729024,1427729055,GB
1427729056,1427729087,CA
-1427729088,1427729311,DE
+1427729088,1427729119,DE
+1427729120,1427729151,BR
+1427729152,1427729311,DE
1427729312,1427729343,GR
1427729344,1427742719,DE
1427742720,1427742751,IO
1427742752,1427742975,DE
1427742976,1427743007,RU
1427743008,1427743039,US
-1427743040,1427743071,DE
+1427743040,1427743071,BR
1427743072,1427743103,CY
1427743104,1427743135,BR
1427743136,1427743199,DE
@@ -44034,7 +44776,7 @@
1427743840,1427743871,RU
1427743872,1427743935,DE
1427743936,1427743967,RU
-1427743968,1427743999,DE
+1427743968,1427743999,US
1427744000,1427744031,TW
1427744032,1427744127,DE
1427744128,1427744159,PL
@@ -44051,22 +44793,22 @@
1427744640,1427744671,TR
1427744672,1427744735,DE
1427744736,1427744767,DK
-1427744768,1427744831,DE
-1427744832,1427744863,US
+1427744768,1427744863,DE
1427744864,1427744927,TR
1427744928,1427744959,HU
1427744960,1427744991,RU
1427744992,1427745023,DK
1427745024,1427745055,BM
-1427745056,1427745151,DE
+1427745056,1427745087,US
+1427745088,1427745151,DE
1427745152,1427745183,RO
1427745184,1427745215,CH
-1427745216,1427745311,DE
+1427745216,1427745279,DE
+1427745280,1427745311,MA
1427745312,1427745343,TH
1427745344,1427745375,DE
1427745376,1427745407,TW
-1427745408,1427745439,DE
-1427745440,1427745471,US
+1427745408,1427745471,US
1427745472,1427745503,RO
1427745504,1427745535,RU
1427745536,1427745567,CN
@@ -44080,7 +44822,9 @@
1427745792,1427745823,GB
1427745824,1427745855,US
1427745856,1427745887,BR
-1427745888,1427746047,DE
+1427745888,1427745919,DE
+1427745920,1427745951,ES
+1427745952,1427746047,DE
1427746048,1427746079,SE
1427746080,1427746111,GB
1427746112,1427746143,DE
@@ -44089,27 +44833,33 @@
1427746240,1427746271,US
1427746272,1427747839,DE
1427747840,1427747871,FI
-1427747872,1427747935,DE
+1427747872,1427747903,BR
+1427747904,1427747935,CY
1427747936,1427747967,US
-1427747968,1427748063,DE
+1427747968,1427747999,DE
+1427748000,1427748031,BR
+1427748032,1427748063,DE
1427748064,1427748095,US
-1427748096,1427748255,DE
+1427748096,1427748127,BR
+1427748128,1427748159,DE
+1427748160,1427748191,GB
+1427748192,1427748255,DE
1427748256,1427748287,US
1427748288,1427748447,DE
1427748448,1427748479,RU
-1427748480,1427748511,DE
-1427748512,1427748543,US
-1427748544,1427748575,MX
-1427748576,1427748607,DE
+1427748480,1427748511,MA
+1427748512,1427748607,DE
1427748608,1427748639,HU
-1427748640,1427749567,DE
+1427748640,1427748767,DE
+1427748768,1427748799,BR
+1427748800,1427749567,DE
1427749568,1427749599,CY
1427749600,1427749695,DE
1427749696,1427749727,BR
1427749728,1427749855,DE
1427749856,1427749887,RU
1427749888,1427749919,BR
-1427749920,1427749951,DE
+1427749920,1427749951,US
1427749952,1427749983,RU
1427749984,1427750079,DE
1427750080,1427750111,BG
@@ -44122,19 +44872,19 @@
1427750336,1427750367,US
1427750368,1427751167,DE
1427751168,1427751423,NL
-1427751424,1427759935,DE
+1427751424,1427759903,DE
+1427759904,1427759935,MA
1427759936,1427759967,HR
1427759968,1427760031,DE
-1427760032,1427760063,US
-1427760064,1427760095,DE
-1427760096,1427760127,US
-1427760128,1427760191,DE
+1427760032,1427760095,US
+1427760096,1427760191,DE
1427760192,1427760255,US
1427760256,1427760319,BR
1427760320,1427760351,TR
1427760352,1427760383,RU
1427760384,1427760415,TR
-1427760416,1427760575,DE
+1427760416,1427760447,BR
+1427760448,1427760575,DE
1427760576,1427760607,CH
1427760608,1427760799,DE
1427760800,1427760831,US
@@ -44147,8 +44897,7 @@
1427761056,1427761087,CL
1427761088,1427761119,CH
1427761120,1427761151,TR
-1427761152,1427761183,DE
-1427761184,1427761215,US
+1427761152,1427761215,DE
1427761216,1427761247,TR
1427761248,1427761279,DE
1427761280,1427761311,RU
@@ -44196,9 +44945,7 @@
1428142080,1428143263,DE
1428143264,1428143279,CH
1428143280,1428144127,DE
-1428144128,1428146983,FR
-1428146984,1428146991,GB
-1428146992,1428147343,FR
+1428144128,1428147343,FR
1428147344,1428147351,GB
1428147352,1428147599,FR
1428147600,1428147615,GB
@@ -44210,9 +44957,7 @@
1428150488,1428150495,GB
1428150496,1428150663,FR
1428150664,1428150671,GB
-1428150672,1428150879,FR
-1428150880,1428150911,GB
-1428150912,1428151231,FR
+1428150672,1428151231,FR
1428151232,1428151295,CH
1428151296,1428152319,FR
1428152320,1428160511,PL
@@ -44549,8 +45294,7 @@
1434681984,1434682015,CY
1434682016,1434682111,NL
1434682112,1434682303,DE
-1434682304,1434682319,CY
-1434682320,1434682367,NL
+1434682304,1434682367,NL
1434682368,1434683119,DE
1434683120,1434683135,NL
1434683136,1434683327,DE
@@ -44565,21 +45309,35 @@
1434687648,1434687679,NL
1434687680,1434688031,DE
1434688032,1434688063,NL
-1434688064,1434688207,DE
+1434688064,1434688095,DE
+1434688096,1434688127,NL
+1434688128,1434688143,DE
+1434688144,1434688151,NL
+1434688152,1434688207,DE
1434688208,1434688223,NL
1434688224,1434689887,DE
1434689888,1434689919,NL
-1434689920,1434692607,DE
+1434689920,1434689951,DE
+1434689952,1434690015,NL
+1434690016,1434692607,DE
1434692608,1434692671,NL
1434692672,1434693119,DE
1434693120,1434693375,NL
1434693376,1434694655,DE
1434694656,1434694719,NL
-1434694720,1434702463,DE
+1434694720,1434696447,DE
+1434696448,1434696703,NL
+1434696704,1434698879,DE
+1434698880,1434699007,NL
+1434699008,1434702463,DE
1434702464,1434702591,NL
1434702592,1434702655,DE
1434702656,1434702671,NL
-1434702672,1434705727,DE
+1434702672,1434702783,DE
+1434702784,1434702847,NL
+1434702848,1434702975,DE
+1434702976,1434703039,NL
+1434703040,1434705727,DE
1434705728,1434705919,NL
1434705920,1434712063,DE
1434712064,1434712319,NL
@@ -44726,7 +45484,9 @@
1438810112,1438826495,SE
1438826496,1438842879,FI
1438842880,1438859263,SE
-1438859264,1438861823,DE
+1438859264,1438860287,DE
+1438860288,1438860415,US
+1438860416,1438861823,DE
1438861824,1438862079,CH
1438862080,1438869591,DE
1438869592,1438869595,RU
@@ -44750,9 +45510,7 @@
1438874800,1438874855,PA
1438874856,1438874863,DE
1438874864,1438874879,PA
-1438874880,1438875223,DE
-1438875224,1438875255,GB
-1438875256,1438875647,DE
+1438874880,1438875647,DE
1438875648,1438876159,RU
1438876160,1438876415,LT
1438876416,1438876927,RU
@@ -45157,9 +45915,15 @@
1446707176,1446707179,NO
1446707180,1446707183,FI
1446707184,1446707199,DK
-1446707200,1446712783,AT
+1446707200,1446710799,AT
+1446710800,1446710815,MT
+1446710816,1446710887,AT
+1446710888,1446710895,MT
+1446710896,1446712783,AT
1446712784,1446712791,DE
-1446712792,1446736503,AT
+1446712792,1446716399,AT
+1446716400,1446716407,MT
+1446716408,1446736503,AT
1446736504,1446736511,US
1446736512,1446739967,AT
1446739968,1446772735,RU
@@ -45173,14 +45937,16 @@
1446904064,1446904071,CY
1446904072,1446904079,LY
1446904080,1446904087,AF
-1446904088,1446904095,A2
+1446904088,1446904095,BF
1446904096,1446904103,SD
1446904104,1446904111,IQ
1446904112,1446904119,GN
1446904120,1446904127,IQ
-1446904128,1446904143,A2
+1446904128,1446904135,AF
+1446904136,1446904143,LY
1446904144,1446904151,ER
-1446904152,1446904231,A2
+1446904152,1446904159,AF
+1446904160,1446904231,A2
1446904232,1446904239,IQ
1446904240,1446904247,A2
1446904248,1446904255,AF
@@ -45208,24 +45974,24 @@
1446904844,1446904847,CG
1446904848,1446904851,AF
1446904852,1446904855,LY
-1446904856,1446904859,A2
+1446904856,1446904859,IQ
1446904860,1446904867,LY
1446904868,1446904871,IQ
1446904872,1446904879,A2
1446904880,1446904883,IQ
1446904884,1446904887,AF
-1446904888,1446904891,A2
-1446904892,1446904895,IQ
+1446904888,1446904895,IQ
1446904896,1446904899,LY
1446904900,1446904903,A2
1446904904,1446904907,AF
-1446904908,1446904911,IQ
-1446904912,1446904919,A2
+1446904908,1446904919,A2
1446904920,1446904923,LY
1446904924,1446904927,AF
-1446904928,1446904935,A2
+1446904928,1446904931,TD
+1446904932,1446904935,A2
1446904936,1446904939,AO
-1446904940,1446904947,IQ
+1446904940,1446904943,LY
+1446904944,1446904947,IQ
1446904948,1446904951,LY
1446904952,1446904955,AF
1446904956,1446904959,A2
@@ -45239,12 +46005,12 @@
1446904992,1446904995,IQ
1446904996,1446905007,A2
1446905008,1446905011,CG
-1446905012,1446905015,A2
+1446905012,1446905015,AF
1446905016,1446905019,NG
1446905020,1446905027,A2
1446905028,1446905031,IQ
1446905032,1446905035,LY
-1446905036,1446905039,A2
+1446905036,1446905039,IQ
1446905040,1446905043,AF
1446905044,1446905047,IQ
1446905048,1446905051,LY
@@ -45253,7 +46019,7 @@
1446905064,1446905067,NG
1446905068,1446905083,A2
1446905084,1446905095,AF
-1446905096,1446905099,A2
+1446905096,1446905099,LY
1446905100,1446905103,IQ
1446905104,1446905111,LY
1446905112,1446905115,NG
@@ -45262,19 +46028,18 @@
1446905124,1446905127,AF
1446905128,1446905131,IQ
1446905132,1446905139,LY
-1446905140,1446905143,A2
-1446905144,1446905147,IQ
+1446905140,1446905147,IQ
1446905148,1446905155,A2
1446905156,1446905159,IQ
-1446905160,1446905167,A2
-1446905168,1446905171,LY
+1446905160,1446905163,A2
+1446905164,1446905171,LY
1446905172,1446905175,A2
1446905176,1446905179,AF
1446905180,1446905183,LY
1446905184,1446905191,A2
1446905192,1446905195,LY
1446905196,1446905199,AF
-1446905200,1446905203,NG
+1446905200,1446905203,A2
1446905204,1446905207,AF
1446905208,1446905211,ER
1446905212,1446905215,AF
@@ -45282,23 +46047,24 @@
1446905220,1446905223,IQ
1446905224,1446905227,LY
1446905228,1446905235,NG
-1446905236,1446905243,A2
+1446905236,1446905239,A2
+1446905240,1446905243,IQ
1446905244,1446905247,AF
1446905248,1446905251,A2
1446905252,1446905255,LY
1446905256,1446905271,A2
-1446905272,1446905283,IQ
-1446905284,1446905287,A2
-1446905288,1446905291,LY
-1446905292,1446905303,A2
+1446905272,1446905287,IQ
+1446905288,1446905295,LY
+1446905296,1446905303,IQ
1446905304,1446905307,CF
1446905308,1446905311,IQ
-1446905312,1446905315,A2
+1446905312,1446905315,EG
1446905316,1446905319,NG
1446905320,1446905331,IQ
1446905332,1446905335,A2
1446905336,1446905343,IQ
-1446905344,1446905383,A2
+1446905344,1446905351,NG
+1446905352,1446905383,A2
1446905384,1446905391,SD
1446905392,1446905583,A2
1446905584,1446905591,AF
@@ -45357,7 +46123,8 @@
1446906112,1446906119,IQ
1446906120,1446906123,BG
1446906124,1446906131,IQ
-1446906132,1446906151,A2
+1446906132,1446906135,SD
+1446906136,1446906151,A2
1446906152,1446906159,AF
1446906160,1446906167,A2
1446906168,1446906171,IQ
@@ -45366,8 +46133,7 @@
1446906212,1446906215,AF
1446906216,1446906219,IQ
1446906220,1446906223,BG
-1446906224,1446906227,IQ
-1446906228,1446906231,A2
+1446906224,1446906231,A2
1446906232,1446906239,AF
1446906240,1446906243,IQ
1446906244,1446906251,A2
@@ -45433,7 +46199,9 @@
1446907136,1446907143,A2
1446907144,1446907147,AF
1446907148,1446907151,IQ
-1446907152,1446907171,A2
+1446907152,1446907159,A2
+1446907160,1446907163,IQ
+1446907164,1446907171,A2
1446907172,1446907175,IQ
1446907176,1446907187,A2
1446907188,1446907191,CG
@@ -45480,8 +46248,7 @@
1446907448,1446907487,A2
1446907488,1446907491,IQ
1446907492,1446907495,TD
-1446907496,1446907499,IQ
-1446907500,1446907519,A2
+1446907496,1446907519,A2
1446907520,1446907523,LY
1446907524,1446907531,A2
1446907532,1446907535,CI
@@ -45520,8 +46287,8 @@
1446907744,1446907747,IQ
1446907748,1446907751,A2
1446907752,1446907755,AF
-1446907756,1446907771,A2
-1446907772,1446907775,IQ
+1446907756,1446907767,A2
+1446907768,1446907775,IQ
1446907776,1446907787,A2
1446907788,1446907791,IQ
1446907792,1446907811,A2
@@ -45553,11 +46320,14 @@
1446908232,1446908235,LY
1446908236,1446908247,A2
1446908248,1446908251,AF
-1446908252,1446908259,A2
+1446908252,1446908255,A2
+1446908256,1446908259,SZ
1446908260,1446908263,IQ
1446908264,1446908267,A2
1446908268,1446908271,AF
-1446908272,1446908283,A2
+1446908272,1446908275,A2
+1446908276,1446908279,LY
+1446908280,1446908283,A2
1446908284,1446908287,AF
1446908288,1446908299,A2
1446908300,1446908303,IQ
@@ -45581,14 +46351,14 @@
1446908456,1446908459,LB
1446908460,1446908479,A2
1446908480,1446908483,IQ
-1446908484,1446908539,A2
-1446908540,1446908543,ZM
-1446908544,1446908603,A2
+1446908484,1446908603,A2
1446908604,1446908607,CG
1446908608,1446908631,A2
1446908632,1446908635,IQ
1446908636,1446908655,A2
-1446908656,1446908667,IQ
+1446908656,1446908659,IQ
+1446908660,1446908663,A2
+1446908664,1446908667,IQ
1446908668,1446908683,A2
1446908684,1446908687,SD
1446908688,1446908691,IQ
@@ -45604,8 +46374,7 @@
1446908920,1446908923,IQ
1446908924,1446908927,A2
1446908928,1446908931,IQ
-1446908932,1446908935,ZM
-1446908936,1446908971,A2
+1446908932,1446908971,A2
1446908972,1446908975,AF
1446908976,1446908979,GA
1446908980,1446908983,AF
@@ -45646,7 +46415,8 @@
1446909520,1446909523,CG
1446909524,1446909527,A2
1446909528,1446909531,EG
-1446909532,1446909539,A2
+1446909532,1446909535,A2
+1446909536,1446909539,AF
1446909540,1446909547,IQ
1446909548,1446909575,A2
1446909576,1446909579,AF
@@ -45663,9 +46433,7 @@
1446909808,1446909815,A2
1446909816,1446909819,AF
1446909820,1446909827,IQ
-1446909828,1446909903,A2
-1446909904,1446909907,IQ
-1446909908,1446909999,A2
+1446909828,1446909999,A2
1446910000,1446910003,AF
1446910004,1446910019,A2
1446910020,1446910023,IQ
@@ -45721,7 +46489,9 @@
1446910728,1446910731,AF
1446910732,1446910739,A2
1446910740,1446910747,AF
-1446910748,1446910791,A2
+1446910748,1446910771,A2
+1446910772,1446910775,AF
+1446910776,1446910791,A2
1446910792,1446910795,LY
1446910796,1446910799,A2
1446910800,1446910807,IQ
@@ -45771,9 +46541,7 @@
1446911164,1446911171,IQ
1446911172,1446911183,A2
1446911184,1446911187,AF
-1446911188,1446911195,A2
-1446911196,1446911199,IQ
-1446911200,1446911207,A2
+1446911188,1446911207,A2
1446911208,1446911215,IQ
1446911216,1446911223,A2
1446911224,1446911227,AF
@@ -45784,9 +46552,7 @@
1446911260,1446911263,AF
1446911264,1446911267,IQ
1446911268,1446911271,AF
-1446911272,1446911295,A2
-1446911296,1446911299,GH
-1446911300,1446911303,A2
+1446911272,1446911303,A2
1446911304,1446911307,IQ
1446911308,1446911319,A2
1446911320,1446911323,AF
@@ -45837,9 +46603,7 @@
1446911624,1446911627,IQ
1446911628,1446911631,AF
1446911632,1446911635,IQ
-1446911636,1446911643,A2
-1446911644,1446911647,AF
-1446911648,1446911679,A2
+1446911636,1446911679,A2
1446911680,1446911683,SD
1446911684,1446911691,A2
1446911692,1446911695,LY
@@ -45848,7 +46612,9 @@
1446911702,1446911739,A2
1446911740,1446911743,LY
1446911744,1446911751,IQ
-1446911752,1446911771,A2
+1446911752,1446911763,A2
+1446911764,1446911767,LY
+1446911768,1446911771,A2
1446911772,1446911775,AF
1446911776,1446911779,A2
1446911780,1446911783,AF
@@ -45857,13 +46623,14 @@
1446911792,1446911795,A2
1446911796,1446911799,IQ
1446911800,1446911803,NG
-1446911804,1446911827,A2
+1446911804,1446911819,A2
+1446911820,1446911823,IQ
+1446911824,1446911827,A2
1446911828,1446911831,IQ
1446911832,1446911835,A2
1446911836,1446911843,IQ
1446911844,1446911847,A2
-1446911848,1446911851,IQ
-1446911852,1446911855,A2
+1446911848,1446911855,IQ
1446911856,1446911859,AF
1446911860,1446911867,A2
1446911868,1446911871,LY
@@ -45886,7 +46653,7 @@
1446912028,1446912031,AF
1446912032,1446912035,A2
1446912036,1446912039,AF
-1446912040,1446912043,A2
+1446912040,1446912043,IQ
1446912044,1446912047,CG
1446912048,1446912051,AF
1446912052,1446912055,ER
@@ -45894,17 +46661,19 @@
1446912060,1446912063,NG
1446912064,1446912067,AF
1446912068,1446912071,A2
-1446912072,1446912075,AE
-1446912076,1446912083,A2
+1446912072,1446912075,IQ
+1446912076,1446912079,A2
+1446912080,1446912083,IQ
1446912084,1446912087,AF
1446912088,1446912095,A2
1446912096,1446912103,AF
-1446912104,1446912107,IQ
-1446912108,1446912115,A2
+1446912104,1446912115,A2
1446912116,1446912119,LY
1446912120,1446912151,A2
1446912152,1446912155,CF
-1446912156,1446912183,A2
+1446912156,1446912163,A2
+1446912164,1446912167,IQ
+1446912168,1446912183,A2
1446912184,1446912187,AF
1446912188,1446912191,IQ
1446912192,1446912195,A2
@@ -45914,18 +46683,19 @@
1446912220,1446912239,A2
1446912240,1446912247,IQ
1446912248,1446912251,AF
-1446912252,1446912255,A2
+1446912252,1446912255,IQ
1446912256,1446912263,AF
1446912264,1446912295,IQ
-1446912296,1446912303,AF
-1446912304,1446912319,A2
+1446912296,1446912311,AF
+1446912312,1446912319,A2
1446912320,1446912335,IQ
1446912336,1446912343,KW
1446912344,1446912367,IQ
1446912368,1446912375,A2
1446912376,1446912391,AF
1446912392,1446912399,GA
-1446912400,1446912423,A2
+1446912400,1446912415,AF
+1446912416,1446912423,A2
1446912424,1446912431,AF
1446912432,1446920191,A2
1446920192,1446936575,RU
@@ -46032,6 +46802,9 @@
1450123264,1450131455,AT
1450131456,1450139647,UA
1450139648,1450147839,PL
+1450147840,1450151935,CH
+1450151936,1450153983,IQ
+1450153984,1450156031,DE
1450156032,1450164223,GB
1450164224,1450166271,SA
1450166272,1450168319,PL
@@ -46092,7 +46865,9 @@
1466265600,1466269695,HU
1466269696,1466302463,SA
1466302464,1466335231,GB
-1466335232,1466367631,CH
+1466335232,1466367119,CH
+1466367120,1466367127,GR
+1466367128,1466367631,CH
1466367632,1466367639,AT
1466367640,1466367999,CH
1466368000,1466400767,PT
@@ -46137,7 +46912,7 @@
1467301888,1467318271,GB
1467318272,1467334655,RU
1467334656,1467340959,GB
-1467340960,1467340991,TR
+1467340960,1467340991,US
1467340992,1467344639,GB
1467344640,1467344895,ZA
1467344896,1467351039,GB
@@ -46281,6 +47056,7 @@
1475131392,1475133439,RU
1475133440,1475135487,CZ
1475135488,1475137535,CH
+1475137536,1475139583,IR
1475139584,1475141631,ES
1475141632,1475143679,FI
1475143680,1475145727,JO
@@ -46313,6 +47089,7 @@
1475182080,1475182335,RO
1475182336,1475184639,DE
1475184640,1475186687,RU
+1475186688,1475188735,GB
1475188736,1475190783,SE
1475190784,1475192831,GB
1475192832,1475194879,CH
@@ -46354,13 +47131,7 @@
1475208192,1475209215,AE
1475209216,1475211263,UZ
1475211264,1475213311,DE
-1475213312,1475214335,FR
-1475214336,1475214399,GB
-1475214400,1475214847,FR
-1475214848,1475214975,GB
-1475214976,1475215103,FR
-1475215104,1475215167,GB
-1475215168,1475215359,FR
+1475213312,1475215359,FR
1475215360,1475223551,IT
1475223552,1475229695,NO
1475229696,1475229759,SE
@@ -46378,8 +47149,11 @@
1475241984,1475242239,MC
1475242240,1475243775,FR
1475243776,1475244031,MC
-1475244032,1475245055,DE
-1475245056,1475245183,IE
+1475244032,1475244287,DE
+1475244288,1475244311,SD
+1475244312,1475244319,DE
+1475244320,1475244543,SD
+1475244544,1475245183,DE
1475245184,1475245311,SD
1475245312,1475246079,DE
1475246080,1475248127,CH
@@ -46426,6 +47200,7 @@
1475287040,1475291135,RU
1475291136,1475293183,PL
1475293184,1475295231,GB
+1475295232,1475297279,SK
1475297280,1475299327,DK
1475299328,1475301375,PL
1475301376,1475303423,LT
@@ -46500,11 +47275,11 @@
1475637480,1475637487,JE
1475637488,1475637503,GB
1475637504,1475638783,JE
-1475638784,1475639182,GB
+1475638784,1475639039,GB
+1475639040,1475639047,JE
+1475639048,1475639182,GB
1475639183,1475639183,JE
-1475639184,1475639199,GB
-1475639200,1475639207,JE
-1475639208,1475639216,GB
+1475639184,1475639216,GB
1475639217,1475639223,JE
1475639224,1475639263,GB
1475639264,1475639271,BB
@@ -46517,7 +47292,9 @@
1475639528,1475639543,JE
1475639544,1475639595,GB
1475639596,1475639599,JE
-1475639600,1475639807,GB
+1475639600,1475639775,GB
+1475639776,1475639783,JE
+1475639784,1475639807,GB
1475639808,1475641343,JE
1475641344,1475657727,UA
1475657728,1475674111,SK
@@ -46539,9 +47316,13 @@
1475727616,1475727623,FI
1475727624,1475727631,GB
1475727632,1475727639,FI
-1475727640,1475729087,GB
+1475727640,1475727807,GB
+1475727808,1475727871,FI
+1475727872,1475729087,GB
1475729088,1475729103,DE
-1475729104,1475729407,GB
+1475729104,1475729151,GB
+1475729152,1475729215,AT
+1475729216,1475729407,GB
1475729408,1475731455,UA
1475731456,1475739647,GB
1475739648,1475756031,BG
@@ -46553,6 +47334,7 @@
1475837952,1475846143,GB
1475846144,1475854335,IR
1475854336,1475862527,AT
+1475862528,1475864575,FR
1475864576,1475866623,IT
1475866624,1475868671,GB
1475868672,1475870719,BG
@@ -46828,18 +47610,9 @@
1486317568,1486320383,RU
1486320384,1486320639,US
1486320640,1486321663,RU
-1486321664,1486321823,EU
-1486321824,1486321855,US
-1486321856,1486321887,NL
-1486321888,1486321919,US
-1486321920,1486323199,EU
-1486323200,1486323215,US
-1486323216,1486323231,NL
-1486323232,1486323239,GB
-1486323240,1486323447,EU
-1486323448,1486323455,GB
-1486323456,1486323711,EU
+1486321664,1486323711,EU
1486323712,1486325759,GB
+1486325760,1486327807,PL
1486327808,1486329855,CH
1486329856,1486331903,FR
1486331904,1486333951,NO
@@ -46891,7 +47664,9 @@
1489638656,1489638911,FR
1489638912,1489640703,IT
1489640704,1489640959,FR
-1489640960,1489642495,IT
+1489640960,1489641727,IT
+1489641728,1489641983,HK
+1489641984,1489642495,IT
1489642496,1489642751,FR
1489642752,1489644543,IT
1489644544,1489645055,A2
@@ -47038,19 +47813,21 @@
1489855520,1489855535,PL
1489855536,1489855543,DE
1489855544,1489855551,PL
-1489855552,1489855999,DE
+1489855552,1489855583,DE
+1489855584,1489855615,RU
+1489855616,1489855999,DE
1489856000,1489856031,PL
1489856032,1489856063,RU
1489856064,1489862655,DE
-1489862656,1489895423,RU
+1489862656,1489928191,RU
1489928192,1489960959,SE
1489960960,1489993727,HR
1489993728,1490026495,LU
1490026496,1490028543,US
1490028544,1490029055,UA
-1490029056,1490040847,NL
-1490040848,1490041599,UA
-1490041600,1490042879,NL
+1490029056,1490041087,NL
+1490041088,1490041343,UA
+1490041344,1490042879,NL
1490042880,1490049879,CZ
1490049880,1490049887,AT
1490049888,1490049919,CZ
@@ -47079,8 +47856,8 @@
1490196864,1490196895,ES
1490196896,1490196927,HU
1490196928,1490196959,IT
-1490196960,1490197247,IE
-1490197248,1490206719,GB
+1490196960,1490197503,IE
+1490197504,1490206719,GB
1490206720,1490223103,GE
1490223104,1490255871,GB
1490255872,1490272255,NL
@@ -47158,6 +47935,7 @@
1494294528,1494302719,RU
1494302720,1494310911,FI
1494310912,1494319103,LB
+1494319104,1494327295,IS
1494327296,1494335487,IT
1494335488,1494343679,ES
1494343680,1494351871,PL
@@ -47267,8 +48045,8 @@
1495153920,1495154175,TR
1495154176,1495154687,FR
1495154688,1495160063,EU
-1495160064,1495160095,NL
-1495160096,1495161599,EU
+1495160064,1495160319,NL
+1495160320,1495161599,EU
1495161600,1495161855,FR
1495161856,1495162367,EU
1495162368,1495162879,US
@@ -47307,7 +48085,7 @@
1495209984,1495212031,KZ
1495212032,1495214079,RU
1495214080,1495216127,CZ
-1495218176,1495220223,IT
+1495216128,1495220223,IT
1495220224,1495222271,PL
1495222272,1495224319,IT
1495224320,1495228415,RU
@@ -47563,9 +48341,7 @@
1502606336,1502609407,SI
1502609408,1502624030,DE
1502624031,1502624047,IR
-1502624048,1502624063,DE
-1502624064,1502624127,IR
-1502624128,1502625791,DE
+1502624048,1502625791,DE
1502625792,1502642175,SA
1502642176,1502658559,IR
1502658560,1502674943,AT
@@ -47606,16 +48382,15 @@
1502975264,1502975295,GB
1502975296,1502975311,FR
1502975312,1502975319,IE
-1502975320,1502975327,FR
-1502975328,1502975367,IE
+1502975320,1502975359,FR
+1502975360,1502975367,IE
1502975368,1502975383,FR
1502975384,1502975391,ES
1502975392,1502975423,FR
1502975424,1502975455,GB
1502975456,1502975487,IE
1502975488,1502975743,ES
-1502975744,1502975775,IE
-1502975776,1502975999,FR
+1502975744,1502975999,FR
1502976000,1502977055,US
1502977056,1502977151,FR
1502977152,1502979071,US
@@ -47640,7 +48415,9 @@
1502986256,1502986495,TR
1502986496,1502986511,DE
1502986512,1502986751,PL
-1502986752,1502987775,DE
+1502986752,1502987535,DE
+1502987536,1502987551,AE
+1502987552,1502987775,DE
1502987776,1502988031,TR
1502988032,1502989055,DE
1502989056,1502989567,TR
@@ -47792,7 +48569,9 @@
1503899336,1503899343,TH
1503899344,1503899351,DE
1503899352,1503899367,GR
-1503899368,1503908351,DE
+1503899368,1503899399,DE
+1503899400,1503899407,CH
+1503899408,1503908351,DE
1503908352,1503909375,IT
1503909376,1503920127,DE
1503920128,1503985663,HR
@@ -47877,10 +48656,10 @@
1505321832,1505321983,DE
1505321984,1505322287,AT
1505322288,1505322415,DE
-1505322416,1505322879,AT
-1505322880,1505324335,DE
-1505324336,1505324351,AT
-1505324352,1505324791,DE
+1505322416,1505322895,AT
+1505322896,1505324335,DE
+1505324336,1505324367,AT
+1505324368,1505324791,DE
1505324792,1505324799,AT
1505324800,1505325055,DE
1505325056,1505329151,AT
@@ -47972,7 +48751,11 @@
1505456000,1505456079,US
1505456080,1505456127,GB
1505456128,1505456255,US
-1505456256,1505456639,GB
+1505456256,1505456343,GB
+1505456344,1505456347,US
+1505456348,1505456351,GB
+1505456352,1505456367,US
+1505456368,1505456639,GB
1505456640,1505456895,US
1505456896,1505456927,GB
1505456928,1505456935,US
@@ -47990,7 +48773,9 @@
1505458528,1505458543,GB
1505458544,1505458559,US
1505458560,1505460223,GB
-1505460224,1505476607,CZ
+1505460224,1505478655,CZ
+1505478656,1505482751,DE
+1505482752,1505484799,LB
1505484800,1505492991,PL
1505492992,1505501183,NL
1505501184,1505509375,ME
@@ -48066,11 +48851,16 @@
1506427664,1506427679,GB
1506427680,1506428223,DE
1506428224,1506428239,US
-1506428240,1506437119,DE
+1506428240,1506436863,DE
+1506436864,1506436879,FR
+1506436880,1506437119,DE
1506437120,1506437503,US
1506437504,1506437551,DE
1506437552,1506437567,BG
-1506437568,1506437631,DE
+1506437568,1506437583,DE
+1506437584,1506437615,NL
+1506437616,1506437623,US
+1506437624,1506437631,DE
1506437632,1506437887,MU
1506437888,1506437903,CA
1506437904,1506437919,US
@@ -48100,7 +48890,9 @@
1506439464,1506439471,GB
1506439472,1506439571,DE
1506439572,1506439575,US
-1506439576,1506439935,DE
+1506439576,1506439579,DE
+1506439580,1506439583,NL
+1506439584,1506439935,DE
1506439936,1506440191,US
1506440192,1506440447,DE
1506440448,1506440575,US
@@ -48174,15 +48966,19 @@
1506445528,1506445703,FR
1506445704,1506445711,NL
1506445712,1506445719,GB
-1506445720,1506445759,FR
+1506445720,1506445727,FR
+1506445728,1506445735,GB
+1506445736,1506445759,FR
1506445760,1506445767,GB
1506445768,1506445815,FR
1506445816,1506445823,GB
1506445824,1506446143,FR
1506446144,1506446151,GB
1506446152,1506446335,FR
-1506446336,1506446591,NL
-1506446592,1506446735,GB
+1506446336,1506446599,NL
+1506446600,1506446623,GB
+1506446624,1506446719,NL
+1506446720,1506446735,GB
1506446736,1506447359,NL
1506447360,1506447423,IT
1506447424,1506447455,GB
@@ -48236,8 +49032,7 @@
1506452992,1506453247,AT
1506453248,1506453391,SE
1506453392,1506453399,ES
-1506453400,1506453407,GB
-1506453408,1506453415,SE
+1506453400,1506453415,SE
1506453416,1506453423,GB
1506453424,1506453439,SE
1506453440,1506453447,GB
@@ -48245,7 +49040,9 @@
1506453472,1506453487,GB
1506453488,1506453503,SE
1506453504,1506453759,DE
-1506453760,1506454015,FR
+1506453760,1506453823,FR
+1506453824,1506453839,GB
+1506453840,1506454015,FR
1506454016,1506454271,AT
1506454272,1506454527,ES
1506454528,1506454783,IT
@@ -48372,7 +49169,13 @@
1506767616,1506767679,NO
1506767680,1506768895,GE
1506768896,1506770943,AT
-1506770944,1506772017,NL
+1506770944,1506771468,NL
+1506771469,1506771469,US
+1506771470,1506771489,NL
+1506771490,1506771498,US
+1506771499,1506771645,NL
+1506771646,1506771655,US
+1506771656,1506772017,NL
1506772018,1506772018,US
1506772019,1506772143,NL
1506772144,1506772145,TR
@@ -48380,8 +49183,8 @@
1506772148,1506772176,TR
1506772177,1506772323,NL
1506772324,1506772325,IR
-1506772326,1506772327,RO
-1506772328,1506772361,NL
+1506772326,1506772326,RO
+1506772327,1506772361,NL
1506772362,1506772364,IR
1506772365,1506772938,NL
1506772939,1506772939,IR
@@ -48400,9 +49203,7 @@
1506795520,1506797567,IE
1506797568,1506799615,ES
1506799616,1506801663,LV
-1506801664,1506802767,DE
-1506802768,1506802775,DK
-1506802776,1506802831,DE
+1506801664,1506802831,DE
1506802832,1506802839,CH
1506802840,1506803135,DE
1506803136,1506803151,CH
@@ -48643,7 +49444,9 @@
1509900288,1509916671,RU
1509916672,1509933055,GB
1509933056,1509949439,US
-1509949440,1515467007,FR
+1509949440,1515241759,FR
+1515241760,1515241791,GB
+1515241792,1515467007,FR
1515467008,1515467263,ES
1515467264,1515467519,FR
1515467520,1515468031,US
@@ -48916,6 +49719,7 @@
1533421568,1533423615,NL
1533423616,1533425663,IT
1533425664,1533429759,GB
+1533429760,1533431807,RU
1533431808,1533433855,IE
1533433856,1533435903,DK
1533435904,1533437951,CZ
@@ -48984,7 +49788,9 @@
1533542400,1534066687,GB
1534066688,1534129151,AT
1534129152,1534129407,A2
-1534129408,1534328831,AT
+1534129408,1534202591,AT
+1534202592,1534202595,ES
+1534202596,1534328831,AT
1534328832,1534459903,ES
1534459904,1534482091,AT
1534482092,1534482095,GB
@@ -49071,8 +49877,10 @@
1534714880,1534714895,PL
1534714896,1534714911,FR
1534714912,1534714927,DE
-1534714928,1534714943,FR
-1534714944,1534714975,DE
+1534714928,1534714931,BE
+1534714932,1534714935,DE
+1534714936,1534714939,GB
+1534714940,1534714975,DE
1534714976,1534715039,FR
1534715040,1534715055,GB
1534715056,1534715071,PL
@@ -49093,7 +49901,7 @@
1534715300,1534715303,FR
1534715304,1534715307,ES
1534715308,1534715311,DE
-1534715312,1534715315,FR
+1534715312,1534715315,PL
1534715316,1534715319,ES
1534715320,1534715327,PL
1534715328,1534715359,FR
@@ -49143,14 +49951,14 @@
1534715920,1534715935,ES
1534715936,1534715951,PL
1534715952,1534715999,FR
-1534716000,1534716007,PL
+1534716000,1534716007,NL
1534716008,1534716047,FR
1534716048,1534716063,GB
1534716064,1534716127,FR
1534716128,1534716143,ES
1534716144,1534716159,PL
1534716160,1534716163,IT
-1534716164,1534716167,FR
+1534716164,1534716167,FI
1534716168,1534716175,IE
1534716176,1534716191,FR
1534716192,1534716223,ES
@@ -49160,7 +49968,10 @@
1534716320,1534716359,PL
1534716360,1534716363,CZ
1534716364,1534716367,GB
-1534716368,1534716391,FR
+1534716368,1534716375,BE
+1534716376,1534716379,CH
+1534716380,1534716383,PL
+1534716384,1534716391,FR
1534716392,1534716395,ES
1534716396,1534716399,GB
1534716400,1534716431,FR
@@ -49181,7 +49992,12 @@
1534716752,1534716759,PL
1534716760,1534716763,DE
1534716764,1534716767,ES
-1534716768,1534716823,FR
+1534716768,1534716799,FR
+1534716800,1534716803,DE
+1534716804,1534716807,PL
+1534716808,1534716811,NL
+1534716812,1534716815,DE
+1534716816,1534716823,FR
1534716824,1534716831,GB
1534716832,1534716879,FR
1534716880,1534716895,BE
@@ -49191,7 +50007,9 @@
1534716928,1534716943,DE
1534716944,1534716991,FR
1534716992,1534717007,DE
-1534717008,1534717023,FR
+1534717008,1534717011,PL
+1534717012,1534717019,FR
+1534717020,1534717023,DE
1534717024,1534717055,PL
1534717056,1534717071,GB
1534717072,1534717103,FR
@@ -49240,7 +50058,9 @@
1534717740,1534717743,PL
1534717744,1534717751,FR
1534717752,1534717759,BE
-1534717760,1534717783,FR
+1534717760,1534717767,FR
+1534717768,1534717771,IT
+1534717772,1534717783,FR
1534717784,1534717787,GB
1534717788,1534717791,DE
1534717792,1534717823,FR
@@ -49256,13 +50076,18 @@
1534717928,1534717931,DE
1534717932,1534717935,FR
1534717936,1534717951,IT
-1534717952,1534717967,BE
+1534717952,1534717955,DE
+1534717956,1534717959,BE
+1534717960,1534717963,PT
+1534717964,1534717967,CH
1534717968,1534717983,IT
1534717984,1534717987,PL
1534717988,1534717991,DE
1534717992,1534717995,NL
1534717996,1534717999,GB
-1534718000,1534718015,FR
+1534718000,1534718007,ES
+1534718008,1534718011,PL
+1534718012,1534718015,FR
1534718016,1534718031,BE
1534718032,1534718063,FR
1534718064,1534718079,IT
@@ -49342,7 +50167,10 @@
1534719704,1534719711,GB
1534719712,1534719759,FR
1534719760,1534719775,IT
-1534719776,1534719799,FR
+1534719776,1534719783,PL
+1534719784,1534719787,FR
+1534719788,1534719791,DE
+1534719792,1534719799,FR
1534719800,1534719803,ES
1534719804,1534719807,GB
1534719808,1534719811,PL
@@ -49352,9 +50180,7 @@
1534719824,1534719827,PT
1534719828,1534719831,FR
1534719832,1534719839,PL
-1534719840,1534719871,FR
-1534719872,1534719887,PL
-1534719888,1534719951,FR
+1534719840,1534719951,FR
1534719952,1534719967,DE
1534719968,1534719983,PL
1534719984,1534720003,FR
@@ -49362,9 +50188,7 @@
1534720008,1534720015,PL
1534720016,1534720023,ES
1534720024,1534720027,PL
-1534720028,1534720031,ES
-1534720032,1534720047,FR
-1534720048,1534720063,ES
+1534720028,1534720063,ES
1534720064,1534720079,IT
1534720080,1534720095,GB
1534720096,1534720111,FR
@@ -49383,7 +50207,11 @@
1534720300,1534720351,FR
1534720352,1534720367,ES
1534720368,1534720383,PL
-1534720384,1534720431,FR
+1534720384,1534720399,FR
+1534720400,1534720403,LT
+1534720404,1534720411,GB
+1534720412,1534720415,IE
+1534720416,1534720431,FR
1534720432,1534720435,DE
1534720436,1534720439,FR
1534720440,1534720443,GB
@@ -49414,7 +50242,8 @@
1534720744,1534720747,IE
1534720748,1534720767,FR
1534720768,1534720783,ES
-1534720784,1534720791,PL
+1534720784,1534720787,FR
+1534720788,1534720791,DE
1534720792,1534720795,IT
1534720796,1534720799,ES
1534720800,1534720815,PL
@@ -49445,8 +50274,8 @@
1534721088,1534721103,ES
1534721104,1534721107,PL
1534721108,1534721111,ES
-1534721112,1534721115,FR
-1534721116,1534721119,BE
+1534721112,1534721115,DE
+1534721116,1534721119,FR
1534721120,1534721135,IT
1534721136,1534721159,FR
1534721160,1534721163,ES
@@ -49483,7 +50312,8 @@
1534721600,1534721619,ES
1534721620,1534721627,PL
1534721628,1534721631,NL
-1534721632,1534721663,FR
+1534721632,1534721647,ES
+1534721648,1534721663,FR
1534721664,1534721679,ES
1534721680,1534721743,FR
1534721744,1534721747,PL
@@ -49499,7 +50329,7 @@
1534721888,1534721903,FR
1534721904,1534721919,DE
1534721920,1534721935,FR
-1534721936,1534721943,IT
+1534721936,1534721943,CH
1534721944,1534721951,IE
1534721952,1534721955,FR
1534721956,1534721959,PL
@@ -49645,7 +50475,7 @@
1536118784,1536122879,DE
1536122880,1536126975,AT
1536126976,1536131071,DK
-1536131072,1536143359,RU
+1536131072,1536139263,RU
1536143360,1536147455,GB
1536147456,1536151551,IT
1536151552,1536155647,RS
@@ -49719,7 +50549,7 @@
1536663360,1536663423,DE
1536663424,1536663551,KW
1536663552,1536667647,SA
-1536671744,1536675839,RU
+1536667648,1536675839,RU
1536675840,1536679935,GB
1536679936,1536684031,LB
1536684032,1536688127,GB
@@ -49749,8 +50579,8 @@
1538897720,1538897727,GB
1538897728,1538897735,NL
1538897736,1538897919,FR
-1538897920,1538898175,DE
-1538898176,1538899967,FR
+1538897920,1538898431,DE
+1538898432,1538899967,FR
1538899968,1538904031,SI
1538904032,1538904039,BH
1538904040,1538908159,SI
@@ -49875,6 +50705,7 @@
1539227648,1539229695,FI
1539229696,1539231743,DE
1539231744,1539233791,BE
+1539233792,1539235839,LU
1539235840,1539237887,DE
1539237888,1539239935,RU
1539239936,1539244031,DE
@@ -49896,6 +50727,7 @@
1539314688,1539315711,RU
1539315712,1539316735,UA
1539316736,1539317759,SE
+1539317760,1539318783,CZ
1539318784,1539319807,NL
1539319808,1539320831,DE
1539320832,1539321855,UA
@@ -49950,6 +50782,7 @@
1539379200,1539380223,EU
1539380224,1539381247,CH
1539381248,1539382271,RS
+1539382272,1539383295,RO
1539383296,1539384319,UA
1539384320,1539385343,RU
1539385344,1539385855,PL
@@ -50077,6 +50910,7 @@
1539482112,1539482623,UA
1539482624,1539483135,RU
1539483136,1539483647,ES
+1539483648,1539484159,UA
1539484160,1539484671,GB
1539484672,1539485695,RU
1539485696,1539486207,RO
@@ -50117,7 +50951,7 @@
1539506688,1539507199,UA
1539507200,1539508223,RO
1539508224,1539508735,NO
-1539508736,1539509759,UA
+1539508736,1539509247,UA
1539509760,1539510271,RO
1539510272,1539510783,RU
1539510784,1539511295,LU
@@ -50172,8 +51006,7 @@
1539536384,1539536895,NL
1539536896,1539537407,UA
1539537408,1539537919,GB
-1539537920,1539539455,RU
-1539539968,1539540479,RU
+1539537920,1539540479,RU
1539540480,1539540991,PL
1539540992,1539541503,RU
1539541504,1539542015,TR
@@ -50249,7 +51082,9 @@
1539589120,1539590143,GB
1539590144,1539591167,RU
1539591168,1539592191,UZ
-1539592192,1539598335,UA
+1539592192,1539593215,UA
+1539593216,1539594239,RU
+1539594240,1539598335,UA
1539598336,1539599359,NL
1539600384,1539601407,HU
1539601408,1539602431,GB
@@ -50536,7 +51371,6 @@
1539757568,1539757823,SI
1539757824,1539758079,UA
1539758080,1539758335,HR
-1539758336,1539758591,EU
1539758592,1539758847,NL
1539758848,1539759103,BA
1539759104,1539759359,DK
@@ -50565,6 +51399,7 @@
1539764992,1539765247,BE
1539765248,1539765503,GB
1539765504,1539766015,PL
+1539766016,1539766271,UA
1539766272,1539766527,PL
1539766528,1539766783,UA
1539766784,1539767039,DE
@@ -50623,6 +51458,7 @@
1539780608,1539780863,PL
1539780864,1539781119,RO
1539781120,1539781375,NL
+1539781376,1539781631,PL
1539781632,1539781887,HU
1539781888,1539782143,IL
1539782144,1539782399,UA
@@ -50645,6 +51481,7 @@
1539786752,1539787007,HU
1539787008,1539787263,TR
1539787264,1539787519,IE
+1539787520,1539787775,DE
1539787776,1539788031,CH
1539788032,1539788287,HR
1539788288,1539788543,GB
@@ -50924,6 +51761,7 @@
1539975168,1539976191,DE
1539976192,1539977215,RU
1539977216,1539978239,DE
+1539978240,1539979263,CZ
1539979264,1539980287,UA
1539980288,1539981311,VG
1539981312,1539982335,SI
@@ -50964,7 +51802,7 @@
1540025344,1540026367,GB
1540026368,1540028415,UA
1540028416,1540029439,ES
-1540029440,1540030463,RU
+1540029440,1540031487,RU
1540031488,1540032511,UA
1540032512,1540033535,RU
1540033536,1540034559,UA
@@ -51015,7 +51853,7 @@
1540081664,1540082687,DE
1540082688,1540083711,NO
1540083712,1540084735,RU
-1540084736,1540085759,LU
+1540084736,1540085759,NL
1540085760,1540087807,PL
1540087808,1540092927,RU
1540092928,1540094975,PL
@@ -51035,6 +51873,7 @@
1540118528,1540119551,PL
1540119552,1540120575,UA
1540120576,1540124671,RU
+1540124672,1540125695,UA
1540125696,1540126719,FR
1540126720,1540127743,UA
1540127744,1540128767,GB
@@ -51109,6 +51948,7 @@
1540206592,1540208639,RU
1540208640,1540209663,NO
1540209664,1540211711,RU
+1540211712,1540212735,RO
1540212736,1540213759,RU
1540213760,1540214783,UA
1540214784,1540215807,RU
@@ -51803,6 +52643,7 @@
1540488960,1540489215,RO
1540489216,1540491263,RU
1540491264,1540492287,UA
+1540492288,1540493311,PL
1540493312,1540494335,CZ
1540494336,1540495359,UA
1540495360,1540496383,RU
@@ -51813,12 +52654,14 @@
1540502528,1540503551,RU
1540503552,1540504575,NL
1540504576,1540505599,SE
+1540505600,1540506623,RO
1540506624,1540507647,GB
1540507648,1540508671,RU
1540508672,1540509695,UA
1540509696,1540510719,RO
1540510720,1540511743,RU
1540511744,1540512767,BG
+1540512768,1540513791,RU
1540513792,1540514815,UA
1540514816,1540515839,GB
1540515840,1540516863,RU
@@ -51907,6 +52750,7 @@
1540621824,1540622335,RU
1540622336,1540622591,KW
1540622592,1540622847,PL
+1540622848,1540623103,RU
1540623104,1540623359,SE
1540623360,1540623615,GB
1540623616,1540623871,BG
@@ -51949,7 +52793,7 @@
1540633088,1540633343,RU
1540633344,1540633599,CH
1540633600,1540633855,RO
-1540633856,1540634367,GB
+1540634112,1540634367,GB
1540634368,1540634623,FR
1540634624,1540634879,UA
1540634880,1540635135,RU
@@ -52015,6 +52859,7 @@
1540651520,1540651775,MK
1540651776,1540652031,RU
1540652032,1540652543,UA
+1540652544,1540652799,TR
1540652800,1540653055,EU
1540653056,1540653311,FR
1540653312,1540653567,DK
@@ -52039,7 +52884,6 @@
1540659200,1540659455,FR
1540659456,1540659967,UA
1540659968,1540660223,PL
-1540660224,1540660479,UA
1540660480,1540660735,FR
1540660736,1540660991,UA
1540660992,1540661247,RO
@@ -52208,7 +53052,7 @@
1540706304,1540706559,SI
1540706560,1540706815,GB
1540706816,1540707071,FR
-1540707072,1540707583,GB
+1540707328,1540707583,GB
1540707584,1540707839,NL
1540707840,1540708095,MD
1540708096,1540708351,RU
@@ -52245,6 +53089,7 @@
1540717312,1540717823,PL
1540717824,1540718079,UA
1540718080,1540718335,RU
+1540718336,1540718591,NO
1540718592,1540718847,CH
1540718848,1540719103,IT
1540719104,1540719359,RU
@@ -52414,7 +53259,7 @@
1540817920,1540818943,NL
1540818944,1540819967,UA
1540819968,1540820991,CZ
-1540820992,1540822015,RU
+1540820992,1540823039,RU
1540823040,1540824063,UA
1540824064,1540825087,RU
1540825088,1540826111,PL
@@ -52506,7 +53351,7 @@
1540893952,1540894207,DE
1540894208,1540894463,RU
1540894464,1540894719,RO
-1540894976,1540895487,RU
+1540894720,1540895487,RU
1540895488,1540895743,PL
1540895744,1540895999,RO
1540896000,1540896255,RU
@@ -52567,6 +53412,7 @@
1540911104,1540911359,GB
1540911360,1540911615,NL
1540911616,1540911871,RU
+1540911872,1540912127,PL
1540912128,1540912383,GB
1540912384,1540912639,PT
1540912640,1540912895,DK
@@ -52634,7 +53480,7 @@
1540930560,1540930815,KW
1540930816,1540931071,KZ
1540931072,1540931327,EU
-1540931328,1540931583,PL
+1540931328,1540931839,PL
1540931840,1540932095,GB
1540932096,1540932351,PL
1540932352,1540932607,FR
@@ -52880,6 +53726,7 @@
1541027840,1541028863,RU
1541028864,1541029887,PL
1541029888,1541030911,UA
+1541030912,1541031935,PL
1541031936,1541032959,UA
1541032960,1541033983,PL
1541033984,1541035007,BG
@@ -53076,7 +53923,6 @@
1541171968,1541172223,SI
1541172224,1541172479,GR
1541172480,1541172735,RU
-1541172736,1541172991,RO
1541172992,1541173247,BE
1541173248,1541173503,RU
1541173504,1541173759,UA
@@ -53264,7 +54110,7 @@
1541236736,1541237247,DE
1541237248,1541237759,RU
1541237760,1541238271,CZ
-1541238784,1541239295,SK
+1541238272,1541239295,SK
1541239296,1541239807,PL
1541239808,1541240319,RU
1541240320,1541240831,CH
@@ -53334,6 +54180,7 @@
1541275136,1541275647,FR
1541275648,1541276671,UA
1541276672,1541277695,RS
+1541277696,1541278719,GB
1541278720,1541280767,UA
1541280768,1541281791,BG
1541281792,1541282815,PL
@@ -53575,7 +54422,7 @@
1541391872,1541392127,DE
1541392128,1541392383,RU
1541392384,1541392639,RO
-1541392640,1541392895,TR
+1541392640,1541392895,MD
1541392896,1541393151,DE
1541393152,1541393407,GB
1541393408,1541393663,DE
@@ -53731,6 +54578,7 @@
1541467136,1541467647,PL
1541467648,1541468159,SI
1541468160,1541468671,ES
+1541468672,1541469183,NL
1541469184,1541469695,SE
1541469696,1541470207,LV
1541470208,1541470719,NL
@@ -53802,6 +54650,7 @@
1541547520,1541548543,PL
1541548544,1541549567,UA
1541549568,1541550079,DE
+1541550080,1541550591,RU
1541550592,1541551103,PL
1541551104,1541552127,RO
1541552128,1541553151,UA
@@ -53832,7 +54681,9 @@
1541569536,1541570559,NL
1541570560,1541571583,RU
1541571584,1541572607,UA
-1541572608,1541574655,RU
+1541572608,1541573119,RU
+1541573120,1541573631,UA
+1541573632,1541574655,RU
1541574656,1541575167,DK
1541575168,1541575423,PL
1541575424,1541575679,IT
@@ -53849,6 +54700,7 @@
1541583360,1541583615,RU
1541583616,1541583871,GE
1541583872,1541584127,SE
+1541584128,1541584383,GB
1541584384,1541584895,BE
1541584896,1541585151,DE
1541585152,1541585663,RU
@@ -53861,6 +54713,7 @@
1541589248,1541589503,UA
1541589504,1541590015,CH
1541590016,1541590527,RU
+1541590528,1541590783,GB
1541590784,1541591039,UA
1541591040,1541592063,RU
1541592064,1541592575,UA
@@ -53872,6 +54725,7 @@
1541595648,1541596159,BG
1541596160,1541597695,PL
1541597696,1541597951,RU
+1541597952,1541598207,AM
1541598208,1541599231,PL
1541599232,1541600255,RS
1541600256,1541600511,HR
@@ -53936,6 +54790,7 @@
1541633024,1541634303,PL
1541634304,1541634559,MD
1541634560,1541635071,PL
+1541635072,1541636095,GB
1541636096,1541636863,AT
1541636864,1541637119,RO
1541637120,1541637631,PL
@@ -53951,6 +54806,7 @@
1541643264,1541644287,PL
1541644288,1541645311,RU
1541645312,1541645823,IL
+1541645824,1541646079,RO
1541646080,1541646335,PL
1541646336,1541646847,RU
1541646848,1541647359,NO
@@ -54001,6 +54857,7 @@
1541674496,1541675007,KG
1541675008,1541675519,IE
1541675520,1541676031,RU
+1541676032,1541676287,PL
1541676288,1541676543,RO
1541676544,1541677055,RU
1541677056,1541678079,PL
@@ -54049,6 +54906,7 @@
1541704704,1541706239,RO
1541706240,1541706751,UA
1541706752,1541707263,RU
+1541707264,1541707519,CH
1541707520,1541707775,NL
1541707776,1541708799,RU
1541708800,1541709823,PL
@@ -54088,6 +54946,7 @@
1541729536,1541729791,PL
1541729792,1541730303,RU
1541730304,1541730815,ES
+1541730816,1541731071,GB
1541731072,1541731327,DE
1541731328,1541731839,SK
1541731840,1541732351,RU
@@ -54224,6 +55083,7 @@
1541800960,1541801471,FI
1541801472,1541801983,BG
1541801984,1541802495,PL
+1541802496,1541803007,RU
1541803008,1541804031,LT
1541804032,1541804287,GB
1541804288,1541804543,PL
@@ -54354,10 +55214,31 @@
1541864192,1541864447,GB
1541864448,1541864959,RU
1541864960,1541865471,AL
-1541865472,1541866495,SE
1541866496,1541867263,NL
1541867264,1541867519,RO
1541867520,1541867775,RU
+1541867776,1541868031,PL
+1541868032,1541868287,MT
+1541868288,1541868543,AE
+1541868544,1541869567,PL
+1541869568,1541870079,RU
+1541870080,1541871103,PL
+1541871104,1541871359,AT
+1541871616,1541872639,PL
+1541872640,1541873663,CZ
+1541873664,1541874175,PL
+1541874176,1541874687,RU
+1541874688,1541875711,PL
+1541875712,1541876735,UA
+1541876736,1541877247,PL
+1541877248,1541877503,GB
+1541877504,1541877759,RU
+1541877760,1541878783,RO
+1541878784,1541879295,PL
+1541879296,1541879807,UA
+1541879808,1541880831,UZ
+1541880832,1541881343,PL
+1541881344,1541881599,IT
1543503872,1545601023,GB
1545601024,1545673167,SE
1545673168,1545673175,FI
@@ -54737,7 +55618,9 @@
1547777120,1547777127,IT
1547777128,1548157119,NL
1548157120,1548157183,DE
-1548157184,1548222463,NL
+1548157184,1548157951,NL
+1548157952,1548158207,SE
+1548158208,1548222463,NL
1548222464,1548746751,DE
1548746752,1549271039,RO
1549271040,1549795327,FR
@@ -54747,7 +55630,8 @@
1550319616,1550581759,CH
1550581760,1550843903,NL
1550843904,1550974975,UA
-1550974976,1550996223,RO
+1550974976,1550975231,MD
+1550975232,1550996223,RO
1550996224,1550996479,CH
1550996480,1551007743,RO
1551007744,1551106047,MD
@@ -54916,9 +55800,7 @@
1566097408,1566101503,HU
1566101504,1566105599,RU
1566105600,1566109695,DE
-1566109696,1566111231,CH
-1566111232,1566111487,FR
-1566111488,1566113791,CH
+1566109696,1566113791,CH
1566113792,1566117887,DE
1566117888,1566121983,TR
1566121984,1566126079,NO
@@ -55021,28 +55903,66 @@
1566396416,1566398463,GB
1566398464,1566400511,RU
1566400512,1566400575,NO
-1566400576,1566400607,NL
-1566400608,1566400639,GB
+1566400576,1566400639,GB
1566400640,1566400671,NO
1566400672,1566400703,DE
1566400704,1566400735,NL
-1566400736,1566400832,NO
-1566400833,1566400895,GB
-1566400896,1566401023,NO
+1566400736,1566400863,NO
+1566400864,1566400871,GB
+1566400872,1566400903,NO
+1566400904,1566400907,DE
+1566400908,1566400911,GB
+1566400912,1566400915,GE
+1566400916,1566400919,NO
+1566400920,1566400923,NE
+1566400924,1566400943,NO
+1566400944,1566400955,NE
+1566400956,1566400975,NO
+1566400976,1566400979,GB
+1566400980,1566400983,GE
+1566400984,1566400987,NE
+1566400988,1566401023,NO
1566401024,1566401055,US
1566401056,1566401087,NO
1566401088,1566401215,US
1566401216,1566401279,NO
-1566401280,1566401535,US
+1566401280,1566401327,US
+1566401328,1566401399,NO
+1566401400,1566401463,US
+1566401464,1566401467,NO
+1566401468,1566401503,US
+1566401504,1566401507,NO
+1566401508,1566401535,US
1566401536,1566401599,IN
-1566401600,1566401663,CN
-1566401664,1566401727,SG
-1566401728,1566401791,AU
+1566401600,1566401631,HK
+1566401632,1566401663,NO
+1566401664,1566401695,SG
+1566401696,1566401727,NO
+1566401728,1566401759,AU
+1566401760,1566401791,NO
1566401792,1566401856,SI
-1566401857,1566401919,HK
-1566401920,1566401983,NO
-1566401984,1566402047,AU
-1566402048,1566402559,NO
+1566401857,1566401887,NO
+1566401888,1566401919,US
+1566401920,1566401967,NO
+1566401968,1566401975,HK
+1566401976,1566401987,NO
+1566401988,1566401991,HK
+1566401992,1566401999,SG
+1566402000,1566402003,AU
+1566402004,1566402011,NO
+1566402012,1566402031,HK
+1566402032,1566402111,NO
+1566402112,1566402143,HK
+1566402144,1566402175,NO
+1566402176,1566402199,US
+1566402200,1566402207,NO
+1566402208,1566402215,US
+1566402216,1566402223,NO
+1566402224,1566402239,US
+1566402240,1566402255,NO
+1566402256,1566402303,US
+1566402304,1566402559,NO
+1566402560,1566404607,IQ
1566404608,1566406655,ES
1566406656,1566408703,NL
1566408704,1566410751,GB
@@ -55078,8 +55998,8 @@
1566470144,1566470159,IE
1566470160,1566470171,GB
1566470172,1566470239,IE
-1566470240,1566470343,GB
-1566470344,1566470351,IE
+1566470240,1566470303,GB
+1566470304,1566470351,IE
1566470352,1566470367,GB
1566470368,1566470511,IE
1566470512,1566470527,GB
@@ -55281,6 +56201,7 @@
1570275328,1570308095,BG
1570308096,1570340863,CZ
1570340864,1570373631,RU
+1570373632,1570406399,NL
1570406400,1570439167,PL
1570439168,1570471935,TR
1570471936,1570480895,BG
@@ -55416,8 +56337,8 @@
1570667232,1570667247,FR
1570667248,1570667263,SE
1570667264,1570667267,ES
-1570667268,1570667279,SE
-1570667280,1570667295,ES
+1570667268,1570667283,SE
+1570667284,1570667295,ES
1570667296,1570667327,GB
1570667328,1570667335,SE
1570667336,1570667339,GB
@@ -55575,6 +56496,7 @@
1572028416,1572044799,RU
1572044800,1572061183,IT
1572061184,1572077567,PL
+1572077568,1572093951,RU
1572110336,1572126719,RU
1572126720,1572143103,UA
1572143104,1572159487,DE
@@ -55679,7 +56601,9 @@
1572542088,1572542111,GB
1572542112,1572542119,PL
1572542120,1572542127,ES
-1572542128,1572542207,GB
+1572542128,1572542151,GB
+1572542152,1572542159,DE
+1572542160,1572542207,GB
1572542208,1572542463,FR
1572542464,1572544511,IT
1572544512,1572546559,IQ
@@ -55687,6 +56611,7 @@
1572548608,1572550655,NL
1572550656,1572552703,DE
1572552704,1572554751,TR
+1572554752,1572556799,RU
1572556800,1572558847,NO
1572558848,1572560895,IT
1572560896,1572562943,RU
@@ -55708,7 +56633,9 @@
1572587520,1572589567,TR
1572589568,1572591615,CH
1572591616,1572593663,NL
-1572593664,1572595711,GB
+1572593664,1572594687,GB
+1572594688,1572594943,FR
+1572594944,1572595711,GB
1572595712,1572597759,DE
1572597760,1572599807,RS
1572599808,1572601855,DE
@@ -55720,6 +56647,7 @@
1572612096,1572614143,RU
1572614144,1572616191,ES
1572616192,1572618239,CH
+1572618240,1572620287,NL
1572620288,1572620415,CH
1572620416,1572620431,CZ
1572620432,1572620559,CH
@@ -55746,21 +56674,13 @@
1572661248,1572663295,NO
1572663296,1572665343,DE
1572665344,1572667391,NL
-1572667392,1572667903,GB
-1572667904,1572667927,SA
-1572667928,1572668303,GB
-1572668304,1572668311,SA
-1572668312,1572668415,GB
-1572668416,1572668431,SA
-1572668432,1572668463,GB
-1572668464,1572668471,SA
-1572668472,1572668639,GB
-1572668640,1572668647,SA
-1572668648,1572668655,GB
+1572667392,1572668655,GB
1572668656,1572668671,CY
1572668672,1572668703,GB
1572668704,1572668711,CY
-1572668712,1572669439,GB
+1572668712,1572668719,GB
+1572668720,1572668727,CY
+1572668728,1572669439,GB
1572669440,1572673535,RU
1572673536,1572675583,AT
1572675584,1572677631,ES
@@ -55950,12 +56870,18 @@
1578590692,1578590695,DE
1578590696,1578590699,FR
1578590700,1578590735,PL
-1578590736,1578590799,FR
+1578590736,1578590787,FR
+1578590788,1578590791,LT
+1578590792,1578590795,NL
+1578590796,1578590799,IT
1578590800,1578590815,ES
1578590816,1578590831,GB
1578590832,1578590839,FR
1578590840,1578590847,PL
-1578590848,1578590879,FR
+1578590848,1578590851,DE
+1578590852,1578590855,FR
+1578590856,1578590859,GB
+1578590860,1578590879,FR
1578590880,1578590911,PL
1578590912,1578590927,GB
1578590928,1578590935,DE
@@ -56072,7 +56998,9 @@
1578592544,1578592559,FR
1578592560,1578592575,NL
1578592576,1578592591,GB
-1578592592,1578592687,FR
+1578592592,1578592607,FR
+1578592608,1578592623,IE
+1578592624,1578592687,FR
1578592688,1578592695,DE
1578592696,1578592719,ES
1578592720,1578592735,CH
@@ -56179,9 +57107,9 @@
1578594172,1578594191,FR
1578594192,1578594207,IT
1578594208,1578594211,DE
-1578594212,1578594223,PL
-1578594224,1578594255,FR
-1578594256,1578594271,GB
+1578594212,1578594239,PL
+1578594240,1578594255,FR
+1578594256,1578594271,IE
1578594272,1578594303,PL
1578594304,1578594307,GB
1578594308,1578594311,FI
@@ -56191,7 +57119,7 @@
1578594336,1578594355,GB
1578594356,1578594359,FR
1578594360,1578594363,PT
-1578594364,1578594367,IT
+1578594364,1578594367,ES
1578594368,1578594375,FR
1578594376,1578594383,PT
1578594384,1578594399,FR
@@ -56265,8 +57193,8 @@
1578595440,1578595447,FR
1578595448,1578595455,ES
1578595456,1578595459,DE
-1578595460,1578595463,PL
-1578595464,1578595487,FR
+1578595460,1578595467,PL
+1578595468,1578595487,FR
1578595488,1578595503,DE
1578595504,1578595519,PL
1578595520,1578595535,FR
@@ -56300,7 +57228,8 @@
1578595996,1578596095,FR
1578596096,1578596099,DE
1578596100,1578596103,GB
-1578596104,1578596111,FR
+1578596104,1578596107,PL
+1578596108,1578596111,ES
1578596112,1578596115,DE
1578596116,1578596119,FR
1578596120,1578596123,PT
@@ -56431,7 +57360,8 @@
1578612304,1578612319,DE
1578612320,1578612383,FR
1578612384,1578612415,PL
-1578612416,1578612623,FR
+1578612416,1578612607,FR
+1578612608,1578612623,PT
1578612624,1578612639,CH
1578612640,1578612671,PL
1578612672,1578612687,ES
@@ -56457,7 +57387,8 @@
1578613712,1578613719,BE
1578613720,1578613723,ES
1578613724,1578613727,IT
-1578613728,1578613743,NL
+1578613728,1578613739,PL
+1578613740,1578613743,FR
1578613744,1578613751,ES
1578613752,1578613759,NL
1578613760,1578613775,DE
@@ -56595,7 +57526,9 @@
1583632384,1583636479,RU
1583636480,1583640575,MK
1583640576,1583644671,NL
-1583644672,1583648767,DE
+1583644672,1583646463,DE
+1583646464,1583646719,GB
+1583646720,1583648767,DE
1583648768,1583652863,CH
1583652864,1583656959,FR
1583656960,1583665151,RU
@@ -56682,7 +57615,9 @@
1583815712,1583815727,US
1583815728,1583815807,NL
1583815808,1583815935,US
-1583815936,1583816703,NL
+1583815936,1583816191,GB
+1583816192,1583816255,DE
+1583816256,1583816703,NL
1583816704,1583819007,TR
1583819008,1583819136,GB
1583819137,1583820799,TR
@@ -56741,7 +57676,7 @@
1585231360,1585231615,NL
1585231616,1585231871,RU
1585231872,1585233919,CZ
-1585235968,1585238015,RU
+1585233920,1585238015,RU
1585238016,1585240063,DE
1585240064,1585241087,FR
1585241088,1585242111,MQ
@@ -56949,7 +57884,9 @@
1586411520,1586411775,GB
1586411776,1586412287,US
1586412288,1586412543,HK
-1586412544,1586413567,GB
+1586412544,1586412799,GB
+1586412800,1586413055,US
+1586413056,1586413567,GB
1586413568,1586415615,IT
1586415616,1586416255,ES
1586416256,1586417663,AD
@@ -57099,6 +58036,7 @@
1590132992,1590134783,GB
1590134784,1590136831,ES
1590136832,1590138879,GB
+1590138880,1590140927,FR
1590140928,1590142975,UA
1590142976,1590145023,AT
1590145024,1590147071,HU
@@ -57203,6 +58141,7 @@
1592281088,1592283135,UA
1592283136,1592285183,GR
1592285184,1592287231,RU
+1592287232,1592289279,RO
1592289280,1592291327,RU
1592291328,1592293375,NL
1592293376,1592295423,LT
@@ -57225,9 +58164,7 @@
1592524800,1592540415,GB
1592540416,1592540423,A2
1592540424,1592557567,GB
-1592557568,1592584447,BG
-1592584448,1592584703,GB
-1592584704,1592590335,BG
+1592557568,1592590335,BG
1592590336,1592623103,FI
1592623104,1592655871,RU
1592655872,1592786943,FR
@@ -57463,7 +58400,8 @@
1602248704,1602250751,BE
1602250752,1602252799,NO
1602252800,1602254847,SE
-1602254848,1602255359,HU
+1602254848,1602255103,PT
+1602255104,1602255359,HU
1602255360,1602255615,US
1602255616,1602255871,PT
1602255872,1602256895,HU
@@ -57484,9 +58422,7 @@
1602273792,1602274559,IN
1602274560,1602274815,IE
1602274816,1602275327,IN
-1602275328,1602275615,DE
-1602275616,1602275647,CY
-1602275648,1602275679,DE
+1602275328,1602275679,DE
1602275680,1602275695,CA
1602275696,1602279423,DE
1602279424,1602281471,GB
@@ -57496,7 +58432,6 @@
1602287616,1602289663,DE
1602289664,1602291711,LB
1602291712,1602293759,SA
-1602293760,1602295807,RU
1602295808,1602297855,NL
1602297856,1602298367,IL
1602298368,1602298431,MT
@@ -57644,11 +58579,15 @@
1603083264,1603084287,DE
1603084288,1603085871,IT
1603085872,1603085879,CH
-1603085880,1603087515,IT
+1603085880,1603087047,IT
+1603087048,1603087103,DE
+1603087104,1603087515,IT
1603087516,1603087517,CH
1603087518,1603087544,IT
1603087545,1603087546,CH
-1603087547,1603088383,IT
+1603087547,1603087644,IT
+1603087645,1603087646,CH
+1603087647,1603088383,IT
1603088384,1603092479,LB
1603092480,1603100671,NO
1603100672,1603108863,FR
@@ -57659,27 +58598,35 @@
1603133440,1603137535,RU
1603137536,1603141631,KW
1603141632,1603145727,ES
-1603145728,1603146015,NL
-1603146016,1603146079,CY
-1603146080,1603146239,NL
+1603145728,1603146031,NL
+1603146032,1603146063,CY
+1603146064,1603146239,NL
1603146240,1603146751,US
1603146752,1603147007,NL
1603147008,1603147263,US
-1603147264,1603147775,IL
+1603147264,1603147327,CY
+1603147328,1603147519,NL
+1603147520,1603147775,IL
1603147776,1603148031,US
-1603148032,1603149567,IL
+1603148032,1603148287,IL
+1603148288,1603148799,NL
+1603148800,1603149311,IL
+1603149312,1603149567,NL
1603149568,1603149823,US
1603149824,1603153919,RU
1603153920,1603158015,NL
1603158016,1603159167,DE
1603159168,1603159183,NL
-1603159184,1603159487,DE
+1603159184,1603159199,FR
+1603159200,1603159487,DE
1603159488,1603159519,AT
1603159520,1603159535,DE
1603159536,1603159551,GB
1603159552,1603159823,DE
1603159824,1603159839,CH
-1603159840,1603161007,DE
+1603159840,1603160079,DE
+1603160080,1603160095,NL
+1603160096,1603161007,DE
1603161008,1603161023,GB
1603161024,1603161103,DE
1603161104,1603161119,GB
@@ -57738,16 +58685,14 @@
1603224432,1603224447,US
1603224448,1603224463,MX
1603224464,1603224575,GB
-1603224576,1603224775,FR
-1603224776,1603224783,GB
-1603224784,1603224831,FR
+1603224576,1603224831,FR
1603224832,1603224847,ES
1603224848,1603224895,FR
1603224896,1603224911,GB
1603224912,1603225007,FR
1603225008,1603225023,MX
-1603225024,1603225127,FR
-1603225128,1603225343,GB
+1603225024,1603225159,FR
+1603225160,1603225343,GB
1603225344,1603225599,FR
1603225600,1603225607,ES
1603225608,1603225615,GB
@@ -57779,9 +58724,7 @@
1603895296,1603928063,RU
1603928064,1603944447,DK
1603944448,1603977215,RU
-1603977216,1603979295,GB
-1603979296,1603979327,ID
-1603979328,1603980463,GB
+1603977216,1603980463,GB
1603980464,1603980479,CH
1603980480,1603980863,GB
1603980864,1603980927,ID
@@ -57845,9 +58788,7 @@
1604891968,1604892159,RU
1604892160,1604892927,DE
1604892928,1604893183,HK
-1604893184,1604893311,DE
-1604893312,1604893375,CY
-1604893376,1604893951,DE
+1604893184,1604893951,DE
1604893952,1604894463,TR
1604894464,1604894719,DE
1604894720,1604895487,CZ
@@ -57860,7 +58801,9 @@
1604901312,1604901375,SC
1604901376,1604901631,CZ
1604901632,1604901887,SK
-1604901888,1604901983,CZ
+1604901888,1604901919,CZ
+1604901920,1604901935,SK
+1604901936,1604901983,CZ
1604901984,1604902142,SK
1604902143,1604902399,CZ
1604902400,1604902911,SK
@@ -57937,7 +58880,10 @@
1605230592,1605238783,TR
1605238784,1605246975,IT
1605246976,1605255167,PL
-1605263360,1605271551,RU
+1605255168,1605257215,RU
+1605257216,1605259263,FR
+1605259264,1605261311,DE
+1605261312,1605271551,RU
1605271552,1605279743,DE
1605279744,1605287935,FR
1605287936,1605296127,RU
@@ -58024,6 +58970,7 @@
1607965696,1607966719,UA
1607967744,1607968767,UA
1607968768,1607969791,SE
+1607970816,1607972863,RU
1607972864,1607974911,NL
1607979008,1607980031,RU
1607980032,1607981055,DE
@@ -58775,7 +59722,9 @@
1652681472,1652681479,GB
1652681480,1652681511,US
1652681512,1652681519,IL
-1652681520,1653534719,US
+1652681520,1653496847,US
+1653496848,1653496863,AU
+1653496864,1653534719,US
1653534720,1653538815,CA
1653538816,1653555199,US
1653555200,1653560319,CA
@@ -58977,12 +59926,16 @@
1701117952,1701134335,NC
1701134336,1701142527,CN
1701142528,1701143551,HK
-1701143552,1701150719,CN
+1701143552,1701143807,CN
+1701143808,1701144063,AU
+1701144064,1701150719,CN
1701150720,1701183487,KR
1701183488,1701199871,JP
1701199872,1701208063,CN
1701208064,1701209087,JP
-1701209088,1701216255,CN
+1701209088,1701209855,CN
+1701209856,1701210111,AU
+1701210112,1701216255,CN
1701216256,1701249023,JP
1701249024,1701314559,AU
1701314560,1701576703,CN
@@ -59209,6 +60162,8 @@
1728376832,1728377855,ID
1728377856,1728378879,HK
1728378880,1728380927,IN
+1728380928,1728382975,PH
+1728382976,1728383999,SG
1728708608,1728709631,CN
1728709632,1728710655,TW
1728710656,1728710911,AU
@@ -59274,6 +60229,21 @@
1728762880,1728763903,VN
1728763904,1728764927,KR
1728764928,1728765439,SG
+1728765440,1728765695,IN
+1728765696,1728765951,ID
+1728765952,1728766975,IN
+1728766976,1728767999,TH
+1728768000,1728768255,AU
+1728768256,1728768511,NZ
+1728768512,1728769023,IN
+1728769024,1728770047,HK
+1728770048,1728772095,JP
+1728772096,1728773375,IN
+1728773376,1728773631,ID
+1728773632,1728774143,PH
+1729495040,1729519615,CN
+1729519616,1729520639,HK
+1729520640,1729527807,CN
1729527808,1729528831,SG
1729528832,1729530879,ID
1729530880,1729531903,MY
@@ -59342,6 +60312,38 @@
1729983488,1729984511,IN
1729984512,1729985535,ID
1729985536,1729986559,BD
+1729986560,1729989631,CN
+1729989632,1729990655,HK
+1729990656,1729991679,MN
+1729991680,1729992703,ID
+1729992704,1729993727,NC
+1729993728,1729994751,IN
+1729994752,1729995519,AU
+1729995520,1729995775,PK
+1729995776,1729996799,ID
+1729996800,1729997311,AU
+1729997312,1729997823,ID
+1729997824,1729998847,AU
+1729998848,1730000895,JP
+1730000896,1730001919,ID
+1730001920,1730002943,TH
+1730002944,1730003967,AU
+1730003968,1730004223,ID
+1730004224,1730004479,IN
+1730004480,1730004735,MY
+1730004736,1730004991,MN
+1730004992,1730007039,AU
+1730007040,1730008063,IN
+1730008064,1730009087,ID
+1730009088,1730010111,AU
+1730010112,1730011135,IN
+1730011136,1730012159,BT
+1730012160,1730013183,ID
+1730013184,1730015231,IN
+1730015232,1730016255,MY
+1730016256,1730017279,PH
+1730017280,1730017791,IN
+1730017792,1730019327,PH
1744175104,1744176127,ID
1744176128,1744177151,AU
1744177152,1744179199,CN
@@ -59360,7 +60362,8 @@
1744192512,1744194559,JP
1744194560,1744194815,ID
1744194816,1744195071,HK
-1744195072,1744195583,SG
+1744195072,1744195327,SG
+1744195328,1744195583,HK
1744195584,1744196607,JP
1744196608,1744197631,IN
1744197632,1744198655,MY
@@ -59373,6 +60376,45 @@
1744203776,1744204799,MY
1744204800,1744205823,ID
1744205824,1744207871,CN
+1744207872,1744208127,AU
+1744208128,1744208383,ID
+1744208384,1744208895,AU
+1744208896,1744209919,CN
+1744209920,1744210943,AU
+1744210944,1744211967,SG
+1744211968,1744212991,KH
+1744212992,1744214015,JP
+1744214016,1744216063,CN
+1744216064,1744217087,HK
+1744217088,1744218111,JP
+1744218112,1744218367,AU
+1744218368,1744218623,ID
+1744218624,1744219135,IN
+1744219136,1744220159,PH
+1744220160,1744221183,HK
+1744221184,1744222207,NZ
+1744222208,1744222719,ID
+1744222720,1744223231,AU
+1744223232,1744224255,TH
+1744224256,1744225279,JP
+1744225280,1744226303,IN
+1744226304,1744227327,SG
+1744227328,1744228351,MY
+1744228352,1744229375,TW
+1744229376,1744230399,IN
+1744230400,1744230655,HK
+1744230656,1744230911,MY
+1744230912,1744231423,IN
+1744231424,1744232447,VN
+1744232448,1744233471,IN
+1744233472,1744234495,KH
+1744234496,1744234751,JP
+1744234752,1744235519,AU
+1744235520,1744236543,KR
+1744236544,1744237567,IN
+1744237568,1744238591,HK
+1744238592,1744239615,NZ
+1744239616,1744240639,JP
1769996288,1772093439,MA
1778384896,1778385151,CN
1778385152,1778385407,AU
@@ -59466,6 +60508,7 @@
1833248768,1833250815,MK
1833250816,1833254911,GB
1833254912,1833256959,DE
+1833256960,1833259007,RU
1833259008,1833261055,GB
1833261056,1833263103,PL
1833263104,1833265151,DE
@@ -59474,6 +60517,7 @@
1833269248,1833271295,FI
1833271296,1833273343,IT
1833273344,1833275391,EU
+1833275392,1833277439,IT
1833277440,1833279487,CH
1833279488,1833281535,AL
1833281536,1833283583,AT
@@ -59481,8 +60525,9 @@
1833285632,1833289727,FR
1833289728,1833291775,IT
1833291776,1833293823,CZ
-1833293824,1833294557,BE
-1833294558,1833294591,FR
+1833293824,1833294540,BE
+1833294541,1833294550,NL
+1833294551,1833294591,FR
1833294592,1833295871,BE
1833295872,1833297919,NL
1833297920,1833299967,GB
@@ -59595,7 +60640,8 @@
1833472000,1833474047,EU
1833474048,1833474559,UA
1833474560,1833474815,RU
-1833474816,1833476095,EU
+1833474816,1833475071,EU
+1833475072,1833476095,DE
1833476096,1833477375,NL
1833477376,1833477503,GB
1833477504,1833477631,DE
@@ -59660,8 +60706,10 @@
1833676800,1833677567,DE
1833677568,1833677599,CH
1833677600,1833678903,DE
-1833678904,1833678911,HK
-1833678912,1833680895,DE
+1833678904,1833678935,HK
+1833678936,1833678959,DE
+1833678960,1833678975,BA
+1833678976,1833680895,DE
1833680896,1833684991,UA
1833684992,1833689087,DE
1833689088,1833693183,FI
@@ -59734,7 +60782,10 @@
1835627648,1835629567,SE
1835629568,1835630335,DK
1835630336,1835630591,SE
-1835630592,1835646975,RU
+1835630592,1835636735,RU
+1835636736,1835638527,LU
+1835638528,1835638783,AM
+1835638784,1835646975,RU
1835646976,1835655167,BA
1835655168,1835663359,CY
1835663360,1835671551,UA
@@ -59771,10 +60822,12 @@
1835913216,1835917311,RU
1835917312,1835920127,GB
1835920128,1835920199,PT
-1835920200,1835920207,GB
-1835920208,1835920215,PT
-1835920216,1835920255,GB
-1835920256,1835920319,PT
+1835920200,1835920223,GB
+1835920224,1835920247,PT
+1835920248,1835920255,GB
+1835920256,1835920287,PT
+1835920288,1835920295,GB
+1835920296,1835920319,PT
1835920320,1835925503,GB
1835925504,1835933695,LV
1835933696,1835941887,RU
@@ -59989,7 +61042,26 @@
1842085888,1842118655,GB
1842118656,1842151423,FI
1842151424,1842153471,FR
-1842153472,1842155519,NO
+1842153472,1842153567,NO
+1842153568,1842153575,GB
+1842153576,1842153823,NO
+1842153824,1842153855,GB
+1842153856,1842153887,NO
+1842153888,1842153919,DE
+1842153920,1842153951,NE
+1842153952,1842153983,NO
+1842153984,1842154015,US
+1842154016,1842154031,NO
+1842154032,1842154047,US
+1842154048,1842154111,NO
+1842154112,1842154115,US
+1842154116,1842154119,NO
+1842154120,1842154143,US
+1842154144,1842154239,NO
+1842154240,1842154247,HK
+1842154248,1842154367,NO
+1842154368,1842154431,US
+1842154432,1842155519,NO
1842155520,1842157567,IT
1842157568,1842159615,AE
1842159616,1842161663,BA
@@ -60132,8 +61204,8 @@
1844031776,1844031999,EU
1844032000,1844032031,GB
1844032032,1844032255,EU
-1844032256,1844032831,CH
-1844032832,1844033271,EU
+1844032256,1844033023,CH
+1844033024,1844033271,EU
1844033272,1844033535,CH
1844033536,1844035583,RS
1844035584,1844037631,MD
@@ -60154,7 +61226,9 @@
1844078592,1844080127,DE
1844080128,1844080639,PL
1844080640,1844082687,GE
-1844082688,1844084735,DE
+1844082688,1844084055,DE
+1844084056,1844084063,CH
+1844084064,1844084735,DE
1844084736,1844086783,RU
1844086784,1844088831,IT
1844088832,1844090879,AT
@@ -60164,7 +61238,9 @@
1844099072,1844101119,DE
1844101120,1844105215,GB
1844105216,1844107263,ES
-1844107264,1844109311,DE
+1844107264,1844107807,DE
+1844107808,1844107823,CH
+1844107824,1844109311,DE
1844109312,1844109567,US
1844109568,1844111359,GB
1844111360,1844113407,AL
@@ -60220,10 +61296,15 @@
1844170016,1844170019,NG
1844170020,1844170027,AF
1844170028,1844170031,IQ
-1844170032,1844170239,DE
+1844170032,1844170047,AF
+1844170048,1844170051,DE
+1844170052,1844170055,GH
+1844170056,1844170063,AF
+1844170064,1844170239,DE
1844170240,1844170255,AF
-1844170256,1844170259,IQ
-1844170260,1844170751,DE
+1844170256,1844170263,IQ
+1844170264,1844170271,AF
+1844170272,1844170751,DE
1844170752,1844174847,RU
1844174848,1844178943,DE
1844178944,1844180991,EE
@@ -60425,7 +61506,7 @@
1850400768,1850408959,JP
1850408960,1850490879,CN
1850490880,1850507263,KR
-1850507264,1850509311,AU
+1850507264,1850510335,AU
1850510336,1850511359,KR
1850511360,1850513407,ID
1850513408,1850514431,TH
@@ -62936,7 +64017,9 @@
2178351104,2178416639,GB
2178416640,2178482175,US
2178482176,2178547711,DE
-2178547712,2179465215,US
+2178547712,2179379199,US
+2179379200,2179399679,GB
+2179399680,2179465215,US
2179530752,2179596287,DE
2179596288,2179661823,GB
2179661824,2179989503,US
@@ -63068,7 +64151,9 @@
2193817600,2193883135,NZ
2193883136,2194014207,US
2194014208,2194079743,CH
-2194079744,2194407423,US
+2194079744,2194210815,US
+2194210816,2194276351,GB
+2194276352,2194407423,US
2194472960,2194538495,US
2194538496,2194604031,ES
2194604032,2194669567,US
@@ -63693,9 +64778,7 @@
2305622016,2305687551,AU
2305687552,2305753087,US
2305753088,2305818623,AU
-2305818624,2306146303,US
-2306146304,2306211839,CA
-2306211840,2306342911,US
+2305818624,2306342911,US
2306342912,2306408447,NL
2306408448,2306473983,FR
2306473984,2306539519,CA
@@ -63866,7 +64949,8 @@
2330066944,2330132479,US
2330132480,2330198015,SE
2330198016,2330263551,CH
-2330263552,2330394623,US
+2330263552,2330267647,US
+2330329088,2330394623,US
2330394624,2330460159,FR
2330460160,2330525695,AT
2330525696,2330591231,SE
@@ -64038,7 +65122,7 @@
2354249728,2354315263,AU
2354315264,2354380799,DE
2354380800,2354446335,NL
-2354446336,2354511871,FR
+2354446336,2354511871,SE
2354511872,2354577407,CA
2354577408,2354839551,US
2354839552,2354905087,TW
@@ -64238,12 +65322,11 @@
2374686720,2374688767,NL
2374688768,2374696959,GB
2374696960,2374959103,US
-2374959104,2375024639,BE
+2374959104,2375024639,SE
2375024640,2375090175,DK
2375090176,2375155711,NO
2375155712,2375221247,US
-2375221248,2375286783,SE
-2375286784,2375352319,CH
+2375221248,2375352319,SE
2375352320,2376269823,US
2376269824,2376335359,GB
2376335360,2376597503,US
@@ -64666,8 +65749,8 @@
2453815296,2453831679,RO
2453831680,2453831807,IR
2453831808,2453831871,IQ
-2453831872,2453832703,IR
-2453832704,2453833727,IQ
+2453831872,2453832959,IR
+2453832960,2453833727,IQ
2453833728,2453835775,ES
2453835776,2453837823,DE
2453837824,2453838335,LU
@@ -64675,6 +65758,7 @@
2453839872,2453852159,RU
2453852160,2453856255,RO
2453856256,2453858303,DE
+2453858304,2453860351,SE
2453860352,2453864447,ES
2453864448,2453929983,CH
2453929984,2454061055,US
@@ -64723,8 +65807,8 @@
2457272320,2457337855,FI
2457337856,2457360895,RU
2457360896,2457361151,UA
-2457361152,2457362431,CZ
-2457362432,2457364479,RU
+2457361152,2457361407,CZ
+2457361408,2457364479,RU
2457364480,2457376767,CZ
2457376768,2457378815,DE
2457378816,2457380863,RU
@@ -64787,7 +65871,11 @@
2461614080,2461630463,TR
2461630464,2461651967,RU
2461651968,2461652991,GB
-2461652992,2461663231,RU
+2461652992,2461659135,RU
+2461659136,2461659391,UA
+2461659392,2461659903,RU
+2461659904,2461660159,UA
+2461660160,2461663231,RU
2461663232,2461794303,US
2461794304,2461859839,GB
2461859840,2461990911,US
@@ -64833,29 +65921,31 @@
2465683456,2465685503,FR
2465685504,2465690367,DE
2465690368,2465690431,US
-2465690432,2465690623,CH
+2465690432,2465690623,IT
2465690624,2465690639,GB
-2465690640,2465691135,CH
+2465690640,2465690879,IT
+2465690880,2465690895,CH
+2465690896,2465691135,IT
2465691136,2465691151,DE
-2465691152,2465691391,CH
+2465691152,2465691391,IT
2465691392,2465691407,NL
-2465691408,2465691647,CH
+2465691408,2465691647,IT
2465691648,2465691663,BR
-2465691664,2465691903,CH
+2465691664,2465691903,IT
2465691904,2465691919,JP
-2465691920,2465692159,CH
+2465691920,2465692159,IT
2465692160,2465692175,CN
-2465692176,2465692415,CH
+2465692176,2465692415,IT
2465692416,2465692431,LT
-2465692432,2465692671,CH
+2465692432,2465692671,IT
2465692672,2465692687,FR
-2465692688,2465692927,CH
+2465692688,2465692927,IT
2465692928,2465692943,ID
-2465692944,2465693183,CH
+2465692944,2465693183,IT
2465693184,2465693199,RU
-2465693200,2465693439,CH
+2465693200,2465693439,IT
2465693440,2465693455,FR
-2465693456,2465693695,CH
+2465693456,2465693695,IT
2465693696,2465726463,NO
2465726464,2465791999,CH
2465792000,2465857535,FR
@@ -64921,9 +66011,9 @@
2471165952,2471231487,CH
2471231488,2471297023,AU
2471297024,2471362559,GB
-2471362560,2471428095,EU
2471428096,2471690239,US
2471690240,2471821311,ES
+2471821312,2471886847,US
2471886848,2472083455,CH
2472083456,2472148991,GB
2472148992,2472214527,US
@@ -65119,7 +66209,8 @@
2508075008,2508077055,CH
2508077056,2508079103,BE
2508079104,2508081151,DE
-2508081152,2508083199,IL
+2508081152,2508081279,GB
+2508081280,2508083199,IL
2508083200,2508085247,IS
2508085248,2508087295,PS
2508087296,2508089343,RU
@@ -65152,6 +66243,32 @@
2509916160,2509918207,DE
2509918208,2509920255,FR
2509920256,2509922303,IT
+2509922304,2509924351,AT
+2509924352,2509928447,RU
+2509928448,2509930495,FI
+2509930496,2509934591,RU
+2509934592,2509936639,DE
+2509936640,2509936914,AT
+2509936915,2509936915,IR
+2509936916,2509937681,AT
+2509937682,2509937682,ME
+2509937683,2509937683,AT
+2509937684,2509937684,IQ
+2509937685,2509937685,AQ
+2509937686,2509937686,MP
+2509937687,2509937687,BT
+2509937688,2509937688,KP
+2509937689,2509937689,KY
+2509937690,2509937690,BS
+2509937691,2509937691,CU
+2509937692,2509937692,SO
+2509937693,2509937693,SZ
+2509937694,2509937694,NA
+2509937695,2509937695,AM
+2509937696,2509937697,CN
+2509937698,2509938687,AT
+2509938688,2509946879,UA
+2509946880,2509963263,BE
2509963264,2510028799,GB
2510028800,2510094335,PL
2510094336,2510159871,IE
@@ -65160,13 +66277,18 @@
2510815232,2510946303,US
2510946304,2511011839,GB
2511011840,2511077375,AU
-2511077376,2511339519,US
+2511077376,2511142911,DE
+2511142912,2511339519,US
2511339520,2511405055,AU
2511405056,2512715775,GB
2512715776,2512781311,FI
2512781312,2512912383,US
-2512912384,2513502207,DE
+2512912384,2512945151,HU
+2512945152,2512977919,JO
+2512977920,2513502207,DE
2513502208,2513567743,NO
+2513567744,2513600511,GR
+2513600512,2513633279,RO
2513633280,2513698815,DE
2513698816,2513764351,DK
2513764352,2514419711,DE
@@ -65177,6 +66299,25 @@
2516254720,2516320255,FR
2516320256,2516451327,US
2516451328,2516516863,GB
+2516516864,2516520959,RU
+2516520960,2516523007,SA
+2516523008,2516525055,RU
+2516525056,2516527103,NL
+2516527104,2516529151,GB
+2516529152,2516531199,CH
+2516531200,2516533247,GB
+2516533248,2516541439,CZ
+2516541440,2516545535,GB
+2516545536,2516547583,RU
+2516547584,2516549631,GB
+2516549632,2516551679,RU
+2516551680,2516553727,FR
+2516553728,2516557823,AZ
+2516557824,2516559871,RU
+2516559872,2516561919,GB
+2516561920,2516563967,LI
+2516563968,2516566015,GB
+2516566016,2516582399,IQ
2516582400,2516647935,CN
2516647936,2523201535,JP
2523201536,2523267071,AU
@@ -65189,7 +66330,6 @@
2524512256,2524643327,CN
2524643328,2524971007,US
2524971008,2525036543,ES
-2525036544,2525102079,EU
2525102080,2525233151,US
2525233152,2525298687,SE
2525298688,2525626367,US
@@ -65686,9 +66826,8 @@
2654404608,2654994431,US
2654994432,2655059967,LU
2655059968,2655125503,US
-2655125504,2655185151,EU
-2655185152,2655186944,PL
-2655186945,2655256575,EU
+2655125504,2655191039,PL
+2655191040,2655256575,EU
2655256576,2655715327,US
2655715328,2655780863,PL
2655780864,2656632831,US
@@ -65778,7 +66917,9 @@
2667118592,2667184127,HU
2667184128,2667249663,RU
2667249664,2667315199,CL
-2667315200,2667970559,US
+2667315200,2667577343,US
+2667577344,2667642879,SA
+2667642880,2667970559,US
2667970560,2668036095,CA
2668036096,2668101631,SE
2668101632,2668167167,CH
@@ -65791,6 +66932,12 @@
2668691456,2668756991,US
2668756992,2668822527,CA
2668822528,2668888063,US
+2668888064,2668890111,DK
+2668890112,2668892159,FR
+2668892160,2668894207,BA
+2668894208,2668896255,MT
+2668896256,2668904447,GB
+2668920832,2668953599,IT
2668953600,2669019135,US
2669019136,2669084671,CH
2669084672,2669150207,ES
@@ -65827,6 +66974,7 @@
2672951296,2673082367,US
2673082368,2673147903,FR
2673147904,2673213439,US
+2673213440,2673278975,GB
2673278976,2673410047,US
2673410048,2673475583,CA
2673475584,2673541119,VE
@@ -65861,6 +67009,8 @@
2676424704,2677014527,US
2677014528,2677080063,CH
2677080064,2677145599,US
+2677145600,2677178367,TR
+2677178368,2677211135,UA
2677211136,2677276671,GB
2677276672,2677342207,LV
2677342208,2677407743,IT
@@ -66112,7 +67262,8 @@
2706960384,2706964479,US
2706964480,2707226623,NL
2707226624,2707488767,JP
-2707488768,2707947519,US
+2707488768,2707619839,US
+2707619840,2707947519,GB
2707947520,2708144127,FR
2708144128,2708340735,US
2708340736,2708406271,AT
@@ -66124,7 +67275,6 @@
2708865024,2708930559,JP
2708930560,2709127167,US
2709127168,2709192703,KR
-2709192704,2709258239,EU
2709258240,2709389311,US
2709389312,2709454847,SG
2709454848,2709716991,US
@@ -67017,9 +68167,15 @@
2905381888,2905382016,CA
2905382017,2905384959,US
2905384960,2905385471,CA
-2905385472,2905388031,US
+2905385472,2905385951,US
+2905385952,2905385983,CR
+2905385984,2905388031,US
2905388032,2905388287,CA
-2905388288,2905392895,US
+2905388288,2905391327,US
+2905391328,2905391335,CR
+2905391336,2905391359,US
+2905391360,2905391391,CR
+2905391392,2905392895,US
2905392896,2905393151,CA
2905393152,2905394175,US
2905394176,2905394943,CA
@@ -67039,7 +68195,9 @@
2905446656,2905446911,DE
2905446912,2905449983,US
2905449984,2905451007,CA
-2905451008,2905451519,US
+2905451008,2905451327,US
+2905451328,2905451391,CY
+2905451392,2905451519,US
2905451520,2905451647,PA
2905451648,2905473023,US
2905473024,2905481215,CA
@@ -67056,11 +68214,15 @@
2915275328,2915516415,US
2915516416,2915516671,NL
2915516672,2915516927,CA
-2915516928,2915765279,US
+2915516928,2915517439,US
+2915517440,2915518463,DK
+2915518464,2915520511,GB
+2915520512,2915521023,AU
+2915521024,2915521279,JP
+2915521280,2915521535,PL
+2915521536,2915765279,US
2915765280,2915765287,IN
-2915765288,2915765343,US
-2915765344,2915765351,NZ
-2915765352,2915765367,US
+2915765288,2915765367,US
2915765368,2915765375,ZA
2915765376,2915765431,US
2915765432,2915765439,MX
@@ -67407,13 +68569,13 @@
2916442624,2916442879,CA
2916442880,2916443614,US
2916443615,2916443647,CA
-2916443648,2916444927,US
-2916444928,2916445951,CA
-2916445952,2916449279,US
+2916443648,2916449279,US
2916449280,2916450303,CA
-2916450304,2916515839,US
+2916450304,2916478975,US
+2916478976,2916483071,A1
+2916483072,2916515839,US
2916515840,2916519935,CA
-2916524032,2916530482,US
+2916519936,2916530482,US
2916530483,2916530552,AU
2916530553,2916581375,US
2916581376,2916614143,PR
@@ -67439,9 +68601,7 @@
2917168448,2917168479,BR
2917168480,2917168607,US
2917168608,2917168639,BR
-2917168640,2917169663,US
-2917169664,2917169695,DE
-2917169696,2917170015,US
+2917168640,2917170015,US
2917170016,2917170047,UA
2917170048,2917170079,BR
2917170080,2917170111,US
@@ -67477,7 +68637,75 @@
2917597440,2917597695,GB
2917597696,2917621759,US
2917621760,2917629951,CA
-2917629952,2917663231,US
+2917629952,2917646591,US
+2917646592,2917647231,CN
+2917647232,2917647359,US
+2917647360,2917648511,CN
+2917648512,2917648639,US
+2917648640,2917649279,CN
+2917649280,2917649407,US
+2917649408,2917649535,RU
+2917649536,2917649663,CN
+2917649664,2917649791,GB
+2917649792,2917649919,AZ
+2917649920,2917650047,CN
+2917650048,2917650175,US
+2917650176,2917650303,CN
+2917650304,2917650431,PA
+2917650432,2917650559,CN
+2917650560,2917651071,US
+2917651072,2917651455,CN
+2917651456,2917651711,US
+2917651712,2917651839,CR
+2917651840,2917652095,CN
+2917652096,2917652223,IN
+2917652224,2917652479,AU
+2917652480,2917652735,CN
+2917652736,2917652863,NZ
+2917652864,2917653247,US
+2917653248,2917653375,CN
+2917653376,2917653503,PA
+2917653504,2917654015,GB
+2917654016,2917654143,FI
+2917654144,2917654271,MY
+2917654272,2917654527,CN
+2917654528,2917654655,TH
+2917654656,2917654783,MX
+2917654784,2917655039,DE
+2917655040,2917655167,US
+2917655168,2917655295,SG
+2917655296,2917655423,GB
+2917655424,2917655807,CN
+2917655808,2917655935,US
+2917655936,2917656063,HU
+2917656064,2917656447,CN
+2917656448,2917656575,FR
+2917656576,2917656703,US
+2917656704,2917657087,CN
+2917657088,2917657215,NO
+2917657216,2917657471,US
+2917657472,2917657599,CN
+2917657600,2917657855,US
+2917657856,2917657983,CN
+2917657984,2917658367,US
+2917658368,2917658495,CN
+2917658496,2917658879,US
+2917658880,2917659007,PH
+2917659008,2917659519,US
+2917659520,2917659647,HK
+2917659648,2917659775,US
+2917659776,2917659903,CN
+2917659904,2917660287,US
+2917660288,2917660415,MY
+2917660416,2917660543,CA
+2917660544,2917660671,GI
+2917660672,2917661183,GB
+2917661184,2917661311,CA
+2917661312,2917661695,CN
+2917661696,2917661823,ZA
+2917661824,2917661951,PK
+2917661952,2917662079,CN
+2917662080,2917663231,US
2917663232,2917663487,CA
2917663488,2917665791,US
2917665792,2917666303,CA
@@ -67521,15 +68749,54 @@
2917723136,2917723391,CA
2917723392,2917724159,US
2917724160,2917724415,CA
-2917724416,2917802367,US
+2917724416,2917726207,US
+2917726208,2917726463,CA
+2917726464,2917726495,CR
+2917726496,2917795951,US
+2917795952,2917795959,CA
+2917795960,2917796263,US
+2917796264,2917796271,CA
+2917796272,2917801983,US
+2917801984,2917801991,CA
+2917801992,2917802231,US
+2917802232,2917802239,CA
+2917802240,2917802295,US
+2917802296,2917802303,CA
+2917802304,2917802367,US
2917802368,2917802375,CA
-2917802376,2917804935,US
+2917802376,2917802479,US
+2917802480,2917802487,CA
+2917802488,2917804911,US
+2917804912,2917804919,CA
+2917804920,2917804935,US
2917804936,2917804943,CA
-2917804944,2917815575,US
+2917804944,2917805039,US
+2917805040,2917805047,CA
+2917805048,2917809231,US
+2917809232,2917809239,CA
+2917809240,2917809927,US
+2917809928,2917809935,CA
+2917809936,2917811511,US
+2917811512,2917811519,LK
+2917811520,2917811583,US
+2917811584,2917811647,LK
+2917811648,2917815575,US
2917815576,2917815583,RO
-2917815584,2917834751,US
+2917815584,2917823871,US
+2917823872,2917823887,CA
+2917823888,2917823895,US
+2917823896,2917823903,CA
+2917823904,2917823975,US
+2917823976,2917823991,CA
+2917823992,2917829727,US
+2917829728,2917829743,CA
+2917829744,2917834143,US
+2917834144,2917834151,CA
+2917834152,2917834751,US
2917834752,2917835007,GB
-2917835008,2917842175,US
+2917835008,2917835679,US
+2917835680,2917835687,CA
+2917835688,2917842175,US
2917842176,2917842431,CA
2917842432,2917853471,US
2917853472,2917853495,CA
@@ -67586,7 +68853,9 @@
2918477824,2918481919,CA
2918481920,2918514943,US
2918514944,2918515079,CA
-2918515080,2918532111,US
+2918515080,2918515199,US
+2918515200,2918515231,CA
+2918515232,2918532111,US
2918532112,2918532119,CN
2918532120,2918532143,US
2918532144,2918532151,PK
@@ -67615,11 +68884,13 @@
2918534992,2918535807,US
2918535808,2918535967,CN
2918535968,2918535999,US
-2918536000,2918536159,CN
-2918536160,2918536167,US
+2918536000,2918536127,CN
+2918536128,2918536167,US
2918536168,2918536191,CN
2918536192,2918536703,A1
-2918536704,2918580223,US
+2918536704,2918536719,US
+2918536720,2918536727,CA
+2918536728,2918580223,US
2918580224,2918588415,CA
2918588416,2918596607,US
2918596608,2918604799,CA
@@ -67628,9 +68899,7 @@
2918703104,2918760447,US
2918760448,2918776831,CA
2918776832,2918816000,US
-2918816001,2918816511,GB
-2918816512,2918816767,US
-2918816768,2918817023,GB
+2918816001,2918817023,GB
2918817024,2918828031,US
2918828032,2918828543,UA
2918828544,2918829055,ES
@@ -67659,8 +68928,8 @@
2919020760,2919020767,US
2919020768,2919020799,CA
2919020800,2919021343,US
-2919021344,2919021359,CA
-2919021360,2919063551,US
+2919021344,2919021471,CA
+2919021472,2919063551,US
2919063552,2919064063,MX
2919064064,2919067655,CN
2919067656,2919067695,US
@@ -67884,7 +69153,7 @@
2919170352,2919170359,PE
2919170360,2919170367,AU
2919170368,2919170383,BR
-2919170384,2919170391,AU
+2919170384,2919170391,US
2919170392,2919170399,IN
2919170400,2919170407,TR
2919170408,2919170415,ES
@@ -67930,9 +69199,7 @@
2919170936,2919170943,PH
2919170944,2919170967,US
2919170968,2919170975,NZ
-2919170976,2919171047,US
-2919171048,2919171055,BR
-2919171056,2919171071,US
+2919170976,2919171071,US
2919171072,2919171079,IN
2919171080,2919171087,CL
2919171088,2919171095,TR
@@ -67968,7 +69235,7 @@
2919186432,2919190527,CA
2919190528,2919202079,US
2919202080,2919202111,BE
-2919202112,2919202815,US
+2919202112,2919206911,US
2919206912,2919211007,CA
2919219200,2919235583,US
2919235584,2919759871,CA
@@ -68068,7 +69335,9 @@
2928175304,2928175311,CN
2928175312,2928175399,US
2928175400,2928175407,TR
-2928175408,2928175551,US
+2928175408,2928175471,US
+2928175472,2928175479,JP
+2928175480,2928175551,US
2928175552,2928175567,CA
2928175568,2928175655,US
2928175656,2928175663,AU
@@ -68398,7 +69667,9 @@
2928321072,2928321311,US
2928321312,2928321327,GB
2928321328,2928321343,CN
-2928321344,2928323135,US
+2928321344,2928322639,US
+2928322640,2928322655,RU
+2928322656,2928323135,US
2928323136,2928323143,RU
2928323144,2928323175,US
2928323176,2928323183,AU
@@ -69047,7 +70318,9 @@
2953459712,2953461759,IT
2953461760,2953465855,ES
2953465856,2953465991,GB
-2953465992,2953467903,EU
+2953465992,2953466111,EU
+2953466112,2953466127,GB
+2953466128,2953467903,EU
2953467904,2953469951,BE
2953469952,2953478143,CH
2953478144,2953510911,SE
@@ -69070,7 +70343,93 @@
2954647552,2954657791,ES
2954657792,2954756095,JO
2954756096,2954821631,TR
-2954821632,2954887167,FR
+2954821632,2954870783,FR
+2954870784,2954870787,DE
+2954870788,2954870799,GB
+2954870800,2954870831,FR
+2954870832,2954870835,PL
+2954870836,2954870839,GB
+2954870840,2954870843,DE
+2954870844,2954870847,GB
+2954870848,2954870863,PL
+2954870864,2954870871,FR
+2954870872,2954870875,ES
+2954870876,2954870879,PL
+2954870880,2954870895,IE
+2954870896,2954870903,FR
+2954870904,2954870907,PL
+2954870908,2954870911,ES
+2954870912,2954871583,FR
+2954871584,2954871599,GB
+2954871600,2954871603,FR
+2954871604,2954871607,PL
+2954871608,2954871611,BE
+2954871612,2954871615,CZ
+2954871616,2954871631,ES
+2954871632,2954871635,BE
+2954871636,2954871639,ES
+2954871640,2954871643,FR
+2954871644,2954871647,IT
+2954871648,2954871663,FR
+2954871664,2954871671,IE
+2954871672,2954871703,FR
+2954871704,2954871707,CH
+2954871708,2954871711,IT
+2954871712,2954871807,FR
+2954871808,2954871823,NL
+2954871824,2954871831,FR
+2954871832,2954871839,PL
+2954871840,2954871887,FR
+2954871888,2954871895,GB
+2954871896,2954871903,FR
+2954871904,2954871919,IE
+2954871920,2954871923,ES
+2954871924,2954871935,IE
+2954871936,2954871939,PL
+2954871940,2954871943,GB
+2954871944,2954871947,ES
+2954871948,2954871951,DE
+2954871952,2954871955,ES
+2954871956,2954871959,PT
+2954871960,2954871967,FR
+2954871968,2954871999,PL
+2954872000,2954872323,FR
+2954872324,2954872327,PL
+2954872328,2954872335,DE
+2954872336,2954872351,ES
+2954872352,2954872383,DE
+2954872384,2954872415,GB
+2954872416,2954872419,DE
+2954872420,2954872435,PL
+2954872436,2954872587,FR
+2954872588,2954872591,DE
+2954872592,2954872607,IT
+2954872608,2954872639,FR
+2954872640,2954872671,BE
+2954872672,2954872675,IE
+2954872676,2954872679,ES
+2954872680,2954872687,FR
+2954872688,2954872703,GB
+2954872704,2954872831,DE
+2954872832,2954873367,FR
+2954873368,2954873375,PL
+2954873376,2954873391,FR
+2954873392,2954873407,PL
+2954873408,2954873447,FR
+2954873448,2954873459,PL
+2954873460,2954873463,NL
+2954873464,2954873467,PL
+2954873468,2954873535,FR
+2954873536,2954873567,DE
+2954873568,2954873583,FR
+2954873584,2954873591,ES
+2954873592,2954873599,FR
+2954873600,2954873631,DE
+2954873632,2954873635,NL
+2954873636,2954873639,PL
+2954873640,2954873647,FR
+2954873648,2954873663,GB
+2954873664,2954887167,FR
2954887168,2954891263,UA
2954891264,2954895359,IT
2954895360,2954897407,RU
@@ -69095,7 +70454,9 @@
2954940490,2954940535,DE
2954940536,2954940539,RO
2954940540,2954940658,DE
-2954940659,2954940670,PL
+2954940659,2954940662,PL
+2954940663,2954940664,DE
+2954940665,2954940670,PL
2954940671,2954940927,DE
2954940928,2954940931,RO
2954940932,2954940935,DE
@@ -69185,17 +70546,23 @@
2954941936,2954941939,RO
2954941940,2954941951,DE
2954941952,2954941955,GR
-2954941956,2954941967,DE
+2954941956,2954941961,DE
+2954941962,2954941965,ES
+2954941966,2954941967,DE
2954941968,2954941971,TR
2954941972,2954942041,DE
2954942042,2954942045,GR
2954942046,2954942057,DE
2954942058,2954942058,TR
-2954942059,2954942151,DE
+2954942059,2954942108,DE
+2954942109,2954942112,ES
+2954942113,2954942151,DE
2954942152,2954942155,RO
2954942156,2954942167,DE
2954942168,2954942171,TR
-2954942172,2954942227,DE
+2954942172,2954942191,DE
+2954942192,2954942195,TR
+2954942196,2954942227,DE
2954942228,2954942231,RO
2954942232,2954942243,DE
2954942244,2954942247,TR
@@ -69203,23 +70570,33 @@
2954942348,2954942351,GR
2954942352,2954942363,DE
2954942364,2954942367,TR
-2954942368,2954942441,DE
+2954942368,2954942427,DE
+2954942428,2954942431,TR
+2954942432,2954942441,DE
2954942442,2954942445,TR
2954942446,2954942457,DE
2954942458,2954942461,RO
2954942462,2954942471,DE
2954942472,2954942475,GR
-2954942476,2954942487,DE
+2954942476,2954942479,DE
+2954942480,2954942483,ES
+2954942484,2954942487,DE
2954942488,2954942491,TR
-2954942492,2954942571,DE
+2954942492,2954942563,DE
+2954942564,2954942567,TR
+2954942568,2954942571,DE
2954942572,2954942575,RO
2954942576,2954942587,DE
2954942588,2954942591,TR
-2954942592,2954942671,DE
+2954942592,2954942654,DE
+2954942655,2954942658,ES
+2954942659,2954942671,DE
2954942672,2954942675,GR
2954942676,2954942687,DE
2954942688,2954942691,TR
-2954942692,2954942727,DE
+2954942692,2954942719,DE
+2954942720,2954942723,TR
+2954942724,2954942727,DE
2954942728,2954942731,RO
2954942732,2954942743,DE
2954942744,2954942747,TR
@@ -69277,13 +70654,17 @@
2954943516,2954943519,TR
2954943520,2954943539,DE
2954943540,2954943543,TR
-2954943544,2954943563,DE
+2954943544,2954943547,DE
+2954943548,2954943563,GB
2954943564,2954943567,TR
-2954943568,2954943587,DE
+2954943568,2954943583,GB
+2954943584,2954943587,DE
2954943588,2954943591,TR
-2954943592,2954943611,DE
+2954943592,2954943603,GB
+2954943604,2954943611,FR
2954943612,2954943615,TR
-2954943616,2954943635,DE
+2954943616,2954943623,FR
+2954943624,2954943635,DE
2954943636,2954943639,TR
2954943640,2954943659,DE
2954943660,2954943663,TR
@@ -69293,7 +70674,11 @@
2954943708,2954943711,TR
2954943712,2954943731,DE
2954943732,2954943735,TR
-2954943736,2954943999,DE
+2954943736,2954943743,DE
+2954943744,2954943823,GB
+2954943824,2954943903,DE
+2954943904,2954943943,FR
+2954943944,2954943999,DE
2954944000,2954944007,RO
2954944008,2954944511,DE
2954944512,2954946559,GB
@@ -69307,8 +70692,8 @@
2955069440,2955071487,NL
2955071488,2955073535,IE
2955073536,2955075583,FR
-2955075584,2955079679,NL
-2955079680,2955083775,IE
+2955075584,2955081727,NL
+2955081728,2955083775,IE
2955083776,2955149311,GB
2955149312,2955411455,UA
2955411456,2955673599,TR
@@ -69323,7 +70708,7 @@
2956238848,2956242943,ES
2956242944,2956244991,SE
2956244992,2956247039,FR
-2956247040,2956249087,DE
+2956247040,2956251135,DE
2956251136,2956253183,GB
2956253184,2956255231,IE
2956255232,2956259327,FR
@@ -69379,7 +70764,8 @@
2956722176,2956787711,BY
2956787712,2956820479,IE
2956820480,2956822527,NL
-2956822528,2956824575,SE
+2956822528,2956823551,SE
+2956823552,2956824575,US
2956824576,2956826623,PT
2956826624,2956828671,DK
2956828672,2956836863,AT
@@ -69391,8 +70777,8 @@
2956888064,2956890111,BE
2956890112,2956892159,IR
2956892160,2956894207,IT
-2956894208,2956894719,BE
-2956894720,2956898303,NL
+2956894208,2956895743,BE
+2956895744,2956898303,NL
2956898304,2956902399,RU
2956902400,2956904447,NL
2956904448,2956906495,DK
@@ -69405,6 +70791,7 @@
2957049856,2957058047,PS
2957058048,2957066239,RU
2957066240,2957068287,GB
+2957068288,2957070335,LU
2957070336,2957074431,IT
2957074432,2957082623,RU
2957082624,2957115391,DE
@@ -69418,7 +70805,8 @@
2957201424,2957201427,IE
2957201428,2957201431,DK
2957201432,2957201435,CH
-2957201436,2957201727,US
+2957201436,2957201468,BR
+2957201469,2957201727,US
2957201728,2957201743,CA
2957201744,2957201759,MX
2957201760,2957201775,BR
@@ -69517,7 +70905,10 @@
2957203108,2957203111,NL
2957203112,2957203115,NZ
2957203116,2957203119,NO
-2957203120,2957203455,US
+2957203120,2957203123,US
+2957203124,2957203127,MT
+2957203128,2957203131,RS
+2957203132,2957203455,US
2957203456,2957205503,FR
2957205504,2957213695,PS
2957213696,2957221887,FR
@@ -69570,11 +70961,14 @@
2959126528,2959128575,RO
2959128576,2959130623,RU
2959130624,2959138815,UA
+2959138816,2959147007,RU
2961178624,2965372927,FR
2965372928,2965766143,RU
2965766144,2965897215,DE
2965897216,2966028287,IT
2966028288,2966159359,QA
+2966159360,2966290431,AE
+2966421504,2966683647,RU
2969567232,2977955839,BR
2986344448,2987393023,DE
2987393024,2987397119,IM
@@ -69719,6 +71113,7 @@
2987755520,2987757567,PL
2987757568,2987759615,DE
2987759616,2987761663,PL
+2987761664,2987763711,IR
2987763712,2987765759,GR
2987765760,2987767807,FR
2987767808,2987769855,CZ
@@ -69748,7 +71143,8 @@
2987810816,2987812863,NO
2987812864,2987814911,CH
2987814912,2987816959,CZ
-2987816960,2987819007,NL
+2987816960,2987817983,NL
+2987817984,2987819007,GB
2987819008,2987821055,FR
2987821056,2987823103,GB
2987823104,2987827199,FR
@@ -69820,7 +71216,8 @@
2988441896,2988441903,PL
2988441904,2988441911,IT
2988441912,2988441919,ES
-2988441920,2988441935,PL
+2988441920,2988441931,PL
+2988441932,2988441935,BE
2988441936,2988441939,FR
2988441940,2988441943,ES
2988441944,2988441951,FR
@@ -69930,7 +71327,8 @@
2988445120,2988445127,ES
2988445128,2988445139,FR
2988445140,2988445143,GB
-2988445144,2988445167,FR
+2988445144,2988445151,IT
+2988445152,2988445167,FR
2988445168,2988445183,ES
2988445184,2988445951,DE
2988445952,2988445967,FR
@@ -69940,7 +71338,8 @@
2988446272,2988446275,IT
2988446276,2988446291,FR
2988446292,2988446295,ES
-2988446296,2988446307,FR
+2988446296,2988446299,GB
+2988446300,2988446307,FR
2988446308,2988446319,PL
2988446320,2988446323,FR
2988446324,2988446327,LT
@@ -70069,20 +71468,18 @@
2988459176,2988459179,PL
2988459180,2988459183,FR
2988459184,2988459199,PL
-2988459200,2988459215,FR
-2988459216,2988459219,DE
-2988459220,2988459223,FR
+2988459200,2988459223,FR
2988459224,2988459231,DE
2988459232,2988459235,IT
2988459236,2988459239,PL
2988459240,2988459243,FR
2988459244,2988459247,ES
2988459248,2988459251,LT
-2988459252,2988459255,BE
+2988459252,2988459255,GB
2988459256,2988459259,FR
2988459260,2988459263,NL
2988459264,2988459519,ES
-2988459520,2988459583,DE
+2988459520,2988459583,FR
2988459584,2988459599,ES
2988459600,2988459603,GB
2988459604,2988459615,FR
@@ -70109,8 +71506,8 @@
2988459768,2988459771,NL
2988459772,2988459775,GB
2988459776,2988459839,FR
-2988459840,2988459855,GB
-2988459856,2988459863,FR
+2988459840,2988459859,GB
+2988459860,2988459863,FR
2988459864,2988459871,ES
2988459872,2988459895,PL
2988459896,2988459967,FR
@@ -70193,7 +71590,7 @@
2988461424,2988461431,IT
2988461432,2988461435,PT
2988461436,2988461439,BE
-2988461440,2988461471,ES
+2988461440,2988461471,FR
2988461472,2988461475,PL
2988461476,2988461479,IE
2988461480,2988461483,CZ
@@ -70216,8 +71613,9 @@
2988461708,2988461711,BE
2988461712,2988461719,FR
2988461720,2988461723,DE
-2988461724,2988461735,FR
-2988461736,2988461743,DE
+2988461724,2988461727,FR
+2988461728,2988461731,PL
+2988461732,2988461743,DE
2988461744,2988461747,ES
2988461748,2988461751,IT
2988461752,2988461755,FR
@@ -70307,7 +71705,10 @@
2988463212,2988463223,GB
2988463224,2988463227,ES
2988463228,2988463231,CH
-2988463232,2988463263,NL
+2988463232,2988463251,FR
+2988463252,2988463255,PL
+2988463256,2988463259,IE
+2988463260,2988463263,CH
2988463264,2988463279,PL
2988463280,2988463283,GB
2988463284,2988463315,FR
@@ -70395,7 +71796,7 @@
2988464800,2988464815,DE
2988464816,2988464819,FR
2988464820,2988464823,NL
-2988464824,2988464827,IT
+2988464824,2988464827,ES
2988464828,2988464831,GB
2988464832,2988464895,ES
2988464896,2988464911,PL
@@ -70492,7 +71893,8 @@
2988482816,2988482819,NL
2988482820,2988482823,DE
2988482824,2988482831,PL
-2988482832,2988482839,FR
+2988482832,2988482835,IE
+2988482836,2988482839,PL
2988482840,2988482843,ES
2988482844,2988482847,NL
2988482848,2988482863,FR
@@ -70663,7 +72065,8 @@
2988485520,2988485559,FR
2988485560,2988485567,NL
2988485568,2988485583,GB
-2988485584,2988485591,ES
+2988485584,2988485587,IT
+2988485588,2988485591,BE
2988485592,2988485599,FR
2988485600,2988485607,PL
2988485608,2988485611,FR
@@ -70675,7 +72078,10 @@
2988485676,2988485683,FR
2988485684,2988485687,PL
2988485688,2988485691,GB
-2988485692,2988485791,FR
+2988485692,2988485695,PL
+2988485696,2988485759,FR
+2988485760,2988485767,GB
+2988485768,2988485791,FR
2988485792,2988485795,PT
2988485796,2988485799,LT
2988485800,2988485803,PT
@@ -70685,7 +72091,10 @@
2988485832,2988485835,NL
2988485836,2988485839,LT
2988485840,2988485855,BE
-2988485856,2988485887,FR
+2988485856,2988485871,FR
+2988485872,2988485875,PL
+2988485876,2988485879,ES
+2988485880,2988485887,FR
2988485888,2988485903,PL
2988485904,2988485911,GB
2988485912,2988485951,FR
@@ -70728,15 +72137,40 @@
2988486288,2988486291,FR
2988486292,2988486295,DE
2988486296,2988486299,GB
-2988486300,2988486303,PL
-2988486304,2988486319,DE
+2988486300,2988486319,PL
2988486320,2988486323,IT
2988486324,2988486327,PT
2988486328,2988486343,ES
2988486344,2988486347,FR
2988486348,2988486351,ES
2988486352,2988486399,FR
-2988486400,2988486783,GB
+2988486400,2988486431,GB
+2988486432,2988486447,FR
+2988486448,2988486463,ES
+2988486464,2988486471,BE
+2988486472,2988486475,ES
+2988486476,2988486479,PL
+2988486480,2988486495,IE
+2988486496,2988486503,DE
+2988486504,2988486515,ES
+2988486516,2988486527,PL
+2988486528,2988486575,FR
+2988486576,2988486579,PL
+2988486580,2988486583,GB
+2988486584,2988486595,FR
+2988486596,2988486599,GB
+2988486600,2988486603,DE
+2988486604,2988486607,FR
+2988486608,2988486615,FI
+2988486616,2988486623,ES
+2988486624,2988486643,FR
+2988486644,2988486647,GB
+2988486648,2988486651,ES
+2988486652,2988486655,PL
+2988486656,2988486719,GB
+2988486720,2988486735,CZ
+2988486736,2988486751,FR
+2988486752,2988486783,GB
2988486784,2988486787,DE
2988486788,2988486795,FR
2988486796,2988486799,PL
@@ -70807,8 +72241,8 @@
2988489088,2988489103,GB
2988489104,2988489119,FI
2988489120,2988489123,ES
-2988489124,2988489127,NL
-2988489128,2988489131,DE
+2988489124,2988489127,IE
+2988489128,2988489131,IT
2988489132,2988489167,FR
2988489168,2988489175,PT
2988489176,2988489179,PL
@@ -70866,7 +72300,7 @@
2988489760,2988489791,NL
2988489792,2988489887,PL
2988489888,2988489903,FR
-2988489904,2988489919,GB
+2988489904,2988489919,IE
2988489920,2988489935,PL
2988489936,2988489943,ES
2988489944,2988489947,FR
@@ -70885,7 +72319,8 @@
2988490108,2988490111,FR
2988490112,2988490143,PL
2988490144,2988490175,ES
-2988490176,2988490183,FR
+2988490176,2988490179,IE
+2988490180,2988490183,PL
2988490184,2988490191,ES
2988490192,2988490195,GB
2988490196,2988490199,PT
@@ -70922,8 +72357,7 @@
2988498976,2988498983,ES
2988498984,2988498991,FR
2988498992,2988499007,PL
-2988499008,2988499039,FR
-2988499040,2988499051,DE
+2988499008,2988499051,DE
2988499052,2988499055,IT
2988499056,2988499063,FR
2988499064,2988499067,DE
@@ -70947,13 +72381,13 @@
2988499380,2988499387,PL
2988499388,2988499407,FR
2988499408,2988499415,PL
-2988499416,2988499423,FR
+2988499416,2988499423,DE
2988499424,2988499455,PL
2988499456,2988499463,NL
2988499464,2988499471,DE
2988499472,2988499487,FR
2988499488,2988499519,PL
-2988499520,2988499551,FR
+2988499520,2988499551,ES
2988499552,2988499559,PL
2988499560,2988499567,NL
2988499568,2988499575,IE
@@ -70998,7 +72432,8 @@
2988499872,2988499903,CH
2988499904,2988499907,FR
2988499908,2988499911,BE
-2988499912,2988499919,FR
+2988499912,2988499915,FR
+2988499916,2988499919,LT
2988499920,2988499923,DE
2988499924,2988499927,BE
2988499928,2988499935,FR
@@ -71013,7 +72448,9 @@
2988500312,2988500315,ES
2988500316,2988500319,DE
2988500320,2988500335,IT
-2988500336,2988500347,FR
+2988500336,2988500339,DE
+2988500340,2988500343,IE
+2988500344,2988500347,FR
2988500348,2988500351,PL
2988500352,2988500383,GB
2988500384,2988500399,BE
@@ -71041,8 +72478,8 @@
2988500768,2988500771,PT
2988500772,2988500775,ES
2988500776,2988500779,GB
-2988500780,2988500783,PL
-2988500784,2988500791,FR
+2988500780,2988500787,PL
+2988500788,2988500791,ES
2988500792,2988500799,PL
2988500800,2988500815,ES
2988500816,2988500831,FR
@@ -71131,7 +72568,15 @@
2988502452,2988502455,IT
2988502456,2988502459,ES
2988502460,2988502463,PT
-2988502464,2988502527,FR
+2988502464,2988502479,IE
+2988502480,2988502483,CH
+2988502484,2988502487,PL
+2988502488,2988502491,CH
+2988502492,2988502495,PL
+2988502496,2988502511,ES
+2988502512,2988502519,FR
+2988502520,2988502523,ES
+2988502524,2988502527,DE
2988502528,2988502543,PL
2988502544,2988502559,FR
2988502560,2988502591,PL
@@ -71194,7 +72639,8 @@
2988503200,2988503215,FR
2988503216,2988503231,PL
2988503232,2988503375,FR
-2988503376,2988503391,GB
+2988503376,2988503383,PT
+2988503384,2988503391,PL
2988503392,2988503395,ES
2988503396,2988503399,PL
2988503400,2988503415,FR
@@ -71205,13 +72651,20 @@
2988503504,2988503519,FR
2988503520,2988503535,NL
2988503536,2988503551,FI
-2988503552,2988503939,FR
+2988503552,2988503871,FR
+2988503872,2988503903,DE
+2988503904,2988503911,FI
+2988503912,2988503919,NL
+2988503920,2988503927,FR
+2988503928,2988503931,IT
+2988503932,2988503935,NL
+2988503936,2988503939,FR
2988503940,2988503943,CH
2988503944,2988503947,PL
2988503948,2988503951,IE
2988503952,2988503987,FR
-2988503988,2988504003,PL
-2988504004,2988504015,FR
+2988503988,2988504007,PL
+2988504008,2988504015,FR
2988504016,2988504019,GB
2988504020,2988504023,BE
2988504024,2988504031,FR
@@ -71245,9 +72698,13 @@
2988504544,2988504559,PL
2988504560,2988504563,FR
2988504564,2988504567,PL
-2988504568,2988504571,FR
+2988504568,2988504571,CH
2988504572,2988504603,PL
-2988504604,2988504671,FR
+2988504604,2988504639,FR
+2988504640,2988504643,DE
+2988504644,2988504647,PT
+2988504648,2988504655,GB
+2988504656,2988504671,FR
2988504672,2988504703,PT
2988504704,2988504735,FR
2988504736,2988504743,PL
@@ -71273,7 +72730,8 @@
2988505212,2988505215,PT
2988505216,2988505247,FR
2988505248,2988505255,PL
-2988505256,2988505311,FR
+2988505256,2988505279,FR
+2988505280,2988505311,BE
2988505312,2988505315,DE
2988505316,2988505319,ES
2988505320,2988505323,PL
@@ -71308,7 +72766,9 @@
2988505812,2988505815,DE
2988505816,2988505819,GB
2988505820,2988505823,PL
-2988505824,2988506111,FR
+2988505824,2988505839,FR
+2988505840,2988505843,CH
+2988505844,2988506111,FR
2988506112,2988506143,BE
2988506144,2988506175,PT
2988506176,2988506191,IT
@@ -71457,7 +72917,7 @@
2988508072,2988508079,FR
2988508080,2988508095,ES
2988508096,2988508103,FR
-2988508104,2988508111,GB
+2988508104,2988508111,IT
2988508112,2988508127,BE
2988508128,2988508135,PL
2988508136,2988508143,GB
@@ -71496,7 +72956,7 @@
2988508688,2988508703,PL
2988508704,2988508711,GB
2988508712,2988508719,DE
-2988508720,2988508723,IT
+2988508720,2988508723,FR
2988508724,2988508735,GB
2988508736,2988508767,FR
2988508768,2988508799,PT
@@ -71507,7 +72967,8 @@
2988508876,2988508879,PT
2988508880,2988508895,DE
2988508896,2988508911,PL
-2988508912,2988508927,FR
+2988508912,2988508919,GB
+2988508920,2988508927,FR
2988508928,2988508943,GB
2988508944,2988508947,DE
2988508948,2988508951,FR
@@ -71537,7 +72998,8 @@
2988509412,2988509415,DE
2988509416,2988509419,ES
2988509420,2988509443,FR
-2988509444,2988509451,ES
+2988509444,2988509447,FI
+2988509448,2988509451,GB
2988509452,2988509455,PL
2988509456,2988509467,FR
2988509468,2988509503,NL
@@ -71558,15 +73020,14 @@
2988509712,2988509715,IE
2988509716,2988509719,GB
2988509720,2988509727,IT
-2988509728,2988509743,FR
-2988509744,2988509751,ES
+2988509728,2988509751,FR
2988509752,2988509759,DE
2988509760,2988509767,PL
2988509768,2988509775,IT
2988509776,2988509779,ES
2988509780,2988509783,GB
2988509784,2988509787,FR
-2988509788,2988509791,ES
+2988509788,2988509791,BE
2988509792,2988509823,NL
2988509824,2988509839,FR
2988509840,2988509855,ES
@@ -71583,8 +73044,7 @@
2988509940,2988509943,IT
2988509944,2988509951,FR
2988509952,2988509955,IT
-2988509956,2988509959,PL
-2988509960,2988509963,IT
+2988509956,2988509963,PL
2988509964,2988509967,GB
2988509968,2988509983,ES
2988509984,2988509987,DE
@@ -71605,7 +73065,11 @@
2988510176,2988510207,ES
2988510208,2988510211,FR
2988510212,2988510215,ES
-2988510216,2988510255,FR
+2988510216,2988510239,FR
+2988510240,2988510243,IT
+2988510244,2988510247,FR
+2988510248,2988510251,FI
+2988510252,2988510255,LT
2988510256,2988510259,GB
2988510260,2988510263,FR
2988510264,2988510271,PL
@@ -71634,9 +73098,7 @@
2988510560,2988510591,IT
2988510592,2988510623,BE
2988510624,2988510655,IE
-2988510656,2988510687,PL
-2988510688,2988510703,FR
-2988510704,2988510719,PL
+2988510656,2988510719,PL
2988510720,2988510751,FR
2988510752,2988510759,PL
2988510760,2988510767,FR
@@ -71693,8 +73155,7 @@
2988511824,2988511831,DE
2988511832,2988511835,GB
2988511836,2988511855,FR
-2988511856,2988511871,GB
-2988511872,2988511887,PL
+2988511856,2988511887,PL
2988511888,2988511903,FR
2988511904,2988511911,IT
2988511912,2988511915,FR
@@ -71714,7 +73175,7 @@
2988512096,2988512127,IE
2988512128,2988512143,PL
2988512144,2988512151,GB
-2988512152,2988512155,ES
+2988512152,2988512155,CH
2988512156,2988512159,FR
2988512160,2988512191,GB
2988512192,2988512195,FR
@@ -71790,7 +73251,11 @@
2988512964,2988512967,PL
2988512968,2988512971,GB
2988512972,2988512975,NL
-2988512976,2988512995,FR
+2988512976,2988512979,FI
+2988512980,2988512983,DE
+2988512984,2988512987,CH
+2988512988,2988512991,CZ
+2988512992,2988512995,FR
2988512996,2988512999,GB
2988513000,2988513003,FR
2988513004,2988513007,PL
@@ -71826,7 +73291,9 @@
2988513360,2988513375,GB
2988513376,2988513379,FR
2988513380,2988513383,PT
-2988513384,2988513407,FR
+2988513384,2988513387,FR
+2988513388,2988513391,CH
+2988513392,2988513407,FR
2988513408,2988513471,PL
2988513472,2988513503,FR
2988513504,2988513507,CH
@@ -71839,8 +73306,10 @@
2988513568,2988513575,GB
2988513576,2988513583,PL
2988513584,2988513599,IE
-2988513600,2988513671,FR
-2988513672,2988513675,ES
+2988513600,2988513631,FR
+2988513632,2988513647,ES
+2988513648,2988513671,FR
+2988513672,2988513675,PT
2988513676,2988513679,FR
2988513680,2988513683,ES
2988513684,2988513691,FR
@@ -71864,8 +73333,7 @@
2988513984,2988513991,GB
2988513992,2988513999,IE
2988514000,2988514015,FR
-2988514016,2988514019,ES
-2988514020,2988514023,NL
+2988514016,2988514023,ES
2988514024,2988514027,CH
2988514028,2988514031,PL
2988514032,2988514047,FR
@@ -71874,7 +73342,7 @@
2988514096,2988514099,DE
2988514100,2988514103,PL
2988514104,2988514111,FR
-2988514112,2988514115,DE
+2988514112,2988514115,IE
2988514116,2988514127,FR
2988514128,2988514131,IE
2988514132,2988514135,IT
@@ -71911,7 +73379,7 @@
2988514560,2988514623,FR
2988514624,2988514655,DE
2988514656,2988514671,FR
-2988514672,2988514675,GB
+2988514672,2988514675,CH
2988514676,2988514679,IT
2988514680,2988514687,FR
2988514688,2988514719,GB
@@ -72021,7 +73489,8 @@
2988525824,2988525839,FR
2988525840,2988525847,ES
2988525848,2988525851,IT
-2988525852,2988525887,DE
+2988525852,2988525855,DE
+2988525856,2988525887,FR
2988525888,2988525951,FI
2988525952,2988526079,ES
2988526080,2988526143,PT
@@ -72051,7 +73520,11 @@
2988526704,2988526711,FR
2988526712,2988526715,ES
2988526716,2988526719,GB
-2988526720,2988526847,FR
+2988526720,2988526727,FR
+2988526728,2988526735,DE
+2988526736,2988526751,PL
+2988526752,2988526783,GB
+2988526784,2988526847,FR
2988526848,2988526863,PL
2988526864,2988526867,GB
2988526868,2988526871,FR
@@ -72084,7 +73557,8 @@
2988527196,2988527199,FR
2988527200,2988527207,NL
2988527208,2988527211,DE
-2988527212,2988527391,FR
+2988527212,2988527359,FR
+2988527360,2988527391,DE
2988527392,2988527399,PL
2988527400,2988527407,DE
2988527408,2988527411,FR
@@ -72094,7 +73568,7 @@
2988527432,2988527439,IT
2988527440,2988527451,PL
2988527452,2988527455,PT
-2988527456,2988527459,IT
+2988527456,2988527459,LT
2988527460,2988527475,FR
2988527476,2988527479,ES
2988527480,2988527487,FR
@@ -72111,13 +73585,47 @@
2988527604,2988527607,FR
2988527608,2988527611,DE
2988527612,2988527615,PT
-2988527616,2988528127,DE
+2988527616,2988527619,ES
+2988527620,2988527623,PL
+2988527624,2988527631,ES
+2988527632,2988527667,FR
+2988527668,2988527671,IE
+2988527672,2988527675,ES
+2988527676,2988527679,DE
+2988527680,2988527683,ES
+2988527684,2988527695,FR
+2988527696,2988527711,GB
+2988527712,2988527743,FR
+2988527744,2988527747,IE
+2988527748,2988527751,ES
+2988527752,2988527755,DE
+2988527756,2988527823,FR
+2988527824,2988527827,ES
+2988527828,2988527831,DE
+2988527832,2988527839,ES
+2988527840,2988527843,PL
+2988527844,2988527847,NL
+2988527848,2988527851,LT
+2988527852,2988527855,GB
+2988527856,2988527871,FR
+2988527872,2988527903,PT
+2988527904,2988527935,ES
+2988527936,2988527967,DE
+2988527968,2988527983,PL
+2988527984,2988527999,FR
+2988528000,2988528007,IT
+2988528008,2988528015,ES
+2988528016,2988528063,IE
+2988528064,2988528071,GB
+2988528072,2988528075,NL
+2988528076,2988528079,BE
+2988528080,2988528127,FR
2988528128,2988528159,GB
2988528160,2988528175,ES
2988528176,2988528179,CH
2988528180,2988528183,IT
2988528184,2988528187,PL
-2988528188,2988528191,GB
+2988528188,2988528191,FR
2988528192,2988528207,IE
2988528208,2988528215,FR
2988528216,2988528219,IE
@@ -72125,8 +73633,12 @@
2988528224,2988528231,CH
2988528232,2988528235,GB
2988528236,2988528239,FR
-2988528240,2988528255,GB
-2988528256,2988528383,FR
+2988528240,2988528263,GB
+2988528264,2988528267,PL
+2988528268,2988528271,FR
+2988528272,2988528303,GB
+2988528304,2988528351,FR
+2988528352,2988528383,DE
2988528384,2988528399,GB
2988528400,2988528415,FR
2988528416,2988528423,GB
@@ -72151,7 +73663,17 @@
2988528644,2988528647,PL
2988528648,2988528671,FR
2988528672,2988528703,DE
-2988528704,2988528767,FR
+2988528704,2988528715,ES
+2988528716,2988528723,IT
+2988528724,2988528727,GB
+2988528728,2988528731,FR
+2988528732,2988528735,DE
+2988528736,2988528739,FI
+2988528740,2988528743,IE
+2988528744,2988528747,NL
+2988528748,2988528759,PL
+2988528760,2988528763,GB
+2988528764,2988528767,FR
2988528768,2988528771,DE
2988528772,2988528783,FR
2988528784,2988528787,ES
@@ -72160,16 +73682,17 @@
2988528796,2988528799,GB
2988528800,2988528863,FR
2988528864,2988528867,DE
-2988528868,2988528875,FR
-2988528876,2988528879,GB
+2988528868,2988528871,FR
+2988528872,2988528879,GB
2988528880,2988528895,ES
2988528896,2988528911,FR
2988528912,2988528919,PL
2988528920,2988528923,CH
2988528924,2988528927,GB
2988528928,2988528959,FR
-2988528960,2988528991,FI
-2988528992,2988529007,LT
+2988528960,2988528995,FI
+2988528996,2988528999,BE
+2988529000,2988529007,IE
2988529008,2988529023,FI
2988529024,2988529031,PL
2988529032,2988529047,FR
@@ -72178,7 +73701,7 @@
2988529056,2988529119,FR
2988529120,2988529151,NL
2988529152,2988529159,IT
-2988529160,2988529163,IE
+2988529160,2988529163,GB
2988529164,2988529167,DE
2988529168,2988529171,IE
2988529172,2988529175,PT
@@ -72214,7 +73737,7 @@
2988529600,2988529607,IT
2988529608,2988529631,FR
2988529632,2988529647,LT
-2988529648,2988529663,FR
+2988529648,2988529663,FI
2988529664,2988529679,PL
2988529680,2988529703,FR
2988529704,2988529707,DE
@@ -72255,9 +73778,7 @@
2988530064,2988530079,IE
2988530080,2988530095,FR
2988530096,2988530099,DE
-2988530100,2988530103,FR
-2988530104,2988530111,GB
-2988530112,2988530191,FR
+2988530100,2988530191,FR
2988530192,2988530207,NL
2988530208,2988530239,PL
2988530240,2988530271,FR
@@ -72266,8 +73787,8 @@
2988530308,2988530311,PL
2988530312,2988530323,FR
2988530324,2988530327,GB
-2988530328,2988530351,FR
-2988530352,2988530371,ES
+2988530328,2988530367,FR
+2988530368,2988530371,ES
2988530372,2988530379,FR
2988530380,2988530383,CH
2988530384,2988530391,FR
@@ -72324,8 +73845,10 @@
2988531192,2988531199,FR
2988531200,2988531247,ES
2988531248,2988531259,PL
-2988531260,2988531263,GB
-2988531264,2988531295,FR
+2988531260,2988531271,GB
+2988531272,2988531279,ES
+2988531280,2988531287,PT
+2988531288,2988531295,ES
2988531296,2988531311,IE
2988531312,2988531319,FR
2988531320,2988531323,PT
@@ -72401,7 +73924,9 @@
2988540652,2988540667,PL
2988540668,2988540671,IT
2988540672,2988540683,PL
-2988540684,2988540715,FR
+2988540684,2988540707,FR
+2988540708,2988540711,DE
+2988540712,2988540715,FR
2988540716,2988540719,PL
2988540720,2988540735,DE
2988540736,2988540751,ES
@@ -72411,15 +73936,12 @@
2988540768,2988540775,PL
2988540776,2988540783,BE
2988540784,2988540787,ES
-2988540788,2988540791,DE
-2988540792,2988540795,FR
+2988540788,2988540795,FR
2988540796,2988540799,GB
2988540800,2988540831,FR
2988540832,2988540839,PL
2988540840,2988540847,GB
-2988540848,2988540855,FR
-2988540856,2988540863,ES
-2988540864,2988540931,FR
+2988540848,2988540931,FR
2988540932,2988540935,DE
2988540936,2988540943,FR
2988540944,2988540959,ES
@@ -72445,7 +73967,14 @@
2988541316,2988541319,CH
2988541320,2988541327,DE
2988541328,2988541335,PL
-2988541336,2988541375,FR
+2988541336,2988541343,FR
+2988541344,2988541347,GB
+2988541348,2988541351,IT
+2988541352,2988541355,IE
+2988541356,2988541359,IT
+2988541360,2988541367,ES
+2988541368,2988541371,PL
+2988541372,2988541375,GB
2988541376,2988541391,BE
2988541392,2988541407,CH
2988541408,2988541423,BE
@@ -72528,7 +74057,7 @@
2988542072,2988542255,FR
2988542256,2988542271,IT
2988542272,2988542335,ES
-2988542336,2988542367,FR
+2988542336,2988542367,DE
2988542368,2988542399,CZ
2988542400,2988542403,FI
2988542404,2988542407,FR
@@ -72632,7 +74161,8 @@
2988543936,2988543947,PL
2988543948,2988543959,BE
2988543960,2988543967,PL
-2988543968,2988544015,FR
+2988543968,2988543999,FR
+2988544000,2988544015,DE
2988544016,2988544023,GB
2988544024,2988544031,IE
2988544032,2988544035,PL
@@ -72660,7 +74190,8 @@
2988544304,2988544307,PL
2988544308,2988544311,IT
2988544312,2988544315,DE
-2988544316,2988544323,FR
+2988544316,2988544319,FR
+2988544320,2988544323,PL
2988544324,2988544327,ES
2988544328,2988544331,PL
2988544332,2988544351,FR
@@ -72680,13 +74211,12 @@
2988544544,2988544639,ES
2988544640,2988544647,PL
2988544648,2988544655,FR
-2988544656,2988544659,ES
-2988544660,2988544663,FR
+2988544656,2988544663,ES
2988544664,2988544667,DE
2988544668,2988544671,ES
2988544672,2988544687,GB
2988544688,2988544703,PL
-2988544704,2988544719,IT
+2988544704,2988544719,GB
2988544720,2988544723,FR
2988544724,2988544727,DE
2988544728,2988544767,FR
@@ -72748,8 +74278,7 @@
2988545448,2988545455,PL
2988545456,2988545471,FR
2988545472,2988545503,ES
-2988545504,2988545507,FR
-2988545508,2988545511,DE
+2988545504,2988545511,DE
2988545512,2988545515,IT
2988545516,2988545523,PL
2988545524,2988545527,FR
@@ -72816,8 +74345,7 @@
2988546296,2988546299,PL
2988546300,2988546307,ES
2988546308,2988546311,NL
-2988546312,2988546315,IT
-2988546316,2988546319,FR
+2988546312,2988546319,FR
2988546320,2988546327,CH
2988546328,2988546335,ES
2988546336,2988546351,PT
@@ -72828,8 +74356,9 @@
2988546448,2988546463,ES
2988546464,2988546527,FR
2988546528,2988546535,BE
-2988546536,2988546539,IE
-2988546540,2988546547,ES
+2988546536,2988546539,FR
+2988546540,2988546543,DE
+2988546544,2988546547,ES
2988546548,2988546559,FR
2988546560,2988546567,NL
2988546568,2988546571,PL
@@ -72956,7 +74485,12 @@
2988547872,2988547903,GB
2988547904,2988547935,FR
2988547936,2988547967,LT
-2988547968,2988548047,FR
+2988547968,2988547971,GB
+2988547972,2988547975,DE
+2988547976,2988547983,PL
+2988547984,2988548015,FR
+2988548016,2988548031,ES
+2988548032,2988548047,FR
2988548048,2988548055,ES
2988548056,2988548059,PL
2988548060,2988548063,FR
@@ -73047,7 +74581,7 @@
2988557388,2988557391,CZ
2988557392,2988557399,PL
2988557400,2988557403,ES
-2988557404,2988557407,FR
+2988557404,2988557407,IT
2988557408,2988557427,ES
2988557428,2988557431,DE
2988557432,2988557439,PL
@@ -73086,7 +74620,8 @@
2988558084,2988558087,PL
2988558088,2988558095,FR
2988558096,2988558103,PL
-2988558104,2988558111,FR
+2988558104,2988558107,NL
+2988558108,2988558111,IT
2988558112,2988558115,IE
2988558116,2988558123,GB
2988558124,2988558127,FR
@@ -73153,7 +74688,8 @@
2988559736,2988559743,GB
2988559744,2988559807,FR
2988559808,2988559871,ES
-2988559872,2988560387,IT
+2988559872,2988560383,IT
+2988560384,2988560387,FR
2988560388,2988560391,ES
2988560392,2988560399,IT
2988560400,2988560415,IE
@@ -73260,7 +74796,9 @@
2988561760,2988561763,PL
2988561764,2988561767,PT
2988561768,2988561775,PL
-2988561776,2988561843,FR
+2988561776,2988561791,FR
+2988561792,2988561823,PL
+2988561824,2988561843,FR
2988561844,2988561847,IT
2988561848,2988561855,FR
2988561856,2988561871,IE
@@ -73314,7 +74852,7 @@
2988563068,2988563075,PT
2988563076,2988563079,GB
2988563080,2988563083,DE
-2988563084,2988563087,FR
+2988563084,2988563087,LT
2988563088,2988563103,PL
2988563104,2988563135,FR
2988563136,2988563151,PL
@@ -73646,7 +75184,11 @@
2991985920,2991986175,JP
2991986176,2991986431,UA
2991986432,2991986687,JP
-2991986688,2992111615,UA
+2991986688,2991988263,UA
+2991988264,2991988271,IN
+2991988272,2992014727,UA
+2992014728,2992014735,IN
+2992014736,2992111615,UA
2992111616,2992373759,KZ
2992373760,2992635903,UA
2992635904,2993684479,GB
@@ -73671,7 +75213,9 @@
2996174848,2996305919,UA
2996305920,2996436991,QA
2996436992,2996469759,BY
-2996469760,2996535295,RU
+2996469760,2996502399,RU
+2996502400,2996502431,TR
+2996502432,2996535295,RU
2996535296,2996568063,DK
2996568064,2996600831,ES
2996600832,2996633599,RO
@@ -73731,12 +75275,9 @@
2996999680,2996999935,GB
2996999936,2997000447,DE
2997000448,2997000703,RU
-2997000704,2997000767,DE
-2997000768,2997000831,CY
+2997000704,2997000831,DE
2997000832,2997000959,CA
-2997000960,2997000991,DE
-2997000992,2997001119,RO
-2997001120,2997001471,DE
+2997000960,2997001471,DE
2997001472,2997001727,BZ
2997001728,2997001983,TR
2997001984,2997003023,DE
@@ -73774,9 +75315,7 @@
2997008512,2997008639,LT
2997008640,2997008959,DE
2997008960,2997009023,RU
-2997009024,2997010495,DE
-2997010496,2997010559,CY
-2997010560,2997018623,DE
+2997009024,2997018623,DE
2997018624,2997019135,GB
2997019136,2997019391,TR
2997019392,2997019647,GB
@@ -73962,6 +75501,7 @@
3000545280,3000547327,RU
3000547328,3000549375,UA
3000549376,3000551423,SE
+3000551424,3000553471,PL
3000553472,3000555519,KG
3000555520,3000557567,RU
3000557568,3000561663,UA
@@ -73998,7 +75538,7 @@
3000664064,3000668159,RO
3000668160,3000672255,RU
3000672256,3000676351,HR
-3000676352,3000680447,RO
+3000676352,3000684543,RO
3000684544,3000688639,RU
3000688640,3000692735,PL
3000692736,3000696831,UA
@@ -74087,7 +75627,71 @@
3001862144,3001863167,EE
3001863168,3001864191,LT
3001864192,3001868287,RU
-3001868288,3001869055,FR
+3001868288,3001868799,FR
+3001868800,3001868803,US
+3001868804,3001868807,CN
+3001868808,3001868811,JP
+3001868812,3001868815,DE
+3001868816,3001868819,FR
+3001868820,3001868823,GB
+3001868824,3001868827,BR
+3001868828,3001868831,IT
+3001868832,3001868835,FR
+3001868836,3001868839,IN
+3001868840,3001868843,RU
+3001868844,3001868847,ES
+3001868848,3001868851,AU
+3001868852,3001868855,MX
+3001868856,3001868859,KR
+3001868860,3001868863,FR
+3001868864,3001868867,TR
+3001868868,3001868871,ID
+3001868872,3001868875,CH
+3001868876,3001868879,PL
+3001868880,3001868883,BE
+3001868884,3001868887,SE
+3001868888,3001868891,SA
+3001868892,3001868895,TW
+3001868896,3001868899,SJ
+3001868900,3001868903,AT
+3001868904,3001868907,AR
+3001868908,3001868911,ZA
+3001868912,3001868915,IR
+3001868916,3001868919,TH
+3001868920,3001868923,DK
+3001868924,3001868927,GR
+3001868928,3001868931,AE
+3001868932,3001868935,VE
+3001868936,3001868939,CD
+3001868940,3001868943,FI
+3001868944,3001868947,MY
+3001868948,3001868951,PT
+3001868952,3001868955,HK
+3001868956,3001868959,SG
+3001868960,3001868963,EG
+3001868964,3001868967,NG
+3001868968,3001868971,IL
+3001868972,3001868975,IE
+3001868976,3001868979,CL
+3001868980,3001868983,CZ
+3001868984,3001868987,PH
+3001868988,3001868991,PK
+3001868992,3001868995,RO
+3001868996,3001868999,DZ
+3001869000,3001869003,PE
+3001869004,3001869007,NZ
+3001869008,3001869011,KZ
+3001869012,3001869015,UA
+3001869016,3001869019,KW
+3001869020,3001869023,QA
+3001869024,3001869027,HU
+3001869028,3001869031,BD
+3001869032,3001869035,VN
+3001869036,3001869039,MA
+3001869040,3001869043,SK
+3001869044,3001869047,AO
+3001869048,3001869051,IQ
+3001869052,3001869055,LY
3001869056,3001869311,RU
3001869312,3001869312,FR
3001869313,3001869599,SA
@@ -74210,12 +75814,14 @@
3001977568,3001977575,CA
3001977576,3001977599,GB
3001977600,3001977855,DK
-3001977856,3001978031,GB
+3001977856,3001978015,GB
+3001978016,3001978023,CN
+3001978024,3001978031,GB
3001978032,3001978047,US
3001978048,3001978367,GB
3001978368,3001978495,US
3001978496,3001978527,RU
-3001978528,3001978543,PK
+3001978528,3001978543,GB
3001978544,3001978559,RU
3001978560,3001978591,US
3001978592,3001978607,RU
@@ -74227,7 +75833,8 @@
3001978784,3001978815,US
3001978816,3001978823,LK
3001978824,3001978847,GB
-3001978848,3001978879,UA
+3001978848,3001978863,UA
+3001978864,3001978879,PK
3001978880,3001982975,GB
3001982976,3001987071,CH
3001987072,3001991167,JO
@@ -74272,8 +75879,7 @@
3002619984,3002619991,GB
3002619992,3002620015,IT
3002620016,3002620031,GB
-3002620032,3002620039,DE
-3002620040,3002620047,IT
+3002620032,3002620047,IT
3002620048,3002620087,GB
3002620088,3002620103,IT
3002620104,3002620111,GB
@@ -74310,7 +75916,8 @@
3002673152,3002675199,GB
3002675200,3002677247,DK
3002677248,3002683391,RU
-3002683392,3002685439,DE
+3002683392,3002685183,DE
+3002685184,3002685439,CH
3002685440,3002687487,MT
3002687488,3002688511,GB
3002688512,3002689535,NL
@@ -74335,7 +75942,6 @@
3002730496,3002732543,DE
3002732544,3002734591,NL
3002734592,3002736639,CH
-3002736640,3002738687,FR
3002738688,3002740735,PL
3002740736,3002742783,GB
3002742784,3002744831,LI
@@ -74351,7 +75957,9 @@
3002763264,3002765311,RS
3002765312,3002767359,NL
3002767360,3002769407,RU
-3002769408,3002773503,DE
+3002769408,3002771711,DE
+3002771712,3002771719,NL
+3002771720,3002773503,DE
3002773504,3002775551,GB
3002775552,3002777599,RO
3002777600,3002779647,NL
@@ -74433,7 +76041,9 @@
3003092992,3003095039,NO
3003095040,3003095567,AT
3003095568,3003095583,CZ
-3003095584,3003096063,AT
+3003095584,3003095871,AT
+3003095872,3003095935,IT
+3003095936,3003096063,AT
3003096064,3003096079,CZ
3003096080,3003097087,AT
3003097088,3003099135,FR
@@ -74678,7 +76288,9 @@
3035348992,3035357183,AU
3035357184,3035365375,JP
3035365376,3035627519,KR
-3035627520,3036610559,ID
+3035627520,3035660287,ID
+3035660288,3035693055,SG
+3035693056,3036610559,ID
3036610560,3036676095,SG
3036676096,3037790207,AR
3037790208,3037855743,VE
@@ -74686,7 +76298,9 @@
3038511104,3038773247,AR
3039035392,3039166463,DO
3039297536,3039363071,PY
+3039428608,3039494143,CL
3039821824,3040346111,CO
+3040870400,3041001471,PE
3053453312,3054501887,ID
3054501888,3054534655,HK
3054534656,3054537727,PH
@@ -74959,7 +76573,8 @@
3093249600,3093249623,AU
3093249624,3093249679,US
3093249680,3093249687,AU
-3093249688,3093266431,US
+3093249688,3093282815,US
+3093282816,3093299199,CA
3093299200,3093940991,US
3093940992,3093941055,CN
3093941056,3093941103,US
@@ -75101,14 +76716,13 @@
3097493504,3097755647,CA
3097755648,3098095615,US
3098095616,3098099711,CA
-3098099712,3098116095,US
+3098099712,3098148863,US
3098148864,3098165247,JM
3098165248,3098181631,US
3098181632,3098185727,CA
3098185728,3098263551,US
3098263552,3098271743,CA
-3098271744,3098275839,US
-3098279936,3098279943,US
+3098271744,3098279943,US
3098279944,3098279951,KW
3098279952,3098280591,US
3098280592,3098280599,PA
@@ -75116,7 +76730,15 @@
3098281504,3098281511,PA
3098281512,3098281711,US
3098281712,3098281719,PA
-3098281720,3098290223,US
+3098281720,3098286287,US
+3098286288,3098286295,IN
+3098286296,3098286399,US
+3098286400,3098286431,BR
+3098286432,3098288343,US
+3098288344,3098288351,BR
+3098288352,3098288775,US
+3098288776,3098288783,BR
+3098288784,3098290223,US
3098290224,3098290231,IN
3098290232,3098291087,US
3098291088,3098291095,IN
@@ -75126,27 +76748,51 @@
3098291152,3098291159,NL
3098291160,3098295751,US
3098295752,3098295759,PL
-3098295760,3098322367,US
+3098295760,3098321663,US
+3098321664,3098321695,IN
+3098321696,3098322367,US
3098322368,3098322375,BD
3098322376,3098322383,US
3098322384,3098322391,BD
3098322392,3098322695,US
3098322696,3098322703,BD
-3098322704,3098333951,US
+3098322704,3098331151,US
+3098331152,3098331159,HK
+3098331160,3098331471,US
+3098331472,3098331479,CL
+3098331480,3098333951,US
3098333952,3098333959,BD
-3098333960,3098365535,US
+3098333960,3098336303,US
+3098336304,3098336311,MY
+3098336312,3098365535,US
3098365536,3098365551,IN
3098365552,3098365951,US
3098365952,3098365959,MX
-3098365960,3098371303,US
+3098365960,3098371191,US
+3098371192,3098371199,BR
+3098371200,3098371303,US
3098371304,3098371311,PE
-3098371312,3098476543,US
+3098371312,3098371495,US
+3098371496,3098371503,JO
+3098371504,3098375583,US
+3098375584,3098375615,BR
+3098375616,3098376863,US
+3098376864,3098376895,BR
+3098376896,3098377727,US
+3098377728,3098377759,AR
+3098377760,3098381455,US
+3098381456,3098381471,LT
+3098381472,3098388175,US
+3098388176,3098388183,SA
+3098388184,3098476543,US
3098476544,3098492927,CA
3098492928,3098495999,US
3098496000,3098496255,CA
3098496256,3098502143,US
3098502144,3098502207,IN
-3098502208,3103784959,US
+3098502208,3098507263,US
+3098507264,3098507519,CA
+3098507520,3103784959,US
3103784960,3107979263,EU
3120562176,3120594943,CO
3120594944,3120599039,AR
@@ -75161,7 +76807,8 @@
3120644096,3120660479,DO
3120660480,3120668671,PA
3120676864,3120680959,HT
-3120685056,3120689151,AR
+3120680960,3120691199,AR
+3120691200,3120693247,CO
3120693248,3120726015,BO
3120726016,3120734207,HN
3120742400,3120750591,PY
@@ -75224,8 +76871,11 @@
3130261504,3130277887,CL
3130294272,3130302463,AR
3130310656,3130312703,PA
-3130318848,3130322943,AR
+3130314752,3130315775,CL
+3130315776,3130316799,CR
+3130318848,3130327039,AR
3130327040,3130392575,DO
+3130458112,3130523647,GT
3130523648,3130654719,AR
3130654720,3130720255,CO
3130785792,3130818559,CL
@@ -75250,7 +76900,11 @@
3133079552,3133145087,AR
3133145088,3145727999,BR
3145728000,3154116607,MX
-3154149376,3154157567,UA
+3154116608,3154124799,RU
+3154124800,3154126847,PL
+3154126848,3154128895,RU
+3154128896,3154132991,EE
+3154132992,3154157567,UA
3154157568,3154173951,RU
3154173952,3154182143,MD
3154182144,3154247679,DE
@@ -75292,6 +76946,7 @@
3157786624,3158048767,TR
3158048768,3158310911,CH
3158310912,3158312959,FI
+3158312960,3158315007,AZ
3158315008,3158317055,DE
3158317056,3158319103,SI
3158319104,3158321151,GB
@@ -75341,8 +76996,8 @@
3158395168,3158395175,DE
3158395176,3158395191,AT
3158395192,3158395199,DE
-3158395200,3158395263,AT
-3158395264,3158395295,DE
+3158395200,3158395247,AT
+3158395248,3158395295,DE
3158395296,3158395359,AT
3158395360,3158395367,DE
3158395368,3158395431,AT
@@ -75426,8 +77081,7 @@
3158893568,3158893823,GB
3158893824,3158895167,DE
3158895168,3158895231,RU
-3158895232,3158895359,TR
-3158895360,3158895423,DE
+3158895232,3158895423,DE
3158895424,3158895487,RU
3158895488,3158895551,MK
3158895552,3158895615,AE
@@ -75575,7 +77229,9 @@
3160332760,3160332767,AU
3160332768,3160333055,NO
3160333056,3160333087,CO
-3160333088,3160334335,NO
+3160333088,3160334063,NO
+3160334064,3160334071,PA
+3160334072,3160334335,NO
3160334336,3160336383,RU
3160336384,3160338431,CZ
3160338432,3160340479,GB
@@ -75770,19 +77426,22 @@
3163161696,3163161727,BG
3163161728,3163161759,DE
3163161760,3163161791,BR
-3163161792,3163161887,DE
+3163161792,3163161823,DE
+3163161824,3163161855,US
+3163161856,3163161887,BR
3163161888,3163161951,US
3163161952,3163162079,DE
3163162080,3163162111,RU
3163162112,3163162143,TR
-3163162144,3163162239,DE
-3163162240,3163162271,US
+3163162144,3163162271,DE
3163162272,3163162303,NL
3163162304,3163162367,DE
3163162368,3163162399,TR
3163162400,3163162431,DE
3163162432,3163162463,CY
-3163162464,3163163711,DE
+3163162464,3163162559,DE
+3163162560,3163162591,US
+3163162592,3163163711,DE
3163163712,3163163743,BR
3163163744,3163163807,DE
3163163808,3163163839,CY
@@ -75805,24 +77464,31 @@
3163164544,3163164575,RU
3163164576,3163164607,DE
3163164608,3163164639,ES
-3163164640,3163165759,DE
+3163164640,3163164671,US
+3163164672,3163165695,DE
+3163165696,3163165727,US
+3163165728,3163165759,DE
3163165760,3163165791,PL
3163165792,3163165823,RU
-3163165824,3163166015,DE
+3163165824,3163165855,BR
+3163165856,3163165983,DE
+3163165984,3163166015,CH
3163166016,3163166047,US
3163166048,3163166175,DE
3163166176,3163166207,RU
3163166208,3163166239,TR
3163166240,3163166271,IT
-3163166272,3163166367,DE
-3163166368,3163166399,US
+3163166272,3163166335,DE
+3163166336,3163166399,US
3163166400,3163166431,DE
3163166432,3163166463,BR
3163166464,3163166495,DE
3163166496,3163166527,RO
3163166528,3163166559,DE
3163166560,3163166591,HU
-3163166592,3163166687,DE
+3163166592,3163166623,DE
+3163166624,3163166655,US
+3163166656,3163166687,DE
3163166688,3163166719,RU
3163166720,3163167775,DE
3163167776,3163167807,GR
@@ -75830,7 +77496,7 @@
3163167840,3163167871,BR
3163167872,3163167903,DE
3163167904,3163167935,UA
-3163167936,3163167967,DE
+3163167936,3163167967,US
3163167968,3163167999,TR
3163168000,3163168031,DE
3163168032,3163168095,RU
@@ -75853,9 +77519,7 @@
3163168704,3163168735,GR
3163168736,3163169823,DE
3163169824,3163169855,RU
-3163169856,3163169951,DE
-3163169952,3163169983,GB
-3163169984,3163170015,DE
+3163169856,3163170015,DE
3163170016,3163170047,ES
3163170048,3163170079,RU
3163170080,3163170111,TR
@@ -75874,7 +77538,8 @@
3163170624,3163170655,GR
3163170656,3163170751,DE
3163170752,3163170783,CH
-3163170784,3163171871,DE
+3163170784,3163170815,US
+3163170816,3163171871,DE
3163171872,3163171903,RO
3163171904,3163171935,BZ
3163171936,3163171967,DE
@@ -75883,15 +77548,20 @@
3163172096,3163172127,BR
3163172128,3163172159,US
3163172160,3163172191,TR
-3163172192,3163172319,DE
+3163172192,3163172255,DE
+3163172256,3163172287,US
+3163172288,3163172319,DE
3163172320,3163172351,NL
3163172352,3163172383,GB
-3163172384,3163172479,DE
-3163172480,3163172511,US
+3163172384,3163172447,DE
+3163172448,3163172511,US
3163172512,3163172543,RU
-3163172544,3163172607,DE
+3163172544,3163172575,DE
+3163172576,3163172607,MA
3163172608,3163172639,DK
-3163172640,3163172735,DE
+3163172640,3163172671,LV
+3163172672,3163172703,BR
+3163172704,3163172735,DE
3163172736,3163172767,GR
3163172768,3163173919,DE
3163173920,3163173951,TW
@@ -75900,9 +77570,8 @@
3163174048,3163174079,DK
3163174080,3163174111,US
3163174112,3163174143,BE
-3163174144,3163174175,DE
-3163174176,3163174207,US
-3163174208,3163174239,DE
+3163174144,3163174175,BD
+3163174176,3163174239,DE
3163174240,3163174271,TW
3163174272,3163174303,DE
3163174304,3163174335,IL
@@ -75918,20 +77587,23 @@
3163174656,3163174687,RU
3163174688,3163174719,DE
3163174720,3163174751,NL
-3163174752,3163174815,DE
+3163174752,3163174783,TR
+3163174784,3163174815,DE
3163174816,3163174847,CA
3163174848,3163174879,TR
3163174880,3163174911,RU
-3163174912,3163176095,DE
+3163174912,3163175999,DE
+3163176000,3163176031,US
+3163176032,3163176063,DE
+3163176064,3163176095,RU
3163176096,3163176127,CY
3163176128,3163176159,US
3163176160,3163176255,DE
3163176256,3163176287,UG
-3163176288,3163176319,PT
-3163176320,3163176479,DE
+3163176288,3163176479,DE
3163176480,3163176511,GB
-3163176512,3163176543,TR
-3163176544,3163176575,DE
+3163176512,3163176543,DE
+3163176544,3163176575,US
3163176576,3163176607,GR
3163176608,3163176639,TW
3163176640,3163176767,DE
@@ -76024,7 +77696,10 @@
3164949152,3164949155,NL
3164949156,3164949159,DE
3164949160,3164949163,PL
-3164949164,3164949183,FR
+3164949164,3164949167,FR
+3164949168,3164949175,GB
+3164949176,3164949179,ES
+3164949180,3164949183,FR
3164949184,3164949199,GB
3164949200,3164949215,FR
3164949216,3164949219,PL
@@ -76159,7 +77834,9 @@
3164953312,3164953319,CZ
3164953320,3164953327,BE
3164953328,3164953375,PL
-3164953376,3164953391,FR
+3164953376,3164953379,NL
+3164953380,3164953383,GB
+3164953384,3164953391,PL
3164953392,3164953395,IT
3164953396,3164953399,NL
3164953400,3164953403,BE
@@ -76239,8 +77916,7 @@
3164959896,3164959903,PL
3164959904,3164959919,DE
3164959920,3164959927,FR
-3164959928,3164959931,GB
-3164959932,3164959935,ES
+3164959928,3164959935,GB
3164959936,3164959999,FR
3164960000,3164960259,DE
3164960260,3164960263,FR
@@ -76372,11 +78048,11 @@
3164962112,3164962143,GB
3164962144,3164962151,ES
3164962152,3164962159,DE
-3164962160,3164962203,FR
+3164962160,3164962199,FR
+3164962200,3164962203,GB
3164962204,3164962207,PT
-3164962208,3164962211,GB
-3164962212,3164962215,PL
-3164962216,3164962239,FR
+3164962208,3164962211,FI
+3164962212,3164962239,FR
3164962240,3164962247,PL
3164962248,3164962251,FR
3164962252,3164962255,DE
@@ -76384,7 +78060,9 @@
3164962260,3164962263,DE
3164962264,3164962279,ES
3164962280,3164962283,DE
-3164962284,3164962295,ES
+3164962284,3164962287,ES
+3164962288,3164962291,FR
+3164962292,3164962295,ES
3164962296,3164962303,PL
3164962304,3164962319,NL
3164962320,3164962335,FR
@@ -76405,7 +78083,8 @@
3164962632,3164962639,FR
3164962640,3164962647,ES
3164962648,3164962655,PT
-3164962656,3164962687,ES
+3164962656,3164962663,GB
+3164962664,3164962687,ES
3164962688,3164962703,PL
3164962704,3164962715,FR
3164962716,3164962719,NL
@@ -76540,13 +78219,13 @@
3164970848,3164970887,FR
3164970888,3164970891,GB
3164970892,3164970911,FR
-3164970912,3164970915,ES
+3164970912,3164970915,NL
3164970916,3164970919,FR
3164970920,3164970923,GB
3164970924,3164970927,LT
3164970928,3164970991,FR
3164970992,3164971007,BE
-3164971008,3164971011,ES
+3164971008,3164971011,IT
3164971012,3164971015,FR
3164971016,3164971023,PL
3164971024,3164971071,FR
@@ -76571,11 +78250,12 @@
3164971808,3164971903,BE
3164971904,3164971967,DE
3164971968,3164971983,FR
-3164971984,3164971999,ES
+3164971984,3164971991,ES
+3164971992,3164971999,FR
3164972000,3164972015,CH
3164972016,3164972019,ES
3164972020,3164972027,FR
-3164972028,3164972031,ES
+3164972028,3164972031,CH
3164972032,3164972287,GB
3164972288,3164972319,FR
3164972320,3164972351,DE
@@ -76585,18 +78265,65 @@
3164972500,3164972511,DE
3164972512,3164972527,GB
3164972528,3164972531,DE
-3164972532,3164972799,FR
+3164972532,3164972559,FR
+3164972560,3164972575,IT
+3164972576,3164972579,CZ
+3164972580,3164972583,GB
+3164972584,3164972587,NL
+3164972588,3164972591,FR
+3164972592,3164972595,IE
+3164972596,3164972599,PL
+3164972600,3164972607,FR
+3164972608,3164972639,PL
+3164972640,3164972671,IE
+3164972672,3164972679,PL
+3164972680,3164972691,FR
+3164972692,3164972695,FI
+3164972696,3164972699,FR
+3164972700,3164972703,DE
+3164972704,3164972735,FR
+3164972736,3164972767,GB
+3164972768,3164972799,IT
3164972800,3164973311,ES
-3164973312,3164973823,FR
+3164973312,3164973407,DE
+3164973408,3164973415,GB
+3164973416,3164973419,FR
+3164973420,3164973423,ES
+3164973424,3164973439,DE
+3164973440,3164973503,PL
+3164973504,3164973511,FR
+3164973512,3164973515,ES
+3164973516,3164973519,DE
+3164973520,3164973551,PL
+3164973552,3164973555,GB
+3164973556,3164973559,FR
+3164973560,3164973563,BE
+3164973564,3164973575,CZ
+3164973576,3164973583,GB
+3164973584,3164973599,FR
+3164973600,3164973615,IE
+3164973616,3164973623,BE
+3164973624,3164973627,PL
+3164973628,3164973631,CH
+3164973632,3164973663,IE
+3164973664,3164973695,ES
+3164973696,3164973727,FR
+3164973728,3164973743,GB
+3164973744,3164973759,FR
+3164973760,3164973815,GB
+3164973816,3164973823,FR
3164973824,3164973855,DE
3164973856,3164973863,PL
3164973864,3164973867,FR
-3164973868,3164973875,ES
+3164973868,3164973871,ES
+3164973872,3164973875,PL
3164973876,3164973879,GB
3164973880,3164973883,FR
3164973884,3164973887,DE
-3164973888,3164973919,ES
-3164973920,3164973935,FR
+3164973888,3164973903,GB
+3164973904,3164973911,FR
+3164973912,3164973915,DE
+3164973916,3164973935,FR
3164973936,3164973939,GB
3164973940,3164973943,FR
3164973944,3164973951,PL
@@ -76605,8 +78332,8 @@
3164974624,3164974647,FR
3164974648,3164974651,PT
3164974652,3164974655,DE
-3164974656,3164974663,FR
-3164974664,3164974667,GB
+3164974656,3164974659,BE
+3164974660,3164974667,GB
3164974668,3164974671,DE
3164974672,3164974675,FR
3164974676,3164974719,PL
@@ -76621,9 +78348,7 @@
3164975104,3164975167,CH
3164975168,3164975231,GB
3164975232,3164975299,IT
-3164975300,3164975303,ES
-3164975304,3164975311,IT
-3164975312,3164975343,ES
+3164975300,3164975343,ES
3164975344,3164975351,GB
3164975352,3164975355,NL
3164975356,3164975359,FR
@@ -76632,7 +78357,7 @@
3164975664,3164975679,DE
3164975680,3164975695,GB
3164975696,3164975699,PL
-3164975700,3164975703,ES
+3164975700,3164975703,DE
3164975704,3164975719,PL
3164975720,3164975731,ES
3164975732,3164975735,PT
@@ -76643,7 +78368,7 @@
3164975760,3164975775,PL
3164975776,3164975807,FR
3164975808,3164975823,PL
-3164975824,3164975839,GB
+3164975824,3164975839,ES
3164975840,3164975843,DE
3164975844,3164975847,PL
3164975848,3164975851,ES
@@ -76652,15 +78377,16 @@
3164975936,3164975939,ES
3164975940,3164975943,PT
3164975944,3164975947,PL
-3164975948,3164975967,GB
+3164975948,3164975951,NL
+3164975952,3164975967,GB
3164975968,3164975983,NL
3164975984,3164975987,PL
3164975988,3164975991,DE
3164975992,3164976011,PL
3164976012,3164976015,ES
3164976016,3164976023,PL
-3164976024,3164976027,ES
-3164976028,3164976063,FR
+3164976024,3164976031,ES
+3164976032,3164976063,FR
3164976064,3164976095,PT
3164976096,3164976127,PL
3164976128,3164976131,NL
@@ -76703,9 +78429,9 @@
3164976480,3164976511,PL
3164976512,3164976767,FR
3164976768,3164976783,DE
-3164976784,3164976799,ES
+3164976784,3164976799,CZ
3164976800,3164976815,DE
-3164976816,3164976831,GB
+3164976816,3164976831,CZ
3164976832,3164976835,IT
3164976836,3164976839,ES
3164976840,3164976847,FR
@@ -76749,11 +78475,8 @@
3164978156,3164978159,DE
3164978160,3164978175,FR
3164978176,3164978431,IT
-3164978432,3164978495,FR
-3164978496,3164978511,IT
-3164978512,3164978527,ES
-3164978528,3164978543,FR
-3164978544,3164978563,PT
+3164978432,3164978559,FR
+3164978560,3164978563,PT
3164978564,3164978567,PL
3164978568,3164978571,GB
3164978572,3164978575,FR
@@ -77006,6 +78729,8 @@
3188236288,3188237311,PA
3188237312,3188238335,VE
3188240384,3188241407,CO
+3188241408,3188242431,EC
+3188242432,3188244479,AR
3188244480,3188260863,CO
3188260864,3188269055,AR
3188269056,3188273151,VE
@@ -77076,6 +78801,7 @@
3191093248,3191095295,AR
3191095296,3191099391,EC
3191103488,3191107583,CO
+3191107584,3191111679,PE
3191111680,3191128063,PY
3191128064,3191132159,EC
3191136256,3191144447,DO
@@ -77244,10 +78970,10 @@
3194994688,3195023359,AR
3195023360,3195024383,CL
3195024384,3195025407,UY
-3195025408,3195035647,AR
+3195025408,3195043839,AR
3195043840,3195060223,CO
3195060224,3195064319,UY
-3195068416,3195072511,AN
+3195068416,3195076607,AN
3195076608,3195084799,CL
3195092992,3195097087,AR
3195101184,3195109375,CR
@@ -77366,6 +79092,8 @@
3201302528,3201433599,CL
3201433600,3201499135,AR
3201499136,3201515519,CL
+3201515520,3201519615,AR
+3201523712,3201531903,CR
3201531904,3201540095,AR
3201540096,3201544191,CL
3201548288,3201556479,AR
@@ -79590,9 +81318,7 @@
3230368768,3230370303,US
3230370304,3230370559,CA
3230370816,3230400511,CA
-3230400512,3230681599,EU
-3230681600,3230682623,FR
-3230682624,3230793727,EU
+3230681088,3230683135,FR
3230793728,3230823679,US
3230823680,3230823935,DK
3230824192,3230824447,FR
@@ -79732,7 +81458,8 @@
3230996480,3230997247,US
3230997248,3230997503,AT
3230997504,3230997759,US
-3230997760,3230999039,NL
+3230997760,3230998015,SE
+3230998016,3230999039,NL
3230999040,3230999295,US
3230999296,3230999551,NL
3230999552,3230999807,AU
@@ -80287,7 +82014,10 @@
3232131072,3232133119,DE
3232133120,3232133631,UA
3232133632,3232134143,DE
-3232134144,3232137215,EU
+3232134144,3232135167,RU
+3232135168,3232135679,PL
+3232135680,3232135935,RO
+3232135936,3232137215,RU
3232137216,3232139263,UA
3232139264,3232140287,GB
3232140288,3232141311,FR
@@ -81154,6 +82884,7 @@
3238007040,3238010879,NL
3238010880,3238017023,CH
3238017024,3238018303,DK
+3238018304,3238018559,UA
3238018560,3238018815,FR
3238018816,3238019071,DE
3238019072,3238035455,PL
@@ -81202,7 +82933,9 @@
3238502400,3238504447,RU
3238504448,3238526975,DE
3238526976,3238527231,RU
-3238527232,3238542591,CH
+3238527232,3238541567,CH
+3238541568,3238541823,PL
+3238541824,3238542591,CH
3238542592,3238542847,PL
3238542848,3238545919,CH
3238545920,3238546431,RU
@@ -81350,7 +83083,7 @@
3239114752,3239116543,DE
3239116544,3239116799,PL
3239116800,3239117055,PT
-3239117056,3239119871,DE
+3239117312,3239119871,DE
3239119872,3239120127,GB
3239120128,3239120383,CZ
3239120384,3239120639,PL
@@ -81399,7 +83132,9 @@
3239161600,3239161855,HU
3239161856,3239162623,DE
3239162624,3239162879,BE
-3239162880,3239164671,DE
+3239162880,3239163903,DE
+3239163904,3239164159,PL
+3239164160,3239164671,DE
3239164672,3239164927,GB
3239164928,3239165183,DK
3239165184,3239165951,DE
@@ -81439,7 +83174,8 @@
3239175424,3239175679,BG
3239175680,3239175935,DE
3239175936,3239176191,FI
-3239176192,3239181311,DE
+3239176192,3239180287,DE
+3239180288,3239181311,CZ
3239181312,3239181567,AT
3239181568,3239181823,UA
3239181824,3239264255,DE
@@ -81510,6 +83246,7 @@
3239452416,3239452671,HR
3239452672,3239464959,DE
3239464960,3239465215,IL
+3239465216,3239465471,PL
3239465472,3239465727,AT
3239465728,3239465983,PL
3239465984,3239466239,UA
@@ -81678,7 +83415,6 @@
3239682560,3239683071,BG
3239683072,3239683583,PT
3239683584,3239684607,PL
-3239684608,3239685119,GB
3239685120,3239686143,DE
3239686144,3239686655,UA
3239686656,3239687167,IT
@@ -81777,8 +83513,10 @@
3239783424,3239783679,DK
3239783680,3239783935,CH
3239783936,3239784191,DE
+3239784192,3239784447,FR
3239784448,3239788543,DE
3239788544,3239789055,EU
+3239789056,3239789567,DE
3239789568,3239790079,FR
3239790080,3239790591,RO
3239790592,3239791103,LV
@@ -81794,7 +83532,6 @@
3239796736,3239821311,DE
3239821312,3239821823,SE
3239821824,3239822335,FR
-3239822336,3239822847,RU
3239822848,3239823359,PL
3239823360,3239823871,SE
3239823872,3239824383,IT
@@ -81892,6 +83629,7 @@
3239895296,3239895551,TR
3239895552,3239895807,PL
3239895808,3239896063,DK
+3239896064,3239896319,DE
3239896320,3239896575,AT
3239896576,3239896831,PL
3239896832,3239897087,HU
@@ -82048,6 +83786,7 @@
3240189952,3240190463,DE
3240190464,3240190975,IT
3240190976,3240191487,RU
+3240191488,3240191999,AE
3240192000,3240192511,UA
3240192512,3240193023,RO
3240193024,3240193535,GB
@@ -82080,6 +83819,7 @@
3240207872,3240208383,RU
3240208384,3240208895,FR
3240208896,3240209407,GB
+3240209408,3240209919,AE
3240209920,3240210943,PL
3240210944,3240211455,GB
3240211456,3240211967,NL
@@ -82186,6 +83926,7 @@
3240281600,3240281727,JO
3240281728,3240281855,PL
3240281856,3240281983,NL
+3240281984,3240282111,FR
3240282112,3240282239,DE
3240282240,3240282367,UA
3240282368,3240282495,RO
@@ -82232,7 +83973,7 @@
3240409088,3240409343,TR
3240409344,3240409599,GB
3240409600,3240409855,NL
-3240409856,3240410111,DE
+3240409856,3240410367,DE
3240410368,3240410623,AT
3240410624,3240410879,PT
3240410880,3240411135,NO
@@ -82284,6 +84025,7 @@
3240577280,3240577535,RO
3240577536,3240577791,DE
3240577792,3240578559,UA
+3240578560,3240578815,RU
3240578816,3240579071,IL
3240579072,3240587263,GB
3240587264,3240587519,NL
@@ -82396,7 +84138,6 @@
3240742400,3240742655,RO
3240742656,3240742911,AT
3240742912,3240743423,IL
-3240743424,3240743935,DK
3240743936,3240744447,DE
3240744448,3240744959,SE
3240744960,3240745471,RO
@@ -82425,7 +84166,6 @@
3240791552,3240791807,RU
3240791808,3240792063,ES
3240792064,3240792319,GB
-3240792320,3240792575,RO
3240792576,3240792831,CH
3240792832,3240793087,PL
3240793088,3240793343,UA
@@ -82666,8 +84406,7 @@
3241146880,3241148415,CH
3241148416,3241476095,FR
3241476096,3241476351,CH
-3241476352,3241481471,BE
-3241481472,3241481727,NL
+3241476352,3241481727,BE
3241481728,3241481983,PT
3241481984,3241482239,DE
3241482240,3241484799,SE
@@ -82796,8 +84535,7 @@
3243514112,3243514367,CH
3243514368,3243514623,IE
3243514624,3243514879,DK
-3243514880,3243515135,AT
-3243515136,3243515391,PL
+3243514880,3243515391,AT
3243515392,3243515647,DE
3243515648,3243515903,RU
3243515904,3243520511,CZ
@@ -83060,6 +84798,7 @@
3244844800,3244845055,GB
3244845056,3244845311,NL
3244845312,3244845567,NO
+3244845568,3244845823,RO
3244845824,3244846335,GB
3244846336,3244846591,TR
3244846592,3244846847,CZ
@@ -83095,7 +84834,6 @@
3244854528,3244855295,RU
3244855296,3244855551,GB
3244855552,3244855807,UA
-3244855808,3244856063,CZ
3244856064,3244856319,IL
3244856320,3244856575,CH
3244856576,3244856831,RU
@@ -83206,7 +84944,6 @@
3244886016,3244886271,LB
3244886272,3244886527,CH
3244886528,3244886783,DK
-3244886784,3244887039,UA
3244887040,3244887295,NL
3244887296,3244887551,GB
3244887552,3244887807,CZ
@@ -83270,6 +85007,7 @@
3244903168,3244903423,PL
3244903424,3244903679,FI
3244903680,3244903935,NO
+3244903936,3244904191,RO
3244904192,3244904447,IT
3244904448,3244904703,GR
3244904704,3244904959,FR
@@ -83282,6 +85020,7 @@
3244906752,3244907007,SA
3244907008,3244907263,FR
3244907264,3244907519,RO
+3244907520,3244907775,UA
3244907776,3244908287,RU
3244908288,3244908543,NL
3244908544,3244908799,RU
@@ -83305,6 +85044,7 @@
3244913408,3244913663,SI
3244913664,3244913919,DK
3244913920,3244914431,RU
+3244914432,3244914687,SA
3244914688,3244914943,GB
3244914944,3244915199,UA
3244915200,3244915455,PL
@@ -83383,6 +85123,7 @@
3244935168,3244935423,NL
3244935424,3244935679,UA
3244935680,3244935935,PL
+3244935936,3244936191,IL
3244936192,3244936959,AT
3244936960,3244937215,KZ
3244937216,3244937471,TR
@@ -83474,12 +85215,16 @@
3245001728,3245002751,IL
3245002752,3245003263,PL
3245003264,3245003519,SE
+3245003520,3245003775,UA
3245003776,3245004799,RU
3245004800,3245005823,PL
3245005824,3245006847,UA
3245006848,3245007871,DE
3245007872,3245008895,PL
3245008896,3245009919,RU
+3245009920,3245010431,UA
+3245010432,3245010687,PL
+3245010688,3245010943,FR
3245010944,3245011967,RU
3245011968,3245012991,PL
3245012992,3245014015,UA
@@ -83632,6 +85377,7 @@
3245136384,3245136639,GB
3245136640,3245136895,EU
3245136896,3245137151,PL
+3245137152,3245137407,GB
3245137408,3245137663,DE
3245137664,3245137919,SE
3245137920,3245138431,DK
@@ -84059,7 +85805,8 @@
3246784512,3246915583,CH
3246915584,3247046655,PT
3247046656,3247046911,AT
-3247046912,3247048703,SI
+3247046912,3247048191,SI
+3247048192,3247048703,NO
3247048704,3247048959,EE
3247048960,3247049215,SI
3247049216,3247054079,DE
@@ -84102,6 +85849,7 @@
3247071488,3247072255,RO
3247072256,3247072511,IE
3247072512,3247072767,BE
+3247072768,3247073023,SE
3247073024,3247073279,RO
3247073280,3247073535,DE
3247073536,3247073791,AT
@@ -84393,9 +86141,12 @@
3247308728,3247308735,DE
3247308736,3247308799,NL
3247308800,3247309055,BG
-3247309056,3247316479,FI
+3247309056,3247313663,FI
+3247313664,3247313919,AM
+3247313920,3247316479,FI
3247316480,3247316735,NO
-3247316736,3247322367,FI
+3247316736,3247316991,RU
+3247316992,3247322367,FI
3247322368,3247322623,DE
3247322624,3247323135,FI
3247323136,3247323647,RU
@@ -84451,7 +86202,6 @@
3247366144,3247371007,FI
3247371008,3247371263,PL
3247371264,3247371519,SE
-3247371520,3247371775,GB
3247371776,3247374335,FI
3247374336,3247374591,RU
3247374592,3247394047,FI
@@ -84508,6 +86258,7 @@
3247828992,3247833087,BE
3247865856,3247871999,GB
3247872000,3247875327,NL
+3247875328,3247875583,PL
3247875584,3247876095,DE
3247876096,3247876351,PL
3247876352,3247876607,FR
@@ -84676,12 +86427,9 @@
3248881664,3249012735,FI
3249012736,3249012991,DE
3249012992,3249014271,LU
-3249014272,3249014783,EU
3249014784,3249025535,LU
3249025536,3249025791,FR
-3249025792,3249026559,LU
-3249026560,3249026815,EU
-3249026816,3249045503,LU
+3249025792,3249045503,LU
3249045504,3249078271,DE
3249078272,3249078783,RU
3249078784,3249079295,CH
@@ -84814,7 +86562,13 @@
3249574144,3249574399,RU
3249574400,3249574655,SE
3249574656,3249574911,UA
-3249574912,3249668095,NL
+3249574912,3249590527,NL
+3249590528,3249590783,FR
+3249590784,3249600255,NL
+3249600256,3249600511,AT
+3249600512,3249601535,UA
+3249601536,3249601791,RU
+3249601792,3249668095,NL
3249668096,3249676287,IE
3249676288,3249676543,GB
3249676544,3249676799,IE
@@ -84922,12 +86676,18 @@
3249872384,3249872639,GB
3249872640,3249910783,SE
3249910784,3249912319,GB
-3249912320,3249931007,SE
+3249912320,3249926143,SE
+3249926144,3249926399,AU
+3249926400,3249926655,SE
+3249926656,3249926911,AU
+3249926912,3249931007,SE
3249931008,3249931263,GB
3249931264,3249932031,SE
3249932032,3249932287,GB
3249932288,3249934335,US
-3249934336,3249967615,SE
+3249934336,3249961471,SE
+3249961472,3249961727,NL
+3249961728,3249967615,SE
3249967616,3249967871,GB
3249967872,3249968127,SE
3249968128,3249969151,FR
@@ -84941,7 +86701,9 @@
3249976832,3249977087,GB
3249977088,3249991679,SE
3249991680,3249991935,US
-3249991936,3249995263,SE
+3249991936,3249993215,SE
+3249993216,3249993471,NL
+3249993472,3249995263,SE
3249995264,3249995519,GB
3249995520,3249997055,SE
3249997056,3249997311,US
@@ -84991,7 +86753,7 @@
3250200832,3250201087,RO
3250201088,3250201343,RU
3250201344,3250201599,DK
-3250201600,3250233855,AT
+3250202624,3250233855,AT
3250233856,3250234111,GB
3250234112,3250234367,GR
3250234368,3250245631,AT
@@ -85030,7 +86792,7 @@
3250359296,3250359807,HU
3250359808,3250362879,KW
3250362880,3250363391,DE
-3250363392,3250363903,EU
+3250363392,3250363903,SE
3250363904,3250364415,DE
3250364416,3250372607,KW
3250372608,3250373375,HU
@@ -85146,6 +86908,9 @@
3250692096,3250692351,NO
3250692352,3250692607,NL
3250692608,3250693375,BG
+3250693376,3250693631,NL
+3250693632,3250694143,DE
+3250694144,3250694399,PL
3250694400,3250694655,GB
3250694656,3250694911,SK
3250694912,3250695167,NL
@@ -85155,6 +86920,7 @@
3250697728,3250697983,BG
3250697984,3250698239,IT
3250698240,3250698751,GR
+3250698752,3250699263,RU
3250699264,3250699775,GB
3250699776,3250700287,DE
3250700288,3250708479,UA
@@ -85167,6 +86933,9 @@
3250722304,3250724863,GB
3250724864,3250733055,MA
3250733056,3250741247,DZ
+3250741248,3250742783,RU
+3250742784,3250743551,AT
+3250743808,3250745343,UA
3250749440,3250749695,GH
3250749696,3250749951,IT
3250749952,3250750463,RO
@@ -85395,6 +87164,7 @@
3251182080,3251182591,FR
3251182592,3251183103,IT
3251183104,3251183615,RU
+3251183616,3251183871,LT
3251183872,3251184127,CH
3251184128,3251184383,PL
3251184384,3251184639,DK
@@ -85436,7 +87206,6 @@
3251202816,3251203327,ES
3251203328,3251203583,SI
3251203584,3251203839,CZ
-3251203840,3251204095,SE
3251204096,3251204607,DE
3251204608,3251205119,BG
3251205120,3251205631,UA
@@ -85521,7 +87290,8 @@
3251237888,3251238911,DK
3251238912,3251239935,FR
3251239936,3251240959,US
-3251240960,3251243007,GB
+3251240960,3251241215,DE
+3251241216,3251243007,GB
3251243008,3251245055,BE
3251245056,3251245311,DE
3251245312,3251245567,BE
@@ -85575,7 +87345,7 @@
3251308544,3251310591,EU
3251310592,3251311103,SI
3251311104,3251311615,RS
-3251311616,3251312127,EU
+3251311616,3251312127,GB
3251312128,3251312383,RS
3251312384,3251312639,CH
3251312640,3251313151,RS
@@ -85694,7 +87464,8 @@
3252318720,3252318975,MQ
3252318976,3252319231,PL
3252319232,3252319743,AT
-3252319744,3252321791,GR
+3252319744,3252319999,UA
+3252320000,3252321791,GR
3252321792,3252322303,PL
3252322304,3252323327,NO
3252323328,3252324351,PL
@@ -85714,6 +87485,7 @@
3252342144,3252342207,LU
3252342208,3252342239,GB
3252342240,3252342271,CH
+3252342272,3252342527,SE
3252342528,3252342543,NO
3252342544,3252342591,DE
3252342592,3252342607,IE
@@ -85774,8 +87546,7 @@
3252407760,3252407775,CD
3252407776,3252407791,GH
3252407792,3252407807,NO
-3252407808,3252407999,GN
-3252408000,3252408063,NO
+3252407808,3252408063,GN
3252408064,3252408079,ML
3252408080,3252408159,NO
3252408160,3252408191,GQ
@@ -85785,7 +87556,7 @@
3252408336,3252408343,GN
3252408344,3252408351,LT
3252408352,3252408367,GN
-3252408368,3252408375,NG
+3252408368,3252408375,LT
3252408376,3252408383,GN
3252408384,3252408391,BI
3252408392,3252408415,LT
@@ -85814,9 +87585,7 @@
3252409040,3252409047,MR
3252409048,3252409103,LT
3252409104,3252409111,SD
-3252409112,3252409119,LT
-3252409120,3252409127,NG
-3252409128,3252409151,LT
+3252409112,3252409151,LT
3252409152,3252409159,KE
3252409160,3252409167,LT
3252409168,3252409175,UG
@@ -85883,8 +87652,8 @@
3252414624,3252414639,TZ
3252414640,3252414647,GH
3252414648,3252414655,NE
-3252414656,3252414991,LT
-3252414992,3252414999,IQ
+3252414656,3252414975,LT
+3252414976,3252414999,IQ
3252415000,3252415015,LT
3252415016,3252415031,IQ
3252415032,3252415039,LT
@@ -85904,9 +87673,9 @@
3252417024,3252417279,LT
3252417280,3252417287,IQ
3252417288,3252417463,AF
-3252417464,3252417479,LT
-3252417480,3252417487,AF
-3252417488,3252417791,LT
+3252417464,3252417471,LT
+3252417472,3252417503,AF
+3252417504,3252417791,LT
3252417792,3252417855,NG
3252417856,3252417919,LT
3252417920,3252417935,MW
@@ -85961,8 +87730,7 @@
3252424704,3252424719,GN
3252424720,3252424735,LT
3252424736,3252424751,GA
-3252424752,3252424767,MA
-3252424768,3252424799,LT
+3252424752,3252424799,LT
3252424800,3252424815,NE
3252424816,3252425023,LT
3252425024,3252425215,SO
@@ -86012,7 +87780,8 @@
3252434712,3252434719,LT
3252434720,3252434743,GH
3252434744,3252435199,LT
-3252435200,3252435247,TZ
+3252435200,3252435231,TZ
+3252435232,3252435247,LT
3252435248,3252435263,BW
3252435264,3252435279,ML
3252435280,3252435295,LT
@@ -86020,8 +87789,7 @@
3252435312,3252435319,CF
3252435320,3252435327,MZ
3252435328,3252435343,CD
-3252435344,3252435359,BF
-3252435360,3252435375,LT
+3252435344,3252435375,BF
3252435376,3252435415,GN
3252435416,3252435423,LT
3252435424,3252435447,CD
@@ -86030,7 +87798,7 @@
3252435712,3252435855,GH
3252435856,3252435871,MR
3252435872,3252435887,GH
-3252435888,3252435903,LT
+3252435888,3252435903,CD
3252435904,3252435919,BW
3252435920,3252435935,BF
3252435936,3252435951,CF
@@ -86046,8 +87814,7 @@
3252436336,3252436351,ZM
3252436352,3252436383,GN
3252436384,3252436399,LR
-3252436400,3252436407,SL
-3252436408,3252436415,ML
+3252436400,3252436415,SL
3252436416,3252436447,LT
3252436448,3252436479,ER
3252436480,3252436991,LT
@@ -86063,7 +87830,9 @@
3252439272,3252439287,LT
3252439288,3252439295,SN
3252439296,3252439391,SO
-3252439392,3252439807,LT
+3252439392,3252439551,LT
+3252439552,3252439615,SO
+3252439616,3252439807,LT
3252439808,3252439871,SO
3252439872,3252444287,LT
3252444288,3252444351,TZ
@@ -86174,6 +87943,7 @@
3252510720,3252514815,FR
3252514816,3252515071,SI
3252515072,3252515327,GB
+3252515328,3252515583,NL
3252515584,3252515839,SI
3252515840,3252516095,CH
3252516096,3252516351,FR
@@ -86190,11 +87960,12 @@
3252518912,3252527103,NL
3252527104,3252535295,BE
3252535296,3252539391,GB
-3252539392,3252540415,EU
+3252539392,3252540415,IE
3252540416,3252541951,NL
3252541952,3252542207,CI
3252542208,3252551679,BE
-3252551680,3252567295,CH
+3252551680,3252563967,CH
+3252566784,3252567295,CH
3252567296,3252567551,GB
3252567552,3252567807,RU
3252567808,3252568063,RO
@@ -86349,11 +88120,14 @@
3253265920,3253270527,RU
3253270528,3253271551,BY
3253271552,3253338111,RU
-3253338112,3253380863,SE
+3253338112,3253338367,PL
+3253338368,3253380863,SE
3253380864,3253381119,IT
3253381120,3253383935,SE
3253383936,3253384191,NO
-3253384192,3253409791,SE
+3253384192,3253403647,SE
+3253403648,3253403903,PL
+3253403904,3253409791,SE
3253409792,3253410047,GB
3253410048,3253412351,SE
3253412352,3253412607,US
@@ -86807,10 +88581,11 @@
3254785280,3254785535,KZ
3254785536,3254785791,DK
3254785792,3254786047,LU
-3254786304,3254786815,AT
+3254786048,3254786815,AT
3254786816,3254787071,SM
3254787072,3254788095,NL
3254788096,3254788351,BG
+3254788352,3254789119,ES
3254796288,3254797311,SE
3254797312,3254798335,RU
3254798336,3254799359,AT
@@ -86880,6 +88655,7 @@
3254827776,3254828031,UA
3254828032,3254828287,DE
3254828288,3254828799,RO
+3254828800,3254829055,SI
3254829056,3254829311,NO
3254829312,3254829567,GB
3254829568,3254829823,NL
@@ -87285,9 +89061,7 @@
3255300804,3255300807,LU
3255300808,3255304191,BE
3255304192,3255304447,DE
-3255304448,3255305215,LV
-3255305216,3255305471,EU
-3255305472,3255307775,LV
+3255304448,3255307775,LV
3255307776,3255308031,PL
3255308032,3255308287,CH
3255308288,3255311359,LV
@@ -87295,8 +89069,7 @@
3255311616,3255311871,SE
3255311872,3255312127,PT
3255312128,3255312383,SE
-3255312384,3255315455,LV
-3255315456,3255315711,EU
+3255312384,3255315711,LV
3255315712,3255316223,PL
3255316224,3255316479,RU
3255316480,3255316991,GB
@@ -87396,6 +89169,7 @@
3255412480,3255412735,RO
3255412736,3255413247,DE
3255413248,3255413503,LV
+3255413504,3255413759,UZ
3255413760,3255414271,GB
3255414272,3255414527,TR
3255414528,3255414783,LV
@@ -87603,6 +89377,7 @@
3256413184,3256413695,UA
3256413696,3256414207,PL
3256414208,3256414719,RU
+3256414720,3256415231,DE
3256415232,3256415743,PL
3256415744,3256416255,UA
3256416256,3256416767,RS
@@ -87742,6 +89517,7 @@
3256788224,3256788479,RU
3256788480,3256788735,GB
3256788736,3256788991,DE
+3256788992,3256789247,RO
3256789248,3256789503,SE
3256789504,3256789759,UA
3256789760,3256790015,GB
@@ -87767,7 +89543,9 @@
3256795136,3256811519,GR
3256811520,3256864511,DE
3256864512,3256864767,CH
-3256864768,3256877055,DE
+3256864768,3256870911,DE
+3256870912,3256871167,RU
+3256871168,3256877055,DE
3256877056,3256915455,GB
3256915456,3256915967,SE
3256915968,3256945663,GB
@@ -87781,7 +89559,6 @@
3256988672,3256989183,UA
3256989184,3256989439,FR
3256989440,3256989695,GB
-3256989696,3256989951,HU
3256989952,3256990207,PL
3256990208,3256990463,CH
3256990464,3256990719,PL
@@ -87837,6 +89614,7 @@
3257401344,3257466879,CH
3257466880,3257467135,DE
3257467136,3257467391,GB
+3257467392,3257467903,SE
3257467904,3257468927,IT
3257468928,3257469183,EU
3257469184,3257469439,IT
@@ -88986,7 +90764,8 @@
3258765056,3258765311,NL
3258765312,3258767615,GB
3258767616,3258767871,CH
-3258767872,3258802175,GB
+3258767872,3258769919,GB
+3258777600,3258802175,GB
3258802176,3258806271,LU
3258806272,3258818047,GB
3258818048,3258818303,SE
@@ -89020,7 +90799,9 @@
3259031656,3259031659,ES
3259031660,3259031895,DE
3259031896,3259031899,ES
-3259031900,3259032199,DE
+3259031900,3259032151,DE
+3259032152,3259032159,GB
+3259032160,3259032199,DE
3259032200,3259032203,ES
3259032204,3259032439,DE
3259032440,3259032443,ES
@@ -89180,7 +90961,9 @@
3259457280,3259457535,IT
3259457536,3259460351,SE
3259460352,3259460607,DE
-3259460608,3259465215,SE
+3259460608,3259461375,SE
+3259461376,3259461631,GB
+3259461632,3259465215,SE
3259465216,3259465471,KH
3259465472,3259479807,SE
3259479808,3259480063,DK
@@ -89422,8 +91205,7 @@
3260894208,3260895231,AT
3260895232,3260898303,SE
3260898304,3260899327,ES
-3260899328,3260900095,CH
-3260900096,3260900607,EU
+3260899328,3260900351,CH
3260900608,3260901119,NL
3260901120,3260903423,DE
3260903424,3260906239,CH
@@ -89591,29 +91373,41 @@
3262034048,3262034119,AX
3262034120,3262034123,FI
3262034124,3262034127,AX
-3262034128,3262034175,FI
-3262034176,3262034191,AX
-3262034192,3262034431,FI
+3262034128,3262034143,FI
+3262034144,3262034191,AX
+3262034192,3262034239,FI
+3262034240,3262034287,AX
+3262034288,3262034431,FI
3262034432,3262034447,AX
3262034448,3262034455,FI
3262034456,3262034463,AX
3262034464,3262034527,FI
-3262034528,3262034559,AX
-3262034560,3262034687,FI
-3262034688,3262034719,AX
-3262034720,3262034783,FI
+3262034528,3262034567,AX
+3262034568,3262034575,FI
+3262034576,3262034591,AX
+3262034592,3262034687,FI
+3262034688,3262034723,AX
+3262034724,3262034783,FI
3262034784,3262034791,AX
-3262034792,3262034839,FI
+3262034792,3262034799,FI
+3262034800,3262034807,AX
+3262034808,3262034815,FI
+3262034816,3262034831,AX
+3262034832,3262034839,FI
3262034840,3262034847,AX
3262034848,3262034943,FI
3262034944,3262035455,AX
3262035456,3262035487,FI
3262035488,3262035551,AX
-3262035552,3262036143,FI
-3262036144,3262036151,AX
+3262035552,3262035711,FI
+3262035712,3262035967,AX
+3262035968,3262036127,FI
+3262036128,3262036139,AX
+3262036140,3262036141,FI
+3262036142,3262036151,AX
3262036152,3262036287,FI
-3262036288,3262036303,AX
-3262036304,3262036311,FI
+3262036288,3262036307,AX
+3262036308,3262036311,FI
3262036312,3262036335,AX
3262036336,3262036367,FI
3262036368,3262036383,AX
@@ -89622,8 +91416,12 @@
3262036432,3262036463,FI
3262036464,3262036479,AX
3262036480,3262036607,FI
-3262036608,3262036615,AX
-3262036616,3262036719,FI
+3262036608,3262036623,AX
+3262036624,3262036655,FI
+3262036656,3262036659,AX
+3262036660,3262036663,FI
+3262036664,3262036671,AX
+3262036672,3262036719,FI
3262036720,3262038015,AX
3262038016,3262038271,FR
3262038272,3262038527,RU
@@ -89687,24 +91485,32 @@
3262120448,3262120703,FI
3262120704,3262121599,AX
3262121600,3262121663,FI
-3262121664,3262121727,AX
-3262121728,3262121983,FI
-3262121984,3262122007,AX
+3262121664,3262122007,AX
3262122008,3262122015,FI
-3262122016,3262122039,AX
-3262122040,3262122143,FI
+3262122016,3262122047,AX
+3262122048,3262122143,FI
3262122144,3262122159,AX
-3262122160,3262122239,FI
+3262122160,3262122167,FI
+3262122168,3262122183,AX
+3262122184,3262122199,FI
+3262122200,3262122207,AX
+3262122208,3262122239,FI
3262122240,3262122367,AX
3262122368,3262122431,FI
-3262122432,3262122455,AX
-3262122456,3262122463,FI
-3262122464,3262122591,AX
-3262122592,3262122631,FI
-3262122632,3262122639,AX
-3262122640,3262122751,FI
-3262122752,3262122815,AX
-3262122816,3262124031,FI
+3262122432,3262122623,AX
+3262122624,3262122631,FI
+3262122632,3262122655,AX
+3262122656,3262122751,FI
+3262122752,3262123007,AX
+3262123008,3262123263,FI
+3262123264,3262123295,AX
+3262123296,3262123311,FI
+3262123312,3262123327,AX
+3262123328,3262123391,FI
+3262123392,3262123519,AX
+3262123520,3262123527,FI
+3262123528,3262123775,AX
+3262123776,3262124031,FI
3262124032,3262128127,DE
3262128128,3262136319,GB
3262136320,3262137599,EU
@@ -91670,7 +93476,7 @@
3262479279,3262479279,ES
3262479280,3262479280,DE
3262479281,3262479281,FR
-3262479282,3262479282,AD
+3262479282,3262479282,DE
3262479283,3262479283,IT
3262479284,3262479284,NO
3262479285,3262479289,DE
@@ -92423,7 +94229,6 @@
3262510080,3262511103,FR
3262511104,3262511615,GB
3262511616,3262512127,DE
-3262512128,3262512639,GB
3262512640,3262513151,DE
3262513152,3262578687,AT
3262578688,3262611455,FR
@@ -92929,7 +94734,9 @@
3264340992,3264341503,PL
3264341504,3264341759,DE
3264341760,3264342015,IT
-3264342016,3264343295,DE
+3264342016,3264342783,DE
+3264342784,3264343039,FR
+3264343040,3264343295,DE
3264343296,3264343551,GB
3264343552,3264343807,RO
3264343808,3264344063,DE
@@ -92937,7 +94744,9 @@
3264345088,3264346111,NL
3264346112,3264347135,SE
3264347136,3264348159,DE
-3264348160,3264375039,FR
+3264348160,3264372223,FR
+3264372224,3264372735,GB
+3264372736,3264375039,FR
3264375040,3264376063,SE
3264376064,3264376319,HR
3264376320,3264376575,UA
@@ -93031,16 +94840,19 @@
3264610304,3264612351,GB
3264612352,3264612599,FR
3264612600,3264612607,GB
-3264612608,3264613183,FR
-3264613184,3264613375,GB
+3264612608,3264613199,FR
+3264613200,3264613247,GB
+3264613248,3264613311,FR
+3264613312,3264613375,GB
3264613376,3264613887,NL
3264613888,3264613895,GB
3264613896,3264613903,NL
3264613904,3264614399,GB
3264614400,3264614655,NL
-3264614656,3264615423,GB
-3264615424,3264615679,CH
-3264615680,3264617215,GB
+3264614656,3264614911,SE
+3264614912,3264615423,GB
+3264615424,3264615727,CH
+3264615728,3264617215,GB
3264617216,3264617471,DE
3264617472,3264618239,GB
3264618240,3264618495,US
@@ -93204,7 +95016,7 @@
3264850688,3264850943,LV
3264850944,3264851967,IT
3264851968,3264854015,CH
-3264854016,3264854527,DE
+3264854016,3264854783,DE
3264854784,3264855039,IT
3264855040,3264855551,CH
3264855552,3264856063,DE
@@ -93350,6 +95162,7 @@
3265605376,3265605631,CZ
3265605632,3265605887,PL
3265605888,3265606143,FR
+3265606400,3265606655,NL
3265606656,3265606911,AT
3265607168,3265607423,PL
3265607424,3265607935,DK
@@ -93530,7 +95343,11 @@
3266799104,3266799615,NL
3266799616,3266800895,GB
3266800896,3266801151,NL
-3266801152,3266804223,GB
+3266801152,3266801487,GB
+3266801488,3266801503,NL
+3266801504,3266803815,GB
+3266803816,3266803823,NL
+3266803824,3266804223,GB
3266804224,3266804479,NL
3266804480,3266805759,GB
3266805760,3266813951,AT
@@ -94395,8 +96212,10 @@
3268739072,3268739327,DE
3268739328,3268739583,PL
3268739584,3268739839,DE
+3268739840,3268740095,GB
3268740096,3268740351,IL
3268740352,3268740607,DE
+3268740608,3268740863,RO
3268740864,3268741119,CH
3268741120,3268741375,FR
3268741376,3268741887,LV
@@ -94931,6 +96750,7 @@
3270980608,3270980863,MD
3270980864,3270981631,RU
3270981632,3270981887,IT
+3270981888,3270982143,AT
3270982144,3270982399,RU
3270982400,3270982655,TR
3270982656,3270982911,UA
@@ -95263,9 +97083,15 @@
3272040448,3272048639,FR
3272048640,3272056831,NL
3272056832,3272065023,RU
-3272065024,3272070143,GB
+3272065024,3272065631,GB
+3272065632,3272065663,NL
+3272065664,3272069503,GB
+3272069504,3272069567,NL
+3272069568,3272070143,GB
3272070144,3272070175,NL
-3272070176,3272081407,GB
+3272070176,3272070239,GB
+3272070240,3272070255,NL
+3272070256,3272081407,GB
3272081408,3272081919,PT
3272081920,3272082687,CV
3272082688,3272083455,PT
@@ -95391,29 +97217,10 @@
3272214352,3272214407,FR
3272214408,3272214431,EU
3272214432,3272214463,SE
-3272214464,3272214655,EU
-3272214656,3272214671,NL
-3272214672,3272214679,GB
-3272214680,3272214687,FR
-3272214688,3272214815,EU
-3272214816,3272214823,CH
-3272214824,3272214831,EU
-3272214832,3272214847,BE
-3272214848,3272214879,NL
-3272214880,3272214883,EU
-3272214884,3272214887,NL
-3272214888,3272214895,EU
-3272214896,3272214903,ES
-3272214904,3272214911,SE
-3272214912,3272214943,EU
-3272214944,3272214951,DE
-3272214952,3272214959,BE
-3272214960,3272215007,NL
-3272215008,3272215015,FR
-3272215016,3272215023,IT
-3272215024,3272215039,EU
+3272214464,3272214527,EU
+3272214528,3272215039,FR
3272215040,3272215295,ES
-3272215296,3272215551,IR
+3272215296,3272215551,NL
3272215552,3272215807,CH
3272215808,3272215823,NL
3272215824,3272215871,EU
@@ -95482,8 +97289,8 @@
3272219904,3272220159,DE
3272220160,3272220415,FR
3272220416,3272221183,GB
-3272221184,3272221311,NL
-3272221312,3272221439,EU
+3272221184,3272221375,NL
+3272221376,3272221439,EU
3272221440,3272221447,SE
3272221448,3272221455,NO
3272221456,3272221463,SE
@@ -95509,7 +97316,9 @@
3272224256,3272224383,GI
3272224384,3272224511,EU
3272224512,3272225279,GB
-3272225280,3272225791,IT
+3272225280,3272225535,IT
+3272225536,3272225591,GB
+3272225592,3272225791,IT
3272225792,3272226047,EU
3272226048,3272226815,FR
3272226816,3272227071,GB
@@ -95532,11 +97341,63 @@
3272228736,3272228799,NL
3272228800,3272228863,CH
3272228864,3272237055,LU
-3272237056,3272240575,GB
+3272237056,3272238919,GB
+3272238920,3272238975,IM
+3272238976,3272239039,GB
+3272239040,3272239103,IM
+3272239104,3272239687,GB
+3272239688,3272239695,IM
+3272239696,3272239703,GB
+3272239704,3272239711,IM
+3272239712,3272239791,GB
+3272239792,3272239799,IM
+3272239800,3272240127,GB
+3272240128,3272240367,IM
+3272240368,3272240575,GB
3272240576,3272240639,GH
-3272240640,3272243967,GB
+3272240640,3272241215,GB
+3272241216,3272241295,IM
+3272241296,3272241303,GB
+3272241304,3272241311,IM
+3272241312,3272241335,GB
+3272241336,3272241407,IM
+3272241408,3272241518,GB
+3272241519,3272241599,IM
+3272241600,3272241663,GB
+3272241664,3272241855,IM
+3272241856,3272242215,GB
+3272242216,3272242223,IM
+3272242224,3272242239,GB
+3272242240,3272242591,IM
+3272242592,3272242607,GB
+3272242608,3272242623,IM
+3272242624,3272242655,GB
+3272242656,3272242719,IM
+3272242720,3272242735,GB
+3272242736,3272242751,IM
+3272242752,3272242783,GB
+3272242784,3272242943,IM
+3272242944,3272243207,GB
+3272243208,3272243215,IM
+3272243216,3272243231,GB
+3272243232,3272243263,IM
+3272243264,3272243327,GB
+3272243328,3272243455,IM
+3272243456,3272243967,GB
3272243968,3272244007,IM
-3272244008,3272245247,GB
+3272244008,3272244015,GB
+3272244016,3272244031,IM
+3272244032,3272244039,GB
+3272244040,3272244047,IM
+3272244048,3272244071,GB
+3272244072,3272244079,IM
+3272244080,3272244111,GB
+3272244112,3272244127,IM
+3272244128,3272244151,GB
+3272244152,3272244159,IM
+3272244160,3272244175,GB
+3272244176,3272244215,IM
+3272244216,3272245247,GB
3272245248,3272261631,FI
3272261632,3272261887,MT
3272261888,3272262143,BG
@@ -95736,7 +97597,8 @@
3272646785,3272646911,GB
3272646912,3272647423,DE
3272647424,3272649215,GB
-3272649216,3272649727,IE
+3272649216,3272649471,IE
+3272649472,3272649727,SA
3272649728,3272650623,GB
3272650624,3272650639,FR
3272650640,3272650655,GB
@@ -95830,7 +97692,6 @@
3272897536,3272898047,FI
3272898048,3272898559,UA
3272898560,3272899071,DE
-3272899072,3272899583,GB
3272899584,3272900095,UA
3272900096,3272900607,LV
3272900608,3272900863,RU
@@ -95884,10 +97745,10 @@
3272923648,3272924159,PL
3272924160,3272924671,DE
3272924672,3272925183,GB
-3272925184,3272933375,DE
-3272933376,3272933759,GB
-3272933760,3272933775,DK
-3272933776,3272940287,GB
+3272925184,3272931135,DE
+3272931136,3272931151,GB
+3272931152,3272933375,DE
+3272933376,3272940287,GB
3272940288,3272940543,DE
3272940544,3272964351,GB
3272964352,3272964607,DE
@@ -96215,8 +98076,8 @@
3273387552,3273387583,DE
3273387584,3273388159,EU
3273388160,3273388223,DE
-3273388224,3273388799,EU
-3273388800,3273388807,DE
+3273388224,3273388543,EU
+3273388544,3273388807,DE
3273388808,3273388815,EU
3273388816,3273388863,DE
3273388864,3273388871,EU
@@ -96360,7 +98221,7 @@
3273878016,3273878271,FR
3273878272,3273878527,LV
3273878528,3273879039,DE
-3273879040,3273879551,BE
+3273879040,3273879551,EU
3273879552,3273880063,GB
3273880064,3273880575,LV
3273880576,3273881087,RU
@@ -96743,7 +98604,6 @@
3274692864,3274693119,AT
3274693120,3274693375,LT
3274693376,3274693631,UA
-3274693632,3274693887,NL
3274693888,3274694143,IT
3274694144,3274694399,DK
3274694400,3274694655,GB
@@ -96988,6 +98848,7 @@
3274964992,3275030527,DE
3275030528,3275096063,ES
3275096064,3275104767,RU
+3275104768,3275105279,DE
3275105280,3275105791,GB
3275105792,3275106303,NL
3275106304,3275106815,RU
@@ -96997,6 +98858,7 @@
3275108352,3275108863,FR
3275108864,3275109375,PL
3275109376,3275109887,UA
+3275109888,3275110399,RO
3275110400,3275110911,NL
3275110912,3275111423,GB
3275111424,3275111935,IT
@@ -97039,13 +98901,15 @@
3275423752,3275423775,EU
3275423776,3275423807,GB
3275423808,3275423871,EU
-3275423872,3275425031,GB
-3275425032,3275425791,EU
-3275425792,3275427631,GB
-3275427632,3275427647,EU
-3275427648,3275427711,GB
-3275427712,3275427839,EU
-3275427840,3275428399,GB
+3275423872,3275425067,GB
+3275425068,3275425071,EU
+3275425072,3275425087,GB
+3275425088,3275425791,EU
+3275425792,3275427639,GB
+3275427640,3275427647,EU
+3275427648,3275427759,GB
+3275427760,3275427775,EU
+3275427776,3275428399,GB
3275428400,3275428415,EU
3275428416,3275428447,GB
3275428448,3275429887,EU
@@ -97053,15 +98917,17 @@
3275430144,3275430271,EU
3275430272,3275430399,GB
3275430400,3275430591,EU
-3275430592,3275430623,GB
-3275430624,3275431935,EU
+3275430592,3275430631,GB
+3275430632,3275430655,EU
+3275430656,3275430911,GB
+3275430912,3275431935,EU
3275431936,3275432831,GB
3275432832,3275433983,EU
-3275433984,3275437567,GB
-3275437568,3275438079,EU
-3275438080,3275438639,GB
-3275438640,3275438719,EU
-3275438720,3275439103,GB
+3275433984,3275438647,GB
+3275438648,3275438655,EU
+3275438656,3275438671,GB
+3275438672,3275438687,EU
+3275438688,3275439103,GB
3275439104,3275440127,EU
3275440128,3275440639,GB
3275440640,3275442175,EU
@@ -97069,8 +98935,8 @@
3275442720,3275444223,EU
3275444224,3275444735,GB
3275444736,3275446271,EU
-3275446272,3275447103,GB
-3275447104,3275448319,EU
+3275446272,3275447135,GB
+3275447136,3275448319,EU
3275448320,3275449519,GB
3275449520,3275449527,FR
3275449528,3275450879,GB
@@ -97079,7 +98945,9 @@
3275451264,3275452415,EU
3275452416,3275454127,GB
3275454128,3275454143,EU
-3275454144,3275457023,GB
+3275454144,3275456383,GB
+3275456384,3275456391,EU
+3275456392,3275457023,GB
3275457024,3275457791,FK
3275457792,3275458559,GB
3275458560,3275460095,IE
@@ -97097,8 +98965,8 @@
3275468768,3275468799,IE
3275468800,3275469071,GB
3275469072,3275469087,IE
-3275469088,3275473151,GB
-3275473152,3275489279,EU
+3275469088,3275473215,GB
+3275473216,3275489279,EU
3275489280,3275497471,GB
3275497472,3275505663,DE
3275505664,3275506175,PL
@@ -97120,6 +98988,7 @@
3275510464,3275510527,GB
3275510528,3275510559,PL
3275510560,3275510591,DE
+3275510592,3275510623,FR
3275510624,3275510655,EE
3275510656,3275510687,FR
3275510720,3275510751,GB
@@ -97175,7 +99044,6 @@
3275543552,3275544575,NL
3275544576,3275545599,PL
3275546624,3275547647,UA
-3275547648,3275548671,RU
3275548672,3275549695,IL
3275549696,3275550719,SY
3275550720,3275551743,PL
@@ -97449,6 +99317,8 @@
3275902720,3275902975,UA
3275902976,3275903231,FR
3275903232,3275903487,GB
+3275903488,3275903743,FR
+3275903744,3275903999,DE
3275904000,3275904255,RU
3275904256,3275904511,CH
3275904512,3275904767,PL
@@ -97869,7 +99739,9 @@
3276032056,3276032063,GB
3276032064,3276032103,FR
3276032104,3276032111,GB
-3276032112,3276032223,FR
+3276032112,3276032191,FR
+3276032192,3276032207,GB
+3276032208,3276032223,FR
3276032224,3276032255,GB
3276032256,3276032263,FR
3276032264,3276032303,GB
@@ -98094,7 +99966,9 @@
3276073472,3276073983,SK
3276073984,3276074495,DE
3276074496,3276075007,GB
-3276075008,3276077055,DE
+3276075008,3276075519,RU
+3276075520,3276076031,DE
+3276076544,3276077055,DE
3276077056,3276077567,UA
3276077568,3276078079,FR
3276078080,3276078591,RU
@@ -98795,9 +100669,7 @@
3276361680,3276361687,DE
3276361688,3276361751,NL
3276361752,3276361767,DE
-3276361768,3276361999,NL
-3276362000,3276362007,DE
-3276362008,3276362047,NL
+3276361768,3276362047,NL
3276362048,3276362055,DE
3276362056,3276362071,NL
3276362072,3276362079,DE
@@ -100290,9 +102162,7 @@
3276477984,3276478319,EU
3276478320,3276478335,CH
3276478336,3276478463,EU
-3276478464,3276479127,FR
-3276479128,3276479135,EU
-3276479136,3276479167,FR
+3276478464,3276479167,FR
3276479168,3276479199,EU
3276479200,3276479215,FR
3276479216,3276479223,EU
@@ -100342,7 +102212,8 @@
3276489216,3276490751,EU
3276490752,3276491263,NL
3276491264,3276491327,CZ
-3276491328,3276491391,EU
+3276491328,3276491359,EU
+3276491360,3276491391,NO
3276491392,3276491775,CZ
3276491776,3276491847,GB
3276491848,3276491855,EU
@@ -100492,14 +102363,14 @@
3276518024,3276518095,EU
3276518096,3276518111,NL
3276518112,3276518127,EU
-3276518128,3276518175,NL
-3276518176,3276518183,EU
-3276518184,3276518191,NL
+3276518128,3276518191,NL
3276518192,3276518207,EU
3276518208,3276518271,NL
3276518272,3276518303,EU
3276518304,3276518335,NL
-3276518336,3276518399,EU
+3276518336,3276518351,EU
+3276518352,3276518367,NL
+3276518368,3276518399,EU
3276518400,3276518527,BE
3276518528,3276518591,EU
3276518592,3276518655,BE
@@ -100607,8 +102478,8 @@
3276529392,3276529407,TR
3276529408,3276529663,EU
3276529664,3276530447,NL
-3276530448,3276530463,EU
-3276530464,3276530495,NL
+3276530448,3276530455,EU
+3276530456,3276530495,NL
3276530496,3276530559,EU
3276530560,3276532735,NL
3276532736,3276532775,TR
@@ -100647,8 +102518,8 @@
3276534880,3276534887,EU
3276534888,3276534895,NL
3276534896,3276534911,EU
-3276534912,3276534927,NL
-3276534928,3276535015,EU
+3276534912,3276534919,NL
+3276534920,3276535015,EU
3276535016,3276535039,GB
3276535040,3276535063,RU
3276535064,3276535071,LV
@@ -100728,6 +102599,7 @@
3276697600,3276698111,UA
3276698112,3276699647,RU
3276699648,3276700159,NL
+3276700160,3276700671,CZ
3276700672,3276701183,RO
3276701184,3276701695,RU
3276701696,3276709887,SE
@@ -101112,8 +102984,11 @@
3276799872,3276799999,NL
3276800000,3276824575,GB
3276824576,3276832767,EE
+3276832768,3276834815,PL
+3276834816,3276835839,RU
+3276835840,3276836351,UA
+3276836352,3276836863,RO
3276836864,3276837887,RU
-3276837888,3276838911,EU
3276838912,3276840959,FR
3276840960,3276849151,SK
3276849152,3276857343,DE
@@ -101151,9 +103026,10 @@
3276869728,3276869855,IT
3276869856,3276869887,GB
3276869888,3276870143,NL
-3276870144,3276871423,IT
-3276871424,3276871679,GB
-3276871680,3276872479,DE
+3276870144,3276871679,IT
+3276871680,3276872255,DE
+3276872256,3276872319,CZ
+3276872320,3276872479,DE
3276872480,3276872511,GB
3276872512,3276872703,DE
3276872704,3276873727,GB
@@ -101172,7 +103048,11 @@
3276877552,3276878079,GB
3276878080,3276878335,BG
3276878336,3276878399,GB
-3276878400,3276878847,FR
+3276878400,3276878431,FR
+3276878432,3276878463,GB
+3276878464,3276878559,FR
+3276878560,3276878591,GB
+3276878592,3276878847,FR
3276878848,3276879359,ES
3276879360,3276879423,TR
3276879424,3276879615,GB
@@ -101200,8 +103080,8 @@
3276888832,3276890111,GB
3276890112,3276890135,US
3276890136,3276890143,GB
-3276890144,3276890191,US
-3276890192,3276890367,GB
+3276890144,3276890207,US
+3276890208,3276890367,GB
3276890368,3276890623,US
3276890624,3276891135,IT
3276891136,3276891391,BE
@@ -101219,11 +103099,11 @@
3276897024,3276897663,BE
3276897664,3276898047,GB
3276898048,3276898303,CZ
-3276898304,3276898775,CH
+3276898304,3276898655,CH
+3276898656,3276898671,GB
+3276898672,3276898775,CH
3276898776,3276898783,GB
-3276898784,3276899087,CH
-3276899088,3276899103,GB
-3276899104,3276900039,CH
+3276898784,3276900039,CH
3276900040,3276900047,GB
3276900048,3276900351,CH
3276900352,3276900607,GB
@@ -101239,17 +103119,14 @@
3276902200,3276902207,GB
3276902208,3276902335,CH
3276902336,3276902399,GB
-3276902400,3276902407,SE
-3276902408,3276902415,GB
-3276902416,3276902583,SE
+3276902400,3276902583,SE
3276902584,3276902615,GB
3276902616,3276902639,SE
3276902640,3276902655,GB
3276902656,3276903319,SE
3276903320,3276903327,GB
3276903328,3276903359,NO
-3276903360,3276903423,GB
-3276903424,3276903935,SE
+3276903360,3276903935,SE
3276903936,3276904191,GB
3276904192,3276904447,SE
3276904448,3276905311,GB
@@ -101282,9 +103159,7 @@
3276908192,3276909055,NL
3276909056,3276909567,GB
3276909568,3276910591,NL
-3276910592,3276912319,IT
-3276912320,3276912383,GB
-3276912384,3276912615,IT
+3276910592,3276912615,IT
3276912616,3276912623,GB
3276912624,3276913183,IT
3276913184,3276913215,GB
@@ -101362,6 +103237,7 @@
3277179392,3277179647,DE
3277179648,3277180159,BE
3277180160,3277180415,NL
+3277180416,3277180671,RU
3277180672,3277180927,FR
3277180928,3277181183,DE
3277181184,3277181439,PL
@@ -101522,7 +103398,6 @@
3277386240,3277386751,UA
3277386752,3277387263,SA
3277387264,3277388287,RU
-3277388288,3277388799,SE
3277388800,3277389311,RU
3277389312,3277389823,AM
3277389824,3277394943,GB
@@ -101761,9 +103636,7 @@
3278103296,3278110719,GB
3278110720,3278110751,SE
3278110752,3278110767,ES
-3278110768,3278111239,SE
-3278111240,3278111247,ES
-3278111248,3278115327,SE
+3278110768,3278115327,SE
3278115328,3278116607,ES
3278116608,3278116863,SE
3278116864,3278118399,ES
@@ -103350,8 +105223,7 @@
3278943625,3278943625,FR
3278943626,3278943628,DE
3278943629,3278943630,FR
-3278943631,3278943631,CH
-3278943632,3278943632,DE
+3278943631,3278943632,DE
3278943633,3278943633,GB
3278943634,3278943634,DE
3278943635,3278943635,IT
@@ -104692,7 +106564,7 @@
3280126976,3280127231,CH
3280127232,3280127487,PL
3280127488,3280127743,AT
-3280127744,3280127999,EU
+3280127744,3280127999,NL
3280128000,3280128255,SE
3280128256,3280128511,GB
3280128512,3280129023,HU
@@ -104726,11 +106598,11 @@
3280355328,3280371711,GR
3280371712,3280379903,CH
3280379904,3280388095,FR
-3280388096,3280392703,GB
+3280388096,3280390719,GB
+3280390720,3280390751,FR
+3280390752,3280392703,GB
3280392704,3280392831,FR
-3280392832,3280396255,GB
-3280396256,3280396263,FR
-3280396264,3280396287,GB
+3280392832,3280396287,GB
3280396288,3280404479,FI
3280404480,3280437247,IT
3280437248,3280453631,DE
@@ -106367,7 +108239,7 @@
3281341440,3281341695,DE
3281341696,3281341951,PL
3281341952,3281342207,DK
-3281342464,3281343231,DE
+3281342208,3281343231,DE
3281343232,3281343487,FI
3281343488,3281343743,GB
3281343744,3281343999,TR
@@ -106518,6 +108390,7 @@
3282149472,3282173951,RU
3282173952,3282174463,UA
3282174464,3282174975,GB
+3282174976,3282175487,DE
3282175488,3282177023,RU
3282177024,3282177535,GB
3282177536,3282178047,KZ
@@ -106682,6 +108555,7 @@
3283210752,3283211263,PL
3283211264,3283211775,GB
3283211776,3283212287,NL
+3283212288,3283212799,PL
3283212800,3283213311,BG
3283213312,3283213823,ES
3283213824,3283214335,UA
@@ -106808,6 +108682,7 @@
3283495680,3283495935,NL
3283495936,3283496191,BG
3283496192,3283496447,DE
+3283496448,3283496703,HR
3283496704,3283496959,LV
3283496960,3283497215,DE
3283497216,3283497471,GB
@@ -106817,7 +108692,6 @@
3283498496,3283498751,PL
3283498752,3283499007,AT
3283499008,3283499263,DE
-3283499264,3283499519,GB
3283499520,3283499775,DE
3283499776,3283500031,GB
3283500032,3283500287,DE
@@ -107426,11 +109300,23 @@
3284016384,3284016639,CH
3284016640,3284017151,DK
3284017152,3284025343,GR
-3284025344,3284028415,GB
+3284025344,3284025439,GB
+3284025440,3284025471,DE
+3284025472,3284027327,GB
+3284027328,3284027343,DE
+3284027344,3284028415,GB
3284028416,3284028671,DE
-3284028672,3284031743,GB
+3284028672,3284028879,GB
+3284028880,3284028895,DE
+3284028896,3284031743,GB
3284031744,3284031999,DE
-3284032000,3284033535,GB
+3284032000,3284032063,GB
+3284032064,3284032095,DE
+3284032096,3284032159,GB
+3284032160,3284032191,DE
+3284032192,3284032671,GB
+3284032672,3284032703,DE
+3284032704,3284033535,GB
3284033536,3284041727,RU
3284041728,3284041983,DK
3284041984,3284042239,SI
@@ -107609,6 +109495,7 @@
3284686848,3284687359,PL
3284687360,3284687871,UA
3284687872,3284688383,NG
+3284688384,3284688895,IT
3284688896,3284697087,FR
3284697088,3284697215,GB
3284697216,3284697279,FR
@@ -107664,15 +109551,9 @@
3284795392,3284803583,FR
3284803584,3284811775,DE
3284811776,3284819967,KE
-3284819968,3284820479,GB
-3284820480,3284820495,DE
-3284820496,3284823519,GB
-3284823520,3284823527,DE
-3284823528,3284825343,GB
+3284819968,3284825343,GB
3284825344,3284825359,DE
-3284825360,3284825423,GB
-3284825424,3284825439,DE
-3284825440,3284828159,GB
+3284825360,3284828159,GB
3284828160,3284844543,AT
3284844544,3284860927,CH
3284860928,3284863743,DE
@@ -107770,8 +109651,7 @@
3285387264,3285388287,PL
3285388288,3285389311,CH
3285389312,3285390335,FI
-3285390336,3285391359,RU
-3285392384,3285393407,RU
+3285390336,3285393407,RU
3285393408,3285394431,AT
3285394432,3285396479,RU
3285396480,3285397503,IR
@@ -107795,6 +109675,7 @@
3285419008,3285420031,SE
3285420032,3285424127,UA
3285424128,3285425151,RO
+3285425152,3285426175,LV
3285426176,3285427199,UA
3285427200,3285428223,GB
3285428224,3285429247,RU
@@ -107850,9 +109731,7 @@
3285457664,3285457759,IT
3285457760,3285457791,EU
3285457792,3285457919,IT
-3285457920,3285458127,GB
-3285458128,3285458143,EU
-3285458144,3285458151,GB
+3285457920,3285458151,GB
3285458152,3285458175,EU
3285458176,3285458943,GB
3285458944,3285458975,DK
@@ -107871,20 +109750,15 @@
3285461008,3285461055,EU
3285461056,3285461111,NL
3285461112,3285461119,EU
-3285461120,3285461231,NL
-3285461232,3285461247,EU
-3285461248,3285461263,NL
+3285461120,3285461263,NL
3285461264,3285461279,BE
3285461280,3285461311,EU
3285461312,3285461375,CH
3285461376,3285461407,NL
3285461408,3285461423,EU
-3285461424,3285461439,NL
-3285461440,3285461447,EU
+3285461424,3285461447,NL
3285461448,3285461455,DE
-3285461456,3285461519,NL
-3285461520,3285461527,EU
-3285461528,3285461535,NL
+3285461456,3285461535,NL
3285461536,3285461567,EU
3285461568,3285461807,NL
3285461808,3285461855,EU
@@ -107924,9 +109798,7 @@
3285463664,3285463671,EU
3285463672,3285463743,BE
3285463744,3285463775,EU
-3285463776,3285463839,BE
-3285463840,3285463855,EU
-3285463856,3285463991,BE
+3285463776,3285463991,BE
3285463992,3285464031,EU
3285464032,3285464063,BE
3285464064,3285464071,EU
@@ -109175,7 +111047,9 @@
3285926416,3285926431,GB
3285926432,3285926463,CH
3285926464,3285926511,GB
-3285926512,3285926639,EU
+3285926512,3285926623,EU
+3285926624,3285926631,US
+3285926632,3285926639,EU
3285926640,3285926671,GB
3285926672,3285926687,EU
3285926688,3285926719,IN
@@ -109386,6 +111260,8 @@
3286313984,3286314495,CH
3286314496,3286315007,IL
3286315008,3286315519,UA
+3286315520,3286315775,SI
+3286315776,3286316031,BG
3286316032,3286316543,UA
3286316544,3286317055,NL
3286317056,3286317567,RU
@@ -109491,6 +111367,7 @@
3286654976,3286655231,UA
3286655232,3286655487,KZ
3286655488,3286655743,LT
+3286655744,3286655999,RU
3286656000,3286656255,CH
3286656256,3286656511,RU
3286656512,3286656767,GR
@@ -109923,6 +111800,8 @@
3287468032,3287469055,UA
3287469056,3287471103,DE
3287471104,3287472127,GB
+3287472128,3287472639,RU
+3287472640,3287473151,UA
3287473152,3287474175,GB
3287474176,3287476223,DE
3287476224,3287477247,PL
@@ -110195,13 +112074,14 @@
3287949824,3287950079,IT
3287950080,3287950335,DE
3287950336,3287950591,UA
-3287950592,3287950847,PL
+3287950592,3287951103,PL
3287951104,3287951359,HU
3287951360,3287951615,FR
3287951616,3287951871,CH
3287951872,3287952127,RU
3287952128,3287952383,UA
-3287952384,3287953407,CH
+3287952384,3287953151,CH
+3287953152,3287953407,UA
3287953408,3287953663,DE
3287953664,3287953919,GB
3287953920,3287954175,DE
@@ -110213,7 +112093,6 @@
3287955712,3287955967,DE
3287955968,3287956223,SI
3287956224,3287956479,RO
-3287956480,3287956735,FR
3287956736,3287956991,SE
3287956992,3287957247,UA
3287957248,3287957503,GB
@@ -110533,6 +112412,7 @@
3291208704,3291208959,KE
3291208960,3291209215,TZ
3291209216,3291209471,KE
+3291209472,3291209727,AO
3291217920,3291230207,ZA
3291230208,3291234303,GH
3291234304,3291242495,ZA
@@ -110747,6 +112627,9 @@
3314024448,3314286591,KE
3314286592,3314548735,DZ
3315335168,3315351551,ZA
+3315351552,3315367935,ET
+3315564544,3315568639,GH
+3315580928,3315589119,CI
3315597312,3316121599,EG
3316121600,3316645887,ZA
3316645888,3317170175,KE
@@ -110754,7 +112637,7 @@
3318218752,3318743039,DZ
3319398400,3319529471,MZ
3319529472,3319537663,ZM
-3319537664,3319545855,UG
+3319537664,3319545855,MW
3319545856,3319554047,SO
3319554048,3319562239,KE
3319562240,3319570431,LS
@@ -110773,6 +112656,7 @@
3320643584,3320709119,KE
3320709120,3320840191,ZA
3321102336,3321167871,NG
+3321167872,3321233407,ZA
3321364480,3321430015,KE
3321430016,3321495551,MZ
3321495552,3321561087,TZ
@@ -110792,6 +112676,7 @@
3321868288,3321872383,CG
3321872384,3321876479,GM
3321876480,3321880575,NG
+3321880576,3321884671,KM
3321954304,3321970687,US
3322019840,3322023935,US
3322023936,3322028031,CL
@@ -111816,9 +113701,7 @@
3343167488,3343169535,CA
3343169536,3343171583,US
3343171584,3343172607,BM
-3343172608,3343172735,US
-3343172736,3343172751,HK
-3343172752,3343319295,US
+3343172608,3343319295,US
3343319296,3343364095,CA
3343364096,3343365119,US
3343365632,3343372543,CA
@@ -111902,11 +113785,95 @@
3345398784,3345399807,BS
3345399808,3345401855,PR
3345401856,3345403903,CA
-3345403904,3345408197,US
+3345403904,3345408005,US
+3345408006,3345408009,CZ
+3345408010,3345408017,US
+3345408018,3345408021,GB
+3345408022,3345408092,US
+3345408093,3345408094,GB
+3345408095,3345408098,VE
+3345408099,3345408110,US
+3345408111,3345408114,AU
+3345408115,3345408161,US
+3345408162,3345408165,CA
+3345408166,3345408189,US
+3345408190,3345408193,AR
+3345408194,3345408197,US
3345408198,3345408225,IN
-3345408226,3345408949,US
+3345408226,3345408227,GB
+3345408228,3345408235,US
+3345408236,3345408239,CN
+3345408240,3345408319,US
+3345408320,3345408323,GB
+3345408324,3345408335,US
+3345408336,3345408339,GB
+3345408340,3345408386,US
+3345408387,3345408394,GB
+3345408395,3345408415,US
+3345408416,3345408420,AU
+3345408421,3345408424,US
+3345408425,3345408428,GB
+3345408429,3345408460,US
+3345408461,3345408464,IN
+3345408465,3345408479,US
+3345408480,3345408483,GB
+3345408484,3345408534,US
+3345408535,3345408538,AU
+3345408539,3345408542,CA
+3345408543,3345408569,US
+3345408570,3345408573,CA
+3345408574,3345408577,US
+3345408578,3345408589,GB
+3345408590,3345408634,US
+3345408635,3345408639,CA
+3345408640,3345408651,US
+3345408652,3345408655,CA
+3345408656,3345408667,US
+3345408668,3345408671,CA
+3345408672,3345408697,US
+3345408698,3345408701,GB
+3345408702,3345408784,US
+3345408785,3345408788,CA
+3345408789,3345408903,US
+3345408904,3345408907,GB
+3345408908,3345408949,US
3345408950,3345408993,IN
-3345408994,3345418239,US
+3345408994,3345409033,US
+3345409034,3345409037,CA
+3345409038,3345409085,US
+3345409086,3345409089,CA
+3345409090,3345409093,US
+3345409094,3345409097,CA
+3345409098,3345409101,US
+3345409102,3345409105,GB
+3345409106,3345409171,US
+3345409172,3345409175,GB
+3345409176,3345409179,CN
+3345409180,3345409204,US
+3345409205,3345409212,AU
+3345409213,3345409217,US
+3345409218,3345409221,AU
+3345409222,3345409245,US
+3345409246,3345409255,GB
+3345409256,3345409558,US
+3345409559,3345409562,CA
+3345409563,3345409576,US
+3345409577,3345409580,GB
+3345409581,3345409722,US
+3345409723,3345409727,GB
+3345409728,3345409782,US
+3345409783,3345409786,SG
+3345409787,3345409895,US
+3345409896,3345409899,PR
+3345409900,3345409903,CA
+3345409904,3345409911,US
+3345409912,3345409915,CA
+3345409916,3345409919,AU
+3345409920,3345409945,US
+3345409946,3345409949,SG
+3345409950,3345409957,US
+3345409958,3345409961,CA
+3345409962,3345418239,US
3345418240,3345419519,NL
3345419520,3345422847,US
3345423360,3345424383,TC
@@ -111961,9 +113928,11 @@
3346497536,3346498559,CA
3346498560,3346499583,US
3346499584,3346501631,VI
-3346501632,3346506047,US
-3346506048,3346506055,CA
-3346506056,3346510271,US
+3346501632,3346506039,US
+3346506040,3346506055,CA
+3346506056,3346506119,US
+3346506120,3346506127,MX
+3346506128,3346510271,US
3346510272,3346510335,IL
3346510336,3346520063,US
3346520064,3346521087,CA
@@ -112019,7 +113988,9 @@
3349647360,3349649407,US
3349649408,3349653503,CA
3349653504,3349692415,US
-3349708800,3349731327,US
+3349708800,3349723996,US
+3349723997,3349724000,LK
+3349724001,3349731327,US
3349731328,3349733375,CA
3349733376,3349739519,US
3349739520,3349740543,CA
@@ -112040,7 +114011,17 @@
3350470656,3350475775,US
3350475776,3350476799,CA
3350476800,3350478847,US
-3350495232,3350593535,US
+3350495232,3350495602,US
+3350495603,3350495604,BD
+3350495605,3350495873,US
+3350495874,3350495874,IN
+3350495875,3350495881,US
+3350495882,3350495882,IN
+3350495883,3350496532,US
+3350496533,3350496533,IN
+3350496534,3350496721,US
+3350496722,3350496723,IN
+3350496724,3350593535,US
3350593536,3350609919,CA
3350614016,3350618111,US
3350626304,3350790143,US
@@ -112056,11 +114037,35 @@
3350980608,3350994943,US
3350994944,3350998015,CA
3350998016,3350999039,US
-3351019520,3351027711,US
-3351052288,3351068671,US
-3351117824,3351232511,US
+3351019520,3351030783,US
+3351030784,3351031807,CA
+3351031808,3351034879,US
+3351034880,3351035903,CA
+3351035904,3351036927,US
+3351036928,3351037951,CA
+3351037952,3351043071,US
+3351043072,3351044095,CA
+3351044096,3351068671,US
+3351085056,3351086079,US
+3351086080,3351087103,CA
+3351087104,3351103487,US
+3351103488,3351104511,CA
+3351104512,3351112703,US
+3351112704,3351113727,CA
+3351113728,3351232511,US
3351232512,3351232767,IL
-3351232768,3351380223,US
+3351232768,3351265279,US
+3351281664,3351293951,US
+3351293952,3351294975,CA
+3351294976,3351295999,US
+3351296000,3351298047,CA
+3351298048,3351303167,US
+3351303168,3351304191,CA
+3351304192,3351306239,US
+3351306240,3351307263,VC
+3351307264,3351308287,US
+3351308288,3351310335,CA
+3351310336,3351380223,US
3351380224,3351380479,CA
3351380480,3351380735,US
3351380736,3351381759,CA
@@ -112751,7 +114756,9 @@
3356514304,3356514559,US
3356514560,3356514815,AR
3356514816,3356515327,DO
-3356515328,3356515583,AN
+3356515328,3356515839,AN
+3356515840,3356516095,EC
+3356516096,3356516351,VE
3356516352,3356520447,AR
3356520448,3356521471,CL
3356521472,3356521727,AR
@@ -113007,7 +115014,9 @@
3358720000,3358720075,PR
3358720076,3358720083,DO
3358720084,3358722047,PR
-3358722048,3358723071,DO
+3358722048,3358722671,DO
+3358722672,3358722687,PR
+3358722688,3358723071,DO
3358723072,3358723327,PR
3358723328,3358723583,AN
3358723584,3358724095,PR
@@ -113171,7 +115180,8 @@
3359481856,3359498239,AR
3359498240,3359501311,PY
3359501312,3359502335,SR
-3359502336,3359504383,AR
+3359502336,3359505407,AR
+3359505408,3359505663,VE
3359506432,3359508479,US
3359508480,3359514623,VE
3359514624,3359516671,GT
@@ -113352,7 +115362,7 @@
3360775168,3360775679,BO
3360775680,3360788479,AR
3360788480,3360790527,CL
-3360790528,3360849919,AR
+3360792576,3360849919,AR
3360849920,3360882687,VE
3360882688,3360948223,CL
3360948224,3361013759,VE
@@ -113427,6 +115437,7 @@
3362428928,3362430975,CL
3362430976,3362447359,CO
3362447360,3362451455,SV
+3362451456,3362452479,AR
3362455552,3362471935,EC
3362471936,3362476031,CL
3362476032,3362476287,HN
@@ -113558,7 +115569,8 @@
3363733504,3363831807,AR
3363831808,3378511871,BR
3378511872,3383754751,MX
-3383754752,3384279039,AR
+3383754752,3384147967,AR
+3384147968,3384213503,PA
3384279040,3384410111,CO
3384410112,3384672255,CL
3384672256,3384688639,HN
@@ -113578,6 +115590,7 @@
3386458112,3386474495,EC
3386474496,3386490879,UY
3386490880,3386499071,CO
+3386499072,3386503167,AR
3386507264,3386523647,EC
3386523648,3386540031,PA
3386540032,3386548223,CL
@@ -119152,7 +121165,9 @@
3423554768,3423571967,US
3423571968,3423574015,PR
3423574016,3423582207,US
-3423582208,3423584335,CA
+3423582208,3423584271,CA
+3423584272,3423584279,US
+3423584280,3423584335,CA
3423584336,3423584351,US
3423584352,3423584359,AU
3423584360,3423584367,CA
@@ -119169,9 +121184,7 @@
3423584752,3423584767,US
3423584768,3423585535,CA
3423585536,3423585551,MY
-3423585552,3423585631,CA
-3423585632,3423585647,US
-3423585648,3423585775,CA
+3423585552,3423585775,CA
3423585776,3423585791,MY
3423585792,3423585895,CA
3423585896,3423585903,NL
@@ -119234,6 +121247,7 @@
3423838720,3423838975,US
3423838976,3423848447,CA
3423848448,3423849471,KN
+3423849472,3423849983,US
3423849984,3423850495,CA
3423850496,3423850751,US
3423850752,3423854335,CA
@@ -119259,7 +121273,9 @@
3425173504,3425304575,CA
3425304576,3425697791,US
3425697792,3425699839,CA
-3425699840,3425828863,US
+3425699840,3425714175,US
+3425714176,3425722367,CA
+3425722368,3425828863,US
3425828864,3425830815,CA
3425830816,3425830831,US
3425830832,3425850519,CA
@@ -119295,14 +121311,20 @@
3426618752,3426618911,US
3426618912,3426619071,NZ
3426619072,3426619167,US
-3426619168,3426619231,NZ
-3426619232,3426646015,US
+3426619168,3426619247,NZ
+3426619248,3426619263,US
+3426619264,3426619295,NZ
+3426619296,3426646015,US
3426646016,3426647039,CA
3426647040,3426729471,US
3426729472,3426729983,CA
3426729984,3426744319,US
3426744320,3426746367,CA
-3426746368,3427127295,US
+3426746368,3427033087,US
+3427033088,3427041279,A1
+3427041280,3427117055,US
+3427117056,3427117311,CA
+3427117312,3427127295,US
3427127296,3427127551,CA
3427127552,3427127807,US
3427128064,3427618303,US
@@ -119968,7 +121990,9 @@
3435518528,3436249343,US
3436249344,3436255743,CA
3436255744,3436256255,US
-3436256256,3436282367,CA
+3436256256,3436278271,CA
+3436278272,3436278527,US
+3436278528,3436282367,CA
3436282368,3436282623,US
3436282624,3436289791,CA
3436289792,3436290047,US
@@ -120314,9 +122338,7 @@
3438545424,3438545431,US
3438545432,3438545471,CA
3438545472,3438545479,US
-3438545480,3438545583,CA
-3438545584,3438545591,US
-3438545592,3438550071,CA
+3438545480,3438550071,CA
3438550072,3438550079,US
3438550080,3438550447,CA
3438550448,3438550463,US
@@ -121078,22 +123100,26 @@
3453554160,3453554175,GB
3453554176,3453554207,US
3453554208,3453554215,GB
-3453554216,3453554431,US
+3453554216,3453554239,US
+3453554240,3453554255,GB
+3453554256,3453554431,US
3453554432,3453554687,GB
3453554688,3453554863,US
3453554864,3453554879,NL
3453554880,3453555711,US
3453555712,3453555767,GB
3453555768,3453583615,US
-3453583616,3453583631,SG
-3453583632,3453599999,US
+3453583616,3453583679,SG
+3453583680,3453599999,US
3453600000,3453600767,GB
3453600768,3453601863,US
3453601864,3453601871,GB
3453601872,3453601879,CH
3453601880,3453602175,US
3453602176,3453602183,GB
-3453602184,3453607935,US
+3453602184,3453602207,US
+3453602208,3453602223,GB
+3453602224,3453607935,US
3453607936,3453608959,KN
3453608960,3453609983,LC
3453609984,3453610495,AG
@@ -121596,7 +123622,9 @@
3460453632,3460453887,BS
3460453888,3460507647,US
3460507648,3460507903,MX
-3460507904,3460854439,US
+3460507904,3460800511,US
+3460800512,3460808703,A1
+3460808704,3460854439,US
3460854440,3460854447,CA
3460854448,3460854831,US
3460854832,3460854847,VE
@@ -122274,9 +124302,7 @@
3464341896,3464341903,GB
3464341904,3464341927,US
3464341928,3464341935,CV
-3464341936,3464341951,US
-3464341952,3464341959,CZ
-3464341960,3464342543,US
+3464341936,3464342543,US
3464342544,3464342559,SE
3464342560,3464342567,US
3464342568,3464342575,PT
@@ -122335,7 +124361,9 @@
3464550128,3464550143,US
3464550144,3464550399,LC
3464550400,3464626175,US
-3464626176,3464630271,CA
+3464626432,3464626687,CA
+3464626688,3464627199,US
+3464627968,3464630271,CA
3464630272,3464631295,US
3464631296,3464650751,CA
3464650752,3464664063,US
@@ -122377,11 +124405,21 @@
3465468352,3465468367,FI
3465468368,3465468383,US
3465468384,3465468399,GB
-3465468400,3465510911,US
+3465468400,3465468879,US
+3465468880,3465468911,SG
+3465468912,3465468935,US
+3465468936,3465468943,SG
+3465468944,3465510911,US
3465510912,3465543679,JP
3465543680,3465953503,US
3465953504,3465953535,CA
-3465953536,3465982991,US
+3465953536,3465954175,US
+3465954176,3465954303,CA
+3465954304,3465961607,US
+3465961608,3465961615,CA
+3465961616,3465961631,US
+3465961632,3465961663,CA
+3465961664,3465982991,US
3465982992,3465983007,GB
3465983008,3465983023,US
3465983024,3465983127,GB
@@ -123359,9 +125397,7 @@
3470360688,3470360695,AF
3470360696,3470360799,US
3470360800,3470360807,CA
-3470360808,3470360815,US
-3470360816,3470360823,AU
-3470360824,3470361039,US
+3470360808,3470361039,US
3470361040,3470361055,CA
3470361056,3470361487,US
3470361488,3470361495,SG
@@ -123369,7 +125405,11 @@
3470361664,3470361671,CA
3470361672,3470361703,US
3470361704,3470361711,AF
-3470361712,3470362111,US
+3470361712,3470361771,US
+3470361772,3470361775,AE
+3470361776,3470362099,US
+3470362100,3470362103,AE
+3470362104,3470362111,US
3470362112,3470362119,CA
3470362120,3470362127,AU
3470362128,3470362135,US
@@ -123386,9 +125426,12 @@
3470362456,3470362471,CA
3470362472,3470362487,US
3470362488,3470362495,ES
-3470362496,3470362559,US
+3470362496,3470362543,US
+3470362544,3470362559,SE
3470362560,3470362623,CA
-3470362624,3470362791,US
+3470362624,3470362731,US
+3470362732,3470362735,AE
+3470362736,3470362791,US
3470362792,3470362799,SG
3470362800,3470362847,US
3470362848,3470362855,AR
@@ -123411,9 +125454,7 @@
3470364096,3470364103,AU
3470364104,3470364415,US
3470364416,3470364479,CA
-3470364480,3470364495,US
-3470364496,3470364503,CA
-3470364504,3470364655,US
+3470364480,3470364655,US
3470364656,3470364663,CA
3470364664,3470458879,US
3470458880,3470475263,KR
@@ -123695,7 +125736,9 @@
3471572992,3472375807,US
3472375808,3472392191,PR
3472392192,3472408575,CA
-3472408576,3472990207,US
+3472408576,3472613375,US
+3472613376,3472621567,A1
+3472621568,3472990207,US
3472990208,3472990463,AS
3472990464,3473039359,US
3473039360,3473040639,BM
@@ -124352,7 +126395,9 @@
3482778384,3482779647,PR
3482779648,3482910719,US
3482910720,3482927103,CA
-3482927104,3483296004,US
+3482927104,3483238399,US
+3483238400,3483254783,A1
+3483254784,3483296004,US
3483296005,3483296005,BE
3483296006,3483435007,US
3483435008,3483533311,CA
@@ -124538,7 +126583,8 @@
3485446144,3485458847,US
3485458848,3485458863,FR
3485458864,3485462527,US
-3485462528,3485466623,VC
+3485462528,3485464575,VC
+3485464576,3485466623,LC
3485466624,3485597695,US
3485597696,3485671583,CA
3485671584,3485671615,US
@@ -124850,7 +126896,9 @@
3487862016,3487875071,BM
3487875072,3487891455,US
3487891456,3487907839,CA
-3487907840,3487969791,US
+3487907840,3487912959,US
+3487912960,3487913087,CA
+3487913088,3487969791,US
3487969792,3487970047,KW
3487970048,3488014335,US
3488014336,3488022527,CA
@@ -124995,9 +127043,7 @@
3491743744,3491745791,CO
3491745792,3491764783,US
3491764784,3491764791,PR
-3491764792,3491780607,US
-3491780608,3491781631,EC
-3491781632,3491826687,US
+3491764792,3491826687,US
3491826688,3491826943,AN
3491826944,3491832575,US
3491832576,3491832583,PR
@@ -125036,7 +127082,9 @@
3492188800,3492188831,CH
3492188832,3492472039,US
3492472040,3492472047,GB
-3492472048,3492646623,US
+3492472048,3492576143,US
+3492576144,3492576151,CN
+3492576152,3492646623,US
3492646624,3492646639,IL
3492646640,3492669695,US
3492669696,3492671487,PA
@@ -125084,7 +127132,9 @@
3493137248,3493137407,DE
3493137408,3493138207,US
3493138208,3493138239,DE
-3493138240,3493141279,US
+3493138240,3493140223,US
+3493140224,3493140479,DE
+3493140480,3493141279,US
3493141280,3493141311,CY
3493141312,3493244927,US
3493244928,3493249023,PR
@@ -125303,10 +127353,8 @@
3494313328,3494313343,CO
3494313344,3494313359,US
3494313360,3494313375,MX
-3494313376,3494313391,ES
-3494313392,3494313535,US
-3494313536,3494313551,AU
-3494313552,3494316031,US
+3494313376,3494313383,ES
+3494313384,3494316031,US
3494316032,3494317055,CA
3494317056,3494336511,US
3494336512,3494337023,CA
@@ -125583,7 +127631,11 @@
3494862848,3494863871,DM
3494863872,3494866943,US
3494866944,3494867967,CA
-3494867968,3494893567,US
+3494867968,3494874111,US
+3494874112,3494874367,ES
+3494874368,3494874879,US
+3494874880,3494874911,ES
+3494874912,3494893567,US
3494893568,3494894591,CA
3494894592,3494906455,US
3494906456,3494906463,GB
@@ -125843,7 +127895,13 @@
3495515136,3495516159,CA
3495516160,3495520375,US
3495520376,3495520379,SG
-3495520380,3495526399,US
+3495520380,3495520571,US
+3495520572,3495520579,KE
+3495520580,3495520667,US
+3495520668,3495520706,BR
+3495520707,3495520707,US
+3495520708,3495520715,CH
+3495520716,3495526399,US
3495526400,3495527423,CA
3495527424,3495542783,US
3495542784,3495544831,A2
@@ -125983,7 +128041,7 @@
3495866080,3495866359,CA
3495866360,3495866363,US
3495866364,3495866367,CA
-3495866368,3495868415,VC
+3495866368,3495868415,LC
3495868416,3495871487,US
3495871488,3495872511,CA
3495872512,3495881119,US
@@ -126265,7 +128323,13 @@
3497226392,3497226399,IR
3497226400,3497226687,US
3497226688,3497226719,GB
-3497226720,3497233407,US
+3497226720,3497226943,US
+3497226944,3497226975,CA
+3497226976,3497227311,US
+3497227312,3497227327,CA
+3497227328,3497227599,US
+3497227600,3497227615,CA
+3497227616,3497233407,US
3497233408,3497233663,CN
3497233664,3497263815,US
3497263816,3497263823,GB
@@ -126388,11 +128452,31 @@
3500486656,3500490751,CR
3500490752,3500613631,US
3500613632,3500614655,MZ
-3500614656,3500664511,US
-3500664512,3500664527,CA
-3500664528,3500664831,US
-3500664832,3500665087,CA
-3500665088,3500689407,US
+3500614656,3500663545,US
+3500663546,3500663546,CA
+3500663547,3500664319,US
+3500664320,3500664375,CA
+3500664376,3500664383,US
+3500664384,3500664431,CA
+3500664432,3500664511,US
+3500664512,3500664535,CA
+3500664536,3500664573,US
+3500664574,3500664574,CA
+3500664575,3500664575,US
+3500664576,3500664591,CA
+3500664592,3500664831,US
+3500664832,3500665103,CA
+3500665104,3500665119,US
+3500665120,3500665343,CA
+3500665344,3500665855,US
+3500665856,3500665871,CA
+3500665872,3500665887,US
+3500665888,3500665935,CA
+3500665936,3500665983,US
+3500665984,3500666111,CA
+3500666112,3500669951,US
+3500669952,3500670463,CA
+3500670464,3500689407,US
3500689408,3500689919,CL
3500689920,3500707327,US
3500707328,3500707839,CA
@@ -128138,7 +130222,9 @@
3512269824,3512270847,US
3512270848,3512336383,CA
3512336384,3512369151,US
-3512369152,3512378435,CA
+3512369152,3512377231,CA
+3512377232,3512377239,US
+3512377240,3512378435,CA
3512378436,3512378436,US
3512378437,3512385535,CA
3512385536,3512397823,US
@@ -128598,9 +130684,7 @@
3513501568,3513501631,AZ
3513501632,3513502719,US
3513502720,3513502975,A1
-3513502976,3513503743,US
-3513503744,3513503999,SC
-3513504000,3513506047,US
+3513502976,3513506047,US
3513506048,3513506303,A1
3513506304,3513506559,US
3513506560,3513506815,CA
@@ -128608,7 +130692,9 @@
3513670912,3513671167,A2
3513671168,3513778175,US
3513778176,3513794559,CA
-3513794560,3514007551,US
+3513794560,3513839615,US
+3513839616,3513843711,A1
+3513843712,3514007551,US
3514007552,3514040319,CA
3514040320,3514367999,US
3514368000,3514433535,CA
@@ -128646,11 +130732,7 @@
3515453056,3515453071,JP
3515453072,3515453679,US
3515453680,3515453687,JP
-3515453688,3515454063,US
-3515454064,3515454079,JP
-3515454080,3515454095,US
-3515454096,3515454111,JP
-3515454112,3515454143,US
+3515453688,3515454143,US
3515454144,3515454207,JP
3515454208,3515454399,US
3515454400,3515454463,JP
@@ -128663,7 +130745,9 @@
3515456768,3515596799,US
3515596800,3515613183,CA
3515613184,3515686911,US
-3515686912,3515695103,CA
+3515686912,3515687167,CA
+3515687168,3515688191,US
+3515688192,3515695103,CA
3515695104,3515711487,US
3515711488,3515731967,CA
3515731968,3515736063,US
@@ -129061,7 +131145,8 @@
3517596672,3517596927,NO
3517596928,3517597183,IE
3517597184,3517597695,US
-3517597696,3517598207,SE
+3517597696,3517597951,IE
+3517597952,3517598207,DE
3517598208,3517598463,IE
3517598464,3517598527,SE
3517598528,3517598559,FR
@@ -129608,7 +131693,9 @@
3520036360,3520036863,CA
3520036864,3520071823,US
3520071824,3520071839,NL
-3520071840,3520073967,US
+3520071840,3520072751,US
+3520072752,3520072767,AR
+3520072768,3520073967,US
3520073968,3520073975,CA
3520073976,3520074671,US
3520074672,3520074687,GB
@@ -129665,7 +131752,9 @@
3520527872,3520528383,A2
3520528384,3520626687,US
3520626688,3520634879,CA
-3520634880,3520675839,US
+3520634880,3520643071,US
+3520643072,3520659455,A1
+3520659456,3520675839,US
3520675840,3520675991,CA
3520675992,3520675999,US
3520676000,3520679439,CA
@@ -129693,15 +131782,19 @@
3520956156,3520956159,CH
3520956160,3520978943,US
3520978944,3520979711,BZ
-3520979712,3520999423,US
+3520979712,3520987903,US
+3520987904,3520987935,A1
+3520987936,3520994815,US
+3520994816,3520995327,ES
+3520995328,3520999423,US
3520999424,3521003519,CA
3521003520,3521003583,US
3521003584,3521003647,IL
-3521003648,3521005319,US
+3521003648,3521005311,US
+3521005312,3521005319,MY
3521005320,3521005327,GB
-3521005328,3521009663,US
-3521009664,3521009671,AR
-3521009672,3521011719,US
+3521005328,3521005335,DE
+3521005336,3521011719,US
3521011720,3521011727,BR
3521011728,3521011735,AU
3521011736,3521011743,US
@@ -129779,7 +131872,9 @@
3521372096,3521372159,CA
3521372160,3521377407,US
3521377408,3521377439,IT
-3521377440,3521835903,US
+3521377440,3521835567,US
+3521835568,3521835575,CH
+3521835576,3521835903,US
3521835904,3521835967,CA
3521835968,3521836687,US
3521836688,3521836703,GB
@@ -129820,7 +131915,8 @@
3521933842,3521933929,US
3521933930,3521933937,IN
3521933938,3521933945,GB
-3521933946,3521933981,US
+3521933946,3521933953,EG
+3521933954,3521933981,US
3521933982,3521933989,IN
3521933990,3521934089,US
3521934090,3521934097,EG
@@ -129828,18 +131924,18 @@
3521934122,3521934129,ID
3521934130,3521934137,US
3521934138,3521934145,GR
-3521934146,3521934153,ID
-3521934154,3521934169,US
+3521934146,3521934161,ID
+3521934162,3521934169,US
3521934170,3521934177,EG
-3521934178,3521934233,US
+3521934178,3521934185,US
+3521934186,3521934201,LK
+3521934202,3521934233,US
3521934234,3521934241,ID
3521934242,3521934421,US
3521934422,3521934429,EG
3521934430,3521934437,US
3521934438,3521934445,IN
-3521934446,3521934477,US
-3521934478,3521934485,ID
-3521934486,3521934509,US
+3521934446,3521934509,US
3521934510,3521934517,IN
3521934518,3521934735,US
3521934736,3521934743,EG
@@ -129874,7 +131970,9 @@
3521936978,3521936993,US
3521936994,3521937001,LK
3521937002,3521937005,US
-3521937006,3521937013,EG
+3521937006,3521937009,EG
+3521937010,3521937011,US
+3521937012,3521937013,EG
3521937014,3521937017,US
3521937018,3521937025,SG
3521937026,3521937161,US
@@ -129924,8 +132022,7 @@
3522133664,3522133695,DE
3522133696,3522133759,US
3522133760,3522133791,IR
-3522133792,3522133823,DE
-3522133824,3522174975,US
+3522133792,3522174975,US
3522174976,3522179071,BM
3522179072,3522195455,US
3522195456,3522199551,CA
@@ -129975,7 +132072,7 @@
3523553280,3523555327,MY
3523555328,3523557375,NZ
3523557376,3523575807,PH
-3523579904,3523583999,CN
+3523575808,3523583999,CN
3523584000,3523592479,HK
3523592480,3523592495,YE
3523592496,3523592511,HK
@@ -130373,6 +132470,7 @@
3556851712,3556868095,UA
3556868096,3556876287,GB
3556876288,3556884479,NL
+3556884480,3556886527,IR
3556892672,3556900863,RU
3556900864,3556909055,GB
3556909056,3556925439,DE
@@ -130474,9 +132572,7 @@
3557176832,3557177023,IQ
3557177024,3557177199,IT
3557177200,3557177215,IR
-3557177216,3557178367,IT
-3557178368,3557179135,IR
-3557179136,3557179391,IT
+3557177216,3557179391,IT
3557179392,3557213351,DE
3557213352,3557213359,US
3557213360,3557228543,DE
@@ -130566,9 +132662,7 @@
3557360560,3557360575,JE
3557360576,3557360680,GB
3557360681,3557360687,JE
-3557360688,3557360891,GB
-3557360892,3557360895,JE
-3557360896,3557360927,GB
+3557360688,3557360927,GB
3557360928,3557360943,JE
3557360944,3557360959,GB
3557360960,3557360967,JE
@@ -130584,8 +132678,10 @@
3557361376,3557361391,JE
3557361392,3557361415,GB
3557361416,3557361423,JE
-3557361424,3557361607,GB
-3557361608,3557361615,JE
+3557361424,3557361455,GB
+3557361456,3557361463,JE
+3557361464,3557361599,GB
+3557361600,3557361615,JE
3557361616,3557361663,GB
3557361664,3557361983,JE
3557361984,3557362047,GB
@@ -130602,8 +132698,8 @@
3557364104,3557364107,JE
3557364108,3557364147,GB
3557364148,3557364151,JE
-3557364152,3557364159,GB
-3557364160,3557364223,JE
+3557364152,3557364167,GB
+3557364168,3557364223,JE
3557364224,3557364479,GB
3557364480,3557364495,JE
3557364496,3557364527,GB
@@ -130648,13 +132744,21 @@
3557365912,3557365919,JE
3557365920,3557365935,GB
3557365936,3557366015,JE
-3557366016,3557366055,GB
+3557366016,3557366023,GB
+3557366024,3557366031,JE
+3557366032,3557366055,GB
3557366056,3557366063,JE
-3557366064,3557366111,GB
+3557366064,3557366095,GB
+3557366096,3557366103,JE
+3557366104,3557366111,GB
3557366112,3557366119,JE
-3557366120,3557366263,GB
+3557366120,3557366167,GB
+3557366168,3557366175,JE
+3557366176,3557366263,GB
3557366264,3557366271,JE
-3557366272,3557367807,GB
+3557366272,3557366279,GB
+3557366280,3557366287,JE
+3557366288,3557367807,GB
3557367808,3557375999,DE
3557376000,3557384191,ES
3557384192,3557392383,GB
@@ -130721,7 +132825,10 @@
3557810176,3557818367,ES
3557818368,3557826559,RU
3557826560,3557834751,AT
-3557834752,3557842943,IR
+3557834752,3557836287,GB
+3557836288,3557836543,IR
+3557836544,3557837055,GB
+3557837056,3557842943,IR
3557842944,3557851135,FI
3557851136,3557859327,HU
3557859328,3557859839,SE
@@ -130955,7 +133062,8 @@
3558290672,3558290687,BE
3558290688,3558290871,ES
3558290872,3558290879,GB
-3558290880,3558290943,ES
+3558290880,3558290911,ES
+3558290912,3558290943,GB
3558290944,3558290959,DE
3558290960,3558290967,NL
3558290968,3558290975,GB
@@ -131079,7 +133187,9 @@
3558547456,3558555647,FR
3558555648,3558572031,AT
3558572032,3558580223,DE
-3558580224,3558588415,CH
+3558580224,3558581423,CH
+3558581424,3558581439,DE
+3558581440,3558588415,CH
3558588416,3558596607,CZ
3558596608,3558604799,EE
3558604800,3558612991,GB
@@ -131387,7 +133497,9 @@
3559091424,3559091427,GB
3559091428,3559091439,BE
3559091440,3559091447,ES
-3559091448,3559091495,BE
+3559091448,3559091455,BE
+3559091456,3559091487,DE
+3559091488,3559091495,BE
3559091496,3559091503,GB
3559091504,3559091507,BE
3559091508,3559091511,GB
@@ -131405,11 +133517,7 @@
3559092160,3559092160,GB
3559092161,3559092222,BE
3559092223,3559092223,GB
-3559092224,3559092311,BE
-3559092312,3559092319,GB
-3559092320,3559092399,BE
-3559092400,3559092407,GB
-3559092408,3559092735,BE
+3559092224,3559092735,BE
3559092736,3559092739,GB
3559092740,3559092799,BE
3559092800,3559092803,GB
@@ -131707,7 +133815,9 @@
3559776256,3559792639,RU
3559792640,3559800831,SA
3559800832,3559809023,IT
-3559809024,3559815595,DE
+3559809024,3559815427,DE
+3559815428,3559815431,AT
+3559815432,3559815595,DE
3559815596,3559815599,NL
3559815600,3559817215,DE
3559817216,3559825407,GB
@@ -131776,12 +133886,12 @@
3559902464,3559902975,UA
3559902976,3559903487,EE
3559903488,3559903551,UA
-3559903552,3559903615,EE
-3559903616,3559903679,UA
+3559903552,3559903631,EE
+3559903632,3559903679,UA
3559903680,3559904003,EE
3559904004,3559904015,UA
-3559904016,3559904039,EE
-3559904040,3559904127,UA
+3559904016,3559904043,EE
+3559904044,3559904127,UA
3559904128,3559904383,EE
3559904384,3559904511,UA
3559904512,3559904767,EE
@@ -131809,12 +133919,12 @@
3559905318,3559905319,LT
3559905320,3559905323,UA
3559905324,3559905331,EE
-3559905332,3559905535,UA
-3559905536,3559905623,EE
-3559905624,3559905631,UA
-3559905632,3559905695,EE
-3559905696,3559905703,UA
-3559905704,3559905903,EE
+3559905332,3559905347,UA
+3559905348,3559905349,EE
+3559905350,3559905535,UA
+3559905536,3559905615,EE
+3559905616,3559905631,UA
+3559905632,3559905903,EE
3559905904,3559905911,UA
3559905912,3559906257,EE
3559906258,3559906263,UA
@@ -134392,11 +136502,37 @@
3562086400,3562087423,SE
3562087424,3562088447,GB
3562088448,3562094591,SE
-3562094592,3562105599,GB
+3562094592,3562095607,GB
+3562095608,3562095615,FR
+3562095616,3562096063,GB
+3562096064,3562096127,FR
+3562096128,3562098367,GB
+3562098368,3562098375,FR
+3562098376,3562101471,GB
+3562101472,3562101479,FR
+3562101480,3562101631,GB
+3562101632,3562101639,FR
+3562101640,3562104991,GB
+3562104992,3562104999,FR
+3562105000,3562105599,GB
3562105600,3562105855,FR
3562105856,3562106879,GB
3562106880,3562106911,FR
-3562106912,3562110463,GB
+3562106912,3562106943,GB
+3562106944,3562106959,FR
+3562106960,3562107071,GB
+3562107072,3562107103,FR
+3562107104,3562107231,GB
+3562107232,3562107263,FR
+3562107264,3562107519,GB
+3562107520,3562107583,FR
+3562107584,3562108959,GB
+3562108960,3562108975,FR
+3562108976,3562109567,GB
+3562109568,3562109583,FR
+3562109584,3562110399,GB
+3562110400,3562110431,FR
+3562110432,3562110463,GB
3562110464,3562110719,FR
3562110720,3562110975,GB
3562110976,3562143743,ES
@@ -134579,6 +136715,7 @@
3563097344,3563102207,DE
3563102208,3563110399,CZ
3563110400,3563118591,RU
+3563118592,3563126783,PL
3563126784,3563134975,KG
3563134976,3563143167,IT
3563143168,3563151359,GB
@@ -134766,8 +136903,8 @@
3563848704,3563848979,NL
3563848980,3563848983,ES
3563848984,3563848987,NL
-3563848988,3563848999,ES
-3563849000,3563849151,NL
+3563848988,3563849007,ES
+3563849008,3563849151,NL
3563849152,3563849183,ES
3563849184,3563849191,NL
3563849192,3563849215,ES
@@ -134790,7 +136927,9 @@
3563851136,3563851839,NL
3563851840,3563851903,ES
3563851904,3563852031,NL
-3563852032,3563852095,ES
+3563852032,3563852071,ES
+3563852072,3563852079,NL
+3563852080,3563852095,ES
3563852096,3563852191,NL
3563852192,3563852207,GB
3563852208,3563852216,NL
@@ -134924,7 +137063,25 @@
3564314624,3564322815,GB
3564322816,3564331007,IT
3564331008,3564339199,ES
-3564339200,3564355583,GB
+3564339200,3564339991,GB
+3564339992,3564339999,NL
+3564340000,3564344031,GB
+3564344032,3564344047,NL
+3564344048,3564344207,GB
+3564344208,3564344215,NL
+3564344216,3564345143,GB
+3564345144,3564345151,NL
+3564345152,3564349615,GB
+3564349616,3564349631,NL
+3564349632,3564350399,GB
+3564350400,3564350431,NL
+3564350432,3564351439,GB
+3564351440,3564351455,NL
+3564351456,3564351551,GB
+3564351552,3564351615,NL
+3564351616,3564353207,GB
+3564353208,3564353215,NL
+3564353216,3564355583,GB
3564355584,3564363775,NL
3564363776,3564371967,UA
3564371968,3564380159,DE
@@ -135606,7 +137763,8 @@
3564961320,3564961791,AT
3564961792,3564969983,TR
3564969984,3564972607,DE
-3564972608,3564972631,AT
+3564972608,3564972623,AT
+3564972624,3564972631,DE
3564972632,3564972639,LI
3564972640,3564978175,DE
3564978176,3564986367,GB
@@ -135630,10 +137788,8 @@
3565038664,3565038687,GB
3565038688,3565038719,IE
3565038720,3565038727,GB
-3565038728,3565038759,IE
-3565038760,3565038783,GB
-3565038784,3565038847,IE
-3565038848,3565039615,GB
+3565038728,3565038775,IE
+3565038776,3565039615,GB
3565039616,3565042175,IE
3565042176,3565043711,GB
3565043712,3565047807,AT
@@ -135644,9 +137800,7 @@
3565068288,3565076479,CH
3565076480,3565084671,DE
3565084672,3565092863,IS
-3565092864,3565093391,GB
-3565093392,3565093399,NO
-3565093400,3565096759,GB
+3565092864,3565096759,GB
3565096760,3565096767,IE
3565096768,3565097151,GB
3565097152,3565097167,TZ
@@ -136205,7 +138359,8 @@
3567393280,3567393535,HU
3567393536,3567393791,GB
3567393792,3567394047,SI
-3567394048,3567394975,GB
+3567394048,3567394175,HR
+3567394176,3567394975,GB
3567394976,3567395007,DE
3567395008,3567395071,GB
3567395072,3567395327,DE
@@ -136451,9 +138606,7 @@
3568848792,3568848799,PL
3568848800,3568848871,DE
3568848872,3568848879,GB
-3568848880,3568876159,DE
-3568876160,3568876287,ES
-3568876288,3568915791,DE
+3568848880,3568915791,DE
3568915792,3568915807,LU
3568915808,3568916399,DE
3568916400,3568916407,IT
@@ -136893,39 +139046,115 @@
3571056640,3571122175,DE
3571122176,3571187711,GB
3571187712,3571253247,RU
-3571253248,3571268607,BE
+3571253248,3571264607,BE
+3571264608,3571264639,FR
+3571264640,3571268607,BE
3571268608,3571268639,LU
3571268640,3571286015,BE
3571286016,3571318783,DE
3571318784,3571319807,GB
3571319808,3571319935,DE
-3571319936,3571321599,GB
+3571319936,3571320855,GB
+3571320856,3571320863,DE
+3571320864,3571320943,GB
+3571320944,3571320959,DE
+3571320960,3571321599,GB
3571321600,3571321727,DE
-3571321728,3571326207,GB
+3571321728,3571321823,GB
+3571321824,3571321855,DE
+3571321856,3571321983,GB
+3571321984,3571321999,DE
+3571322000,3571323967,GB
+3571323968,3571324031,DE
+3571324032,3571326207,GB
3571326208,3571326215,DE
-3571326216,3571328511,GB
+3571326216,3571326231,GB
+3571326232,3571326247,DE
+3571326248,3571326983,GB
+3571326984,3571326991,DE
+3571326992,3571328511,GB
3571328512,3571328543,DE
-3571328544,3571331839,GB
+3571328544,3571328863,GB
+3571328864,3571328879,DE
+3571328880,3571329215,GB
+3571329216,3571329247,DE
+3571329248,3571331647,GB
+3571331648,3571331679,DE
+3571331680,3571331839,GB
3571331840,3571332351,DE
-3571332352,3571342079,GB
+3571332352,3571335807,GB
+3571335808,3571335935,DE
+3571335936,3571340415,GB
+3571340416,3571340447,DE
+3571340448,3571342079,GB
3571342080,3571342335,DE
-3571342336,3571347455,GB
+3571342336,3571343391,GB
+3571343392,3571343455,DE
+3571343456,3571347455,GB
3571347456,3571347711,BE
-3571347712,3571351551,GB
+3571347712,3571348387,GB
+3571348388,3571348391,DE
+3571348392,3571349087,GB
+3571349088,3571349119,DE
+3571349120,3571351551,GB
3571351552,3571351807,DE
-3571351808,3571355391,GB
+3571351808,3571354463,GB
+3571354464,3571354495,DE
+3571354496,3571355071,GB
+3571355072,3571355135,DE
+3571355136,3571355391,GB
3571355392,3571355903,DE
-3571355904,3571357183,GB
+3571355904,3571355999,GB
+3571356000,3571356031,DE
+3571356032,3571357183,GB
3571357184,3571357695,DE
-3571357696,3571361279,GB
+3571357696,3571357871,GB
+3571357872,3571357919,DE
+3571357920,3571358239,GB
+3571358240,3571358255,DE
+3571358256,3571358999,GB
+3571359000,3571359007,DE
+3571359008,3571359011,GB
+3571359012,3571359015,DE
+3571359016,3571359143,GB
+3571359144,3571359151,DE
+3571359152,3571359191,GB
+3571359192,3571359199,DE
+3571359200,3571359303,GB
+3571359304,3571359311,DE
+3571359312,3571359407,GB
+3571359408,3571359415,DE
+3571359416,3571359447,GB
+3571359448,3571359455,DE
+3571359456,3571361279,GB
3571361280,3571361407,DE
-3571361408,3571362815,GB
+3571361408,3571361471,GB
+3571361472,3571361535,DE
+3571361536,3571361999,GB
+3571362000,3571362015,DE
+3571362016,3571362815,GB
3571362816,3571362879,DE
3571362880,3571363583,GB
3571363584,3571364095,DE
-3571364096,3571368703,GB
+3571364096,3571368623,GB
+3571368624,3571368639,DE
+3571368640,3571368703,GB
3571368704,3571368959,DE
-3571368960,3571384319,GB
+3571368960,3571371327,GB
+3571371328,3571371359,DE
+3571371360,3571379343,GB
+3571379344,3571379351,DE
+3571379352,3571379359,GB
+3571379360,3571379367,DE
+3571379368,3571379375,GB
+3571379376,3571379391,DE
+3571379392,3571379535,GB
+3571379536,3571379559,DE
+3571379560,3571379887,GB
+3571379888,3571379895,DE
+3571379896,3571382623,GB
+3571382624,3571382655,DE
+3571382656,3571384319,GB
3571384320,3571385151,DE
3571385152,3571385183,GB
3571385184,3571385631,DE
@@ -137983,15 +140212,37 @@
3576096768,3576099071,EU
3576099072,3576100863,GB
3576100864,3576101375,EU
-3576101376,3576108287,GB
-3576108288,3576108295,FR
-3576108296,3576121343,GB
+3576101376,3576103375,GB
+3576103376,3576103423,FR
+3576103424,3576105791,GB
+3576105792,3576105855,FR
+3576105856,3576107711,GB
+3576107712,3576107743,FR
+3576107744,3576108287,GB
+3576108288,3576108303,FR
+3576108304,3576108831,GB
+3576108832,3576108847,FR
+3576108848,3576111423,GB
+3576111424,3576111551,FR
+3576111552,3576119471,GB
+3576119472,3576119487,CH
+3576119488,3576121343,GB
3576121344,3576121471,CH
3576121472,3576121855,GB
3576121856,3576122111,CH
-3576122112,3576134399,GB
+3576122112,3576122543,GB
+3576122544,3576122551,CH
+3576122552,3576122695,GB
+3576122696,3576122703,CH
+3576122704,3576132943,GB
+3576132944,3576132959,CH
+3576132960,3576133759,GB
+3576133760,3576133775,CH
+3576133776,3576134399,GB
3576134400,3576134655,CH
-3576134656,3576135679,GB
+3576134656,3576135295,GB
+3576135296,3576135359,CH
+3576135360,3576135679,GB
3576135680,3576168447,DE
3576168448,3576233983,GB
3576233984,3576236703,FR
@@ -138018,13 +140269,11 @@
3576237712,3576237743,GB
3576237744,3576237919,FR
3576237920,3576237935,GB
-3576237936,3576238143,FR
-3576238144,3576238159,GB
+3576237936,3576238151,FR
+3576238152,3576238159,GB
3576238160,3576238305,FR
3576238306,3576238335,GB
-3576238336,3576238447,FR
-3576238448,3576238463,GB
-3576238464,3576238511,FR
+3576238336,3576238511,FR
3576238512,3576238527,GB
3576238528,3576238559,FR
3576238560,3576238575,GB
@@ -138114,8 +140363,8 @@
3576251648,3576252415,FR
3576252416,3576252671,GB
3576252672,3576254543,FR
-3576254544,3576254559,GB
-3576254560,3576254607,FR
+3576254544,3576254551,GB
+3576254552,3576254607,FR
3576254608,3576254615,GB
3576254616,3576254623,FR
3576254624,3576254647,GB
@@ -138331,8 +140580,8 @@
3576264640,3576264687,GB
3576264688,3576265319,FR
3576265320,3576265327,GB
-3576265328,3576265335,FR
-3576265336,3576265367,GB
+3576265328,3576265359,FR
+3576265360,3576265367,GB
3576265368,3576265375,FR
3576265376,3576265383,GB
3576265384,3576265399,FR
@@ -138355,8 +140604,8 @@
3576265920,3576265935,GB
3576265936,3576266255,FR
3576266256,3576266495,GB
-3576266496,3576266663,FR
-3576266664,3576266751,GB
+3576266496,3576266671,FR
+3576266672,3576266751,GB
3576266752,3576299519,FR
3576299520,3576365055,AE
3576365056,3576430591,TR
@@ -138392,7 +140641,9 @@
3576823808,3576889343,SE
3576889344,3576954879,NL
3576954880,3576987647,NO
-3576987648,3577001983,GB
+3576987648,3577000959,GB
+3577000960,3577001343,NL
+3577001344,3577001983,GB
3577001984,3577003647,NL
3577003648,3577003711,GB
3577003712,3577003767,NL
@@ -138727,7 +140978,9 @@
3579197312,3579197439,US
3579197440,3579197887,GB
3579197888,3579197903,IT
-3579197904,3579205631,GB
+3579197904,3579204127,GB
+3579204128,3579204143,BE
+3579204144,3579205631,GB
3579205632,3579205887,IE
3579205888,3579210079,GB
3579210080,3579210087,BE
@@ -138970,7 +141223,11 @@
3580209152,3580213247,SE
3580213248,3580214271,CH
3580214272,3580214783,LV
-3580214784,3580223487,SE
+3580214784,3580215295,SE
+3580215296,3580216319,EE
+3580216320,3580216831,SE
+3580216832,3580217087,EE
+3580217088,3580223487,SE
3580223488,3580231679,DE
3580231680,3580231935,LT
3580231936,3580232447,LV
@@ -139145,7 +141402,9 @@
3582076928,3582077111,ES
3582077112,3582077439,GB
3582077440,3582077471,DE
-3582077472,3582078631,GB
+3582077472,3582077503,GB
+3582077504,3582077695,DE
+3582077696,3582078631,GB
3582078632,3582078639,DE
3582078640,3582081023,GB
3582081024,3582081535,ES
@@ -139612,7 +141871,8 @@
3582885888,3582894079,TR
3582894080,3582902271,CH
3582902272,3582910463,RU
-3582910464,3582918655,SI
+3582910464,3582917631,SI
+3582917632,3582918655,LU
3582918656,3582926847,GB
3582926848,3582935039,ES
3582935040,3582943231,SI
@@ -139863,8 +142123,8 @@
3583707536,3583707663,UA
3583707664,3583707671,NA
3583707672,3583707751,UA
-3583707752,3583707767,NA
-3583707768,3583707775,UA
+3583707752,3583707759,NA
+3583707760,3583707775,UA
3583707776,3583707791,NA
3583707792,3583707807,UA
3583707808,3583707815,NA
@@ -139898,8 +142158,8 @@
3583709736,3583709743,NA
3583709744,3583709759,UA
3583709760,3583709767,NA
-3583709768,3583709839,UA
-3583709840,3583709863,NA
+3583709768,3583709847,UA
+3583709848,3583709863,NA
3583709864,3583709871,RU
3583709872,3583709879,NA
3583709880,3583709887,UA
@@ -139944,9 +142204,7 @@
3583711360,3583711367,NA
3583711368,3583711375,UA
3583711376,3583711383,NA
-3583711384,3583711695,UA
-3583711696,3583711703,NA
-3583711704,3583711711,UA
+3583711384,3583711711,UA
3583711712,3583711719,NA
3583711720,3583711783,UA
3583711784,3583711799,NA
@@ -139973,7 +142231,9 @@
3583712936,3583712943,NA
3583712944,3583713007,UA
3583713008,3583713015,RU
-3583713016,3583713279,UA
+3583713016,3583713079,UA
+3583713080,3583713087,IN
+3583713088,3583713279,UA
3583713280,3583721471,CZ
3583721472,3583729663,DE
3583729664,3583737855,TR
@@ -140008,8 +142268,7 @@
3583744448,3583744511,EU
3583744512,3583744767,GB
3583744768,3583744831,DE
-3583744832,3583744839,GB
-3583744840,3583744927,EU
+3583744832,3583744927,EU
3583744928,3583744959,DE
3583744960,3583744991,GB
3583744992,3583744999,EU
@@ -140023,7 +142282,9 @@
3583745724,3583745799,EU
3583745800,3583745807,NL
3583745808,3583745823,GB
-3583745824,3583746047,EU
+3583745824,3583745919,EU
+3583745920,3583745951,GB
+3583745952,3583746047,EU
3583746048,3583754239,PL
3583754240,3583762431,RU
3583762432,3583770623,CZ
@@ -140274,37 +142535,7 @@
3584929728,3584931375,CH
3584931376,3584931391,ES
3584931392,3584933887,CH
-3584933888,3584933919,NO
-3584933920,3584933927,PL
-3584933928,3584934079,NO
-3584934080,3584934087,PL
-3584934088,3584934167,NO
-3584934168,3584934171,PL
-3584934172,3584934219,NO
-3584934220,3584934223,PL
-3584934224,3584934431,NO
-3584934432,3584934439,PL
-3584934440,3584935487,NO
-3584935488,3584935491,PL
-3584935492,3584935735,NO
-3584935736,3584935739,PL
-3584935740,3584935775,NO
-3584935776,3584935779,PL
-3584935780,3584936227,NO
-3584936228,3584936231,PL
-3584936232,3584936327,NO
-3584936328,3584936331,PL
-3584936332,3584938607,NO
-3584938608,3584938611,PL
-3584938612,3584938711,NO
-3584938712,3584938715,PL
-3584938716,3584938719,NO
-3584938720,3584938723,PL
-3584938724,3584941111,NO
-3584941112,3584941115,PL
-3584941116,3584941131,NO
-3584941132,3584941135,PL
-3584941136,3584942079,NO
+3584933888,3584942079,NO
3584942080,3584950271,DK
3584950272,3584958463,UA
3584958464,3584966655,DE
@@ -140369,9 +142600,7 @@
3585318912,3585327103,DZ
3585327104,3585331327,NL
3585331328,3585331343,FI
-3585331344,3585332223,NL
-3585332224,3585332351,A1
-3585332352,3585335295,NL
+3585331344,3585335295,NL
3585335296,3585343487,UA
3585343488,3585351679,EE
3585351680,3585359871,CZ
@@ -140400,7 +142629,8 @@
3585542336,3585542351,TR
3585542352,3585544903,DE
3585544904,3585544911,CH
-3585544912,3585548287,DE
+3585544912,3585544927,TR
+3585544928,3585548287,DE
3585548288,3585556479,RU
3585556480,3585564671,DE
3585564672,3585572863,RU
@@ -140928,7 +143158,7 @@
3587179472,3587186687,AT
3587186688,3587186815,DE
3587186816,3587187199,A2
-3587187200,3587187455,DE
+3587187200,3587187455,GB
3587187456,3587188479,A2
3587188480,3587188735,DE
3587188736,3587194495,A2
@@ -141026,7 +143256,9 @@
3587234144,3587234159,GB
3587234160,3587234207,NL
3587234208,3587234815,GB
-3587234816,3587236447,NL
+3587234816,3587236367,NL
+3587236368,3587236383,GB
+3587236384,3587236447,NL
3587236448,3587236479,GB
3587236480,3587236511,NL
3587236512,3587236543,GB
@@ -141056,17 +143288,13 @@
3587239304,3587239311,GB
3587239312,3587239911,NL
3587239912,3587239919,GB
-3587239920,3587239975,NL
-3587239976,3587239983,GB
-3587239984,3587240063,NL
-3587240064,3587240071,GB
-3587240072,3587240087,NL
-3587240088,3587240095,GB
-3587240096,3587240103,NL
+3587239920,3587240063,NL
+3587240064,3587240071,BE
+3587240072,3587240103,NL
3587240104,3587240107,GB
3587240108,3587240271,NL
-3587240272,3587240287,GB
-3587240288,3587240359,NL
+3587240272,3587240279,GB
+3587240280,3587240359,NL
3587240360,3587240367,GB
3587240368,3587240439,NL
3587240440,3587240447,GB
@@ -141239,7 +143467,9 @@
3587440640,3587457023,SE
3587457024,3587459263,GB
3587459264,3587459295,DE
-3587459296,3587473407,GB
+3587459296,3587465359,GB
+3587465360,3587465367,US
+3587465368,3587473407,GB
3587473408,3587489791,IT
3587489792,3587506175,EG
3587506176,3587538943,IT
@@ -141528,7 +143758,9 @@
3589545984,3589554175,DE
3589554176,3589570559,PS
3589570560,3589570655,NL
-3589570656,3589578751,GB
+3589570656,3589571071,GB
+3589571072,3589571135,NL
+3589571136,3589578751,GB
3589578752,3589579391,NL
3589579392,3589579775,GB
3589579776,3589580799,NL
@@ -141808,7 +144040,9 @@
3589980160,3589996543,CZ
3589996544,3589997055,GB
3589997056,3589997311,NL
-3589997312,3590012927,GB
+3589997312,3589997559,GB
+3589997560,3589997567,NL
+3589997568,3590012927,GB
3590012928,3590029311,BE
3590029312,3590033759,FR
3590033760,3590033775,AU
@@ -141836,7 +144070,9 @@
3590156432,3590156447,SI
3590156448,3590156543,HR
3590156544,3590156575,SI
-3590156576,3590156671,HR
+3590156576,3590156599,HR
+3590156600,3590156607,SI
+3590156608,3590156671,HR
3590156672,3590156687,SI
3590156688,3590156719,HR
3590156720,3590156727,SI
@@ -141853,8 +144089,8 @@
3590157568,3590157631,SI
3590157632,3590157679,RS
3590157680,3590157687,SI
-3590157688,3590157703,RS
-3590157704,3590157743,SI
+3590157688,3590157711,RS
+3590157712,3590157743,SI
3590157744,3590157751,RS
3590157752,3590157759,SI
3590157760,3590157767,RS
@@ -141868,12 +144104,12 @@
3590158080,3590158343,RS
3590158344,3590158359,SI
3590158360,3590158367,RS
-3590158368,3590158431,SI
+3590158368,3590158407,SI
+3590158408,3590158415,RS
+3590158416,3590158431,SI
3590158432,3590158439,RS
3590158440,3590158455,SI
-3590158456,3590158463,RS
-3590158464,3590158471,SI
-3590158472,3590158479,RS
+3590158456,3590158479,RS
3590158480,3590158527,SI
3590158528,3590158535,RS
3590158536,3590158591,SI
@@ -142002,8 +144238,8 @@
3590308288,3590308303,A2
3590308304,3590308311,SO
3590308312,3590308343,IQ
-3590308344,3590308351,A2
-3590308352,3590308367,IQ
+3590308344,3590308359,A2
+3590308360,3590308367,IQ
3590308368,3590308375,A2
3590308376,3590308391,IQ
3590308392,3590308399,A2
@@ -142028,7 +144264,7 @@
3590308768,3590308775,RW
3590308776,3590308783,ZA
3590308784,3590308799,ZW
-3590308800,3590308807,A2
+3590308800,3590308807,GB
3590308808,3590308815,ZM
3590308816,3590308823,KE
3590308824,3590308855,A2
@@ -142104,7 +144340,9 @@
3590311040,3590311055,A2
3590311056,3590311063,IQ
3590311064,3590311079,A2
-3590311080,3590311111,IQ
+3590311080,3590311087,IQ
+3590311088,3590311095,A2
+3590311096,3590311111,IQ
3590311112,3590311119,A2
3590311120,3590311135,IQ
3590311136,3590311143,A2
@@ -142116,8 +144354,7 @@
3590311208,3590311215,CD
3590311216,3590311223,AO
3590311224,3590311231,CD
-3590311232,3590311239,AO
-3590311240,3590311255,A2
+3590311232,3590311255,A2
3590311256,3590311263,ZW
3590311264,3590311271,A2
3590311272,3590311279,SD
@@ -142129,9 +144366,9 @@
3590311320,3590311327,CI
3590311328,3590311335,CD
3590311336,3590311343,SD
-3590311344,3590311351,A2
+3590311344,3590311351,LY
3590311352,3590311359,CD
-3590311360,3590311367,A2
+3590311360,3590311367,LY
3590311368,3590311383,CD
3590311384,3590311391,NG
3590311392,3590311423,A2
@@ -142140,9 +144377,7 @@
3590311936,3590312703,MW
3590312704,3590312799,A2
3590312800,3590312807,KE
-3590312808,3590312815,A2
-3590312816,3590312823,US
-3590312824,3590312895,A2
+3590312808,3590312895,A2
3590312896,3590312903,ZA
3590312904,3590312911,AO
3590312912,3590312919,NG
@@ -142156,8 +144391,7 @@
3590314656,3590314671,A2
3590314672,3590314679,UG
3590314680,3590314687,A2
-3590314688,3590314703,NG
-3590314704,3590314719,A2
+3590314688,3590314719,GB
3590314720,3590314727,TG
3590314728,3590314735,UG
3590314736,3590314743,NG
@@ -142263,9 +144497,7 @@
3590323200,3590323711,MW
3590323712,3590323903,A2
3590323904,3590323911,CD
-3590323912,3590323967,A2
-3590323968,3590323975,UG
-3590323976,3590323983,A2
+3590323912,3590323983,A2
3590323984,3590323991,NG
3590323992,3590323999,A2
3590324000,3590324007,LR
@@ -142331,7 +144563,9 @@
3624303760,3624304639,CA
3624304640,3624321023,US
3624321024,3624325119,CA
-3624325120,3624357887,US
+3624325120,3624330511,US
+3624330512,3624330519,CA
+3624330520,3624357887,US
3624357888,3624358143,KN
3624358144,3624359679,US
3624359680,3624360703,AN
@@ -142504,7 +144738,9 @@
3624549112,3624549383,US
3624549384,3624549471,A2
3624549472,3624549479,US
-3624549480,3624550143,A2
+3624549480,3624549583,A2
+3624549584,3624549615,US
+3624549616,3624550143,A2
3624550144,3624587263,US
3624587264,3624591359,JM
3624591360,3624730623,US
@@ -142677,7 +144913,9 @@
3624911648,3624911651,RU
3624911652,3624911999,US
3624912000,3624912127,CA
-3624912128,3624912727,US
+3624912128,3624912679,US
+3624912680,3624912687,IN
+3624912688,3624912727,US
3624912728,3624912735,TT
3624912736,3624912959,US
3624912960,3624913087,IN
@@ -142991,7 +145229,7 @@
3626228464,3626228479,AE
3626228480,3626270719,US
3626270720,3626287103,CA
-3626287104,3626328063,US
+3626287104,3626332159,US
3626332160,3626336255,CA
3626336256,3626381317,US
3626381318,3626381321,AU
@@ -143821,8 +146059,7 @@
3628771456,3628771647,GB
3628771648,3628771839,US
3628771840,3628772095,NO
-3628772096,3628772415,US
-3628772416,3628772431,CA
+3628772096,3628772431,US
3628772432,3628772447,GB
3628772448,3628834815,US
3628834816,3628843007,CA
@@ -144815,7 +147052,7 @@
3632486688,3632486703,HK
3632486704,3632486711,US
3632486712,3632486719,CA
-3632486720,3632486751,TH
+3632486720,3632486751,US
3632486752,3632486759,NL
3632486760,3632486783,US
3632486784,3632486815,DE
@@ -144890,9 +147127,7 @@
3632491536,3632491543,GB
3632491544,3632491583,US
3632491584,3632491591,TH
-3632491592,3632491599,US
-3632491600,3632491607,TH
-3632491608,3632491639,US
+3632491592,3632491639,US
3632491640,3632491647,CA
3632491648,3632491807,US
3632491808,3632491823,TW
@@ -144900,7 +147135,7 @@
3632491968,3632491999,SR
3632492000,3632492007,NL
3632492008,3632492015,IO
-3632492016,3632492023,IN
+3632492016,3632492023,US
3632492024,3632492031,GB
3632492032,3632492087,US
3632492088,3632492095,GB
@@ -144918,9 +147153,7 @@
3632492456,3632492463,TH
3632492464,3632492543,US
3632492544,3632492551,FR
-3632492552,3632492559,US
-3632492560,3632492575,GB
-3632492576,3632492775,US
+3632492552,3632492775,US
3632492776,3632492791,GB
3632492792,3632492839,US
3632492840,3632492847,CA
@@ -145232,7 +147465,9 @@
3633816520,3633816527,ZA
3633816528,3633816535,CA
3633816536,3633816543,US
-3633816544,3633818703,CA
+3633816544,3633816559,ZA
+3633816560,3633816567,IN
+3633816568,3633818703,CA
3633818704,3633818711,US
3633818712,3633818751,CA
3633818752,3633818767,US
@@ -145245,15 +147480,19 @@
3633819424,3633819647,CA
3633819648,3633821279,US
3633821280,3633821311,BB
-3633821312,3633821439,US
-3633821440,3633821695,SC
-3633821696,3633822175,US
+3633821312,3633822175,US
3633822176,3633822191,GB
3633822192,3633822303,US
3633822304,3633822327,CA
3633822328,3633827839,US
3633827840,3633828095,GB
-3633828096,3633874431,US
+3633828096,3633828970,US
+3633828971,3633828977,IN
+3633828978,3633831306,US
+3633831307,3633831338,IN
+3633831339,3633831383,US
+3633831384,3633831395,AU
+3633831396,3633874431,US
3633874432,3633874687,GB
3633874688,3633881087,US
3633881088,3633885183,AN
@@ -145365,7 +147604,33 @@
3635533000,3635533007,NO
3635533008,3635533535,US
3635533536,3635533551,IN
-3635533552,3635654655,US
+3635533552,3635650559,US
+3635650560,3635650815,JP
+3635650816,3635651071,US
+3635651072,3635651327,JP
+3635651328,3635651583,US
+3635651584,3635651839,JP
+3635651840,3635652607,US
+3635652608,3635652639,HK
+3635652640,3635652815,US
+3635652816,3635652831,HK
+3635652832,3635653071,US
+3635653072,3635653119,HK
+3635653120,3635653151,US
+3635653152,3635653183,HK
+3635653184,3635653631,US
+3635653632,3635653695,JP
+3635653696,3635653727,US
+3635653728,3635653743,JP
+3635653744,3635653775,US
+3635653776,3635653791,JP
+3635653792,3635653887,US
+3635653888,3635653983,JP
+3635653984,3635654015,US
+3635654016,3635654143,JP
+3635654144,3635654303,US
+3635654304,3635654335,JP
+3635654336,3635654655,US
3635654656,3635654911,JP
3635654912,3635655167,US
3635655168,3635655935,JP
@@ -145373,7 +147638,8 @@
3635656192,3635656223,JP
3635656224,3635656319,US
3635656320,3635656447,JP
-3635656448,3635659263,US
+3635656448,3635656703,CA
+3635656704,3635659263,US
3635659264,3635660031,ID
3635660032,3635660287,CN
3635660288,3635660799,US
@@ -145412,7 +147678,8 @@
3636150840,3636150911,US
3636150912,3636150935,CA
3636150936,3636150943,US
-3636150944,3636151007,CA
+3636150944,3636150991,CA
+3636150992,3636151007,US
3636151008,3636151023,BS
3636151024,3636151031,CA
3636151032,3636151039,US
@@ -145822,7 +148089,9 @@
3638249752,3638249791,GB
3638249792,3638249983,US
3638249984,3638249991,GB
-3638249992,3638250535,US
+3638249992,3638249999,US
+3638250000,3638250031,GB
+3638250032,3638250535,US
3638250536,3638250543,GB
3638250544,3638250559,US
3638250560,3638250623,GB
@@ -145853,7 +148122,9 @@
3638399616,3638399743,US
3638399744,3638399999,CH
3638400000,3638400063,CA
-3638400064,3638509295,US
+3638400064,3638400271,US
+3638400272,3638400279,CA
+3638400280,3638509295,US
3638509296,3638509311,GB
3638509312,3638509567,US
3638509568,3638526911,CA
@@ -146087,7 +148358,9 @@
3639886592,3639886599,SG
3639886600,3639888962,US
3639888963,3639888963,ID
-3639888964,3639892359,US
+3639888964,3639888986,US
+3639888987,3639888987,ID
+3639888988,3639892359,US
3639892360,3639892367,ID
3639892368,3639892375,US
3639892376,3639892383,ID
@@ -146246,9 +148519,7 @@
3641078560,3641078567,BE
3641078568,3641085687,DE
3641085688,3641085695,CZ
-3641085696,3641098191,DE
-3641098192,3641098207,ES
-3641098208,3641103719,DE
+3641085696,3641103719,DE
3641103720,3641103727,HU
3641103728,3641106951,DE
3641106952,3641106959,CH
@@ -146455,6 +148726,7 @@
3641683968,3641688063,KZ
3641688064,3641692159,RU
3641692160,3641696255,IT
+3641696256,3641700351,BE
3641700352,3641704447,SE
3641704448,3641708543,FR
3641708544,3641712639,RU
@@ -146759,6 +149031,9 @@
3642415636,3642415651,GB
3642415652,3642415655,MT
3642415656,3642417151,GB
+3642417152,3642419199,DE
+3642419200,3642419967,US
+3642419968,3642421247,GB
3642421248,3642423091,A2
3642423092,3642423099,NG
3642423100,3642424151,A2
@@ -146772,7 +149047,7 @@
3642429440,3642433535,GB
3642433536,3642435583,CY
3642435584,3642436607,RU
-3642436608,3642437119,GR
+3642436608,3642437119,CY
3642437120,3642437631,GB
3642437632,3642439423,CY
3642439424,3642439459,RU
@@ -146815,7 +149090,9 @@
3642539976,3642540031,IS
3642540032,3642540063,SE
3642540064,3642540079,NO
-3642540080,3642544127,SE
+3642540080,3642540135,SE
+3642540136,3642540143,NO
+3642540144,3642544127,SE
3642544128,3642552319,RU
3642552320,3642552639,UA
3642552640,3642552655,EE
@@ -146825,7 +149102,9 @@
3642552672,3642552687,SE
3642552688,3642552831,UA
3642552832,3642552847,EE
-3642552848,3642553095,UA
+3642552848,3642553087,UA
+3642553088,3642553091,LV
+3642553092,3642553095,UA
3642553096,3642553099,LV
3642553100,3642553103,UA
3642553104,3642553161,LV
@@ -146866,20 +149145,20 @@
3642553960,3642554111,UA
3642554112,3642554119,RU
3642554120,3642554127,UA
-3642554128,3642554151,RU
-3642554152,3642554187,UA
+3642554128,3642554159,RU
+3642554160,3642554187,UA
3642554188,3642554207,RU
3642554208,3642554219,UA
3642554220,3642554223,RU
3642554224,3642554367,UA
-3642554368,3642554571,LT
-3642554572,3642554575,UA
+3642554368,3642554573,LT
+3642554574,3642554575,UA
3642554576,3642554623,LT
3642554624,3642554631,UA
3642554632,3642554671,LV
3642554672,3642554675,UA
-3642554676,3642554687,LV
-3642554688,3642554751,UA
+3642554676,3642554703,LV
+3642554704,3642554751,UA
3642554752,3642554795,LV
3642554796,3642554807,UA
3642554808,3642554831,LV
@@ -146923,7 +149202,9 @@
3642555224,3642555227,LV
3642555228,3642555289,LT
3642555290,3642555295,UA
-3642555296,3642555391,LT
+3642555296,3642555359,LT
+3642555360,3642555375,UA
+3642555376,3642555391,LT
3642555392,3642555431,PL
3642555432,3642555437,UA
3642555438,3642555439,PL
@@ -147188,9 +149469,7 @@
3645337088,3645337599,DE
3645337600,3645337631,FR
3645337632,3645337663,BE
-3645337664,3645338399,FR
-3645338400,3645338431,BE
-3645338432,3645339295,FR
+3645337664,3645339295,FR
3645339296,3645339359,BE
3645339360,3645339391,FR
3645339392,3645339647,NL
@@ -147229,7 +149508,8 @@
3645435904,3645439999,GB
3645440000,3645444095,SE
3645444096,3645448191,SK
-3645448192,3645452287,DE
+3645448192,3645455487,DE
+3645455488,3645456383,RU
3645456384,3645460479,GB
3645460480,3645464575,UA
3645464576,3645468671,SE
@@ -148369,11 +150649,9 @@
3647973736,3647973743,DE
3647973744,3647973783,IT
3647973784,3647973791,DE
-3647973792,3647973815,IT
-3647973816,3647973823,DE
-3647973824,3647973927,IT
-3647973928,3647973935,DE
-3647973936,3647973967,IT
+3647973792,3647973951,IT
+3647973952,3647973959,DE
+3647973960,3647973967,IT
3647973968,3647973975,DE
3647973976,3647974047,IT
3647974048,3647974055,DE
@@ -148407,9 +150685,7 @@
3647978776,3647978783,DE
3647978784,3647978895,NL
3647978896,3647978911,DE
-3647978912,3647978967,NL
-3647978968,3647978975,DE
-3647978976,3647979007,NL
+3647978912,3647979007,NL
3647979008,3647979136,IT
3647979137,3647979519,DE
3647979520,3647980215,FR
@@ -148443,18 +150719,22 @@
3647987072,3647987087,DE
3647987088,3647987119,ES
3647987120,3647987127,DE
-3647987128,3647987175,ES
-3647987176,3647987455,DE
+3647987128,3647987183,ES
+3647987184,3647987191,DE
+3647987192,3647987199,ES
+3647987200,3647987455,DE
3647987456,3647987527,ES
3647987528,3647987535,GB
3647987536,3647987543,DE
3647987544,3647987711,ES
3647987712,3647988735,IT
3647988736,3647988991,DE
-3647988992,3647989375,BE
-3647989376,3647989503,DE
+3647988992,3647989495,BE
+3647989496,3647989503,DE
3647989504,3647989759,BE
-3647989760,3647995903,DE
+3647989760,3647990271,DE
+3647990272,3647990527,ES
+3647990528,3647995903,DE
3647995904,3648004223,RU
3648004224,3648004607,GB
3648004608,3648006271,RU
@@ -148524,7 +150804,8 @@
3648082240,3648082311,NE
3648082312,3648082431,BE
3648082432,3648082479,ZM
-3648082480,3648085759,BE
+3648082480,3648084991,BE
+3648084992,3648085759,GB
3648085760,3648086015,LR
3648086016,3648090111,AT
3648090112,3648094207,RU
@@ -148617,7 +150898,12 @@
3648225280,3648231263,DE
3648231264,3648231295,NL
3648231296,3648233471,DE
-3648233472,3648237567,FR
+3648233472,3648236667,FR
+3648236668,3648236668,GB
+3648236669,3648236669,NL
+3648236670,3648236670,DE
+3648236671,3648236671,SE
+3648236672,3648237567,FR
3648237568,3648241663,RU
3648241664,3648245759,NL
3648245760,3648249855,RO
@@ -148788,6 +151074,7 @@
3650093056,3650097151,JO
3650097152,3650101247,SK
3650101248,3650105343,DE
+3650105344,3650109439,HU
3650109440,3650113535,NO
3650113536,3650117631,GB
3650117632,3650121727,RU
@@ -149094,7 +151381,9 @@
3651204608,3651205119,ES
3651205120,3651205375,GB
3651205376,3651205631,ES
-3651205632,3651207167,DE
+3651205632,3651206143,DE
+3651206144,3651206399,PL
+3651206400,3651207167,DE
3651207168,3651207199,GB
3651207200,3651207223,EU
3651207224,3651207295,GB
@@ -149620,7 +151909,7 @@
3653410248,3653410255,ZM
3653410256,3653410263,A2
3653410264,3653410271,NG
-3653410272,3653410279,SD
+3653410272,3653410279,A2
3653410280,3653410287,IQ
3653410288,3653410295,A2
3653410296,3653410303,MW
@@ -149721,6 +152010,8 @@
3653586944,3653591039,DE
3653591040,3653595135,LU
3653595136,3653599231,RU
+3653599232,3653601279,CH
+3653601280,3653603327,BA
3653603328,3653607423,CZ
3653607424,3653611519,PL
3653611520,3653615615,HU
@@ -149739,7 +152030,9 @@
3653664896,3653664911,FR
3653664912,3653665023,NL
3653665024,3653665071,DE
-3653665072,3653666815,NL
+3653665072,3653665151,NL
+3653665152,3653665279,DE
+3653665280,3653666815,NL
3653666816,3653667327,DE
3653667328,3653668863,NL
3653668864,3653672959,SE
@@ -150242,3 +152535,4 @@
3758094336,3758095359,AU
3758095360,3758095871,CN
3758095872,3758096127,SG
+3758096128,3758096383,AU
diff --git a/src/or/Makefile.am b/src/or/Makefile.am
index a9ac3cdee..67adf504d 100644
--- a/src/or/Makefile.am
+++ b/src/or/Makefile.am
@@ -7,7 +7,7 @@ else
tor_platform_source=
endif
-EXTRA_DIST=ntmain.c or_sha1.i
+EXTRA_DIST=ntmain.c or_sha1.i Makefile.nmake
if USE_EXTERNAL_EVDNS
evdns_source=
@@ -15,16 +15,46 @@ else
evdns_source=eventdns.c
endif
-libtor_a_SOURCES = buffers.c circuitbuild.c circuitlist.c \
- circuituse.c command.c config.c \
- connection.c connection_edge.c connection_or.c control.c \
- cpuworker.c directory.c dirserv.c dirvote.c \
- dns.c dnsserv.c geoip.c hibernate.c main.c $(tor_platform_source) \
- microdesc.c \
- networkstatus.c onion.c policies.c \
- reasons.c relay.c rendcommon.c rendclient.c rendmid.c \
- rendservice.c rephist.c router.c routerlist.c routerparse.c \
- $(evdns_source) config_codedigest.c
+libtor_a_SOURCES = \
+ buffers.c \
+ circuitbuild.c \
+ circuitlist.c \
+ circuituse.c \
+ command.c \
+ config.c \
+ connection.c \
+ connection_edge.c \
+ connection_or.c \
+ control.c \
+ cpuworker.c \
+ directory.c \
+ dirserv.c \
+ dirvote.c \
+ dns.c \
+ dnsserv.c \
+ geoip.c \
+ hibernate.c \
+ main.c \
+ microdesc.c \
+ networkstatus.c \
+ nodelist.c \
+ onion.c \
+ transports.c \
+ policies.c \
+ reasons.c \
+ relay.c \
+ rendclient.c \
+ rendcommon.c \
+ rendmid.c \
+ rendservice.c \
+ rephist.c \
+ router.c \
+ routerlist.c \
+ routerparse.c \
+ status.c \
+ $(evdns_source) \
+ $(tor_platform_source) \
+ config_codedigest.c
#libtor_a_LIBADD = ../common/libor.a ../common/libor-crypto.a \
# ../common/libor-event.a
@@ -40,18 +70,55 @@ AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
# This seems to matter nowhere but on windows, but I assure you that it
# matters a lot there, and is quite hard to debug if you forget to do it.
+
tor_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@
tor_LDADD = ./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 = buffers.h circuitbuild.h circuitlist.h circuituse.h \
- command.h config.h connection_edge.h connection.h connection_or.h \
- control.h cpuworker.h directory.h dirserv.h dirvote.h dns.h \
- dnsserv.h geoip.h hibernate.h main.h microdesc.h networkstatus.h \
- ntmain.h onion.h policies.h reasons.h relay.h rendclient.h \
- rendcommon.h rendmid.h rendservice.h rephist.h router.h routerlist.h \
- routerparse.h or.h eventdns.h eventdns_tor.h micro-revision.i
+ @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
+ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+
+noinst_HEADERS = \
+ buffers.h \
+ circuitbuild.h \
+ circuitlist.h \
+ circuituse.h \
+ command.h \
+ config.h \
+ connection.h \
+ connection_edge.h \
+ connection_or.h \
+ control.h \
+ cpuworker.h \
+ directory.h \
+ dirserv.h \
+ dirvote.h \
+ dns.h \
+ dnsserv.h \
+ eventdns.h \
+ eventdns_tor.h \
+ geoip.h \
+ hibernate.h \
+ main.h \
+ microdesc.h \
+ networkstatus.h \
+ nodelist.h \
+ ntmain.h \
+ onion.h \
+ or.h \
+ transports.h \
+ policies.h \
+ reasons.h \
+ relay.h \
+ rendclient.h \
+ rendcommon.h \
+ rendmid.h \
+ rendservice.h \
+ rephist.h \
+ router.h \
+ routerlist.h \
+ routerparse.h \
+ status.h \
+ micro-revision.i
config_codedigest.o: or_sha1.i
@@ -72,11 +139,13 @@ micro-revision.i: FORCE
mv micro-revision.tmp micro-revision.i; \
fi; true
-or_sha1.i: $(tor_SOURCES)
+or_sha1.i: $(tor_SOURCES) $(libtor_a_SOURCES)
if test "@SHA1SUM@" != none; then \
- @SHA1SUM@ $(tor_SOURCES) | @SED@ -n 's/^\(.*\)$$/"\1\\n"/p' > or_sha1.i; \
+ @SHA1SUM@ $(tor_SOURCES) $(libtor_a_SOURCES) | \
+ @SED@ -n 's/^\(.*\)$$/"\1\\n"/p' > or_sha1.i; \
elif test "@OPENSSL@" != none; then \
- @OPENSSL@ sha1 $(tor_SOURCES) | @SED@ -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > or_sha1.i; \
+ @OPENSSL@ sha1 $(tor_SOURCES) $(libtor_a_SOURCES) | \
+ @SED@ -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > or_sha1.i; \
else \
rm or_sha1.i; \
touch or_sha1.i; \
diff --git a/src/or/Makefile.nmake b/src/or/Makefile.nmake
new file mode 100644
index 000000000..919edbbf2
--- /dev/null
+++ b/src/or/Makefile.nmake
@@ -0,0 +1,28 @@
+all: tor.exe
+
+CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include /I ..\common
+
+LIBS = ..\..\..\build-alpha\lib\libevent.a \
+ ..\..\..\build-alpha\lib\libcrypto.a \
+ ..\..\..\build-alpha\lib\libssl.a \
+ ..\..\..\build-alpha\lib\libz.a \
+ ws2_32.lib advapi32.lib shell32.lib
+
+LIBTOR_OBJECTS = buffers.obj circuitbuild.obj circuitlist.obj circuituse.obj \
+ command.obj config.obj connection.obj connection_edge.obj \
+ connection_or.obj control.obj cpuworker.obj directory.obj \
+ dirserv.obj dirvote.obj dns.obj dnsserv.obj geoip.obj \
+ hibernate.obj main.obj microdesc.obj networkstatus.obj \
+ nodelist.obj onion.obj policies.obj reasons.obj relay.obj \
+ rendclient.obj rendcommon.obj rendmid.obj rendservice.obj \
+ rephist.obj router.obj routerlist.obj routerparse.obj status.obj \
+ config_codedigest.obj ntmain.obj
+
+libtor.lib: $(LIBTOR_OBJECTS)
+ lib $(LIBTOR_OBJECTS) /out:libtor.lib
+
+tor.exe: libtor.lib tor_main.obj
+ $(CC) $(CFLAGS) $(LIBS) libtor.lib ..\common\*.lib tor_main.obj
+
+clean:
+ del $(LIBTOR_OBJECTS) *.lib tor.exe
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 05163637f..1025cedad 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -23,9 +23,6 @@
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#ifdef HAVE_SYS_UIO_H
-#include <sys/uio.h>
-#endif
//#define PARANOIA
@@ -56,6 +53,13 @@
* forever.
*/
+static int parse_socks(const char *data, size_t datalen, socks_request_t *req,
+ int log_sockstype, int safe_socks, ssize_t *drain_out,
+ size_t *want_length_out);
+static int parse_socks_client(const uint8_t *data, size_t datalen,
+ int state, char **reason,
+ ssize_t *drain_out);
+
/* Chunk manipulation functions */
/** A single chunk on a buffer or in a freelist. */
@@ -64,8 +68,8 @@ typedef struct chunk_t {
size_t datalen; /**< The number of bytes stored in this chunk */
size_t memlen; /**< The number of usable bytes of storage in <b>mem</b>. */
char *data; /**< A pointer to the first byte of data stored in <b>mem</b>. */
- char mem[1]; /**< The actual memory used for storage in this chunk. May be
- * more than one byte long. */
+ char mem[FLEXIBLE_ARRAY_MEMBER]; /**< The actual memory used for storage in
+ * this chunk. */
} chunk_t;
#define CHUNK_HEADER_LEN STRUCT_OFFSET(chunk_t, mem[0])
@@ -547,11 +551,45 @@ buf_free(buf_t *buf)
{
if (!buf)
return;
+
buf_clear(buf);
buf->magic = 0xdeadbeef;
tor_free(buf);
}
+/** Return a new copy of <b>in_chunk</b> */
+static chunk_t *
+chunk_copy(const chunk_t *in_chunk)
+{
+ chunk_t *newch = tor_memdup(in_chunk, CHUNK_ALLOC_SIZE(in_chunk->memlen));
+ newch->next = NULL;
+ if (in_chunk->data) {
+ off_t offset = in_chunk->data - in_chunk->mem;
+ newch->data = newch->mem + offset;
+ }
+ return newch;
+}
+
+/** Return a new copy of <b>buf</b> */
+buf_t *
+buf_copy(const buf_t *buf)
+{
+ chunk_t *ch;
+ buf_t *out = buf_new();
+ out->default_chunk_size = buf->default_chunk_size;
+ for (ch = buf->head; ch; ch = ch->next) {
+ chunk_t *newch = chunk_copy(ch);
+ if (out->tail) {
+ out->tail->next = newch;
+ out->tail = newch;
+ } else {
+ out->head = out->tail = newch;
+ }
+ }
+ out->datalen = buf->datalen;
+ return out;
+}
+
/** Append a new chunk with enough capacity to hold <b>capacity</b> bytes to
* the tail of <b>buf</b>. If <b>capped</b>, don't allocate a chunk bigger
* than MAX_CHUNK_ALLOC. */
@@ -578,10 +616,6 @@ buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
return chunk;
}
-/** If we're using readv and writev, how many chunks are we willing to
- * read/write at a time? */
-#define N_IOV 3
-
/** Read up to <b>at_most</b> bytes from the socket <b>fd</b> into
* <b>chunk</b> (which must be on <b>buf</b>). If we get an EOF, set
* *<b>reached_eof</b> to 1. Return -1 on error, 0 on eof or blocking,
@@ -591,25 +625,9 @@ read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most,
int *reached_eof, int *socket_error)
{
ssize_t read_result;
-#if 0 && defined(HAVE_READV) && !defined(WIN32)
- struct iovec iov[N_IOV];
- int i;
- size_t remaining = at_most;
- for (i=0; chunk && i < N_IOV && remaining; ++i) {
- iov[i].iov_base = CHUNK_WRITE_PTR(chunk);
- if (remaining > CHUNK_REMAINING_CAPACITY(chunk))
- iov[i].iov_len = CHUNK_REMAINING_CAPACITY(chunk);
- else
- iov[i].iov_len = remaining;
- remaining -= iov[i].iov_len;
- chunk = chunk->next;
- }
- read_result = readv(fd, iov, i);
-#else
if (at_most > CHUNK_REMAINING_CAPACITY(chunk))
at_most = CHUNK_REMAINING_CAPACITY(chunk);
read_result = tor_socket_recv(fd, CHUNK_WRITE_PTR(chunk), at_most, 0);
-#endif
if (read_result < 0) {
int e = tor_socket_errno(fd);
@@ -628,14 +646,6 @@ read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most,
return 0;
} else { /* actually got bytes. */
buf->datalen += read_result;
-#if 0 && defined(HAVE_READV) && !defined(WIN32)
- while ((size_t)read_result > CHUNK_REMAINING_CAPACITY(chunk)) {
- chunk->datalen += CHUNK_REMAINING_CAPACITY(chunk);
- read_result -= CHUNK_REMAINING_CAPACITY(chunk);
- chunk = chunk->next;
- tor_assert(chunk);
- }
-#endif
chunk->datalen += read_result;
log_debug(LD_NET,"Read %ld bytes. %d on inbuf.", (long)read_result,
(int)buf->datalen);
@@ -771,25 +781,10 @@ flush_chunk(tor_socket_t s, buf_t *buf, chunk_t *chunk, size_t sz,
size_t *buf_flushlen)
{
ssize_t write_result;
-#if 0 && defined(HAVE_WRITEV) && !defined(WIN32)
- struct iovec iov[N_IOV];
- int i;
- size_t remaining = sz;
- for (i=0; chunk && i < N_IOV && remaining; ++i) {
- iov[i].iov_base = chunk->data;
- if (remaining > chunk->datalen)
- iov[i].iov_len = chunk->datalen;
- else
- iov[i].iov_len = remaining;
- remaining -= iov[i].iov_len;
- chunk = chunk->next;
- }
- write_result = writev(s, iov, i);
-#else
+
if (sz > chunk->datalen)
sz = chunk->datalen;
write_result = tor_socket_send(s, chunk->data, sz, 0);
-#endif
if (write_result < 0) {
int e = tor_socket_errno(s);
@@ -1056,6 +1051,93 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
return 1;
}
+#ifdef USE_BUFFEREVENTS
+/** Try to read <b>n</b> bytes from <b>buf</b> at <b>pos</b> (which may be
+ * NULL for the start of the buffer), copying the data only if necessary. Set
+ * *<b>data_out</b> to a pointer to the desired bytes. Set <b>free_out</b>
+ * to 1 if we needed to malloc *<b>data</b> because the original bytes were
+ * noncontiguous; 0 otherwise. Return the number of bytes actually available
+ * at *<b>data_out</b>.
+ */
+static ssize_t
+inspect_evbuffer(struct evbuffer *buf, char **data_out, size_t n,
+ int *free_out, struct evbuffer_ptr *pos)
+{
+ int n_vecs, i;
+
+ if (evbuffer_get_length(buf) < n)
+ n = evbuffer_get_length(buf);
+ if (n == 0)
+ return 0;
+ n_vecs = evbuffer_peek(buf, n, pos, NULL, 0);
+ tor_assert(n_vecs > 0);
+ if (n_vecs == 1) {
+ struct evbuffer_iovec v;
+ i = evbuffer_peek(buf, n, pos, &v, 1);
+ tor_assert(i == 1);
+ *data_out = v.iov_base;
+ *free_out = 0;
+ return v.iov_len;
+ } else {
+ ev_ssize_t copied;
+ *data_out = tor_malloc(n);
+ *free_out = 1;
+ copied = evbuffer_copyout(buf, *data_out, n);
+ tor_assert(copied >= 0 && (size_t)copied == n);
+ return copied;
+ }
+}
+
+/** As fetch_var_cell_from_buf, buf works on an evbuffer. */
+int
+fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out,
+ int linkproto)
+{
+ char *hdr = NULL;
+ int free_hdr = 0;
+ size_t n;
+ size_t buf_len;
+ uint8_t command;
+ uint16_t cell_length;
+ var_cell_t *cell;
+ int result = 0;
+ if (linkproto == 1)
+ return 0;
+
+ *out = NULL;
+ buf_len = evbuffer_get_length(buf);
+ if (buf_len < VAR_CELL_HEADER_SIZE)
+ return 0;
+
+ n = inspect_evbuffer(buf, &hdr, VAR_CELL_HEADER_SIZE, &free_hdr, NULL);
+ tor_assert(n >= VAR_CELL_HEADER_SIZE);
+
+ command = get_uint8(hdr+2);
+ if (!(CELL_COMMAND_IS_VAR_LENGTH(command))) {
+ goto done;
+ }
+
+ cell_length = ntohs(get_uint16(hdr+3));
+ if (buf_len < (size_t)(VAR_CELL_HEADER_SIZE+cell_length)) {
+ result = 1; /* Not all here yet. */
+ goto done;
+ }
+
+ cell = var_cell_new(cell_length);
+ cell->command = command;
+ cell->circ_id = ntohs(get_uint16(hdr));
+ evbuffer_drain(buf, VAR_CELL_HEADER_SIZE);
+ evbuffer_remove(buf, cell->payload, cell_length);
+ *out = cell;
+ result = 1;
+
+ done:
+ if (free_hdr && hdr)
+ tor_free(hdr);
+ return result;
+}
+#endif
+
/** Move up to *<b>buf_flushlen</b> bytes from <b>buf_in</b> to
* <b>buf_out</b>, and modify *<b>buf_flushlen</b> appropriately.
* Return the number of bytes actually copied.
@@ -1063,8 +1145,7 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
int
move_buf_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen)
{
- /* XXXX we can do way better here, but this doesn't turn up in any
- * profiles. */
+ /* We can do way better here, but this doesn't turn up in any profiles. */
char b[4096];
size_t cp, len;
len = *buf_flushlen;
@@ -1299,6 +1380,94 @@ fetch_from_buf_http(buf_t *buf,
return 1;
}
+#ifdef USE_BUFFEREVENTS
+/** As fetch_from_buf_http, buf works on an evbuffer. */
+int
+fetch_from_evbuffer_http(struct evbuffer *buf,
+ char **headers_out, size_t max_headerlen,
+ char **body_out, size_t *body_used, size_t max_bodylen,
+ int force_complete)
+{
+ struct evbuffer_ptr crlf, content_length;
+ size_t headerlen, bodylen, contentlen;
+
+ /* Find the first \r\n\r\n in the buffer */
+ crlf = evbuffer_search(buf, "\r\n\r\n", 4, NULL);
+ if (crlf.pos < 0) {
+ /* We didn't find one. */
+ if (evbuffer_get_length(buf) > max_headerlen)
+ return -1; /* Headers too long. */
+ return 0; /* Headers not here yet. */
+ } else if (crlf.pos > (int)max_headerlen) {
+ return -1; /* Headers too long. */
+ }
+
+ headerlen = crlf.pos + 4; /* Skip over the \r\n\r\n */
+ bodylen = evbuffer_get_length(buf) - headerlen;
+ if (bodylen > max_bodylen)
+ return -1; /* body too long */
+
+ /* Look for the first occurrence of CONTENT_LENGTH insize buf before the
+ * crlfcrlf */
+ content_length = evbuffer_search_range(buf, CONTENT_LENGTH,
+ strlen(CONTENT_LENGTH), NULL, &crlf);
+
+ if (content_length.pos >= 0) {
+ /* We found a content_length: parse it and figure out if the body is here
+ * yet. */
+ struct evbuffer_ptr eol;
+ char *data = NULL;
+ int free_data = 0;
+ int n, i;
+ n = evbuffer_ptr_set(buf, &content_length, strlen(CONTENT_LENGTH),
+ EVBUFFER_PTR_ADD);
+ tor_assert(n == 0);
+ eol = evbuffer_search_eol(buf, &content_length, NULL, EVBUFFER_EOL_CRLF);
+ tor_assert(eol.pos > content_length.pos);
+ tor_assert(eol.pos <= crlf.pos);
+ inspect_evbuffer(buf, &data, eol.pos - content_length.pos, &free_data,
+ &content_length);
+
+ i = atoi(data);
+ if (free_data)
+ tor_free(data);
+ if (i < 0) {
+ log_warn(LD_PROTOCOL, "Content-Length is less than zero; it looks like "
+ "someone is trying to crash us.");
+ return -1;
+ }
+ contentlen = i;
+ /* if content-length is malformed, then our body length is 0. fine. */
+ log_debug(LD_HTTP,"Got a contentlen of %d.",(int)contentlen);
+ if (bodylen < contentlen) {
+ if (!force_complete) {
+ log_debug(LD_HTTP,"body not all here yet.");
+ return 0; /* not all there yet */
+ }
+ }
+ if (bodylen > contentlen) {
+ bodylen = contentlen;
+ log_debug(LD_HTTP,"bodylen reduced to %d.",(int)bodylen);
+ }
+ }
+
+ if (headers_out) {
+ *headers_out = tor_malloc(headerlen+1);
+ evbuffer_remove(buf, *headers_out, headerlen);
+ (*headers_out)[headerlen] = '\0';
+ }
+ if (body_out) {
+ tor_assert(headers_out);
+ tor_assert(body_used);
+ *body_used = bodylen;
+ *body_out = tor_malloc(bodylen+1);
+ evbuffer_remove(buf, *body_out, bodylen);
+ (*body_out)[bodylen] = '\0';
+ }
+ return 1;
+}
+#endif
+
/**
* Wait this many seconds before warning the user about using SOCKS unsafely
* again (requires that WarnUnsafeSocks is turned on). */
@@ -1313,7 +1482,7 @@ log_unsafe_socks_warning(int socks_protocol, const char *address,
{
static ratelim_t socks_ratelim = RATELIM_INIT(SOCKS_WARN_INTERVAL);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char *m = NULL;
if (! options->WarnUnsafeSocks)
return;
@@ -1340,6 +1509,31 @@ log_unsafe_socks_warning(int socks_protocol, const char *address,
* actually significantly higher than the longest possible socks message. */
#define MAX_SOCKS_MESSAGE_LEN 512
+/** Return a new socks_request_t. */
+socks_request_t *
+socks_request_new(void)
+{
+ return tor_malloc_zero(sizeof(socks_request_t));
+}
+
+/** Free all storage held in the socks_request_t <b>req</b>. */
+void
+socks_request_free(socks_request_t *req)
+{
+ if (!req)
+ return;
+ if (req->username) {
+ memset(req->username, 0x10, req->usernamelen);
+ tor_free(req->username);
+ }
+ if (req->password) {
+ memset(req->password, 0x04, req->passwordlen);
+ tor_free(req->password);
+ }
+ memset(req, 0xCC, sizeof(socks_request_t));
+ tor_free(req);
+}
+
/** There is a (possibly incomplete) socks handshake on <b>buf</b>, of one
* of the forms
* - socks4: "socksheader username\\0"
@@ -1369,59 +1563,241 @@ int
fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
int log_sockstype, int safe_socks)
{
+ int res;
+ ssize_t n_drain;
+ size_t want_length = 128;
+
+ if (buf->datalen < 2) /* version and another byte */
+ return 0;
+
+ do {
+ n_drain = 0;
+ buf_pullup(buf, want_length, 0);
+ tor_assert(buf->head && buf->head->datalen >= 2);
+ want_length = 0;
+
+ res = parse_socks(buf->head->data, buf->head->datalen, req, log_sockstype,
+ safe_socks, &n_drain, &want_length);
+
+ if (n_drain < 0)
+ buf_clear(buf);
+ else if (n_drain > 0)
+ buf_remove_from_front(buf, n_drain);
+
+ } while (res == 0 && buf->head && want_length < buf->datalen &&
+ buf->datalen >= 2);
+
+ return res;
+}
+
+#ifdef USE_BUFFEREVENTS
+/* As fetch_from_buf_socks(), but targets an evbuffer instead. */
+int
+fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req,
+ int log_sockstype, int safe_socks)
+{
+ char *data;
+ ssize_t n_drain;
+ size_t datalen, buflen, want_length;
+ int res;
+
+ buflen = evbuffer_get_length(buf);
+ if (buflen < 2)
+ return 0;
+
+ {
+ /* See if we can find the socks request in the first chunk of the buffer.
+ */
+ struct evbuffer_iovec v;
+ int i;
+ n_drain = 0;
+ i = evbuffer_peek(buf, -1, NULL, &v, 1);
+ tor_assert(i == 1);
+ data = v.iov_base;
+ datalen = v.iov_len;
+ want_length = 0;
+
+ res = parse_socks(data, datalen, req, log_sockstype,
+ safe_socks, &n_drain, &want_length);
+
+ if (n_drain < 0)
+ evbuffer_drain(buf, evbuffer_get_length(buf));
+ else if (n_drain > 0)
+ evbuffer_drain(buf, n_drain);
+
+ if (res)
+ return res;
+ }
+
+ /* Okay, the first chunk of the buffer didn't have a complete socks request.
+ * That means that either we don't have a whole socks request at all, or
+ * it's gotten split up. We're going to try passing parse_socks() bigger
+ * and bigger chunks until either it says "Okay, I got it", or it says it
+ * will need more data than we currently have. */
+
+ /* Loop while we have more data that we haven't given parse_socks() yet. */
+ do {
+ int free_data = 0;
+ const size_t last_wanted = want_length;
+ n_drain = 0;
+ data = NULL;
+ datalen = inspect_evbuffer(buf, &data, want_length, &free_data, NULL);
+
+ want_length = 0;
+ res = parse_socks(data, datalen, req, log_sockstype,
+ safe_socks, &n_drain, &want_length);
+
+ if (free_data)
+ tor_free(data);
+
+ if (n_drain < 0)
+ evbuffer_drain(buf, evbuffer_get_length(buf));
+ else if (n_drain > 0)
+ evbuffer_drain(buf, n_drain);
+
+ if (res == 0 && n_drain == 0 && want_length <= last_wanted) {
+ /* If we drained nothing, and we didn't ask for more than last time,
+ * then we probably wanted more data than the buffer actually had,
+ * and we're finding out that we're not satisified with it. It's
+ * time to break until we have more data. */
+ break;
+ }
+
+ buflen = evbuffer_get_length(buf);
+ } while (res == 0 && want_length <= buflen && buflen >= 2);
+
+ return res;
+}
+#endif
+
+/** Implementation helper to implement fetch_from_*_socks. Instead of looking
+ * at a buffer's contents, we look at the <b>datalen</b> bytes of data in
+ * <b>data</b>. Instead of removing data from the buffer, we set
+ * <b>drain_out</b> to the amount of data that should be removed (or -1 if the
+ * buffer should be cleared). Instead of pulling more data into the first
+ * chunk of the buffer, we set *<b>want_length_out</b> to the number of bytes
+ * we'd like to see in the input buffer, if they're available. */
+static int
+parse_socks(const char *data, size_t datalen, socks_request_t *req,
+ int log_sockstype, int safe_socks, ssize_t *drain_out,
+ size_t *want_length_out)
+{
unsigned int len;
char tmpbuf[TOR_ADDR_BUF_LEN+1];
tor_addr_t destaddr;
uint32_t destip;
uint8_t socksver;
- enum {socks4, socks4a} socks4_prot = socks4a;
char *next, *startaddr;
+ unsigned char usernamelen, passlen;
struct in_addr in;
- if (buf->datalen < 2) /* version and another byte */
+ if (datalen < 2) {
+ /* We always need at least 2 bytes. */
+ *want_length_out = 2;
return 0;
+ }
- buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN, 0);
- tor_assert(buf->head && buf->head->datalen >= 2);
+ if (req->socks_version == 5 && !req->got_auth) {
+ /* See if we have received authentication. Strictly speaking, we should
+ also check whether we actually negotiated username/password
+ authentication. But some broken clients will send us authentication
+ even if we negotiated SOCKS_NO_AUTH. */
+ if (*data == 1) { /* username/pass version 1 */
+ /* Format is: authversion [1 byte] == 1
+ usernamelen [1 byte]
+ username [usernamelen bytes]
+ passlen [1 byte]
+ password [passlen bytes] */
+ usernamelen = (unsigned char)*(data + 1);
+ if (datalen < 2u + usernamelen + 1u) {
+ *want_length_out = 2u + usernamelen + 1u;
+ return 0;
+ }
+ passlen = (unsigned char)*(data + 2u + usernamelen);
+ if (datalen < 2u + usernamelen + 1u + passlen) {
+ *want_length_out = 2u + usernamelen + 1u + passlen;
+ return 0;
+ }
+ req->replylen = 2; /* 2 bytes of response */
+ req->reply[0] = 5;
+ req->reply[1] = 0; /* authentication successful */
+ log_debug(LD_APP,
+ "socks5: Accepted username/password without checking.");
+ if (usernamelen) {
+ req->username = tor_memdup(data+2u, usernamelen);
+ req->usernamelen = usernamelen;
+ }
+ if (passlen) {
+ req->password = tor_memdup(data+3u+usernamelen, passlen);
+ req->passwordlen = passlen;
+ }
+ *drain_out = 2u + usernamelen + 1u + passlen;
+ req->got_auth = 1;
+ *want_length_out = 7; /* Minimal socks5 sommand. */
+ return 0;
+ } else if (req->auth_type == SOCKS_USER_PASS) {
+ /* unknown version byte */
+ log_warn(LD_APP, "Socks5 username/password version %d not recognized; "
+ "rejecting.", (int)*data);
+ return -1;
+ }
+ }
- socksver = *buf->head->data;
+ socksver = *data;
switch (socksver) { /* which version of socks? */
-
case 5: /* socks5 */
if (req->socks_version != 5) { /* we need to negotiate a method */
- unsigned char nummethods = (unsigned char)*(buf->head->data+1);
+ unsigned char nummethods = (unsigned char)*(data+1);
+ int r=0;
tor_assert(!req->socks_version);
- if (buf->datalen < 2u+nummethods)
+ if (datalen < 2u+nummethods) {
+ *want_length_out = 2u+nummethods;
return 0;
- buf_pullup(buf, 2u+nummethods, 0);
- if (!nummethods || !memchr(buf->head->data+2, 0, nummethods)) {
+ }
+ if (!nummethods)
+ return -1;
+ req->replylen = 2; /* 2 bytes of response */
+ req->reply[0] = 5; /* socks5 reply */
+ if (memchr(data+2, SOCKS_NO_AUTH, nummethods)) {
+ req->reply[1] = SOCKS_NO_AUTH; /* tell client to use "none" auth
+ method */
+ req->socks_version = 5; /* remember we've already negotiated auth */
+ log_debug(LD_APP,"socks5: accepted method 0 (no authentication)");
+ r=0;
+ } else if (memchr(data+2, SOCKS_USER_PASS, nummethods)) {
+ req->auth_type = SOCKS_USER_PASS;
+ req->reply[1] = SOCKS_USER_PASS; /* tell client to use "user/pass"
+ auth method */
+ req->socks_version = 5; /* remember we've already negotiated auth */
+ log_debug(LD_APP,"socks5: accepted method 2 (username/password)");
+ r=0;
+ } else {
log_warn(LD_APP,
- "socks5: offered methods don't include 'no auth'. "
- "Rejecting.");
- req->replylen = 2; /* 2 bytes of response */
- req->reply[0] = 5;
+ "socks5: offered methods don't include 'no auth' or "
+ "username/password. Rejecting.");
req->reply[1] = '\xFF'; /* reject all methods */
- return -1;
+ r=-1;
}
- /* remove packet from buf. also remove any other extraneous
- * bytes, to support broken socks clients. */
- buf_clear(buf);
+ /* Remove packet from buf. Some SOCKS clients will have sent extra
+ * junk at this point; let's hope it's an authentication message. */
+ *drain_out = 2u + nummethods;
- req->replylen = 2; /* 2 bytes of response */
- req->reply[0] = 5; /* socks5 reply */
- req->reply[1] = 0; /* tell client to use "none" auth method */
- req->socks_version = 5; /* remember we've already negotiated auth */
- log_debug(LD_APP,"socks5: accepted method 0");
- return 0;
+ return r;
+ }
+ if (req->auth_type != SOCKS_NO_AUTH && !req->got_auth) {
+ log_warn(LD_APP,
+ "socks5: negotiated authentication, but none provided");
+ return -1;
}
/* we know the method; read in the request */
log_debug(LD_APP,"socks5: checking request");
- if (buf->datalen < 8) /* basic info plus >=2 for addr plus 2 for port */
+ if (datalen < 7) {/* basic info plus >=1 for addr plus 2 for port */
+ *want_length_out = 7;
return 0; /* not yet */
- tor_assert(buf->head->datalen >= 8);
- req->command = (unsigned char) *(buf->head->data+1);
+ }
+ req->command = (unsigned char) *(data+1);
if (req->command != SOCKS_COMMAND_CONNECT &&
req->command != SOCKS_COMMAND_RESOLVE &&
req->command != SOCKS_COMMAND_RESOLVE_PTR) {
@@ -1430,19 +1806,21 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
req->command);
return -1;
}
- switch (*(buf->head->data+3)) { /* address type */
+ switch (*(data+3)) { /* address type */
case 1: /* IPv4 address */
case 4: /* IPv6 address */ {
- const int is_v6 = *(buf->head->data+3) == 4;
+ const int is_v6 = *(data+3) == 4;
const unsigned addrlen = is_v6 ? 16 : 4;
log_debug(LD_APP,"socks5: ipv4 address type");
- if (buf->datalen < 6+addrlen) /* ip/port there? */
+ if (datalen < 6+addrlen) {/* ip/port there? */
+ *want_length_out = 6+addrlen;
return 0; /* not yet */
+ }
if (is_v6)
- tor_addr_from_ipv6_bytes(&destaddr, buf->head->data+4);
+ tor_addr_from_ipv6_bytes(&destaddr, data+4);
else
- tor_addr_from_ipv4n(&destaddr, get_uint32(buf->head->data+4));
+ tor_addr_from_ipv4n(&destaddr, get_uint32(data+4));
tor_addr_to_str(tmpbuf, &destaddr, sizeof(tmpbuf), 1);
@@ -1454,8 +1832,8 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
return -1;
}
strlcpy(req->address,tmpbuf,sizeof(req->address));
- req->port = ntohs(get_uint16(buf->head->data+4+addrlen));
- buf_remove_from_front(buf, 6+addrlen);
+ req->port = ntohs(get_uint16(data+4+addrlen));
+ *drain_out = 6+addrlen;
if (req->command != SOCKS_COMMAND_RESOLVE_PTR &&
!addressmap_have_mapping(req->address,0)) {
log_unsafe_socks_warning(5, req->address, req->port, safe_socks);
@@ -1471,21 +1849,21 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
"hostname type. Rejecting.");
return -1;
}
- len = (unsigned char)*(buf->head->data+4);
- if (buf->datalen < 7+len) /* addr/port there? */
+ len = (unsigned char)*(data+4);
+ if (datalen < 7+len) { /* addr/port there? */
+ *want_length_out = 7+len;
return 0; /* not yet */
- buf_pullup(buf, 7+len, 0);
- tor_assert(buf->head->datalen >= 7+len);
+ }
if (len+1 > MAX_SOCKS_ADDR_LEN) {
log_warn(LD_APP,
"socks5 hostname is %d bytes, which doesn't fit in "
"%d. Rejecting.", len+1,MAX_SOCKS_ADDR_LEN);
return -1;
}
- memcpy(req->address,buf->head->data+5,len);
+ memcpy(req->address,data+5,len);
req->address[len] = 0;
- req->port = ntohs(get_uint16(buf->head->data+5+len));
- buf_remove_from_front(buf, 5+len+2);
+ req->port = ntohs(get_uint16(data+5+len));
+ *drain_out = 5+len+2;
if (!tor_strisprint(req->address) || strchr(req->address,'\"')) {
log_warn(LD_PROTOCOL,
"Your application (using socks5 to port %d) gave Tor "
@@ -1495,25 +1873,29 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
}
if (log_sockstype)
log_notice(LD_APP,
- "Your application (using socks5 to port %d) gave "
- "Tor a hostname, which means Tor will do the DNS resolve "
- "for you. This is good.", req->port);
+ "Your application (using socks5 to port %d) instructed "
+ "Tor to take care of the DNS resolution itself if "
+ "necessary. This is good.", req->port);
return 1;
default: /* unsupported */
log_warn(LD_APP,"socks5: unsupported address type %d. Rejecting.",
- (int) *(buf->head->data+3));
+ (int) *(data+3));
return -1;
}
tor_assert(0);
- case 4: /* socks4 */
- /* http://archive.socks.permeo.com/protocol/socks4.protocol */
- /* http://archive.socks.permeo.com/protocol/socks4a.protocol */
+ case 4: { /* socks4 */
+ enum {socks4, socks4a} socks4_prot = socks4a;
+ const char *authstart, *authend;
+ /* http://ss5.sourceforge.net/socks4.protocol.txt */
+ /* http://ss5.sourceforge.net/socks4A.protocol.txt */
req->socks_version = 4;
- if (buf->datalen < SOCKS4_NETWORK_LEN) /* basic info available? */
+ if (datalen < SOCKS4_NETWORK_LEN) {/* basic info available? */
+ *want_length_out = SOCKS4_NETWORK_LEN;
return 0; /* not yet */
- buf_pullup(buf, 1280, 0);
- req->command = (unsigned char) *(buf->head->data+1);
+ }
+ // buf_pullup(buf, 1280, 0);
+ req->command = (unsigned char) *(data+1);
if (req->command != SOCKS_COMMAND_CONNECT &&
req->command != SOCKS_COMMAND_RESOLVE) {
/* not a connect or resolve? we don't support it. (No resolve_ptr with
@@ -1523,8 +1905,8 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
return -1;
}
- req->port = ntohs(get_uint16(buf->head->data+2));
- destip = ntohl(get_uint32(buf->head->data+4));
+ req->port = ntohs(get_uint16(data+2));
+ destip = ntohl(get_uint32(data+4));
if ((!req->port && req->command!=SOCKS_COMMAND_RESOLVE) || !destip) {
log_warn(LD_APP,"socks4: Port or DestIP is zero. Rejecting.");
return -1;
@@ -1544,17 +1926,20 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
socks4_prot = socks4;
}
- next = memchr(buf->head->data+SOCKS4_NETWORK_LEN, 0,
- buf->head->datalen-SOCKS4_NETWORK_LEN);
+ authstart = data + SOCKS4_NETWORK_LEN;
+ next = memchr(authstart, 0,
+ datalen-SOCKS4_NETWORK_LEN);
if (!next) {
- if (buf->head->datalen >= 1024) {
+ if (datalen >= 1024) {
log_debug(LD_APP, "Socks4 user name too long; rejecting.");
return -1;
}
log_debug(LD_APP,"socks4: Username not here yet.");
+ *want_length_out = datalen+1024; /* More than we need, but safe */
return 0;
}
- tor_assert(next < CHUNK_WRITE_PTR(buf->head));
+ authend = next;
+ tor_assert(next < data+datalen);
startaddr = NULL;
if (socks4_prot != socks4a &&
@@ -1565,18 +1950,20 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
return -1;
}
if (socks4_prot == socks4a) {
- if (next+1 == CHUNK_WRITE_PTR(buf->head)) {
+ if (next+1 == data+datalen) {
log_debug(LD_APP,"socks4: No part of destaddr here yet.");
+ *want_length_out = datalen + 1024; /* More than we need, but safe */
return 0;
}
startaddr = next+1;
- next = memchr(startaddr, 0, CHUNK_WRITE_PTR(buf->head)-startaddr);
+ next = memchr(startaddr, 0, data + datalen - startaddr);
if (!next) {
- if (buf->head->datalen >= 1024) {
+ if (datalen >= 1024) {
log_debug(LD_APP,"socks4: Destaddr too long.");
return -1;
}
log_debug(LD_APP,"socks4: Destaddr not all here yet.");
+ *want_length_out = datalen + 1024; /* More than we need, but safe */
return 0;
}
if (MAX_SOCKS_ADDR_LEN <= next-startaddr) {
@@ -1587,9 +1974,9 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
if (log_sockstype)
log_notice(LD_APP,
- "Your application (using socks4a to port %d) gave "
- "Tor a hostname, which means Tor will do the DNS resolve "
- "for you. This is good.", req->port);
+ "Your application (using socks4a to port %d) instructed "
+ "Tor to take care of the DNS resolution itself if "
+ "necessary. This is good.", req->port);
}
log_debug(LD_APP,"socks4: Everything is here. Success.");
strlcpy(req->address, startaddr ? startaddr : tmpbuf,
@@ -1601,15 +1988,20 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
req->port, escaped(req->address));
return -1;
}
+ if (authend != authstart) {
+ req->got_auth = 1;
+ req->usernamelen = authend - authstart;
+ req->username = tor_memdup(authstart, authend - authstart);
+ }
/* next points to the final \0 on inbuf */
- buf_remove_from_front(buf, next - buf->head->data + 1);
+ *drain_out = next - data + 1;
return 1;
-
+ }
case 'G': /* get */
case 'H': /* head */
case 'P': /* put/post */
case 'C': /* connect */
- strlcpy(req->reply,
+ strlcpy((char*)req->reply,
"HTTP/1.0 501 Tor is not an HTTP Proxy\r\n"
"Content-Type: text/html; charset=iso-8859-1\r\n\r\n"
"<html>\n"
@@ -1635,14 +2027,15 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
"</body>\n"
"</html>\n"
, MAX_SOCKS_REPLY_LEN);
- req->replylen = strlen(req->reply)+1;
+ req->replylen = strlen((char*)req->reply)+1;
/* fall through */
default: /* version is not socks4 or socks5 */
log_warn(LD_APP,
"Socks version %d not recognized. (Tor is not an http proxy.)",
- *(buf->head->data));
+ *(data));
{
- char *tmp = tor_strndup(buf->head->data, 8); /*XXXX what if longer?*/
+ /* Tell the controller the first 8 bytes. */
+ char *tmp = tor_strndup(data, datalen < 8 ? datalen : 8);
control_event_client_status(LOG_WARN,
"SOCKS_UNKNOWN_PROTOCOL DATA=\"%s\"",
escaped(tmp));
@@ -1664,21 +2057,67 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
int
fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
{
- unsigned char *data;
- size_t addrlen;
-
+ ssize_t drain = 0;
+ int r;
if (buf->datalen < 2)
return 0;
buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN, 0);
tor_assert(buf->head && buf->head->datalen >= 2);
- data = (unsigned char *) buf->head->data;
+ r = parse_socks_client((uint8_t*)buf->head->data, buf->head->datalen,
+ state, reason, &drain);
+ if (drain > 0)
+ buf_remove_from_front(buf, drain);
+ else if (drain < 0)
+ buf_clear(buf);
+
+ return r;
+}
+
+#ifdef USE_BUFFEREVENTS
+/** As fetch_from_buf_socks_client, buf works on an evbuffer */
+int
+fetch_from_evbuffer_socks_client(struct evbuffer *buf, int state,
+ char **reason)
+{
+ ssize_t drain = 0;
+ uint8_t *data;
+ size_t datalen;
+ int r;
+
+ /* Linearize the SOCKS response in the buffer, up to 128 bytes.
+ * (parse_socks_client shouldn't need to see anything beyond that.) */
+ datalen = evbuffer_get_length(buf);
+ if (datalen > MAX_SOCKS_MESSAGE_LEN)
+ datalen = MAX_SOCKS_MESSAGE_LEN;
+ data = evbuffer_pullup(buf, datalen);
+
+ r = parse_socks_client(data, datalen, state, reason, &drain);
+ if (drain > 0)
+ evbuffer_drain(buf, drain);
+ else if (drain < 0)
+ evbuffer_drain(buf, evbuffer_get_length(buf));
+
+ return r;
+}
+#endif
+
+/** Implementation logic for fetch_from_*_socks_client. */
+static int
+parse_socks_client(const uint8_t *data, size_t datalen,
+ int state, char **reason,
+ ssize_t *drain_out)
+{
+ unsigned int addrlen;
+ *drain_out = 0;
+ if (datalen < 2)
+ return 0;
switch (state) {
case PROXY_SOCKS4_WANT_CONNECT_OK:
/* Wait for the complete response */
- if (buf->head->datalen < 8)
+ if (datalen < 8)
return 0;
if (data[1] != 0x5a) {
@@ -1687,7 +2126,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
}
/* Success */
- buf_remove_from_front(buf, 8);
+ *drain_out = 8;
return 1;
case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
@@ -1699,7 +2138,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
}
log_info(LD_NET, "SOCKS 5 client: continuing without authentication");
- buf_clear(buf);
+ *drain_out = -1;
return 1;
case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
@@ -1709,11 +2148,11 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
case 0x00:
log_info(LD_NET, "SOCKS 5 client: we have auth details but server "
"doesn't require authentication.");
- buf_clear(buf);
+ *drain_out = -1;
return 1;
case 0x02:
log_info(LD_NET, "SOCKS 5 client: need authentication.");
- buf_clear(buf);
+ *drain_out = -1;
return 2;
/* fall through */
}
@@ -1730,7 +2169,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
}
log_info(LD_NET, "SOCKS 5 client: authentication successful.");
- buf_clear(buf);
+ *drain_out = -1;
return 1;
case PROXY_SOCKS5_WANT_CONNECT_OK:
@@ -1739,7 +2178,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
* the data used */
/* wait for address type field to arrive */
- if (buf->datalen < 4)
+ if (datalen < 4)
return 0;
switch (data[3]) {
@@ -1750,7 +2189,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
addrlen = 16;
break;
case 0x03: /* fqdn (can this happen here?) */
- if (buf->datalen < 5)
+ if (datalen < 5)
return 0;
addrlen = 1 + data[4];
break;
@@ -1760,7 +2199,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
}
/* wait for address and port */
- if (buf->datalen < 6 + addrlen)
+ if (datalen < 6 + addrlen)
return 0;
if (data[1] != 0x00) {
@@ -1768,7 +2207,7 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
return -1;
}
- buf_remove_from_front(buf, 6 + addrlen);
+ *drain_out = 6 + addrlen;
return 1;
}
@@ -1794,6 +2233,27 @@ peek_buf_has_control0_command(buf_t *buf)
return 0;
}
+#ifdef USE_BUFFEREVENTS
+int
+peek_evbuffer_has_control0_command(struct evbuffer *buf)
+{
+ int result = 0;
+ if (evbuffer_get_length(buf) >= 4) {
+ int free_out = 0;
+ char *data = NULL;
+ size_t n = inspect_evbuffer(buf, &data, 4, &free_out, NULL);
+ uint16_t cmd;
+ tor_assert(n >= 4);
+ cmd = ntohs(get_uint16(data+2));
+ if (cmd <= 0x14)
+ result = 1;
+ if (free_out)
+ tor_free(data);
+ }
+ return result;
+}
+#endif
+
/** Return the index within <b>buf</b> at which <b>ch</b> first appears,
* or -1 if <b>ch</b> does not appear on buf. */
static off_t
@@ -1811,12 +2271,12 @@ buf_find_offset_of_char(buf_t *buf, char ch)
return -1;
}
-/** Try to read a single LF-terminated line from <b>buf</b>, and write it,
- * NUL-terminated, into the *<b>data_len</b> byte buffer at <b>data_out</b>.
- * Set *<b>data_len</b> to the number of bytes in the line, not counting the
- * terminating NUL. Return 1 if we read a whole line, return 0 if we don't
- * have a whole line yet, and return -1 if the line length exceeds
- * *<b>data_len</b>.
+/** Try to read a single LF-terminated line from <b>buf</b>, and write it
+ * (including the LF), NUL-terminated, into the *<b>data_len</b> byte buffer
+ * at <b>data_out</b>. Set *<b>data_len</b> to the number of bytes in the
+ * line, not counting the terminating NUL. Return 1 if we read a whole line,
+ * return 0 if we don't have a whole line yet, and return -1 if the line
+ * length exceeds *<b>data_len</b>.
*/
int
fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len)
@@ -1890,6 +2350,96 @@ write_to_buf_zlib(buf_t *buf, tor_zlib_state_t *state,
return 0;
}
+#ifdef USE_BUFFEREVENTS
+int
+write_to_evbuffer_zlib(struct evbuffer *buf, tor_zlib_state_t *state,
+ const char *data, size_t data_len,
+ int done)
+{
+ char *next;
+ size_t old_avail, avail;
+ int over = 0, n;
+ struct evbuffer_iovec vec[1];
+ do {
+ {
+ size_t cap = data_len / 4;
+ if (cap < 128)
+ cap = 128;
+ /* XXXX NM this strategy is fragmentation-prone. We should really have
+ * two iovecs, and write first into the one, and then into the
+ * second if the first gets full. */
+ n = evbuffer_reserve_space(buf, cap, vec, 1);
+ tor_assert(n == 1);
+ }
+
+ next = vec[0].iov_base;
+ avail = old_avail = vec[0].iov_len;
+
+ switch (tor_zlib_process(state, &next, &avail, &data, &data_len, done)) {
+ case TOR_ZLIB_DONE:
+ over = 1;
+ break;
+ case TOR_ZLIB_ERR:
+ return -1;
+ case TOR_ZLIB_OK:
+ if (data_len == 0)
+ over = 1;
+ break;
+ case TOR_ZLIB_BUF_FULL:
+ if (avail) {
+ /* Zlib says we need more room (ZLIB_BUF_FULL). Start a new chunk
+ * automatically, whether were going to or not. */
+ }
+ break;
+ }
+
+ /* XXXX possible infinite loop on BUF_FULL. */
+ vec[0].iov_len = old_avail - avail;
+ evbuffer_commit_space(buf, vec, 1);
+
+ } while (!over);
+ check();
+ return 0;
+}
+#endif
+
+/** Set *<b>output</b> to contain a copy of the data in *<b>input</b> */
+int
+generic_buffer_set_to_copy(generic_buffer_t **output,
+ const generic_buffer_t *input)
+{
+#ifdef USE_BUFFEREVENTS
+ struct evbuffer_ptr ptr;
+ size_t remaining = evbuffer_get_length(input);
+ if (*output) {
+ evbuffer_drain(*output, evbuffer_get_length(*output));
+ } else {
+ if (!(*output = evbuffer_new()))
+ return -1;
+ }
+ evbuffer_ptr_set((struct evbuffer*)input, &ptr, 0, EVBUFFER_PTR_SET);
+ while (remaining) {
+ struct evbuffer_iovec v[4];
+ int n_used, i;
+ n_used = evbuffer_peek((struct evbuffer*)input, -1, &ptr, v, 4);
+ if (n_used < 0)
+ return -1;
+ for (i=0;i<n_used;++i) {
+ evbuffer_add(*output, v[i].iov_base, v[i].iov_len);
+ tor_assert(v[i].iov_len <= remaining);
+ remaining -= v[i].iov_len;
+ evbuffer_ptr_set((struct evbuffer*)input,
+ &ptr, v[i].iov_len, EVBUFFER_PTR_ADD);
+ }
+ }
+#else
+ if (*output)
+ buf_free(*output);
+ *output = buf_copy(input);
+#endif
+ return 0;
+}
+
/** Log an error and exit if <b>buf</b> is corrupted.
*/
void
diff --git a/src/or/buffers.h b/src/or/buffers.h
index 63fab4957..7b2a2acc3 100644
--- a/src/or/buffers.h
+++ b/src/or/buffers.h
@@ -16,6 +16,7 @@ buf_t *buf_new(void);
buf_t *buf_new_with_capacity(size_t size);
void buf_free(buf_t *buf);
void buf_clear(buf_t *buf);
+buf_t *buf_copy(const buf_t *buf);
void buf_shrink(buf_t *buf);
void buf_shrink_freelists(int free_all);
void buf_dump_freelist_sizes(int severity);
@@ -41,6 +42,8 @@ int fetch_from_buf_http(buf_t *buf,
char **headers_out, size_t max_headerlen,
char **body_out, size_t *body_used, size_t max_bodylen,
int force_complete);
+socks_request_t *socks_request_new(void);
+void socks_request_free(socks_request_t *req);
int fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
int log_sockstype, int safe_socks);
int fetch_from_buf_socks_client(buf_t *buf, int state, char **reason);
@@ -48,6 +51,41 @@ int fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len);
int peek_buf_has_control0_command(buf_t *buf);
+#ifdef USE_BUFFEREVENTS
+int fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out,
+ int linkproto);
+int fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req,
+ int log_sockstype, int safe_socks);
+int fetch_from_evbuffer_socks_client(struct evbuffer *buf, int state,
+ char **reason);
+int fetch_from_evbuffer_http(struct evbuffer *buf,
+ char **headers_out, size_t max_headerlen,
+ char **body_out, size_t *body_used, size_t max_bodylen,
+ int force_complete);
+int peek_evbuffer_has_control0_command(struct evbuffer *buf);
+int write_to_evbuffer_zlib(struct evbuffer *buf, tor_zlib_state_t *state,
+ const char *data, size_t data_len,
+ int done);
+#endif
+
+#ifdef USE_BUFFEREVENTS
+#define generic_buffer_new() evbuffer_new()
+#define generic_buffer_len(b) evbuffer_get_length((b))
+#define generic_buffer_add(b,dat,len) evbuffer_add((b),(dat),(len))
+#define generic_buffer_get(b,buf,buflen) evbuffer_remove((b),(buf),(buflen))
+#define generic_buffer_clear(b) evbuffer_drain((b), evbuffer_get_length((b)))
+#define generic_buffer_free(b) evbuffer_free((b))
+#else
+#define generic_buffer_new() buf_new()
+#define generic_buffer_len(b) buf_datalen((b))
+#define generic_buffer_add(b,dat,len) write_to_buf((dat),(len),(b))
+#define generic_buffer_get(b,buf,buflen) fetch_from_buf((buf),(buflen),(b))
+#define generic_buffer_clear(b) buf_clear((b))
+#define generic_buffer_free(b) buf_free((b))
+#endif
+int generic_buffer_set_to_copy(generic_buffer_t **output,
+ const generic_buffer_t *input);
+
void assert_buf_ok(buf_t *buf);
#ifdef BUFFERS_PRIVATE
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index a63e89b12..c4b697c9a 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -23,8 +23,10 @@
#include "directory.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "onion.h"
#include "policies.h"
+#include "transports.h"
#include "relay.h"
#include "rephist.h"
#include "router.h"
@@ -55,8 +57,8 @@ extern circuit_t *global_circuitlist;
/** An entry_guard_t represents our information about a chosen long-term
* first hop, known as a "helper" node in the literature. We can't just
- * use a routerinfo_t, since we want to remember these even when we
- * don't have a directory. */
+ * use a node_t, since we want to remember these even when we
+ * don't have any directory info. */
typedef struct {
char nickname[MAX_NICKNAME_LEN+1];
char identity[DIGEST_LEN];
@@ -78,6 +80,28 @@ typedef struct {
* at which we last failed to connect to it. */
} entry_guard_t;
+/** Information about a configured bridge. Currently this just matches the
+ * ones in the torrc file, but one day we may be able to learn about new
+ * bridges on our own, and remember them in the state file. */
+typedef struct {
+ /** Address of the bridge. */
+ tor_addr_t addr;
+ /** TLS port for the bridge. */
+ uint16_t port;
+ /** Boolean: We are re-parsing our bridge list, and we are going to remove
+ * this one if we don't find it in the list of configured bridges. */
+ unsigned marked_for_removal : 1;
+ /** Expected identity digest, or all zero bytes if we don't know what the
+ * digest should be. */
+ char identity[DIGEST_LEN];
+
+ /** Name of pluggable transport protocol taken from its config line. */
+ char *transport_name;
+
+ /** When should we next try to fetch a descriptor for this bridge? */
+ download_status_t fetch_status;
+} bridge_info_t;
+
/** A list of our chosen entry guards. */
static smartlist_t *entry_guards = NULL;
/** A value of 1 means that the entry_guards list has changed
@@ -95,11 +119,13 @@ static int circuit_deliver_create_cell(circuit_t *circ,
static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit);
static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath);
static int onion_extend_cpath(origin_circuit_t *circ);
-static int count_acceptable_routers(smartlist_t *routers);
+static int count_acceptable_nodes(smartlist_t *routers);
static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice);
static void entry_guards_changed(void);
+static void bridge_free(bridge_info_t *bridge);
+
/**
* This function decides if CBT learning should be disabled. It returns
* true if one or more of the following four conditions are met:
@@ -1237,7 +1263,7 @@ circuit_build_times_network_check_changed(circuit_build_times_t *cbt)
if (cbt->timeout_ms >= circuit_build_times_get_initial_timeout()) {
if (cbt->timeout_ms > INT32_MAX/2 || cbt->close_ms > INT32_MAX/2) {
log_warn(LD_CIRC, "Insanely large circuit build timeout value. "
- "(timeout = %lfmsec, close = %lfmsec)",
+ "(timeout = %fmsec, close = %fmsec)",
cbt->timeout_ms, cbt->close_ms);
} else {
cbt->timeout_ms *= 2;
@@ -1381,7 +1407,7 @@ circuit_build_times_set_timeout_worker(circuit_build_times_t *cbt)
cbt->close_ms = MAX(cbt->close_ms, circuit_build_times_initial_timeout());
if (cbt->timeout_ms > max_time) {
- log_notice(LD_CIRC,
+ log_info(LD_CIRC,
"Circuit build timeout of %dms is beyond the maximum build "
"time we have ever observed. Capping it to %dms.",
(int)cbt->timeout_ms, max_time);
@@ -1414,7 +1440,7 @@ circuit_build_times_set_timeout(circuit_build_times_t *cbt)
return;
if (cbt->timeout_ms < circuit_build_times_min_timeout()) {
- log_warn(LD_CIRC, "Set buildtimeout to low value %lfms. Setting to %dms",
+ log_warn(LD_CIRC, "Set buildtimeout to low value %fms. Setting to %dms",
cbt->timeout_ms, circuit_build_times_min_timeout());
cbt->timeout_ms = circuit_build_times_min_timeout();
if (cbt->close_ms < cbt->timeout_ms) {
@@ -1429,31 +1455,31 @@ circuit_build_times_set_timeout(circuit_build_times_t *cbt)
timeout_rate = circuit_build_times_timeout_rate(cbt);
if (prev_timeout > tor_lround(cbt->timeout_ms/1000)) {
- log_notice(LD_CIRC,
+ log_info(LD_CIRC,
"Based on %d circuit times, it looks like we don't need to "
"wait so long for circuits to finish. We will now assume a "
"circuit is too slow to use after waiting %ld seconds.",
cbt->total_build_times,
tor_lround(cbt->timeout_ms/1000));
log_info(LD_CIRC,
- "Circuit timeout data: %lfms, %lfms, Xm: %d, a: %lf, r: %lf",
+ "Circuit timeout data: %fms, %fms, Xm: %d, a: %f, r: %f",
cbt->timeout_ms, cbt->close_ms, cbt->Xm, cbt->alpha,
timeout_rate);
} else if (prev_timeout < tor_lround(cbt->timeout_ms/1000)) {
- log_notice(LD_CIRC,
+ log_info(LD_CIRC,
"Based on %d circuit times, it looks like we need to wait "
"longer for circuits to finish. We will now assume a "
"circuit is too slow to use after waiting %ld seconds.",
cbt->total_build_times,
tor_lround(cbt->timeout_ms/1000));
log_info(LD_CIRC,
- "Circuit timeout data: %lfms, %lfms, Xm: %d, a: %lf, r: %lf",
+ "Circuit timeout data: %fms, %fms, Xm: %d, a: %f, r: %f",
cbt->timeout_ms, cbt->close_ms, cbt->Xm, cbt->alpha,
timeout_rate);
} else {
log_info(LD_CIRC,
- "Set circuit build timeout to %lds (%lfms, %lfms, Xm: %d, a: %lf,"
- " r: %lf) based on %d circuit times",
+ "Set circuit build timeout to %lds (%fms, %fms, Xm: %d, a: %f,"
+ " r: %f) based on %d circuit times",
tor_lround(cbt->timeout_ms/1000),
cbt->timeout_ms, cbt->close_ms, cbt->Xm, cbt->alpha, timeout_rate,
cbt->total_build_times);
@@ -1532,10 +1558,9 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names)
hop = circ->cpath;
do {
- routerinfo_t *ri;
- routerstatus_t *rs;
char *elt;
const char *id;
+ const node_t *node;
if (!hop)
break;
if (!verbose && hop->state != CPATH_STATE_OPEN)
@@ -1545,10 +1570,8 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names)
id = hop->extend_info->identity_digest;
if (verbose_names) {
elt = tor_malloc(MAX_VERBOSE_NICKNAME_LEN+1);
- if ((ri = router_get_by_digest(id))) {
- router_get_verbose_nickname(elt, ri);
- } else if ((rs = router_get_consensus_status_by_id(id))) {
- routerstatus_get_verbose_nickname(elt, rs);
+ if ((node = node_get_by_id(id))) {
+ node_get_verbose_nickname(node, elt);
} else if (is_legal_nickname(hop->extend_info->nickname)) {
elt[0] = '$';
base16_encode(elt+1, HEX_DIGEST_LEN+1, id, DIGEST_LEN);
@@ -1560,9 +1583,9 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names)
base16_encode(elt+1, HEX_DIGEST_LEN+1, id, DIGEST_LEN);
}
} else { /* ! verbose_names */
- if ((ri = router_get_by_digest(id)) &&
- ri->is_named) {
- elt = tor_strdup(hop->extend_info->nickname);
+ node = node_get_by_id(id);
+ if (node && node_is_named(node)) {
+ elt = tor_strdup(node_get_nickname(node));
} else {
elt = tor_malloc(HEX_DIGEST_LEN+2);
elt[0] = '$';
@@ -1631,31 +1654,28 @@ void
circuit_rep_hist_note_result(origin_circuit_t *circ)
{
crypt_path_t *hop;
- char *prev_digest = NULL;
- routerinfo_t *router;
+ const char *prev_digest = NULL;
hop = circ->cpath;
if (!hop) /* circuit hasn't started building yet. */
return;
if (server_mode(get_options())) {
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!me)
return;
prev_digest = me->cache_info.identity_digest;
}
do {
- router = router_get_by_digest(hop->extend_info->identity_digest);
- if (router) {
+ const node_t *node = node_get_by_id(hop->extend_info->identity_digest);
+ if (node) { /* Why do we check this? We know the identity. -NM XXXX */
if (prev_digest) {
if (hop->state == CPATH_STATE_OPEN)
- rep_hist_note_extend_succeeded(prev_digest,
- router->cache_info.identity_digest);
+ rep_hist_note_extend_succeeded(prev_digest, node->identity);
else {
- rep_hist_note_extend_failed(prev_digest,
- router->cache_info.identity_digest);
+ rep_hist_note_extend_failed(prev_digest, node->identity);
break;
}
}
- prev_digest = router->cache_info.identity_digest;
+ prev_digest = node->identity;
} else {
prev_digest = NULL;
}
@@ -1924,7 +1944,7 @@ int
inform_testing_reachability(void)
{
char dirbuf[128];
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!me)
return 0;
control_event_server_status(LOG_NOTICE,
@@ -1953,7 +1973,7 @@ inform_testing_reachability(void)
static INLINE int
should_use_create_fast_for_circuit(origin_circuit_t *circ)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert(circ->cpath);
tor_assert(circ->cpath->extend_info);
@@ -1961,9 +1981,10 @@ should_use_create_fast_for_circuit(origin_circuit_t *circ)
return 1; /* our hand is forced: only a create_fast will work. */
if (!options->FastFirstHopPK)
return 0; /* we prefer to avoid create_fast */
- if (server_mode(options)) {
+ if (public_server_mode(options)) {
/* We're a server, and we know an onion key. We can choose.
- * Prefer to blend in. */
+ * Prefer to blend our circuit into the other circuits we are
+ * creating on behalf of others. */
return 0;
}
@@ -1996,7 +2017,7 @@ int
circuit_send_next_onion_skin(origin_circuit_t *circ)
{
crypt_path_t *hop;
- routerinfo_t *router;
+ const node_t *node;
char payload[2+4+DIGEST_LEN+ONIONSKIN_CHALLENGE_LEN];
char *onionskin;
size_t payload_len;
@@ -2012,7 +2033,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
else
control_event_bootstrap(BOOTSTRAP_STATUS_CIRCUIT_CREATE, 0);
- router = router_get_by_digest(circ->_base.n_conn->identity_digest);
+ node = node_get_by_id(circ->_base.n_conn->identity_digest);
fast = should_use_create_fast_for_circuit(circ);
if (!fast) {
/* We are an OR and we know the right onion key: we should
@@ -2046,7 +2067,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING);
log_info(LD_CIRC,"First hop: finished sending %s cell to '%s'",
fast ? "CREATE_FAST" : "CREATE",
- router ? router_describe(router) : "<unnamed>");
+ node ? node_describe(node) : "<unnamed>");
} else {
tor_assert(circ->cpath->state == CPATH_STATE_OPEN);
tor_assert(circ->_base.state == CIRCUIT_STATE_BUILDING);
@@ -2088,7 +2109,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
if (circ->build_state->onehop_tunnel)
control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_STATUS, 0);
if (!can_complete_circuit && !circ->build_state->onehop_tunnel) {
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
can_complete_circuit=1;
/* FFFF Log a count of known routers here */
log_notice(LD_GENERAL,
@@ -2096,6 +2117,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
"Looks like client functionality is working.");
control_event_bootstrap(BOOTSTRAP_STATUS_DONE, 0);
control_event_client_status(LOG_NOTICE, "CIRCUIT_ESTABLISHED");
+ clear_broken_connection_map(1);
if (server_mode(options) && !check_whether_orport_reachable()) {
inform_testing_reachability();
consider_testing_reachability(1, 1);
@@ -2523,12 +2545,12 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload,
*/
static int
new_route_len(uint8_t purpose, extend_info_t *exit,
- smartlist_t *routers)
+ smartlist_t *nodes)
{
int num_acceptable_routers;
int routelen;
- tor_assert(routers);
+ tor_assert(nodes);
routelen = DEFAULT_ROUTE_LEN;
if (exit &&
@@ -2536,10 +2558,10 @@ new_route_len(uint8_t purpose, extend_info_t *exit,
purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO)
routelen++;
- num_acceptable_routers = count_acceptable_routers(routers);
+ num_acceptable_routers = count_acceptable_nodes(nodes);
log_debug(LD_CIRC,"Chosen route length %d (%d/%d routers suitable).",
- routelen, num_acceptable_routers, smartlist_len(routers));
+ routelen, num_acceptable_routers, smartlist_len(nodes));
if (num_acceptable_routers < 2) {
log_info(LD_CIRC,
@@ -2557,24 +2579,12 @@ new_route_len(uint8_t purpose, extend_info_t *exit,
return routelen;
}
-/** Fetch the list of predicted ports, dup it into a smartlist of
- * uint16_t's, remove the ones that are already handled by an
- * existing circuit, and return it.
- */
+/** Return a newly allocated list of uint16_t * for each predicted port not
+ * handled by a current circuit. */
static smartlist_t *
circuit_get_unhandled_ports(time_t now)
{
- smartlist_t *source = rep_hist_get_predicted_ports(now);
- smartlist_t *dest = smartlist_create();
- uint16_t *tmp;
- int i;
-
- for (i = 0; i < smartlist_len(source); ++i) {
- tmp = tor_malloc(sizeof(uint16_t));
- memcpy(tmp, smartlist_get(source, i), sizeof(uint16_t));
- smartlist_add(dest, tmp);
- }
-
+ smartlist_t *dest = rep_hist_get_predicted_ports(now);
circuit_remove_handled_ports(dest);
return dest;
}
@@ -2608,12 +2618,12 @@ circuit_all_predicted_ports_handled(time_t now, int *need_uptime,
return enough;
}
-/** Return 1 if <b>router</b> can handle one or more of the ports in
+/** Return 1 if <b>node</b> can handle one or more of the ports in
* <b>needed_ports</b>, else return 0.
*/
static int
-router_handles_some_port(routerinfo_t *router, smartlist_t *needed_ports)
-{
+node_handles_some_port(const node_t *node, smartlist_t *needed_ports)
+{ /* XXXX MOVE */
int i;
uint16_t port;
@@ -2623,7 +2633,10 @@ router_handles_some_port(routerinfo_t *router, smartlist_t *needed_ports)
needed_ports is explicitly a smartlist of uint16_t's */
port = *(uint16_t *)smartlist_get(needed_ports, i);
tor_assert(port);
- r = compare_addr_to_addr_policy(0, port, router->exit_policy);
+ if (node)
+ r = compare_tor_addr_to_node_policy(NULL, port, node);
+ else
+ continue;
if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED)
return 1;
}
@@ -2635,14 +2648,18 @@ router_handles_some_port(routerinfo_t *router, smartlist_t *needed_ports)
static int
ap_stream_wants_exit_attention(connection_t *conn)
{
- if (conn->type == CONN_TYPE_AP &&
- conn->state == AP_CONN_STATE_CIRCUIT_WAIT &&
+ entry_connection_t *entry;
+ if (conn->type != CONN_TYPE_AP)
+ return 0;
+ entry = TO_ENTRY_CONN(conn);
+
+ if (conn->state == AP_CONN_STATE_CIRCUIT_WAIT &&
!conn->marked_for_close &&
- !(TO_EDGE_CONN(conn)->want_onehop) && /* ignore one-hop streams */
- !(TO_EDGE_CONN(conn)->use_begindir) && /* ignore targeted dir fetches */
- !(TO_EDGE_CONN(conn)->chosen_exit_name) && /* ignore defined streams */
+ !(entry->want_onehop) && /* ignore one-hop streams */
+ !(entry->use_begindir) && /* ignore targeted dir fetches */
+ !(entry->chosen_exit_name) && /* ignore defined streams */
!connection_edge_is_rendezvous_stream(TO_EDGE_CONN(conn)) &&
- !circuit_stream_is_being_handled(TO_EDGE_CONN(conn), 0,
+ !circuit_stream_is_being_handled(TO_ENTRY_CONN(conn), 0,
MIN_CIRCUITS_HANDLING_STREAM))
return 1;
return 0;
@@ -2656,18 +2673,17 @@ ap_stream_wants_exit_attention(connection_t *conn)
*
* Return NULL if we can't find any suitable routers.
*/
-static routerinfo_t *
-choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
- int need_capacity)
+static const node_t *
+choose_good_exit_server_general(int need_uptime, int need_capacity)
{
int *n_supported;
- int i;
int n_pending_connections = 0;
smartlist_t *connections;
int best_support = -1;
int n_best_support=0;
- routerinfo_t *router;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
+ const smartlist_t *the_nodes;
+ const node_t *node=NULL;
connections = get_connection_array();
@@ -2688,10 +2704,11 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
*
* -1 means "Don't use this router at all."
*/
- n_supported = tor_malloc(sizeof(int)*smartlist_len(dir->routers));
- for (i = 0; i < smartlist_len(dir->routers); ++i) {/* iterate over routers */
- router = smartlist_get(dir->routers, i);
- if (router_is_me(router)) {
+ the_nodes = nodelist_get_list();
+ n_supported = tor_malloc(sizeof(int)*smartlist_len(the_nodes));
+ SMARTLIST_FOREACH_BEGIN(the_nodes, const node_t *, node) {
+ const int i = node_sl_idx;
+ if (router_digest_is_me(node->identity)) {
n_supported[i] = -1;
// log_fn(LOG_DEBUG,"Skipping node %s -- it's me.", router->nickname);
/* XXX there's probably a reverse predecessor attack here, but
@@ -2699,41 +2716,44 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
*/
continue;
}
- if (!router->is_running || router->is_bad_exit) {
+ if (!node_has_descriptor(node)) {
+ n_supported[i] = -1;
+ continue;
+ }
+ if (!node->is_running || node->is_bad_exit) {
n_supported[i] = -1;
continue; /* skip routers that are known to be down or bad exits */
}
-
- if (options->_ExcludeExitNodesUnion &&
- routerset_contains_router(options->_ExcludeExitNodesUnion, router)) {
+ if (routerset_contains_node(options->_ExcludeExitNodesUnion, node)) {
n_supported[i] = -1;
continue; /* user asked us not to use it, no matter what */
}
if (options->ExitNodes &&
- !routerset_contains_router(options->ExitNodes, router)) {
+ !routerset_contains_node(options->ExitNodes, node)) {
n_supported[i] = -1;
continue; /* not one of our chosen exit nodes */
}
- if (router_is_unreliable(router, need_uptime, need_capacity, 0)) {
+ if (node_is_unreliable(node, need_uptime, need_capacity, 0)) {
n_supported[i] = -1;
continue; /* skip routers that are not suitable. Don't worry if
* this makes us reject all the possible routers: if so,
* we'll retry later in this function with need_update and
* need_capacity set to 0. */
}
- if (!(router->is_valid || options->_AllowInvalid & ALLOW_INVALID_EXIT)) {
+ if (!(node->is_valid || options->_AllowInvalid & ALLOW_INVALID_EXIT)) {
/* if it's invalid and we don't want it */
n_supported[i] = -1;
// log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- invalid router.",
// router->nickname, i);
continue; /* skip invalid routers */
}
- if (options->ExcludeSingleHopRelays && router->allow_single_hop_exits) {
+ if (options->ExcludeSingleHopRelays &&
+ node_allows_single_hop_exits(node)) {
n_supported[i] = -1;
continue;
}
- if (router_exit_policy_rejects_all(router)) {
+ if (node_exit_policy_rejects_all(node)) {
n_supported[i] = -1;
// log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- it rejects all.",
// router->nickname, i);
@@ -2741,11 +2761,10 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
}
n_supported[i] = 0;
/* iterate over connections */
- SMARTLIST_FOREACH(connections, connection_t *, conn,
- {
+ SMARTLIST_FOREACH_BEGIN(connections, connection_t *, conn) {
if (!ap_stream_wants_exit_attention(conn))
continue; /* Skip everything but APs in CIRCUIT_WAIT */
- if (connection_ap_can_use_exit(TO_EDGE_CONN(conn), router)) {
+ if (connection_ap_can_use_exit(TO_ENTRY_CONN(conn), node)) {
++n_supported[i];
// log_fn(LOG_DEBUG,"%s is supported. n_supported[%d] now %d.",
// router->nickname, i, n_supported[i]);
@@ -2753,7 +2772,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
// log_fn(LOG_DEBUG,"%s (index %d) would reject this stream.",
// router->nickname, i);
}
- }); /* End looping over connections. */
+ } SMARTLIST_FOREACH_END(conn);
if (n_pending_connections > 0 && n_supported[i] == 0) {
/* Leave best_support at -1 if that's where it is, so we can
* distinguish it later. */
@@ -2770,7 +2789,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
* count of equally good routers.*/
++n_best_support;
}
- }
+ } SMARTLIST_FOREACH_END(node);
log_info(LD_CIRC,
"Found %d servers that might support %d/%d pending connections.",
n_best_support, best_support >= 0 ? best_support : 0,
@@ -2781,11 +2800,12 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
if (best_support > 0) {
smartlist_t *supporting = smartlist_create();
- for (i = 0; i < smartlist_len(dir->routers); i++)
- if (n_supported[i] == best_support)
- smartlist_add(supporting, smartlist_get(dir->routers, i));
+ SMARTLIST_FOREACH(the_nodes, const node_t *, node, {
+ if (n_supported[node_sl_idx] == best_support)
+ smartlist_add(supporting, (void*)node);
+ });
- router = routerlist_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
+ node = node_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
smartlist_free(supporting);
} else {
/* Either there are no pending connections, or no routers even seem to
@@ -2803,7 +2823,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
need_capacity?", fast":"",
need_uptime?", stable":"");
tor_free(n_supported);
- return choose_good_exit_server_general(dir, 0, 0);
+ return choose_good_exit_server_general(0, 0);
}
log_notice(LD_CIRC, "All routers are down or won't exit%s -- "
"choosing a doomed exit at random.",
@@ -2814,18 +2834,17 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
for (attempt = 0; attempt < 2; attempt++) {
/* try once to pick only from routers that satisfy a needed port,
* then if there are none, pick from any that support exiting. */
- for (i = 0; i < smartlist_len(dir->routers); i++) {
- router = smartlist_get(dir->routers, i);
- if (n_supported[i] != -1 &&
- (attempt || router_handles_some_port(router, needed_ports))) {
+ SMARTLIST_FOREACH_BEGIN(the_nodes, const node_t *, node) {
+ if (n_supported[node_sl_idx] != -1 &&
+ (attempt || node_handles_some_port(node, needed_ports))) {
// log_fn(LOG_DEBUG,"Try %d: '%s' is a possibility.",
// try, router->nickname);
- smartlist_add(supporting, router);
+ smartlist_add(supporting, (void*)node);
}
- }
+ } SMARTLIST_FOREACH_END(node);
- router = routerlist_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
- if (router)
+ node = node_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT);
+ if (node)
break;
smartlist_clear(supporting);
}
@@ -2835,9 +2854,9 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
}
tor_free(n_supported);
- if (router) {
- log_info(LD_CIRC, "Chose exit server '%s'", router_describe(router));
- return router;
+ if (node) {
+ log_info(LD_CIRC, "Chose exit server '%s'", node_describe(node));
+ return node;
}
if (options->ExitNodes) {
log_warn(LD_CIRC,
@@ -2858,12 +2877,12 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime,
* For client-side rendezvous circuits, choose a random node, weighted
* toward the preferences in 'options'.
*/
-static routerinfo_t *
-choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
+static const node_t *
+choose_good_exit_server(uint8_t purpose,
int need_uptime, int need_capacity, int is_internal)
{
- or_options_t *options = get_options();
- router_crn_flags_t flags = 0;
+ const or_options_t *options = get_options();
+ router_crn_flags_t flags = CRN_NEED_DESC;
if (need_uptime)
flags |= CRN_NEED_UPTIME;
if (need_capacity)
@@ -2876,7 +2895,7 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
if (is_internal) /* pick it like a middle hop */
return router_choose_random_node(NULL, options->ExcludeNodes, flags);
else
- return choose_good_exit_server_general(dir,need_uptime,need_capacity);
+ return choose_good_exit_server_general(need_uptime,need_capacity);
case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
if (options->_AllowInvalid & ALLOW_INVALID_RENDEZVOUS)
flags |= CRN_ALLOW_INVALID;
@@ -2892,7 +2911,7 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir,
static void
warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
routerset_t *rs = options->ExcludeNodes;
const char *description;
uint8_t purpose = circ->_base.purpose;
@@ -2969,13 +2988,12 @@ static int
onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
{
cpath_build_state_t *state = circ->build_state;
- routerlist_t *rl = router_get_routerlist();
if (state->onehop_tunnel) {
log_debug(LD_CIRC, "Launching a one-hop circuit for dir tunnel.");
state->desired_path_len = 1;
} else {
- int r = new_route_len(circ->_base.purpose, exit, rl->routers);
+ int r = new_route_len(circ->_base.purpose, exit, nodelist_get_list());
if (r < 1) /* must be at least 1 */
return -1;
state->desired_path_len = r;
@@ -2987,14 +3005,15 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit)
extend_info_describe(exit));
exit = extend_info_dup(exit);
} else { /* we have to decide one */
- routerinfo_t *router =
- choose_good_exit_server(circ->_base.purpose, rl, state->need_uptime,
+ const node_t *node =
+ choose_good_exit_server(circ->_base.purpose, state->need_uptime,
state->need_capacity, state->is_internal);
- if (!router) {
+ if (!node) {
log_warn(LD_CIRC,"failed to choose an exit server");
return -1;
}
- exit = extend_info_from_router(router);
+ exit = extend_info_from_node(node);
+ tor_assert(exit);
}
state->chosen_exit = exit;
return 0;
@@ -3045,35 +3064,30 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit)
* and available for building circuits through.
*/
static int
-count_acceptable_routers(smartlist_t *routers)
+count_acceptable_nodes(smartlist_t *nodes)
{
- int i, n;
int num=0;
- routerinfo_t *r;
- n = smartlist_len(routers);
- for (i=0;i<n;i++) {
- r = smartlist_get(routers, i);
-// log_debug(LD_CIRC,
+ SMARTLIST_FOREACH_BEGIN(nodes, const node_t *, node) {
+ // log_debug(LD_CIRC,
// "Contemplating whether router %d (%s) is a new option.",
// i, r->nickname);
- if (r->is_running == 0) {
+ if (! node->is_running)
// log_debug(LD_CIRC,"Nope, the directory says %d is not running.",i);
- goto next_i_loop;
- }
- if (r->is_valid == 0) {
+ continue;
+ if (! node->is_valid)
// log_debug(LD_CIRC,"Nope, the directory says %d is not valid.",i);
- goto next_i_loop;
+ continue;
+ if (! node_has_descriptor(node))
+ continue;
/* XXX This clause makes us count incorrectly: if AllowInvalidRouters
* allows this node in some places, then we're getting an inaccurate
* count. For now, be conservative and don't count it. But later we
* should try to be smarter. */
- }
- num++;
+ ++num;
+ } SMARTLIST_FOREACH_END(node);
+
// log_debug(LD_CIRC,"I like %d. num_acceptable_routers now %d.",i, num);
- next_i_loop:
- ; /* C requires an explicit statement after the label */
- }
return num;
}
@@ -3101,31 +3115,29 @@ onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop)
* circuit. In particular, make sure we don't pick the exit node or its
* family, and make sure we don't duplicate any previous nodes or their
* families. */
-static routerinfo_t *
+static const node_t *
choose_good_middle_server(uint8_t purpose,
cpath_build_state_t *state,
crypt_path_t *head,
int cur_len)
{
int i;
- routerinfo_t *r, *choice;
+ const node_t *r, *choice;
crypt_path_t *cpath;
smartlist_t *excluded;
- or_options_t *options = get_options();
- router_crn_flags_t flags = 0;
+ const or_options_t *options = get_options();
+ router_crn_flags_t flags = CRN_NEED_DESC;
tor_assert(_CIRCUIT_PURPOSE_MIN <= purpose &&
purpose <= _CIRCUIT_PURPOSE_MAX);
log_debug(LD_CIRC, "Contemplating intermediate hop: random choice.");
excluded = smartlist_create();
- if ((r = build_state_get_exit_router(state))) {
- smartlist_add(excluded, r);
- routerlist_add_family(excluded, r);
+ if ((r = build_state_get_exit_node(state))) {
+ nodelist_add_node_and_family(excluded, r);
}
for (i = 0, cpath = head; i < cur_len; ++i, cpath=cpath->next) {
- if ((r = router_get_by_digest(cpath->extend_info->identity_digest))) {
- smartlist_add(excluded, r);
- routerlist_add_family(excluded, r);
+ if ((r = node_get_by_id(cpath->extend_info->identity_digest))) {
+ nodelist_add_node_and_family(excluded, r);
}
}
@@ -3148,44 +3160,43 @@ choose_good_middle_server(uint8_t purpose,
* If <b>state</b> is NULL, we're choosing a router to serve as an entry
* guard, not for any particular circuit.
*/
-static routerinfo_t *
+static const node_t *
choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state)
{
- routerinfo_t *r, *choice;
+ const node_t *choice;
smartlist_t *excluded;
- or_options_t *options = get_options();
- router_crn_flags_t flags = CRN_NEED_GUARD;
+ const or_options_t *options = get_options();
+ router_crn_flags_t flags = CRN_NEED_GUARD|CRN_NEED_DESC;
+ const node_t *node;
if (state && options->UseEntryGuards &&
(purpose != CIRCUIT_PURPOSE_TESTING || options->BridgeRelay)) {
+ /* This is request for an entry server to use for a regular circuit,
+ * and we use entry guard nodes. Just return one of the guard nodes. */
return choose_random_entry(state);
}
excluded = smartlist_create();
- if (state && (r = build_state_get_exit_router(state))) {
- smartlist_add(excluded, r);
- routerlist_add_family(excluded, r);
+ if (state && (node = build_state_get_exit_node(state))) {
+ /* Exclude the exit node from the state, if we have one. Also exclude its
+ * family. */
+ nodelist_add_node_and_family(excluded, node);
}
if (firewall_is_fascist_or()) {
- /*XXXX This could slow things down a lot; use a smarter implementation */
- /* exclude all ORs that listen on the wrong port, if anybody notices. */
- routerlist_t *rl = router_get_routerlist();
- int i;
-
- for (i=0; i < smartlist_len(rl->routers); i++) {
- r = smartlist_get(rl->routers, i);
- if (!fascist_firewall_allows_or(r))
- smartlist_add(excluded, r);
- }
+ /* Exclude all ORs that we can't reach through our firewall */
+ smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, const node_t *, node, {
+ if (!fascist_firewall_allows_node(node))
+ smartlist_add(excluded, (void*)node);
+ });
}
- /* and exclude current entry guards, if applicable */
+ /* and exclude current entry guards and their families, if applicable */
if (options->UseEntryGuards && entry_guards) {
SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry,
{
- if ((r = router_get_by_digest(entry->identity))) {
- smartlist_add(excluded, r);
- routerlist_add_family(excluded, r);
+ if ((node = node_get_by_id(entry->identity))) {
+ nodelist_add_node_and_family(excluded, node);
}
});
}
@@ -3241,14 +3252,18 @@ onion_extend_cpath(origin_circuit_t *circ)
if (cur_len == state->desired_path_len - 1) { /* Picking last node */
info = extend_info_dup(state->chosen_exit);
} else if (cur_len == 0) { /* picking first node */
- routerinfo_t *r = choose_good_entry_server(purpose, state);
- if (r)
- info = extend_info_from_router(r);
+ const node_t *r = choose_good_entry_server(purpose, state);
+ if (r) {
+ info = extend_info_from_node(r);
+ tor_assert(info);
+ }
} else {
- routerinfo_t *r =
+ const node_t *r =
choose_good_middle_server(purpose, state, circ->cpath, cur_len);
- if (r)
- info = extend_info_from_router(r);
+ if (r) {
+ info = extend_info_from_node(r);
+ tor_assert(info);
+ }
}
if (!info) {
@@ -3308,7 +3323,7 @@ extend_info_alloc(const char *nickname, const char *digest,
/** Allocate and return a new extend_info_t that can be used to build a
* circuit to or through the router <b>r</b>. */
extend_info_t *
-extend_info_from_router(routerinfo_t *r)
+extend_info_from_router(const routerinfo_t *r)
{
tor_addr_t addr;
tor_assert(r);
@@ -3317,6 +3332,29 @@ extend_info_from_router(routerinfo_t *r)
r->onion_pkey, &addr, r->or_port);
}
+/** Allocate and return a new extend_info that can be used to build a ircuit
+ * to or through the node <b>node</b>. May return NULL if there is not
+ * enough info about <b>node</b> to extend to it--for example, if there
+ * is no routerinfo_t or microdesc_t.
+ **/
+extend_info_t *
+extend_info_from_node(const node_t *node)
+{
+ if (node->ri) {
+ return extend_info_from_router(node->ri);
+ } else if (node->rs && node->md) {
+ tor_addr_t addr;
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+ return extend_info_alloc(node->rs->nickname,
+ node->identity,
+ node->md->onion_pkey,
+ &addr,
+ node->rs->or_port);
+ } else {
+ return NULL;
+ }
+}
+
/** Release storage held by an extend_info_t struct. */
void
extend_info_free(extend_info_t *info)
@@ -3347,12 +3385,12 @@ extend_info_dup(extend_info_t *info)
* If there is no chosen exit, or if we don't know the routerinfo_t for
* the chosen exit, return NULL.
*/
-routerinfo_t *
-build_state_get_exit_router(cpath_build_state_t *state)
+const node_t *
+build_state_get_exit_node(cpath_build_state_t *state)
{
if (!state || !state->chosen_exit)
return NULL;
- return router_get_by_digest(state->chosen_exit->identity_digest);
+ return node_get_by_id(state->chosen_exit->identity_digest);
}
/** Return the nickname for the chosen exit router in <b>state</b>. If
@@ -3374,10 +3412,10 @@ build_state_get_exit_nickname(cpath_build_state_t *state)
*
* If it's not usable, set *<b>reason</b> to a static string explaining why.
*/
-/*XXXX take a routerstatus, not a routerinfo. */
static int
-entry_guard_set_status(entry_guard_t *e, routerinfo_t *ri,
- time_t now, or_options_t *options, const char **reason)
+entry_guard_set_status(entry_guard_t *e, const node_t *node,
+ time_t now, const or_options_t *options,
+ const char **reason)
{
char buf[HEX_DIGEST_LEN+1];
int changed = 0;
@@ -3385,18 +3423,19 @@ entry_guard_set_status(entry_guard_t *e, routerinfo_t *ri,
*reason = NULL;
/* Do we want to mark this guard as bad? */
- if (!ri)
+ if (!node)
*reason = "unlisted";
- else if (!ri->is_running)
+ else if (!node->is_running)
*reason = "down";
- else if (options->UseBridges && ri->purpose != ROUTER_PURPOSE_BRIDGE)
+ else if (options->UseBridges && (!node->ri ||
+ node->ri->purpose != ROUTER_PURPOSE_BRIDGE))
*reason = "not a bridge";
- else if (options->UseBridges && !routerinfo_is_a_configured_bridge(ri))
+ else if (options->UseBridges && !node_is_a_configured_bridge(node))
*reason = "not a configured bridge";
- else if (!options->UseBridges && !ri->is_possible_guard &&
- !routerset_contains_router(options->EntryNodes,ri))
+ else if (!options->UseBridges && !node->is_possible_guard &&
+ !routerset_contains_node(options->EntryNodes,node))
*reason = "not recommended as a guard";
- else if (routerset_contains_router(options->ExcludeNodes, ri))
+ else if (routerset_contains_node(options->ExcludeNodes, node))
*reason = "excluded";
if (*reason && ! e->bad_since) {
@@ -3440,7 +3479,7 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now)
return now > (e->last_attempted + 36*60*60);
}
-/** Return the router corresponding to <b>e</b>, if <b>e</b> is
+/** Return the node corresponding to <b>e</b>, if <b>e</b> is
* working well enough that we are willing to use it as an entry
* right now. (Else return NULL.) In particular, it must be
* - Listed as either up or never yet contacted;
@@ -3454,12 +3493,12 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now)
*
* If the answer is no, set *<b>msg</b> to an explanation of why.
*/
-static INLINE routerinfo_t *
+static INLINE const node_t *
entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity,
int assume_reachable, const char **msg)
{
- routerinfo_t *r;
- or_options_t *options = get_options();
+ const node_t *node;
+ const or_options_t *options = get_options();
tor_assert(msg);
if (e->bad_since) {
@@ -3472,38 +3511,39 @@ entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity,
*msg = "unreachable";
return NULL;
}
- r = router_get_by_digest(e->identity);
- if (!r) {
+ node = node_get_by_id(e->identity);
+ if (!node || !node_has_descriptor(node)) {
*msg = "no descriptor";
return NULL;
}
- if (options->UseBridges) {
- if (r->purpose != ROUTER_PURPOSE_BRIDGE) {
+ if (get_options()->UseBridges) {
+ if (node_get_purpose(node) != ROUTER_PURPOSE_BRIDGE) {
*msg = "not a bridge";
return NULL;
}
- if (!routerinfo_is_a_configured_bridge(r)) {
+ if (!node_is_a_configured_bridge(node)) {
*msg = "not a configured bridge";
return NULL;
}
- } else if (r->purpose != ROUTER_PURPOSE_GENERAL) {
- *msg = "not general-purpose";
- return NULL;
+ } else { /* !get_options()->UseBridges */
+ if (node_get_purpose(node) != ROUTER_PURPOSE_GENERAL) {
+ *msg = "not general-purpose";
+ return NULL;
+ }
}
- if (options->EntryNodes &&
- routerset_contains_router(options->EntryNodes, r)) {
+ if (routerset_contains_node(options->EntryNodes, node)) {
/* they asked for it, they get it */
need_uptime = need_capacity = 0;
}
- if (router_is_unreliable(r, need_uptime, need_capacity, 0)) {
+ if (node_is_unreliable(node, need_uptime, need_capacity, 0)) {
*msg = "not fast/stable";
return NULL;
}
- if (!fascist_firewall_allows_or(r)) {
+ if (!fascist_firewall_allows_node(node)) {
*msg = "unreachable by config";
return NULL;
}
- return r;
+ return node;
}
/** Return the number of entry guards that we think are usable. */
@@ -3583,7 +3623,7 @@ control_event_guard_deferred(void)
#if 0
int n = 0;
const char *msg;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!entry_guards)
return;
SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry,
@@ -3605,15 +3645,15 @@ control_event_guard_deferred(void)
* If <b>chosen</b> is defined, use that one, and if it's not
* already in our entry_guards list, put it at the *beginning*.
* Else, put the one we pick at the end of the list. */
-static routerinfo_t *
-add_an_entry_guard(routerinfo_t *chosen, int reset_status)
+static const node_t *
+add_an_entry_guard(const node_t *chosen, int reset_status, int prepend)
{
- routerinfo_t *router;
+ const node_t *node;
entry_guard_t *entry;
if (chosen) {
- router = chosen;
- entry = is_an_entry_guard(router->cache_info.identity_digest);
+ node = chosen;
+ entry = is_an_entry_guard(node->identity);
if (entry) {
if (reset_status) {
entry->bad_since = 0;
@@ -3622,15 +3662,15 @@ add_an_entry_guard(routerinfo_t *chosen, int reset_status)
return NULL;
}
} else {
- router = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL);
- if (!router)
+ node = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL);
+ if (!node)
return NULL;
}
entry = tor_malloc_zero(sizeof(entry_guard_t));
- log_info(LD_CIRC, "Chose '%s' as new entry guard.",
- router_describe(router));
- strlcpy(entry->nickname, router->nickname, sizeof(entry->nickname));
- memcpy(entry->identity, router->cache_info.identity_digest, DIGEST_LEN);
+ log_info(LD_CIRC, "Chose %s as new entry guard.",
+ node_describe(node));
+ strlcpy(entry->nickname, node_get_nickname(node), sizeof(entry->nickname));
+ memcpy(entry->identity, node->identity, DIGEST_LEN);
/* Choose expiry time smudged over the past month. The goal here
* is to a) spread out when Tor clients rotate their guards, so they
* don't all select them on the same day, and b) avoid leaving a
@@ -3638,27 +3678,27 @@ add_an_entry_guard(routerinfo_t *chosen, int reset_status)
* this guard. For details, see the Jan 2010 or-dev thread. */
entry->chosen_on_date = time(NULL) - crypto_rand_int(3600*24*30);
entry->chosen_by_version = tor_strdup(VERSION);
- if (chosen) /* prepend */
+ if (prepend)
smartlist_insert(entry_guards, 0, entry);
- else /* append */
+ else
smartlist_add(entry_guards, entry);
control_event_guard(entry->nickname, entry->identity, "NEW");
control_event_guard_deferred();
log_entry_guards(LOG_INFO);
- return router;
+ return node;
}
/** If the use of entry guards is configured, choose more entry guards
* until we have enough in the list. */
static void
-pick_entry_guards(or_options_t *options)
+pick_entry_guards(const or_options_t *options)
{
int changed = 0;
tor_assert(entry_guards);
while (num_live_entry_guards() < options->NumEntryGuards) {
- if (!add_an_entry_guard(NULL, 0))
+ if (!add_an_entry_guard(NULL, 0, 0))
break;
changed = 1;
}
@@ -3784,7 +3824,7 @@ remove_dead_entry_guards(time_t now)
* think that things are unlisted.
*/
void
-entry_guards_compute_status(or_options_t *options, time_t now)
+entry_guards_compute_status(const or_options_t *options, time_t now)
{
int changed = 0;
digestmap_t *reasons;
@@ -3798,7 +3838,7 @@ entry_guards_compute_status(or_options_t *options, time_t now)
reasons = digestmap_new();
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry)
{
- routerinfo_t *r = router_get_by_digest(entry->identity);
+ const node_t *r = node_get_by_id(entry->identity);
const char *reason = NULL;
if (entry_guard_set_status(entry, r, now, options, &reason))
changed = 1;
@@ -3817,7 +3857,7 @@ entry_guards_compute_status(or_options_t *options, time_t now)
SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
const char *reason = digestmap_get(reasons, entry->identity);
const char *live_msg = "";
- routerinfo_t *r = entry_is_live(entry, 0, 1, 0, &live_msg);
+ const node_t *r = entry_is_live(entry, 0, 1, 0, &live_msg);
log_info(LD_CIRC, "Summary: Entry %s [%s] is %s, %s%s%s, and %s%s.",
entry->nickname,
hex_str(entry->identity, DIGEST_LEN),
@@ -3935,7 +3975,7 @@ entry_guard_register_connect_status(const char *digest, int succeeded,
break;
if (e->made_contact) {
const char *msg;
- routerinfo_t *r = entry_is_live(e, 0, 1, 1, &msg);
+ const node_t *r = entry_is_live(e, 0, 1, 1, &msg);
if (r && e->unreachable_since) {
refuse_conn = 1;
e->can_retry = 1;
@@ -3971,12 +4011,12 @@ entry_nodes_should_be_added(void)
should_add_entry_nodes = 1;
}
-/** Add all nodes in EntryNodes that aren't currently guard nodes to the list
- * of guard nodes, at the front. */
+/** Adjust the entry guards list so that it only contains entries from
+ * EntryNodes, adding new entries from EntryNodes to the list as needed. */
static void
-entry_guards_prepend_from_config(or_options_t *options)
+entry_guards_set_from_config(const or_options_t *options)
{
- smartlist_t *entry_routers, *entry_fps;
+ smartlist_t *entry_nodes, *worse_entry_nodes, *entry_fps;
smartlist_t *old_entry_guards_on_list, *old_entry_guards_not_on_list;
tor_assert(entry_guards);
@@ -3996,23 +4036,19 @@ entry_guards_prepend_from_config(or_options_t *options)
tor_free(string);
}
- entry_routers = smartlist_create();
+ entry_nodes = smartlist_create();
+ worse_entry_nodes = smartlist_create();
entry_fps = smartlist_create();
old_entry_guards_on_list = smartlist_create();
old_entry_guards_not_on_list = smartlist_create();
/* Split entry guards into those on the list and those not. */
- /* XXXX023 Now that we allow countries and IP ranges in EntryNodes, this is
- * potentially an enormous list. For now, we disable such values for
- * EntryNodes in options_validate(); really, this wants a better solution.
- * Perhaps we should do this calculation once whenever the list of routers
- * changes or the entrynodes setting changes.
- */
- routerset_get_all_routers(entry_routers, options->EntryNodes,
- options->ExcludeNodes, 0);
- SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri,
- smartlist_add(entry_fps,ri->cache_info.identity_digest));
+ routerset_get_all_nodes(entry_nodes, options->EntryNodes,
+ options->ExcludeNodes, 0);
+ SMARTLIST_FOREACH(entry_nodes, const node_t *,node,
+ smartlist_add(entry_fps, (void*)node->identity));
+
SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, {
if (smartlist_digest_isin(entry_fps, e->identity))
smartlist_add(old_entry_guards_on_list, e);
@@ -4020,27 +4056,47 @@ entry_guards_prepend_from_config(or_options_t *options)
smartlist_add(old_entry_guards_not_on_list, e);
});
- /* Remove all currently configured entry guards from entry_routers. */
- SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri, {
- if (is_an_entry_guard(ri->cache_info.identity_digest)) {
- SMARTLIST_DEL_CURRENT(entry_routers, ri);
+ /* Remove all currently configured guard nodes, excluded nodes, unreachable
+ * nodes, or non-Guard nodes from entry_nodes. */
+ SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) {
+ if (is_an_entry_guard(node->identity)) {
+ SMARTLIST_DEL_CURRENT(entry_nodes, node);
+ continue;
+ } else if (routerset_contains_node(options->ExcludeNodes, node)) {
+ SMARTLIST_DEL_CURRENT(entry_nodes, node);
+ continue;
+ } else if (!fascist_firewall_allows_node(node)) {
+ SMARTLIST_DEL_CURRENT(entry_nodes, node);
+ continue;
+ } else if (! node->is_possible_guard) {
+ smartlist_add(worse_entry_nodes, (node_t*)node);
+ SMARTLIST_DEL_CURRENT(entry_nodes, node);
}
- });
+ } SMARTLIST_FOREACH_END(node);
/* Now build the new entry_guards list. */
smartlist_clear(entry_guards);
/* First, the previously configured guards that are in EntryNodes. */
smartlist_add_all(entry_guards, old_entry_guards_on_list);
+ /* Next, scramble the rest of EntryNodes, putting the guards first. */
+ smartlist_shuffle(entry_nodes);
+ smartlist_shuffle(worse_entry_nodes);
+ smartlist_add_all(entry_nodes, worse_entry_nodes);
+
/* Next, the rest of EntryNodes */
- SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri, {
- add_an_entry_guard(ri, 0);
- });
+ SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) {
+ add_an_entry_guard(node, 0, 0);
+ if (smartlist_len(entry_guards) > options->NumEntryGuards * 10)
+ break;
+ } SMARTLIST_FOREACH_END(node);
+ log_notice(LD_GENERAL, "%d entries in guards", smartlist_len(entry_guards));
/* Finally, free the remaining previously configured guards that are not in
* EntryNodes. */
SMARTLIST_FOREACH(old_entry_guards_not_on_list, entry_guard_t *, e,
entry_guard_free(e));
- smartlist_free(entry_routers);
+ smartlist_free(entry_nodes);
+ smartlist_free(worse_entry_nodes);
smartlist_free(entry_fps);
smartlist_free(old_entry_guards_on_list);
smartlist_free(old_entry_guards_not_on_list);
@@ -4052,7 +4108,7 @@ entry_guards_prepend_from_config(or_options_t *options)
* list already and we must stick to it.
*/
int
-entry_list_is_constrained(or_options_t *options)
+entry_list_is_constrained(const or_options_t *options)
{
if (options->EntryNodes)
return 1;
@@ -4066,20 +4122,21 @@ entry_list_is_constrained(or_options_t *options)
* make sure not to pick this circuit's exit or any node in the
* exit's family. If <b>state</b> is NULL, we're looking for a random
* guard (likely a bridge). */
-routerinfo_t *
+const node_t *
choose_random_entry(cpath_build_state_t *state)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
smartlist_t *live_entry_guards = smartlist_create();
smartlist_t *exit_family = smartlist_create();
- routerinfo_t *chosen_exit = state?build_state_get_exit_router(state) : NULL;
- routerinfo_t *r = NULL;
+ const node_t *chosen_exit =
+ state?build_state_get_exit_node(state) : NULL;
+ const node_t *node = NULL;
int need_uptime = state ? state->need_uptime : 0;
int need_capacity = state ? state->need_capacity : 0;
int preferred_min, consider_exit_family = 0;
if (chosen_exit) {
- routerlist_add_family(exit_family, chosen_exit);
+ nodelist_add_node_and_family(exit_family, chosen_exit);
consider_exit_family = 1;
}
@@ -4087,7 +4144,7 @@ choose_random_entry(cpath_build_state_t *state)
entry_guards = smartlist_create();
if (should_add_entry_nodes)
- entry_guards_prepend_from_config(options);
+ entry_guards_set_from_config(options);
if (!entry_list_is_constrained(options) &&
smartlist_len(entry_guards) < options->NumEntryGuards)
@@ -4095,25 +4152,24 @@ choose_random_entry(cpath_build_state_t *state)
retry:
smartlist_clear(live_entry_guards);
- SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry,
- {
+ SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) {
const char *msg;
- r = entry_is_live(entry, need_uptime, need_capacity, 0, &msg);
- if (!r)
+ node = entry_is_live(entry, need_uptime, need_capacity, 0, &msg);
+ if (!node)
continue; /* down, no point */
- if (r == chosen_exit)
+ if (node == chosen_exit)
continue; /* don't pick the same node for entry and exit */
- if (consider_exit_family && smartlist_isin(exit_family, r))
+ if (consider_exit_family && smartlist_isin(exit_family, node))
continue; /* avoid relays that are family members of our exit */
#if 0 /* since EntryNodes is always strict now, this clause is moot */
if (options->EntryNodes &&
- !routerset_contains_router(options->EntryNodes, r)) {
+ !routerset_contains_node(options->EntryNodes, node)) {
/* We've come to the end of our preferred entry nodes. */
if (smartlist_len(live_entry_guards))
goto choose_and_finish; /* only choose from the ones we like */
if (options->StrictNodes) {
/* in theory this case should never happen, since
- * entry_guards_prepend_from_config() drops unwanted relays */
+ * entry_guards_set_from_config() drops unwanted relays */
tor_fragile_assert();
} else {
log_info(LD_CIRC,
@@ -4121,7 +4177,7 @@ choose_random_entry(cpath_build_state_t *state)
}
}
#endif
- smartlist_add(live_entry_guards, r);
+ smartlist_add(live_entry_guards, (void*)node);
if (!entry->made_contact) {
/* Always start with the first not-yet-contacted entry
* guard. Otherwise we might add several new ones, pick
@@ -4130,8 +4186,8 @@ choose_random_entry(cpath_build_state_t *state)
goto choose_and_finish;
}
if (smartlist_len(live_entry_guards) >= options->NumEntryGuards)
- break; /* we have enough */
- });
+ goto choose_and_finish; /* we have enough */
+ } SMARTLIST_FOREACH_END(entry);
if (entry_list_is_constrained(options)) {
/* If we prefer the entry nodes we've got, and we have at least
@@ -4151,8 +4207,8 @@ choose_random_entry(cpath_build_state_t *state)
/* XXX if guard doesn't imply fast and stable, then we need
* to tell add_an_entry_guard below what we want, or it might
* be a long time til we get it. -RD */
- r = add_an_entry_guard(NULL, 0);
- if (r) {
+ node = add_an_entry_guard(NULL, 0, 0);
+ if (node) {
entry_guards_changed();
/* XXX we start over here in case the new node we added shares
* a family with our exit node. There's a chance that we'll just
@@ -4162,11 +4218,11 @@ choose_random_entry(cpath_build_state_t *state)
goto retry;
}
}
- if (!r && need_uptime) {
+ if (!node && need_uptime) {
need_uptime = 0; /* try without that requirement */
goto retry;
}
- if (!r && need_capacity) {
+ if (!node && need_capacity) {
/* still no? last attempt, try without requiring capacity */
need_capacity = 0;
goto retry;
@@ -4175,10 +4231,10 @@ choose_random_entry(cpath_build_state_t *state)
/* Removing this retry logic: if we only allow one exit, and it is in the
same family as all our entries, then we are just plain not going to win
here. */
- if (!r && entry_list_is_constrained(options) && consider_exit_family) {
- /* still no? if we're using bridges,
- * and our chosen exit is in the same family as all our
- * bridges, then be flexible about families. */
+ if (!node && entry_list_is_constrained(options) && consider_exit_family) {
+ /* still no? if we're using bridges or have strictentrynodes
+ * set, and our chosen exit is in the same family as all our
+ * bridges/entry guards, then be flexible about families. */
consider_exit_family = 0;
goto retry;
}
@@ -4190,16 +4246,16 @@ choose_random_entry(cpath_build_state_t *state)
if (entry_list_is_constrained(options)) {
/* We need to weight by bandwidth, because our bridges or entryguards
* were not already selected proportional to their bandwidth. */
- r = routerlist_sl_choose_by_bandwidth(live_entry_guards, WEIGHT_FOR_GUARD);
+ node = node_sl_choose_by_bandwidth(live_entry_guards, WEIGHT_FOR_GUARD);
} else {
/* We choose uniformly at random here, because choose_good_entry_server()
* already weights its choices by bandwidth, so we don't want to
* *double*-weight our guard selection. */
- r = smartlist_choose(live_entry_guards);
+ node = smartlist_choose(live_entry_guards);
}
smartlist_free(live_entry_guards);
smartlist_free(exit_family);
- return r;
+ return node;
}
/** Parse <b>state</b> and learn about the entry guards it describes.
@@ -4446,7 +4502,7 @@ getinfo_helper_entry_guards(control_connection_t *conn,
char *c = tor_malloc(len);
const char *status = NULL;
time_t when = 0;
- routerinfo_t *ri;
+ const node_t *node;
if (!e->made_contact) {
status = "never-connected";
@@ -4457,9 +4513,9 @@ getinfo_helper_entry_guards(control_connection_t *conn,
status = "up";
}
- ri = router_get_by_digest(e->identity);
- if (ri) {
- router_get_verbose_nickname(nbuf, ri);
+ node = node_get_by_id(e->identity);
+ if (node) {
+ node_get_verbose_nickname(node, nbuf);
} else {
nbuf[0] = '$';
base16_encode(nbuf+1, sizeof(nbuf)-1, e->identity, DIGEST_LEN);
@@ -4482,24 +4538,6 @@ getinfo_helper_entry_guards(control_connection_t *conn,
return 0;
}
-/** Information about a configured bridge. Currently this just matches the
- * ones in the torrc file, but one day we may be able to learn about new
- * bridges on our own, and remember them in the state file. */
-typedef struct {
- /** Address of the bridge. */
- tor_addr_t addr;
- /** TLS port for the bridge. */
- uint16_t port;
- /** Boolean: We are re-parsing our bridge list, and we are going to remove
- * this one if we don't find it in the list of configured bridges. */
- unsigned marked_for_removal : 1;
- /** Expected identity digest, or all zero bytes if we don't know what the
- * digest should be. */
- char identity[DIGEST_LEN];
- /** When should we next try to fetch a descriptor for this bridge? */
- download_status_t fetch_status;
-} bridge_info_t;
-
/** A list of configured bridges. Whenever we actually get a descriptor
* for one, we add it as an entry guard. Note that the order of bridges
* in this list does not necessarily correspond to the order of bridges
@@ -4527,7 +4565,7 @@ sweep_bridge_list(void)
SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) {
if (b->marked_for_removal) {
SMARTLIST_DEL_CURRENT(bridge_list, b);
- tor_free(b);
+ bridge_free(b);
}
} SMARTLIST_FOREACH_END(b);
}
@@ -4538,10 +4576,243 @@ clear_bridge_list(void)
{
if (!bridge_list)
bridge_list = smartlist_create();
- SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b, tor_free(b));
+ SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b, bridge_free(b));
smartlist_clear(bridge_list);
}
+/** Free the bridge <b>bridge</b>. */
+static void
+bridge_free(bridge_info_t *bridge)
+{
+ if (!bridge)
+ return;
+
+ tor_free(bridge->transport_name);
+ tor_free(bridge);
+}
+
+/** A list of pluggable transports found in torrc. */
+static smartlist_t *transport_list = NULL;
+
+/** Mark every entry of the transport list to be removed on our next call to
+ * sweep_transport_list unless it has first been un-marked. */
+void
+mark_transport_list(void)
+{
+ if (!transport_list)
+ transport_list = smartlist_create();
+ SMARTLIST_FOREACH(transport_list, transport_t *, t,
+ t->marked_for_removal = 1);
+}
+
+/** Remove every entry of the transport list that was marked with
+ * mark_transport_list if it has not subsequently been un-marked. */
+void
+sweep_transport_list(void)
+{
+ if (!transport_list)
+ transport_list = smartlist_create();
+ SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, t) {
+ if (t->marked_for_removal) {
+ SMARTLIST_DEL_CURRENT(transport_list, t);
+ transport_free(t);
+ }
+ } SMARTLIST_FOREACH_END(t);
+}
+
+/** Initialize the pluggable transports list to empty, creating it if
+ * needed. */
+void
+clear_transport_list(void)
+{
+ if (!transport_list)
+ transport_list = smartlist_create();
+ SMARTLIST_FOREACH(transport_list, transport_t *, t, transport_free(t));
+ smartlist_clear(transport_list);
+}
+
+/** Free the pluggable transport struct <b>transport</b>. */
+void
+transport_free(transport_t *transport)
+{
+ if (!transport)
+ return;
+
+ tor_free(transport->name);
+ tor_free(transport);
+}
+
+/** Returns the transport in our transport list that has the name <b>name</b>.
+ * Else returns NULL. */
+transport_t *
+transport_get_by_name(const char *name)
+{
+ tor_assert(name);
+
+ if (!transport_list)
+ return NULL;
+
+ SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, transport) {
+ if (!strcmp(transport->name, name))
+ return transport;
+ } SMARTLIST_FOREACH_END(transport);
+
+ return NULL;
+}
+
+/** Returns a transport_t struct for a transport proxy supporting the
+ protocol <b>name</b> listening at <b>addr</b>:<b>port</b> using
+ SOCKS version <b>socks_ver</b>. */
+transport_t *
+transport_create(const tor_addr_t *addr, uint16_t port,
+ const char *name, int socks_ver)
+{
+ transport_t *t = tor_malloc_zero(sizeof(transport_t));
+
+ tor_addr_copy(&t->addr, addr);
+ t->port = port;
+ t->name = tor_strdup(name);
+ t->socks_version = socks_ver;
+
+ return t;
+}
+
+/** Resolve any conflicts that the insertion of transport <b>t</b>
+ * might cause.
+ * Return 0 if <b>t</b> is OK and should be registered, 1 if there is
+ * a transport identical to <b>t</b> already registered and -1 if
+ * <b>t</b> cannot be added due to conflicts. */
+static int
+transport_resolve_conflicts(transport_t *t)
+{
+ /* This is how we resolve transport conflicts:
+
+ If there is already a transport with the same name and addrport,
+ we either have duplicate torrc lines OR we are here post-HUP and
+ this transport was here pre-HUP as well. In any case, mark the
+ old transport so that it doesn't get removed and ignore the new
+ one. Our caller has to free the new transport so we return '1' to
+ signify this.
+
+ If there is already a transport with the same name but different
+ addrport:
+ * if it's marked for removal, it means that it either has a lower
+ priority than 't' in torrc (otherwise the mark would have been
+ cleared by the paragraph above), or it doesn't exist at all in
+ the post-HUP torrc. We destroy the old transport and register 't'.
+ * if it's *not* marked for removal, it means that it was newly
+ added in the post-HUP torrc or that it's of higher priority, in
+ this case we ignore 't'. */
+ transport_t *t_tmp = transport_get_by_name(t->name);
+ if (t_tmp) { /* same name */
+ if (tor_addr_eq(&t->addr, &t_tmp->addr) && (t->port == t_tmp->port)) {
+ /* same name *and* addrport */
+ t_tmp->marked_for_removal = 0;
+ return 1;
+ } else { /* same name but different addrport */
+ if (t_tmp->marked_for_removal) { /* marked for removal */
+ log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' "
+ "but there was already a transport marked for deletion at "
+ "'%s:%u'. We deleted the old transport and registered the "
+ "new one.", t->name, fmt_addr(&t->addr), t->port,
+ fmt_addr(&t_tmp->addr), t_tmp->port);
+ smartlist_remove(transport_list, t_tmp);
+ transport_free(t_tmp);
+ } else { /* *not* marked for removal */
+ log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' "
+ "but the same transport already exists at '%s:%u'. "
+ "Skipping.", t->name, fmt_addr(&t->addr), t->port,
+ fmt_addr(&t_tmp->addr), t_tmp->port);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/** Add transport <b>t</b> to the internal list of pluggable
+ * transports.
+ * Returns 0 if the transport was added correctly, 1 if the same
+ * transport was already registered (in this case the caller must
+ * free the transport) and -1 if there was an error. */
+int
+transport_add(transport_t *t)
+{
+ int r;
+ tor_assert(t);
+
+ r = transport_resolve_conflicts(t);
+
+ switch (r) {
+ case 0: /* should register transport */
+ if (!transport_list)
+ transport_list = smartlist_create();
+ smartlist_add(transport_list, t);
+ return 0;
+ default: /* let our caller know the return code */
+ return r;
+ }
+}
+
+/** Remember a new pluggable transport proxy at <b>addr</b>:<b>port</b>.
+ * <b>name</b> is set to the name of the protocol this proxy uses.
+ * <b>socks_ver</b> is set to the SOCKS version of the proxy. */
+int
+transport_add_from_config(const tor_addr_t *addr, uint16_t port,
+ const char *name, int socks_ver)
+{
+ transport_t *t = transport_create(addr, port, name, socks_ver);
+
+ int r = transport_add(t);
+
+ switch (r) {
+ case -1:
+ default:
+ log_notice(LD_GENERAL, "Could not add transport %s at %s:%u. Skipping.",
+ t->name, fmt_addr(&t->addr), t->port);
+ transport_free(t);
+ return -1;
+ case 1:
+ log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.",
+ t->name, fmt_addr(&t->addr), t->port);
+ transport_free(t); /* falling */
+ return 0;
+ case 0:
+ log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.",
+ t->name, fmt_addr(&t->addr), t->port);
+ return 0;
+ }
+}
+
+/** Warn the user of possible pluggable transport misconfiguration.
+ * Return 0 if the validation happened, -1 if we should postpone the
+ * validation. */
+int
+validate_pluggable_transports_config(void)
+{
+ /* Don't validate if managed proxies are not yet fully configured. */
+ if (bridge_list && !pt_proxies_configuration_pending()) {
+ SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) {
+ /* Skip bridges without transports. */
+ if (!b->transport_name)
+ continue;
+ /* See if the user has Bridges that specify nonexistent
+ pluggable transports. We should warn the user in such case,
+ since it's probably misconfiguration. */
+ if (!transport_get_by_name(b->transport_name))
+ log_warn(LD_CONFIG, "You have a Bridge line using the %s "
+ "pluggable transport, but there doesn't seem to be a "
+ "corresponding ClientTransportPlugin line.",
+ b->transport_name);
+ } SMARTLIST_FOREACH_END(b);
+
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
/** Return a bridge pointer if <b>ri</b> is one of our known bridges
* (either by comparing keys if possible, else by comparing addr/port).
* Else return NULL. */
@@ -4568,7 +4839,7 @@ get_configured_bridge_by_addr_port_digest(const tor_addr_t *addr,
/** Wrapper around get_configured_bridge_by_addr_port_digest() to look
* it up via router descriptor <b>ri</b>. */
static bridge_info_t *
-get_configured_bridge_by_routerinfo(routerinfo_t *ri)
+get_configured_bridge_by_routerinfo(const routerinfo_t *ri)
{
tor_addr_t addr;
tor_addr_from_ipv4h(&addr, ri->addr);
@@ -4578,11 +4849,29 @@ get_configured_bridge_by_routerinfo(routerinfo_t *ri)
/** Return 1 if <b>ri</b> is one of our known bridges, else 0. */
int
-routerinfo_is_a_configured_bridge(routerinfo_t *ri)
+routerinfo_is_a_configured_bridge(const routerinfo_t *ri)
{
return get_configured_bridge_by_routerinfo(ri) ? 1 : 0;
}
+/** Return 1 if <b>node</b> is one of our configured bridges, else 0. */
+int
+node_is_a_configured_bridge(const node_t *node)
+{
+ tor_addr_t addr;
+ uint16_t orport;
+ if (!node)
+ return 0;
+ if (node_get_addr(node, &addr) < 0)
+ return 0;
+ orport = node_get_orport(node);
+ if (orport == 0)
+ return 0;
+
+ return get_configured_bridge_by_addr_port_digest(
+ &addr, orport, node->identity) != NULL;
+}
+
/** We made a connection to a router at <b>addr</b>:<b>port</b>
* without knowing its digest. Its digest turned out to be <b>digest</b>.
* If it was a bridge, and we still don't know its digest, record it.
@@ -4602,10 +4891,12 @@ learned_router_identity(const tor_addr_t *addr, uint16_t port,
/** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b>
* is set, it tells us the identity key too. If we already had the
- * bridge in our list, unmark it, and don't actually add anything new. */
+ * bridge in our list, unmark it, and don't actually add anything new.
+ * If <b>transport_name</b> is non-NULL - the bridge is associated with a
+ * pluggable transport - we assign the transport to the bridge. */
void
bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
- const char *digest)
+ const char *digest, const char *transport_name)
{
bridge_info_t *b;
@@ -4619,6 +4910,8 @@ bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
b->port = port;
if (digest)
memcpy(b->identity, digest, DIGEST_LEN);
+ if (transport_name)
+ b->transport_name = tor_strdup(transport_name);
b->fetch_status.schedule = DL_SCHED_BRIDGE;
if (!bridge_list)
bridge_list = smartlist_create();
@@ -4656,12 +4949,48 @@ find_bridge_by_digest(const char *digest)
return NULL;
}
+/** If <b>addr</b> and <b>port</b> match the address and port of a
+ * bridge of ours that uses pluggable transports, place its transport
+ * in <b>transport</b>.
+ *
+ * Return 0 on success (found a transport, or found a bridge with no
+ * transport, or found no bridge); return -1 if we should be using a
+ * transport, but the transport could not be found.
+ */
+int
+find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
+ const transport_t **transport)
+{
+ *transport = NULL;
+ if (!bridge_list)
+ return 0;
+
+ SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) {
+ if (tor_addr_eq(&bridge->addr, addr) &&
+ (bridge->port == port)) { /* bridge matched */
+ if (bridge->transport_name) { /* it also uses pluggable transports */
+ *transport = transport_get_by_name(bridge->transport_name);
+ if (*transport == NULL) { /* it uses pluggable transports, but
+ the transport could not be found! */
+ return -1;
+ }
+ return 0;
+ } else { /* bridge matched, but it doesn't use transports. */
+ break;
+ }
+ }
+ } SMARTLIST_FOREACH_END(bridge);
+
+ *transport = NULL;
+ return 0;
+}
+
/** We need to ask <b>bridge</b> for its server descriptor. */
static void
launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge)
{
char *address;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (connection_get_by_type_addr_port_purpose(
CONN_TYPE_DIR, &bridge->addr, bridge->port,
@@ -4702,15 +5031,20 @@ retry_bridge_descriptor_fetch_directly(const char *digest)
* descriptor, fetch a new copy of its descriptor -- either directly
* from the bridge or via a bridge authority. */
void
-fetch_bridge_descriptors(or_options_t *options, time_t now)
+fetch_bridge_descriptors(const or_options_t *options, time_t now)
{
- int num_bridge_auths = get_n_authorities(BRIDGE_AUTHORITY);
+ int num_bridge_auths = get_n_authorities(BRIDGE_DIRINFO);
int ask_bridge_directly;
int can_use_bridge_authority;
if (!bridge_list)
return;
+ /* If we still have unconfigured managed proxies, don't go and
+ connect to a bridge. */
+ if (pt_proxies_configuration_pending())
+ return;
+
SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge)
{
if (!download_status_is_ready(&bridge->fetch_status, now,
@@ -4769,26 +5103,55 @@ fetch_bridge_descriptors(or_options_t *options, time_t now)
}
/** If our <b>bridge</b> is configured to be a different address than
- * the bridge gives in its routerinfo <b>ri</b>, rewrite the routerinfo
+ * the bridge gives in <b>node</b>, rewrite the routerinfo
* we received to use the address we meant to use. Now we handle
* multihomed bridges better.
*/
static void
-rewrite_routerinfo_address_for_bridge(bridge_info_t *bridge, routerinfo_t *ri)
+rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node)
{
+ /* XXXX move this function. */
+ /* XXXX overridden addresses should really live in the node_t, so that the
+ * routerinfo_t and the microdesc_t can be immutable. But we can only
+ * do that safely if we know that no function that connects to an OR
+ * does so through an address from any source other than node_get_addr().
+ */
tor_addr_t addr;
- tor_addr_from_ipv4h(&addr, ri->addr);
- if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
- bridge->port == ri->or_port)
- return; /* they match, so no need to do anything */
+ if (node->ri) {
+ routerinfo_t *ri = node->ri;
+ tor_addr_from_ipv4h(&addr, ri->addr);
+
+ if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
+ bridge->port == ri->or_port) {
+ /* they match, so no need to do anything */
+ } else {
+ ri->addr = tor_addr_to_ipv4h(&bridge->addr);
+ tor_free(ri->address);
+ ri->address = tor_dup_ip(ri->addr);
+ ri->or_port = bridge->port;
+ log_info(LD_DIR,
+ "Adjusted bridge routerinfo for '%s' to match configured "
+ "address %s:%d.",
+ ri->nickname, ri->address, ri->or_port);
+ }
+ }
+ if (node->rs) {
+ routerstatus_t *rs = node->rs;
+ tor_addr_from_ipv4h(&addr, rs->addr);
- ri->addr = tor_addr_to_ipv4h(&bridge->addr);
- tor_free(ri->address);
- ri->address = tor_dup_ip(ri->addr);
- ri->or_port = bridge->port;
- log_info(LD_DIR, "Adjusted bridge '%s' to match configured address %s:%d.",
- ri->nickname, ri->address, ri->or_port);
+ if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) &&
+ bridge->port == rs->or_port) {
+ /* they match, so no need to do anything */
+ } else {
+ rs->addr = tor_addr_to_ipv4h(&bridge->addr);
+ rs->or_port = bridge->port;
+ log_info(LD_DIR,
+ "Adjusted bridge routerstatus for '%s' to match "
+ "configured address %s:%d.",
+ rs->nickname, fmt_addr(&bridge->addr), rs->or_port);
+ }
+ }
}
/** We just learned a descriptor for a bridge. See if that
@@ -4802,16 +5165,19 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
int first = !any_bridge_descriptors_known();
bridge_info_t *bridge = get_configured_bridge_by_routerinfo(ri);
time_t now = time(NULL);
- ri->is_running = 1;
+ router_set_status(ri->cache_info.identity_digest, 1);
if (bridge) { /* if we actually want to use this one */
+ node_t *node;
/* it's here; schedule its re-fetch for a long time from now. */
if (!from_cache)
download_status_reset(&bridge->fetch_status);
- rewrite_routerinfo_address_for_bridge(bridge, ri);
+ node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ tor_assert(node);
+ rewrite_node_address_for_bridge(bridge, node);
+ add_an_entry_guard(node, 1, 1);
- add_an_entry_guard(ri, 1);
log_notice(LD_DIR, "new bridge descriptor '%s' (%s)", ri->nickname,
from_cache ? "cached" : "fresh");
/* set entry->made_contact so if it goes down we don't drop it from
@@ -4864,21 +5230,20 @@ any_pending_bridge_descriptor_fetches(void)
* down. Else return 0. If <b>act</b> is 1, then mark the down guards
* up; else just observe and report. */
static int
-entries_retry_helper(or_options_t *options, int act)
+entries_retry_helper(const or_options_t *options, int act)
{
- routerinfo_t *ri;
+ const node_t *node;
int any_known = 0;
int any_running = 0;
- int purpose = options->UseBridges ?
- ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL;
+ int need_bridges = options->UseBridges != 0;
if (!entry_guards)
entry_guards = smartlist_create();
- SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e,
- {
- ri = router_get_by_digest(e->identity);
- if (ri && ri->purpose == purpose) {
+ SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) {
+ node = node_get_by_id(e->identity);
+ if (node && node_has_descriptor(node) &&
+ node_is_bridge(node) == need_bridges) {
any_known = 1;
- if (ri->is_running)
+ if (node->is_running)
any_running = 1; /* some entry is both known and running */
else if (act) {
/* Mark all current connections to this OR as unhealthy, since
@@ -4887,15 +5252,15 @@ entries_retry_helper(or_options_t *options, int act)
* the node down and undermine the retry attempt. We mark even
* the established conns, since if the network just came back
* we'll want to attach circuits to fresh conns. */
- connection_or_set_bad_connections(ri->cache_info.identity_digest, 1);
+ connection_or_set_bad_connections(node->identity, 1);
/* mark this entry node for retry */
- router_set_status(ri->cache_info.identity_digest, 1);
+ router_set_status(node->identity, 1);
e->can_retry = 1;
e->bad_since = 0;
}
}
- });
+ } SMARTLIST_FOREACH_END(e);
log_debug(LD_DIR, "%d: any_known %d, any_running %d",
act, any_known, any_running);
return any_known && !any_running;
@@ -4904,7 +5269,7 @@ entries_retry_helper(or_options_t *options, int act)
/** Do we know any descriptors for our bridges / entrynodes, and are
* all the ones we have descriptors for down? */
int
-entries_known_but_down(or_options_t *options)
+entries_known_but_down(const or_options_t *options)
{
tor_assert(entry_list_is_constrained(options));
return entries_retry_helper(options, 0);
@@ -4912,7 +5277,7 @@ entries_known_but_down(or_options_t *options)
/** Mark all down known bridges / entrynodes up. */
void
-entries_retry_all(or_options_t *options)
+entries_retry_all(const or_options_t *options)
{
tor_assert(entry_list_is_constrained(options));
entries_retry_helper(options, 1);
@@ -4930,7 +5295,10 @@ entry_guards_free_all(void)
entry_guards = NULL;
}
clear_bridge_list();
+ clear_transport_list();
smartlist_free(bridge_list);
+ smartlist_free(transport_list);
bridge_list = NULL;
+ transport_list = NULL;
}
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index 0e673e1c0..1052db615 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -12,6 +12,21 @@
#ifndef _TOR_CIRCUITBUILD_H
#define _TOR_CIRCUITBUILD_H
+/** Represents a pluggable transport proxy used by a bridge. */
+typedef struct {
+ /** SOCKS version: One of PROXY_SOCKS4, PROXY_SOCKS5. */
+ int socks_version;
+ /** Name of pluggable transport protocol */
+ char *name;
+ /** Address of proxy */
+ tor_addr_t addr;
+ /** Port of proxy */
+ uint16_t port;
+ /** Boolean: We are re-parsing our transport list, and we are going to remove
+ * this one if we don't find it in the list of configured transports. */
+ unsigned marked_for_removal : 1;
+} transport_t;
+
char *circuit_list_path(origin_circuit_t *circ, int verbose);
char *circuit_list_path_for_controller(origin_circuit_t *circ);
void circuit_log_path(int severity, unsigned int domain,
@@ -44,18 +59,19 @@ void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop);
extend_info_t *extend_info_alloc(const char *nickname, const char *digest,
crypto_pk_env_t *onion_key,
const tor_addr_t *addr, uint16_t port);
-extend_info_t *extend_info_from_router(routerinfo_t *r);
+extend_info_t *extend_info_from_router(const routerinfo_t *r);
+extend_info_t *extend_info_from_node(const node_t *node);
extend_info_t *extend_info_dup(extend_info_t *info);
void extend_info_free(extend_info_t *info);
-routerinfo_t *build_state_get_exit_router(cpath_build_state_t *state);
+const node_t *build_state_get_exit_node(cpath_build_state_t *state);
const char *build_state_get_exit_nickname(cpath_build_state_t *state);
-void entry_guards_compute_status(or_options_t *options, time_t now);
+void entry_guards_compute_status(const or_options_t *options, time_t now);
int entry_guard_register_connect_status(const char *digest, int succeeded,
int mark_relay_status, time_t now);
void entry_nodes_should_be_added(void);
-int entry_list_is_constrained(or_options_t *options);
-routerinfo_t *choose_random_entry(cpath_build_state_t *state);
+int entry_list_is_constrained(const or_options_t *options);
+const node_t *choose_random_entry(cpath_build_state_t *state);
int entry_guards_parse_state(or_state_t *state, int set, char **msg);
void entry_guards_update_state(or_state_t *state);
int getinfo_helper_entry_guards(control_connection_t *conn,
@@ -64,18 +80,23 @@ int getinfo_helper_entry_guards(control_connection_t *conn,
void mark_bridge_list(void);
void sweep_bridge_list(void);
-int routerinfo_is_a_configured_bridge(routerinfo_t *ri);
+void mark_transport_list(void);
+void sweep_transport_list(void);
+
+int routerinfo_is_a_configured_bridge(const routerinfo_t *ri);
+int node_is_a_configured_bridge(const node_t *node);
void learned_router_identity(const tor_addr_t *addr, uint16_t port,
const char *digest);
void bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
- const char *digest);
+ const char *digest,
+ const char *transport_name);
void retry_bridge_descriptor_fetch_directly(const char *digest);
-void fetch_bridge_descriptors(or_options_t *options, time_t now);
+void fetch_bridge_descriptors(const or_options_t *options, time_t now);
void learned_bridge_descriptor(routerinfo_t *ri, int from_cache);
int any_bridge_descriptors_known(void);
int any_pending_bridge_descriptor_fetches(void);
-int entries_known_but_down(or_options_t *options);
-void entries_retry_all(or_options_t *options);
+int entries_known_but_down(const or_options_t *options);
+void entries_retry_all(const or_options_t *options);
void entry_guards_free_all(void);
@@ -124,5 +145,19 @@ void circuit_build_times_network_circ_success(circuit_build_times_t *cbt);
int circuit_build_times_get_bw_scale(networkstatus_t *ns);
+void clear_transport_list(void);
+int transport_add_from_config(const tor_addr_t *addr, uint16_t port,
+ const char *name, int socks_ver);
+int transport_add(transport_t *t);
+void transport_free(transport_t *transport);
+transport_t *transport_create(const tor_addr_t *addr, uint16_t port,
+ const char *name, int socks_ver);
+
+int find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port,
+ const transport_t **transport);
+transport_t *transport_get_by_name(const char *name);
+
+int validate_pluggable_transports_config(void);
+
#endif
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index e9cc9eb1f..e4408f84c 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -19,6 +19,7 @@
#include "connection_or.h"
#include "control.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "onion.h"
#include "relay.h"
#include "rendclient.h"
@@ -86,10 +87,7 @@ orconn_circid_circuit_map_t *_last_circid_orconn_ent = NULL;
/** Implementation helper for circuit_set_{p,n}_circid_orconn: A circuit ID
* and/or or_connection for circ has just changed from <b>old_conn, old_id</b>
* to <b>conn, id</b>. Adjust the conn,circid map as appropriate, removing
- * the old entry (if any) and adding a new one. If <b>active</b> is true,
- * remove the circuit from the list of active circuits on old_conn and add it
- * to the list of active circuits on conn.
- * XXX "active" isn't an arg anymore */
+ * the old entry (if any) and adding a new one. */
static void
circuit_set_circid_orconn_helper(circuit_t *circ, int direction,
circid_t id,
@@ -552,6 +550,16 @@ circuit_free(circuit_t *circ)
crypto_free_pk_env(ocirc->intro_key);
rend_data_free(ocirc->rend_data);
+
+ tor_free(ocirc->dest_address);
+ if (ocirc->socks_username) {
+ memset(ocirc->socks_username, 0x12, ocirc->socks_username_len);
+ tor_free(ocirc->socks_username);
+ }
+ if (ocirc->socks_password) {
+ memset(ocirc->socks_password, 0x06, ocirc->socks_password_len);
+ tor_free(ocirc->socks_password);
+ }
} else {
or_circuit_t *ocirc = TO_OR_CIRCUIT(circ);
/* Remember cell statistics for this circuit before deallocating. */
@@ -981,7 +989,7 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
int need_uptime = (flags & CIRCLAUNCH_NEED_UPTIME) != 0;
int need_capacity = (flags & CIRCLAUNCH_NEED_CAPACITY) != 0;
int internal = (flags & CIRCLAUNCH_IS_INTERNAL) != 0;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* Make sure we're not trying to create a onehop circ by
* cannibalization. */
@@ -1003,19 +1011,20 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info,
(!need_capacity || circ->build_state->need_capacity) &&
(internal == circ->build_state->is_internal) &&
circ->remaining_relay_early_cells &&
- !circ->build_state->onehop_tunnel) {
+ !circ->build_state->onehop_tunnel &&
+ !circ->isolation_values_set) {
if (info) {
/* need to make sure we don't duplicate hops */
crypt_path_t *hop = circ->cpath;
- routerinfo_t *ri1 = router_get_by_digest(info->identity_digest);
+ const node_t *ri1 = node_get_by_id(info->identity_digest);
do {
- routerinfo_t *ri2;
+ const node_t *ri2;
if (tor_memeq(hop->extend_info->identity_digest,
info->identity_digest, DIGEST_LEN))
goto next;
if (ri1 &&
- (ri2 = router_get_by_digest(hop->extend_info->identity_digest))
- && routers_in_same_family(ri1, ri2))
+ (ri2 = node_get_by_id(hop->extend_info->identity_digest))
+ && nodes_in_same_family(ri1, ri2))
goto next;
hop=hop->next;
} while (hop!=circ->cpath);
@@ -1100,7 +1109,7 @@ void
circuit_expire_all_dirty_circs(void)
{
circuit_t *circ;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
for (circ=global_circuitlist; circ; circ = circ->next) {
if (CIRCUIT_IS_ORIGIN(circ) &&
@@ -1119,9 +1128,11 @@ circuit_expire_all_dirty_circs(void)
* - If circ isn't open yet: call circuit_build_failed() if we're
* the origin, and in either case call circuit_rep_hist_note_result()
* to note stats.
- * - If purpose is C_INTRODUCE_ACK_WAIT, remove the intro point we
- * just tried from our list of intro points for that service
- * descriptor.
+ * - If purpose is C_INTRODUCE_ACK_WAIT, report the intro point
+ * failure we just had to the hidden service client module.
+ * - If purpose is C_INTRODUCING and <b>reason</b> isn't TIMEOUT,
+ * report to the hidden service client module that the intro point
+ * we just tried may be unreachable.
* - Send appropriate destroys and edge_destroys for conns and
* streams attached to circ.
* - If circ->rend_splice is set (we are the midpoint of a joined
@@ -1190,16 +1201,33 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line,
}
if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ int timed_out = (reason == END_STREAM_REASON_TIMEOUT);
tor_assert(circ->state == CIRCUIT_STATE_OPEN);
tor_assert(ocirc->build_state->chosen_exit);
tor_assert(ocirc->rend_data);
/* treat this like getting a nack from it */
- log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). "
- "Removing from descriptor.",
+ log_info(LD_REND, "Failed intro circ %s to %s (awaiting ack). %s",
safe_str_client(ocirc->rend_data->onion_address),
+ safe_str_client(build_state_get_exit_nickname(ocirc->build_state)),
+ timed_out ? "Recording timeout." : "Removing from descriptor.");
+ rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
+ ocirc->rend_data,
+ timed_out ?
+ INTRO_POINT_FAILURE_TIMEOUT :
+ INTRO_POINT_FAILURE_GENERIC);
+ } else if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCING &&
+ reason != END_STREAM_REASON_TIMEOUT) {
+ origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
+ tor_assert(ocirc->build_state->chosen_exit);
+ tor_assert(ocirc->rend_data);
+ log_info(LD_REND, "Failed intro circ %s to %s "
+ "(building circuit to intro point). "
+ "Marking intro point as possibly unreachable.",
+ safe_str_client(ocirc->rend_data->onion_address),
safe_str_client(build_state_get_exit_nickname(ocirc->build_state)));
- rend_client_remove_intro_point(ocirc->build_state->chosen_exit,
- ocirc->rend_data);
+ rend_client_report_intro_point_failure(ocirc->build_state->chosen_exit,
+ ocirc->rend_data,
+ INTRO_POINT_FAILURE_UNREACHABLE);
}
if (circ->n_conn) {
circuit_clear_cell_queue(circ, circ->n_conn);
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index 0ad8b3b51..9b9621890 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -17,6 +17,8 @@
#include "connection.h"
#include "connection_edge.h"
#include "control.h"
+#include "nodelist.h"
+#include "networkstatus.h"
#include "policies.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -38,19 +40,19 @@ static void circuit_increment_failure_count(void);
* Else return 0.
*/
static int
-circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
+circuit_is_acceptable(const origin_circuit_t *origin_circ,
+ const entry_connection_t *conn,
int must_be_open, uint8_t purpose,
int need_uptime, int need_internal,
time_t now)
{
- routerinfo_t *exitrouter;
+ const circuit_t *circ = TO_CIRCUIT(origin_circ);
+ const node_t *exitnode;
cpath_build_state_t *build_state;
tor_assert(circ);
tor_assert(conn);
tor_assert(conn->socks_request);
- if (!CIRCUIT_IS_ORIGIN(circ))
- return 0; /* this circ doesn't start at us */
if (must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_conn))
return 0; /* ignore non-open circs */
if (circ->marked_for_close)
@@ -85,8 +87,8 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
* circuit, it's the magical extra bob hop. so just check the nickname
* of the one we meant to finish at.
*/
- build_state = TO_ORIGIN_CIRCUIT(circ)->build_state;
- exitrouter = build_state_get_exit_router(build_state);
+ build_state = origin_circ->build_state;
+ exitnode = build_state_get_exit_node(build_state);
if (need_uptime && !build_state->need_uptime)
return 0;
@@ -94,7 +96,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
return 0;
if (purpose == CIRCUIT_PURPOSE_C_GENERAL) {
- if (!exitrouter && !build_state->onehop_tunnel) {
+ if (!exitnode && !build_state->onehop_tunnel) {
log_debug(LD_CIRC,"Not considering circuit with unknown router.");
return 0; /* this circuit is screwed and doesn't know it yet,
* or is a rendezvous circuit. */
@@ -128,30 +130,43 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn,
return 0;
}
}
- if (exitrouter && !connection_ap_can_use_exit(conn, exitrouter)) {
+ if (exitnode && !connection_ap_can_use_exit(conn, exitnode)) {
/* can't exit from this router */
return 0;
}
} else { /* not general */
- origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
- if ((conn->rend_data && !ocirc->rend_data) ||
- (!conn->rend_data && ocirc->rend_data) ||
- (conn->rend_data && ocirc->rend_data &&
- rend_cmp_service_ids(conn->rend_data->onion_address,
- ocirc->rend_data->onion_address))) {
+ const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
+ if ((edge_conn->rend_data && !origin_circ->rend_data) ||
+ (!edge_conn->rend_data && origin_circ->rend_data) ||
+ (edge_conn->rend_data && origin_circ->rend_data &&
+ rend_cmp_service_ids(edge_conn->rend_data->onion_address,
+ origin_circ->rend_data->onion_address))) {
/* this circ is not for this conn */
return 0;
}
}
+
+ if (!connection_edge_compatible_with_circuit(conn, origin_circ)) {
+ /* conn needs to be isolated from other conns that have already used
+ * origin_circ */
+ return 0;
+ }
+
return 1;
}
/** Return 1 if circuit <b>a</b> is better than circuit <b>b</b> for
- * <b>purpose</b>, and return 0 otherwise. Used by circuit_get_best.
+ * <b>conn</b>, and return 0 otherwise. Used by circuit_get_best.
*/
static int
-circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
+circuit_is_better(const origin_circuit_t *oa, const origin_circuit_t *ob,
+ const entry_connection_t *conn)
{
+ const circuit_t *a = TO_CIRCUIT(oa);
+ const circuit_t *b = TO_CIRCUIT(ob);
+ const uint8_t purpose = ENTRY_TO_CONN(conn)->purpose;
+ int a_bits, b_bits;
+
switch (purpose) {
case CIRCUIT_PURPOSE_C_GENERAL:
/* if it's used but less dirty it's best;
@@ -165,8 +180,7 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
if (a->timestamp_dirty ||
timercmp(&a->timestamp_created, &b->timestamp_created, >))
return 1;
- if (CIRCUIT_IS_ORIGIN(b) &&
- TO_ORIGIN_CIRCUIT(b)->build_state->is_internal)
+ if (ob->build_state->is_internal)
/* XXX023 what the heck is this internal thing doing here. I
* think we can get rid of it. circuit_is_acceptable() already
* makes sure that is_internal is exactly what we need it to
@@ -185,6 +199,29 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
return 1;
break;
}
+
+ /* XXXX023 Maybe this check should get a higher priority to avoid
+ * using up circuits too rapidly. */
+
+ a_bits = connection_edge_update_circuit_isolation(conn,
+ (origin_circuit_t*)oa, 1);
+ b_bits = connection_edge_update_circuit_isolation(conn,
+ (origin_circuit_t*)ob, 1);
+ /* if x_bits < 0, then we have not used x for anything; better not to dirty
+ * a connection if we can help it. */
+ if (a_bits < 0) {
+ return 0;
+ } else if (b_bits < 0) {
+ return 1;
+ }
+ a_bits &= ~ oa->isolation_flags_mixed;
+ a_bits &= ~ ob->isolation_flags_mixed;
+ if (n_bits_set_u8(a_bits) < n_bits_set_u8(b_bits)) {
+ /* The fewer new restrictions we need to make on a circuit for stream
+ * isolation, the better. */
+ return 1;
+ }
+
return 0;
}
@@ -205,10 +242,12 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose)
* closest introduce-purposed circuit that you can find.
*/
static origin_circuit_t *
-circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose,
+circuit_get_best(const entry_connection_t *conn,
+ int must_be_open, uint8_t purpose,
int need_uptime, int need_internal)
{
- circuit_t *circ, *best=NULL;
+ circuit_t *circ;
+ origin_circuit_t *best=NULL;
struct timeval now;
int intro_going_on_but_too_old = 0;
@@ -221,7 +260,11 @@ circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose,
tor_gettimeofday(&now);
for (circ=global_circuitlist;circ;circ = circ->next) {
- if (!circuit_is_acceptable(circ,conn,must_be_open,purpose,
+ origin_circuit_t *origin_circ;
+ if (!CIRCUIT_IS_ORIGIN(circ))
+ continue;
+ origin_circ = TO_ORIGIN_CIRCUIT(circ);
+ if (!circuit_is_acceptable(origin_circ,conn,must_be_open,purpose,
need_uptime,need_internal,now.tv_sec))
continue;
@@ -235,8 +278,8 @@ circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose,
/* now this is an acceptable circ to hand back. but that doesn't
* mean it's the *best* circ to hand back. try to decide.
*/
- if (!best || circuit_is_better(circ,best,purpose))
- best = circ;
+ if (!best || circuit_is_better(origin_circ,best,conn))
+ best = origin_circ;
}
if (!best && intro_going_on_but_too_old)
@@ -244,7 +287,28 @@ circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose,
"right now, but it has already taken quite a while. Starting "
"one in parallel.");
- return best ? TO_ORIGIN_CIRCUIT(best) : NULL;
+ return best;
+}
+
+/** Return the number of not-yet-open general-purpose origin circuits. */
+static int
+count_pending_general_client_circuits(void)
+{
+ const circuit_t *circ;
+
+ int count = 0;
+
+ for (circ = global_circuitlist; circ; circ = circ->next) {
+ if (circ->marked_for_close ||
+ circ->state == CIRCUIT_STATE_OPEN ||
+ circ->purpose != CIRCUIT_PURPOSE_C_GENERAL ||
+ !CIRCUIT_IS_ORIGIN(circ))
+ continue;
+
+ ++count;
+ }
+
+ return count;
}
#if 0
@@ -481,11 +545,11 @@ circuit_remove_handled_ports(smartlist_t *needed_ports)
* Else return 0.
*/
int
-circuit_stream_is_being_handled(edge_connection_t *conn,
+circuit_stream_is_being_handled(entry_connection_t *conn,
uint16_t port, int min)
{
circuit_t *circ;
- routerinfo_t *exitrouter;
+ const node_t *exitnode;
int num=0;
time_t now = time(NULL);
int need_uptime = smartlist_string_num_isin(get_options()->LongLivedPorts,
@@ -501,14 +565,14 @@ circuit_stream_is_being_handled(edge_connection_t *conn,
if (build_state->is_internal || build_state->onehop_tunnel)
continue;
- exitrouter = build_state_get_exit_router(build_state);
- if (exitrouter && (!need_uptime || build_state->need_uptime)) {
+ exitnode = build_state_get_exit_node(build_state);
+ if (exitnode && (!need_uptime || build_state->need_uptime)) {
int ok;
if (conn) {
- ok = connection_ap_can_use_exit(conn, exitrouter);
+ ok = connection_ap_can_use_exit(conn, exitnode);
} else {
- addr_policy_result_t r = compare_addr_to_addr_policy(
- 0, port, exitrouter->exit_policy);
+ addr_policy_result_t r;
+ r = compare_tor_addr_to_node_policy(NULL, port, exitnode);
ok = r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED;
}
if (ok) {
@@ -575,7 +639,7 @@ circuit_predict_and_launch_new(void)
log_info(LD_CIRC,
"Have %d clean circs (%d internal), need another exit circ.",
num, num_internal);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
@@ -587,7 +651,7 @@ circuit_predict_and_launch_new(void)
"Have %d clean circs (%d internal), need another internal "
"circ for my hidden service.",
num, num_internal);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
@@ -605,7 +669,7 @@ circuit_predict_and_launch_new(void)
"Have %d clean circs (%d uptime-internal, %d internal), need"
" another hidden service circ.",
num, num_uptime_internal, num_internal);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
@@ -618,7 +682,7 @@ circuit_predict_and_launch_new(void)
flags = CIRCLAUNCH_NEED_CAPACITY;
log_info(LD_CIRC,
"Have %d clean circs need another buildtime test circ.", num);
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags);
return;
}
}
@@ -635,7 +699,7 @@ void
circuit_build_needed_circs(time_t now)
{
static time_t time_to_new_circuit = 0;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* launch a new circ for any pending streams that need one */
connection_ap_attach_pending();
@@ -654,9 +718,9 @@ circuit_build_needed_circs(time_t now)
circ = circuit_get_youngest_clean_open(CIRCUIT_PURPOSE_C_GENERAL);
if (get_options()->RunTesting &&
circ &&
- circ->timestamp_created + TESTING_CIRCUIT_INTERVAL < now) {
+ circ->timestamp_created.tv_sec + TESTING_CIRCUIT_INTERVAL < now) {
log_fn(LOG_INFO,"Creating a new testing circuit.");
- circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, 0);
+ circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, 0);
}
#endif
}
@@ -675,7 +739,11 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn)
tor_assert(circ);
tor_assert(conn);
- conn->cpath_layer = NULL; /* make sure we don't keep a stale pointer */
+ if (conn->_base.type == CONN_TYPE_AP) {
+ entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
+ entry_conn->may_use_optimistic_data = 0;
+ }
+ conn->cpath_layer = NULL; /* don't keep a stale pointer */
conn->on_circuit = NULL;
if (CIRCUIT_IS_ORIGIN(circ)) {
@@ -936,6 +1004,7 @@ circuit_testing_failed(origin_circuit_t *circ, int at_last_hop)
void
circuit_has_opened(origin_circuit_t *circ)
{
+ int can_try_clearing_isolation = 0, tried_clearing_isolation = 0;
control_event_circuit_status(circ, CIRC_EVENT_BUILT, 0);
/* Remember that this circuit has finished building. Now if we start
@@ -943,9 +1012,12 @@ circuit_has_opened(origin_circuit_t *circ)
* to consider its build time. */
circ->has_opened = 1;
+ again:
+
switch (TO_CIRCUIT(circ)->purpose) {
case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
rend_client_rendcirc_has_opened(circ);
+ can_try_clearing_isolation = 1;
connection_ap_attach_pending();
break;
case CIRCUIT_PURPOSE_C_INTRODUCING:
@@ -954,6 +1026,7 @@ circuit_has_opened(origin_circuit_t *circ)
case CIRCUIT_PURPOSE_C_GENERAL:
/* Tell any AP connections that have been waiting for a new
* circuit that one is ready. */
+ can_try_clearing_isolation = 1;
connection_ap_attach_pending();
break;
case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO:
@@ -971,6 +1044,24 @@ circuit_has_opened(origin_circuit_t *circ)
* This won't happen in normal operation, but might happen if the
* controller did it. Just let it slide. */
}
+
+ if (/* The circuit may have become non-open if it was cannibalized.*/
+ circ->_base.state == CIRCUIT_STATE_OPEN &&
+ /* Only if the purpose is clearable, and only if we haven't tried
+ * to clear isolation yet, do we try. */
+ can_try_clearing_isolation && !tried_clearing_isolation &&
+ /* If !isolation_values_set, there is nothing to clear. */
+ circ->isolation_values_set &&
+ /* It's not legal to clear a circuit's isolation info if it's ever had
+ * streams attached */
+ !circ->isolation_any_streams_attached) {
+ /* If we have any isolation information set on this circuit, and
+ * we didn't manage to attach any streams to it, then we can
+ * and should clear it and try again. */
+ circuit_clear_isolation(circ);
+ tried_clearing_isolation = 1;
+ goto again;
+ }
}
/** Called whenever a circuit could not be successfully built.
@@ -1091,17 +1182,9 @@ static int did_circs_fail_last_period = 0;
/** Launch a new circuit; see circuit_launch_by_extend_info() for
* details on arguments. */
origin_circuit_t *
-circuit_launch_by_router(uint8_t purpose,
- routerinfo_t *exit, int flags)
+circuit_launch(uint8_t purpose, int flags)
{
- origin_circuit_t *circ;
- extend_info_t *info = NULL;
- if (exit)
- info = extend_info_from_router(exit);
- circ = circuit_launch_by_extend_info(purpose, info, flags);
-
- extend_info_free(info);
- return circ;
+ return circuit_launch_by_extend_info(purpose, NULL, flags);
}
/** Launch a new circuit with purpose <b>purpose</b> and exit node
@@ -1207,7 +1290,7 @@ circuit_reset_failure_count(int timeout)
* Write the found or in-progress or launched circ into *circp.
*/
static int
-circuit_get_open_circ_or_launch(edge_connection_t *conn,
+circuit_get_open_circ_or_launch(entry_connection_t *conn,
uint8_t desired_circuit_purpose,
origin_circuit_t **circp)
{
@@ -1215,15 +1298,15 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
int check_exit_policy;
int need_uptime, need_internal;
int want_onehop;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert(conn);
tor_assert(circp);
- tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
+ tor_assert(ENTRY_TO_CONN(conn)->state == AP_CONN_STATE_CIRCUIT_WAIT);
check_exit_policy =
conn->socks_request->command == SOCKS_COMMAND_CONNECT &&
!conn->use_begindir &&
- !connection_edge_is_rendezvous_stream(conn);
+ !connection_edge_is_rendezvous_stream(ENTRY_TO_EDGE_CONN(conn));
want_onehop = conn->want_onehop;
need_uptime = !conn->want_onehop && !conn->use_begindir &&
@@ -1269,12 +1352,14 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
if (check_exit_policy) {
if (!conn->chosen_exit_name) {
struct in_addr in;
- uint32_t addr = 0;
- if (tor_inet_aton(conn->socks_request->address, &in))
- addr = ntohl(in.s_addr);
- if (router_exit_policy_all_routers_reject(addr,
- conn->socks_request->port,
- need_uptime)) {
+ tor_addr_t addr, *addrp=NULL;
+ if (tor_inet_aton(conn->socks_request->address, &in)) {
+ tor_addr_from_in(&addr, &in);
+ addrp = &addr;
+ }
+ if (router_exit_policy_all_nodes_reject(addrp,
+ conn->socks_request->port,
+ need_uptime)) {
log_notice(LD_APP,
"No Tor server allows exit to %s:%d. Rejecting.",
safe_str_client(conn->socks_request->address),
@@ -1284,9 +1369,9 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
} else {
/* XXXX023 Duplicates checks in connection_ap_handshake_attach_circuit:
* refactor into a single function? */
- routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1);
+ const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1);
int opt = conn->chosen_exit_optional;
- if (router && !connection_ap_can_use_exit(conn, router)) {
+ if (node && !connection_ap_can_use_exit(conn, node)) {
log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
"Requested exit point '%s' is excluded or "
"would refuse request. %s.",
@@ -1312,22 +1397,37 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
if (!circ) {
extend_info_t *extend_info=NULL;
uint8_t new_circ_purpose;
+ const int n_pending = count_pending_general_client_circuits();
+
+ if (n_pending >= options->MaxClientCircuitsPending) {
+ static ratelim_t delay_limit = RATELIM_INIT(10*60);
+ char *m;
+ if ((m = rate_limit_log(&delay_limit, approx_time()))) {
+ log_notice(LD_APP, "We'd like to launch a circuit to handle a "
+ "connection, but we already have %d general-purpose client "
+ "circuits pending. Waiting until some finish.",
+ n_pending);
+ tor_free(m);
+ }
+ return 0;
+ }
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
/* need to pick an intro point */
- tor_assert(conn->rend_data);
- extend_info = rend_client_get_random_intro(conn->rend_data);
+ rend_data_t *rend_data = ENTRY_TO_EDGE_CONN(conn)->rend_data;
+ tor_assert(rend_data);
+ extend_info = rend_client_get_random_intro(rend_data);
if (!extend_info) {
log_info(LD_REND,
"No intro points for '%s': re-fetching service descriptor.",
- safe_str_client(conn->rend_data->onion_address));
- rend_client_refetch_v2_renddesc(conn->rend_data);
- conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT;
+ safe_str_client(rend_data->onion_address));
+ rend_client_refetch_v2_renddesc(rend_data);
+ ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_RENDDESC_WAIT;
return 0;
}
log_info(LD_REND,"Chose %s as intro point for '%s'.",
extend_info_describe(extend_info),
- safe_str_client(conn->rend_data->onion_address));
+ safe_str_client(rend_data->onion_address));
}
/* If we have specified a particular exit node for our
@@ -1335,11 +1435,11 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
*/
if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) {
if (conn->chosen_exit_name) {
- routerinfo_t *r;
+ const node_t *r;
int opt = conn->chosen_exit_optional;
- r = router_get_by_nickname(conn->chosen_exit_name, 1);
- if (r) {
- extend_info = extend_info_from_router(r);
+ r = node_get_by_nickname(conn->chosen_exit_name, 1);
+ if (r && node_has_descriptor(r)) {
+ extend_info = extend_info_from_node(r);
} else {
log_debug(LD_DIR, "considering %d, %s",
want_onehop, conn->chosen_exit_name);
@@ -1416,18 +1516,26 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn,
rep_hist_note_used_internal(time(NULL), need_uptime, 1);
if (circ) {
/* write the service_id into circ */
- circ->rend_data = rend_data_dup(conn->rend_data);
+ circ->rend_data = rend_data_dup(ENTRY_TO_EDGE_CONN(conn)->rend_data);
if (circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
circ->_base.state == CIRCUIT_STATE_OPEN)
rend_client_rendcirc_has_opened(circ);
}
}
- }
- if (!circ)
+ } /* endif (!circ) */
+ if (circ) {
+ /* Mark the circuit with the isolation fields for this connection.
+ * When the circuit arrives, we'll clear these flags: this is
+ * just some internal bookkeeping to make sure that we have
+ * launched enough circuits.
+ */
+ connection_edge_update_circuit_isolation(conn, circ, 0);
+ } else {
log_info(LD_APP,
"No safe circuit (purpose %d) ready for edge "
"connection; delaying.",
desired_circuit_purpose);
+ }
*circp = circ;
return 0;
}
@@ -1446,39 +1554,86 @@ cpath_is_on_circuit(origin_circuit_t *circ, crypt_path_t *crypt_path)
return 0;
}
+/** Return true iff client-side optimistic data is supported. */
+static int
+optimistic_data_enabled(void)
+{
+ const or_options_t *options = get_options();
+ if (options->OptimisticData < 0) {
+ /* XXX023 consider having auto default to 1 rather than 0 before
+ * the 0.2.3 branch goes stable. See bug 3617. -RD */
+ const int32_t enabled =
+ networkstatus_get_param(NULL, "UseOptimisticData", 0, 0, 1);
+ return (int)enabled;
+ }
+ return options->OptimisticData;
+}
+
/** Attach the AP stream <b>apconn</b> to circ's linked list of
* p_streams. Also set apconn's cpath_layer to <b>cpath</b>, or to the last
* hop in circ's cpath if <b>cpath</b> is NULL.
*/
static void
-link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ,
+link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ,
crypt_path_t *cpath)
{
+ const node_t *exitnode;
+
/* add it into the linked list of streams on this circuit */
log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %d.",
circ->_base.n_circ_id);
/* reset it, so we can measure circ timeouts */
- apconn->_base.timestamp_lastread = time(NULL);
- apconn->next_stream = circ->p_streams;
- apconn->on_circuit = TO_CIRCUIT(circ);
+ ENTRY_TO_CONN(apconn)->timestamp_lastread = time(NULL);
+ ENTRY_TO_EDGE_CONN(apconn)->next_stream = circ->p_streams;
+ ENTRY_TO_EDGE_CONN(apconn)->on_circuit = TO_CIRCUIT(circ);
/* assert_connection_ok(conn, time(NULL)); */
- circ->p_streams = apconn;
+ circ->p_streams = ENTRY_TO_EDGE_CONN(apconn);
+
+ if (connection_edge_is_rendezvous_stream(ENTRY_TO_EDGE_CONN(apconn))) {
+ /* We are attaching a stream to a rendezvous circuit. That means
+ * that an attempt to connect to a hidden service just
+ * succeeded. Tell rendclient.c. */
+ rend_client_note_connection_attempt_ended(
+ ENTRY_TO_EDGE_CONN(apconn)->rend_data->onion_address);
+ }
if (cpath) { /* we were given one; use it */
tor_assert(cpath_is_on_circuit(circ, cpath));
- apconn->cpath_layer = cpath;
- } else { /* use the last hop in the circuit */
+ } else {
+ /* use the last hop in the circuit */
tor_assert(circ->cpath);
tor_assert(circ->cpath->prev);
tor_assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
- apconn->cpath_layer = circ->cpath->prev;
+ cpath = circ->cpath->prev;
+ }
+ ENTRY_TO_EDGE_CONN(apconn)->cpath_layer = cpath;
+
+ circ->isolation_any_streams_attached = 1;
+ connection_edge_update_circuit_isolation(apconn, circ, 0);
+
+ /* See if we can use optimistic data on this circuit */
+ if (cpath->extend_info &&
+ (exitnode = node_get_by_id(cpath->extend_info->identity_digest)) &&
+ exitnode->rs) {
+ /* Okay; we know what exit node this is. */
+ if (optimistic_data_enabled() &&
+ circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL &&
+ exitnode->rs->version_supports_optimistic_data)
+ apconn->may_use_optimistic_data = 1;
+ else
+ apconn->may_use_optimistic_data = 0;
+ log_info(LD_APP, "Looks like completed circuit to %s %s allow "
+ "optimistic data for connection to %s",
+ safe_str_client(node_describe(exitnode)),
+ apconn->may_use_optimistic_data ? "does" : "doesn't",
+ safe_str_client(apconn->socks_request->address));
}
}
/** Return true iff <b>address</b> is matched by one of the entries in
* TrackHostExits. */
int
-hostname_in_track_host_exits(or_options_t *options, const char *address)
+hostname_in_track_host_exits(const or_options_t *options, const char *address)
{
if (!options->TrackHostExits)
return 0;
@@ -1500,9 +1655,10 @@ hostname_in_track_host_exits(or_options_t *options, const char *address)
* <b>conn</b>'s destination.
*/
static void
-consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ)
+consider_recording_trackhost(const entry_connection_t *conn,
+ const origin_circuit_t *circ)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char *new_address = NULL;
char fp[HEX_DIGEST_LEN+1];
@@ -1537,18 +1693,19 @@ consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ)
* indicated by <b>cpath</b>, or from the last hop in circ's cpath if
* <b>cpath</b> is NULL. */
int
-connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
+connection_ap_handshake_attach_chosen_circuit(entry_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath)
{
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
tor_assert(conn);
- tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT ||
- conn->_base.state == AP_CONN_STATE_CONTROLLER_WAIT);
+ tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT ||
+ base_conn->state == AP_CONN_STATE_CONTROLLER_WAIT);
tor_assert(conn->socks_request);
tor_assert(circ);
tor_assert(circ->_base.state == CIRCUIT_STATE_OPEN);
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
if (!circ->_base.timestamp_dirty)
circ->_base.timestamp_dirty = time(NULL);
@@ -1578,21 +1735,22 @@ connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
/* XXXX this function should mark for close whenever it returns -1;
* its callers shouldn't have to worry about that. */
int
-connection_ap_handshake_attach_circuit(edge_connection_t *conn)
+connection_ap_handshake_attach_circuit(entry_connection_t *conn)
{
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
int retval;
int conn_age;
int want_onehop;
tor_assert(conn);
- tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
+ tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(conn->socks_request);
want_onehop = conn->want_onehop;
- conn_age = (int)(time(NULL) - conn->_base.timestamp_created);
+ conn_age = (int)(time(NULL) - base_conn->timestamp_created);
if (conn_age >= get_options()->SocksTimeout) {
- int severity = (tor_addr_is_null(&conn->_base.addr) && !conn->_base.port) ?
+ int severity = (tor_addr_is_null(&base_conn->addr) && !base_conn->port) ?
LOG_INFO : LOG_NOTICE;
log_fn(severity, LD_APP,
"Tried for %d seconds to get a connection to %s:%d. Giving up.",
@@ -1601,13 +1759,14 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
return -1;
}
- if (!connection_edge_is_rendezvous_stream(conn)) { /* we're a general conn */
+ if (!connection_edge_is_rendezvous_stream(ENTRY_TO_EDGE_CONN(conn))) {
+ /* we're a general conn */
origin_circuit_t *circ=NULL;
if (conn->chosen_exit_name) {
- routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1);
+ const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1);
int opt = conn->chosen_exit_optional;
- if (!router && !want_onehop) {
+ if (!node && !want_onehop) {
/* We ran into this warning when trying to extend a circuit to a
* hidden service directory for which we didn't have a router
* descriptor. See flyspray task 767 for more details. We should
@@ -1623,7 +1782,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
}
return -1;
}
- if (router && !connection_ap_can_use_exit(conn, router)) {
+ if (node && !connection_ap_can_use_exit(conn, node)) {
log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP,
"Requested exit point '%s' is excluded or "
"would refuse request. %s.",
@@ -1656,7 +1815,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
} else { /* we're a rendezvous conn */
origin_circuit_t *rendcirc=NULL, *introcirc=NULL;
- tor_assert(!conn->cpath_layer);
+ tor_assert(!ENTRY_TO_EDGE_CONN(conn)->cpath_layer);
/* start by finding a rendezvous circuit for us */
@@ -1712,8 +1871,9 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
!c->marked_for_close && CIRCUIT_IS_ORIGIN(c)) {
origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(c);
if (oc->rend_data &&
- !rend_cmp_service_ids(conn->rend_data->onion_address,
- oc->rend_data->onion_address)) {
+ !rend_cmp_service_ids(
+ ENTRY_TO_EDGE_CONN(conn)->rend_data->onion_address,
+ oc->rend_data->onion_address)) {
log_info(LD_REND|LD_CIRC, "Closing introduction circuit that we "
"built in parallel.");
circuit_mark_for_close(c, END_CIRC_REASON_TIMEOUT);
diff --git a/src/or/circuituse.h b/src/or/circuituse.h
index bfeaea20d..9867fd820 100644
--- a/src/or/circuituse.h
+++ b/src/or/circuituse.h
@@ -14,7 +14,7 @@
void circuit_expire_building(void);
void circuit_remove_handled_ports(smartlist_t *needed_ports);
-int circuit_stream_is_being_handled(edge_connection_t *conn, uint16_t port,
+int circuit_stream_is_being_handled(entry_connection_t *conn, uint16_t port,
int min);
#if 0
int circuit_conforms_to_options(const origin_circuit_t *circ,
@@ -43,15 +43,15 @@ void circuit_build_failed(origin_circuit_t *circ);
origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose,
extend_info_t *info,
int flags);
-origin_circuit_t *circuit_launch_by_router(uint8_t purpose,
- routerinfo_t *exit, int flags);
+origin_circuit_t *circuit_launch(uint8_t purpose, int flags);
void circuit_reset_failure_count(int timeout);
-int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn,
+int connection_ap_handshake_attach_chosen_circuit(entry_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath);
-int connection_ap_handshake_attach_circuit(edge_connection_t *conn);
+int connection_ap_handshake_attach_circuit(entry_connection_t *conn);
-int hostname_in_track_host_exits(or_options_t *options, const char *address);
+int hostname_in_track_host_exits(const or_options_t *options,
+ const char *address);
#endif
diff --git a/src/or/command.c b/src/or/command.c
index 12b4c30f5..d24373eec 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -25,6 +25,7 @@
#include "control.h"
#include "cpuworker.h"
#include "hibernate.h"
+#include "nodelist.h"
#include "onion.h"
#include "relay.h"
#include "router.h"
@@ -267,15 +268,18 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn)
}
if (circuit_id_in_use_on_orconn(cell->circ_id, conn)) {
- routerinfo_t *router = router_get_by_digest(conn->identity_digest);
+ const node_t *node = node_get_by_id(conn->identity_digest);
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Received CREATE cell (circID %d) for known circ. "
"Dropping (age %d).",
cell->circ_id, (int)(time(NULL) - conn->_base.timestamp_created));
- if (router)
+ if (node) {
+ char *p = esc_for_log(node_get_platform(node));
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Details: router %s, platform %s.",
- router_describe(router), escaped(router->platform));
+ node_describe(node), p);
+ tor_free(p);
+ }
return;
}
@@ -620,7 +624,7 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
/** Warn when we get a netinfo skew with at least this value. */
#define NETINFO_NOTICE_SKEW 3600
if (labs(apparent_skew) > NETINFO_NOTICE_SKEW &&
- router_get_by_digest(conn->identity_digest)) {
+ router_get_by_id_digest(conn->identity_digest)) {
char dbuf[64];
int severity;
/*XXXX be smarter about when everybody says we are skewed. */
diff --git a/src/or/config.c b/src/or/config.c
index 7202ea254..2705ba5a1 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -33,13 +33,18 @@
#include "rendservice.h"
#include "rephist.h"
#include "router.h"
+#include "util.h"
#include "routerlist.h"
+#include "transports.h"
#ifdef MS_WINDOWS
#include <shlobj.h>
#endif
#include "procmon.h"
+/* From main.c */
+extern int quiet_level;
+
/** Enumeration of types which option values can take */
typedef enum config_type_t {
CONFIG_TYPE_STRING = 0, /**< An arbitrary string. */
@@ -48,9 +53,13 @@ typedef enum config_type_t {
CONFIG_TYPE_PORT, /**< A port from 1...65535, 0 for "not set", or
* "auto". */
CONFIG_TYPE_INTERVAL, /**< A number of seconds, with optional units*/
+ CONFIG_TYPE_MSEC_INTERVAL,/**< A number of milliseconds, with optional
+ * units */
CONFIG_TYPE_MEMUNIT, /**< A number of bytes, with optional units*/
CONFIG_TYPE_DOUBLE, /**< A floating-point value */
CONFIG_TYPE_BOOL, /**< A boolean value, expressed as 0 or 1. */
+ CONFIG_TYPE_AUTOBOOL, /**< A boolean+auto value, expressed 0 for false,
+ * 1 for true, and -1 for auto */
CONFIG_TYPE_ISOTIME, /**< An ISO-formatted time relative to GMT. */
CONFIG_TYPE_CSV, /**< A list of strings, separated by commas and
* optional whitespace. */
@@ -199,10 +208,12 @@ static config_var_t _option_vars[] = {
V(CircuitStreamTimeout, INTERVAL, "0"),
V(CircuitPriorityHalflife, DOUBLE, "-100.0"), /*negative:'Use default'*/
V(ClientDNSRejectInternalAddresses, BOOL,"1"),
- V(ClientRejectInternalAddresses, BOOL, "1"),
V(ClientOnly, BOOL, "0"),
+ V(ClientRejectInternalAddresses, BOOL, "1"),
+ V(ClientTransportPlugin, LINELIST, NULL),
V(ConsensusParams, STRING, NULL),
V(ConnLimit, UINT, "1000"),
+ V(ConnDirectionStatistics, BOOL, "0"),
V(ConstrainedSockets, BOOL, "0"),
V(ConstrainedSockSize, MEMUNIT, "8192"),
V(ContactInfo, STRING, NULL),
@@ -215,6 +226,7 @@ static config_var_t _option_vars[] = {
V(CookieAuthentication, BOOL, "0"),
V(CookieAuthFileGroupReadable, BOOL, "0"),
V(CookieAuthFile, STRING, NULL),
+ V(CountPrivateBandwidth, BOOL, "0"),
V(DataDirectory, FILENAME, NULL),
OBSOLETE("DebugLogFile"),
V(DirAllowPrivateAddresses, BOOL, NULL),
@@ -229,10 +241,11 @@ static config_var_t _option_vars[] = {
OBSOLETE("DirRecordUsageGranularity"),
OBSOLETE("DirRecordUsageRetainIPs"),
OBSOLETE("DirRecordUsageSaveInterval"),
- V(DirReqStatistics, BOOL, "0"),
+ V(DirReqStatistics, BOOL, "1"),
VAR("DirServer", LINELIST, DirServers, NULL),
V(DisableAllSwap, BOOL, "0"),
- V(DNSPort, PORT, "0"),
+ V(DisableIOCP, BOOL, "1"),
+ V(DNSPort, LINELIST, NULL),
V(DNSListenAddress, LINELIST, NULL),
V(DownloadExtraInfo, BOOL, "0"),
V(EnforceDistinctSubnets, BOOL, "1"),
@@ -246,7 +259,7 @@ static config_var_t _option_vars[] = {
V(ExitPolicy, LINELIST, NULL),
V(ExitPolicyRejectPrivate, BOOL, "1"),
V(ExitPortStatistics, BOOL, "0"),
- V(ExtraInfoStatistics, BOOL, "0"),
+ V(ExtraInfoStatistics, BOOL, "1"),
#if defined (WINCE)
V(FallbackNetworkstatusFile, FILENAME, "fallback-consensus"),
@@ -271,6 +284,7 @@ static config_var_t _option_vars[] = {
#endif
OBSOLETE("Group"),
V(HardwareAccel, BOOL, "0"),
+ V(HeartbeatPeriod, INTERVAL, "6 hours"),
V(AccelName, STRING, NULL),
V(AccelDir, FILENAME, NULL),
V(HashedControlPassword, LINELIST, NULL),
@@ -289,6 +303,7 @@ static config_var_t _option_vars[] = {
V(HTTPProxyAuthenticator, STRING, NULL),
V(HTTPSProxy, STRING, NULL),
V(HTTPSProxyAuthenticator, STRING, NULL),
+ VAR("ServerTransportPlugin", LINELIST, ServerTransportPlugin, NULL),
V(Socks4Proxy, STRING, NULL),
V(Socks5Proxy, STRING, NULL),
V(Socks5ProxyUsername, STRING, NULL),
@@ -300,23 +315,25 @@ static config_var_t _option_vars[] = {
OBSOLETE("LinkPadding"),
OBSOLETE("LogLevel"),
OBSOLETE("LogFile"),
+ V(LogTimeGranularity, MSEC_INTERVAL, "1 second"),
V(LongLivedPorts, CSV,
- "21,22,706,1863,5050,5190,5222,5223,6667,6697,8300"),
+ "21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"),
VAR("MapAddress", LINELIST, AddressMap, NULL),
V(MaxAdvertisedBandwidth, MEMUNIT, "1 GB"),
V(MaxCircuitDirtiness, INTERVAL, "10 minutes"),
+ V(MaxClientCircuitsPending, UINT, "32"),
V(MaxOnionsPending, UINT, "100"),
OBSOLETE("MonthlyAccountingStart"),
V(MyFamily, STRING, NULL),
V(NewCircuitPeriod, INTERVAL, "30 seconds"),
VAR("NamingAuthoritativeDirectory",BOOL, NamingAuthoritativeDir, "0"),
V(NATDListenAddress, LINELIST, NULL),
- V(NATDPort, PORT, "0"),
+ V(NATDPort, LINELIST, NULL),
V(Nickname, STRING, NULL),
V(WarnUnsafeSocks, BOOL, "1"),
OBSOLETE("NoPublish"),
VAR("NodeFamily", LINELIST, NodeFamilies, NULL),
- V(NumCPUs, UINT, "1"),
+ V(NumCPUs, UINT, "0"),
V(NumEntryGuards, UINT, "3"),
V(ORListenAddress, LINELIST, NULL),
V(ORPort, PORT, "0"),
@@ -326,6 +343,9 @@ static config_var_t _option_vars[] = {
V(PerConnBWRate, MEMUNIT, "0"),
V(PidFile, STRING, NULL),
V(TestingTorNetwork, BOOL, "0"),
+ V(OptimisticData, AUTOBOOL, "auto"),
+ V(PortForwarding, BOOL, "0"),
+ V(PortForwardingHelper, FILENAME, "tor-fw-helper"),
V(PreferTunneledDirConns, BOOL, "1"),
V(ProtocolWarnings, BOOL, "0"),
V(PublishServerDescriptor, CSV, "1"),
@@ -337,7 +357,7 @@ static config_var_t _option_vars[] = {
V(RecommendedClientVersions, LINELIST, NULL),
V(RecommendedServerVersions, LINELIST, NULL),
OBSOLETE("RedirectExit"),
- V(RefuseUnknownExits, STRING, "auto"),
+ V(RefuseUnknownExits, AUTOBOOL, "auto"),
V(RejectPlaintextPorts, CSV, ""),
V(RelayBandwidthBurst, MEMUNIT, "0"),
V(RelayBandwidthRate, MEMUNIT, "0"),
@@ -362,22 +382,24 @@ static config_var_t _option_vars[] = {
V(ShutdownWaitLength, INTERVAL, "30 seconds"),
V(SocksListenAddress, LINELIST, NULL),
V(SocksPolicy, LINELIST, NULL),
- V(SocksPort, PORT, "9050"),
+ V(SocksPort, LINELIST, NULL),
V(SocksTimeout, INTERVAL, "2 minutes"),
OBSOLETE("StatusFetchPeriod"),
V(StrictNodes, BOOL, "0"),
OBSOLETE("SysLog"),
V(TestSocks, BOOL, "0"),
OBSOLETE("TestVia"),
+ V(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"),
V(TrackHostExits, CSV, NULL),
V(TrackHostExitsExpire, INTERVAL, "30 minutes"),
OBSOLETE("TrafficShaping"),
V(TransListenAddress, LINELIST, NULL),
- V(TransPort, PORT, "0"),
+ V(TransPort, LINELIST, NULL),
V(TunnelDirConns, BOOL, "1"),
V(UpdateBridgesFromAuthority, BOOL, "0"),
V(UseBridges, BOOL, "0"),
V(UseEntryGuards, BOOL, "1"),
+ V(UseMicrodescriptors, AUTOBOOL, "auto"),
V(User, STRING, NULL),
VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
VAR("V2AuthoritativeDirectory",BOOL, V2AuthoritativeDir, "0"),
@@ -394,6 +416,7 @@ static config_var_t _option_vars[] = {
VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"),
V(VirtualAddrNetwork, STRING, "127.192.0.0/10"),
V(WarnPlaintextPorts, CSV, "23,109,110,143"),
+ V(_UseFilteringSSLBufferevents, BOOL, "0"),
VAR("__ReloadTorrcOnSIGHUP", BOOL, ReloadTorrcOnSIGHUP, "1"),
VAR("__AllDirActionsPrivate", BOOL, AllDirActionsPrivate, "0"),
VAR("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"),
@@ -401,7 +424,8 @@ static config_var_t _option_vars[] = {
VAR("__HashedControlSessionPassword", LINELIST, HashedControlSessionPassword,
NULL),
VAR("__OwningControllerProcess",STRING,OwningControllerProcess, NULL),
- V(MinUptimeHidServDirectoryV2, INTERVAL, "24 hours"),
+ V(MinUptimeHidServDirectoryV2, INTERVAL, "25 hours"),
+ V(VoteOnHidServDirectoriesV2, BOOL, "1"),
V(_UsingTestNetworkDefaults, BOOL, "0"),
{ NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
@@ -409,7 +433,7 @@ static config_var_t _option_vars[] = {
/** Override default values with these if the user sets the TestingTorNetwork
* option. */
-static config_var_t testing_tor_network_defaults[] = {
+static const config_var_t testing_tor_network_defaults[] = {
V(ServerDNSAllowBrokenConfig, BOOL, "1"),
V(DirAllowPrivateAddresses, BOOL, "1"),
V(EnforceDistinctSubnets, BOOL, "0"),
@@ -418,6 +442,7 @@ static config_var_t testing_tor_network_defaults[] = {
V(AuthDirMaxServersPerAuthAddr,UINT, "0"),
V(ClientDNSRejectInternalAddresses, BOOL,"0"),
V(ClientRejectInternalAddresses, BOOL, "0"),
+ V(CountPrivateBandwidth, BOOL, "1"),
V(ExitPolicyRejectPrivate, BOOL, "0"),
V(V3AuthVotingInterval, INTERVAL, "5 minutes"),
V(V3AuthVoteDelay, INTERVAL, "20 seconds"),
@@ -429,6 +454,7 @@ static config_var_t testing_tor_network_defaults[] = {
V(TestingEstimatedDescriptorPropagationTime, INTERVAL, "0 minutes"),
V(MinUptimeHidServDirectoryV2, INTERVAL, "0 minutes"),
V(_UsingTestNetworkDefaults, BOOL, "1"),
+
{ NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
};
#undef VAR
@@ -454,6 +480,9 @@ static config_var_t _state_vars[] = {
VAR("EntryGuardAddedBy", LINELIST_S, EntryGuards, NULL),
V(EntryGuards, LINELIST_V, NULL),
+ VAR("TransportProxy", LINELIST_S, TransportProxies, NULL),
+ V(TransportProxies, LINELIST_V, NULL),
+
V(BWHistoryReadEnds, ISOTIME, NULL),
V(BWHistoryReadInterval, UINT, "900"),
V(BWHistoryReadValues, CSV, ""),
@@ -480,7 +509,6 @@ static config_var_t _state_vars[] = {
V(CircuitBuildAbandonedCount, UINT, "0"),
VAR("CircuitBuildTimeBin", LINELIST_S, BuildtimeHistogram, NULL),
VAR("BuildtimeHistogram", LINELIST_V, BuildtimeHistogram, NULL),
-
{ NULL, CONFIG_TYPE_OBSOLETE, 0, NULL }
};
@@ -531,39 +559,48 @@ static char *get_windows_conf_root(void);
#endif
static void config_line_append(config_line_t **lst,
const char *key, const char *val);
-static void option_clear(config_format_t *fmt, or_options_t *options,
- config_var_t *var);
-static void option_reset(config_format_t *fmt, or_options_t *options,
- config_var_t *var, int use_defaults);
-static void config_free(config_format_t *fmt, void *options);
+static void option_clear(const config_format_t *fmt, or_options_t *options,
+ const config_var_t *var);
+static void option_reset(const config_format_t *fmt, or_options_t *options,
+ const config_var_t *var, int use_defaults);
+static void config_free(const config_format_t *fmt, void *options);
static int config_lines_eq(config_line_t *a, config_line_t *b);
-static int option_is_same(config_format_t *fmt,
- or_options_t *o1, or_options_t *o2,
+static int option_is_same(const config_format_t *fmt,
+ const or_options_t *o1, const or_options_t *o2,
const char *name);
-static or_options_t *options_dup(config_format_t *fmt, or_options_t *old);
-static int options_validate(or_options_t *old_options, or_options_t *options,
+static or_options_t *options_dup(const config_format_t *fmt,
+ const or_options_t *old);
+static int options_validate(or_options_t *old_options,
+ or_options_t *options,
int from_setconf, char **msg);
-static int options_act_reversible(or_options_t *old_options, char **msg);
-static int options_act(or_options_t *old_options);
-static int options_transition_allowed(or_options_t *old, or_options_t *new,
+static int options_act_reversible(const or_options_t *old_options, char **msg);
+static int options_act(const or_options_t *old_options);
+static int options_transition_allowed(const or_options_t *old,
+ const or_options_t *new,
char **msg);
-static int options_transition_affects_workers(or_options_t *old_options,
- or_options_t *new_options);
-static int options_transition_affects_descriptor(or_options_t *old_options,
- or_options_t *new_options);
+static int options_transition_affects_workers(
+ const or_options_t *old_options, const or_options_t *new_options);
+static int options_transition_affects_descriptor(
+ const or_options_t *old_options, const or_options_t *new_options);
static int check_nickname_list(const char *lst, const char *name, char **msg);
-static void config_register_addressmaps(or_options_t *options);
static int parse_bridge_line(const char *line, int validate_only);
+static int parse_client_transport_line(const char *line, int validate_only);
+
+static int parse_server_transport_line(const char *line, int validate_only);
static int parse_dir_server_line(const char *line,
- authority_type_t required_type,
+ dirinfo_type_t required_type,
int validate_only);
+static void port_cfg_free(port_cfg_t *port);
+static int parse_client_ports(const or_options_t *options, int validate_only,
+ char **msg_out, int *n_ports_out);
static int validate_data_directory(or_options_t *options);
-static int write_configuration_file(const char *fname, or_options_t *options);
-static config_line_t *get_assigned_option(config_format_t *fmt,
- void *options, const char *key,
- int escape_val);
-static void config_init(config_format_t *fmt, void *options);
+static int write_configuration_file(const char *fname,
+ const or_options_t *options);
+static config_line_t *get_assigned_option(const config_format_t *fmt,
+ const void *options, const char *key,
+ int escape_val);
+static void config_init(const config_format_t *fmt, void *options);
static int or_state_validate(or_state_t *old_options, or_state_t *options,
int from_setconf, char **msg);
static int or_state_load(void);
@@ -573,8 +610,9 @@ static int is_listening_on_low_port(int port_option,
const config_line_t *listen_options);
static uint64_t config_parse_memunit(const char *s, int *ok);
+static int config_parse_msec_interval(const char *s, int *ok);
static int config_parse_interval(const char *s, int *ok);
-static void init_libevent(void);
+static void init_libevent(const or_options_t *options);
static int opt_streq(const char *s1, const char *s2);
/** Magic value for or_options_t. */
@@ -601,7 +639,7 @@ static config_var_t state_extra_var = {
};
/** Configuration format for or_state_t. */
-static config_format_t state_format = {
+static const config_format_t state_format = {
sizeof(or_state_t),
OR_STATE_MAGIC,
STRUCT_OFFSET(or_state_t, _magic),
@@ -625,6 +663,8 @@ static or_state_t *global_state = NULL;
static config_line_t *global_cmdline_options = NULL;
/** Contents of most recently read DirPortFrontPage file. */
static char *global_dirfrontpagecontents = NULL;
+/** List of port_cfg_t for client-level (SOCKS, DNS, Trans, NATD) ports. */
+static smartlist_t *configured_client_ports = NULL;
/** Return the contents of our frontpage string, or NULL if not configured. */
const char *
@@ -635,7 +675,7 @@ get_dirportfrontpage(void)
/** Allocate an empty configuration object of a given format type. */
static void *
-config_alloc(config_format_t *fmt)
+config_alloc(const config_format_t *fmt)
{
void *opts = tor_malloc_zero(fmt->size);
*(uint32_t*)STRUCT_VAR_P(opts, fmt->magic_offset) = fmt->magic;
@@ -645,12 +685,19 @@ config_alloc(config_format_t *fmt)
/** Return the currently configured options. */
or_options_t *
-get_options(void)
+get_options_mutable(void)
{
tor_assert(global_options);
return global_options;
}
+/** Returns the currently configured options */
+const or_options_t *
+get_options(void)
+{
+ return get_options_mutable();
+}
+
/** Change the current global options to contain <b>new_val</b> instead of
* their current value; take action based on the new value; free the old value
* as necessary. Returns 0 on success, -1 on failure.
@@ -658,6 +705,9 @@ get_options(void)
int
set_options(or_options_t *new_val, char **msg)
{
+ int i;
+ smartlist_t *elements;
+ config_line_t *line;
or_options_t *old_options = global_options;
global_options = new_val;
/* Note that we pass the *old* options below, for comparison. It
@@ -672,7 +722,34 @@ set_options(or_options_t *new_val, char **msg)
"Acting on config options left us in a broken state. Dying.");
exit(1);
}
-
+ /* Issues a CONF_CHANGED event to notify controller of the change. If Tor is
+ * just starting up then the old_options will be undefined. */
+ if (old_options) {
+ elements = smartlist_create();
+ for (i=0; options_format.vars[i].name; ++i) {
+ const config_var_t *var = &options_format.vars[i];
+ const char *var_name = var->name;
+ if (var->type == CONFIG_TYPE_LINELIST_S ||
+ var->type == CONFIG_TYPE_OBSOLETE) {
+ continue;
+ }
+ if (!option_is_same(&options_format, new_val, old_options, var_name)) {
+ line = get_assigned_option(&options_format, new_val, var_name, 1);
+
+ if (line) {
+ for (; line; line = line->next) {
+ smartlist_add(elements, line->key);
+ smartlist_add(elements, line->value);
+ }
+ } else {
+ smartlist_add(elements, (char*)options_format.vars[i].name);
+ smartlist_add(elements, NULL);
+ }
+ }
+ }
+ control_event_conf_changed(elements);
+ smartlist_free(elements);
+ }
config_free(&options_format, old_options);
return 0;
@@ -708,6 +785,11 @@ or_options_free(or_options_t *options)
return;
routerset_free(options->_ExcludeExitNodesUnion);
+ if (options->NodeFamilySets) {
+ SMARTLIST_FOREACH(options->NodeFamilySets, routerset_t *,
+ rs, routerset_free(rs));
+ smartlist_free(options->NodeFamilySets);
+ }
config_free(&options_format, options);
}
@@ -725,6 +807,13 @@ config_free_all(void)
config_free_lines(global_cmdline_options);
global_cmdline_options = NULL;
+ if (configured_client_ports) {
+ SMARTLIST_FOREACH(configured_client_ports,
+ port_cfg_t *, p, tor_free(p));
+ smartlist_free(configured_client_ports);
+ configured_client_ports = NULL;
+ }
+
tor_free(torrc_fname);
tor_free(_version);
tor_free(global_dirfrontpagecontents);
@@ -790,7 +879,7 @@ escaped_safe_str(const char *address)
/** Add the default directory authorities directly into the trusted dir list,
* but only add them insofar as they share bits with <b>type</b>. */
static void
-add_default_trusted_dir_authorities(authority_type_t type)
+add_default_trusted_dir_authorities(dirinfo_type_t type)
{
int i;
const char *dirservers[] = {
@@ -864,16 +953,16 @@ validate_dir_authorities(or_options_t *options, or_options_t *old_options)
/* Now go through the four ways you can configure an alternate
* set of directory authorities, and make sure none are broken. */
for (cl = options->DirServers; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
for (cl = options->AlternateDirAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
for (cl = options->AlternateHSAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 1)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 1)<0)
return -1;
return 0;
}
@@ -882,8 +971,8 @@ validate_dir_authorities(or_options_t *options, or_options_t *old_options)
* as appropriate.
*/
static int
-consider_adding_dir_authorities(or_options_t *options,
- or_options_t *old_options)
+consider_adding_dir_authorities(const or_options_t *options,
+ const or_options_t *old_options)
{
config_line_t *cl;
int need_to_update =
@@ -904,27 +993,28 @@ consider_adding_dir_authorities(or_options_t *options,
if (!options->DirServers) {
/* then we may want some of the defaults */
- authority_type_t type = NO_AUTHORITY;
+ dirinfo_type_t type = NO_DIRINFO;
if (!options->AlternateBridgeAuthority)
- type |= BRIDGE_AUTHORITY;
+ type |= BRIDGE_DIRINFO;
if (!options->AlternateDirAuthority)
- type |= V1_AUTHORITY | V2_AUTHORITY | V3_AUTHORITY;
+ type |= V1_DIRINFO | V2_DIRINFO | V3_DIRINFO | EXTRAINFO_DIRINFO |
+ MICRODESC_DIRINFO;
if (!options->AlternateHSAuthority)
- type |= HIDSERV_AUTHORITY;
+ type |= HIDSERV_DIRINFO;
add_default_trusted_dir_authorities(type);
}
for (cl = options->DirServers; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
for (cl = options->AlternateBridgeAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
for (cl = options->AlternateDirAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
for (cl = options->AlternateHSAuthority; cl; cl = cl->next)
- if (parse_dir_server_line(cl->value, NO_AUTHORITY, 0)<0)
+ if (parse_dir_server_line(cl->value, NO_DIRINFO, 0)<0)
return -1;
return 0;
}
@@ -936,12 +1026,12 @@ consider_adding_dir_authorities(or_options_t *options,
* Return 0 if all goes well, return -1 if things went badly.
*/
static int
-options_act_reversible(or_options_t *old_options, char **msg)
+options_act_reversible(const or_options_t *old_options, char **msg)
{
smartlist_t *new_listeners = smartlist_create();
smartlist_t *replaced_listeners = smartlist_create();
static int libevent_initialized = 0;
- or_options_t *options = get_options();
+ or_options_t *options = get_options_mutable();
int running_tor = options->command == CMD_RUN_TOR;
int set_conn_limit = 0;
int r = -1;
@@ -970,6 +1060,7 @@ options_act_reversible(or_options_t *old_options, char **msg)
#endif
if (running_tor) {
+ int n_client_ports=0;
/* We need to set the connection limit before we can open the listeners. */
if (set_max_file_descriptors((unsigned)options->ConnLimit,
&options->_ConnLimit) < 0) {
@@ -981,10 +1072,14 @@ options_act_reversible(or_options_t *old_options, char **msg)
/* Set up libevent. (We need to do this before we can register the
* listeners as listeners.) */
if (running_tor && !libevent_initialized) {
- init_libevent();
+ init_libevent(options);
libevent_initialized = 1;
}
+ /* Adjust the client port configuration so we can launch listeners. */
+ if (parse_client_ports(options, 0, msg, &n_client_ports))
+ return -1;
+
/* Launch the listeners. (We do this before we setuid, so we can bind to
* ports under 1024.) We don't want to rebind if we're hibernating. */
if (!we_are_hibernating()) {
@@ -1037,7 +1132,7 @@ options_act_reversible(or_options_t *old_options, char **msg)
/* Write control ports to disk as appropriate */
control_ports_write_to_file();
- if (directory_caches_v2_dir_info(options)) {
+ if (directory_caches_v2_dir_info(options)) {
size_t len = strlen(options->DataDirectory)+32;
char *fn = tor_malloc(len);
tor_snprintf(fn, len, "%s"PATH_SEPARATOR"cached-status",
@@ -1113,7 +1208,7 @@ options_act_reversible(or_options_t *old_options, char **msg)
/** If we need to have a GEOIP ip-to-country map to run with our configured
* options, return 1 and set *<b>reason_out</b> to a description of why. */
int
-options_need_geoip_info(or_options_t *options, const char **reason_out)
+options_need_geoip_info(const or_options_t *options, const char **reason_out)
{
int bridge_usage =
options->BridgeRelay && options->BridgeRecordUsageByCountry;
@@ -1138,7 +1233,7 @@ options_need_geoip_info(or_options_t *options, const char **reason_out)
/** Return the bandwidthrate that we are going to report to the authorities
* based on the config options. */
uint32_t
-get_effective_bwrate(or_options_t *options)
+get_effective_bwrate(const or_options_t *options)
{
uint64_t bw = options->BandwidthRate;
if (bw > options->MaxAdvertisedBandwidth)
@@ -1152,7 +1247,7 @@ get_effective_bwrate(or_options_t *options)
/** Return the bandwidthburst that we are going to report to the authorities
* based on the config options. */
uint32_t
-get_effective_bwburst(or_options_t *options)
+get_effective_bwburst(const or_options_t *options)
{
uint64_t bw = options->BandwidthBurst;
if (options->RelayBandwidthBurst > 0 && bw > options->RelayBandwidthBurst)
@@ -1171,10 +1266,10 @@ get_effective_bwburst(or_options_t *options)
* here yet. Some is still in do_hup() and other places.
*/
static int
-options_act(or_options_t *old_options)
+options_act(const or_options_t *old_options)
{
config_line_t *cl;
- or_options_t *options = get_options();
+ or_options_t *options = get_options_mutable();
int running_tor = options->command == CMD_RUN_TOR;
char *msg;
const int transition_affects_workers =
@@ -1219,6 +1314,32 @@ options_act(or_options_t *old_options)
rep_hist_load_mtbf_data(time(NULL));
}
+ mark_transport_list();
+ pt_prepare_proxy_list_for_config_read();
+ if (options->ClientTransportPlugin) {
+ for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
+ if (parse_client_transport_line(cl->value, 0)<0) {
+ log_warn(LD_BUG,
+ "Previously validated ClientTransportPlugin line "
+ "could not be added!");
+ return -1;
+ }
+ }
+ }
+
+ if (options->ServerTransportPlugin) {
+ for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
+ if (parse_server_transport_line(cl->value, 0)<0) {
+ log_warn(LD_BUG,
+ "Previously validated ServerTransportPlugin line "
+ "could not be added!");
+ return -1;
+ }
+ }
+ }
+ sweep_transport_list();
+ sweep_proxy_list();
+
/* Bail out at this point if we're not going to be a client or server:
* we want to not fork, and to log stuff to stderr. */
if (!running_tor)
@@ -1278,17 +1399,16 @@ options_act(or_options_t *old_options)
if (accounting_is_enabled(options))
configure_accounting(time(NULL));
- /* parse RefuseUnknownExits tristate */
- if (!strcmp(options->RefuseUnknownExits, "0"))
- options->RefuseUnknownExits_ = 0;
- else if (!strcmp(options->RefuseUnknownExits, "1"))
- options->RefuseUnknownExits_ = 1;
- else if (!strcmp(options->RefuseUnknownExits, "auto"))
- options->RefuseUnknownExits_ = -1;
- else {
- /* Should have caught this in options_validate */
- return -1;
- }
+#ifdef USE_BUFFEREVENTS
+ /* If we're using the bufferevents implementation and our rate limits
+ * changed, we need to tell the rate-limiting system about it. */
+ if (!old_options ||
+ old_options->BandwidthRate != options->BandwidthRate ||
+ old_options->BandwidthBurst != options->BandwidthBurst ||
+ old_options->RelayBandwidthRate != options->RelayBandwidthRate ||
+ old_options->RelayBandwidthBurst != options->RelayBandwidthBurst)
+ connection_bucket_init();
+#endif
/* Change the cell EWMA settings */
cell_ewma_set_scale_factor(options, networkstatus_get_latest_consensus());
@@ -1407,44 +1527,54 @@ options_act(or_options_t *old_options)
tor_free(actual_fname);
}
- if (options->DirReqStatistics && !geoip_is_loaded()) {
- /* Check if GeoIP database could be loaded. */
- log_warn(LD_CONFIG, "Configured to measure directory request "
- "statistics, but no GeoIP database found!");
- return -1;
- }
-
- if (options->EntryStatistics) {
- if (should_record_bridge_info(options)) {
- /* Don't allow measuring statistics on entry guards when configured
- * as bridge. */
- log_warn(LD_CONFIG, "Bridges cannot be configured to measure "
- "additional GeoIP statistics as entry guards.");
- return -1;
- } else if (!geoip_is_loaded()) {
- /* Check if GeoIP database could be loaded. */
- log_warn(LD_CONFIG, "Configured to measure entry node statistics, "
- "but no GeoIP database found!");
- return -1;
- }
- }
-
if (options->CellStatistics || options->DirReqStatistics ||
- options->EntryStatistics || options->ExitPortStatistics) {
+ options->EntryStatistics || options->ExitPortStatistics ||
+ options->ConnDirectionStatistics) {
time_t now = time(NULL);
+ int print_notice = 0;
if ((!old_options || !old_options->CellStatistics) &&
- options->CellStatistics)
+ options->CellStatistics) {
rep_hist_buffer_stats_init(now);
+ print_notice = 1;
+ }
if ((!old_options || !old_options->DirReqStatistics) &&
- options->DirReqStatistics)
- geoip_dirreq_stats_init(now);
+ options->DirReqStatistics) {
+ if (geoip_is_loaded()) {
+ geoip_dirreq_stats_init(now);
+ print_notice = 1;
+ } else {
+ options->DirReqStatistics = 0;
+ /* Don't warn Tor clients, they don't use statistics */
+ if (options->ORPort)
+ log_notice(LD_CONFIG, "Configured to measure directory request "
+ "statistics, but no GeoIP database found. "
+ "Please specify a GeoIP database using the "
+ "GeoIPFile option.");
+ }
+ }
if ((!old_options || !old_options->EntryStatistics) &&
- options->EntryStatistics)
- geoip_entry_stats_init(now);
+ options->EntryStatistics && !should_record_bridge_info(options)) {
+ if (geoip_is_loaded()) {
+ geoip_entry_stats_init(now);
+ print_notice = 1;
+ } else {
+ options->EntryStatistics = 0;
+ log_notice(LD_CONFIG, "Configured to measure entry node "
+ "statistics, but no GeoIP database found. "
+ "Please specify a GeoIP database using the "
+ "GeoIPFile option.");
+ }
+ }
if ((!old_options || !old_options->ExitPortStatistics) &&
- options->ExitPortStatistics)
+ options->ExitPortStatistics) {
rep_hist_exit_stats_init(now);
- if (!old_options)
+ print_notice = 1;
+ }
+ if ((!old_options || !old_options->ConnDirectionStatistics) &&
+ options->ConnDirectionStatistics) {
+ rep_hist_conn_stats_init(now);
+ }
+ if (print_notice)
log_notice(LD_CONFIG, "Configured to measure statistics. Look for "
"the *-stats files that will first be written to the "
"data directory in 24 hours from now.");
@@ -1462,6 +1592,9 @@ options_act(or_options_t *old_options)
if (old_options && old_options->ExitPortStatistics &&
!options->ExitPortStatistics)
rep_hist_exit_stats_term();
+ if (old_options && old_options->ConnDirectionStatistics &&
+ !options->ConnDirectionStatistics)
+ rep_hist_conn_stats_term();
/* Check if we need to parse and add the EntryNodes config option. */
if (options->EntryNodes &&
@@ -1519,7 +1652,7 @@ options_act(or_options_t *old_options)
* apply abbreviations that work for the config file and the command line.
* If <b>warn_obsolete</b> is set, warn about deprecated names. */
static const char *
-expand_abbrev(config_format_t *fmt, const char *option, int command_line,
+expand_abbrev(const config_format_t *fmt, const char *option, int command_line,
int warn_obsolete)
{
int i;
@@ -1679,12 +1812,9 @@ config_free_lines(config_line_t *front)
}
}
-/** If <b>key</b> is a configuration option, return the corresponding
- * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
- * warn, and return the corresponding config_var_t. Otherwise return NULL.
- */
+/** As config_find_option, but return a non-const pointer. */
static config_var_t *
-config_find_option(config_format_t *fmt, const char *key)
+config_find_option_mutable(config_format_t *fmt, const char *key)
{
int i;
size_t keylen = strlen(key);
@@ -1709,9 +1839,20 @@ config_find_option(config_format_t *fmt, const char *key)
return NULL;
}
+/** If <b>key</b> is a configuration option, return the corresponding const
+ * config_var_t. Otherwise, if <b>key</b> is a non-standard abbreviation,
+ * warn, and return the corresponding const config_var_t. Otherwise return
+ * NULL.
+ */
+static const config_var_t *
+config_find_option(const config_format_t *fmt, const char *key)
+{
+ return config_find_option_mutable((config_format_t*)fmt, key);
+}
+
/** Return the number of option entries in <b>fmt</b>. */
static int
-config_count_options(config_format_t *fmt)
+config_count_options(const config_format_t *fmt)
{
int i;
for (i=0; fmt->vars[i].name; ++i)
@@ -1729,11 +1870,11 @@ config_count_options(config_format_t *fmt)
* Called from config_assign_line() and option_reset().
*/
static int
-config_assign_value(config_format_t *fmt, or_options_t *options,
+config_assign_value(const config_format_t *fmt, or_options_t *options,
config_line_t *c, char **msg)
{
int i, ok;
- config_var_t *var;
+ const config_var_t *var;
void *lvalue;
CHECK(fmt, options);
@@ -1776,6 +1917,18 @@ config_assign_value(config_format_t *fmt, or_options_t *options,
break;
}
+ case CONFIG_TYPE_MSEC_INTERVAL: {
+ i = config_parse_msec_interval(c->value, &ok);
+ if (!ok) {
+ tor_asprintf(msg,
+ "Msec interval '%s %s' is malformed or out of bounds.",
+ c->key, c->value);
+ return -1;
+ }
+ *(int *)lvalue = i;
+ break;
+ }
+
case CONFIG_TYPE_MEMUNIT: {
uint64_t u64 = config_parse_memunit(c->value, &ok);
if (!ok) {
@@ -1799,6 +1952,20 @@ config_assign_value(config_format_t *fmt, or_options_t *options,
*(int *)lvalue = i;
break;
+ case CONFIG_TYPE_AUTOBOOL:
+ if (!strcmp(c->value, "auto"))
+ *(int *)lvalue = -1;
+ else if (!strcmp(c->value, "0"))
+ *(int *)lvalue = 0;
+ else if (!strcmp(c->value, "1"))
+ *(int *)lvalue = 1;
+ else {
+ tor_asprintf(msg, "Boolean '%s %s' expects 0, 1, or 'auto'.",
+ c->key, c->value);
+ return -1;
+ }
+ break;
+
case CONFIG_TYPE_STRING:
case CONFIG_TYPE_FILENAME:
tor_free(*(char **)lvalue);
@@ -1869,11 +2036,11 @@ config_assign_value(config_format_t *fmt, or_options_t *options,
* Called from config_assign().
*/
static int
-config_assign_line(config_format_t *fmt, or_options_t *options,
+config_assign_line(const config_format_t *fmt, or_options_t *options,
config_line_t *c, int use_defaults,
int clear_first, bitarray_t *options_seen, char **msg)
{
- config_var_t *var;
+ const config_var_t *var;
CHECK(fmt, options);
@@ -1934,10 +2101,10 @@ config_assign_line(config_format_t *fmt, or_options_t *options,
/** Restore the option named <b>key</b> in options to its default value.
* Called from config_assign(). */
static void
-config_reset_line(config_format_t *fmt, or_options_t *options,
+config_reset_line(const config_format_t *fmt, or_options_t *options,
const char *key, int use_defaults)
{
- config_var_t *var;
+ const config_var_t *var;
CHECK(fmt, options);
@@ -1952,7 +2119,7 @@ config_reset_line(config_format_t *fmt, or_options_t *options,
int
option_is_recognized(const char *key)
{
- config_var_t *var = config_find_option(&options_format, key);
+ const config_var_t *var = config_find_option(&options_format, key);
return (var != NULL);
}
@@ -1961,14 +2128,14 @@ option_is_recognized(const char *key)
const char *
option_get_canonical_name(const char *key)
{
- config_var_t *var = config_find_option(&options_format, key);
+ const config_var_t *var = config_find_option(&options_format, key);
return var ? var->name : NULL;
}
/** Return a canonical list of the options assigned for key.
*/
config_line_t *
-option_get_assignment(or_options_t *options, const char *key)
+option_get_assignment(const or_options_t *options, const char *key)
{
return get_assigned_option(&options_format, options, key, 1);
}
@@ -2021,10 +2188,10 @@ config_lines_dup(const config_line_t *inp)
* value needs to be quoted before it's put in a config file, quote and
* escape that value. Return NULL if no such key exists. */
static config_line_t *
-get_assigned_option(config_format_t *fmt, void *options,
+get_assigned_option(const config_format_t *fmt, const void *options,
const char *key, int escape_val)
{
- config_var_t *var;
+ const config_var_t *var;
const void *value;
config_line_t *result;
tor_assert(options && key);
@@ -2070,6 +2237,7 @@ get_assigned_option(config_format_t *fmt, void *options,
}
/* fall through */
case CONFIG_TYPE_INTERVAL:
+ case CONFIG_TYPE_MSEC_INTERVAL:
case CONFIG_TYPE_UINT:
/* This means every or_options_t uint or bool element
* needs to be an int. Not, say, a uint16_t or char. */
@@ -2085,6 +2253,14 @@ get_assigned_option(config_format_t *fmt, void *options,
tor_asprintf(&result->value, "%f", *(double*)value);
escape_val = 0; /* Can't need escape. */
break;
+
+ case CONFIG_TYPE_AUTOBOOL:
+ if (*(int*)value == -1) {
+ result->value = tor_strdup("auto");
+ escape_val = 0;
+ break;
+ }
+ /* fall through */
case CONFIG_TYPE_BOOL:
result->value = tor_strdup(*(int*)value ? "1" : "0");
escape_val = 0; /* Can't need escape. */
@@ -2197,7 +2373,7 @@ options_trial_assign() calls config_assign(1, 1)
returns.
*/
static int
-config_assign(config_format_t *fmt, void *options, config_line_t *list,
+config_assign(const config_format_t *fmt, void *options, config_line_t *list,
int use_defaults, int clear_first, char **msg)
{
config_line_t *p;
@@ -2259,7 +2435,7 @@ options_trial_assign(config_line_t *list, int use_defaults,
return r;
}
- if (options_validate(get_options(), trial_options, 1, msg) < 0) {
+ if (options_validate(get_options_mutable(), trial_options, 1, msg) < 0) {
config_free(&options_format, trial_options);
return SETOPT_ERR_PARSE; /*XXX make this a separate return value. */
}
@@ -2281,7 +2457,8 @@ options_trial_assign(config_line_t *list, int use_defaults,
/** Reset config option <b>var</b> to 0, 0.0, NULL, or the equivalent.
* Called from option_reset() and config_free(). */
static void
-option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var)
+option_clear(const config_format_t *fmt, or_options_t *options,
+ const config_var_t *var)
{
void *lvalue = STRUCT_VAR_P(options, var->var_offset);
(void)fmt; /* unused */
@@ -2297,11 +2474,15 @@ option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var)
*(time_t*)lvalue = 0;
break;
case CONFIG_TYPE_INTERVAL:
+ case CONFIG_TYPE_MSEC_INTERVAL:
case CONFIG_TYPE_UINT:
case CONFIG_TYPE_PORT:
case CONFIG_TYPE_BOOL:
*(int*)lvalue = 0;
break;
+ case CONFIG_TYPE_AUTOBOOL:
+ *(int*)lvalue = -1;
+ break;
case CONFIG_TYPE_MEMUNIT:
*(uint64_t*)lvalue = 0;
break;
@@ -2335,8 +2516,8 @@ option_clear(config_format_t *fmt, or_options_t *options, config_var_t *var)
* <b>use_defaults</b>, set it to its default value.
* Called by config_init() and option_reset_line() and option_assign_line(). */
static void
-option_reset(config_format_t *fmt, or_options_t *options,
- config_var_t *var, int use_defaults)
+option_reset(const config_format_t *fmt, or_options_t *options,
+ const config_var_t *var, int use_defaults)
{
config_line_t *c;
char *msg = NULL;
@@ -2376,7 +2557,7 @@ list_torrc_options(void)
int i;
smartlist_t *lines = smartlist_create();
for (i = 0; _option_vars[i].name; ++i) {
- config_var_t *var = &_option_vars[i];
+ const config_var_t *var = &_option_vars[i];
if (var->type == CONFIG_TYPE_OBSOLETE ||
var->type == CONFIG_TYPE_LINELIST_V)
continue;
@@ -2395,7 +2576,7 @@ static uint32_t last_resolved_addr = 0;
* public IP address.
*/
int
-resolve_my_address(int warn_severity, or_options_t *options,
+resolve_my_address(int warn_severity, const or_options_t *options,
uint32_t *addr_out, char **hostname_out)
{
struct in_addr in;
@@ -2404,7 +2585,7 @@ resolve_my_address(int warn_severity, or_options_t *options,
int explicit_ip=1;
int explicit_hostname=1;
int from_interface=0;
- char tmpbuf[INET_NTOA_BUF_LEN];
+ char *addr_string = NULL;
const char *address = options->Address;
int notice_severity = warn_severity <= LOG_NOTICE ?
LOG_NOTICE : warn_severity;
@@ -2446,48 +2627,43 @@ resolve_my_address(int warn_severity, or_options_t *options,
return -1;
}
from_interface = 1;
- in.s_addr = htonl(interface_ip);
- tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
+ addr = interface_ip;
log_fn(notice_severity, LD_CONFIG, "Learned IP address '%s' for "
- "local interface. Using that.", tmpbuf);
+ "local interface. Using that.", fmt_addr32(addr));
strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
} else { /* resolved hostname into addr */
- in.s_addr = htonl(addr);
-
if (!explicit_hostname &&
- is_internal_IP(ntohl(in.s_addr), 0)) {
+ is_internal_IP(addr, 0)) {
uint32_t interface_ip;
- tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
log_fn(notice_severity, LD_CONFIG, "Guessed local hostname '%s' "
- "resolves to a private IP address (%s). Trying something "
- "else.", hostname, tmpbuf);
+ "resolves to a private IP address (%s). Trying something "
+ "else.", hostname, fmt_addr32(addr));
if (get_interface_address(warn_severity, &interface_ip)) {
log_fn(warn_severity, LD_CONFIG,
"Could not get local interface IP address. Too bad.");
} else if (is_internal_IP(interface_ip, 0)) {
- struct in_addr in2;
- in2.s_addr = htonl(interface_ip);
- tor_inet_ntoa(&in2,tmpbuf,sizeof(tmpbuf));
log_fn(notice_severity, LD_CONFIG,
"Interface IP address '%s' is a private address too. "
- "Ignoring.", tmpbuf);
+ "Ignoring.", fmt_addr32(interface_ip));
} else {
from_interface = 1;
- in.s_addr = htonl(interface_ip);
- tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
+ addr = interface_ip;
log_fn(notice_severity, LD_CONFIG,
"Learned IP address '%s' for local interface."
- " Using that.", tmpbuf);
+ " Using that.", fmt_addr32(addr));
strlcpy(hostname, "<guessed from interfaces>", sizeof(hostname));
}
}
}
+ } else {
+ addr = ntohl(in.s_addr); /* set addr so that addr_string is not
+ * illformed */
}
- tor_inet_ntoa(&in,tmpbuf,sizeof(tmpbuf));
- if (is_internal_IP(ntohl(in.s_addr), 0)) {
+ addr_string = tor_dup_ip(addr);
+ if (is_internal_IP(addr, 0)) {
/* make sure we're ok with publishing an internal IP */
if (!options->DirServers && !options->AlternateDirAuthority) {
/* if they are using the default dirservers, disallow internal IPs
@@ -2495,7 +2671,8 @@ resolve_my_address(int warn_severity, or_options_t *options,
log_fn(warn_severity, LD_CONFIG,
"Address '%s' resolves to private IP address '%s'. "
"Tor servers that use the default DirServers must have public "
- "IP addresses.", hostname, tmpbuf);
+ "IP addresses.", hostname, addr_string);
+ tor_free(addr_string);
return -1;
}
if (!explicit_ip) {
@@ -2503,19 +2680,20 @@ resolve_my_address(int warn_severity, or_options_t *options,
* they're using an internal address. */
log_fn(warn_severity, LD_CONFIG, "Address '%s' resolves to private "
"IP address '%s'. Please set the Address config option to be "
- "the IP address you want to use.", hostname, tmpbuf);
+ "the IP address you want to use.", hostname, addr_string);
+ tor_free(addr_string);
return -1;
}
}
- log_debug(LD_CONFIG, "Resolved Address to '%s'.", tmpbuf);
- *addr_out = ntohl(in.s_addr);
+ log_debug(LD_CONFIG, "Resolved Address to '%s'.", fmt_addr32(addr));
+ *addr_out = addr;
if (last_resolved_addr && last_resolved_addr != *addr_out) {
/* Leave this as a notice, regardless of the requested severity,
* at least until dynamic IP address support becomes bulletproof. */
log_notice(LD_NET,
"Your IP address seems to have changed to %s. Updating.",
- tmpbuf);
+ addr_string);
ip_address_changed(0);
}
if (last_resolved_addr != *addr_out) {
@@ -2534,11 +2712,12 @@ resolve_my_address(int warn_severity, or_options_t *options,
}
control_event_server_status(LOG_NOTICE,
"EXTERNAL_ADDRESS ADDRESS=%s METHOD=%s %s%s",
- tmpbuf, method, h?"HOSTNAME=":"", h);
+ addr_string, method, h?"HOSTNAME=":"", h);
}
last_resolved_addr = *addr_out;
if (hostname_out)
*hostname_out = tor_strdup(hostname);
+ tor_free(addr_string);
return 0;
}
@@ -2573,7 +2752,7 @@ is_local_addr(const tor_addr_t *addr)
/** Release storage held by <b>options</b>. */
static void
-config_free(config_format_t *fmt, void *options)
+config_free(const config_format_t *fmt, void *options)
{
int i;
@@ -2612,8 +2791,9 @@ config_lines_eq(config_line_t *a, config_line_t *b)
* and <b>o2</b>. Must not be called for LINELIST_S or OBSOLETE options.
*/
static int
-option_is_same(config_format_t *fmt,
- or_options_t *o1, or_options_t *o2, const char *name)
+option_is_same(const config_format_t *fmt,
+ const or_options_t *o1, const or_options_t *o2,
+ const char *name)
{
config_line_t *c1, *c2;
int r = 1;
@@ -2630,7 +2810,7 @@ option_is_same(config_format_t *fmt,
/** Copy storage held by <b>old</b> into a new or_options_t and return it. */
static or_options_t *
-options_dup(config_format_t *fmt, or_options_t *old)
+options_dup(const config_format_t *fmt, const or_options_t *old)
{
or_options_t *newopts;
int i;
@@ -2706,10 +2886,10 @@ is_listening_on_low_port(int port_option,
/** Set all vars in the configuration object <b>options</b> to their default
* values. */
static void
-config_init(config_format_t *fmt, void *options)
+config_init(const config_format_t *fmt, void *options)
{
int i;
- config_var_t *var;
+ const config_var_t *var;
CHECK(fmt, options);
for (i=0; fmt->vars[i].name; ++i) {
@@ -2725,7 +2905,7 @@ config_init(config_format_t *fmt, void *options)
* Else, if comment_defaults, write default values as comments.
*/
static char *
-config_dump(config_format_t *fmt, void *options, int minimal,
+config_dump(const config_format_t *fmt, const void *options, int minimal,
int comment_defaults)
{
smartlist_t *elements;
@@ -2793,7 +2973,7 @@ config_dump(config_format_t *fmt, void *options, int minimal,
* include options that are the same as Tor's defaults.
*/
char *
-options_dump(or_options_t *options, int minimal)
+options_dump(const or_options_t *options, int minimal)
{
return config_dump(&options_format, options, minimal, 0);
}
@@ -2852,24 +3032,24 @@ static int
compute_publishserverdescriptor(or_options_t *options)
{
smartlist_t *list = options->PublishServerDescriptor;
- authority_type_t *auth = &options->_PublishServerDescriptor;
- *auth = NO_AUTHORITY;
+ dirinfo_type_t *auth = &options->_PublishServerDescriptor;
+ *auth = NO_DIRINFO;
if (!list) /* empty list, answer is none */
return 0;
SMARTLIST_FOREACH(list, const char *, string, {
if (!strcasecmp(string, "v1"))
- *auth |= V1_AUTHORITY;
+ *auth |= V1_DIRINFO;
else if (!strcmp(string, "1"))
if (options->BridgeRelay)
- *auth |= BRIDGE_AUTHORITY;
+ *auth |= BRIDGE_DIRINFO;
else
- *auth |= V2_AUTHORITY | V3_AUTHORITY;
+ *auth |= V2_DIRINFO | V3_DIRINFO;
else if (!strcasecmp(string, "v2"))
- *auth |= V2_AUTHORITY;
+ *auth |= V2_DIRINFO;
else if (!strcasecmp(string, "v3"))
- *auth |= V3_AUTHORITY;
+ *auth |= V3_DIRINFO;
else if (!strcasecmp(string, "bridge"))
- *auth |= BRIDGE_AUTHORITY;
+ *auth |= BRIDGE_DIRINFO;
else if (!strcasecmp(string, "hidserv"))
log_warn(LD_CONFIG,
"PublishServerDescriptor hidserv is invalid. See "
@@ -2897,6 +3077,10 @@ compute_publishserverdescriptor(or_options_t *options)
* will generate too many circuits and potentially overload the network. */
#define MIN_CIRCUIT_STREAM_TIMEOUT 10
+/** Lowest allowable value for HeartbeatPeriod; if this is too low, we might
+ * expose more information than we're comfortable with. */
+#define MIN_HEARTBEAT_PERIOD (30*60)
+
/** Return 0 if every setting in <b>options</b> is reasonable, and a
* permissible transition from <b>old_options</b>. Else return -1.
* Should have no side effects, except for normalizing the contents of
@@ -2916,6 +3100,7 @@ options_validate(or_options_t *old_options, or_options_t *options,
int i;
config_line_t *cl;
const char *uname = get_uname();
+ int n_client_ports=0;
#define REJECT(arg) \
STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END
#define COMPLAIN(arg) STMT_BEGIN log(LOG_WARN, LD_CONFIG, arg); STMT_END
@@ -2939,57 +3124,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (options->DirPort == 0 && options->DirListenAddress != NULL)
REJECT("DirPort must be defined if DirListenAddress is defined.");
- if (options->DNSPort == 0 && options->DNSListenAddress != NULL)
- REJECT("DNSPort must be defined if DNSListenAddress is defined.");
-
- if (options->ControlPort == 0 && options->ControlListenAddress != NULL)
- REJECT("ControlPort must be defined if ControlListenAddress is defined.");
-
- if (options->TransPort == 0 && options->TransListenAddress != NULL)
- REJECT("TransPort must be defined if TransListenAddress is defined.");
-
- if (options->NATDPort == 0 && options->NATDListenAddress != NULL)
- REJECT("NATDPort must be defined if NATDListenAddress is defined.");
-
- /* Don't gripe about SocksPort 0 with SocksListenAddress set; a standard
- * configuration does this. */
-
- for (i = 0; i < 3; ++i) {
- int is_socks = i==0;
- int is_trans = i==1;
- config_line_t *line, *opt, *old;
- const char *tp;
- if (is_socks) {
- opt = options->SocksListenAddress;
- old = old_options ? old_options->SocksListenAddress : NULL;
- tp = "SOCKS proxy";
- } else if (is_trans) {
- opt = options->TransListenAddress;
- old = old_options ? old_options->TransListenAddress : NULL;
- tp = "transparent proxy";
- } else {
- opt = options->NATDListenAddress;
- old = old_options ? old_options->NATDListenAddress : NULL;
- tp = "natd proxy";
- }
-
- for (line = opt; line; line = line->next) {
- char *address = NULL;
- uint16_t port;
- uint32_t addr;
- if (parse_addr_port(LOG_WARN, line->value, &address, &addr, &port)<0)
- continue; /* We'll warn about this later. */
- if (!is_internal_IP(addr, 1) &&
- (!old_options || !config_lines_eq(old, opt))) {
- log_warn(LD_CONFIG,
- "You specified a public address '%s' for a %s. Other "
- "people on the Internet might find your computer and use it as "
- "an open %s. Please don't allow this unless you have "
- "a good reason.", address, tp, tp);
- }
- tor_free(address);
- }
- }
+ if (parse_client_ports(options, 1, msg, &n_client_ports) < 0)
+ return -1;
if (validate_data_directory(options)<0)
REJECT("Invalid DataDirectory");
@@ -3013,8 +3149,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
"misconfigured or something else goes wrong.");
/* Special case on first boot if no Log options are given. */
- if (!options->Logs && !options->RunAsDaemon && !from_setconf)
- config_line_append(&options->Logs, "Log", "notice stdout");
+ if (!options->Logs && !options->RunAsDaemon && !from_setconf) {
+ if (quiet_level == 0)
+ config_line_append(&options->Logs, "Log", "notice stdout");
+ else if (quiet_level == 1)
+ config_line_append(&options->Logs, "Log", "warn stdout");
+ }
if (options_init_logs(options, 1)<0) /* Validate the log(s) */
REJECT("Failed to validate Log options. See logs for details.");
@@ -3026,20 +3166,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("Failed to resolve/guess local address. See logs for details.");
}
- if (strcmp(options->RefuseUnknownExits, "0") &&
- strcmp(options->RefuseUnknownExits, "1") &&
- strcmp(options->RefuseUnknownExits, "auto")) {
- REJECT("RefuseUnknownExits must be 0, 1, or auto");
- }
-
#ifndef MS_WINDOWS
if (options->RunAsDaemon && torrc_fname && path_is_relative(torrc_fname))
REJECT("Can't use a relative path to torrc when RunAsDaemon is set.");
#endif
- if (options->SocksPort == 0 && options->TransPort == 0 &&
- options->NATDPort == 0 && options->ORPort == 0 &&
- options->DNSPort == 0 && !options->RendConfigLines)
+ if (n_client_ports == 0 && options->ORPort == 0 && !options->RendConfigLines)
log(LOG_WARN, LD_CONFIG,
"SocksPort, TransPort, NATDPort, DNSPort, and ORPort are all "
"undefined, and there aren't any hidden services configured. "
@@ -3050,6 +3182,11 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("TransPort and TransListenAddress are disabled in this build.");
#endif
+ if (options->TokenBucketRefillInterval <= 0
+ || options->TokenBucketRefillInterval > 1000) {
+ REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive.");
+ }
+
if (options->AccountingMax &&
(is_listening_on_low_port(options->ORPort, options->ORListenAddress) ||
is_listening_on_low_port(options->DirPort, options->DirListenAddress)))
@@ -3069,17 +3206,24 @@ options_validate(or_options_t *old_options, or_options_t *options,
routerset_union(options->_ExcludeExitNodesUnion,options->ExcludeNodes);
}
+ if (options->NodeFamilies) {
+ options->NodeFamilySets = smartlist_create();
+ for (cl = options->NodeFamilies; cl; cl = cl->next) {
+ routerset_t *rs = routerset_new();
+ if (routerset_parse(rs, cl->value, cl->key) == 0) {
+ smartlist_add(options->NodeFamilySets, rs);
+ } else {
+ routerset_free(rs);
+ }
+ }
+ }
+
if (options->ExcludeNodes && options->StrictNodes) {
COMPLAIN("You have asked to exclude certain relays from all positions "
"in your circuits. Expect hidden services and other Tor "
"features to be broken in unpredictable ways.");
}
- if (options->EntryNodes && !routerset_is_list(options->EntryNodes)) {
- /* XXXX fix this; see entry_guards_prepend_from_config(). */
- REJECT("IPs or countries are not yet supported in EntryNodes.");
- }
-
if (options->AuthoritativeDir) {
if (!options->ContactInfo && !options->TestingTorNetwork)
REJECT("Authoritative directory servers must set ContactInfo");
@@ -3141,6 +3285,15 @@ options_validate(or_options_t *old_options, or_options_t *options,
return -1;
}
+ if (options->MaxClientCircuitsPending <= 0 ||
+ options->MaxClientCircuitsPending > MAX_MAX_CLIENT_CIRCUITS_PENDING) {
+ tor_asprintf(msg,
+ "MaxClientCircuitsPending must be between 1 and %d, but "
+ "was set to %d", MAX_MAX_CLIENT_CIRCUITS_PENDING,
+ options->MaxClientCircuitsPending);
+ return -1;
+ }
+
if (validate_ports_csv(options->FirewallPorts, "FirewallPorts", msg) < 0)
return -1;
@@ -3289,9 +3442,9 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
if ((options->BridgeRelay
- || options->_PublishServerDescriptor & BRIDGE_AUTHORITY)
+ || options->_PublishServerDescriptor & BRIDGE_DIRINFO)
&& (options->_PublishServerDescriptor
- & (V1_AUTHORITY|V2_AUTHORITY|V3_AUTHORITY))) {
+ & (V1_DIRINFO|V2_DIRINFO|V3_DIRINFO))) {
REJECT("Bridges are not supposed to publish router descriptors to the "
"directory authorities. Please correct your "
"PublishServerDescriptor line.");
@@ -3334,6 +3487,13 @@ options_validate(or_options_t *old_options, or_options_t *options,
options->CircuitStreamTimeout = MIN_CIRCUIT_STREAM_TIMEOUT;
}
+ if (options->HeartbeatPeriod &&
+ options->HeartbeatPeriod < MIN_HEARTBEAT_PERIOD) {
+ log_warn(LD_CONFIG, "HeartbeatPeriod option is too short; "
+ "raising to %d seconds.", MIN_HEARTBEAT_PERIOD);
+ options->HeartbeatPeriod = MIN_HEARTBEAT_PERIOD;
+ }
+
if (options->KeepalivePeriod < 1)
REJECT("KeepalivePeriod option must be positive.");
@@ -3457,8 +3617,11 @@ options_validate(or_options_t *old_options, or_options_t *options,
}
}
- if (options->Socks4Proxy && options->Socks5Proxy)
- REJECT("You cannot specify both Socks4Proxy and SOCKS5Proxy");
+ /* Check if more than one proxy type has been enabled. */
+ if (!!options->Socks4Proxy + !!options->Socks5Proxy +
+ !!options->HTTPSProxy + !!options->ClientTransportPlugin > 1)
+ REJECT("You have configured more than one proxy type. "
+ "(Socks4Proxy|Socks5Proxy|HTTPSProxy|ClientTransportPlugin)");
if (options->Socks5ProxyUsername) {
size_t len;
@@ -3561,8 +3724,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (check_nickname_list(options->MyFamily, "MyFamily", msg))
return -1;
for (cl = options->NodeFamilies; cl; cl = cl->next) {
- if (check_nickname_list(cl->value, "NodeFamily", msg))
+ routerset_t *rs = routerset_new();
+ if (routerset_parse(rs, cl->value, cl->key)) {
+ routerset_free(rs);
return -1;
+ }
+ routerset_free(rs);
}
if (validate_addr_policies(options, msg) < 0)
@@ -3575,11 +3742,20 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("If you set UseBridges, you must specify at least one bridge.");
if (options->UseBridges && !options->TunnelDirConns)
REJECT("If you set UseBridges, you must set TunnelDirConns.");
- if (options->Bridges) {
- for (cl = options->Bridges; cl; cl = cl->next) {
- if (parse_bridge_line(cl->value, 1)<0)
- REJECT("Bridge line did not parse. See logs for details.");
- }
+
+ for (cl = options->Bridges; cl; cl = cl->next) {
+ if (parse_bridge_line(cl->value, 1)<0)
+ REJECT("Bridge line did not parse. See logs for details.");
+ }
+
+ for (cl = options->ClientTransportPlugin; cl; cl = cl->next) {
+ if (parse_client_transport_line(cl->value, 1)<0)
+ REJECT("Transport line did not parse. See logs for details.");
+ }
+
+ for (cl = options->ServerTransportPlugin; cl; cl = cl->next) {
+ if (parse_server_transport_line(cl->value, 1)<0)
+ REJECT("Server transport line did not parse. See logs for details.");
}
if (options->ConstrainedSockets) {
@@ -3762,17 +3938,13 @@ options_validate(or_options_t *old_options, or_options_t *options,
static int
opt_streq(const char *s1, const char *s2)
{
- if (!s1 && !s2)
- return 1;
- else if (s1 && s2 && !strcmp(s1,s2))
- return 1;
- else
- return 0;
+ return 0 == strcmp_opt(s1, s2);
}
/** Check if any of the previous options have changed but aren't allowed to. */
static int
-options_transition_allowed(or_options_t *old, or_options_t *new_val,
+options_transition_allowed(const or_options_t *old,
+ const or_options_t *new_val,
char **msg)
{
if (!old)
@@ -3822,14 +3994,26 @@ options_transition_allowed(or_options_t *old, or_options_t *new_val,
return -1;
}
+ if (old->TokenBucketRefillInterval != new_val->TokenBucketRefillInterval) {
+ *msg = tor_strdup("While Tor is running, changing TokenBucketRefill"
+ "Interval is not allowed");
+ return -1;
+ }
+
+ if (old->DisableIOCP != new_val->DisableIOCP) {
+ *msg = tor_strdup("While Tor is running, changing DisableIOCP "
+ "is not allowed.");
+ return -1;
+ }
+
return 0;
}
/** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
* will require us to rotate the CPU and DNS workers; else return 0. */
static int
-options_transition_affects_workers(or_options_t *old_options,
- or_options_t *new_options)
+options_transition_affects_workers(const or_options_t *old_options,
+ const or_options_t *new_options)
{
if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) ||
old_options->NumCPUs != new_options->NumCPUs ||
@@ -3852,8 +4036,8 @@ options_transition_affects_workers(or_options_t *old_options,
/** Return 1 if any change from <b>old_options</b> to <b>new_options</b>
* will require us to generate a new descriptor; else return 0. */
static int
-options_transition_affects_descriptor(or_options_t *old_options,
- or_options_t *new_options)
+options_transition_affects_descriptor(const or_options_t *old_options,
+ const or_options_t *new_options)
{
/* XXX We can be smarter here. If your DirPort isn't being
* published and you just turned it off, no need to republish. Etc. */
@@ -3874,7 +4058,8 @@ options_transition_affects_descriptor(or_options_t *old_options,
!opt_streq(old_options->ContactInfo, new_options->ContactInfo) ||
!opt_streq(old_options->MyFamily, new_options->MyFamily) ||
!opt_streq(old_options->AccountingStart, new_options->AccountingStart) ||
- old_options->AccountingMax != new_options->AccountingMax)
+ old_options->AccountingMax != new_options->AccountingMax ||
+ public_server_mode(old_options) != public_server_mode(new_options))
return 1;
return 0;
@@ -4057,6 +4242,8 @@ load_torrc_from_disk(int argc, char **argv)
"Unable to open configuration file \"%s\".", fname);
goto err;
}
+ } else {
+ log(LOG_NOTICE, LD_CONFIG, "Read configuration file \"%s\".", fname);
}
return cf;
@@ -4217,9 +4404,9 @@ options_init_from_string(const char *cf,
/* Change defaults. */
int i;
for (i = 0; testing_tor_network_defaults[i].name; ++i) {
- config_var_t *new_var = &testing_tor_network_defaults[i];
+ const config_var_t *new_var = &testing_tor_network_defaults[i];
config_var_t *old_var =
- config_find_option(&options_format, new_var->name);
+ config_find_option_mutable(&options_format, new_var->name);
tor_assert(new_var);
tor_assert(old_var);
old_var->initvalue = new_var->initvalue;
@@ -4295,8 +4482,8 @@ get_torrc_fname(void)
/** Adjust the address map based on the MapAddress elements in the
* configuration <b>options</b>
*/
-static void
-config_register_addressmaps(or_options_t *options)
+void
+config_register_addressmaps(const or_options_t *options)
{
smartlist_t *elts;
config_line_t *opt;
@@ -4345,6 +4532,35 @@ options_init_logs(or_options_t *options, int validate_only)
options->RunAsDaemon;
#endif
+ if (options->LogTimeGranularity <= 0) {
+ log_warn(LD_CONFIG, "Log time granularity '%d' has to be positive.",
+ options->LogTimeGranularity);
+ return -1;
+ } else if (1000 % options->LogTimeGranularity != 0 &&
+ options->LogTimeGranularity % 1000 != 0) {
+ int granularity = options->LogTimeGranularity;
+ if (granularity < 40) {
+ do granularity++;
+ while (1000 % granularity != 0);
+ } else if (granularity < 1000) {
+ granularity = 1000 / granularity;
+ while (1000 % granularity != 0)
+ granularity--;
+ granularity = 1000 / granularity;
+ } else {
+ granularity = 1000 * ((granularity / 1000) + 1);
+ }
+ log_warn(LD_CONFIG, "Log time granularity '%d' has to be either a "
+ "divisor or a multiple of 1 second. Changing to "
+ "'%d'.",
+ options->LogTimeGranularity, granularity);
+ if (!validate_only)
+ set_log_time_granularity(granularity);
+ } else {
+ if (!validate_only)
+ set_log_time_granularity(options->LogTimeGranularity);
+ }
+
ok = 1;
elts = smartlist_create();
@@ -4434,6 +4650,8 @@ parse_bridge_line(const char *line, int validate_only)
smartlist_t *items = NULL;
int r;
char *addrport=NULL, *fingerprint=NULL;
+ char *transport_name=NULL;
+ char *field1=NULL;
tor_addr_t addr;
uint16_t port = 0;
char digest[DIGEST_LEN];
@@ -4445,8 +4663,24 @@ parse_bridge_line(const char *line, int validate_only)
log_warn(LD_CONFIG, "Too few arguments to Bridge line.");
goto err;
}
- addrport = smartlist_get(items, 0);
+
+ /* field1 is either a transport name or addrport */
+ field1 = smartlist_get(items, 0);
smartlist_del_keeporder(items, 0);
+
+ if (!(strstr(field1, ".") || strstr(field1, ":"))) {
+ /* new-style bridge line */
+ transport_name = field1;
+ if (smartlist_len(items) < 1) {
+ log_warn(LD_CONFIG, "Too few items to Bridge line.");
+ goto err;
+ }
+ addrport = smartlist_get(items, 0);
+ smartlist_del_keeporder(items, 0);
+ } else {
+ addrport = field1;
+ }
+
if (tor_addr_port_parse(addrport, &addr, &port)<0) {
log_warn(LD_CONFIG, "Error parsing Bridge address '%s'", addrport);
goto err;
@@ -4471,26 +4705,278 @@ parse_bridge_line(const char *line, int validate_only)
}
if (!validate_only) {
- log_debug(LD_DIR, "Bridge at %s:%d (%s)", fmt_addr(&addr),
- (int)port,
+ log_debug(LD_DIR, "Bridge at %s:%d (transport: %s) (%s)",
+ fmt_addr(&addr), (int)port,
+ transport_name ? transport_name : "no transport",
fingerprint ? fingerprint : "no key listed");
- bridge_add_from_config(&addr, port, fingerprint ? digest : NULL);
+ bridge_add_from_config(&addr, port,
+ fingerprint ? digest : NULL, transport_name);
}
r = 0;
goto done;
- err:
+ err:
r = -1;
- done:
+ done:
SMARTLIST_FOREACH(items, char*, s, tor_free(s));
smartlist_free(items);
tor_free(addrport);
+ tor_free(transport_name);
tor_free(fingerprint);
return r;
}
+/** Read the contents of a ClientTransportPlugin line from
+ * <b>line</b>. Return 0 if the line is well-formed, and -1 if it
+ * isn't.
+ *
+ * If <b>validate_only</b> is 0, and the line is well-formed:
+ * - If it's an external proxy line, add the transport described in the line to
+ * our internal transport list.
+ * - If it's a managed proxy line, launch the managed proxy. */
+static int
+parse_client_transport_line(const char *line, int validate_only)
+{
+ smartlist_t *items = NULL;
+ int r;
+ char *field2=NULL;
+
+ const char *transports=NULL;
+ smartlist_t *transport_list=NULL;
+ char *addrport=NULL;
+ tor_addr_t addr;
+ uint16_t port = 0;
+ int socks_ver=PROXY_NONE;
+
+ /* managed proxy options */
+ int is_managed=0;
+ char **proxy_argv=NULL;
+ char **tmp=NULL;
+ int proxy_argc,i;
+
+ int line_length;
+
+ items = smartlist_create();
+ smartlist_split_string(items, line, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+
+ line_length = smartlist_len(items);
+ if (line_length < 3) {
+ log_warn(LD_CONFIG, "Too few arguments on ClientTransportPlugin line.");
+ goto err;
+ }
+
+ /* Get the first line element, split it to commas into
+ transport_list (in case it's multiple transports) and validate
+ the transport names. */
+ transports = smartlist_get(items, 0);
+ transport_list = smartlist_create();
+ smartlist_split_string(transport_list, transports, ",",
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport_name) {
+ if (!string_is_C_identifier(transport_name)) {
+ log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
+ transport_name);
+ goto err;
+ }
+ } SMARTLIST_FOREACH_END(transport_name);
+
+ /* field2 is either a SOCKS version or "exec" */
+ field2 = smartlist_get(items, 1);
+
+ if (!strcmp(field2,"socks4")) {
+ socks_ver = PROXY_SOCKS4;
+ } else if (!strcmp(field2,"socks5")) {
+ socks_ver = PROXY_SOCKS5;
+ } else if (!strcmp(field2,"exec")) {
+ is_managed=1;
+ } else {
+ log_warn(LD_CONFIG, "Strange ClientTransportPlugin field '%s'.",
+ field2);
+ goto err;
+ }
+
+ if (is_managed) { /* managed */
+ if (!validate_only) { /* if we are not just validating, use the
+ rest of the line as the argv of the proxy
+ to be launched */
+ proxy_argc = line_length-2;
+ tor_assert(proxy_argc > 0);
+ proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1));
+ tmp = proxy_argv;
+ for (i=0;i<proxy_argc;i++) { /* store arguments */
+ *tmp++ = smartlist_get(items, 2);
+ smartlist_del_keeporder(items, 2);
+ }
+ *tmp = NULL; /*terminated with NUL pointer, just like execve() likes it*/
+
+ /* kickstart the thing */
+ pt_kickstart_client_proxy(transport_list, proxy_argv);
+ }
+ } else { /* external */
+ if (smartlist_len(transport_list) != 1) {
+ log_warn(LD_CONFIG, "You can't have an external proxy with "
+ "more than one transports.");
+ goto err;
+ }
+
+ addrport = smartlist_get(items, 2);
+
+ if (tor_addr_port_parse(addrport, &addr, &port)<0) {
+ log_warn(LD_CONFIG, "Error parsing transport "
+ "address '%s'", addrport);
+ goto err;
+ }
+ if (!port) {
+ log_warn(LD_CONFIG,
+ "Transport address '%s' has no port.", addrport);
+ goto err;
+ }
+
+ if (!validate_only) {
+ transport_add_from_config(&addr, port, smartlist_get(transport_list, 0),
+ socks_ver);
+
+ log_info(LD_DIR, "Transport '%s' found at %s:%d",
+ transports, fmt_addr(&addr), (int)port);
+ }
+ }
+
+ r = 0;
+ goto done;
+
+ err:
+ r = -1;
+
+ done:
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+ SMARTLIST_FOREACH(transport_list, char*, s, tor_free(s));
+ smartlist_free(transport_list);
+
+ return r;
+}
+
+/** Read the contents of a ServerTransportPlugin line from
+ * <b>line</b>. Return 0 if the line is well-formed, and -1 if it
+ * isn't.
+ * If <b>validate_only</b> is 0, the line is well-formed, and it's a
+ * managed proxy line, launch the managed proxy. */
+static int
+parse_server_transport_line(const char *line, int validate_only)
+{
+ smartlist_t *items = NULL;
+ int r;
+ const char *transports=NULL;
+ smartlist_t *transport_list=NULL;
+ char *type=NULL;
+ char *addrport=NULL;
+ tor_addr_t addr;
+ uint16_t port = 0;
+
+ /* managed proxy options */
+ int is_managed=0;
+ char **proxy_argv=NULL;
+ char **tmp=NULL;
+ int proxy_argc,i;
+
+ int line_length;
+
+ items = smartlist_create();
+ smartlist_split_string(items, line, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+
+ line_length = smartlist_len(items);
+ if (line_length < 3) {
+ log_warn(LD_CONFIG, "Too few arguments on ServerTransportPlugin line.");
+ goto err;
+ }
+
+ /* Get the first line element, split it to commas into
+ transport_list (in case it's multiple transports) and validate
+ the transport names. */
+ transports = smartlist_get(items, 0);
+ transport_list = smartlist_create();
+ smartlist_split_string(transport_list, transports, ",",
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport_name) {
+ if (!string_is_C_identifier(transport_name)) {
+ log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
+ transport_name);
+ goto err;
+ }
+ } SMARTLIST_FOREACH_END(transport_name);
+
+ type = smartlist_get(items, 1);
+
+ if (!strcmp(type, "exec")) {
+ is_managed=1;
+ } else if (!strcmp(type, "proxy")) {
+ is_managed=0;
+ } else {
+ log_warn(LD_CONFIG, "Strange ServerTransportPlugin type '%s'", type);
+ goto err;
+ }
+
+ if (is_managed) { /* managed */
+ if (!validate_only) {
+ proxy_argc = line_length-2;
+ tor_assert(proxy_argc > 0);
+ proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1));
+ tmp = proxy_argv;
+
+ for (i=0;i<proxy_argc;i++) { /* store arguments */
+ *tmp++ = smartlist_get(items, 2);
+ smartlist_del_keeporder(items, 2);
+ }
+ *tmp = NULL; /*terminated with NUL pointer, just like execve() likes it*/
+
+ /* kickstart the thing */
+ pt_kickstart_server_proxy(transport_list, proxy_argv);
+ }
+ } else { /* external */
+ if (smartlist_len(transport_list) != 1) {
+ log_warn(LD_CONFIG, "You can't have an external proxy with "
+ "more than one transports.");
+ goto err;
+ }
+
+ addrport = smartlist_get(items, 2);
+
+ if (tor_addr_port_parse(addrport, &addr, &port)<0) {
+ log_warn(LD_CONFIG, "Error parsing transport "
+ "address '%s'", addrport);
+ goto err;
+ }
+ if (!port) {
+ log_warn(LD_CONFIG,
+ "Transport address '%s' has no port.", addrport);
+ goto err;
+ }
+
+ if (!validate_only) {
+ log_info(LD_DIR, "Server transport '%s' at %s:%d.",
+ transports, fmt_addr(&addr), (int)port);
+ }
+ }
+
+ r = 0;
+ goto done;
+
+ err:
+ r = -1;
+
+ done:
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+ SMARTLIST_FOREACH(transport_list, char*, s, tor_free(s));
+ smartlist_free(transport_list);
+
+ return r;
+}
+
/** Read the contents of a DirServer line from <b>line</b>. If
* <b>validate_only</b> is 0, and the line is well-formed, and it
* shares any bits with <b>required_type</b> or <b>required_type</b>
@@ -4498,7 +4984,7 @@ parse_bridge_line(const char *line, int validate_only)
* bits it's missing) as a valid authority. Return 0 on success,
* or -1 if the line isn't well-formed or if we can't add it. */
static int
-parse_dir_server_line(const char *line, authority_type_t required_type,
+parse_dir_server_line(const char *line, dirinfo_type_t required_type,
int validate_only)
{
smartlist_t *items = NULL;
@@ -4507,7 +4993,7 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
uint16_t dir_port = 0, or_port = 0;
char digest[DIGEST_LEN];
char v3_digest[DIGEST_LEN];
- authority_type_t type = V2_AUTHORITY;
+ dirinfo_type_t type = V2_DIRINFO;
int is_not_hidserv_authority = 0, is_not_v2_authority = 0;
items = smartlist_create();
@@ -4528,13 +5014,13 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
if (TOR_ISDIGIT(flag[0]))
break;
if (!strcasecmp(flag, "v1")) {
- type |= (V1_AUTHORITY | HIDSERV_AUTHORITY);
+ type |= (V1_DIRINFO | HIDSERV_DIRINFO);
} else if (!strcasecmp(flag, "hs")) {
- type |= HIDSERV_AUTHORITY;
+ type |= HIDSERV_DIRINFO;
} else if (!strcasecmp(flag, "no-hs")) {
is_not_hidserv_authority = 1;
} else if (!strcasecmp(flag, "bridge")) {
- type |= BRIDGE_AUTHORITY;
+ type |= BRIDGE_DIRINFO;
} else if (!strcasecmp(flag, "no-v2")) {
is_not_v2_authority = 1;
} else if (!strcasecmpstart(flag, "orport=")) {
@@ -4551,7 +5037,7 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
log_warn(LD_CONFIG, "Bad v3 identity digest '%s' on DirServer line",
flag);
} else {
- type |= V3_AUTHORITY;
+ type |= V3_DIRINFO|EXTRAINFO_DIRINFO|MICRODESC_DIRINFO;
}
} else {
log_warn(LD_CONFIG, "Unrecognized flag '%s' on DirServer line",
@@ -4561,9 +5047,9 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
smartlist_del_keeporder(items, 0);
}
if (is_not_hidserv_authority)
- type &= ~HIDSERV_AUTHORITY;
+ type &= ~HIDSERV_DIRINFO;
if (is_not_v2_authority)
- type &= ~V2_AUTHORITY;
+ type &= ~V2_DIRINFO;
if (smartlist_len(items) < 2) {
log_warn(LD_CONFIG, "Too few arguments to DirServer line.");
@@ -4626,6 +5112,372 @@ parse_dir_server_line(const char *line, authority_type_t required_type,
return r;
}
+/** Free all storage held in <b>port</b> */
+static void
+port_cfg_free(port_cfg_t *port)
+{
+ tor_free(port);
+}
+
+/** Warn for every port in <b>ports</b> that is on a publicly routable
+ * address. */
+static void
+warn_nonlocal_client_ports(const smartlist_t *ports, const char *portname)
+{
+ SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) {
+ if (!tor_addr_is_internal(&port->addr, 1)) {
+ log_warn(LD_CONFIG, "You specified a public address for %sPort. "
+ "Other people on the Internet might find your computer and "
+ "use it as an open proxy. Please don't allow this unless you "
+ "have a good reason.", portname);
+ } else if (!tor_addr_is_loopback(&port->addr)) {
+ log_notice(LD_CONFIG, "You configured a non-loopback address for %sPort. "
+ "This allows everybody on your local network to use your "
+ "machine as a proxy. Make sure this is what you wanted.",
+ portname);
+ }
+ } SMARTLIST_FOREACH_END(port);
+}
+
+#define CL_PORT_NO_OPTIONS (1u<<0)
+#define CL_PORT_WARN_NONLOCAL (1u<<1)
+#define CL_PORT_ALLOW_EXTRA_LISTENADDR (1u<<2)
+
+/**
+ * Parse port configuration for a single client port type.
+ *
+ * Read entries of the "FooPort" type from the list <b>ports</b>, and
+ * entries of the "FooListenAddress" type from the list
+ * <b>listenaddrs</b>. Two syntaxes are supported: a legacy syntax
+ * where FooPort is at most a single entry containing a port number and
+ * where FooListenAddress has any number of address:port combinations;
+ * and a new syntax where there are no FooListenAddress entries and
+ * where FooPort can have any number of entries of the format
+ * "[Address:][Port] IsolationOptions".
+ *
+ * In log messages, describe the port type as <b>portname</b>.
+ *
+ * If no address is specified, default to <b>defaultaddr</b>. If no
+ * FooPort is given, default to defaultport (if 0, there is no default).
+ *
+ * If CL_PORT_NO_OPTIONS is set in <b>flags</b>, do not allow stream
+ * isolation options in the FooPort entries.
+ *
+ * If CL_PORT_WARN_NONLOCAL is set in <b>flags</b>, warn if any of the
+ * ports are not on a local address.
+ *
+ * Unless CL_PORT_ALLOW_EXTRA_LISTENADDR is set in <b>flags</b>, warn
+ * if FooListenAddress is set but FooPort is 0.
+ *
+ * On success, if <b>out</b> is given, add a new port_cfg_t entry to
+ * <b>out</b> for every port that the client should listen on. Return 0
+ * on success, -1 on failure.
+ */
+static int
+parse_client_port_config(smartlist_t *out,
+ const config_line_t *ports,
+ const config_line_t *listenaddrs,
+ const char *portname,
+ int listener_type,
+ const char *defaultaddr,
+ int defaultport,
+ unsigned flags)
+{
+ smartlist_t *elts;
+ int retval = -1;
+ const unsigned allow_client_options = !(flags & CL_PORT_NO_OPTIONS);
+ const unsigned warn_nonlocal = flags & CL_PORT_WARN_NONLOCAL;
+ const unsigned allow_spurious_listenaddr =
+ flags & CL_PORT_ALLOW_EXTRA_LISTENADDR;
+
+ /* FooListenAddress is deprecated; let's make it work like it used to work,
+ * though. */
+ if (listenaddrs) {
+ int mainport = defaultport;
+
+ if (ports && ports->next) {
+ log_warn(LD_CONFIG, "%sListenAddress can't be used when there are "
+ "multiple %sPort lines", portname, portname);
+ return -1;
+ } else if (ports) {
+ if (!strcmp(ports->value, "auto")) {
+ mainport = CFG_AUTO_PORT;
+ } else {
+ int ok;
+ mainport = (int)tor_parse_long(ports->value, 10, 0, 65535, &ok, NULL);
+ if (!ok) {
+ log_warn(LD_CONFIG, "%sListenAddress can only be used with a single "
+ "%sPort with value \"auto\" or 1-65535.",
+ portname, portname);
+ return -1;
+ }
+ }
+ }
+
+ if (mainport == 0) {
+ if (allow_spurious_listenaddr)
+ return 1;
+ log_warn(LD_CONFIG, "%sPort must be defined if %sListenAddress is used",
+ portname, portname);
+ return -1;
+ }
+
+ for (; listenaddrs; listenaddrs = listenaddrs->next) {
+ tor_addr_t addr;
+ uint16_t port = 0;
+ if (tor_addr_port_parse(listenaddrs->value, &addr, &port) < 0) {
+ log_warn(LD_CONFIG, "Unable to parse %sListenAddress '%s'",
+ portname, listenaddrs->value);
+ return -1;
+ }
+ if (out) {
+ port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t));
+ cfg->type = listener_type;
+ cfg->port = port ? port : mainport;
+ tor_addr_copy(&cfg->addr, &addr);
+ cfg->session_group = SESSION_GROUP_UNSET;
+ cfg->isolation_flags = ISO_DEFAULT;
+ smartlist_add(out, cfg);
+ }
+ }
+
+ if (warn_nonlocal && out)
+ warn_nonlocal_client_ports(out, portname);
+ return 0;
+ } /* end if (listenaddrs) */
+
+ /* No ListenAddress lines. If there's no FooPort, then maybe make a default
+ * one. */
+ if (! ports) {
+ if (defaultport && out) {
+ port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t));
+ cfg->type = listener_type;
+ cfg->port = defaultport;
+ tor_addr_from_str(&cfg->addr, defaultaddr);
+ cfg->session_group = SESSION_GROUP_UNSET;
+ cfg->isolation_flags = ISO_DEFAULT;
+ smartlist_add(out, cfg);
+ }
+ return 0;
+ }
+
+ /* At last we can actually parse the FooPort lines. The syntax is:
+ * [Addr:](Port|auto) [Options].*/
+ elts = smartlist_create();
+
+ for (; ports; ports = ports->next) {
+ tor_addr_t addr;
+ int port;
+ int sessiongroup = SESSION_GROUP_UNSET;
+ unsigned isolation = ISO_DEFAULT;
+
+ char *addrport;
+ uint16_t ptmp=0;
+ int ok;
+
+ smartlist_split_string(elts, ports->value, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ if (smartlist_len(elts) == 0) {
+ log_warn(LD_CONFIG, "Invalid %sPort line with no value", portname);
+ goto err;
+ }
+
+ if (!allow_client_options && smartlist_len(elts) > 1) {
+ log_warn(LD_CONFIG, "Too many options on %sPort line", portname);
+ goto err;
+ }
+
+ /* Now parse the addr/port value */
+ addrport = smartlist_get(elts, 0);
+ if (!strcmp(addrport, "auto")) {
+ port = CFG_AUTO_PORT;
+ tor_addr_from_str(&addr, defaultaddr);
+ } else if (!strcasecmpend(addrport, ":auto")) {
+ char *addrtmp = tor_strndup(addrport, strlen(addrport)-5);
+ port = CFG_AUTO_PORT;
+ if (tor_addr_port_parse(addrtmp, &addr, &ptmp)<0 || ptmp) {
+ log_warn(LD_CONFIG, "Invalid address '%s' for %sPort",
+ escaped(addrport), portname);
+ tor_free(addrtmp);
+ goto err;
+ }
+ } else {
+ /* Try parsing integer port before address, because, who knows?
+ "9050" might be a valid address. */
+ port = (int) tor_parse_long(addrport, 10, 0, 65535, &ok, NULL);
+ if (ok) {
+ tor_addr_from_str(&addr, defaultaddr);
+ } else if (tor_addr_port_parse(addrport, &addr, &ptmp) == 0) {
+ if (ptmp == 0) {
+ log_warn(LD_CONFIG, "%sPort line has address but no port", portname);
+ goto err;
+ }
+ port = ptmp;
+ } else {
+ log_warn(LD_CONFIG, "Couldn't parse address '%s' for %sPort",
+ escaped(addrport), portname);
+ goto err;
+ }
+ }
+
+ /* Now parse the rest of the options, if any. */
+ SMARTLIST_FOREACH_BEGIN(elts, char *, elt) {
+ int no = 0, isoflag = 0;
+ const char *elt_orig = elt;
+ if (elt_sl_idx == 0)
+ continue; /* Skip addr:port */
+ if (!strcasecmpstart(elt, "SessionGroup=")) {
+ int group = (int)tor_parse_long(elt+strlen("SessionGroup="),
+ 10, 0, INT_MAX, &ok, NULL);
+ if (!ok) {
+ log_warn(LD_CONFIG, "Invalid %sPort option '%s'",
+ portname, escaped(elt));
+ goto err;
+ }
+ if (sessiongroup >= 0) {
+ log_warn(LD_CONFIG, "Multiple SessionGroup options on %sPort",
+ portname);
+ goto err;
+ }
+ sessiongroup = group;
+ continue;
+ }
+
+ if (!strcasecmpstart(elt, "No")) {
+ no = 1;
+ elt += 2;
+ }
+ if (!strcasecmpend(elt, "s"))
+ elt[strlen(elt)-1] = '\0'; /* kill plurals. */
+
+ if (!strcasecmp(elt, "IsolateDestPort")) {
+ isoflag = ISO_DESTPORT;
+ } else if (!strcasecmp(elt, "IsolateDestAddr")) {
+ isoflag = ISO_DESTADDR;
+ } else if (!strcasecmp(elt, "IsolateSOCKSAuth")) {
+ isoflag = ISO_SOCKSAUTH;
+ } else if (!strcasecmp(elt, "IsolateClientProtocol")) {
+ isoflag = ISO_CLIENTPROTO;
+ } else if (!strcasecmp(elt, "IsolateClientAddr")) {
+ isoflag = ISO_CLIENTADDR;
+ } else {
+ log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'",
+ portname, escaped(elt_orig));
+ }
+
+ if (no) {
+ isolation &= ~isoflag;
+ } else {
+ isolation |= isoflag;
+ }
+ } SMARTLIST_FOREACH_END(elt);
+
+ if (out && port) {
+ port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t));
+ cfg->type = listener_type;
+ cfg->port = port;
+ tor_addr_copy(&cfg->addr, &addr);
+ cfg->session_group = sessiongroup;
+ cfg->isolation_flags = isolation;
+ smartlist_add(out, cfg);
+ }
+ SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
+ smartlist_clear(elts);
+ }
+
+ if (warn_nonlocal && out)
+ warn_nonlocal_client_ports(out, portname);
+
+ retval = 0;
+ err:
+ SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp));
+ smartlist_free(elts);
+ return retval;
+}
+
+/** Parse all client port types (Socks, DNS, Trans, NATD) from
+ * <b>options</b>. On success, set *<b>n_ports_out</b> to the number of
+ * ports that are listed and return 0. On failure, set *<b>msg</b> to a
+ * description of the problem and return -1.
+ *
+ * If <b>validate_only</b> is false, set configured_client_ports to the
+ * new list of ports parsed from <b>options</b>.
+ **/
+static int
+parse_client_ports(const or_options_t *options, int validate_only,
+ char **msg, int *n_ports_out)
+{
+ smartlist_t *ports;
+ int retval = -1;
+
+ ports = smartlist_create();
+
+ *n_ports_out = 0;
+
+ if (parse_client_port_config(ports,
+ options->SocksPort, options->SocksListenAddress,
+ "Socks", CONN_TYPE_AP_LISTENER,
+ "127.0.0.1", 9050,
+ CL_PORT_WARN_NONLOCAL|CL_PORT_ALLOW_EXTRA_LISTENADDR) < 0) {
+ *msg = tor_strdup("Invalid SocksPort/SocksListenAddress configuration");
+ goto err;
+ }
+ if (parse_client_port_config(ports,
+ options->DNSPort, options->DNSListenAddress,
+ "DNS", CONN_TYPE_AP_DNS_LISTENER,
+ "127.0.0.1", 0,
+ CL_PORT_WARN_NONLOCAL) < 0) {
+ *msg = tor_strdup("Invalid DNSPort/DNSListenAddress configuration");
+ goto err;
+ }
+ if (parse_client_port_config(ports,
+ options->TransPort, options->TransListenAddress,
+ "Trans", CONN_TYPE_AP_TRANS_LISTENER,
+ "127.0.0.1", 0,
+ CL_PORT_WARN_NONLOCAL) < 0) {
+ *msg = tor_strdup("Invalid TransPort/TransListenAddress configuration");
+ goto err;
+ }
+ if (parse_client_port_config(ports,
+ options->NATDPort, options->NATDListenAddress,
+ "NATD", CONN_TYPE_AP_NATD_LISTENER,
+ "127.0.0.1", 0,
+ CL_PORT_WARN_NONLOCAL) < 0) {
+ *msg = tor_strdup("Invalid NatdPort/NatdListenAddress configuration");
+ goto err;
+ }
+
+ *n_ports_out = smartlist_len(ports);
+
+ if (!validate_only) {
+ if (configured_client_ports) {
+ SMARTLIST_FOREACH(configured_client_ports,
+ port_cfg_t *, p, port_cfg_free(p));
+ smartlist_free(configured_client_ports);
+ }
+ configured_client_ports = ports;
+ ports = NULL; /* prevent free below. */
+ }
+
+ retval = 0;
+ err:
+ if (ports) {
+ SMARTLIST_FOREACH(ports, port_cfg_t *, p, port_cfg_free(p));
+ smartlist_free(ports);
+ }
+ return retval;
+}
+
+/** Return a list of port_cfg_t for client ports parsed from the
+ * options. */
+const smartlist_t *
+get_configured_client_ports(void)
+{
+ if (!configured_client_ports)
+ configured_client_ports = smartlist_create();
+ return configured_client_ports;
+}
+
/** Adjust the value of options->DataDirectory, or fill it in if it's
* absent. Return 0 on success, -1 on failure. */
static int
@@ -4697,7 +5549,7 @@ validate_data_directory(or_options_t *options)
* doesn't begin with GENERATED_FILE_PREFIX, rename it. Otherwise
* replace it. Return 0 on success, -1 on failure. */
static int
-write_configuration_file(const char *fname, or_options_t *options)
+write_configuration_file(const char *fname, const or_options_t *options)
{
char *old_val=NULL, *new_val=NULL, *new_conf=NULL;
int rename_old = 0, r;
@@ -4838,6 +5690,26 @@ static struct unit_table_t time_units[] = {
{ NULL, 0 },
};
+/** Table to map the names of time units to the number of milliseconds
+ * they contain. */
+static struct unit_table_t time_msec_units[] = {
+ { "", 1 },
+ { "msec", 1 },
+ { "millisecond", 1 },
+ { "milliseconds", 1 },
+ { "second", 1000 },
+ { "seconds", 1000 },
+ { "minute", 60*1000 },
+ { "minutes", 60*1000 },
+ { "hour", 60*60*1000 },
+ { "hours", 60*60*1000 },
+ { "day", 24*60*60*1000 },
+ { "days", 24*60*60*1000 },
+ { "week", 7*24*60*60*1000 },
+ { "weeks", 7*24*60*60*1000 },
+ { NULL, 0 },
+};
+
/** Parse a string <b>val</b> containing a number, zero or more
* spaces, and an optional unit string. If the unit appears in the
* table <b>u</b>, then multiply the number by the unit multiplier.
@@ -4901,6 +5773,25 @@ config_parse_memunit(const char *s, int *ok)
return u;
}
+/** Parse a string in the format "number unit", where unit is a unit of
+ * time in milliseconds. On success, set *<b>ok</b> to true and return
+ * the number of milliseconds in the provided interval. Otherwise, set
+ * *<b>ok</b> to 0 and return -1. */
+static int
+config_parse_msec_interval(const char *s, int *ok)
+{
+ uint64_t r;
+ r = config_parse_units(s, time_msec_units, ok);
+ if (!ok)
+ return -1;
+ if (r > INT_MAX) {
+ log_warn(LD_CONFIG, "Msec interval '%s' is too long", s);
+ *ok = 0;
+ return -1;
+ }
+ return (int)r;
+}
+
/** Parse a string in the format "number unit", where unit is a unit of time.
* On success, set *<b>ok</b> to true and return the number of seconds in
* the provided interval. Otherwise, set *<b>ok</b> to 0 and return -1.
@@ -4920,13 +5811,29 @@ config_parse_interval(const char *s, int *ok)
return (int)r;
}
+/** Return the number of cpus configured in <b>options</b>. If we are
+ * told to auto-detect the number of cpus, return the auto-detected number. */
+int
+get_num_cpus(const or_options_t *options)
+{
+ if (options->NumCPUs == 0) {
+ int n = compute_num_cpus();
+ return (n >= 1) ? n : 1;
+ } else {
+ return options->NumCPUs;
+ }
+}
+
/**
* Initialize the libevent library.
*/
static void
-init_libevent(void)
+init_libevent(const or_options_t *options)
{
const char *badness=NULL;
+ tor_libevent_cfg cfg;
+
+ tor_assert(options);
configure_libevent_logging();
/* If the kernel complains that some method (say, epoll) doesn't
@@ -4936,7 +5843,12 @@ init_libevent(void)
tor_check_libevent_header_compatibility();
- tor_libevent_initialize();
+ memset(&cfg, 0, sizeof(cfg));
+ cfg.disable_iocp = options->DisableIOCP;
+ cfg.num_cpus = get_num_cpus(options);
+ cfg.msec_per_tick = options->TokenBucketRefillInterval;
+
+ tor_libevent_initialize(&cfg);
suppress_libevent_log_msg(NULL);
@@ -4975,7 +5887,7 @@ get_or_state(void)
* Note: Consider using the get_datadir_fname* macros in or.h.
*/
char *
-options_get_datadir_fname2_suffix(or_options_t *options,
+options_get_datadir_fname2_suffix(const or_options_t *options,
const char *sub1, const char *sub2,
const char *suffix)
{
@@ -5010,6 +5922,69 @@ options_get_datadir_fname2_suffix(or_options_t *options,
return fname;
}
+/** Return true if <b>line</b> is a valid state TransportProxy line.
+ * Return false otherwise. */
+static int
+state_transport_line_is_valid(const char *line)
+{
+ smartlist_t *items = NULL;
+ char *addrport=NULL;
+ tor_addr_t addr;
+ uint16_t port = 0;
+ int r;
+
+ items = smartlist_create();
+ smartlist_split_string(items, line, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+
+ if (smartlist_len(items) != 2) {
+ log_warn(LD_CONFIG, "state: Not enough arguments in TransportProxy line.");
+ goto err;
+ }
+
+ addrport = smartlist_get(items, 1);
+ if (tor_addr_port_parse(addrport, &addr, &port) < 0) {
+ log_warn(LD_CONFIG, "state: Could not parse addrport.");
+ goto err;
+ }
+
+ if (!port) {
+ log_warn(LD_CONFIG, "state: Transport line did not contain port.");
+ goto err;
+ }
+
+ r = 1;
+ goto done;
+
+ err:
+ r = 0;
+
+ done:
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+ return r;
+}
+
+/** Return 0 if all TransportProxy lines in <b>state</b> are well
+ * formed. Otherwise, return -1. */
+static int
+validate_transports_in_state(or_state_t *state)
+{
+ int broken = 0;
+ config_line_t *line;
+
+ for (line = state->TransportProxies ; line ; line = line->next) {
+ tor_assert(!strcmp(line->key, "TransportProxy"));
+ if (!state_transport_line_is_valid(line->value)<0)
+ broken = 1;
+ }
+
+ if (broken)
+ log_warn(LD_CONFIG, "state: State file seems to be broken.");
+
+ return 0;
+}
+
/** Return 0 if every setting in <b>state</b> is reasonable, and a
* permissible transition from <b>old_state</b>. Else warn and return -1.
* Should have no side effects, except for normalizing the contents of
@@ -5028,6 +6003,9 @@ or_state_validate(or_state_t *old_state, or_state_t *state,
if (entry_guards_parse_state(state, 0, msg)<0)
return -1;
+ if (validate_transports_in_state(state)<0)
+ return -1;
+
return 0;
}
@@ -5260,6 +6238,150 @@ or_state_save(time_t now)
return 0;
}
+/** Return the config line for transport <b>transport</b> in the current state.
+ * Return NULL if there is no config line for <b>transport</b>. */
+static config_line_t *
+get_transport_in_state_by_name(const char *transport)
+{
+ or_state_t *or_state = get_or_state();
+ config_line_t *line;
+ config_line_t *ret = NULL;
+ smartlist_t *items = NULL;
+
+ for (line = or_state->TransportProxies ; line ; line = line->next) {
+ tor_assert(!strcmp(line->key, "TransportProxy"));
+
+ items = smartlist_create();
+ smartlist_split_string(items, line->value, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+ if (smartlist_len(items) != 2) /* broken state */
+ goto done;
+
+ if (!strcmp(smartlist_get(items, 0), transport)) {
+ ret = line;
+ goto done;
+ }
+
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+ items = NULL;
+ }
+
+ done:
+ if (items) {
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+ }
+ return ret;
+}
+
+/** Return string containing the address:port part of the
+ * TransportProxy <b>line</b> for transport <b>transport</b>.
+ * If the line is corrupted, return NULL. */
+static const char *
+get_transport_bindaddr(const char *line, const char *transport)
+{
+ char *line_tmp = NULL;
+
+ if (strlen(line) < strlen(transport) + 2) {
+ goto broken_state;
+ } else {
+ /* line should start with the name of the transport and a space.
+ (for example, "obfs2 127.0.0.1:47245") */
+ tor_asprintf(&line_tmp, "%s ", transport);
+ if (strcmpstart(line, line_tmp))
+ goto broken_state;
+
+ tor_free(line_tmp);
+ return (line+strlen(transport)+1);
+ }
+
+ broken_state:
+ tor_free(line_tmp);
+ return NULL;
+}
+
+/** Return a static string containing the address:port a proxy
+ * transport should bind on. */
+const char *
+get_bindaddr_for_transport(const char *transport)
+{
+ static const char default_addrport[] = "127.0.0.1:0";
+ const char *bindaddr = NULL;
+
+ config_line_t *line = get_transport_in_state_by_name(transport);
+ if (!line)
+ return default_addrport;
+
+ bindaddr = get_transport_bindaddr(line->value, transport);
+
+ return bindaddr ? bindaddr : default_addrport;
+}
+
+/** Save <b>transport</b> listening on <b>addr</b>:<b>port</b> to
+ state */
+void
+save_transport_to_state(const char *transport,
+ const tor_addr_t *addr, uint16_t port)
+{
+ or_state_t *state = get_or_state();
+
+ char *transport_addrport=NULL;
+
+ /** find where to write on the state */
+ config_line_t **next, *line;
+
+ /* see if this transport is already stored in state */
+ config_line_t *transport_line =
+ get_transport_in_state_by_name(transport);
+
+ if (transport_line) { /* if transport already exists in state... */
+ const char *prev_bindaddr = /* get its addrport... */
+ get_transport_bindaddr(transport_line->value, transport);
+ tor_asprintf(&transport_addrport, "%s:%d", fmt_addr(addr), (int)port);
+
+ /* if transport in state has the same address as this one, life is good */
+ if (!strcmp(prev_bindaddr, transport_addrport)) {
+ log_info(LD_CONFIG, "Transport seems to have spawned on its usual "
+ "address:port.");
+ goto done;
+ } else { /* if addrport in state is different than the one we got */
+ log_info(LD_CONFIG, "Transport seems to have spawned on different "
+ "address:port. Let's update the state file with the new "
+ "address:port");
+ tor_free(transport_line->value); /* free the old line */
+ tor_asprintf(&transport_line->value, "%s %s:%d", transport,
+ fmt_addr(addr),
+ (int) port); /* replace old addrport line with new line */
+ }
+ } else { /* never seen this one before; save it in state for next time */
+ log_info(LD_CONFIG, "It's the first time we see this transport. "
+ "Let's save its address:port");
+ next = &state->TransportProxies;
+ /* find the last TransportProxy line in the state and point 'next'
+ right after it */
+ line = state->TransportProxies;
+ while (line) {
+ next = &(line->next);
+ line = line->next;
+ }
+
+ /* allocate space for the new line and fill it in */
+ *next = line = tor_malloc_zero(sizeof(config_line_t));
+ line->key = tor_strdup("TransportProxy");
+ tor_asprintf(&line->value, "%s %s:%d", transport,
+ fmt_addr(addr), (int) port);
+
+ next = &(line->next);
+ }
+
+ if (!get_options()->AvoidDiskWrites)
+ or_state_mark_dirty(state, 0);
+
+ done:
+ tor_free(transport_addrport);
+}
+
/** Given a file name check to see whether the file exists but has not been
* modified for a very long time. If so, remove it. */
void
@@ -5292,7 +6414,7 @@ getinfo_helper_config(control_connection_t *conn,
smartlist_t *sl = smartlist_create();
int i;
for (i = 0; _option_vars[i].name; ++i) {
- config_var_t *var = &_option_vars[i];
+ const config_var_t *var = &_option_vars[i];
const char *type;
char *line;
switch (var->type) {
@@ -5301,9 +6423,11 @@ getinfo_helper_config(control_connection_t *conn,
case CONFIG_TYPE_UINT: type = "Integer"; break;
case CONFIG_TYPE_PORT: type = "Port"; break;
case CONFIG_TYPE_INTERVAL: type = "TimeInterval"; break;
+ case CONFIG_TYPE_MSEC_INTERVAL: type = "TimeMsecInterval"; break;
case CONFIG_TYPE_MEMUNIT: type = "DataSize"; break;
case CONFIG_TYPE_DOUBLE: type = "Float"; break;
case CONFIG_TYPE_BOOL: type = "Boolean"; break;
+ case CONFIG_TYPE_AUTOBOOL: type = "Boolean+Auto"; break;
case CONFIG_TYPE_ISOTIME: type = "Time"; break;
case CONFIG_TYPE_ROUTERSET: type = "RouterList"; break;
case CONFIG_TYPE_CSV: type = "CommaList"; break;
diff --git a/src/or/config.h b/src/or/config.h
index 78a67dddf..76f6841d7 100644
--- a/src/or/config.h
+++ b/src/or/config.h
@@ -13,7 +13,8 @@
#define _TOR_CONFIG_H
const char *get_dirportfrontpage(void);
-or_options_t *get_options(void);
+const or_options_t *get_options(void);
+or_options_t *get_options_mutable(void);
int set_options(or_options_t *new_val, char **msg);
void config_free_all(void);
const char *safe_str_client(const char *address);
@@ -26,21 +27,21 @@ int config_get_lines(const char *string, config_line_t **result);
void config_free_lines(config_line_t *front);
setopt_err_t options_trial_assign(config_line_t *list, int use_defaults,
int clear_first, char **msg);
-int resolve_my_address(int warn_severity, or_options_t *options,
+int resolve_my_address(int warn_severity, const or_options_t *options,
uint32_t *addr, char **hostname_out);
int is_local_addr(const tor_addr_t *addr) ATTR_PURE;
void options_init(or_options_t *options);
-char *options_dump(or_options_t *options, int minimal);
+char *options_dump(const or_options_t *options, int minimal);
int options_init_from_torrc(int argc, char **argv);
setopt_err_t options_init_from_string(const char *cf,
int command, const char *command_arg, char **msg);
int option_is_recognized(const char *key);
const char *option_get_canonical_name(const char *key);
-config_line_t *option_get_assignment(or_options_t *options,
+config_line_t *option_get_assignment(const or_options_t *options,
const char *key);
int options_save_current(void);
const char *get_torrc_fname(void);
-char *options_get_datadir_fname2_suffix(or_options_t *options,
+char *options_get_datadir_fname2_suffix(const or_options_t *options,
const char *sub1, const char *sub2,
const char *suffix);
#define get_datadir_fname2_suffix(sub1, sub2, suffix) \
@@ -57,23 +58,35 @@ char *options_get_datadir_fname2_suffix(or_options_t *options,
#define get_datadir_fname_suffix(sub1, suffix) \
get_datadir_fname2_suffix((sub1), NULL, (suffix))
+int get_num_cpus(const or_options_t *options);
+
or_state_t *get_or_state(void);
int did_last_state_file_write_fail(void);
int or_state_save(time_t now);
-int options_need_geoip_info(or_options_t *options, const char **reason_out);
+const smartlist_t *get_configured_client_ports(void);
+
+int options_need_geoip_info(const or_options_t *options,
+ const char **reason_out);
+
+void save_transport_to_state(const char *transport_name,
+ const tor_addr_t *addr, uint16_t port);
+const char *get_bindaddr_for_transport(const char *transport);
+
int getinfo_helper_config(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg);
const char *tor_get_digests(void);
-uint32_t get_effective_bwrate(or_options_t *options);
-uint32_t get_effective_bwburst(or_options_t *options);
+uint32_t get_effective_bwrate(const or_options_t *options);
+uint32_t get_effective_bwburst(const or_options_t *options);
#ifdef CONFIG_PRIVATE
/* Used only by config.c and test.c */
or_options_t *options_new(void);
#endif
+void config_register_addressmaps(const or_options_t *options);
+
#endif
diff --git a/src/or/connection.c b/src/or/connection.c
index 2049f4240..45a12715a 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -36,17 +36,28 @@
#include "router.h"
#include "routerparse.h"
+#ifdef USE_BUFFEREVENTS
+#include <event2/event.h>
+#endif
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
static connection_t *connection_create_listener(
const struct sockaddr *listensockaddr,
socklen_t listensocklen, int type,
- char* address);
+ const char *address,
+ const port_cfg_t *portcfg);
static void connection_init(time_t now, connection_t *conn, int type,
int socket_family);
static int connection_init_accepted_conn(connection_t *conn,
- uint8_t listener_type);
+ const listener_connection_t *listener);
static int connection_handle_listener_read(connection_t *conn, int new_type);
+#ifndef USE_BUFFEREVENTS
static int connection_bucket_should_increase(int bucket,
or_connection_t *conn);
+#endif
static int connection_finished_flushing(connection_t *conn);
static int connection_flushed_some(connection_t *conn);
static int connection_finished_connecting(connection_t *conn);
@@ -60,6 +71,8 @@ static void set_constrained_socket_buffers(tor_socket_t sock, int size);
static const char *connection_proxy_state_to_string(int state);
static int connection_read_https_proxy_response(connection_t *conn);
static void connection_send_socks5_connect(connection_t *conn);
+static const char *proxy_type_to_string(int proxy_type);
+static int get_proxy_type(void);
/** The last IPv4 address that our network interface seemed to have been
* binding to, in host order. We use this to detect when our IP changes. */
@@ -68,6 +81,15 @@ static uint32_t last_interface_ip = 0;
* Used to detect IP address changes. */
static smartlist_t *outgoing_addrs = NULL;
+#define CASE_ANY_LISTENER_TYPE \
+ case CONN_TYPE_OR_LISTENER: \
+ case CONN_TYPE_AP_LISTENER: \
+ case CONN_TYPE_DIR_LISTENER: \
+ case CONN_TYPE_CONTROL_LISTENER: \
+ case CONN_TYPE_AP_TRANS_LISTENER: \
+ case CONN_TYPE_AP_NATD_LISTENER: \
+ case CONN_TYPE_AP_DNS_LISTENER
+
/**************************************************************/
/**
@@ -108,13 +130,7 @@ conn_state_to_string(int type, int state)
{
static char buf[96];
switch (type) {
- case CONN_TYPE_OR_LISTENER:
- case CONN_TYPE_AP_LISTENER:
- case CONN_TYPE_AP_TRANS_LISTENER:
- case CONN_TYPE_AP_NATD_LISTENER:
- case CONN_TYPE_AP_DNS_LISTENER:
- case CONN_TYPE_DIR_LISTENER:
- case CONN_TYPE_CONTROL_LISTENER:
+ CASE_ANY_LISTENER_TYPE:
if (state == LISTENER_STATE_READY)
return "ready";
break;
@@ -183,6 +199,26 @@ conn_state_to_string(int type, int state)
return buf;
}
+#ifdef USE_BUFFEREVENTS
+/** Return true iff the connection's type is one that can use a
+ bufferevent-based implementation. */
+int
+connection_type_uses_bufferevent(connection_t *conn)
+{
+ switch (conn->type) {
+ case CONN_TYPE_AP:
+ case CONN_TYPE_EXIT:
+ case CONN_TYPE_DIR:
+ case CONN_TYPE_CONTROL:
+ case CONN_TYPE_OR:
+ case CONN_TYPE_CPUWORKER:
+ return 1;
+ default:
+ return 0;
+ }
+}
+#endif
+
/** Allocate and return a new dir_connection_t, initialized as by
* connection_init(). */
dir_connection_t *
@@ -211,16 +247,26 @@ or_connection_new(int socket_family)
return or_conn;
}
+/** Allocate and return a new entry_connection_t, initialized as by
+ * connection_init(). */
+entry_connection_t *
+entry_connection_new(int type, int socket_family)
+{
+ entry_connection_t *entry_conn = tor_malloc_zero(sizeof(entry_connection_t));
+ tor_assert(type == CONN_TYPE_AP);
+ connection_init(time(NULL), ENTRY_TO_CONN(entry_conn), type, socket_family);
+ entry_conn->socks_request = socks_request_new();
+ return entry_conn;
+}
+
/** Allocate and return a new edge_connection_t, initialized as by
* connection_init(). */
edge_connection_t *
edge_connection_new(int type, int socket_family)
{
edge_connection_t *edge_conn = tor_malloc_zero(sizeof(edge_connection_t));
- tor_assert(type == CONN_TYPE_EXIT || type == CONN_TYPE_AP);
+ tor_assert(type == CONN_TYPE_EXIT);
connection_init(time(NULL), TO_CONN(edge_conn), type, socket_family);
- if (type == CONN_TYPE_AP)
- edge_conn->socks_request = tor_malloc_zero(sizeof(socks_request_t));
return edge_conn;
}
@@ -237,6 +283,17 @@ control_connection_new(int socket_family)
return control_conn;
}
+/** Allocate and return a new listener_connection_t, initialized as by
+ * connection_init(). */
+listener_connection_t *
+listener_connection_new(int type, int socket_family)
+{
+ listener_connection_t *listener_conn =
+ tor_malloc_zero(sizeof(listener_connection_t));
+ connection_init(time(NULL), TO_CONN(listener_conn), type, socket_family);
+ return listener_conn;
+}
+
/** Allocate, initialize, and return a new connection_t subtype of <b>type</b>
* to make or receive connections of address family <b>socket_family</b>. The
* type should be one of the CONN_TYPE_* constants. */
@@ -248,15 +305,20 @@ connection_new(int type, int socket_family)
return TO_CONN(or_connection_new(socket_family));
case CONN_TYPE_EXIT:
- case CONN_TYPE_AP:
return TO_CONN(edge_connection_new(type, socket_family));
+ case CONN_TYPE_AP:
+ return ENTRY_TO_CONN(entry_connection_new(type, socket_family));
+
case CONN_TYPE_DIR:
return TO_CONN(dir_connection_new(socket_family));
case CONN_TYPE_CONTROL:
return TO_CONN(control_connection_new(socket_family));
+ CASE_ANY_LISTENER_TYPE:
+ return TO_CONN(listener_connection_new(type, socket_family));
+
default: {
connection_t *conn = tor_malloc_zero(sizeof(connection_t));
connection_init(time(NULL), conn, type, socket_family);
@@ -288,15 +350,20 @@ connection_init(time_t now, connection_t *conn, int type, int socket_family)
conn->magic = OR_CONNECTION_MAGIC;
break;
case CONN_TYPE_EXIT:
- case CONN_TYPE_AP:
conn->magic = EDGE_CONNECTION_MAGIC;
break;
+ case CONN_TYPE_AP:
+ conn->magic = ENTRY_CONNECTION_MAGIC;
+ break;
case CONN_TYPE_DIR:
conn->magic = DIR_CONNECTION_MAGIC;
break;
case CONN_TYPE_CONTROL:
conn->magic = CONTROL_CONNECTION_MAGIC;
break;
+ CASE_ANY_LISTENER_TYPE:
+ conn->magic = LISTENER_CONNECTION_MAGIC;
+ break;
default:
conn->magic = BASE_CONNECTION_MAGIC;
break;
@@ -308,10 +375,13 @@ connection_init(time_t now, connection_t *conn, int type, int socket_family)
conn->type = type;
conn->socket_family = socket_family;
- if (!connection_is_listener(conn)) { /* listeners never use their buf */
+#ifndef USE_BUFFEREVENTS
+ if (!connection_is_listener(conn)) {
+ /* listeners never use their buf */
conn->inbuf = buf_new();
conn->outbuf = buf_new();
}
+#endif
conn->timestamp_created = now;
conn->timestamp_lastread = now;
@@ -350,6 +420,10 @@ _connection_free(connection_t *conn)
memlen = sizeof(or_connection_t);
break;
case CONN_TYPE_AP:
+ tor_assert(conn->magic == ENTRY_CONNECTION_MAGIC);
+ mem = TO_ENTRY_CONN(conn);
+ memlen = sizeof(entry_connection_t);
+ break;
case CONN_TYPE_EXIT:
tor_assert(conn->magic == EDGE_CONNECTION_MAGIC);
mem = TO_EDGE_CONN(conn);
@@ -365,6 +439,11 @@ _connection_free(connection_t *conn)
mem = TO_CONTROL_CONN(conn);
memlen = sizeof(control_connection_t);
break;
+ CASE_ANY_LISTENER_TYPE:
+ tor_assert(conn->magic == LISTENER_CONNECTION_MAGIC);
+ mem = TO_LISTENER_CONN(conn);
+ memlen = sizeof(listener_connection_t);
+ break;
default:
tor_assert(conn->magic == BASE_CONNECTION_MAGIC);
mem = conn;
@@ -377,7 +456,8 @@ _connection_free(connection_t *conn)
"bytes on inbuf, %d on outbuf.",
conn_type_to_string(conn->type),
conn_state_to_string(conn->type, conn->state),
- (int)buf_datalen(conn->inbuf), (int)buf_datalen(conn->outbuf));
+ (int)connection_get_inbuf_len(conn),
+ (int)connection_get_outbuf_len(conn));
}
if (!connection_is_listener(conn)) {
@@ -407,15 +487,21 @@ _connection_free(connection_t *conn)
smartlist_free(or_conn->active_circuit_pqueue);
tor_free(or_conn->nickname);
}
- if (CONN_IS_EDGE(conn)) {
- edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
- tor_free(edge_conn->chosen_exit_name);
- if (edge_conn->socks_request) {
- memset(edge_conn->socks_request, 0xcc, sizeof(socks_request_t));
- tor_free(edge_conn->socks_request);
+ if (conn->type == CONN_TYPE_AP) {
+ entry_connection_t *entry_conn = TO_ENTRY_CONN(conn);
+ tor_free(entry_conn->chosen_exit_name);
+ tor_free(entry_conn->original_dest_address);
+ if (entry_conn->socks_request)
+ socks_request_free(entry_conn->socks_request);
+ if (entry_conn->pending_optimistic_data) {
+ generic_buffer_free(entry_conn->pending_optimistic_data);
}
-
- rend_data_free(edge_conn->rend_data);
+ if (entry_conn->sending_optimistic_data) {
+ generic_buffer_free(entry_conn->sending_optimistic_data);
+ }
+ }
+ if (CONN_IS_EDGE(conn)) {
+ rend_data_free(TO_EDGE_CONN(conn)->rend_data);
}
if (conn->type == CONN_TYPE_CONTROL) {
control_connection_t *control_conn = TO_CONTROL_CONN(conn);
@@ -424,6 +510,15 @@ _connection_free(connection_t *conn)
tor_free(conn->read_event); /* Probably already freed by connection_free. */
tor_free(conn->write_event); /* Probably already freed by connection_free. */
+ IF_HAS_BUFFEREVENT(conn, {
+ /* This was a workaround to handle bugs in some old versions of libevent
+ * where callbacks can occur after calling bufferevent_free(). Setting
+ * the callbacks to NULL prevented this. It shouldn't be necessary any
+ * more, but let's not tempt fate for now. */
+ bufferevent_setcb(conn->bufev, NULL, NULL, NULL, NULL);
+ bufferevent_free(conn->bufev);
+ conn->bufev = NULL;
+ });
if (conn->type == CONN_TYPE_DIR) {
dir_connection_t *dir_conn = TO_DIR_CONN(conn);
@@ -450,6 +545,12 @@ _connection_free(connection_t *conn)
log_warn(LD_BUG, "called on OR conn with non-zeroed identity_digest");
connection_or_remove_from_identity_map(TO_OR_CONN(conn));
}
+#ifdef USE_BUFFEREVENTS
+ if (conn->type == CONN_TYPE_OR && TO_OR_CONN(conn)->bucket_cfg) {
+ ev_token_bucket_cfg_free(TO_OR_CONN(conn)->bucket_cfg);
+ TO_OR_CONN(conn)->bucket_cfg = NULL;
+ }
+#endif
memset(mem, 0xCC, memlen); /* poison memory */
tor_free(mem);
@@ -485,39 +586,9 @@ connection_free(connection_t *conn)
_connection_free(conn);
}
-/** Call _connection_free() on every connection in our array, and release all
- * storage held by connection.c. This is used by cpuworkers and dnsworkers
- * when they fork, so they don't keep resources held open (especially
- * sockets).
- *
- * Don't do the checks in connection_free(), because they will
- * fail.
- */
-void
-connection_free_all(void)
-{
- smartlist_t *conns = get_connection_array();
-
- /* We don't want to log any messages to controllers. */
- SMARTLIST_FOREACH(conns, connection_t *, conn,
- if (conn->type == CONN_TYPE_CONTROL)
- TO_CONTROL_CONN(conn)->event_mask = 0);
-
- control_update_global_event_mask();
-
- /* Unlink everything from the identity map. */
- connection_or_clear_identity_map();
-
- SMARTLIST_FOREACH(conns, connection_t *, conn, _connection_free(conn));
-
- if (outgoing_addrs) {
- SMARTLIST_FOREACH(outgoing_addrs, void*, addr, tor_free(addr));
- smartlist_free(outgoing_addrs);
- outgoing_addrs = NULL;
- }
-}
-
-/** Do any cleanup needed:
+/**
+ * Called when we're about to finally unlink and free a connection:
+ * perform necessary accounting and cleanup
* - Directory conns that failed to fetch a rendezvous descriptor
* need to inform pending rendezvous streams.
* - OR conns need to call rep_hist_note_*() to record status.
@@ -530,114 +601,20 @@ connection_free_all(void)
void
connection_about_to_close_connection(connection_t *conn)
{
- circuit_t *circ;
- dir_connection_t *dir_conn;
- or_connection_t *or_conn;
- edge_connection_t *edge_conn;
- time_t now = time(NULL);
-
tor_assert(conn->marked_for_close);
- if (CONN_IS_EDGE(conn)) {
- edge_conn = TO_EDGE_CONN(conn);
- if (!edge_conn->edge_has_sent_end) {
- log_warn(LD_BUG, "(Harmless.) Edge connection (marked at %s:%d) "
- "hasn't sent end yet?",
- conn->marked_for_close_file, conn->marked_for_close);
- tor_fragile_assert();
- }
- }
-
switch (conn->type) {
case CONN_TYPE_DIR:
- dir_conn = TO_DIR_CONN(conn);
- if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) {
- /* It's a directory connection and connecting or fetching
- * failed: forget about this router, and maybe try again. */
- connection_dir_request_failed(dir_conn);
- }
- /* If we were trying to fetch a v2 rend desc and did not succeed,
- * retry as needed. (If a fetch is successful, the connection state
- * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC to mark that
- * refetching is unnecessary.) */
- if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
- dir_conn->rend_data &&
- strlen(dir_conn->rend_data->onion_address) ==
- REND_SERVICE_ID_LEN_BASE32)
- rend_client_refetch_v2_renddesc(dir_conn->rend_data);
+ connection_dir_about_to_close(TO_DIR_CONN(conn));
break;
case CONN_TYPE_OR:
- or_conn = TO_OR_CONN(conn);
- /* Remember why we're closing this connection. */
- if (conn->state != OR_CONN_STATE_OPEN) {
- /* Inform any pending (not attached) circs that they should
- * give up. */
- circuit_n_conn_done(TO_OR_CONN(conn), 0);
- /* now mark things down as needed */
- if (connection_or_nonopen_was_started_here(or_conn)) {
- or_options_t *options = get_options();
- rep_hist_note_connect_failed(or_conn->identity_digest, now);
- entry_guard_register_connect_status(or_conn->identity_digest,0,
- !options->HTTPSProxy, now);
- if (conn->state >= OR_CONN_STATE_TLS_HANDSHAKING) {
- int reason = tls_error_to_orconn_end_reason(or_conn->tls_error);
- control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
- reason);
- if (!authdir_mode_tests_reachability(options))
- control_event_bootstrap_problem(
- orconn_end_reason_to_control_string(reason), reason);
- }
- }
- } else if (conn->hold_open_until_flushed) {
- /* We only set hold_open_until_flushed when we're intentionally
- * closing a connection. */
- rep_hist_note_disconnect(or_conn->identity_digest, now);
- control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
- tls_error_to_orconn_end_reason(or_conn->tls_error));
- } else if (!tor_digest_is_zero(or_conn->identity_digest)) {
- rep_hist_note_connection_died(or_conn->identity_digest, now);
- control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
- tls_error_to_orconn_end_reason(or_conn->tls_error));
- }
- /* Now close all the attached circuits on it. */
- circuit_unlink_all_from_or_conn(TO_OR_CONN(conn),
- END_CIRC_REASON_OR_CONN_CLOSED);
+ connection_or_about_to_close(TO_OR_CONN(conn));
break;
case CONN_TYPE_AP:
- edge_conn = TO_EDGE_CONN(conn);
- if (edge_conn->socks_request->has_finished == 0) {
- /* since conn gets removed right after this function finishes,
- * there's no point trying to send back a reply at this point. */
- log_warn(LD_BUG,"Closing stream (marked at %s:%d) without sending"
- " back a socks reply.",
- conn->marked_for_close_file, conn->marked_for_close);
- }
- if (!edge_conn->end_reason) {
- log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having"
- " set end_reason.",
- conn->marked_for_close_file, conn->marked_for_close);
- }
- if (edge_conn->dns_server_request) {
- log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having"
- " replied to DNS request.",
- conn->marked_for_close_file, conn->marked_for_close);
- dnsserv_reject_request(edge_conn);
- }
- control_event_stream_bandwidth(edge_conn);
- control_event_stream_status(edge_conn, STREAM_EVENT_CLOSED,
- edge_conn->end_reason);
- circ = circuit_get_by_edge_conn(edge_conn);
- if (circ)
- circuit_detach_stream(circ, edge_conn);
+ connection_ap_about_to_close(TO_ENTRY_CONN(conn));
break;
case CONN_TYPE_EXIT:
- edge_conn = TO_EDGE_CONN(conn);
- circ = circuit_get_by_edge_conn(edge_conn);
- if (circ)
- circuit_detach_stream(circ, edge_conn);
- if (conn->state == EXIT_CONN_STATE_RESOLVING) {
- connection_dns_remove(edge_conn);
- }
+ connection_exit_about_to_close(TO_EDGE_CONN(conn));
break;
}
}
@@ -674,10 +651,9 @@ connection_close_immediate(connection_t *conn)
conn->s = -1;
if (conn->linked)
conn->linked_conn_is_closed = 1;
- if (!connection_is_listener(conn)) {
+ if (conn->outbuf)
buf_clear(conn->outbuf);
- conn->outbuf_flushlen = 0;
- }
+ conn->outbuf_flushlen = 0;
}
/** Mark <b>conn</b> to be closed next time we loop through
@@ -747,48 +723,6 @@ connection_expire_held_open(void)
});
}
-/** Create an AF_INET listenaddr struct.
- * <b>listenaddress</b> provides the host and optionally the port information
- * for the new structure. If no port is provided in <b>listenaddress</b> then
- * <b>listenport</b> is used.
- *
- * If not NULL <b>readable_address</b> will contain a copy of the host part of
- * <b>listenaddress</b>.
- *
- * The listenaddr struct has to be freed by the caller.
- */
-static struct sockaddr_in *
-create_inet_sockaddr(const char *listenaddress, int listenport,
- char **readable_address, socklen_t *socklen_out) {
- struct sockaddr_in *listenaddr = NULL;
- uint32_t addr;
- uint16_t usePort = 0;
-
- if (parse_addr_port(LOG_WARN,
- listenaddress, readable_address, &addr, &usePort)<0) {
- log_warn(LD_CONFIG,
- "Error parsing/resolving ListenAddress %s", listenaddress);
- goto err;
- }
- if (usePort==0) {
- if (listenport != CFG_AUTO_PORT)
- usePort = listenport;
- }
-
- listenaddr = tor_malloc_zero(sizeof(struct sockaddr_in));
- listenaddr->sin_addr.s_addr = htonl(addr);
- listenaddr->sin_family = AF_INET;
- listenaddr->sin_port = htons((uint16_t) usePort);
-
- *socklen_out = sizeof(struct sockaddr_in);
-
- return listenaddr;
-
- err:
- tor_free(listenaddr);
- return NULL;
-}
-
#ifdef HAVE_SYS_UN_H
/** Create an AF_UNIX listenaddr struct.
* <b>listenaddress</b> provides the path to the Unix socket.
@@ -862,7 +796,7 @@ warn_too_many_conns(void)
/** Check whether we should be willing to open an AF_UNIX socket in
* <b>path</b>. Return 0 if we should go ahead and -1 if we shouldn't. */
static int
-check_location_for_unix_socket(or_options_t *options, const char *path)
+check_location_for_unix_socket(const or_options_t *options, const char *path)
{
int r = -1;
char *p = tor_strdup(path);
@@ -923,12 +857,20 @@ make_socket_reuseable(tor_socket_t sock)
static connection_t *
connection_create_listener(const struct sockaddr *listensockaddr,
socklen_t socklen,
- int type, char* address)
+ int type, const char *address,
+ const port_cfg_t *port_cfg)
{
+ listener_connection_t *lis_conn;
connection_t *conn;
tor_socket_t s; /* the socket we're going to make */
+ or_options_t const *options = get_options();
+#if defined(HAVE_PWD_H) && defined(HAVE_SYS_UN_H)
+ struct passwd *pw = NULL;
+#endif
uint16_t usePort = 0, gotPort = 0;
int start_reading = 0;
+ static int global_next_session_group = SESSION_GROUP_FIRST_AUTO;
+ tor_addr_t addr;
if (get_n_open_sockets() >= get_options()->_ConnLimit-1) {
warn_too_many_conns();
@@ -936,7 +878,6 @@ connection_create_listener(const struct sockaddr *listensockaddr,
}
if (listensockaddr->sa_family == AF_INET) {
- tor_addr_t addr;
int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER);
if (is_tcp)
start_reading = 1;
@@ -950,7 +891,8 @@ connection_create_listener(const struct sockaddr *listensockaddr,
is_tcp ? SOCK_STREAM : SOCK_DGRAM,
is_tcp ? IPPROTO_TCP: IPPROTO_UDP);
if (!SOCKET_OK(s)) {
- log_warn(LD_NET,"Socket creation failed.");
+ log_warn(LD_NET,"Socket creation failed: %s",
+ tor_socket_strerror(tor_socket_errno(-1)));
goto err;
}
@@ -998,12 +940,14 @@ connection_create_listener(const struct sockaddr *listensockaddr,
* and listeners at the same time */
tor_assert(type == CONN_TYPE_CONTROL_LISTENER);
- if (check_location_for_unix_socket(get_options(), address) < 0)
+ if (check_location_for_unix_socket(options, address) < 0)
goto err;
log_notice(LD_NET, "Opening %s on %s",
conn_type_to_string(type), address);
+ tor_addr_make_unspec(&addr);
+
if (unlink(address) < 0 && errno != ENOENT) {
log_warn(LD_NET, "Could not unlink %s: %s", address,
strerror(errno));
@@ -1020,7 +964,20 @@ connection_create_listener(const struct sockaddr *listensockaddr,
tor_socket_strerror(tor_socket_errno(s)));
goto err;
}
- if (get_options()->ControlSocketsGroupWritable) {
+#ifdef HAVE_PWD_H
+ if (options->User) {
+ pw = getpwnam(options->User);
+ if (pw == NULL) {
+ log_warn(LD_NET,"Unable to chown() %s socket: user %s not found.",
+ address, options->User);
+ } else if (chown(address, pw->pw_uid, pw->pw_gid) < 0) {
+ log_warn(LD_NET,"Unable to chown() %s socket: %s.",
+ address, strerror(errno));
+ goto err;
+ }
+ }
+#endif
+ if (options->ControlSocketsGroupWritable) {
/* We need to use chmod; fchmod doesn't work on sockets on all
* platforms. */
if (chmod(address, 0660) < 0) {
@@ -1045,11 +1002,23 @@ connection_create_listener(const struct sockaddr *listensockaddr,
set_socket_nonblocking(s);
- conn = connection_new(type, listensockaddr->sa_family);
+ lis_conn = listener_connection_new(type, listensockaddr->sa_family);
+ conn = TO_CONN(lis_conn);
conn->socket_family = listensockaddr->sa_family;
conn->s = s;
conn->address = tor_strdup(address);
conn->port = gotPort;
+ tor_addr_copy(&conn->addr, &addr);
+
+ if (port_cfg->isolation_flags) {
+ lis_conn->isolation_flags = port_cfg->isolation_flags;
+ if (port_cfg->session_group >= 0) {
+ lis_conn->session_group = port_cfg->session_group;
+ } else {
+ /* XXXX023 This can wrap after ~INT_MAX ports are opened. */
+ lis_conn->session_group = global_next_session_group--;
+ }
+ }
if (connection_add(conn) < 0) { /* no space, forget it */
log_warn(LD_NET,"connection_add for listener failed. Giving up.");
@@ -1146,7 +1115,7 @@ connection_handle_listener_read(connection_t *conn, int new_type)
struct sockaddr *remote = (struct sockaddr*)addrbuf;
/* length of the remote address. Must be whatever accept() needs. */
socklen_t remotelen = (socklen_t)sizeof(addrbuf);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert((size_t)remotelen >= sizeof(struct sockaddr_in));
memset(addrbuf, 0, sizeof(addrbuf));
@@ -1260,7 +1229,7 @@ connection_handle_listener_read(connection_t *conn, int new_type)
return 0; /* no need to tear down the parent */
}
- if (connection_init_accepted_conn(newconn, conn->type) < 0) {
+ if (connection_init_accepted_conn(newconn, TO_LISTENER_CONN(conn)) < 0) {
if (! newconn->marked_for_close)
connection_mark_for_close(newconn);
return 0;
@@ -1274,7 +1243,8 @@ connection_handle_listener_read(connection_t *conn, int new_type)
* and place it in circuit_wait.
*/
static int
-connection_init_accepted_conn(connection_t *conn, uint8_t listener_type)
+connection_init_accepted_conn(connection_t *conn,
+ const listener_connection_t *listener)
{
connection_start_reading(conn);
@@ -1283,16 +1253,20 @@ connection_init_accepted_conn(connection_t *conn, uint8_t listener_type)
control_event_or_conn_status(TO_OR_CONN(conn), OR_CONN_EVENT_NEW, 0);
return connection_tls_start_handshake(TO_OR_CONN(conn), 1);
case CONN_TYPE_AP:
- switch (listener_type) {
+ TO_ENTRY_CONN(conn)->isolation_flags = listener->isolation_flags;
+ TO_ENTRY_CONN(conn)->session_group = listener->session_group;
+ TO_ENTRY_CONN(conn)->nym_epoch = get_signewnym_epoch();
+ TO_ENTRY_CONN(conn)->socks_request->listener_type = listener->_base.type;
+ switch (TO_CONN(listener)->type) {
case CONN_TYPE_AP_LISTENER:
conn->state = AP_CONN_STATE_SOCKS_WAIT;
break;
case CONN_TYPE_AP_TRANS_LISTENER:
- TO_EDGE_CONN(conn)->is_transparent_ap = 1;
+ TO_ENTRY_CONN(conn)->is_transparent_ap = 1;
conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
- return connection_ap_process_transparent(TO_EDGE_CONN(conn));
+ return connection_ap_process_transparent(TO_ENTRY_CONN(conn));
case CONN_TYPE_AP_NATD_LISTENER:
- TO_EDGE_CONN(conn)->is_transparent_ap = 1;
+ TO_ENTRY_CONN(conn)->is_transparent_ap = 1;
conn->state = AP_CONN_STATE_NATD_WAIT;
break;
}
@@ -1325,8 +1299,8 @@ connection_connect(connection_t *conn, const char *address,
int inprogress = 0;
char addrbuf[256];
struct sockaddr *dest_addr;
- socklen_t dest_addr_len;
- or_options_t *options = get_options();
+ int dest_addr_len;
+ const or_options_t *options = get_options();
int protocol_family;
if (get_n_open_sockets() >= get_options()->_ConnLimit-1) {
@@ -1383,7 +1357,7 @@ connection_connect(connection_t *conn, const char *address,
make_socket_reuseable(s);
- if (connect(s, dest_addr, dest_addr_len) < 0) {
+ if (connect(s, dest_addr, (socklen_t)dest_addr_len) < 0) {
int e = tor_socket_errno(s);
if (!ERRNO_IS_CONN_EINPROGRESS(e)) {
/* yuck. kill it. */
@@ -1408,7 +1382,7 @@ connection_connect(connection_t *conn, const char *address,
escaped_safe_str_client(address),
port, inprogress?"in progress":"established", s);
conn->s = s;
- if (connection_add(conn) < 0) /* no space, forget it */
+ if (connection_add_connecting(conn) < 0) /* no space, forget it */
return -1;
return inprogress ? 0 : 1;
}
@@ -1421,6 +1395,7 @@ connection_proxy_state_to_string(int state)
static const char *unknown = "???";
static const char *states[] = {
"PROXY_NONE",
+ "PROXY_INFANT",
"PROXY_HTTPS_WANT_CONNECT_OK",
"PROXY_SOCKS4_WANT_CONNECT_OK",
"PROXY_SOCKS5_WANT_AUTH_METHOD_NONE",
@@ -1449,7 +1424,7 @@ connection_proxy_state_to_string(int state)
int
connection_proxy_connect(connection_t *conn, int type)
{
- or_options_t *options;
+ const or_options_t *options;
tor_assert(conn);
@@ -1641,6 +1616,19 @@ connection_send_socks5_connect(connection_t *conn)
conn->proxy_state = PROXY_SOCKS5_WANT_CONNECT_OK;
}
+/** DOCDOC */
+static int
+connection_fetch_from_buf_socks_client(connection_t *conn,
+ int state, char **reason)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ return fetch_from_evbuffer_socks_client(input, state, reason);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return fetch_from_buf_socks_client(conn->inbuf, state, reason);
+ }
+}
+
/** Call this from connection_*_process_inbuf() to advance the proxy
* handshake.
*
@@ -1668,17 +1656,17 @@ connection_read_proxy_handshake(connection_t *conn)
break;
case PROXY_SOCKS4_WANT_CONNECT_OK:
- ret = fetch_from_buf_socks_client(conn->inbuf,
- conn->proxy_state,
- &reason);
+ ret = connection_fetch_from_buf_socks_client(conn,
+ conn->proxy_state,
+ &reason);
if (ret == 1)
conn->proxy_state = PROXY_CONNECTED;
break;
case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE:
- ret = fetch_from_buf_socks_client(conn->inbuf,
- conn->proxy_state,
- &reason);
+ ret = connection_fetch_from_buf_socks_client(conn,
+ conn->proxy_state,
+ &reason);
/* no auth needed, do connect */
if (ret == 1) {
connection_send_socks5_connect(conn);
@@ -1687,9 +1675,9 @@ connection_read_proxy_handshake(connection_t *conn)
break;
case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929:
- ret = fetch_from_buf_socks_client(conn->inbuf,
- conn->proxy_state,
- &reason);
+ ret = connection_fetch_from_buf_socks_client(conn,
+ conn->proxy_state,
+ &reason);
/* send auth if needed, otherwise do connect */
if (ret == 1) {
@@ -1724,9 +1712,9 @@ connection_read_proxy_handshake(connection_t *conn)
break;
case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK:
- ret = fetch_from_buf_socks_client(conn->inbuf,
- conn->proxy_state,
- &reason);
+ ret = connection_fetch_from_buf_socks_client(conn,
+ conn->proxy_state,
+ &reason);
/* send the connect request */
if (ret == 1) {
connection_send_socks5_connect(conn);
@@ -1735,9 +1723,9 @@ connection_read_proxy_handshake(connection_t *conn)
break;
case PROXY_SOCKS5_WANT_CONNECT_OK:
- ret = fetch_from_buf_socks_client(conn->inbuf,
- conn->proxy_state,
- &reason);
+ ret = connection_fetch_from_buf_socks_client(conn,
+ conn->proxy_state,
+ &reason);
if (ret == 1)
conn->proxy_state = PROXY_CONNECTED;
break;
@@ -1770,6 +1758,113 @@ connection_read_proxy_handshake(connection_t *conn)
return ret;
}
+/** Given a list of listener connections in <b>old_conns</b>, and list of
+ * port_cfg_t entries in <b>ports</b>, open a new listener for every port in
+ * <b>ports</b> that does not already have a listener in <b>old_conns</b>.
+ *
+ * Remove from <b>old_conns</b> every connection that has a corresponding
+ * entry in <b>ports</b>. Add to <b>new_conns</b> new every connection we
+ * launch.
+ *
+ * Return 0 on success, -1 on failure.
+ **/
+static int
+retry_listener_ports(smartlist_t *old_conns,
+ const smartlist_t *ports,
+ smartlist_t *new_conns)
+{
+ smartlist_t *launch = smartlist_create();
+ int r = 0;
+
+ smartlist_add_all(launch, ports);
+
+ /* Iterate through old_conns, comparing it to launch: remove from both lists
+ * each pair of elements that corresponds to the same port. */
+ SMARTLIST_FOREACH_BEGIN(old_conns, connection_t *, conn) {
+ const port_cfg_t *found_port = NULL;
+
+ /* Okay, so this is a listener. Is it configured? */
+ SMARTLIST_FOREACH_BEGIN(launch, const port_cfg_t *, wanted) {
+ if (conn->type != wanted->type)
+ continue;
+ if ((conn->socket_family != AF_UNIX && wanted->is_unix_addr) ||
+ (conn->socket_family == AF_UNIX && ! wanted->is_unix_addr))
+ continue;
+
+ if (wanted->is_unix_addr) {
+ if (conn->socket_family == AF_UNIX &&
+ !strcmp(wanted->unix_addr, conn->address)) {
+ found_port = wanted;
+ break;
+ }
+ } else {
+ int port_matches;
+ if (wanted->port == CFG_AUTO_PORT) {
+ port_matches = 1;
+ } else {
+ port_matches = (wanted->port == conn->port);
+ }
+ if (port_matches && tor_addr_eq(&wanted->addr, &conn->addr)) {
+ found_port = wanted;
+ break;
+ }
+ }
+ } SMARTLIST_FOREACH_END(wanted);
+
+ if (found_port) {
+ /* This listener is already running; we don't need to launch it. */
+ //log_debug(LD_NET, "Already have %s on %s:%d",
+ // conn_type_to_string(found_port->type), conn->address, conn->port);
+ smartlist_remove(launch, found_port);
+ /* And we can remove the connection from old_conns too. */
+ SMARTLIST_DEL_CURRENT(old_conns, conn);
+ }
+ } SMARTLIST_FOREACH_END(conn);
+
+ /* Now open all the listeners that are configured but not opened. */
+ SMARTLIST_FOREACH_BEGIN(launch, const port_cfg_t *, port) {
+ struct sockaddr *listensockaddr;
+ socklen_t listensocklen = 0;
+ char *address=NULL;
+ connection_t *conn;
+ int real_port = port->port == CFG_AUTO_PORT ? 0 : port->port;
+ tor_assert(real_port <= UINT16_MAX);
+
+ if (port->is_unix_addr) {
+ listensockaddr = (struct sockaddr *)
+ create_unix_sockaddr(port->unix_addr,
+ &address, &listensocklen);
+ } else {
+ listensockaddr = tor_malloc(sizeof(struct sockaddr_storage));
+ listensocklen = tor_addr_to_sockaddr(&port->addr,
+ real_port,
+ listensockaddr,
+ sizeof(struct sockaddr_storage));
+ address = tor_dup_addr(&port->addr);
+ }
+
+ if (listensockaddr) {
+ conn = connection_create_listener(listensockaddr, listensocklen,
+ port->type, address, port);
+ tor_free(listensockaddr);
+ tor_free(address);
+ } else {
+ conn = NULL;
+ }
+
+ if (!conn) {
+ r = -1;
+ } else {
+ if (new_conns)
+ smartlist_add(new_conns, conn);
+ }
+ } SMARTLIST_FOREACH_END(port);
+
+ smartlist_free(launch);
+
+ return r;
+}
+
/**
* Launch any configured listener connections of type <b>type</b>. (A
* listener is configured if <b>port_option</b> is non-zero. If any
@@ -1777,168 +1872,73 @@ connection_read_proxy_handshake(connection_t *conn)
* connection binding to each one. Otherwise, create a single
* connection binding to the address <b>default_addr</b>.)
*
- * Only launch the listeners of this type that are not already open, and
- * only close listeners that are no longer wanted. Existing listeners
- * that are still configured are not touched.
+ * We assume that we're starting with a list of existing listener connection_t
+ * pointers in <b>old_conns</b>: we do not launch listeners that are already
+ * in that list. Instead, we just remove them from the list.
*
- * If <b>disable_all_conns</b> is set, then never open new conns, and
- * close the existing ones.
- *
- * Add all old conns that should be closed to <b>replaced_conns</b>.
- * Add all new connections to <b>new_conns</b>.
+ * All new connections we launch are added to <b>new_conns</b>.
*/
static int
-retry_listeners(int type, config_line_t *cfg,
+retry_listeners(smartlist_t *old_conns,
+ int type, const config_line_t *cfg,
int port_option, const char *default_addr,
- smartlist_t *replaced_conns,
smartlist_t *new_conns,
- int disable_all_conns,
- int socket_family)
+ int is_sockaddr_un)
{
- smartlist_t *launch = smartlist_create(), *conns;
- int free_launch_elts = 1;
- int r;
- config_line_t *c;
- connection_t *conn;
- config_line_t *line;
-
- tor_assert(socket_family == AF_INET || socket_family == AF_UNIX);
+ smartlist_t *ports = smartlist_create();
+ tor_addr_t dflt_addr;
+ int retval = 0;
- if (cfg && port_option) {
- for (c = cfg; c; c = c->next) {
- smartlist_add(launch, c);
- }
- free_launch_elts = 0;
- } else if (port_option) {
- line = tor_malloc_zero(sizeof(config_line_t));
- line->key = tor_strdup("");
- line->value = tor_strdup(default_addr);
- smartlist_add(launch, line);
+ if (default_addr) {
+ tor_addr_from_str(&dflt_addr, default_addr);
+ } else {
+ tor_addr_make_unspec(&dflt_addr);
}
- /*
- SMARTLIST_FOREACH(launch, config_line_t *, l,
- log_fn(LOG_NOTICE, "#%s#%s", l->key, l->value));
- */
-
- conns = get_connection_array();
- SMARTLIST_FOREACH(conns, connection_t *, conn,
- {
- if (conn->type != type ||
- conn->socket_family != socket_family ||
- conn->marked_for_close)
- continue;
- /* Okay, so this is a listener. Is it configured? */
- line = NULL;
- SMARTLIST_FOREACH(launch, config_line_t *, wanted,
- {
- char *address=NULL;
- uint16_t port;
- switch (socket_family) {
- case AF_INET:
- if (!parse_addr_port(LOG_WARN,
- wanted->value, &address, NULL, &port)) {
- int addr_matches = !strcasecmp(address, conn->address);
- int port_matches;
- tor_free(address);
- if (port) {
- /* The Listener line has a port */
- port_matches = (port == conn->port);
- } else if (port_option == CFG_AUTO_PORT) {
- /* The Listener line has no port, and the Port line is "auto".
- * "auto" matches anything; transitions from any port to
- * "auto" succeed. */
- port_matches = 1;
- } else {
- /* The Listener line has no port, and the Port line is "auto".
- * "auto" matches anything; transitions from any port to
- * "auto" succeed. */
- port_matches = (port_option == conn->port);
- }
- if (port_matches && addr_matches) {
- line = wanted;
- break;
- }
- }
- break;
- case AF_UNIX:
- if (!strcasecmp(wanted->value, conn->address)) {
- line = wanted;
- break;
- }
- break;
- default:
- tor_assert(0);
- }
- });
- if (!line || disable_all_conns) {
- /* This one isn't configured. Close it. */
- log_notice(LD_NET, "Closing no-longer-configured %s on %s:%d",
- conn_type_to_string(type), conn->address, conn->port);
- if (replaced_conns) {
- smartlist_add(replaced_conns, conn);
- } else {
- connection_close_immediate(conn);
- connection_mark_for_close(conn);
- }
+ if (port_option) {
+ if (!cfg) {
+ port_cfg_t *port = tor_malloc_zero(sizeof(port_cfg_t));
+ tor_addr_copy(&port->addr, &dflt_addr);
+ port->port = port_option;
+ port->type = type;
+ smartlist_add(ports, port);
} else {
- /* It's configured; we don't need to launch it. */
-// log_debug(LD_NET, "Already have %s on %s:%d",
-// conn_type_to_string(type), conn->address, conn->port);
- smartlist_remove(launch, line);
- if (free_launch_elts)
- config_free_lines(line);
- }
- });
-
- /* Now open all the listeners that are configured but not opened. */
- r = 0;
- if (!disable_all_conns) {
- SMARTLIST_FOREACH_BEGIN(launch, config_line_t *, cfg_line) {
- char *address = NULL;
- struct sockaddr *listensockaddr;
- socklen_t listensocklen = 0;
-
- switch (socket_family) {
- case AF_INET:
- listensockaddr = (struct sockaddr *)
- create_inet_sockaddr(cfg_line->value,
- port_option,
- &address, &listensocklen);
- break;
- case AF_UNIX:
- listensockaddr = (struct sockaddr *)
- create_unix_sockaddr(cfg_line->value,
- &address, &listensocklen);
- break;
- default:
- tor_assert(0);
- }
-
- if (listensockaddr) {
- conn = connection_create_listener(listensockaddr, listensocklen,
- type, address);
- tor_free(listensockaddr);
- tor_free(address);
- } else
- conn = NULL;
-
- if (!conn) {
- r = -1;
+ const config_line_t *c;
+ for (c = cfg; c; c = c->next) {
+ port_cfg_t *port;
+ tor_addr_t addr;
+ uint16_t portval = 0;
+ if (is_sockaddr_un) {
+ size_t len = strlen(c->value);
+ port = tor_malloc_zero(sizeof(port_cfg_t) + len + 1);
+ port->is_unix_addr = 1;
+ memcpy(port->unix_addr, c->value, len+1);
} else {
- if (new_conns)
- smartlist_add(new_conns, conn);
+ if (tor_addr_port_parse(c->value, &addr, &portval) < 0) {
+ log_warn(LD_CONFIG, "Can't parse/resolve %s %s",
+ c->key, c->value);
+ retval = -1;
+ continue;
+ }
+ port = tor_malloc_zero(sizeof(port_cfg_t));
+ tor_addr_copy(&port->addr, &addr);
}
- } SMARTLIST_FOREACH_END(cfg_line);
+ port->type = type;
+ port->port = portval ? portval : port_option;
+ smartlist_add(ports, port);
+ }
+ }
}
- if (free_launch_elts) {
- SMARTLIST_FOREACH(launch, config_line_t *, cfg_line,
- config_free_lines(cfg_line));
- }
- smartlist_free(launch);
+ if (retval == -1)
+ goto cleanup;
- return r;
+ retval = retry_listener_ports(old_conns, ports, new_conns);
+
+ cleanup:
+ SMARTLIST_FOREACH(ports, port_cfg_t *, p, tor_free(p));
+ smartlist_free(ports);
+ return retval;
}
/** Launch listeners for each port you should have open. Only launch
@@ -1952,54 +1952,62 @@ int
retry_all_listeners(smartlist_t *replaced_conns,
smartlist_t *new_conns)
{
- or_options_t *options = get_options();
+ smartlist_t *listeners = smartlist_create();
+ const or_options_t *options = get_options();
int retval = 0;
const uint16_t old_or_port = router_get_advertised_or_port(options);
const uint16_t old_dir_port = router_get_advertised_dir_port(options, 0);
- if (retry_listeners(CONN_TYPE_OR_LISTENER, options->ORListenAddress,
- options->ORPort, "0.0.0.0",
- replaced_conns, new_conns, options->ClientOnly,
- AF_INET)<0)
- retval = -1;
- if (retry_listeners(CONN_TYPE_DIR_LISTENER, options->DirListenAddress,
- options->DirPort, "0.0.0.0",
- replaced_conns, new_conns, options->ClientOnly,
- AF_INET)<0)
- retval = -1;
- if (retry_listeners(CONN_TYPE_AP_LISTENER, options->SocksListenAddress,
- options->SocksPort, "127.0.0.1",
- replaced_conns, new_conns, 0,
- AF_INET)<0)
- retval = -1;
- if (retry_listeners(CONN_TYPE_AP_TRANS_LISTENER, options->TransListenAddress,
- options->TransPort, "127.0.0.1",
- replaced_conns, new_conns, 0,
- AF_INET)<0)
- retval = -1;
- if (retry_listeners(CONN_TYPE_AP_NATD_LISTENER, options->NATDListenAddress,
- options->NATDPort, "127.0.0.1",
- replaced_conns, new_conns, 0,
- AF_INET)<0)
- retval = -1;
- if (retry_listeners(CONN_TYPE_AP_DNS_LISTENER, options->DNSListenAddress,
- options->DNSPort, "127.0.0.1",
- replaced_conns, new_conns, 0,
- AF_INET)<0)
+ SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) {
+ if (connection_is_listener(conn) && !conn->marked_for_close)
+ smartlist_add(listeners, conn);
+ } SMARTLIST_FOREACH_END(conn);
+
+ if (! options->ClientOnly) {
+ if (retry_listeners(listeners,
+ CONN_TYPE_OR_LISTENER, options->ORListenAddress,
+ options->ORPort, "0.0.0.0",
+ new_conns, 0) < 0)
+ retval = -1;
+ if (retry_listeners(listeners,
+ CONN_TYPE_DIR_LISTENER, options->DirListenAddress,
+ options->DirPort, "0.0.0.0",
+ new_conns, 0) < 0)
+ retval = -1;
+ }
+
+ if (retry_listener_ports(listeners,
+ get_configured_client_ports(),
+ new_conns) < 0)
retval = -1;
- if (retry_listeners(CONN_TYPE_CONTROL_LISTENER,
+ if (retry_listeners(listeners,
+ CONN_TYPE_CONTROL_LISTENER,
options->ControlListenAddress,
options->ControlPort, "127.0.0.1",
- replaced_conns, new_conns, 0,
- AF_INET)<0)
+ new_conns, 0) < 0)
return -1;
- if (retry_listeners(CONN_TYPE_CONTROL_LISTENER,
+ if (retry_listeners(listeners,
+ CONN_TYPE_CONTROL_LISTENER,
options->ControlSocket,
options->ControlSocket ? 1 : 0, NULL,
- replaced_conns, new_conns, 0,
- AF_UNIX)<0)
+ new_conns, 1) < 0)
return -1;
+ /* Any members that were still in 'listeners' don't correspond to
+ * any configured port. Kill 'em. */
+ SMARTLIST_FOREACH_BEGIN(listeners, connection_t *, conn) {
+ log_notice(LD_NET, "Closing no-longer-configured %s on %s:%d",
+ conn_type_to_string(conn->type), conn->address, conn->port);
+ if (replaced_conns) {
+ smartlist_add(replaced_conns, conn);
+ } else {
+ connection_close_immediate(conn);
+ connection_mark_for_close(conn);
+ }
+ } SMARTLIST_FOREACH_END(conn);
+
+ smartlist_free(listeners);
+
if (old_or_port != router_get_advertised_or_port(options) ||
old_dir_port != router_get_advertised_dir_port(options, 0)) {
/* Our chosen ORPort or DirPort is not what it used to be: the
@@ -2012,20 +2020,29 @@ retry_all_listeners(smartlist_t *replaced_conns,
return retval;
}
-/** Return 1 if we should apply rate limiting to <b>conn</b>,
- * and 0 otherwise. Right now this just checks if it's an internal
- * IP address or an internal connection. */
+/** Return 1 if we should apply rate limiting to <b>conn</b>, and 0
+ * otherwise.
+ * Right now this just checks if it's an internal IP address or an
+ * internal connection. We also check if the connection uses pluggable
+ * transports, since we should then limit it even if it comes from an
+ * internal IP address. */
static int
connection_is_rate_limited(connection_t *conn)
{
- if (conn->linked || /* internal connection */
- tor_addr_family(&conn->addr) == AF_UNSPEC || /* no address */
- tor_addr_is_internal(&conn->addr, 0)) /* internal address */
- return 0;
+ const or_options_t *options = get_options();
+ if (conn->linked)
+ return 0; /* Internal connection */
+ else if (! options->CountPrivateBandwidth &&
+ (tor_addr_family(&conn->addr) == AF_UNSPEC || /* no address */
+ tor_addr_is_internal(&conn->addr, 0)))
+ return 0; /* Internal address */
else
return 1;
}
+#ifdef USE_BUFFEREVENTS
+static struct bufferevent_rate_limit_group *global_rate_limit = NULL;
+#else
extern int global_read_bucket, global_write_bucket;
extern int global_relayed_read_bucket, global_relayed_write_bucket;
@@ -2033,11 +2050,13 @@ extern int global_relayed_read_bucket, global_relayed_write_bucket;
* we are likely to run dry again this second, so be stingy with the
* tokens we just put in. */
static int write_buckets_empty_last_second = 0;
+#endif
/** How many seconds of no active local circuits will make the
* connection revert to the "relayed" bandwidth class? */
#define CLIENT_IDLE_TIME_FOR_PRIORITY 30
+#ifndef USE_BUFFEREVENTS
/** Return 1 if <b>conn</b> should use tokens from the "relayed"
* bandwidth rates, else 0. Currently, only OR conns with bandwidth
* class 1, and directory conns that are serving data out, count.
@@ -2148,6 +2167,20 @@ connection_bucket_write_limit(connection_t *conn, time_t now)
return connection_bucket_round_robin(base, priority,
global_bucket, conn_bucket);
}
+#else
+static ssize_t
+connection_bucket_read_limit(connection_t *conn, time_t now)
+{
+ (void) now;
+ return bufferevent_get_max_to_read(conn->bufev);
+}
+ssize_t
+connection_bucket_write_limit(connection_t *conn, time_t now)
+{
+ (void) now;
+ return bufferevent_get_max_to_write(conn->bufev);
+}
+#endif
/** Return 1 if the global write buckets are low enough that we
* shouldn't send <b>attempt</b> bytes of low-priority directory stuff
@@ -2172,8 +2205,12 @@ connection_bucket_write_limit(connection_t *conn, time_t now)
int
global_write_bucket_low(connection_t *conn, size_t attempt, int priority)
{
+#ifdef USE_BUFFEREVENTS
+ ssize_t smaller_bucket = bufferevent_get_max_to_write(conn->bufev);
+#else
int smaller_bucket = global_write_bucket < global_relayed_write_bucket ?
global_write_bucket : global_relayed_write_bucket;
+#endif
if (authdir_mode(get_options()) && priority>1)
return 0; /* there's always room to answer v2 if we're an auth dir */
@@ -2183,12 +2220,14 @@ global_write_bucket_low(connection_t *conn, size_t attempt, int priority)
if (smaller_bucket < (int)attempt)
return 1; /* not enough space no matter the priority */
+#ifndef USE_BUFFEREVENTS
if (write_buckets_empty_last_second)
return 1; /* we're already hitting our limits, no more please */
+#endif
if (priority == 1) { /* old-style v1 query */
/* Could we handle *two* of these requests within the next two seconds? */
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int64_t can_write = (int64_t)smaller_bucket
+ 2*(options->RelayBandwidthRate ? options->RelayBandwidthRate :
options->BandwidthRate);
@@ -2200,23 +2239,11 @@ global_write_bucket_low(connection_t *conn, size_t attempt, int priority)
return 0;
}
-/** We just read <b>num_read</b> and wrote <b>num_written</b> bytes
- * onto <b>conn</b>. Decrement buckets appropriately. */
+/** DOCDOC */
static void
-connection_buckets_decrement(connection_t *conn, time_t now,
- size_t num_read, size_t num_written)
+record_num_bytes_transferred_impl(connection_t *conn,
+ time_t now, size_t num_read, size_t num_written)
{
- if (num_written >= INT_MAX || num_read >= INT_MAX) {
- log_err(LD_BUG, "Value out of range. num_read=%lu, num_written=%lu, "
- "connection type=%s, state=%s",
- (unsigned long)num_read, (unsigned long)num_written,
- conn_type_to_string(conn->type),
- conn_state_to_string(conn->type, conn->state));
- if (num_written >= INT_MAX) num_written = 1;
- if (num_read >= INT_MAX) num_read = 1;
- tor_fragile_assert();
- }
-
/* Count bytes of answering direct and tunneled directory requests */
if (conn->type == CONN_TYPE_DIR && conn->purpose == DIR_PURPOSE_SERVER) {
if (num_read > 0)
@@ -2227,6 +2254,11 @@ connection_buckets_decrement(connection_t *conn, time_t now,
if (!connection_is_rate_limited(conn))
return; /* local IPs are free */
+
+ if (conn->type == CONN_TYPE_OR)
+ rep_hist_note_or_conn_bytes(conn->global_identifier, num_read,
+ num_written, now);
+
if (num_read > 0) {
rep_hist_note_bytes_read(num_read, now);
}
@@ -2235,6 +2267,52 @@ connection_buckets_decrement(connection_t *conn, time_t now,
}
if (conn->type == CONN_TYPE_EXIT)
rep_hist_note_exit_bytes(conn->port, num_written, num_read);
+}
+
+#ifdef USE_BUFFEREVENTS
+/** DOCDOC */
+static void
+record_num_bytes_transferred(connection_t *conn,
+ time_t now, size_t num_read, size_t num_written)
+{
+ /* XXX023 check if this is necessary */
+ if (num_written >= INT_MAX || num_read >= INT_MAX) {
+ log_err(LD_BUG, "Value out of range. num_read=%lu, num_written=%lu, "
+ "connection type=%s, state=%s",
+ (unsigned long)num_read, (unsigned long)num_written,
+ conn_type_to_string(conn->type),
+ conn_state_to_string(conn->type, conn->state));
+ if (num_written >= INT_MAX) num_written = 1;
+ if (num_read >= INT_MAX) num_read = 1;
+ tor_fragile_assert();
+ }
+
+ record_num_bytes_transferred_impl(conn,now,num_read,num_written);
+}
+#endif
+
+#ifndef USE_BUFFEREVENTS
+/** We just read <b>num_read</b> and wrote <b>num_written</b> bytes
+ * onto <b>conn</b>. Decrement buckets appropriately. */
+static void
+connection_buckets_decrement(connection_t *conn, time_t now,
+ size_t num_read, size_t num_written)
+{
+ if (num_written >= INT_MAX || num_read >= INT_MAX) {
+ log_err(LD_BUG, "Value out of range. num_read=%lu, num_written=%lu, "
+ "connection type=%s, state=%s",
+ (unsigned long)num_read, (unsigned long)num_written,
+ conn_type_to_string(conn->type),
+ conn_state_to_string(conn->type, conn->state));
+ if (num_written >= INT_MAX) num_written = 1;
+ if (num_read >= INT_MAX) num_read = 1;
+ tor_fragile_assert();
+ }
+
+ record_num_bytes_transferred_impl(conn, now, num_read, num_written);
+
+ if (!connection_is_rate_limited(conn))
+ return; /* local IPs are free */
if (connection_counts_as_relayed_traffic(conn, now)) {
global_relayed_read_bucket -= (int)num_read;
@@ -2300,7 +2378,7 @@ connection_consider_empty_write_buckets(connection_t *conn)
void
connection_bucket_init(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* start it at max traffic */
global_read_bucket = (int)options->BandwidthBurst;
global_write_bucket = (int)options->BandwidthBurst;
@@ -2313,22 +2391,23 @@ connection_bucket_init(void)
}
}
-/** Refill a single <b>bucket</b> called <b>name</b> with bandwidth rate
- * <b>rate</b> and bandwidth burst <b>burst</b>, assuming that
- * <b>seconds_elapsed</b> seconds have passed since the last call.
- **/
+/** Refill a single <b>bucket</b> called <b>name</b> with bandwidth rate per
+ * second <b>rate</b> and bandwidth burst <b>burst</b>, assuming that
+ * <b>milliseconds_elapsed</b> milliseconds have passed since the last
+ * call. */
static void
connection_bucket_refill_helper(int *bucket, int rate, int burst,
- int seconds_elapsed, const char *name)
+ int milliseconds_elapsed,
+ const char *name)
{
int starting_bucket = *bucket;
- if (starting_bucket < burst && seconds_elapsed) {
- if (((burst - starting_bucket)/seconds_elapsed) < rate) {
+ if (starting_bucket < burst && milliseconds_elapsed > 0) {
+ int64_t incr = (((int64_t)rate) * milliseconds_elapsed) / 1000;
+ if ((burst - starting_bucket) < incr) {
*bucket = burst; /* We would overflow the bucket; just set it to
* the maximum. */
} else {
- int incr = rate*seconds_elapsed;
- *bucket += incr;
+ *bucket += (int)incr;
if (*bucket > burst || *bucket < starting_bucket) {
/* If we overflow the burst, or underflow our starting bucket,
* cap the bucket value to burst. */
@@ -2341,41 +2420,46 @@ connection_bucket_refill_helper(int *bucket, int rate, int burst,
}
}
-/** A second has rolled over; increment buckets appropriately. */
+/** Time has passed; increment buckets appropriately. */
void
-connection_bucket_refill(int seconds_elapsed, time_t now)
+connection_bucket_refill(int milliseconds_elapsed, time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
smartlist_t *conns = get_connection_array();
- int relayrate, relayburst;
+ int bandwidthrate, bandwidthburst, relayrate, relayburst;
+
+ bandwidthrate = (int)options->BandwidthRate;
+ bandwidthburst = (int)options->BandwidthBurst;
if (options->RelayBandwidthRate) {
relayrate = (int)options->RelayBandwidthRate;
relayburst = (int)options->RelayBandwidthBurst;
} else {
- relayrate = (int)options->BandwidthRate;
- relayburst = (int)options->BandwidthBurst;
+ relayrate = bandwidthrate;
+ relayburst = bandwidthburst;
}
- tor_assert(seconds_elapsed >= 0);
+ tor_assert(milliseconds_elapsed >= 0);
write_buckets_empty_last_second =
global_relayed_write_bucket <= 0 || global_write_bucket <= 0;
/* refill the global buckets */
connection_bucket_refill_helper(&global_read_bucket,
- (int)options->BandwidthRate,
- (int)options->BandwidthBurst,
- seconds_elapsed, "global_read_bucket");
+ bandwidthrate, bandwidthburst,
+ milliseconds_elapsed,
+ "global_read_bucket");
connection_bucket_refill_helper(&global_write_bucket,
- (int)options->BandwidthRate,
- (int)options->BandwidthBurst,
- seconds_elapsed, "global_write_bucket");
+ bandwidthrate, bandwidthburst,
+ milliseconds_elapsed,
+ "global_write_bucket");
connection_bucket_refill_helper(&global_relayed_read_bucket,
- relayrate, relayburst, seconds_elapsed,
+ relayrate, relayburst,
+ milliseconds_elapsed,
"global_relayed_read_bucket");
connection_bucket_refill_helper(&global_relayed_write_bucket,
- relayrate, relayburst, seconds_elapsed,
+ relayrate, relayburst,
+ milliseconds_elapsed,
"global_relayed_write_bucket");
/* refill the per-connection buckets */
@@ -2383,18 +2467,20 @@ connection_bucket_refill(int seconds_elapsed, time_t now)
{
if (connection_speaks_cells(conn)) {
or_connection_t *or_conn = TO_OR_CONN(conn);
+ int orbandwidthrate = or_conn->bandwidthrate;
+ int orbandwidthburst = or_conn->bandwidthburst;
if (connection_bucket_should_increase(or_conn->read_bucket, or_conn)) {
connection_bucket_refill_helper(&or_conn->read_bucket,
- or_conn->bandwidthrate,
- or_conn->bandwidthburst,
- seconds_elapsed,
+ orbandwidthrate,
+ orbandwidthburst,
+ milliseconds_elapsed,
"or_conn->read_bucket");
}
if (connection_bucket_should_increase(or_conn->write_bucket, or_conn)) {
connection_bucket_refill_helper(&or_conn->write_bucket,
- or_conn->bandwidthrate,
- or_conn->bandwidthburst,
- seconds_elapsed,
+ orbandwidthrate,
+ orbandwidthburst,
+ milliseconds_elapsed,
"or_conn->write_bucket");
}
}
@@ -2443,6 +2529,91 @@ connection_bucket_should_increase(int bucket, or_connection_t *conn)
return 1;
}
+#else
+static void
+connection_buckets_decrement(connection_t *conn, time_t now,
+ size_t num_read, size_t num_written)
+{
+ (void) conn;
+ (void) now;
+ (void) num_read;
+ (void) num_written;
+ /* Libevent does this for us. */
+}
+
+void
+connection_bucket_refill(int seconds_elapsed, time_t now)
+{
+ (void) seconds_elapsed;
+ (void) now;
+ /* Libevent does this for us. */
+}
+void
+connection_bucket_init(void)
+{
+ const or_options_t *options = get_options();
+ const struct timeval *tick = tor_libevent_get_one_tick_timeout();
+ struct ev_token_bucket_cfg *bucket_cfg;
+
+ uint64_t rate, burst;
+ if (options->RelayBandwidthRate) {
+ rate = options->RelayBandwidthRate;
+ burst = options->RelayBandwidthBurst;
+ } else {
+ rate = options->BandwidthRate;
+ burst = options->BandwidthBurst;
+ }
+
+ /* This can't overflow, since TokenBucketRefillInterval <= 1000,
+ * and rate started out less than INT32_MAX. */
+ rate = (rate * options->TokenBucketRefillInterval) / 1000;
+
+ bucket_cfg = ev_token_bucket_cfg_new((uint32_t)rate, (uint32_t)burst,
+ (uint32_t)rate, (uint32_t)burst,
+ tick);
+
+ if (!global_rate_limit) {
+ global_rate_limit =
+ bufferevent_rate_limit_group_new(tor_libevent_get_base(), bucket_cfg);
+ } else {
+ bufferevent_rate_limit_group_set_cfg(global_rate_limit, bucket_cfg);
+ }
+ ev_token_bucket_cfg_free(bucket_cfg);
+}
+
+void
+connection_get_rate_limit_totals(uint64_t *read_out, uint64_t *written_out)
+{
+ if (global_rate_limit == NULL) {
+ *read_out = *written_out = 0;
+ } else {
+ bufferevent_rate_limit_group_get_totals(
+ global_rate_limit, read_out, written_out);
+ }
+}
+
+/** DOCDOC */
+void
+connection_enable_rate_limiting(connection_t *conn)
+{
+ if (conn->bufev) {
+ if (!global_rate_limit)
+ connection_bucket_init();
+ tor_add_bufferevent_to_rate_limit_group(conn->bufev, global_rate_limit);
+ }
+}
+
+static void
+connection_consider_empty_write_buckets(connection_t *conn)
+{
+ (void) conn;
+}
+static void
+connection_consider_empty_read_buckets(connection_t *conn)
+{
+ (void) conn;
+}
+#endif
/** Read bytes from conn-\>s and process them.
*
@@ -2501,8 +2672,10 @@ connection_handle_read_impl(connection_t *conn)
if (CONN_IS_EDGE(conn)) {
edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
connection_edge_end_errno(edge_conn);
- if (edge_conn->socks_request) /* broken, don't send a socks reply back */
- edge_conn->socks_request->has_finished = 1;
+ if (conn->type == CONN_TYPE_AP && TO_ENTRY_CONN(conn)->socks_request) {
+ /* broken, don't send a socks reply back */
+ TO_ENTRY_CONN(conn)->socks_request->has_finished = 1;
+ }
}
connection_close_immediate(conn); /* Don't flush; connection is dead. */
connection_mark_for_close(conn);
@@ -2697,7 +2870,7 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read,
}
if (n_read > 0) {
- /* change *max_to_read */
+ /* change *max_to_read */
*max_to_read = at_most - n_read;
/* Update edge_conn->n_read */
@@ -2729,11 +2902,212 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read,
return 0;
}
+#ifdef USE_BUFFEREVENTS
+/* XXXX These generic versions could be simplified by making them
+ type-specific */
+
+/** Callback: Invoked whenever bytes are added to or drained from an input
+ * evbuffer. Used to track the number of bytes read. */
+static void
+evbuffer_inbuf_callback(struct evbuffer *buf,
+ const struct evbuffer_cb_info *info, void *arg)
+{
+ connection_t *conn = arg;
+ (void) buf;
+ /* XXXX These need to get real counts on the non-nested TLS case. - NM */
+ if (info->n_added) {
+ time_t now = approx_time();
+ conn->timestamp_lastread = now;
+ record_num_bytes_transferred(conn, now, info->n_added, 0);
+ connection_consider_empty_read_buckets(conn);
+ if (conn->type == CONN_TYPE_AP) {
+ edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+ /*XXXX022 check for overflow*/
+ edge_conn->n_read += (int)info->n_added;
+ }
+ }
+}
+
+/** Callback: Invoked whenever bytes are added to or drained from an output
+ * evbuffer. Used to track the number of bytes written. */
+static void
+evbuffer_outbuf_callback(struct evbuffer *buf,
+ const struct evbuffer_cb_info *info, void *arg)
+{
+ connection_t *conn = arg;
+ (void)buf;
+ if (info->n_deleted) {
+ time_t now = approx_time();
+ conn->timestamp_lastwritten = now;
+ record_num_bytes_transferred(conn, now, 0, info->n_deleted);
+ connection_consider_empty_write_buckets(conn);
+ if (conn->type == CONN_TYPE_AP) {
+ edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+ /*XXXX022 check for overflow*/
+ edge_conn->n_written += (int)info->n_deleted;
+ }
+ }
+}
+
+/** Callback: invoked whenever a bufferevent has read data. */
+void
+connection_handle_read_cb(struct bufferevent *bufev, void *arg)
+{
+ connection_t *conn = arg;
+ (void) bufev;
+ if (!conn->marked_for_close) {
+ if (connection_process_inbuf(conn, 1)<0) /* XXXX Always 1? */
+ if (!conn->marked_for_close)
+ connection_mark_for_close(conn);
+ }
+}
+
+/** Callback: invoked whenever a bufferevent has written data. */
+void
+connection_handle_write_cb(struct bufferevent *bufev, void *arg)
+{
+ connection_t *conn = arg;
+ struct evbuffer *output;
+ if (connection_flushed_some(conn)<0) {
+ if (!conn->marked_for_close)
+ connection_mark_for_close(conn);
+ return;
+ }
+
+ output = bufferevent_get_output(bufev);
+ if (!evbuffer_get_length(output)) {
+ connection_finished_flushing(conn);
+ if (conn->marked_for_close && conn->hold_open_until_flushed) {
+ conn->hold_open_until_flushed = 0;
+ if (conn->linked) {
+ /* send eof */
+ bufferevent_flush(conn->bufev, EV_WRITE, BEV_FINISHED);
+ }
+ }
+ }
+}
+
+/** Callback: invoked whenever a bufferevent has had an event (like a
+ * connection, or an eof, or an error) occur. */
+void
+connection_handle_event_cb(struct bufferevent *bufev, short event, void *arg)
+{
+ connection_t *conn = arg;
+ (void) bufev;
+ if (event & BEV_EVENT_CONNECTED) {
+ tor_assert(connection_state_is_connecting(conn));
+ if (connection_finished_connecting(conn)<0)
+ return;
+ }
+ if (event & BEV_EVENT_EOF) {
+ if (!conn->marked_for_close) {
+ conn->inbuf_reached_eof = 1;
+ if (connection_reached_eof(conn)<0)
+ return;
+ }
+ }
+ if (event & BEV_EVENT_ERROR) {
+ int socket_error = evutil_socket_geterror(conn->s);
+ if (conn->type == CONN_TYPE_OR &&
+ conn->state == OR_CONN_STATE_CONNECTING) {
+ connection_or_connect_failed(TO_OR_CONN(conn),
+ errno_to_orconn_end_reason(socket_error),
+ tor_socket_strerror(socket_error));
+ } else if (CONN_IS_EDGE(conn)) {
+ edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+ if (!edge_conn->edge_has_sent_end)
+ connection_edge_end_errno(edge_conn);
+ if (conn->type == CONN_TYPE_AP && TO_ENTRY_CONN(conn)->socks_request) {
+ /* broken, don't send a socks reply back */
+ TO_ENTRY_CONN(conn)->socks_request->has_finished = 1;
+ }
+ }
+ connection_close_immediate(conn); /* Connection is dead. */
+ if (!conn->marked_for_close)
+ connection_mark_for_close(conn);
+ }
+}
+
+/** Set up the generic callbacks for the bufferevent on <b>conn</b>. */
+void
+connection_configure_bufferevent_callbacks(connection_t *conn)
+{
+ struct bufferevent *bufev;
+ struct evbuffer *input, *output;
+ tor_assert(conn->bufev);
+ bufev = conn->bufev;
+ bufferevent_setcb(bufev,
+ connection_handle_read_cb,
+ connection_handle_write_cb,
+ connection_handle_event_cb,
+ conn);
+ /* Set a fairly high write low-watermark so that we get the write callback
+ called whenever data is written to bring us under 128K. Leave the
+ high-watermark at 0.
+ */
+ bufferevent_setwatermark(bufev, EV_WRITE, 128*1024, 0);
+
+ input = bufferevent_get_input(bufev);
+ output = bufferevent_get_output(bufev);
+ evbuffer_add_cb(input, evbuffer_inbuf_callback, conn);
+ evbuffer_add_cb(output, evbuffer_outbuf_callback, conn);
+}
+#endif
+
/** A pass-through to fetch_from_buf. */
int
connection_fetch_from_buf(char *string, size_t len, connection_t *conn)
{
- return fetch_from_buf(string, len, conn->inbuf);
+ IF_HAS_BUFFEREVENT(conn, {
+ /* XXX overflow -seb */
+ return (int)bufferevent_read(conn->bufev, string, len);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return fetch_from_buf(string, len, conn->inbuf);
+ }
+}
+
+/** As fetch_from_buf_line(), but read from a connection's input buffer. */
+int
+connection_fetch_from_buf_line(connection_t *conn, char *data,
+ size_t *data_len)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ int r;
+ size_t eol_len=0;
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ struct evbuffer_ptr ptr =
+ evbuffer_search_eol(input, NULL, &eol_len, EVBUFFER_EOL_LF);
+ if (ptr.pos == -1)
+ return 0; /* No EOL found. */
+ if ((size_t)ptr.pos+eol_len >= *data_len) {
+ return -1; /* Too long */
+ }
+ *data_len = ptr.pos+eol_len;
+ r = evbuffer_remove(input, data, ptr.pos+eol_len);
+ tor_assert(r >= 0);
+ data[ptr.pos+eol_len] = '\0';
+ return 1;
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return fetch_from_buf_line(conn->inbuf, data, data_len);
+ }
+}
+
+/** As fetch_from_buf_http, but fetches from a conncetion's input buffer_t or
+ * its bufferevent as appropriate. */
+int
+connection_fetch_from_buf_http(connection_t *conn,
+ char **headers_out, size_t max_headerlen,
+ char **body_out, size_t *body_used,
+ size_t max_bodylen, int force_complete)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ return fetch_from_evbuffer_http(input, headers_out, max_headerlen,
+ body_out, body_used, max_bodylen, force_complete);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return fetch_from_buf_http(conn->inbuf, headers_out, max_headerlen,
+ body_out, body_used, max_bodylen, force_complete);
+ }
}
/** Return conn-\>outbuf_flushlen: how many bytes conn wants to flush
@@ -2854,6 +3228,7 @@ connection_handle_write_impl(connection_t *conn, int force)
/* If we just flushed the last bytes, check if this tunneled dir
* request is done. */
+ /* XXXX move this to flushed_some or finished_flushing -NM */
if (buf_datalen(conn->outbuf) == 0 && conn->dirreq_id)
geoip_change_dirreq_state(conn->dirreq_id, DIRREQ_TUNNELED,
DIRREQ_OR_CONN_BUFFER_FLUSHED);
@@ -2909,6 +3284,7 @@ connection_handle_write_impl(connection_t *conn, int force)
if (n_written && conn->type == CONN_TYPE_AP) {
edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+
/* Check for overflow: */
if (PREDICT_LIKELY(UINT32_MAX - edge_conn->n_written > n_written))
edge_conn->n_written += (int)n_written;
@@ -2952,6 +3328,25 @@ connection_handle_write(connection_t *conn, int force)
return res;
}
+/**
+ * Try to flush data that's waiting for a write on <b>conn</b>. Return
+ * -1 on failure, 0 on success.
+ *
+ * Don't use this function for regular writing; the buffers/bufferevents
+ * system should be good enough at scheduling writes there. Instead, this
+ * function is for cases when we're about to exit or something and we want
+ * to report it right away.
+ */
+int
+connection_flush(connection_t *conn)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ int r = bufferevent_flush(conn->bufev, EV_WRITE, BEV_FLUSH);
+ return (r < 0) ? -1 : 0;
+ });
+ return connection_handle_write(conn, 1);
+}
+
/** OpenSSL TLS record size is 16383; this is close. The goal here is to
* push data out as soon as we know there's enough for a TLS record, so
* during periods of high load we won't read entire megabytes from
@@ -2985,6 +3380,22 @@ _connection_write_to_buf_impl(const char *string, size_t len,
if (conn->marked_for_close && !conn->hold_open_until_flushed)
return;
+ IF_HAS_BUFFEREVENT(conn, {
+ if (zlib) {
+ int done = zlib < 0;
+ r = write_to_evbuffer_zlib(bufferevent_get_output(conn->bufev),
+ TO_DIR_CONN(conn)->zlib_state,
+ string, len, done);
+ } else {
+ r = bufferevent_write(conn->bufev, string, len);
+ }
+ if (r < 0) {
+ /* XXXX mark for close? */
+ log_warn(LD_NET, "bufferevent_write failed! That shouldn't happen.");
+ }
+ return;
+ });
+
old_datalen = buf_datalen(conn->outbuf);
if (zlib) {
dir_connection_t *dir_conn = TO_DIR_CONN(conn);
@@ -3012,7 +3423,13 @@ _connection_write_to_buf_impl(const char *string, size_t len,
return;
}
- connection_start_writing(conn);
+ /* If we receive optimistic data in the EXIT_CONN_STATE_RESOLVING
+ * state, we don't want to try to write it right away, since
+ * conn->write_event won't be set yet. Otherwise, write data from
+ * this conn as the socket is available. */
+ if (conn->write_event) {
+ connection_start_writing(conn);
+ }
if (zlib) {
conn->outbuf_flushlen += buf_datalen(conn->outbuf) - old_datalen;
} else {
@@ -3138,8 +3555,7 @@ connection_get_by_type_state_rendquery(int type, int state,
type == CONN_TYPE_AP || type == CONN_TYPE_EXIT);
tor_assert(rendquery);
- SMARTLIST_FOREACH(conns, connection_t *, conn,
- {
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
if (conn->type == type &&
!conn->marked_for_close &&
(!state || state == conn->state)) {
@@ -3154,7 +3570,33 @@ connection_get_by_type_state_rendquery(int type, int state,
TO_EDGE_CONN(conn)->rend_data->onion_address))
return conn;
}
- });
+ } SMARTLIST_FOREACH_END(conn);
+ return NULL;
+}
+
+/** Return a directory connection (if any one exists) that is fetching
+ * the item described by <b>state</b>/<b>resource</b> */
+dir_connection_t *
+connection_dir_get_by_purpose_and_resource(int purpose,
+ const char *resource)
+{
+ smartlist_t *conns = get_connection_array();
+
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
+ dir_connection_t *dirconn;
+ if (conn->type != CONN_TYPE_DIR || conn->marked_for_close ||
+ conn->purpose != purpose)
+ continue;
+ dirconn = TO_DIR_CONN(conn);
+ if (dirconn->requested_resource == NULL) {
+ if (resource == NULL)
+ return dirconn;
+ } else if (resource) {
+ if (0 == strcmp(resource, dirconn->requested_resource))
+ return dirconn;
+ }
+ } SMARTLIST_FOREACH_END(conn);
+
return NULL;
}
@@ -3408,6 +3850,9 @@ connection_finished_flushing(connection_t *conn)
// log_fn(LOG_DEBUG,"entered. Socket %u.", conn->s);
+ IF_HAS_NO_BUFFEREVENT(conn)
+ connection_stop_writing(conn);
+
switch (conn->type) {
case CONN_TYPE_OR:
return connection_or_finished_flushing(TO_OR_CONN(conn));
@@ -3533,11 +3978,23 @@ assert_connection_ok(connection_t *conn, time_t now)
tor_assert(conn);
tor_assert(conn->type >= _CONN_TYPE_MIN);
tor_assert(conn->type <= _CONN_TYPE_MAX);
+
+#ifdef USE_BUFFEREVENTS
+ if (conn->bufev) {
+ tor_assert(conn->read_event == NULL);
+ tor_assert(conn->write_event == NULL);
+ tor_assert(conn->inbuf == NULL);
+ tor_assert(conn->outbuf == NULL);
+ }
+#endif
+
switch (conn->type) {
case CONN_TYPE_OR:
tor_assert(conn->magic == OR_CONNECTION_MAGIC);
break;
case CONN_TYPE_AP:
+ tor_assert(conn->magic == ENTRY_CONNECTION_MAGIC);
+ break;
case CONN_TYPE_EXIT:
tor_assert(conn->magic == EDGE_CONNECTION_MAGIC);
break;
@@ -3547,6 +4004,9 @@ assert_connection_ok(connection_t *conn, time_t now)
case CONN_TYPE_CONTROL:
tor_assert(conn->magic == CONTROL_CONNECTION_MAGIC);
break;
+ CASE_ANY_LISTENER_TYPE:
+ tor_assert(conn->magic == LISTENER_CONNECTION_MAGIC);
+ break;
default:
tor_assert(conn->magic == BASE_CONNECTION_MAGIC);
break;
@@ -3560,8 +4020,15 @@ assert_connection_ok(connection_t *conn, time_t now)
tor_assert(!SOCKET_OK(conn->s));
if (conn->outbuf_flushlen > 0) {
- tor_assert(connection_is_writing(conn) || conn->write_blocked_on_bw ||
- (CONN_IS_EDGE(conn) && TO_EDGE_CONN(conn)->edge_blocked_on_circ));
+ /* With optimistic data, we may have queued data in
+ * EXIT_CONN_STATE_RESOLVING while the conn is not yet marked to writing.
+ * */
+ tor_assert((conn->type == CONN_TYPE_EXIT &&
+ conn->state == EXIT_CONN_STATE_RESOLVING) ||
+ connection_is_writing(conn) ||
+ conn->write_blocked_on_bw ||
+ (CONN_IS_EDGE(conn) &&
+ TO_EDGE_CONN(conn)->edge_blocked_on_circ));
}
if (conn->hold_open_until_flushed)
@@ -3571,10 +4038,10 @@ assert_connection_ok(connection_t *conn, time_t now)
* marked_for_close. */
/* buffers */
- if (!connection_is_listener(conn)) {
+ if (conn->inbuf)
assert_buf_ok(conn->inbuf);
+ if (conn->outbuf)
assert_buf_ok(conn->outbuf);
- }
if (conn->type == CONN_TYPE_OR) {
or_connection_t *or_conn = TO_OR_CONN(conn);
@@ -3594,21 +4061,18 @@ assert_connection_ok(connection_t *conn, time_t now)
}
if (CONN_IS_EDGE(conn)) {
- edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
- if (edge_conn->chosen_exit_optional || edge_conn->chosen_exit_retries) {
- tor_assert(conn->type == CONN_TYPE_AP);
- tor_assert(edge_conn->chosen_exit_name);
- }
-
/* XXX unchecked: package window, deliver window. */
if (conn->type == CONN_TYPE_AP) {
+ entry_connection_t *entry_conn = TO_ENTRY_CONN(conn);
+ if (entry_conn->chosen_exit_optional || entry_conn->chosen_exit_retries)
+ tor_assert(entry_conn->chosen_exit_name);
- tor_assert(edge_conn->socks_request);
+ tor_assert(entry_conn->socks_request);
if (conn->state == AP_CONN_STATE_OPEN) {
- tor_assert(edge_conn->socks_request->has_finished);
+ tor_assert(entry_conn->socks_request->has_finished);
if (!conn->marked_for_close) {
- tor_assert(edge_conn->cpath_layer);
- assert_cpath_layer_ok(edge_conn->cpath_layer);
+ tor_assert(ENTRY_TO_EDGE_CONN(entry_conn)->cpath_layer);
+ assert_cpath_layer_ok(ENTRY_TO_EDGE_CONN(entry_conn)->cpath_layer);
}
}
}
@@ -3624,13 +4088,7 @@ assert_connection_ok(connection_t *conn, time_t now)
switch (conn->type)
{
- case CONN_TYPE_OR_LISTENER:
- case CONN_TYPE_AP_LISTENER:
- case CONN_TYPE_AP_TRANS_LISTENER:
- case CONN_TYPE_AP_NATD_LISTENER:
- case CONN_TYPE_DIR_LISTENER:
- case CONN_TYPE_CONTROL_LISTENER:
- case CONN_TYPE_AP_DNS_LISTENER:
+ CASE_ANY_LISTENER_TYPE:
tor_assert(conn->state == LISTENER_STATE_READY);
break;
case CONN_TYPE_OR:
@@ -3647,7 +4105,7 @@ assert_connection_ok(connection_t *conn, time_t now)
case CONN_TYPE_AP:
tor_assert(conn->state >= _AP_CONN_STATE_MIN);
tor_assert(conn->state <= _AP_CONN_STATE_MAX);
- tor_assert(TO_EDGE_CONN(conn)->socks_request);
+ tor_assert(TO_ENTRY_CONN(conn)->socks_request);
break;
case CONN_TYPE_DIR:
tor_assert(conn->state >= _DIR_CONN_STATE_MIN);
@@ -3668,3 +4126,141 @@ assert_connection_ok(connection_t *conn, time_t now)
}
}
+/** Fills <b>addr</b> and <b>port</b> with the details of the global
+ * proxy server we are using.
+ * <b>conn</b> contains the connection we are using the proxy for.
+ *
+ * Return 0 on success, -1 on failure.
+ */
+int
+get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
+ const connection_t *conn)
+{
+ const or_options_t *options = get_options();
+
+ if (options->HTTPSProxy) {
+ tor_addr_copy(addr, &options->HTTPSProxyAddr);
+ *port = options->HTTPSProxyPort;
+ *proxy_type = PROXY_CONNECT;
+ return 0;
+ } else if (options->Socks4Proxy) {
+ tor_addr_copy(addr, &options->Socks4ProxyAddr);
+ *port = options->Socks4ProxyPort;
+ *proxy_type = PROXY_SOCKS4;
+ return 0;
+ } else if (options->Socks5Proxy) {
+ tor_addr_copy(addr, &options->Socks5ProxyAddr);
+ *port = options->Socks5ProxyPort;
+ *proxy_type = PROXY_SOCKS5;
+ return 0;
+ } else if (options->ClientTransportPlugin ||
+ options->Bridges) {
+ const transport_t *transport = NULL;
+ int r;
+ r = find_transport_by_bridge_addrport(&conn->addr, conn->port, &transport);
+ if (r<0)
+ return -1;
+ if (transport) { /* transport found */
+ tor_addr_copy(addr, &transport->addr);
+ *port = transport->port;
+ *proxy_type = transport->socks_version;
+ return 0;
+ }
+ }
+
+ *proxy_type = PROXY_NONE;
+ return 0;
+}
+
+/** Returns the global proxy type used by tor. */
+static int
+get_proxy_type(void)
+{
+ const or_options_t *options = get_options();
+
+ if (options->HTTPSProxy)
+ return PROXY_CONNECT;
+ else if (options->Socks4Proxy)
+ return PROXY_SOCKS4;
+ else if (options->Socks5Proxy)
+ return PROXY_SOCKS5;
+ else if (options->ClientTransportPlugin)
+ return PROXY_PLUGGABLE;
+ else
+ return PROXY_NONE;
+}
+
+/** Log a failed connection to a proxy server.
+ * <b>conn</b> is the connection we use the proxy server for. */
+void
+log_failed_proxy_connection(connection_t *conn)
+{
+ tor_addr_t proxy_addr;
+ uint16_t proxy_port;
+ int proxy_type;
+
+ if (get_proxy_addrport(&proxy_addr, &proxy_port, &proxy_type, conn) != 0)
+ return; /* if we have no proxy set up, leave this function. */
+
+ log_warn(LD_NET,
+ "The connection to the %s proxy server at %s:%u just failed. "
+ "Make sure that the proxy server is up and running.",
+ proxy_type_to_string(get_proxy_type()), fmt_addr(&proxy_addr),
+ proxy_port);
+}
+
+/** Return string representation of <b>proxy_type</b>. */
+static const char *
+proxy_type_to_string(int proxy_type)
+{
+ switch (proxy_type) {
+ case PROXY_CONNECT: return "HTTP";
+ case PROXY_SOCKS4: return "SOCKS4";
+ case PROXY_SOCKS5: return "SOCKS5";
+ case PROXY_PLUGGABLE: return "pluggable transports SOCKS";
+ case PROXY_NONE: return "NULL";
+ default: tor_assert(0);
+ }
+ return NULL; /*Unreached*/
+}
+
+/** Call _connection_free() on every connection in our array, and release all
+ * storage held by connection.c. This is used by cpuworkers and dnsworkers
+ * when they fork, so they don't keep resources held open (especially
+ * sockets).
+ *
+ * Don't do the checks in connection_free(), because they will
+ * fail.
+ */
+void
+connection_free_all(void)
+{
+ smartlist_t *conns = get_connection_array();
+
+ /* We don't want to log any messages to controllers. */
+ SMARTLIST_FOREACH(conns, connection_t *, conn,
+ if (conn->type == CONN_TYPE_CONTROL)
+ TO_CONTROL_CONN(conn)->event_mask = 0);
+
+ control_update_global_event_mask();
+
+ /* Unlink everything from the identity map. */
+ connection_or_clear_identity_map();
+
+ /* Clear out our list of broken connections */
+ clear_broken_connection_map(0);
+
+ SMARTLIST_FOREACH(conns, connection_t *, conn, _connection_free(conn));
+
+ if (outgoing_addrs) {
+ SMARTLIST_FOREACH(outgoing_addrs, void*, addr, tor_free(addr));
+ smartlist_free(outgoing_addrs);
+ outgoing_addrs = NULL;
+ }
+
+#ifdef USE_BUFFEREVENTS
+ if (global_rate_limit)
+ bufferevent_rate_limit_group_free(global_rate_limit);
+#endif
+}
+
diff --git a/src/or/connection.h b/src/or/connection.h
index 576d3a63e..9f1148972 100644
--- a/src/or/connection.h
+++ b/src/or/connection.h
@@ -12,13 +12,18 @@
#ifndef _TOR_CONNECTION_H
#define _TOR_CONNECTION_H
+/* XXXX For buf_datalen in inline function */
+#include "buffers.h"
+
const char *conn_type_to_string(int type);
const char *conn_state_to_string(int type, int state);
dir_connection_t *dir_connection_new(int socket_family);
or_connection_t *or_connection_new(int socket_family);
edge_connection_t *edge_connection_new(int type, int socket_family);
+entry_connection_t *entry_connection_new(int type, int socket_family);
control_connection_t *control_connection_new(int socket_family);
+listener_connection_t *listener_connection_new(int type, int socket_family);
connection_t *connection_new(int type, int socket_family);
void connection_link_connections(connection_t *conn_a, connection_t *conn_b);
@@ -31,6 +36,21 @@ void _connection_mark_for_close(connection_t *conn,int line, const char *file);
#define connection_mark_for_close(c) \
_connection_mark_for_close((c), __LINE__, _SHORT_FILE_)
+/**
+ * Mark 'c' for close, but try to hold it open until all the data is written.
+ */
+#define _connection_mark_and_flush(c,line,file) \
+ do { \
+ connection_t *tmp_conn_ = (c); \
+ _connection_mark_for_close(tmp_conn_, (line), (file)); \
+ tmp_conn_->hold_open_until_flushed = 1; \
+ IF_HAS_BUFFEREVENT(tmp_conn_, \
+ connection_start_writing(tmp_conn_)); \
+ } while (0)
+
+#define connection_mark_and_flush(c) \
+ _connection_mark_and_flush((c), __LINE__, _SHORT_FILE_)
+
void connection_expire_held_open(void);
int connection_connect(connection_t *conn, const char *address,
@@ -39,6 +59,9 @@ int connection_connect(connection_t *conn, const char *address,
int connection_proxy_connect(connection_t *conn, int type);
int connection_read_proxy_handshake(connection_t *conn);
+void log_failed_proxy_connection(connection_t *conn);
+int get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type,
+ const connection_t *conn);
int retry_all_listeners(smartlist_t *replaced_conns,
smartlist_t *new_conns);
@@ -51,10 +74,18 @@ void connection_bucket_refill(int seconds_elapsed, time_t now);
int connection_handle_read(connection_t *conn);
int connection_fetch_from_buf(char *string, size_t len, connection_t *conn);
+int connection_fetch_from_buf_line(connection_t *conn, char *data,
+ size_t *data_len);
+int connection_fetch_from_buf_http(connection_t *conn,
+ char **headers_out, size_t max_headerlen,
+ char **body_out, size_t *body_used,
+ size_t max_bodylen, int force_complete);
int connection_wants_to_flush(connection_t *conn);
int connection_outbuf_too_full(connection_t *conn);
int connection_handle_write(connection_t *conn, int force);
+int connection_flush(connection_t *conn);
+
void _connection_write_to_buf_impl(const char *string, size_t len,
connection_t *conn, int zlib);
static void connection_write_to_buf(const char *string, size_t len,
@@ -73,6 +104,29 @@ connection_write_to_buf_zlib(const char *string, size_t len,
_connection_write_to_buf_impl(string, len, TO_CONN(conn), done ? -1 : 1);
}
+static size_t connection_get_inbuf_len(connection_t *conn);
+static size_t connection_get_outbuf_len(connection_t *conn);
+
+static INLINE size_t
+connection_get_inbuf_len(connection_t *conn)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ return evbuffer_get_length(bufferevent_get_input(conn->bufev));
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return conn->inbuf ? buf_datalen(conn->inbuf) : 0;
+ }
+}
+
+static INLINE size_t
+connection_get_outbuf_len(connection_t *conn)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ return evbuffer_get_length(bufferevent_get_output(conn->bufev));
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return conn->outbuf ? buf_datalen(conn->outbuf) : 0;
+ }
+}
+
connection_t *connection_get_by_global_id(uint64_t id);
connection_t *connection_get_by_type(int type);
@@ -83,6 +137,8 @@ connection_t *connection_get_by_type_addr_port_purpose(int type,
connection_t *connection_get_by_type_state(int type, int state);
connection_t *connection_get_by_type_state_rendquery(int type, int state,
const char *rendquery);
+dir_connection_t *connection_dir_get_by_purpose_and_resource(
+ int state, const char *resource);
#define connection_speaks_cells(conn) ((conn)->type == CONN_TYPE_OR)
int connection_is_listener(connection_t *conn);
@@ -96,5 +152,19 @@ int connection_or_nonopen_was_started_here(or_connection_t *conn);
void connection_dump_buffer_mem_stats(int severity);
void remove_file_if_very_old(const char *fname, time_t now);
+#ifdef USE_BUFFEREVENTS
+int connection_type_uses_bufferevent(connection_t *conn);
+void connection_configure_bufferevent_callbacks(connection_t *conn);
+void connection_handle_read_cb(struct bufferevent *bufev, void *arg);
+void connection_handle_write_cb(struct bufferevent *bufev, void *arg);
+void connection_handle_event_cb(struct bufferevent *bufev, short event,
+ void *arg);
+void connection_get_rate_limit_totals(uint64_t *read_out,
+ uint64_t *written_out);
+void connection_enable_rate_limiting(connection_t *conn);
+#else
+#define connection_type_uses_bufferevent(c) (0)
+#endif
+
#endif
diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c
index d4d7e1c73..40426a9b2 100644
--- a/src/or/connection_edge.c
+++ b/src/or/connection_edge.c
@@ -23,6 +23,7 @@
#include "dirserv.h"
#include "hibernate.h"
#include "main.h"
+#include "nodelist.h"
#include "policies.h"
#include "reasons.h"
#include "relay.h"
@@ -50,27 +51,43 @@
#define SOCKS4_GRANTED 90
#define SOCKS4_REJECT 91
-static int connection_ap_handshake_process_socks(edge_connection_t *conn);
-static int connection_ap_process_natd(edge_connection_t *conn);
+static int connection_ap_handshake_process_socks(entry_connection_t *conn);
+static int connection_ap_process_natd(entry_connection_t *conn);
static int connection_exit_connect_dir(edge_connection_t *exitconn);
static int address_is_in_virtual_range(const char *addr);
-static int consider_plaintext_ports(edge_connection_t *conn, uint16_t port);
+static int consider_plaintext_ports(entry_connection_t *conn, uint16_t port);
static void clear_trackexithost_mappings(const char *exitname);
+static int connection_ap_supports_optimistic_data(const entry_connection_t *);
/** An AP stream has failed/finished. If it hasn't already sent back
* a socks reply, send one now (based on endreason). Also set
* has_sent_end to 1, and mark the conn.
*/
void
-_connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
+_connection_mark_unattached_ap(entry_connection_t *conn, int endreason,
int line, const char *file)
{
- tor_assert(conn->_base.type == CONN_TYPE_AP);
- conn->edge_has_sent_end = 1; /* no circ yet */
-
- if (conn->_base.marked_for_close) {
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
+ tor_assert(base_conn->type == CONN_TYPE_AP);
+ ENTRY_TO_EDGE_CONN(conn)->edge_has_sent_end = 1; /* no circ yet */
+
+ /* If this is a rendezvous stream and it is failing without ever
+ * being attached to a circuit, assume that an attempt to connect to
+ * the destination hidden service has just ended.
+ *
+ * XXX023 This condition doesn't limit to only streams failing
+ * without ever being attached. That sloppiness should be harmless,
+ * but we should fix it someday anyway. */
+ if ((edge_conn->on_circuit != NULL || edge_conn->edge_has_sent_end) &&
+ connection_edge_is_rendezvous_stream(edge_conn)) {
+ rend_client_note_connection_attempt_ended(
+ edge_conn->rend_data->onion_address);
+ }
+
+ if (base_conn->marked_for_close) {
/* This call will warn as appropriate. */
- _connection_mark_for_close(TO_CONN(conn), line, file);
+ _connection_mark_for_close(base_conn, line, file);
return;
}
@@ -90,9 +107,9 @@ _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
conn->socks_request->has_finished = 1;
}
- _connection_mark_for_close(TO_CONN(conn), line, file);
- conn->_base.hold_open_until_flushed = 1;
- conn->end_reason = endreason;
+ _connection_mark_and_flush(base_conn, line, file);
+
+ ENTRY_TO_EDGE_CONN(conn)->end_reason = endreason;
}
/** There was an EOF. Send an end and mark the connection for close.
@@ -100,7 +117,7 @@ _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
int
connection_edge_reached_eof(edge_connection_t *conn)
{
- if (buf_datalen(conn->_base.inbuf) &&
+ if (connection_get_inbuf_len(TO_CONN(conn)) &&
connection_state_is_open(TO_CONN(conn))) {
/* it still has stuff to process. don't let it die yet. */
return 0;
@@ -110,8 +127,11 @@ connection_edge_reached_eof(edge_connection_t *conn)
/* only mark it if not already marked. it's possible to
* get the 'end' right around when the client hangs up on us. */
connection_edge_end(conn, END_STREAM_REASON_DONE);
- if (conn->socks_request) /* eof, so don't send a socks reply back */
- conn->socks_request->has_finished = 1;
+ if (conn->_base.type == CONN_TYPE_AP) {
+ /* eof, so don't send a socks reply back */
+ if (EDGE_TO_ENTRY_CONN(conn)->socks_request)
+ EDGE_TO_ENTRY_CONN(conn)->socks_request->has_finished = 1;
+ }
connection_mark_for_close(TO_CONN(conn));
}
return 0;
@@ -134,13 +154,13 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
switch (conn->_base.state) {
case AP_CONN_STATE_SOCKS_WAIT:
- if (connection_ap_handshake_process_socks(conn) < 0) {
+ if (connection_ap_handshake_process_socks(EDGE_TO_ENTRY_CONN(conn)) <0) {
/* already marked */
return -1;
}
return 0;
case AP_CONN_STATE_NATD_WAIT:
- if (connection_ap_process_natd(conn) < 0) {
+ if (connection_ap_process_natd(EDGE_TO_ENTRY_CONN(conn)) < 0) {
/* already marked */
return -1;
}
@@ -153,10 +173,26 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial)
return -1;
}
return 0;
+ case AP_CONN_STATE_CONNECT_WAIT:
+ if (connection_ap_supports_optimistic_data(EDGE_TO_ENTRY_CONN(conn))) {
+ log_info(LD_EDGE,
+ "data from edge while in '%s' state. Sending it anyway. "
+ "package_partial=%d, buflen=%ld",
+ conn_state_to_string(conn->_base.type, conn->_base.state),
+ package_partial,
+ (long)connection_get_inbuf_len(TO_CONN(conn)));
+ if (connection_edge_package_raw_inbuf(conn, package_partial, NULL)<0) {
+ /* (We already sent an end cell if possible) */
+ connection_mark_for_close(TO_CONN(conn));
+ return -1;
+ }
+ return 0;
+ }
+ /* Fall through if the connection is on a circuit without optimistic
+ * data support. */
case EXIT_CONN_STATE_CONNECTING:
case AP_CONN_STATE_RENDDESC_WAIT:
case AP_CONN_STATE_CIRCUIT_WAIT:
- case AP_CONN_STATE_CONNECT_WAIT:
case AP_CONN_STATE_RESOLVE_WAIT:
case AP_CONN_STATE_CONTROLLER_WAIT:
log_info(LD_EDGE,
@@ -181,9 +217,10 @@ connection_edge_destroy(circid_t circ_id, edge_connection_t *conn)
log_info(LD_EDGE,
"CircID %d: At an edge. Marking connection for close.", circ_id);
if (conn->_base.type == CONN_TYPE_AP) {
- connection_mark_unattached_ap(conn, END_STREAM_REASON_DESTROY);
+ entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_DESTROY);
control_event_stream_bandwidth(conn);
- control_event_stream_status(conn, STREAM_EVENT_CLOSED,
+ control_event_stream_status(entry_conn, STREAM_EVENT_CLOSED,
END_STREAM_REASON_DESTROY);
conn->end_reason |= END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED;
} else {
@@ -191,8 +228,7 @@ connection_edge_destroy(circid_t circ_id, edge_connection_t *conn)
conn->edge_has_sent_end = 1;
conn->end_reason = END_STREAM_REASON_DESTROY;
conn->end_reason |= END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED;
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+ connection_mark_and_flush(TO_CONN(conn));
}
}
conn->cpath_layer = NULL;
@@ -336,7 +372,6 @@ connection_edge_finished_flushing(edge_connection_t *conn)
switch (conn->_base.state) {
case AP_CONN_STATE_OPEN:
case EXIT_CONN_STATE_OPEN:
- connection_stop_writing(TO_CONN(conn));
connection_edge_consider_sending_sendme(conn);
return 0;
case AP_CONN_STATE_SOCKS_WAIT:
@@ -345,7 +380,7 @@ connection_edge_finished_flushing(edge_connection_t *conn)
case AP_CONN_STATE_CIRCUIT_WAIT:
case AP_CONN_STATE_CONNECT_WAIT:
case AP_CONN_STATE_CONTROLLER_WAIT:
- connection_stop_writing(TO_CONN(conn));
+ case AP_CONN_STATE_RESOLVE_WAIT:
return 0;
default:
log_warn(LD_BUG, "Called in unexpected state %d.",conn->_base.state);
@@ -375,8 +410,9 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn)
rep_hist_note_exit_stream_opened(conn->port);
conn->state = EXIT_CONN_STATE_OPEN;
- connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */
- if (connection_wants_to_flush(conn)) /* in case there are any queued relay
+ IF_HAS_NO_BUFFEREVENT(conn)
+ connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */
+ if (connection_get_outbuf_len(conn)) /* in case there are any queued relay
* cells */
connection_start_writing(conn);
/* deliver a 'connected' relay cell back through the circuit. */
@@ -408,13 +444,79 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn)
return connection_edge_process_inbuf(edge_conn, 1);
}
+/** Common code to connection_(ap|exit)_about_to_close. */
+static void
+connection_edge_about_to_close(edge_connection_t *edge_conn)
+{
+ if (!edge_conn->edge_has_sent_end) {
+ connection_t *conn = TO_CONN(edge_conn);
+ log_warn(LD_BUG, "(Harmless.) Edge connection (marked at %s:%d) "
+ "hasn't sent end yet?",
+ conn->marked_for_close_file, conn->marked_for_close);
+ tor_fragile_assert();
+ }
+}
+
+/* Called when we're about to finally unlink and free an AP (client)
+ * connection: perform necessary accounting and cleanup */
+void
+connection_ap_about_to_close(entry_connection_t *entry_conn)
+{
+ circuit_t *circ;
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn);
+ connection_t *conn = ENTRY_TO_CONN(entry_conn);
+
+ if (entry_conn->socks_request->has_finished == 0) {
+ /* since conn gets removed right after this function finishes,
+ * there's no point trying to send back a reply at this point. */
+ log_warn(LD_BUG,"Closing stream (marked at %s:%d) without sending"
+ " back a socks reply.",
+ conn->marked_for_close_file, conn->marked_for_close);
+ }
+ if (!edge_conn->end_reason) {
+ log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having"
+ " set end_reason.",
+ conn->marked_for_close_file, conn->marked_for_close);
+ }
+ if (entry_conn->dns_server_request) {
+ log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having"
+ " replied to DNS request.",
+ conn->marked_for_close_file, conn->marked_for_close);
+ dnsserv_reject_request(entry_conn);
+ }
+ control_event_stream_bandwidth(edge_conn);
+ control_event_stream_status(entry_conn, STREAM_EVENT_CLOSED,
+ edge_conn->end_reason);
+ circ = circuit_get_by_edge_conn(edge_conn);
+ if (circ)
+ circuit_detach_stream(circ, edge_conn);
+}
+
+/* Called when we're about to finally unlink and free an exit
+ * connection: perform necessary accounting and cleanup */
+void
+connection_exit_about_to_close(edge_connection_t *edge_conn)
+{
+ circuit_t *circ;
+ connection_t *conn = TO_CONN(edge_conn);
+
+ connection_edge_about_to_close(edge_conn);
+
+ circ = circuit_get_by_edge_conn(edge_conn);
+ if (circ)
+ circuit_detach_stream(circ, edge_conn);
+ if (conn->state == EXIT_CONN_STATE_RESOLVING) {
+ connection_dns_remove(edge_conn);
+ }
+}
+
/** Define a schedule for how long to wait between retrying
* application connections. Rather than waiting a fixed amount of
* time between each retry, we wait 10 seconds each for the first
* two tries, and 15 seconds for each retry after
* that. Hopefully this will improve the expected user experience. */
static int
-compute_retry_timeout(edge_connection_t *conn)
+compute_retry_timeout(entry_connection_t *conn)
{
int timeout = get_options()->CircuitStreamTimeout;
if (timeout) /* if our config options override the default, use them */
@@ -437,41 +539,43 @@ void
connection_ap_expire_beginning(void)
{
edge_connection_t *conn;
+ entry_connection_t *entry_conn;
circuit_t *circ;
time_t now = time(NULL);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int severity;
int cutoff;
int seconds_idle, seconds_since_born;
smartlist_t *conns = get_connection_array();
- SMARTLIST_FOREACH_BEGIN(conns, connection_t *, c) {
- if (c->type != CONN_TYPE_AP || c->marked_for_close)
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
+ if (base_conn->type != CONN_TYPE_AP || base_conn->marked_for_close)
continue;
- conn = TO_EDGE_CONN(c);
+ entry_conn = TO_ENTRY_CONN(base_conn);
+ conn = ENTRY_TO_EDGE_CONN(entry_conn);
/* if it's an internal linked connection, don't yell its status. */
- severity = (tor_addr_is_null(&conn->_base.addr) && !conn->_base.port)
+ severity = (tor_addr_is_null(&base_conn->addr) && !base_conn->port)
? LOG_INFO : LOG_NOTICE;
- seconds_idle = (int)( now - conn->_base.timestamp_lastread );
- seconds_since_born = (int)( now - conn->_base.timestamp_created );
+ seconds_idle = (int)( now - base_conn->timestamp_lastread );
+ seconds_since_born = (int)( now - base_conn->timestamp_created );
- if (conn->_base.state == AP_CONN_STATE_OPEN)
+ if (base_conn->state == AP_CONN_STATE_OPEN)
continue;
/* We already consider SocksTimeout in
* connection_ap_handshake_attach_circuit(), but we need to consider
* it here too because controllers that put streams in controller_wait
* state never ask Tor to attach the circuit. */
- if (AP_CONN_STATE_IS_UNATTACHED(conn->_base.state)) {
+ if (AP_CONN_STATE_IS_UNATTACHED(base_conn->state)) {
if (seconds_since_born >= options->SocksTimeout) {
log_fn(severity, LD_APP,
"Tried for %d seconds to get a connection to %s:%d. "
"Giving up. (%s)",
seconds_since_born,
- safe_str_client(conn->socks_request->address),
- conn->socks_request->port,
- conn_state_to_string(CONN_TYPE_AP, conn->_base.state));
- connection_mark_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
+ safe_str_client(entry_conn->socks_request->address),
+ entry_conn->socks_request->port,
+ conn_state_to_string(CONN_TYPE_AP, base_conn->state));
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT);
}
continue;
}
@@ -479,14 +583,14 @@ connection_ap_expire_beginning(void)
/* We're in state connect_wait or resolve_wait now -- waiting for a
* reply to our relay cell. See if we want to retry/give up. */
- cutoff = compute_retry_timeout(conn);
+ cutoff = compute_retry_timeout(entry_conn);
if (seconds_idle < cutoff)
continue;
circ = circuit_get_by_edge_conn(conn);
if (!circ) { /* it's vanished? */
log_info(LD_APP,"Conn is waiting (address %s), but lost its circ.",
- safe_str_client(conn->socks_request->address));
- connection_mark_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
+ safe_str_client(entry_conn->socks_request->address));
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT);
continue;
}
if (circ->purpose == CIRCUIT_PURPOSE_C_REND_JOINED) {
@@ -495,9 +599,9 @@ connection_ap_expire_beginning(void)
"Rend stream is %d seconds late. Giving up on address"
" '%s.onion'.",
seconds_idle,
- safe_str_client(conn->socks_request->address));
+ safe_str_client(entry_conn->socks_request->address));
connection_edge_end(conn, END_STREAM_REASON_TIMEOUT);
- connection_mark_unattached_ap(conn, END_STREAM_REASON_TIMEOUT);
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT);
}
continue;
}
@@ -506,9 +610,10 @@ connection_ap_expire_beginning(void)
"We tried for %d seconds to connect to '%s' using exit %s."
" Retrying on a new circuit.",
seconds_idle,
- safe_str_client(conn->socks_request->address),
+ safe_str_client(entry_conn->socks_request->address),
conn->cpath_layer ?
- extend_info_describe(conn->cpath_layer->extend_info): "*unnamed*");
+ extend_info_describe(conn->cpath_layer->extend_info):
+ "*unnamed*");
/* send an end down the circuit */
connection_edge_end(conn, END_STREAM_REASON_TIMEOUT);
/* un-mark it as ending, since we're going to reuse it */
@@ -522,15 +627,16 @@ connection_ap_expire_beginning(void)
circ->timestamp_dirty -= options->MaxCircuitDirtiness;
/* give our stream another 'cutoff' seconds to try */
conn->_base.timestamp_lastread += cutoff;
- if (conn->num_socks_retries < 250) /* avoid overflow */
- conn->num_socks_retries++;
+ if (entry_conn->num_socks_retries < 250) /* avoid overflow */
+ entry_conn->num_socks_retries++;
/* move it back into 'pending' state, and try to attach. */
- if (connection_ap_detach_retriable(conn, TO_ORIGIN_CIRCUIT(circ),
+ if (connection_ap_detach_retriable(entry_conn, TO_ORIGIN_CIRCUIT(circ),
END_STREAM_REASON_TIMEOUT)<0) {
- if (!conn->_base.marked_for_close)
- connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
+ if (!base_conn->marked_for_close)
+ connection_mark_unattached_ap(entry_conn,
+ END_STREAM_REASON_CANT_ATTACH);
}
- } SMARTLIST_FOREACH_END(conn);
+ } SMARTLIST_FOREACH_END(base_conn);
}
/** Tell any AP streams that are waiting for a new circuit to try again,
@@ -539,7 +645,7 @@ connection_ap_expire_beginning(void)
void
connection_ap_attach_pending(void)
{
- edge_connection_t *edge_conn;
+ entry_connection_t *entry_conn;
smartlist_t *conns = get_connection_array();
SMARTLIST_FOREACH(conns, connection_t *, conn,
{
@@ -547,10 +653,10 @@ connection_ap_attach_pending(void)
conn->type != CONN_TYPE_AP ||
conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
continue;
- edge_conn = TO_EDGE_CONN(conn);
- if (connection_ap_handshake_attach_circuit(edge_conn) < 0) {
- if (!edge_conn->_base.marked_for_close)
- connection_mark_unattached_ap(edge_conn,
+ entry_conn = TO_ENTRY_CONN(conn);
+ if (connection_ap_handshake_attach_circuit(entry_conn) < 0) {
+ if (!conn->marked_for_close)
+ connection_mark_unattached_ap(entry_conn,
END_STREAM_REASON_CANT_ATTACH);
}
});
@@ -565,7 +671,7 @@ void
connection_ap_fail_onehop(const char *failed_digest,
cpath_build_state_t *build_state)
{
- edge_connection_t *edge_conn;
+ entry_connection_t *entry_conn;
char digest[DIGEST_LEN];
smartlist_t *conns = get_connection_array();
SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
@@ -573,27 +679,27 @@ connection_ap_fail_onehop(const char *failed_digest,
conn->type != CONN_TYPE_AP ||
conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
continue;
- edge_conn = TO_EDGE_CONN(conn);
- if (!edge_conn->want_onehop)
+ entry_conn = TO_ENTRY_CONN(conn);
+ if (!entry_conn->want_onehop)
continue;
- if (hexdigest_to_digest(edge_conn->chosen_exit_name, digest) < 0 ||
+ if (hexdigest_to_digest(entry_conn->chosen_exit_name, digest) < 0 ||
tor_memneq(digest, failed_digest, DIGEST_LEN))
continue;
if (tor_digest_is_zero(digest)) {
/* we don't know the digest; have to compare addr:port */
tor_addr_t addr;
if (!build_state || !build_state->chosen_exit ||
- !edge_conn->socks_request || !edge_conn->socks_request->address)
+ !entry_conn->socks_request || !entry_conn->socks_request->address)
continue;
- if (tor_addr_from_str(&addr, edge_conn->socks_request->address)<0 ||
+ if (tor_addr_from_str(&addr, entry_conn->socks_request->address)<0 ||
!tor_addr_eq(&build_state->chosen_exit->addr, &addr) ||
- build_state->chosen_exit->port != edge_conn->socks_request->port)
+ build_state->chosen_exit->port != entry_conn->socks_request->port)
continue;
}
log_info(LD_APP, "Closing one-hop stream to '%s/%s' because the OR conn "
- "just failed.", edge_conn->chosen_exit_name,
- edge_conn->socks_request->address);
- connection_mark_unattached_ap(edge_conn, END_STREAM_REASON_TIMEOUT);
+ "just failed.", entry_conn->chosen_exit_name,
+ entry_conn->socks_request->address);
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT);
} SMARTLIST_FOREACH_END(conn);
}
@@ -604,8 +710,8 @@ connection_ap_fail_onehop(const char *failed_digest,
void
circuit_discard_optional_exit_enclaves(extend_info_t *info)
{
- edge_connection_t *edge_conn;
- routerinfo_t *r1, *r2;
+ entry_connection_t *entry_conn;
+ const node_t *r1, *r2;
smartlist_t *conns = get_connection_array();
SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
@@ -613,32 +719,32 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info)
conn->type != CONN_TYPE_AP ||
conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
continue;
- edge_conn = TO_EDGE_CONN(conn);
- if (!edge_conn->chosen_exit_optional &&
- !edge_conn->chosen_exit_retries)
+ entry_conn = TO_ENTRY_CONN(conn);
+ if (!entry_conn->chosen_exit_optional &&
+ !entry_conn->chosen_exit_retries)
continue;
- r1 = router_get_by_nickname(edge_conn->chosen_exit_name, 0);
- r2 = router_get_by_digest(info->identity_digest);
+ r1 = node_get_by_nickname(entry_conn->chosen_exit_name, 0);
+ r2 = node_get_by_id(info->identity_digest);
if (!r1 || !r2 || r1 != r2)
continue;
- tor_assert(edge_conn->socks_request);
- if (edge_conn->chosen_exit_optional) {
+ tor_assert(entry_conn->socks_request);
+ if (entry_conn->chosen_exit_optional) {
log_info(LD_APP, "Giving up on enclave exit '%s' for destination %s.",
- safe_str_client(edge_conn->chosen_exit_name),
- escaped_safe_str_client(edge_conn->socks_request->address));
- edge_conn->chosen_exit_optional = 0;
- tor_free(edge_conn->chosen_exit_name); /* clears it */
+ safe_str_client(entry_conn->chosen_exit_name),
+ escaped_safe_str_client(entry_conn->socks_request->address));
+ entry_conn->chosen_exit_optional = 0;
+ tor_free(entry_conn->chosen_exit_name); /* clears it */
/* if this port is dangerous, warn or reject it now that we don't
* think it'll be using an enclave. */
- consider_plaintext_ports(edge_conn, edge_conn->socks_request->port);
+ consider_plaintext_ports(entry_conn, entry_conn->socks_request->port);
}
- if (edge_conn->chosen_exit_retries) {
- if (--edge_conn->chosen_exit_retries == 0) { /* give up! */
- clear_trackexithost_mappings(edge_conn->chosen_exit_name);
- tor_free(edge_conn->chosen_exit_name); /* clears it */
+ if (entry_conn->chosen_exit_retries) {
+ if (--entry_conn->chosen_exit_retries == 0) { /* give up! */
+ clear_trackexithost_mappings(entry_conn->chosen_exit_name);
+ tor_free(entry_conn->chosen_exit_name); /* clears it */
/* if this port is dangerous, warn or reject it now that we don't
* think it'll be using an enclave. */
- consider_plaintext_ports(edge_conn, edge_conn->socks_request->port);
+ consider_plaintext_ports(entry_conn, entry_conn->socks_request->port);
}
}
} SMARTLIST_FOREACH_END(conn);
@@ -652,20 +758,27 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info)
* Returns -1 on err, 1 on success, 0 on not-yet-sure.
*/
int
-connection_ap_detach_retriable(edge_connection_t *conn, origin_circuit_t *circ,
+connection_ap_detach_retriable(entry_connection_t *conn,
+ origin_circuit_t *circ,
int reason)
{
control_event_stream_status(conn, STREAM_EVENT_FAILED_RETRIABLE, reason);
- conn->_base.timestamp_lastread = time(NULL);
+ ENTRY_TO_CONN(conn)->timestamp_lastread = time(NULL);
+
+ if (conn->pending_optimistic_data) {
+ generic_buffer_set_to_copy(&conn->sending_optimistic_data,
+ conn->pending_optimistic_data);
+ }
+
if (!get_options()->LeaveStreamsUnattached || conn->use_begindir) {
/* If we're attaching streams ourself, or if this connection is
* a tunneled directory connection, then just attach it. */
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
- circuit_detach_stream(TO_CIRCUIT(circ),conn);
+ ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CIRCUIT_WAIT;
+ circuit_detach_stream(TO_CIRCUIT(circ),ENTRY_TO_EDGE_CONN(conn));
return connection_ap_handshake_attach_circuit(conn);
} else {
- conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
- circuit_detach_stream(TO_CIRCUIT(circ),conn);
+ ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
+ circuit_detach_stream(TO_CIRCUIT(circ),ENTRY_TO_EDGE_CONN(conn));
return 0;
}
}
@@ -813,7 +926,7 @@ clear_trackexithost_mappings(const char *exitname)
* host is unknown or no longer allowed, or for which the source address
* is no longer in trackexithosts. */
void
-addressmap_clear_excluded_trackexithosts(or_options_t *options)
+addressmap_clear_excluded_trackexithosts(const or_options_t *options)
{
const routerset_t *allow_nodes = options->ExitNodes;
const routerset_t *exclude_nodes = options->_ExcludeExitNodesUnion;
@@ -829,7 +942,7 @@ addressmap_clear_excluded_trackexithosts(or_options_t *options)
size_t len;
const char *target = ent->new_address, *dot;
char *nodename;
- routerinfo_t *ri; /* XXX023 Use node_t. */
+ const node_t *node;
if (strcmpend(target, ".exit")) {
/* Not a .exit mapping */
@@ -842,17 +955,15 @@ addressmap_clear_excluded_trackexithosts(or_options_t *options)
if (len < 6)
continue; /* malformed. */
dot = target + len - 6; /* dot now points to just before .exit */
- dot = strrchr(dot, '.'); /* dot now points to the . before .exit or NULL */
- if (!dot) {
- nodename = tor_strndup(target, len-5);
- } else {
- nodename = tor_strndup(dot+1, strlen(dot+1)-5);
- }
- ri = router_get_by_nickname(nodename, 0);
+ while (dot > target && *dot != '.')
+ dot--;
+ if (*dot == '.') dot++;
+ nodename = tor_strndup(dot, len-5-(dot-target));;
+ node = node_get_by_nickname(nodename, 0);
tor_free(nodename);
- if (!ri ||
- (allow_nodes && !routerset_contains_router(allow_nodes, ri)) ||
- routerset_contains_router(exclude_nodes, ri) ||
+ if (!node ||
+ (allow_nodes && !routerset_contains_node(allow_nodes, node)) ||
+ routerset_contains_node(exclude_nodes, node) ||
!hostname_in_track_host_exits(options, address)) {
/* We don't know this one, or we want to be rid of it. */
addressmap_ent_remove(address, ent);
@@ -866,7 +977,7 @@ addressmap_clear_excluded_trackexithosts(or_options_t *options)
* no longer allowed by AutomapHostsOnResolve, or for which the
* target address is no longer in the virtual network. */
void
-addressmap_clear_invalid_automaps(or_options_t *options)
+addressmap_clear_invalid_automaps(const or_options_t *options)
{
int clear_all = !options->AutomapHostsOnResolve;
const smartlist_t *suffixes = options->AutomapHostsSuffixes;
@@ -1313,7 +1424,6 @@ static char *
addressmap_get_virtual_address(int type)
{
char buf[64];
- struct in_addr in;
tor_assert(addressmap);
if (type == RESOLVED_TYPE_HOSTNAME) {
@@ -1327,6 +1437,7 @@ addressmap_get_virtual_address(int type)
} else if (type == RESOLVED_TYPE_IPV4) {
// This is an imperfect estimate of how many addresses are available, but
// that's ok.
+ struct in_addr in;
uint32_t available = 1u << (32-virtual_addr_netmask_bits);
while (available) {
/* Don't hand out any .0 or .255 address. */
@@ -1518,9 +1629,9 @@ addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
/** Check if <b>conn</b> is using a dangerous port. Then warn and/or
* reject depending on our config options. */
static int
-consider_plaintext_ports(edge_connection_t *conn, uint16_t port)
+consider_plaintext_ports(entry_connection_t *conn, uint16_t port)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int reject = smartlist_string_num_isin(options->RejectPlaintextPorts, port);
if (smartlist_string_num_isin(options->WarnPlaintextPorts, port)) {
@@ -1553,14 +1664,14 @@ consider_plaintext_ports(edge_connection_t *conn, uint16_t port)
* documentation for arguments and return value.
*/
int
-connection_ap_rewrite_and_attach_if_allowed(edge_connection_t *conn,
+connection_ap_rewrite_and_attach_if_allowed(entry_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->LeaveStreamsUnattached) {
- conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
+ ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
return 0;
}
return connection_ap_handshake_rewrite_and_attach(conn, circ, cpath);
@@ -1582,13 +1693,13 @@ connection_ap_rewrite_and_attach_if_allowed(edge_connection_t *conn,
* <b>cpath</b> is NULL.
*/
int
-connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
+connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath)
{
socks_request_t *socks = conn->socks_request;
hostname_type_t addresstype;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
struct in_addr addr_tmp;
/* We set this to true if this is an address we should automatically
* remap to a local address in VirtualAddrNetwork */
@@ -1599,6 +1710,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
address, and we remap it to one because of an entry in the addressmap. */
int remapped_to_exit = 0;
time_t now = time(NULL);
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
tor_strlower(socks->address); /* normalize it */
strlcpy(orig_address, socks->address, sizeof(orig_address));
@@ -1606,6 +1718,9 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
safe_str_client(socks->address),
socks->port);
+ if (! conn->original_dest_address)
+ conn->original_dest_address = tor_strdup(conn->socks_request->address);
+
if (socks->command == SOCKS_COMMAND_RESOLVE &&
!tor_inet_aton(socks->address, &addr_tmp) &&
options->AutomapHostsOnResolve && options->AutomapHostsSuffixes) {
@@ -1711,15 +1826,14 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
/* If StrictNodes is not set, then .exit overrides ExcludeNodes. */
routerset_t *excludeset = options->StrictNodes ?
options->_ExcludeExitNodesUnion : options->ExcludeExitNodes;
- /*XXX023 make this a node_t. */
- routerinfo_t *router;
+ const node_t *node;
tor_assert(!automap);
if (s) {
/* The address was of the form "(stuff).(name).exit */
if (s[1] != '\0') {
conn->chosen_exit_name = tor_strdup(s+1);
- router = router_get_by_nickname(conn->chosen_exit_name, 1);
+ node = node_get_by_nickname(conn->chosen_exit_name, 1);
if (remapped_to_exit) /* 5 tries before it expires the addressmap */
conn->chosen_exit_retries = TRACKHOSTEXITS_RETRIES;
*s = 0;
@@ -1734,15 +1848,16 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
}
} else {
/* It looks like they just asked for "foo.exit". */
+
conn->chosen_exit_name = tor_strdup(socks->address);
- router = router_get_by_nickname(conn->chosen_exit_name, 1);
- if (router) {
+ node = node_get_by_nickname(conn->chosen_exit_name, 1);
+ if (node) {
*socks->address = 0;
- strlcpy(socks->address, router->address, sizeof(socks->address));
+ node_get_address_string(node, socks->address, sizeof(socks->address));
}
}
/* Now make sure that the chosen exit exists... */
- if (!router) {
+ if (!node) {
log_warn(LD_APP,
"Unrecognized relay in exit address '%s.exit'. Refusing.",
safe_str_client(socks->address));
@@ -1750,7 +1865,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
return -1;
}
/* ...and make sure that it isn't excluded. */
- if (routerset_contains_router(excludeset, router)) {
+ if (routerset_contains_node(excludeset, node)) {
log_warn(LD_APP,
"Excluded relay in exit address '%s.exit'. Refusing.",
safe_str_client(socks->address));
@@ -1825,17 +1940,16 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
if (!conn->use_begindir && !conn->chosen_exit_name && !circ) {
/* see if we can find a suitable enclave exit */
- routerinfo_t *r =
+ const node_t *r =
router_find_exact_exit_enclave(socks->address, socks->port);
if (r) {
log_info(LD_APP,
"Redirecting address %s to exit at enclave router %s",
- safe_str_client(socks->address),
- router_describe(r));
+ safe_str_client(socks->address), node_describe(r));
/* use the hex digest, not nickname, in case there are two
routers with this nickname */
conn->chosen_exit_name =
- tor_strdup(hex_str(r->cache_info.identity_digest, DIGEST_LEN));
+ tor_strdup(hex_str(r->identity, DIGEST_LEN));
conn->chosen_exit_optional = 1;
}
}
@@ -1855,12 +1969,12 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
} else {
tor_fragile_assert();
}
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
if ((circ && connection_ap_handshake_attach_chosen_circuit(
conn, circ, cpath) < 0) ||
(!circ &&
connection_ap_handshake_attach_circuit(conn) < 0)) {
- if (!conn->_base.marked_for_close)
+ if (!base_conn->marked_for_close)
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
return -1;
}
@@ -1870,6 +1984,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
rend_cache_entry_t *entry;
int r;
rend_service_authorization_t *client_auth;
+ rend_data_t *rend_data;
tor_assert(!automap);
if (SOCKS_COMMAND_IS_RESOLVE(socks->command)) {
/* if it's a resolve request, fail it right now, rather than
@@ -1891,16 +2006,17 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
return -1;
}
- conn->rend_data = tor_malloc_zero(sizeof(rend_data_t));
- strlcpy(conn->rend_data->onion_address, socks->address,
- sizeof(conn->rend_data->onion_address));
+ ENTRY_TO_EDGE_CONN(conn)->rend_data = rend_data =
+ tor_malloc_zero(sizeof(rend_data_t));
+ strlcpy(rend_data->onion_address, socks->address,
+ sizeof(rend_data->onion_address));
log_info(LD_REND,"Got a hidden service request for ID '%s'",
- safe_str_client(conn->rend_data->onion_address));
+ safe_str_client(rend_data->onion_address));
/* see if we already have it cached */
- r = rend_cache_lookup_entry(conn->rend_data->onion_address, -1, &entry);
+ r = rend_cache_lookup_entry(rend_data->onion_address, -1, &entry);
if (r<0) {
log_warn(LD_BUG,"Invalid service name '%s'",
- safe_str_client(conn->rend_data->onion_address));
+ safe_str_client(rend_data->onion_address));
connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
return -1;
}
@@ -1911,24 +2027,24 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
/* Look up if we have client authorization for it. */
client_auth = rend_client_lookup_service_authorization(
- conn->rend_data->onion_address);
+ rend_data->onion_address);
if (client_auth) {
log_info(LD_REND, "Using previously configured client authorization "
"for hidden service request.");
- memcpy(conn->rend_data->descriptor_cookie,
+ memcpy(rend_data->descriptor_cookie,
client_auth->descriptor_cookie, REND_DESC_COOKIE_LEN);
- conn->rend_data->auth_type = client_auth->auth_type;
+ rend_data->auth_type = client_auth->auth_type;
}
if (r==0) {
- conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT;
+ base_conn->state = AP_CONN_STATE_RENDDESC_WAIT;
log_info(LD_REND, "Unknown descriptor %s. Fetching.",
- safe_str_client(conn->rend_data->onion_address));
- rend_client_refetch_v2_renddesc(conn->rend_data);
+ safe_str_client(rend_data->onion_address));
+ rend_client_refetch_v2_renddesc(rend_data);
} else { /* r > 0 */
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
log_info(LD_REND, "Descriptor is here. Great.");
if (connection_ap_handshake_attach_circuit(conn) < 0) {
- if (!conn->_base.marked_for_close)
+ if (!base_conn->marked_for_close)
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
return -1;
}
@@ -1950,10 +2066,10 @@ get_pf_socket(void)
#ifdef OPENBSD
/* only works on OpenBSD */
- pf = open("/dev/pf", O_RDONLY);
+ pf = tor_open_cloexec("/dev/pf", O_RDONLY, 0);
#else
/* works on NetBSD and FreeBSD */
- pf = open("/dev/pf", O_RDWR);
+ pf = tor_open_cloexec("/dev/pf", O_RDWR, 0);
#endif
if (pf < 0) {
@@ -1974,7 +2090,7 @@ get_pf_socket(void)
* else return 0.
*/
static int
-connection_ap_get_original_destination(edge_connection_t *conn,
+connection_ap_get_original_destination(entry_connection_t *conn,
socks_request_t *req)
{
#ifdef TRANS_NETFILTER
@@ -1983,9 +2099,9 @@ connection_ap_get_original_destination(edge_connection_t *conn,
socklen_t orig_dst_len = sizeof(orig_dst);
tor_addr_t addr;
- if (getsockopt(conn->_base.s, SOL_IP, SO_ORIGINAL_DST,
+ if (getsockopt(ENTRY_TO_CONN(conn)->s, SOL_IP, SO_ORIGINAL_DST,
(struct sockaddr*)&orig_dst, &orig_dst_len) < 0) {
- int e = tor_socket_errno(conn->_base.s);
+ int e = tor_socket_errno(ENTRY_TO_CONN(conn)->s);
log_warn(LD_NET, "getsockopt() failed: %s", tor_socket_strerror(e));
return -1;
}
@@ -2002,9 +2118,9 @@ connection_ap_get_original_destination(edge_connection_t *conn,
tor_addr_t addr;
int pf = -1;
- if (getsockname(conn->_base.s, (struct sockaddr*)&proxy_addr,
+ if (getsockname(ENTRY_TO_CONN(conn)->s, (struct sockaddr*)&proxy_addr,
&proxy_addr_len) < 0) {
- int e = tor_socket_errno(conn->_base.s);
+ int e = tor_socket_errno(ENTRY_TO_CONN(conn)->s);
log_warn(LD_NET, "getsockname() to determine transocks destination "
"failed: %s", tor_socket_strerror(e));
return -1;
@@ -2016,16 +2132,16 @@ connection_ap_get_original_destination(edge_connection_t *conn,
if (proxy_sa->sa_family == AF_INET) {
struct sockaddr_in *sin = (struct sockaddr_in *)proxy_sa;
pnl.af = AF_INET;
- pnl.saddr.v4.s_addr = tor_addr_to_ipv4n(&conn->_base.addr);
- pnl.sport = htons(conn->_base.port);
+ pnl.saddr.v4.s_addr = tor_addr_to_ipv4n(&ENTRY_TO_CONN(conn)->addr);
+ pnl.sport = htons(ENTRY_TO_CONN(conn)->port);
pnl.daddr.v4.s_addr = sin->sin_addr.s_addr;
pnl.dport = sin->sin_port;
} else if (proxy_sa->sa_family == AF_INET6) {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)proxy_sa;
pnl.af = AF_INET6;
- memcpy(&pnl.saddr.v6, tor_addr_to_in6(&conn->_base.addr),
+ memcpy(&pnl.saddr.v6, tor_addr_to_in6(&ENTRY_TO_CONN(conn)->addr),
sizeof(struct in6_addr));
- pnl.sport = htons(conn->_base.port);
+ pnl.sport = htons(ENTRY_TO_CONN(conn)->port);
memcpy(&pnl.daddr.v6, &sin6->sin6_addr, sizeof(struct in6_addr));
pnl.dport = sin6->sin6_port;
} else {
@@ -2076,38 +2192,43 @@ connection_ap_get_original_destination(edge_connection_t *conn,
* else return 0.
*/
static int
-connection_ap_handshake_process_socks(edge_connection_t *conn)
+connection_ap_handshake_process_socks(entry_connection_t *conn)
{
socks_request_t *socks;
int sockshere;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
+ int had_reply = 0;
+ connection_t *base_conn = ENTRY_TO_CONN(conn);
tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_AP);
- tor_assert(conn->_base.state == AP_CONN_STATE_SOCKS_WAIT);
+ tor_assert(base_conn->type == CONN_TYPE_AP);
+ tor_assert(base_conn->state == AP_CONN_STATE_SOCKS_WAIT);
tor_assert(conn->socks_request);
socks = conn->socks_request;
log_debug(LD_APP,"entered.");
- sockshere = fetch_from_buf_socks(conn->_base.inbuf, socks,
- options->TestSocks, options->SafeSocks);
+ IF_HAS_BUFFEREVENT(base_conn, {
+ struct evbuffer *input = bufferevent_get_input(base_conn->bufev);
+ sockshere = fetch_from_evbuffer_socks(input, socks,
+ options->TestSocks, options->SafeSocks);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ sockshere = fetch_from_buf_socks(base_conn->inbuf, socks,
+ options->TestSocks, options->SafeSocks);
+ };
+
+ if (socks->replylen) {
+ had_reply = 1;
+ connection_write_to_buf((const char*)socks->reply, socks->replylen,
+ base_conn);
+ socks->replylen = 0;
+ }
+
if (sockshere == 0) {
- if (socks->replylen) {
- connection_write_to_buf(socks->reply, socks->replylen, TO_CONN(conn));
- /* zero it out so we can do another round of negotiation */
- socks->replylen = 0;
- } else {
- log_debug(LD_APP,"socks handshake not all here yet.");
- }
+ log_debug(LD_APP,"socks handshake not all here yet.");
return 0;
} else if (sockshere == -1) {
- if (socks->replylen) { /* we should send reply back */
- log_debug(LD_APP,"reply is already set for us. Using it.");
- connection_ap_handshake_socks_reply(conn, socks->reply, socks->replylen,
- END_STREAM_REASON_SOCKSPROTOCOL);
-
- } else {
+ if (!had_reply) {
log_warn(LD_APP,"Fetching socks handshake failed. Closing.");
connection_ap_handshake_socks_reply(conn, NULL, 0,
END_STREAM_REASON_SOCKSPROTOCOL);
@@ -2134,12 +2255,11 @@ connection_ap_handshake_process_socks(edge_connection_t *conn)
* for close), else return 0.
*/
int
-connection_ap_process_transparent(edge_connection_t *conn)
+connection_ap_process_transparent(entry_connection_t *conn)
{
socks_request_t *socks;
tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_AP);
tor_assert(conn->socks_request);
socks = conn->socks_request;
@@ -2175,7 +2295,7 @@ connection_ap_process_transparent(edge_connection_t *conn)
* for close), else return 0.
*/
static int
-connection_ap_process_natd(edge_connection_t *conn)
+connection_ap_process_natd(entry_connection_t *conn)
{
char tmp_buf[36], *tbuf, *daddr;
size_t tlen = 30;
@@ -2183,8 +2303,7 @@ connection_ap_process_natd(edge_connection_t *conn)
socks_request_t *socks;
tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_AP);
- tor_assert(conn->_base.state == AP_CONN_STATE_NATD_WAIT);
+ tor_assert(ENTRY_TO_CONN(conn)->state == AP_CONN_STATE_NATD_WAIT);
tor_assert(conn->socks_request);
socks = conn->socks_request;
@@ -2192,7 +2311,7 @@ connection_ap_process_natd(edge_connection_t *conn)
/* look for LF-terminated "[DEST ip_addr port]"
* where ip_addr is a dotted-quad and port is in string form */
- err = fetch_from_buf_line(conn->_base.inbuf, tmp_buf, &tlen);
+ err = connection_fetch_from_buf_line(ENTRY_TO_CONN(conn), tmp_buf, &tlen);
if (err == 0)
return 0;
if (err < 0) {
@@ -2236,7 +2355,7 @@ connection_ap_process_natd(edge_connection_t *conn)
control_event_stream_status(conn, STREAM_EVENT_NEW, 0);
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CIRCUIT_WAIT;
return connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL);
}
@@ -2266,28 +2385,46 @@ get_unique_stream_id_by_circ(origin_circuit_t *circ)
return test_stream_id;
}
+/** Return true iff <b>conn</b> is linked to a circuit and configured to use
+ * an exit that supports optimistic data. */
+static int
+connection_ap_supports_optimistic_data(const entry_connection_t *conn)
+{
+ const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
+ /* We can only send optimistic data if we're connected to an open
+ general circuit. */
+ if (edge_conn->on_circuit == NULL ||
+ edge_conn->on_circuit->state != CIRCUIT_STATE_OPEN ||
+ edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL)
+ return 0;
+
+ return conn->may_use_optimistic_data;
+}
+
/** Write a relay begin cell, using destaddr and destport from ap_conn's
* socks_request field, and send it down circ.
*
* If ap_conn is broken, mark it for close and return -1. Else return 0.
*/
int
-connection_ap_handshake_send_begin(edge_connection_t *ap_conn)
+connection_ap_handshake_send_begin(entry_connection_t *ap_conn)
{
char payload[CELL_PAYLOAD_SIZE];
int payload_len;
int begin_type;
origin_circuit_t *circ;
- tor_assert(ap_conn->on_circuit);
- circ = TO_ORIGIN_CIRCUIT(ap_conn->on_circuit);
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(ap_conn);
+ connection_t *base_conn = TO_CONN(edge_conn);
+ tor_assert(edge_conn->on_circuit);
+ circ = TO_ORIGIN_CIRCUIT(edge_conn->on_circuit);
- tor_assert(ap_conn->_base.type == CONN_TYPE_AP);
- tor_assert(ap_conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
+ tor_assert(base_conn->type == CONN_TYPE_AP);
+ tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(ap_conn->socks_request);
tor_assert(SOCKS_COMMAND_IS_CONNECT(ap_conn->socks_request->command));
- ap_conn->stream_id = get_unique_stream_id_by_circ(circ);
- if (ap_conn->stream_id==0) {
+ edge_conn->stream_id = get_unique_stream_id_by_circ(circ);
+ if (edge_conn->stream_id==0) {
/* XXXX023 Instead of closing this stream, we should make it get
* retried on another circuit. */
connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
@@ -2305,8 +2442,10 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn)
ap_conn->socks_request->port);
payload_len = (int)strlen(payload)+1;
- log_debug(LD_APP,
- "Sending relay cell to begin stream %d.", ap_conn->stream_id);
+ log_info(LD_APP,
+ "Sending relay cell %d to begin stream %d.",
+ (int)ap_conn->use_begindir,
+ edge_conn->stream_id);
begin_type = ap_conn->use_begindir ?
RELAY_COMMAND_BEGIN_DIR : RELAY_COMMAND_BEGIN;
@@ -2314,17 +2453,31 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn)
tor_assert(circ->build_state->onehop_tunnel == 0);
}
- if (connection_edge_send_command(ap_conn, begin_type,
+ if (connection_edge_send_command(edge_conn, begin_type,
begin_type == RELAY_COMMAND_BEGIN ? payload : NULL,
begin_type == RELAY_COMMAND_BEGIN ? payload_len : 0) < 0)
return -1; /* circuit is closed, don't continue */
- ap_conn->package_window = STREAMWINDOW_START;
- ap_conn->deliver_window = STREAMWINDOW_START;
- ap_conn->_base.state = AP_CONN_STATE_CONNECT_WAIT;
+ edge_conn->package_window = STREAMWINDOW_START;
+ edge_conn->deliver_window = STREAMWINDOW_START;
+ base_conn->state = AP_CONN_STATE_CONNECT_WAIT;
log_info(LD_APP,"Address/port sent, ap socket %d, n_circ_id %d",
- ap_conn->_base.s, circ->_base.n_circ_id);
+ base_conn->s, circ->_base.n_circ_id);
control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT, 0);
+
+ /* If there's queued-up data, send it now */
+ if ((connection_get_inbuf_len(base_conn) ||
+ ap_conn->sending_optimistic_data) &&
+ connection_ap_supports_optimistic_data(ap_conn)) {
+ log_info(LD_APP, "Sending up to %ld + %ld bytes of queued-up data",
+ (long)connection_get_inbuf_len(base_conn),
+ ap_conn->sending_optimistic_data ?
+ (long)generic_buffer_len(ap_conn->sending_optimistic_data) : 0);
+ if (connection_edge_package_raw_inbuf(edge_conn, 1, NULL) < 0) {
+ connection_mark_for_close(base_conn);
+ }
+ }
+
return 0;
}
@@ -2334,25 +2487,27 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn)
* If ap_conn is broken, mark it for close and return -1. Else return 0.
*/
int
-connection_ap_handshake_send_resolve(edge_connection_t *ap_conn)
+connection_ap_handshake_send_resolve(entry_connection_t *ap_conn)
{
int payload_len, command;
const char *string_addr;
char inaddr_buf[REVERSE_LOOKUP_NAME_BUF_LEN];
origin_circuit_t *circ;
- tor_assert(ap_conn->on_circuit);
- circ = TO_ORIGIN_CIRCUIT(ap_conn->on_circuit);
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(ap_conn);
+ connection_t *base_conn = TO_CONN(edge_conn);
+ tor_assert(edge_conn->on_circuit);
+ circ = TO_ORIGIN_CIRCUIT(edge_conn->on_circuit);
- tor_assert(ap_conn->_base.type == CONN_TYPE_AP);
- tor_assert(ap_conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT);
+ tor_assert(base_conn->type == CONN_TYPE_AP);
+ tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
tor_assert(ap_conn->socks_request);
tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL);
command = ap_conn->socks_request->command;
tor_assert(SOCKS_COMMAND_IS_RESOLVE(command));
- ap_conn->stream_id = get_unique_stream_id_by_circ(circ);
- if (ap_conn->stream_id==0) {
+ edge_conn->stream_id = get_unique_stream_id_by_circ(circ);
+ if (edge_conn->stream_id==0) {
/* XXXX023 Instead of closing this stream, we should make it get
* retried on another circuit. */
connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL);
@@ -2397,18 +2552,18 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn)
}
log_debug(LD_APP,
- "Sending relay cell to begin stream %d.", ap_conn->stream_id);
+ "Sending relay cell to begin stream %d.", edge_conn->stream_id);
- if (connection_edge_send_command(ap_conn,
+ if (connection_edge_send_command(edge_conn,
RELAY_COMMAND_RESOLVE,
string_addr, payload_len) < 0)
return -1; /* circuit is closed, don't continue */
- tor_free(ap_conn->_base.address); /* Maybe already set by dnsserv. */
- ap_conn->_base.address = tor_strdup("(Tor_internal)");
- ap_conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
+ tor_free(base_conn->address); /* Maybe already set by dnsserv. */
+ base_conn->address = tor_strdup("(Tor_internal)");
+ base_conn->state = AP_CONN_STATE_RESOLVE_WAIT;
log_info(LD_APP,"Address sent for resolve, ap socket %d, n_circ_id %d",
- ap_conn->_base.s, circ->_base.n_circ_id);
+ base_conn->s, circ->_base.n_circ_id);
control_event_stream_status(ap_conn, STREAM_EVENT_NEW, 0);
control_event_stream_status(ap_conn, STREAM_EVENT_SENT_RESOLVE, 0);
return 0;
@@ -2419,19 +2574,25 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn)
* and call connection_ap_handshake_attach_circuit(conn) on it.
*
* Return the other end of the linked connection pair, or -1 if error.
+ * DOCDOC partner.
*/
-edge_connection_t *
-connection_ap_make_link(char *address, uint16_t port,
- const char *digest, int use_begindir, int want_onehop)
+entry_connection_t *
+connection_ap_make_link(connection_t *partner,
+ char *address, uint16_t port,
+ const char *digest,
+ int session_group, int isolation_flags,
+ int use_begindir, int want_onehop)
{
- edge_connection_t *conn;
+ entry_connection_t *conn;
+ connection_t *base_conn;
log_info(LD_APP,"Making internal %s tunnel to %s:%d ...",
want_onehop ? "direct" : "anonymized",
safe_str_client(address), port);
- conn = edge_connection_new(CONN_TYPE_AP, AF_INET);
- conn->_base.linked = 1; /* so that we can add it safely below. */
+ conn = entry_connection_new(CONN_TYPE_AP, AF_INET);
+ base_conn = ENTRY_TO_CONN(conn);
+ base_conn->linked = 1; /* so that we can add it safely below. */
/* populate conn->socks_request */
@@ -2452,22 +2613,30 @@ connection_ap_make_link(char *address, uint16_t port,
digest, DIGEST_LEN);
}
- conn->_base.address = tor_strdup("(Tor_internal)");
- tor_addr_make_unspec(&conn->_base.addr);
- conn->_base.port = 0;
+ /* Populate isolation fields. */
+ conn->socks_request->listener_type = CONN_TYPE_DIR_LISTENER;
+ conn->original_dest_address = tor_strdup(address);
+ conn->session_group = session_group;
+ conn->isolation_flags = isolation_flags;
+
+ base_conn->address = tor_strdup("(Tor_internal)");
+ tor_addr_make_unspec(&base_conn->addr);
+ base_conn->port = 0;
- if (connection_add(TO_CONN(conn)) < 0) { /* no space, forget it */
- connection_free(TO_CONN(conn));
+ connection_link_connections(partner, base_conn);
+
+ if (connection_add(base_conn) < 0) { /* no space, forget it */
+ connection_free(base_conn);
return NULL;
}
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
control_event_stream_status(conn, STREAM_EVENT_NEW, 0);
/* attaching to a dirty circuit is fine */
if (connection_ap_handshake_attach_circuit(conn) < 0) {
- if (!conn->_base.marked_for_close)
+ if (!base_conn->marked_for_close)
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
return NULL;
}
@@ -2480,7 +2649,7 @@ connection_ap_make_link(char *address, uint16_t port,
* or resolve error. Takes the same arguments as does
* connection_ap_handshake_socks_resolved(). */
static void
-tell_controller_about_resolved_result(edge_connection_t *conn,
+tell_controller_about_resolved_result(entry_connection_t *conn,
int answer_type,
size_t answer_len,
const char *answer,
@@ -2492,13 +2661,11 @@ tell_controller_about_resolved_result(edge_connection_t *conn,
answer_type == RESOLVED_TYPE_HOSTNAME)) {
return; /* we already told the controller. */
} else if (answer_type == RESOLVED_TYPE_IPV4 && answer_len >= 4) {
- struct in_addr in;
- char buf[INET_NTOA_BUF_LEN];
- in.s_addr = get_uint32(answer);
- tor_inet_ntoa(&in, buf, sizeof(buf));
+ char *cp = tor_dup_ip(get_uint32(answer));
control_event_address_mapped(conn->socks_request->address,
- buf, expires, NULL);
- } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len <256) {
+ cp, expires, NULL);
+ tor_free(cp);
+ } else if (answer_type == RESOLVED_TYPE_HOSTNAME && answer_len < 256) {
char *cp = tor_strndup(answer, answer_len);
control_event_address_mapped(conn->socks_request->address,
cp, expires, NULL);
@@ -2521,7 +2688,7 @@ tell_controller_about_resolved_result(edge_connection_t *conn,
/* XXXX023 the use of the ttl and expires fields is nutty. Let's make this
* interface and those that use it less ugly. */
void
-connection_ap_handshake_socks_resolved(edge_connection_t *conn,
+connection_ap_handshake_socks_resolved(entry_connection_t *conn,
int answer_type,
size_t answer_len,
const uint8_t *answer,
@@ -2546,7 +2713,7 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn,
}
}
- if (conn->is_dns_request) {
+ if (ENTRY_TO_EDGE_CONN(conn)->is_dns_request) {
if (conn->dns_server_request) {
/* We had a request on our DNS port: answer it. */
dnsserv_resolved(conn, answer_type, answer_len, (char*)answer, ttl);
@@ -2626,7 +2793,7 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn,
* be 0 or REASON_DONE. Send endreason to the controller, if appropriate.
*/
void
-connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
+connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
size_t replylen, int endreason)
{
char buf[256];
@@ -2645,7 +2812,7 @@ connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
return;
}
if (replylen) { /* we already have a reply in mind */
- connection_write_to_buf(reply, replylen, TO_CONN(conn));
+ connection_write_to_buf(reply, replylen, ENTRY_TO_CONN(conn));
conn->socks_request->has_finished = 1;
return;
}
@@ -2653,7 +2820,7 @@ connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
memset(buf,0,SOCKS4_NETWORK_LEN);
buf[1] = (status==SOCKS5_SUCCEEDED ? SOCKS4_GRANTED : SOCKS4_REJECT);
/* leave version, destport, destip zero */
- connection_write_to_buf(buf, SOCKS4_NETWORK_LEN, TO_CONN(conn));
+ connection_write_to_buf(buf, SOCKS4_NETWORK_LEN, ENTRY_TO_CONN(conn));
} else if (conn->socks_request->socks_version == 5) {
buf[0] = 5; /* version 5 */
buf[1] = (char)status;
@@ -2661,7 +2828,7 @@ connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
buf[3] = 1; /* ipv4 addr */
memset(buf+4,0,6); /* Set external addr/port to 0.
The spec doesn't seem to say what to do here. -RD */
- connection_write_to_buf(buf,10,TO_CONN(conn));
+ connection_write_to_buf(buf,10,ENTRY_TO_CONN(conn));
}
/* If socks_version isn't 4 or 5, don't send anything.
* This can happen in the case of AP bridges. */
@@ -2695,7 +2862,7 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ)
char *address=NULL;
uint16_t port;
or_circuit_t *or_circ = NULL;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
assert_circuit_ok(circ);
if (!CIRCUIT_IS_ORIGIN(circ))
@@ -2978,12 +3145,13 @@ connection_exit_connect(edge_connection_t *edge_conn)
}
conn->state = EXIT_CONN_STATE_OPEN;
- if (connection_wants_to_flush(conn)) {
+ if (connection_get_outbuf_len(conn)) {
/* in case there are any queued data cells */
log_warn(LD_BUG,"newly connected conn had data waiting!");
// connection_start_writing(conn);
}
- connection_watch_events(conn, READ_EVENT);
+ IF_HAS_NO_BUFFEREVENT(conn)
+ connection_watch_events(conn, READ_EVENT);
/* also, deliver a 'connected' cell back through the circuit. */
if (connection_edge_is_rendezvous_stream(edge_conn)) {
@@ -3093,12 +3261,11 @@ connection_edge_is_rendezvous_stream(edge_connection_t *conn)
* resolved.)
*/
int
-connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
+connection_ap_can_use_exit(const entry_connection_t *conn, const node_t *exit)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert(conn);
- tor_assert(conn->_base.type == CONN_TYPE_AP);
tor_assert(conn->socks_request);
tor_assert(exit);
@@ -3106,10 +3273,10 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
* make sure the exit node of the existing circuit matches exactly.
*/
if (conn->chosen_exit_name) {
- routerinfo_t *chosen_exit =
- router_get_by_nickname(conn->chosen_exit_name, 1);
- if (!chosen_exit || tor_memneq(chosen_exit->cache_info.identity_digest,
- exit->cache_info.identity_digest, DIGEST_LEN)) {
+ const node_t *chosen_exit =
+ node_get_by_nickname(conn->chosen_exit_name, 1);
+ if (!chosen_exit || tor_memneq(chosen_exit->identity,
+ exit->identity, DIGEST_LEN)) {
/* doesn't match */
// log_debug(LD_APP,"Requested node '%s', considering node '%s'. No.",
// conn->chosen_exit_name, exit->nickname);
@@ -3120,12 +3287,13 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
if (conn->socks_request->command == SOCKS_COMMAND_CONNECT &&
!conn->use_begindir) {
struct in_addr in;
- uint32_t addr = 0;
+ tor_addr_t addr, *addrp = NULL;
addr_policy_result_t r;
- if (tor_inet_aton(conn->socks_request->address, &in))
- addr = ntohl(in.s_addr);
- r = compare_addr_to_addr_policy(addr, conn->socks_request->port,
- exit->exit_policy);
+ if (tor_inet_aton(conn->socks_request->address, &in)) {
+ tor_addr_from_in(&addr, &in);
+ addrp = &addr;
+ }
+ r = compare_tor_addr_to_node_policy(addrp, conn->socks_request->port,exit);
if (r == ADDR_POLICY_REJECTED)
return 0; /* We know the address, and the exit policy rejects it. */
if (r == ADDR_POLICY_PROBABLY_REJECTED && !conn->chosen_exit_name)
@@ -3133,17 +3301,11 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit)
* addresses with this port. Since the user didn't ask for
* this node, err on the side of caution. */
} else if (SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) {
- /* Can't support reverse lookups without eventdns. */
- if (conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR &&
- exit->has_old_dnsworkers)
- return 0;
-
/* Don't send DNS requests to non-exit servers by default. */
- if (!conn->chosen_exit_name && policy_is_reject_star(exit->exit_policy))
+ if (!conn->chosen_exit_name && node_exit_policy_rejects_all(exit))
return 0;
}
- if (options->_ExcludeExitNodesUnion &&
- routerset_contains_router(options->_ExcludeExitNodesUnion, exit)) {
+ if (routerset_contains_node(options->_ExcludeExitNodesUnion, exit)) {
/* Not a suitable exit. Refuse it. */
return 0;
}
@@ -3198,3 +3360,205 @@ parse_extended_hostname(char *address, int allowdotexit)
return BAD_HOSTNAME;
}
+/** Return true iff the (possibly NULL) <b>alen</b>-byte chunk of memory at
+ * <b>a</b> is equal to the (possibly NULL) <b>blen</b>-byte chunk of memory
+ * at <b>b</b>. */
+static int
+memeq_opt(const char *a, size_t alen, const char *b, size_t blen)
+{
+ if (a == NULL) {
+ return (b == NULL);
+ } else if (b == NULL) {
+ return 0;
+ } else if (alen != blen) {
+ return 0;
+ } else {
+ return tor_memeq(a, b, alen);
+ }
+}
+
+/**
+ * Return true iff none of the isolation flags and fields in <b>conn</b>
+ * should prevent it from being attached to <b>circ</b>.
+ */
+int
+connection_edge_compatible_with_circuit(const entry_connection_t *conn,
+ const origin_circuit_t *circ)
+{
+ const uint8_t iso = conn->isolation_flags;
+ const socks_request_t *sr = conn->socks_request;
+
+ /* If circ has never been used for an isolated connection, we can
+ * totally use it for this one. */
+ if (!circ->isolation_values_set)
+ return 1;
+
+ /* If circ has been used for connections having more than one value
+ * for some field f, it will have the corresponding bit set in
+ * isolation_flags_mixed. If isolation_flags_mixed has any bits
+ * in common with iso, then conn must be isolated from at least
+ * one stream that has been attached to circ. */
+ if ((iso & circ->isolation_flags_mixed) != 0) {
+ /* For at least one field where conn is isolated, the circuit
+ * already has mixed streams. */
+ return 0;
+ }
+
+ if (! conn->original_dest_address) {
+ log_warn(LD_BUG, "Reached connection_edge_compatible_with_circuit without "
+ "having set conn->original_dest_address");
+ ((entry_connection_t*)conn)->original_dest_address =
+ tor_strdup(conn->socks_request->address);
+ }
+
+ if ((iso & ISO_STREAM) &&
+ (circ->associated_isolated_stream_global_id !=
+ ENTRY_TO_CONN(conn)->global_identifier))
+ return 0;
+
+ if ((iso & ISO_DESTPORT) && conn->socks_request->port != circ->dest_port)
+ return 0;
+ if ((iso & ISO_DESTADDR) &&
+ strcasecmp(conn->original_dest_address, circ->dest_address))
+ return 0;
+ if ((iso & ISO_SOCKSAUTH) &&
+ (! memeq_opt(sr->username, sr->usernamelen,
+ circ->socks_username, circ->socks_username_len) ||
+ ! memeq_opt(sr->password, sr->passwordlen,
+ circ->socks_password, circ->socks_password_len)))
+ return 0;
+ if ((iso & ISO_CLIENTPROTO) &&
+ (conn->socks_request->listener_type != circ->client_proto_type ||
+ conn->socks_request->socks_version != circ->client_proto_socksver))
+ return 0;
+ if ((iso & ISO_CLIENTADDR) &&
+ !tor_addr_eq(&ENTRY_TO_CONN(conn)->addr, &circ->client_addr))
+ return 0;
+ if ((iso & ISO_SESSIONGRP) && conn->session_group != circ->session_group)
+ return 0;
+ if ((iso & ISO_NYM_EPOCH) && conn->nym_epoch != circ->nym_epoch)
+ return 0;
+
+ return 1;
+}
+
+/**
+ * If <b>dry_run</b> is false, update <b>circ</b>'s isolation flags and fields
+ * to reflect having had <b>conn</b> attached to it, and return 0. Otherwise,
+ * if <b>dry_run</b> is true, then make no changes to <b>circ</b>, and return
+ * a bitfield of isolation flags that we would have to set in
+ * isolation_flags_mixed to add <b>conn</b> to <b>circ</b>, or -1 if
+ * <b>circ</b> has had no streams attached to it.
+ */
+int
+connection_edge_update_circuit_isolation(const entry_connection_t *conn,
+ origin_circuit_t *circ,
+ int dry_run)
+{
+ const socks_request_t *sr = conn->socks_request;
+ if (! conn->original_dest_address) {
+ log_warn(LD_BUG, "Reached connection_update_circuit_isolation without "
+ "having set conn->original_dest_address");
+ ((entry_connection_t*)conn)->original_dest_address =
+ tor_strdup(conn->socks_request->address);
+ }
+
+ if (!circ->isolation_values_set) {
+ if (dry_run)
+ return -1;
+ circ->associated_isolated_stream_global_id =
+ ENTRY_TO_CONN(conn)->global_identifier;
+ circ->dest_port = conn->socks_request->port;
+ circ->dest_address = tor_strdup(conn->original_dest_address);
+ circ->client_proto_type = conn->socks_request->listener_type;
+ circ->client_proto_socksver = conn->socks_request->socks_version;
+ tor_addr_copy(&circ->client_addr, &ENTRY_TO_CONN(conn)->addr);
+ circ->session_group = conn->session_group;
+ circ->nym_epoch = conn->nym_epoch;
+ circ->socks_username = sr->username ?
+ tor_memdup(sr->username, sr->usernamelen) : NULL;
+ circ->socks_password = sr->password ?
+ tor_memdup(sr->password, sr->passwordlen) : NULL;
+ circ->socks_username_len = sr->usernamelen;
+ circ->socks_password_len = sr->passwordlen;
+
+ circ->isolation_values_set = 1;
+ return 0;
+ } else {
+ uint8_t mixed = 0;
+ if (conn->socks_request->port != circ->dest_port)
+ mixed |= ISO_DESTPORT;
+ if (strcasecmp(conn->original_dest_address, circ->dest_address))
+ mixed |= ISO_DESTADDR;
+ if (!memeq_opt(sr->username, sr->usernamelen,
+ circ->socks_username, circ->socks_username_len) ||
+ !memeq_opt(sr->password, sr->passwordlen,
+ circ->socks_password, circ->socks_password_len))
+ mixed |= ISO_SOCKSAUTH;
+ if ((conn->socks_request->listener_type != circ->client_proto_type ||
+ conn->socks_request->socks_version != circ->client_proto_socksver))
+ mixed |= ISO_CLIENTPROTO;
+ if (!tor_addr_eq(&ENTRY_TO_CONN(conn)->addr, &circ->client_addr))
+ mixed |= ISO_CLIENTADDR;
+ if (conn->session_group != circ->session_group)
+ mixed |= ISO_SESSIONGRP;
+ if (conn->nym_epoch != circ->nym_epoch)
+ mixed |= ISO_NYM_EPOCH;
+
+ if (dry_run)
+ return mixed;
+
+ if ((mixed & conn->isolation_flags) != 0) {
+ log_warn(LD_BUG, "Updating a circuit with seemingly incompatible "
+ "isolation flags.");
+ }
+ circ->isolation_flags_mixed |= mixed;
+ return 0;
+ }
+}
+
+/**
+ * Clear the isolation settings on <b>circ</b>.
+ *
+ * This only works on an open circuit that has never had a stream attached to
+ * it, and whose isolation settings are hypothetical. (We set hypothetical
+ * isolation settings on circuits as we're launching them, so that we
+ * know whether they can handle more streams or whether we need to launch
+ * even more circuits. Once the circuit is open, if it turns out that
+ * we no longer have any streams to attach to it, we clear the isolation flags
+ * and data so that other streams can have a chance.)
+ */
+void
+circuit_clear_isolation(origin_circuit_t *circ)
+{
+ if (circ->isolation_any_streams_attached) {
+ log_warn(LD_BUG, "Tried to clear the isolation status of a dirty circuit");
+ return;
+ }
+ if (TO_CIRCUIT(circ)->state != CIRCUIT_STATE_OPEN) {
+ log_warn(LD_BUG, "Tried to clear the isolation status of a non-open "
+ "circuit");
+ return;
+ }
+
+ circ->isolation_values_set = 0;
+ circ->isolation_flags_mixed = 0;
+ circ->associated_isolated_stream_global_id = 0;
+ circ->client_proto_type = 0;
+ circ->client_proto_socksver = 0;
+ circ->dest_port = 0;
+ tor_addr_make_unspec(&circ->client_addr);
+ tor_free(circ->dest_address);
+ circ->session_group = -1;
+ circ->nym_epoch = 0;
+ if (circ->socks_username) {
+ memset(circ->socks_username, 0x11, circ->socks_username_len);
+ tor_free(circ->socks_username);
+ }
+ if (circ->socks_password) {
+ memset(circ->socks_password, 0x05, circ->socks_password_len);
+ tor_free(circ->socks_password);
+ }
+ circ->socks_username_len = circ->socks_password_len = 0;
+}
+
diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h
index 8ba2fafd0..830667e60 100644
--- a/src/or/connection_edge.h
+++ b/src/or/connection_edge.h
@@ -15,7 +15,7 @@
#define connection_mark_unattached_ap(conn, endreason) \
_connection_mark_unattached_ap((conn), (endreason), __LINE__, _SHORT_FILE_)
-void _connection_mark_unattached_ap(edge_connection_t *conn, int endreason,
+void _connection_mark_unattached_ap(entry_connection_t *conn, int endreason,
int line, const char *file);
int connection_edge_reached_eof(edge_connection_t *conn);
int connection_edge_process_inbuf(edge_connection_t *conn,
@@ -27,16 +27,22 @@ int connection_edge_flushed_some(edge_connection_t *conn);
int connection_edge_finished_flushing(edge_connection_t *conn);
int connection_edge_finished_connecting(edge_connection_t *conn);
-int connection_ap_handshake_send_begin(edge_connection_t *ap_conn);
-int connection_ap_handshake_send_resolve(edge_connection_t *ap_conn);
+void connection_ap_about_to_close(entry_connection_t *edge_conn);
+void connection_exit_about_to_close(edge_connection_t *edge_conn);
-edge_connection_t *connection_ap_make_link(char *address, uint16_t port,
+int connection_ap_handshake_send_begin(entry_connection_t *ap_conn);
+int connection_ap_handshake_send_resolve(entry_connection_t *ap_conn);
+
+entry_connection_t *connection_ap_make_link(connection_t *partner,
+ char *address, uint16_t port,
const char *digest,
+ int session_group,
+ int isolation_flags,
int use_begindir, int want_onehop);
-void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply,
+void connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply,
size_t replylen,
int endreason);
-void connection_ap_handshake_socks_resolved(edge_connection_t *conn,
+void connection_ap_handshake_socks_resolved(entry_connection_t *conn,
int answer_type,
size_t answer_len,
const uint8_t *answer,
@@ -47,22 +53,23 @@ int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ);
void connection_exit_connect(edge_connection_t *conn);
int connection_edge_is_rendezvous_stream(edge_connection_t *conn);
-int connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit);
+int connection_ap_can_use_exit(const entry_connection_t *conn,
+ const node_t *exit);
void connection_ap_expire_beginning(void);
void connection_ap_attach_pending(void);
void connection_ap_fail_onehop(const char *failed_digest,
cpath_build_state_t *build_state);
void circuit_discard_optional_exit_enclaves(extend_info_t *info);
-int connection_ap_detach_retriable(edge_connection_t *conn,
+int connection_ap_detach_retriable(entry_connection_t *conn,
origin_circuit_t *circ,
int reason);
-int connection_ap_process_transparent(edge_connection_t *conn);
+int connection_ap_process_transparent(entry_connection_t *conn);
int address_is_invalid_destination(const char *address, int client);
void addressmap_init(void);
-void addressmap_clear_excluded_trackexithosts(or_options_t *options);
-void addressmap_clear_invalid_automaps(or_options_t *options);
+void addressmap_clear_excluded_trackexithosts(const or_options_t *options);
+void addressmap_clear_invalid_automaps(const or_options_t *options);
void addressmap_clean(time_t now);
void addressmap_clear_configured(void);
void addressmap_clear_transient(void);
@@ -81,10 +88,10 @@ void client_dns_set_addressmap(const char *address, uint32_t val,
const char *addressmap_register_virtual_address(int type, char *new_address);
void addressmap_get_mappings(smartlist_t *sl, time_t min_expires,
time_t max_expires, int want_expiry);
-int connection_ap_rewrite_and_attach_if_allowed(edge_connection_t *conn,
+int connection_ap_rewrite_and_attach_if_allowed(entry_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath);
-int connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn,
+int connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn,
origin_circuit_t *circ,
crypt_path_t *cpath);
@@ -98,5 +105,12 @@ hostname_type_t parse_extended_hostname(char *address, int allowdotexit);
int get_pf_socket(void);
#endif
+int connection_edge_compatible_with_circuit(const entry_connection_t *conn,
+ const origin_circuit_t *circ);
+int connection_edge_update_circuit_isolation(const entry_connection_t *conn,
+ origin_circuit_t *circ,
+ int dry_run);
+void circuit_clear_isolation(origin_circuit_t *circ);
+
#endif
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index c019f6592..29f0f8de7 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -13,6 +13,7 @@
#include "or.h"
#include "buffers.h"
#include "circuitbuild.h"
+#include "circuitlist.h"
#include "command.h"
#include "config.h"
#include "connection.h"
@@ -22,12 +23,17 @@
#include "geoip.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "reasons.h"
#include "relay.h"
#include "rephist.h"
#include "router.h"
#include "routerlist.h"
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent_ssl.h>
+#endif
+
static int connection_tls_finish_handshake(or_connection_t *conn);
static int connection_or_process_cells_from_inbuf(or_connection_t *conn);
static int connection_or_send_versions(or_connection_t *conn);
@@ -37,6 +43,14 @@ static int connection_or_check_valid_tls_handshake(or_connection_t *conn,
int started_here,
char *digest_rcvd_out);
+static void connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn);
+
+#ifdef USE_BUFFEREVENTS
+static void connection_or_handle_event_cb(struct bufferevent *bufev,
+ short event, void *arg);
+#include <event2/buffer.h>/*XXXX REMOVE */
+#endif
+
/**************************************************************/
/** Map from identity digest of connected OR or desired OR to a connection_t
@@ -136,6 +150,142 @@ connection_or_set_identity_digest(or_connection_t *conn, const char *digest)
#endif
}
+/**************************************************************/
+
+/** Map from a string describing what a non-open OR connection was doing when
+ * failed, to an intptr_t describing the count of connections that failed that
+ * way. Note that the count is stored _as_ the pointer.
+ */
+static strmap_t *broken_connection_counts;
+
+/** If true, do not record information in <b>broken_connection_counts</b>. */
+static int disable_broken_connection_counts = 0;
+
+/** Record that an OR connection failed in <b>state</b>. */
+static void
+note_broken_connection(const char *state)
+{
+ void *ptr;
+ intptr_t val;
+ if (disable_broken_connection_counts)
+ return;
+
+ if (!broken_connection_counts)
+ broken_connection_counts = strmap_new();
+
+ ptr = strmap_get(broken_connection_counts, state);
+ val = (intptr_t)ptr;
+ val++;
+ ptr = (void*)val;
+ strmap_set(broken_connection_counts, state, ptr);
+}
+
+/** Forget all recorded states for failed connections. If
+ * <b>stop_recording</b> is true, don't record any more. */
+void
+clear_broken_connection_map(int stop_recording)
+{
+ if (broken_connection_counts)
+ strmap_free(broken_connection_counts, NULL);
+ broken_connection_counts = NULL;
+ if (stop_recording)
+ disable_broken_connection_counts = 1;
+}
+
+/** Write a detailed description the state of <b>orconn</b> into the
+ * <b>buflen</b>-byte buffer at <b>buf</b>. This description includes not
+ * only the OR-conn level state but also the TLS state. It's useful for
+ * diagnosing broken handshakes. */
+static void
+connection_or_get_state_description(or_connection_t *orconn,
+ char *buf, size_t buflen)
+{
+ connection_t *conn = TO_CONN(orconn);
+ const char *conn_state;
+ char tls_state[256];
+
+ tor_assert(conn->type == CONN_TYPE_OR);
+
+ conn_state = conn_state_to_string(conn->type, conn->state);
+ tor_tls_get_state_description(orconn->tls, tls_state, sizeof(tls_state));
+
+ tor_snprintf(buf, buflen, "%s with SSL state %s", conn_state, tls_state);
+}
+
+/** Record the current state of <b>orconn</b> as the state of a broken
+ * connection. */
+static void
+connection_or_note_state_when_broken(or_connection_t *orconn)
+{
+ char buf[256];
+ if (disable_broken_connection_counts)
+ return;
+ connection_or_get_state_description(orconn, buf, sizeof(buf));
+ log_info(LD_HANDSHAKE,"Connection died in state '%s'", buf);
+ note_broken_connection(buf);
+}
+
+/** Helper type used to sort connection states and find the most frequent. */
+typedef struct broken_state_count_t {
+ intptr_t count;
+ const char *state;
+} broken_state_count_t;
+
+/** Helper function used to sort broken_state_count_t by frequency. */
+static int
+broken_state_count_compare(const void **a_ptr, const void **b_ptr)
+{
+ const broken_state_count_t *a = *a_ptr, *b = *b_ptr;
+ if (b->count < a->count)
+ return -1;
+ else if (b->count == a->count)
+ return 0;
+ else
+ return 1;
+}
+
+/** Upper limit on the number of different states to report for connection
+ * failure. */
+#define MAX_REASONS_TO_REPORT 10
+
+/** Report a list of the top states for failed OR connections at log level
+ * <b>severity</b>, in log domain <b>domain</b>. */
+void
+connection_or_report_broken_states(int severity, int domain)
+{
+ int total = 0;
+ smartlist_t *items;
+
+ if (!broken_connection_counts || disable_broken_connection_counts)
+ return;
+
+ items = smartlist_create();
+ STRMAP_FOREACH(broken_connection_counts, state, void *, countptr) {
+ broken_state_count_t *c = tor_malloc(sizeof(broken_state_count_t));
+ c->count = (intptr_t)countptr;
+ total += (int)c->count;
+ c->state = state;
+ smartlist_add(items, c);
+ } STRMAP_FOREACH_END;
+
+ smartlist_sort(items, broken_state_count_compare);
+
+ log(severity, domain, "%d connections have failed%s", total,
+ smartlist_len(items) > MAX_REASONS_TO_REPORT ? ". Top reasons:" : ":");
+
+ SMARTLIST_FOREACH_BEGIN(items, const broken_state_count_t *, c) {
+ if (c_sl_idx > MAX_REASONS_TO_REPORT)
+ break;
+ log(severity, domain,
+ " %d connections died in state %s", (int)c->count, c->state);
+ } SMARTLIST_FOREACH_END(c);
+
+ SMARTLIST_FOREACH(items, broken_state_count_t *, c, tor_free(c));
+ smartlist_free(items);
+}
+
+/**************************************************************/
+
/** Pack the cell_t host-order structure <b>src</b> into network-order
* in the buffer <b>dest</b>. See tor-spec.txt for details about the
* wire format.
@@ -178,7 +328,8 @@ var_cell_pack_header(const var_cell_t *cell, char *hdr_out)
var_cell_t *
var_cell_new(uint16_t payload_len)
{
- var_cell_t *cell = tor_malloc(sizeof(var_cell_t)+payload_len-1);
+ size_t size = STRUCT_OFFSET(var_cell_t, payload) + payload_len;
+ var_cell_t *cell = tor_malloc(size);
cell->payload_len = payload_len;
cell->command = 0;
cell->circ_id = 0;
@@ -227,6 +378,14 @@ connection_or_process_inbuf(or_connection_t *conn)
}
return ret;
+#ifdef USE_BUFFEREVENTS
+ case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING:
+ if (tor_tls_server_got_renegotiate(conn->tls))
+ connection_or_tls_renegotiated_cb(conn->tls, conn);
+ if (conn->_base.marked_for_close)
+ return 0;
+ /* fall through. */
+#endif
case OR_CONN_STATE_OPEN:
case OR_CONN_STATE_OR_HANDSHAKING:
return connection_or_process_cells_from_inbuf(conn);
@@ -248,7 +407,7 @@ connection_or_process_inbuf(or_connection_t *conn)
int
connection_or_flushed_some(or_connection_t *conn)
{
- size_t datalen = buf_datalen(conn->_base.outbuf);
+ size_t datalen = connection_get_outbuf_len(TO_CONN(conn));
/* If we're under the low water mark, add cells until we're just over the
* high water mark. */
if (datalen < OR_CONN_LOWWATER) {
@@ -281,7 +440,6 @@ connection_or_finished_flushing(or_connection_t *conn)
case OR_CONN_STATE_PROXY_HANDSHAKING:
case OR_CONN_STATE_OPEN:
case OR_CONN_STATE_OR_HANDSHAKING:
- connection_stop_writing(TO_CONN(conn));
break;
default:
log_err(LD_BUG,"Called in unexpected state %d.", conn->_base.state);
@@ -296,7 +454,7 @@ connection_or_finished_flushing(or_connection_t *conn)
int
connection_or_finished_connecting(or_connection_t *or_conn)
{
- int proxy_type;
+ const int proxy_type = or_conn->proxy_type;
connection_t *conn;
tor_assert(or_conn);
conn = TO_CONN(or_conn);
@@ -306,15 +464,6 @@ connection_or_finished_connecting(or_connection_t *or_conn)
conn->address,conn->port);
control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0);
- proxy_type = PROXY_NONE;
-
- if (get_options()->HTTPSProxy)
- proxy_type = PROXY_CONNECT;
- else if (get_options()->Socks4Proxy)
- proxy_type = PROXY_SOCKS4;
- else if (get_options()->Socks5Proxy)
- proxy_type = PROXY_SOCKS5;
-
if (proxy_type != PROXY_NONE) {
/* start proxy handshake */
if (connection_proxy_connect(conn, proxy_type) < 0) {
@@ -335,6 +484,51 @@ connection_or_finished_connecting(or_connection_t *or_conn)
return 0;
}
+/* Called when we're about to finally unlink and free an OR connection:
+ * perform necessary accounting and cleanup */
+void
+connection_or_about_to_close(or_connection_t *or_conn)
+{
+ time_t now = time(NULL);
+ connection_t *conn = TO_CONN(or_conn);
+
+ /* Remember why we're closing this connection. */
+ if (conn->state != OR_CONN_STATE_OPEN) {
+ /* Inform any pending (not attached) circs that they should
+ * give up. */
+ circuit_n_conn_done(TO_OR_CONN(conn), 0);
+ /* now mark things down as needed */
+ if (connection_or_nonopen_was_started_here(or_conn)) {
+ const or_options_t *options = get_options();
+ connection_or_note_state_when_broken(or_conn);
+ rep_hist_note_connect_failed(or_conn->identity_digest, now);
+ entry_guard_register_connect_status(or_conn->identity_digest,0,
+ !options->HTTPSProxy, now);
+ if (conn->state >= OR_CONN_STATE_TLS_HANDSHAKING) {
+ int reason = tls_error_to_orconn_end_reason(or_conn->tls_error);
+ control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
+ reason);
+ if (!authdir_mode_tests_reachability(options))
+ control_event_bootstrap_problem(
+ orconn_end_reason_to_control_string(reason), reason);
+ }
+ }
+ } else if (conn->hold_open_until_flushed) {
+ /* We only set hold_open_until_flushed when we're intentionally
+ * closing a connection. */
+ rep_hist_note_disconnect(or_conn->identity_digest, now);
+ control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
+ tls_error_to_orconn_end_reason(or_conn->tls_error));
+ } else if (!tor_digest_is_zero(or_conn->identity_digest)) {
+ rep_hist_note_connection_died(or_conn->identity_digest, now);
+ control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
+ tls_error_to_orconn_end_reason(or_conn->tls_error));
+ }
+ /* Now close all the attached circuits on it. */
+ circuit_unlink_all_from_or_conn(TO_OR_CONN(conn),
+ END_CIRC_REASON_OR_CONN_CLOSED);
+}
+
/** Return 1 if identity digest <b>id_digest</b> is known to be a
* currently or recently running relay. Otherwise return 0. */
int
@@ -342,7 +536,7 @@ connection_or_digest_is_known_relay(const char *id_digest)
{
if (router_get_consensus_status_by_id(id_digest))
return 1; /* It's in the consensus: "yes" */
- if (router_get_by_digest(id_digest))
+ if (router_get_by_id_digest(id_digest))
return 1; /* Not in the consensus, but we have a descriptor for
* it. Probably it was in a recent consensus. "Yes". */
return 0;
@@ -359,7 +553,7 @@ connection_or_digest_is_known_relay(const char *id_digest)
*/
static void
connection_or_update_token_buckets_helper(or_connection_t *conn, int reset,
- or_options_t *options)
+ const or_options_t *options)
{
int rate, burst; /* per-connection rate limiting params */
if (connection_or_digest_is_known_relay(conn->identity_digest)) {
@@ -382,6 +576,27 @@ connection_or_update_token_buckets_helper(or_connection_t *conn, int reset,
conn->bandwidthrate = rate;
conn->bandwidthburst = burst;
+#ifdef USE_BUFFEREVENTS
+ {
+ const struct timeval *tick = tor_libevent_get_one_tick_timeout();
+ struct ev_token_bucket_cfg *cfg, *old_cfg;
+ int64_t rate64 = (((int64_t)rate) * options->TokenBucketRefillInterval)
+ / 1000;
+ /* This can't overflow, since TokenBucketRefillInterval <= 1000,
+ * and rate started out less than INT_MAX. */
+ int rate_per_tick = (int) rate64;
+
+ cfg = ev_token_bucket_cfg_new(rate_per_tick, burst, rate_per_tick,
+ burst, tick);
+ old_cfg = conn->bucket_cfg;
+ if (conn->_base.bufev)
+ tor_set_bufferevent_rate_limit(conn->_base.bufev, cfg);
+ if (old_cfg)
+ ev_token_bucket_cfg_free(old_cfg);
+ conn->bucket_cfg = cfg;
+ (void) reset; /* No way to do this with libevent yet. */
+ }
+#else
if (reset) { /* set up the token buckets to be full */
conn->read_bucket = conn->write_bucket = burst;
return;
@@ -392,13 +607,15 @@ connection_or_update_token_buckets_helper(or_connection_t *conn, int reset,
conn->read_bucket = burst;
if (conn->write_bucket > burst)
conn->write_bucket = burst;
+#endif
}
/** Either our set of relays or our per-conn rate limits have changed.
* Go through all the OR connections and update their token buckets to make
* sure they don't exceed their maximum values. */
void
-connection_or_update_token_buckets(smartlist_t *conns, or_options_t *options)
+connection_or_update_token_buckets(smartlist_t *conns,
+ const or_options_t *options)
{
SMARTLIST_FOREACH(conns, connection_t *, conn,
{
@@ -416,7 +633,7 @@ connection_or_init_conn_from_address(or_connection_t *conn,
const char *id_digest,
int started_here)
{
- routerinfo_t *r = router_get_by_digest(id_digest);
+ const node_t *r = node_get_by_id(id_digest);
connection_or_set_identity_digest(conn, id_digest);
connection_or_update_token_buckets_helper(conn, 1, get_options());
@@ -424,8 +641,10 @@ connection_or_init_conn_from_address(or_connection_t *conn,
tor_addr_copy(&conn->_base.addr, addr);
tor_addr_copy(&conn->real_addr, addr);
if (r) {
+ tor_addr_t node_addr;
+ node_get_addr(r, &node_addr);
/* XXXX proposal 118 will make this more complex. */
- if (tor_addr_eq_ipv4h(&conn->_base.addr, r->addr))
+ if (tor_addr_eq(&conn->_base.addr, &node_addr))
conn->is_canonical = 1;
if (!started_here) {
/* Override the addr/port, so our log messages will make sense.
@@ -438,12 +657,12 @@ connection_or_init_conn_from_address(or_connection_t *conn,
* right IP address and port 56244, that wouldn't be as helpful. now we
* log the "right" port too, so we know if it's moria1 or moria2.
*/
- tor_addr_from_ipv4h(&conn->_base.addr, r->addr);
- conn->_base.port = r->or_port;
+ tor_addr_copy(&conn->_base.addr, &node_addr);
+ conn->_base.port = node_get_orport(r);
}
- conn->nickname = tor_strdup(r->nickname);
+ conn->nickname = tor_strdup(node_get_nickname(r));
tor_free(conn->_base.address);
- conn->_base.address = tor_strdup(r->address);
+ conn->_base.address = tor_dup_addr(&node_addr);
} else {
const char *n;
/* If we're an authoritative directory server, we may know a
@@ -787,11 +1006,15 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
const char *id_digest)
{
or_connection_t *conn;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int socket_error = 0;
- int using_proxy = 0;
tor_addr_t addr;
+ int r;
+ tor_addr_t proxy_addr;
+ uint16_t proxy_port;
+ int proxy_type;
+
tor_assert(_addr);
tor_assert(id_digest);
tor_addr_copy(&addr, _addr);
@@ -808,19 +1031,20 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
conn->_base.state = OR_CONN_STATE_CONNECTING;
control_event_or_conn_status(conn, OR_CONN_EVENT_LAUNCHED, 0);
- /* use a proxy server if available */
- if (options->HTTPSProxy) {
- using_proxy = 1;
- tor_addr_copy(&addr, &options->HTTPSProxyAddr);
- port = options->HTTPSProxyPort;
- } else if (options->Socks4Proxy) {
- using_proxy = 1;
- tor_addr_copy(&addr, &options->Socks4ProxyAddr);
- port = options->Socks4ProxyPort;
- } else if (options->Socks5Proxy) {
- using_proxy = 1;
- tor_addr_copy(&addr, &options->Socks5ProxyAddr);
- port = options->Socks5ProxyPort;
+ /* If we are using a proxy server, find it and use it. */
+ r = get_proxy_addrport(&proxy_addr, &proxy_port, &proxy_type, TO_CONN(conn));
+ if (r == 0) {
+ conn->proxy_type = proxy_type;
+ if (proxy_type != PROXY_NONE) {
+ tor_addr_copy(&addr, &proxy_addr);
+ port = proxy_port;
+ conn->_base.proxy_state = PROXY_INFANT;
+ }
+ } else {
+ log_warn(LD_GENERAL, "Tried to connect through proxy, but proxy address "
+ "could not be found.");
+ connection_free(TO_CONN(conn));
+ return NULL;
}
switch (connection_connect(TO_CONN(conn), conn->_base.address,
@@ -828,7 +1052,7 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port,
case -1:
/* If the connection failed immediately, and we're using
* a proxy, our proxy is down. Don't blame the Tor server. */
- if (!using_proxy)
+ if (conn->_base.proxy_state == PROXY_INFANT)
entry_guard_register_connect_status(conn->identity_digest,
0, 1, time(NULL));
connection_or_connect_failed(conn,
@@ -863,6 +1087,7 @@ int
connection_tls_start_handshake(or_connection_t *conn, int receiving)
{
conn->_base.state = OR_CONN_STATE_TLS_HANDSHAKING;
+ tor_assert(!conn->tls);
conn->tls = tor_tls_new(conn->_base.s, receiving);
tor_tls_set_logged_address(conn->tls, // XXX client and relay?
escaped_safe_str(conn->_base.address));
@@ -870,12 +1095,38 @@ connection_tls_start_handshake(or_connection_t *conn, int receiving)
log_warn(LD_BUG,"tor_tls_new failed. Closing.");
return -1;
}
+#ifdef USE_BUFFEREVENTS
+ if (connection_type_uses_bufferevent(TO_CONN(conn))) {
+ const int filtering = get_options()->_UseFilteringSSLBufferevents;
+ struct bufferevent *b =
+ tor_tls_init_bufferevent(conn->tls, conn->_base.bufev, conn->_base.s,
+ receiving, filtering);
+ if (!b) {
+ log_warn(LD_BUG,"tor_tls_init_bufferevent failed. Closing.");
+ return -1;
+ }
+ conn->_base.bufev = b;
+ if (conn->bucket_cfg)
+ tor_set_bufferevent_rate_limit(conn->_base.bufev, conn->bucket_cfg);
+ connection_enable_rate_limiting(TO_CONN(conn));
+
+ connection_configure_bufferevent_callbacks(TO_CONN(conn));
+ bufferevent_setcb(b,
+ connection_handle_read_cb,
+ connection_handle_write_cb,
+ connection_or_handle_event_cb,/* overriding this one*/
+ TO_CONN(conn));
+ }
+#endif
connection_start_reading(TO_CONN(conn));
log_debug(LD_HANDSHAKE,"starting TLS handshake on fd %d", conn->_base.s);
note_crypto_pk_op(receiving ? TLS_HANDSHAKE_S : TLS_HANDSHAKE_C);
- if (connection_tls_continue_handshake(conn) < 0) {
- return -1;
+ IF_HAS_BUFFEREVENT(TO_CONN(conn), {
+ /* ???? */;
+ }) ELSE_IF_NO_BUFFEREVENT {
+ if (connection_tls_continue_handshake(conn) < 0)
+ return -1;
}
return 0;
}
@@ -963,6 +1214,78 @@ connection_tls_continue_handshake(or_connection_t *conn)
return 0;
}
+#ifdef USE_BUFFEREVENTS
+static void
+connection_or_handle_event_cb(struct bufferevent *bufev, short event,
+ void *arg)
+{
+ struct or_connection_t *conn = TO_OR_CONN(arg);
+
+ /* XXXX cut-and-paste code; should become a function. */
+ if (event & BEV_EVENT_CONNECTED) {
+ if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) {
+ if (tor_tls_finish_handshake(conn->tls) < 0) {
+ log_warn(LD_OR, "Problem finishing handshake");
+ connection_mark_for_close(TO_CONN(conn));
+ return;
+ }
+ }
+
+ if (! tor_tls_used_v1_handshake(conn->tls)) {
+ if (!tor_tls_is_server(conn->tls)) {
+ if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) {
+ conn->_base.state = OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING;
+ tor_tls_unblock_renegotiation(conn->tls);
+ if (bufferevent_ssl_renegotiate(conn->_base.bufev)<0) {
+ log_warn(LD_OR, "Start_renegotiating went badly.");
+ connection_mark_for_close(TO_CONN(conn));
+ }
+ tor_tls_unblock_renegotiation(conn->tls);
+ return; /* ???? */
+ }
+ } else if (tor_tls_get_num_server_handshakes(conn->tls) == 1) {
+ /* improved handshake, as a server. Only got one handshake, so
+ * wait for the next one. */
+ tor_tls_set_renegotiate_callback(conn->tls,
+ connection_or_tls_renegotiated_cb,
+ conn);
+ conn->_base.state = OR_CONN_STATE_TLS_SERVER_RENEGOTIATING;
+ /* return 0; */
+ return; /* ???? */
+ } else {
+ const int handshakes = tor_tls_get_num_server_handshakes(conn->tls);
+ tor_assert(handshakes >= 2);
+ if (handshakes == 2) {
+ /* improved handshake, as a server. Two handshakes happened already,
+ * so we treat renegotiation as done.
+ */
+ connection_or_tls_renegotiated_cb(conn->tls, conn);
+ } else {
+ log_warn(LD_OR, "More than two handshakes done on connection. "
+ "Closing.");
+ connection_mark_for_close(TO_CONN(conn));
+ }
+ return;
+ }
+ }
+ connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
+ if (connection_tls_finish_handshake(conn) < 0)
+ connection_mark_for_close(TO_CONN(conn)); /* ???? */
+ return;
+ }
+
+ if (event & BEV_EVENT_ERROR) {
+ unsigned long err;
+ while ((err = bufferevent_get_openssl_error(bufev))) {
+ tor_tls_log_one_error(conn->tls, err, LOG_WARN, LD_OR,
+ "handshaking (with bufferevent)");
+ }
+ }
+
+ connection_handle_event_cb(bufev, event, arg);
+}
+#endif
+
/** Return 1 if we initiated this connection, or 0 if it started
* out as an incoming connection.
*/
@@ -1008,7 +1331,7 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
char *digest_rcvd_out)
{
crypto_pk_env_t *identity_rcvd=NULL;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int severity = server_mode(options) ? LOG_PROTOCOL_WARN : LOG_WARN;
const char *safe_address =
started_here ? conn->_base.address :
@@ -1131,7 +1454,9 @@ connection_tls_finish_handshake(or_connection_t *conn)
char digest_rcvd[DIGEST_LEN];
int started_here = connection_or_nonopen_was_started_here(conn);
- log_debug(LD_HANDSHAKE,"tls handshake with %s done. verifying.",
+ log_debug(LD_HANDSHAKE,"%s tls handshake on %p with %s done. verifying.",
+ started_here?"outgoing":"incoming",
+ conn,
safe_str_client(conn->_base.address));
directory_set_dirty();
@@ -1212,7 +1537,7 @@ connection_or_set_state_open(or_connection_t *conn)
router_set_status(conn->identity_digest, 1);
} else {
/* only report it to the geoip module if it's not a known router */
- if (!router_get_by_digest(conn->identity_digest)) {
+ if (!router_get_by_id_digest(conn->identity_digest)) {
if (tor_addr_family(&TO_CONN(conn)->addr) == AF_INET) {
/*XXXX IP6 support ipv6 geoip.*/
uint32_t a = tor_addr_to_ipv4h(&TO_CONN(conn)->addr);
@@ -1223,8 +1548,12 @@ connection_or_set_state_open(or_connection_t *conn)
or_handshake_state_free(conn->handshake_state);
conn->handshake_state = NULL;
+ IF_HAS_BUFFEREVENT(TO_CONN(conn), {
+ connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ connection_start_reading(TO_CONN(conn));
+ }
- connection_start_reading(TO_CONN(conn));
circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */
return 0;
@@ -1269,12 +1598,18 @@ connection_or_write_var_cell_to_buf(const var_cell_t *cell,
conn->timestamp_last_added_nonpadding = approx_time();
}
-/** See whether there's a variable-length cell waiting on <b>conn</b>'s
+/** See whether there's a variable-length cell waiting on <b>or_conn</b>'s
* inbuf. Return values as for fetch_var_cell_from_buf(). */
static int
-connection_fetch_var_cell_from_buf(or_connection_t *conn, var_cell_t **out)
+connection_fetch_var_cell_from_buf(or_connection_t *or_conn, var_cell_t **out)
{
- return fetch_var_cell_from_buf(conn->_base.inbuf, out, conn->link_proto);
+ connection_t *conn = TO_CONN(or_conn);
+ IF_HAS_BUFFEREVENT(conn, {
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ return fetch_var_cell_from_evbuffer(input, out, or_conn->link_proto);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return fetch_var_cell_from_buf(conn->inbuf, out, or_conn->link_proto);
+ }
}
/** Process cells from <b>conn</b>'s inbuf.
@@ -1292,7 +1627,7 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn)
while (1) {
log_debug(LD_OR,
"%d: starting, inbuf_datalen %d (%d pending in tls object).",
- conn->_base.s,(int)buf_datalen(conn->_base.inbuf),
+ conn->_base.s,(int)connection_get_inbuf_len(TO_CONN(conn)),
tor_tls_get_pending_bytes(conn->tls));
if (connection_fetch_var_cell_from_buf(conn, &var_cell)) {
if (!var_cell)
@@ -1303,8 +1638,8 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn)
} else {
char buf[CELL_NETWORK_SIZE];
cell_t cell;
- if (buf_datalen(conn->_base.inbuf) < CELL_NETWORK_SIZE) /* whole response
- available? */
+ if (connection_get_inbuf_len(TO_CONN(conn))
+ < CELL_NETWORK_SIZE) /* whole response available? */
return 0; /* not yet */
circuit_build_times_network_is_live(&circ_times);
@@ -1391,7 +1726,7 @@ connection_or_send_netinfo(or_connection_t *conn)
{
cell_t cell;
time_t now = time(NULL);
- routerinfo_t *me;
+ const routerinfo_t *me;
int len;
uint8_t *out;
diff --git a/src/or/connection_or.h b/src/or/connection_or.h
index 70ef96a33..072edbd8c 100644
--- a/src/or/connection_or.h
+++ b/src/or/connection_or.h
@@ -14,6 +14,7 @@
void connection_or_remove_from_identity_map(or_connection_t *conn);
void connection_or_clear_identity_map(void);
+void clear_broken_connection_map(int disable);
or_connection_t *connection_or_get_for_extend(const char *digest,
const tor_addr_t *target_addr,
const char **msg_out,
@@ -25,15 +26,18 @@ int connection_or_process_inbuf(or_connection_t *conn);
int connection_or_flushed_some(or_connection_t *conn);
int connection_or_finished_flushing(or_connection_t *conn);
int connection_or_finished_connecting(or_connection_t *conn);
+void connection_or_about_to_close(or_connection_t *conn);
int connection_or_digest_is_known_relay(const char *id_digest);
void connection_or_update_token_buckets(smartlist_t *conns,
- or_options_t *options);
+ const or_options_t *options);
void connection_or_connect_failed(or_connection_t *conn,
int reason, const char *msg);
or_connection_t *connection_or_connect(const tor_addr_t *addr, uint16_t port,
const char *id_digest);
+void connection_or_report_broken_states(int severity, int domain);
+
int connection_tls_start_handshake(or_connection_t *conn, int receiving);
int connection_tls_continue_handshake(or_connection_t *conn);
diff --git a/src/or/control.c b/src/or/control.c
index de9dca0be..1fdbac281 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -18,6 +18,7 @@
#include "config.h"
#include "connection.h"
#include "connection_edge.h"
+#include "connection_or.h"
#include "control.h"
#include "directory.h"
#include "dirserv.h"
@@ -26,12 +27,18 @@
#include "hibernate.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "reasons.h"
#include "router.h"
#include "routerlist.h"
#include "routerparse.h"
+#ifndef MS_WINDOWS
+#include <pwd.h>
+#include <sys/resource.h>
+#endif
+
#include "procmon.h"
/** Yield true iff <b>s</b> is the state of a control_connection_t that has
@@ -66,7 +73,9 @@
#define EVENT_CLIENTS_SEEN 0x0015
#define EVENT_NEWCONSENSUS 0x0016
#define EVENT_BUILDTIMEOUT_SET 0x0017
-#define _EVENT_MAX 0x0017
+#define EVENT_SIGNAL 0x0018
+#define EVENT_CONF_CHANGED 0x0019
+#define _EVENT_MAX 0x0019
/* If _EVENT_MAX ever hits 0x0020, we need to make the mask wider. */
/** Bitfield: The bit 1&lt;&lt;e is set if <b>any</b> open control
@@ -168,7 +177,7 @@ static int handle_control_resolve(control_connection_t *conn, uint32_t len,
static int handle_control_usefeature(control_connection_t *conn,
uint32_t len,
const char *body);
-static int write_stream_target_to_buf(edge_connection_t *conn, char *buf,
+static int write_stream_target_to_buf(entry_connection_t *conn, char *buf,
size_t len);
static void orconn_target_get_name(char *buf, size_t len,
or_connection_t *conn);
@@ -494,8 +503,8 @@ connection_printf_to_buf(control_connection_t *conn, const char *format, ...)
va_end(ap);
if (len < 0) {
- log_warn(LD_BUG, "Unable to format string for controller.");
- return;
+ log_err(LD_BUG, "Unable to format string for controller.");
+ tor_assert(0);
}
connection_write_to_buf(buf, (size_t)len, TO_CONN(conn));
@@ -509,7 +518,7 @@ control_ports_write_to_file(void)
{
smartlist_t *lines;
char *joined = NULL;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!options->ControlPortWriteToFile)
return;
@@ -593,7 +602,7 @@ send_control_event_string(uint16_t event, event_format_t which,
else if (event == EVENT_STATUS_SERVER)
is_err = !strcmpstart(msg, "STATUS_SERVER ERR ");
if (is_err)
- connection_handle_write(TO_CONN(control_conn), 1);
+ connection_flush(TO_CONN(control_conn));
}
}
} SMARTLIST_FOREACH_END(conn);
@@ -647,7 +656,7 @@ get_circ(const char *id)
}
/** Given a text stream <b>id</b>, return the corresponding AP connection. */
-static edge_connection_t *
+static entry_connection_t *
get_stream(const char *id)
{
uint64_t n_id;
@@ -659,7 +668,7 @@ get_stream(const char *id)
conn = connection_get_by_global_id(n_id);
if (!conn || conn->type != CONN_TYPE_AP || conn->marked_for_close)
return NULL;
- return TO_EDGE_CONN(conn);
+ return TO_ENTRY_CONN(conn);
}
/** Helper for setconf and resetconf. Acts like setconf, except
@@ -798,7 +807,7 @@ handle_control_getconf(control_connection_t *conn, uint32_t body_len,
smartlist_t *unrecognized = smartlist_create();
char *msg = NULL;
size_t msg_len;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int i, len;
(void) body_len; /* body is NUL-terminated; so we can ignore len. */
@@ -910,13 +919,45 @@ handle_control_loadconf(control_connection_t *conn, uint32_t len,
return 0;
}
+struct control_event_t {
+ uint16_t event_code;
+ const char *event_name;
+};
+static const struct control_event_t control_event_table[] = {
+ { EVENT_CIRCUIT_STATUS, "CIRC" },
+ { EVENT_STREAM_STATUS, "STREAM" },
+ { EVENT_OR_CONN_STATUS, "ORCONN" },
+ { EVENT_BANDWIDTH_USED, "BW" },
+ { EVENT_DEBUG_MSG, "DEBUG" },
+ { EVENT_INFO_MSG, "INFO" },
+ { EVENT_NOTICE_MSG, "NOTICE" },
+ { EVENT_WARN_MSG, "WARN" },
+ { EVENT_ERR_MSG, "ERR" },
+ { EVENT_NEW_DESC, "NEWDESC" },
+ { EVENT_ADDRMAP, "ADDRMAP" },
+ { EVENT_AUTHDIR_NEWDESCS, "AUTHDIR_NEWDESCS" },
+ { EVENT_DESCCHANGED, "DESCCHANGED" },
+ { EVENT_NS, "NS" },
+ { EVENT_STATUS_GENERAL, "STATUS_GENERAL" },
+ { EVENT_STATUS_CLIENT, "STATUS_CLIENT" },
+ { EVENT_STATUS_SERVER, "STATUS_SERVER" },
+ { EVENT_GUARD, "GUARD" },
+ { EVENT_STREAM_BANDWIDTH_USED, "STREAM_BW" },
+ { EVENT_CLIENTS_SEEN, "CLIENTS_SEEN" },
+ { EVENT_NEWCONSENSUS, "NEWCONSENSUS" },
+ { EVENT_BUILDTIMEOUT_SET, "BUILDTIMEOUT_SET" },
+ { EVENT_SIGNAL, "SIGNAL" },
+ { EVENT_CONF_CHANGED, "CONF_CHANGED"},
+ { 0, NULL },
+};
+
/** Called when we get a SETEVENTS message: update conn->event_mask,
* and reply with DONE or ERROR. */
static int
handle_control_setevents(control_connection_t *conn, uint32_t len,
const char *body)
{
- uint16_t event_code;
+ int event_code = -1;
uint32_t event_mask = 0;
smartlist_t *events = smartlist_create();
@@ -928,56 +969,22 @@ handle_control_setevents(control_connection_t *conn, uint32_t len,
{
if (!strcasecmp(ev, "EXTENDED")) {
continue;
- } else if (!strcasecmp(ev, "CIRC"))
- event_code = EVENT_CIRCUIT_STATUS;
- else if (!strcasecmp(ev, "STREAM"))
- event_code = EVENT_STREAM_STATUS;
- else if (!strcasecmp(ev, "ORCONN"))
- event_code = EVENT_OR_CONN_STATUS;
- else if (!strcasecmp(ev, "BW"))
- event_code = EVENT_BANDWIDTH_USED;
- else if (!strcasecmp(ev, "DEBUG"))
- event_code = EVENT_DEBUG_MSG;
- else if (!strcasecmp(ev, "INFO"))
- event_code = EVENT_INFO_MSG;
- else if (!strcasecmp(ev, "NOTICE"))
- event_code = EVENT_NOTICE_MSG;
- else if (!strcasecmp(ev, "WARN"))
- event_code = EVENT_WARN_MSG;
- else if (!strcasecmp(ev, "ERR"))
- event_code = EVENT_ERR_MSG;
- else if (!strcasecmp(ev, "NEWDESC"))
- event_code = EVENT_NEW_DESC;
- else if (!strcasecmp(ev, "ADDRMAP"))
- event_code = EVENT_ADDRMAP;
- else if (!strcasecmp(ev, "AUTHDIR_NEWDESCS"))
- event_code = EVENT_AUTHDIR_NEWDESCS;
- else if (!strcasecmp(ev, "DESCCHANGED"))
- event_code = EVENT_DESCCHANGED;
- else if (!strcasecmp(ev, "NS"))
- event_code = EVENT_NS;
- else if (!strcasecmp(ev, "STATUS_GENERAL"))
- event_code = EVENT_STATUS_GENERAL;
- else if (!strcasecmp(ev, "STATUS_CLIENT"))
- event_code = EVENT_STATUS_CLIENT;
- else if (!strcasecmp(ev, "STATUS_SERVER"))
- event_code = EVENT_STATUS_SERVER;
- else if (!strcasecmp(ev, "GUARD"))
- event_code = EVENT_GUARD;
- else if (!strcasecmp(ev, "STREAM_BW"))
- event_code = EVENT_STREAM_BANDWIDTH_USED;
- else if (!strcasecmp(ev, "CLIENTS_SEEN"))
- event_code = EVENT_CLIENTS_SEEN;
- else if (!strcasecmp(ev, "NEWCONSENSUS"))
- event_code = EVENT_NEWCONSENSUS;
- else if (!strcasecmp(ev, "BUILDTIMEOUT_SET"))
- event_code = EVENT_BUILDTIMEOUT_SET;
- else {
- connection_printf_to_buf(conn, "552 Unrecognized event \"%s\"\r\n",
- ev);
- SMARTLIST_FOREACH(events, char *, e, tor_free(e));
- smartlist_free(events);
- return 0;
+ } else {
+ int i;
+ for (i = 0; control_event_table[i].event_name != NULL; ++i) {
+ if (!strcasecmp(ev, control_event_table[i].event_name)) {
+ event_code = control_event_table[i].event_code;
+ break;
+ }
+ }
+
+ if (event_code == -1) {
+ connection_printf_to_buf(conn, "552 Unrecognized event \"%s\"\r\n",
+ ev);
+ SMARTLIST_FOREACH(events, char *, e, tor_free(e));
+ smartlist_free(events);
+ return 0;
+ }
}
event_mask |= (1 << event_code);
}
@@ -1039,7 +1046,7 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len,
const char *body)
{
int used_quoted_string = 0;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
const char *errstr = NULL;
char *password;
size_t password_len;
@@ -1248,7 +1255,7 @@ handle_control_signal(control_connection_t *conn, uint32_t len,
send_control_done(conn);
/* Flush the "done" first if the signal might make us shut down. */
if (sig == SIGTERM || sig == SIGINT)
- connection_handle_write(TO_CONN(conn), 1);
+ connection_flush(TO_CONN(conn));
process_signal(sig);
@@ -1377,11 +1384,16 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
} else if (!strcmp(question, "info/names")) {
*answer = list_getinfo_options();
} else if (!strcmp(question, "events/names")) {
- *answer = tor_strdup("CIRC STREAM ORCONN BW DEBUG INFO NOTICE WARN ERR "
- "NEWDESC ADDRMAP AUTHDIR_NEWDESCS DESCCHANGED "
- "NS STATUS_GENERAL STATUS_CLIENT STATUS_SERVER "
- "GUARD STREAM_BW CLIENTS_SEEN NEWCONSENSUS "
- "BUILDTIMEOUT_SET");
+ int i;
+ smartlist_t *event_names = smartlist_create();
+
+ for (i = 0; control_event_table[i].event_name != NULL; ++i) {
+ smartlist_add(event_names, (char *)control_event_table[i].event_name);
+ }
+
+ *answer = smartlist_join_strings(event_names, " ", 0, NULL);
+
+ smartlist_free(event_names);
} else if (!strcmp(question, "features/names")) {
*answer = tor_strdup("VERBOSE_NAMES EXTENDED_EVENTS");
} else if (!strcmp(question, "address")) {
@@ -1391,6 +1403,61 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
return -1;
}
*answer = tor_dup_ip(addr);
+ } else if (!strcmp(question, "traffic/read")) {
+ tor_asprintf(answer, U64_FORMAT, U64_PRINTF_ARG(get_bytes_read()));
+ } else if (!strcmp(question, "traffic/written")) {
+ tor_asprintf(answer, U64_FORMAT, U64_PRINTF_ARG(get_bytes_written()));
+ } else if (!strcmp(question, "process/pid")) {
+ int myPid = -1;
+
+ #ifdef MS_WINDOWS
+ myPid = _getpid();
+ #else
+ myPid = getpid();
+ #endif
+
+ tor_asprintf(answer, "%d", myPid);
+ } else if (!strcmp(question, "process/uid")) {
+ #ifdef MS_WINDOWS
+ *answer = tor_strdup("-1");
+ #else
+ int myUid = geteuid();
+ tor_asprintf(answer, "%d", myUid);
+ #endif
+ } else if (!strcmp(question, "process/user")) {
+ #ifdef MS_WINDOWS
+ *answer = tor_strdup("");
+ #else
+ int myUid = geteuid();
+ struct passwd *myPwEntry = getpwuid(myUid);
+
+ if (myPwEntry) {
+ *answer = tor_strdup(myPwEntry->pw_name);
+ } else {
+ *answer = tor_strdup("");
+ }
+ #endif
+ } else if (!strcmp(question, "process/descriptor-limit")) {
+ /** platform specifc limits are from the set_max_file_descriptors function
+ * of src/common/compat.c */
+ /* XXXX023 This is duplicated code from compat.c; it should turn into a
+ * function. */
+ #ifdef HAVE_GETRLIMIT
+ struct rlimit descriptorLimit;
+
+ if (getrlimit(RLIMIT_NOFILE, &descriptorLimit) == 0) {
+ tor_asprintf(answer, U64_FORMAT,
+ U64_PRINTF_ARG(descriptorLimit.rlim_max));
+ } else {
+ *answer = tor_strdup("-1");
+ }
+ #elif defined(CYGWIN) || defined(__CYGWIN__)
+ *answer = tor_strdup("3200");
+ #elif defined(MS_WINDOWS)
+ *answer = tor_strdup("15000");
+ #else
+ *answer = tor_strdup("15000");
+ #endif
} else if (!strcmp(question, "dir-usage")) {
*answer = directory_dump_request_log();
} else if (!strcmp(question, "fingerprint")) {
@@ -1416,8 +1483,9 @@ getinfo_helper_misc(control_connection_t *conn, const char *question,
* NOTE: <b>ri_body</b> is as returned by signed_descriptor_get_body: it might
* not be NUL-terminated. */
static char *
-munge_extrainfo_into_routerinfo(const char *ri_body, signed_descriptor_t *ri,
- signed_descriptor_t *ei)
+munge_extrainfo_into_routerinfo(const char *ri_body,
+ const signed_descriptor_t *ri,
+ const signed_descriptor_t *ei)
{
char *out = NULL, *outp;
int i;
@@ -1519,16 +1587,17 @@ getinfo_helper_dir(control_connection_t *control_conn,
const char *question, char **answer,
const char **errmsg)
{
+ const routerinfo_t *ri;
(void) control_conn;
if (!strcmpstart(question, "desc/id/")) {
- routerinfo_t *ri = router_get_by_hexdigest(question+strlen("desc/id/"));
+ ri = router_get_by_hexdigest(question+strlen("desc/id/"));
if (ri) {
const char *body = signed_descriptor_get_body(&ri->cache_info);
if (body)
*answer = tor_strndup(body, ri->cache_info.signed_descriptor_len);
}
} else if (!strcmpstart(question, "desc/name/")) {
- routerinfo_t *ri = router_get_by_nickname(question+strlen("desc/name/"),1);
+ ri = router_get_by_nickname(question+strlen("desc/name/"),1);
if (ri) {
const char *body = signed_descriptor_get_body(&ri->cache_info);
if (body)
@@ -1538,7 +1607,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
routerlist_t *routerlist = router_get_routerlist();
smartlist_t *sl = smartlist_create();
if (routerlist && routerlist->routers) {
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
+ SMARTLIST_FOREACH(routerlist->routers, const routerinfo_t *, ri,
{
const char *body = signed_descriptor_get_body(&ri->cache_info);
if (body)
@@ -1554,7 +1623,7 @@ getinfo_helper_dir(control_connection_t *control_conn,
routerlist_t *routerlist = router_get_routerlist();
smartlist_t *sl = smartlist_create();
if (routerlist && routerlist->routers) {
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
+ SMARTLIST_FOREACH(routerlist->routers, const routerinfo_t *, ri,
{
const char *body = signed_descriptor_get_body(&ri->cache_info);
signed_descriptor_t *ei = extrainfo_get_by_descriptor_digest(
@@ -1572,8 +1641,8 @@ getinfo_helper_dir(control_connection_t *control_conn,
SMARTLIST_FOREACH(sl, char *, c, tor_free(c));
smartlist_free(sl);
} else if (!strcmpstart(question, "desc-annotations/id/")) {
- routerinfo_t *ri = router_get_by_hexdigest(question+
- strlen("desc-annotations/id/"));
+ ri = router_get_by_hexdigest(question+
+ strlen("desc-annotations/id/"));
if (ri) {
const char *annotations =
signed_descriptor_get_annotations(&ri->cache_info);
@@ -1733,7 +1802,7 @@ getinfo_helper_events(control_connection_t *control_conn,
char buf[256];
SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
const char *state;
- edge_connection_t *conn;
+ entry_connection_t *conn;
char *s;
size_t slen;
circuit_t *circ;
@@ -1743,8 +1812,8 @@ getinfo_helper_events(control_connection_t *control_conn,
base_conn->state == AP_CONN_STATE_SOCKS_WAIT ||
base_conn->state == AP_CONN_STATE_NATD_WAIT)
continue;
- conn = TO_EDGE_CONN(base_conn);
- switch (conn->_base.state)
+ conn = TO_ENTRY_CONN(base_conn);
+ switch (base_conn->state)
{
case AP_CONN_STATE_CONTROLLER_WAIT:
case AP_CONN_STATE_CIRCUIT_WAIT:
@@ -1763,17 +1832,17 @@ getinfo_helper_events(control_connection_t *control_conn,
state = "SUCCEEDED"; break;
default:
log_warn(LD_BUG, "Asked for stream in unknown state %d",
- conn->_base.state);
+ base_conn->state);
continue;
}
- circ = circuit_get_by_edge_conn(conn);
+ circ = circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn));
if (circ && CIRCUIT_IS_ORIGIN(circ))
origin_circ = TO_ORIGIN_CIRCUIT(circ);
write_stream_target_to_buf(conn, buf, sizeof(buf));
slen = strlen(buf)+strlen(state)+32;
s = tor_malloc(slen+1);
tor_snprintf(s, slen, "%lu %s %lu %s",
- (unsigned long) conn->_base.global_identifier,state,
+ (unsigned long) base_conn->global_identifier,state,
origin_circ?
(unsigned long)origin_circ->global_identifier : 0ul,
buf);
@@ -1886,7 +1955,7 @@ getinfo_helper_events(control_connection_t *control_conn,
} else if (!strcmp(question, "status/version/num-versioning") ||
!strcmp(question, "status/version/num-concurring")) {
char s[33];
- tor_snprintf(s, sizeof(s), "%d", get_n_authorities(V3_AUTHORITY));
+ tor_snprintf(s, sizeof(s), "%d", get_n_authorities(V3_DIRINFO));
*answer = tor_strdup(s);
log_warn(LD_GENERAL, "%s is deprecated; it no longer gives useful "
"information", question);
@@ -2004,6 +2073,14 @@ static const getinfo_item_t getinfo_items[] = {
"Number of versioning authorities agreeing on the status of the "
"current version"),
ITEM("address", misc, "IP address of this Tor host, if we can guess it."),
+ ITEM("traffic/read", misc,"Bytes read since the process was started."),
+ ITEM("traffic/written", misc,
+ "Bytes written since the process was started."),
+ ITEM("process/pid", misc, "Process id belonging to the main tor process."),
+ ITEM("process/uid", misc, "User id running the tor process."),
+ ITEM("process/user", misc,
+ "Username under which the tor process is running."),
+ ITEM("process/descriptor-limit", misc, "File descriptor limit."),
ITEM("dir-usage", misc, "Breakdown of bytes transferred over DirPort."),
PREFIX("desc-annotations/id/", dir, "Router annotations by hexdigest."),
PREFIX("dir/server/", dir,"Router descriptors as retrieved from a DirPort."),
@@ -2213,7 +2290,7 @@ static int
handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
const char *body)
{
- smartlist_t *router_nicknames=NULL, *routers=NULL;
+ smartlist_t *router_nicknames=NULL, *nodes=NULL;
origin_circuit_t *circ = NULL;
int zero_circ;
uint8_t intended_purpose = CIRCUIT_PURPOSE_C_GENERAL;
@@ -2244,8 +2321,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
if ((smartlist_len(args) == 1) ||
(smartlist_len(args) >= 2 && is_keyval_pair(smartlist_get(args, 1)))) {
// "EXTENDCIRCUIT 0" || EXTENDCIRCUIT 0 foo=bar"
- circ = circuit_launch_by_router(intended_purpose, NULL,
- CIRCLAUNCH_NEED_CAPACITY);
+ circ = circuit_launch(intended_purpose, CIRCLAUNCH_NEED_CAPACITY);
if (!circ) {
connection_write_str_to_buf("551 Couldn't start circuit\r\n", conn);
} else {
@@ -2273,17 +2349,21 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
smartlist_free(args);
- routers = smartlist_create();
+ nodes = smartlist_create();
SMARTLIST_FOREACH(router_nicknames, const char *, n,
{
- routerinfo_t *r = router_get_by_nickname(n, 1);
- if (!r) {
+ const node_t *node = node_get_by_nickname(n, 1);
+ if (!node) {
connection_printf_to_buf(conn, "552 No such router \"%s\"\r\n", n);
goto done;
}
- smartlist_add(routers, r);
+ if (!node_has_descriptor(node)) {
+ connection_printf_to_buf(conn, "552 descriptor for \"%s\"\r\n", n);
+ goto done;
+ }
+ smartlist_add(nodes, (void*)node);
});
- if (!smartlist_len(routers)) {
+ if (!smartlist_len(nodes)) {
connection_write_str_to_buf("512 No router names provided\r\n", conn);
goto done;
}
@@ -2294,9 +2374,10 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
}
/* now circ refers to something that is ready to be extended */
- SMARTLIST_FOREACH(routers, routerinfo_t *, r,
+ SMARTLIST_FOREACH(nodes, const node_t *, node,
{
- extend_info_t *info = extend_info_from_router(r);
+ extend_info_t *info = extend_info_from_node(node);
+ tor_assert(info); /* True, since node_has_descriptor(node) == true */
circuit_append_new_exit(circ, info);
extend_info_free(info);
});
@@ -2330,7 +2411,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
done:
SMARTLIST_FOREACH(router_nicknames, char *, n, tor_free(n));
smartlist_free(router_nicknames);
- smartlist_free(routers);
+ smartlist_free(nodes);
return 0;
}
@@ -2381,7 +2462,7 @@ static int
handle_control_attachstream(control_connection_t *conn, uint32_t len,
const char *body)
{
- edge_connection_t *ap_conn = NULL;
+ entry_connection_t *ap_conn = NULL;
origin_circuit_t *circ = NULL;
int zero_circ;
smartlist_t *args;
@@ -2417,9 +2498,9 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
if (!ap_conn || (!zero_circ && !circ) || !hop_line_ok)
return 0;
- if (ap_conn->_base.state != AP_CONN_STATE_CONTROLLER_WAIT &&
- ap_conn->_base.state != AP_CONN_STATE_CONNECT_WAIT &&
- ap_conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT) {
+ if (ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_CONTROLLER_WAIT &&
+ ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_CONNECT_WAIT &&
+ ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_RESOLVE_WAIT) {
connection_write_str_to_buf(
"555 Connection is not managed by controller.\r\n",
conn);
@@ -2427,15 +2508,16 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
}
/* Do we need to detach it first? */
- if (ap_conn->_base.state != AP_CONN_STATE_CONTROLLER_WAIT) {
- circuit_t *tmpcirc = circuit_get_by_edge_conn(ap_conn);
- connection_edge_end(ap_conn, END_STREAM_REASON_TIMEOUT);
+ if (ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_CONTROLLER_WAIT) {
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(ap_conn);
+ circuit_t *tmpcirc = circuit_get_by_edge_conn(edge_conn);
+ connection_edge_end(edge_conn, END_STREAM_REASON_TIMEOUT);
/* Un-mark it as ending, since we're going to reuse it. */
- ap_conn->edge_has_sent_end = 0;
- ap_conn->end_reason = 0;
+ edge_conn->edge_has_sent_end = 0;
+ edge_conn->end_reason = 0;
if (tmpcirc)
- circuit_detach_stream(tmpcirc,ap_conn);
- ap_conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT;
+ circuit_detach_stream(tmpcirc, edge_conn);
+ TO_CONN(edge_conn)->state = AP_CONN_STATE_CONTROLLER_WAIT;
}
if (circ && (circ->_base.state != CIRCUIT_STATE_OPEN)) {
@@ -2446,16 +2528,17 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len,
}
/* Is this a single hop circuit? */
if (circ && (circuit_get_cpath_len(circ)<2 || hop==1)) {
- routerinfo_t *r = NULL;
- char* exit_digest;
+ const node_t *node = NULL;
+ char *exit_digest;
if (circ->build_state &&
circ->build_state->chosen_exit &&
!tor_digest_is_zero(circ->build_state->chosen_exit->identity_digest)) {
exit_digest = circ->build_state->chosen_exit->identity_digest;
- r = router_get_by_digest(exit_digest);
+ node = node_get_by_id(exit_digest);
}
/* Do both the client and relay allow one-hop exit circuits? */
- if (!r || !r->allow_single_hop_exits ||
+ if (!node ||
+ !node_allows_single_hop_exits(node) ||
!get_options()->AllowSingleHopCircuits) {
connection_write_str_to_buf(
"551 Can't attach stream to this one-hop circuit.\r\n", conn);
@@ -2556,7 +2639,7 @@ static int
handle_control_redirectstream(control_connection_t *conn, uint32_t len,
const char *body)
{
- edge_connection_t *ap_conn = NULL;
+ entry_connection_t *ap_conn = NULL;
char *new_addr = NULL;
uint16_t new_port = 0;
smartlist_t *args;
@@ -2604,7 +2687,7 @@ static int
handle_control_closestream(control_connection_t *conn, uint32_t len,
const char *body)
{
- edge_connection_t *ap_conn=NULL;
+ entry_connection_t *ap_conn=NULL;
uint8_t reason=0;
smartlist_t *args;
int ok;
@@ -2749,7 +2832,7 @@ handle_control_protocolinfo(control_connection_t *conn, uint32_t len,
connection_mark_for_close(TO_CONN(conn));
goto done;
} else {
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int cookies = options->CookieAuthentication;
char *cfile = get_cookie_file();
char *esc_cfile = esc_for_log(cfile);
@@ -2827,8 +2910,6 @@ int
connection_control_finished_flushing(control_connection_t *conn)
{
tor_assert(conn);
-
- connection_stop_writing(TO_CONN(conn));
return 0;
}
@@ -2900,6 +2981,17 @@ is_valid_initial_command(control_connection_t *conn, const char *cmd)
* interfaces is broken. */
#define MAX_COMMAND_LINE_LENGTH (1024*1024)
+static int
+peek_connection_has_control0_command(connection_t *conn)
+{
+ IF_HAS_BUFFEREVENT(conn, {
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ return peek_evbuffer_has_control0_command(input);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ return peek_buf_has_control0_command(conn->inbuf);
+ }
+}
+
/** Called when data has arrived on a v1 control connection: Try to fetch
* commands from conn->inbuf, and execute them.
*/
@@ -2922,7 +3014,7 @@ connection_control_process_inbuf(control_connection_t *conn)
}
if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH &&
- peek_buf_has_control0_command(conn->_base.inbuf)) {
+ peek_connection_has_control0_command(TO_CONN(conn))) {
/* Detect v0 commands and send a "no more v0" message. */
size_t body_len;
char buf[128];
@@ -2934,8 +3026,8 @@ connection_control_process_inbuf(control_connection_t *conn)
body_len = 2+strlen(buf+6)+2; /* code, msg, nul. */
set_uint16(buf+0, htons(body_len));
connection_write_to_buf(buf, 4+body_len, TO_CONN(conn));
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+
+ connection_mark_and_flush(TO_CONN(conn));
return 0;
}
@@ -2946,7 +3038,7 @@ connection_control_process_inbuf(control_connection_t *conn)
/* First, fetch a line. */
do {
data_len = conn->incoming_cmd_len - conn->incoming_cmd_cur_len;
- r = fetch_from_buf_line(conn->_base.inbuf,
+ r = connection_fetch_from_buf_line(TO_CONN(conn),
conn->incoming_cmd+conn->incoming_cmd_cur_len,
&data_len);
if (r == 0)
@@ -2956,8 +3048,7 @@ connection_control_process_inbuf(control_connection_t *conn)
if (data_len + conn->incoming_cmd_cur_len > MAX_COMMAND_LINE_LENGTH) {
connection_write_str_to_buf("500 Line too long.\r\n", conn);
connection_stop_reading(TO_CONN(conn));
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+ connection_mark_and_flush(TO_CONN(conn));
}
while (conn->incoming_cmd_len < data_len+conn->incoming_cmd_cur_len)
conn->incoming_cmd_len *= 2;
@@ -3017,8 +3108,7 @@ connection_control_process_inbuf(control_connection_t *conn)
/* Otherwise, Quit is always valid. */
if (!strcasecmp(conn->incoming_cmd, "QUIT")) {
connection_write_str_to_buf("250 closing connection\r\n", conn);
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+ connection_mark_and_flush(TO_CONN(conn));
return 0;
}
@@ -3177,7 +3267,7 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp,
* <b>conn</b>, and write it to <b>buf</b>. Return 0 on success, -1 on
* failure. */
static int
-write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len)
+write_stream_target_to_buf(entry_connection_t *conn, char *buf, size_t len)
{
char buf2[256];
if (conn->chosen_exit_name)
@@ -3188,8 +3278,8 @@ write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len)
if (tor_snprintf(buf, len, "%s%s%s:%d",
conn->socks_request->address,
conn->chosen_exit_name ? buf2 : "",
- !conn->chosen_exit_name &&
- connection_edge_is_rendezvous_stream(conn) ? ".onion" : "",
+ !conn->chosen_exit_name && connection_edge_is_rendezvous_stream(
+ ENTRY_TO_EDGE_CONN(conn)) ? ".onion" : "",
conn->socks_request->port)<0)
return -1;
return 0;
@@ -3198,7 +3288,7 @@ write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len)
/** Something has happened to the stream associated with AP connection
* <b>conn</b>: tell any interested control connections. */
int
-control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
+control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp,
int reason_code)
{
char reason_buf[64];
@@ -3270,7 +3360,7 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
if (tp == STREAM_EVENT_NEW) {
tor_snprintf(addrport_buf,sizeof(addrport_buf), " SOURCE_ADDR=%s:%d",
- TO_CONN(conn)->address, TO_CONN(conn)->port );
+ ENTRY_TO_CONN(conn)->address, ENTRY_TO_CONN(conn)->port);
} else {
addrport_buf[0] = '\0';
}
@@ -3278,12 +3368,12 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
if (tp == STREAM_EVENT_NEW_RESOLVE) {
purpose = " PURPOSE=DNS_REQUEST";
} else if (tp == STREAM_EVENT_NEW) {
- if (conn->is_dns_request ||
+ if (ENTRY_TO_EDGE_CONN(conn)->is_dns_request ||
(conn->socks_request &&
SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)))
purpose = " PURPOSE=DNS_REQUEST";
else if (conn->use_begindir) {
- connection_t *linked = TO_CONN(conn)->linked_conn;
+ connection_t *linked = ENTRY_TO_CONN(conn)->linked_conn;
int linked_dir_purpose = -1;
if (linked && linked->type == CONN_TYPE_DIR)
linked_dir_purpose = linked->purpose;
@@ -3295,12 +3385,13 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
purpose = " PURPOSE=USER";
}
- circ = circuit_get_by_edge_conn(conn);
+ circ = circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn));
if (circ && CIRCUIT_IS_ORIGIN(circ))
origin_circ = TO_ORIGIN_CIRCUIT(circ);
send_control_event(EVENT_STREAM_STATUS, ALL_FORMATS,
"650 STREAM "U64_FORMAT" %s %lu %s%s%s%s\r\n",
- U64_PRINTF_ARG(conn->_base.global_identifier), status,
+ U64_PRINTF_ARG(ENTRY_TO_CONN(conn)->global_identifier),
+ status,
origin_circ?
(unsigned long)origin_circ->global_identifier : 0ul,
buf, reason_buf, addrport_buf, purpose);
@@ -3316,10 +3407,10 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp,
static void
orconn_target_get_name(char *name, size_t len, or_connection_t *conn)
{
- routerinfo_t *ri = router_get_by_digest(conn->identity_digest);
- if (ri) {
+ const node_t *node = node_get_by_id(conn->identity_digest);
+ if (node) {
tor_assert(len > MAX_VERBOSE_NICKNAME_LEN);
- router_get_verbose_nickname(name, ri);
+ node_get_verbose_nickname(node, name);
} else if (! tor_digest_is_zero(conn->identity_digest)) {
name[0] = '$';
base16_encode(name+1, len-1, conn->identity_digest,
@@ -3636,7 +3727,7 @@ control_event_networkstatus_changed_helper(smartlist_t *statuses,
smartlist_add(strs, tor_strdup("650+"));
smartlist_add(strs, tor_strdup(event_string));
smartlist_add(strs, tor_strdup("\r\n"));
- SMARTLIST_FOREACH(statuses, routerstatus_t *, rs,
+ SMARTLIST_FOREACH(statuses, const routerstatus_t *, rs,
{
s = networkstatus_getinfo_helper_single(rs);
if (!s) continue;
@@ -3712,8 +3803,8 @@ control_event_buildtimeout_set(const circuit_build_times_t *cbt,
send_control_event(EVENT_BUILDTIMEOUT_SET, ALL_FORMATS,
"650 BUILDTIMEOUT_SET %s TOTAL_TIMES=%lu "
- "TIMEOUT_MS=%lu XM=%lu ALPHA=%lf CUTOFF_QUANTILE=%lf "
- "TIMEOUT_RATE=%lf CLOSE_MS=%lu CLOSE_RATE=%lf\r\n",
+ "TIMEOUT_MS=%lu XM=%lu ALPHA=%f CUTOFF_QUANTILE=%f "
+ "TIMEOUT_RATE=%f CLOSE_MS=%lu CLOSE_RATE=%f\r\n",
type_string, (unsigned long)cbt->total_build_times,
(unsigned long)cbt->timeout_ms,
(unsigned long)cbt->Xm, cbt->alpha, qnt,
@@ -3724,10 +3815,46 @@ control_event_buildtimeout_set(const circuit_build_times_t *cbt,
return 0;
}
+/** Called when a signal has been processed from signal_callback */
+int
+control_event_signal(uintptr_t signal)
+{
+ const char *signal_string = NULL;
+
+ if (!control_event_is_interesting(EVENT_SIGNAL))
+ return 0;
+
+ switch (signal) {
+ case SIGHUP:
+ signal_string = "RELOAD";
+ break;
+ case SIGUSR1:
+ signal_string = "DUMP";
+ break;
+ case SIGUSR2:
+ signal_string = "DEBUG";
+ break;
+ case SIGNEWNYM:
+ signal_string = "NEWNYM";
+ break;
+ case SIGCLEARDNSCACHE:
+ signal_string = "CLEARDNSCACHE";
+ break;
+ default:
+ log_warn(LD_BUG, "Unrecognized signal %lu in control_event_signal",
+ (unsigned long)signal);
+ return -1;
+ }
+
+ send_control_event(EVENT_SIGNAL, ALL_FORMATS, "650 SIGNAL %s\r\n",
+ signal_string);
+ return 0;
+}
+
/** Called when a single local_routerstatus_t has changed: Sends an NS event
* to any controller that cares. */
int
-control_event_networkstatus_changed_single(routerstatus_t *rs)
+control_event_networkstatus_changed_single(const routerstatus_t *rs)
{
smartlist_t *statuses;
int r;
@@ -3736,7 +3863,7 @@ control_event_networkstatus_changed_single(routerstatus_t *rs)
return 0;
statuses = smartlist_create();
- smartlist_add(statuses, rs);
+ smartlist_add(statuses, (void*)rs);
r = control_event_networkstatus_changed(statuses);
smartlist_free(statuses);
return r;
@@ -3861,9 +3988,9 @@ control_event_guard(const char *nickname, const char *digest,
{
char buf[MAX_VERBOSE_NICKNAME_LEN+1];
- routerinfo_t *ri = router_get_by_digest(digest);
- if (ri) {
- router_get_verbose_nickname(buf, ri);
+ const node_t *node = node_get_by_id(digest);
+ if (node) {
+ node_get_verbose_nickname(node, buf);
} else {
tor_snprintf(buf, sizeof(buf), "$%s~%s", hbuf, nickname);
}
@@ -3873,12 +4000,45 @@ control_event_guard(const char *nickname, const char *digest,
return 0;
}
+/** Called when a configuration option changes. This is generally triggered
+ * by SETCONF requests and RELOAD/SIGHUP signals. The <b>elements</b> is
+ * a smartlist_t containing (key, value, ...) pairs in sequence.
+ * <b>value</b> can be NULL. */
+int
+control_event_conf_changed(smartlist_t *elements)
+{
+ int i;
+ char *result;
+ smartlist_t *lines;
+ if (!EVENT_IS_INTERESTING(EVENT_CONF_CHANGED) ||
+ smartlist_len(elements) == 0) {
+ return 0;
+ }
+ lines = smartlist_create();
+ for (i = 0; i < smartlist_len(elements); i += 2) {
+ char *k = smartlist_get(elements, i);
+ char *v = smartlist_get(elements, i+1);
+ if (v == NULL) {
+ smartlist_asprintf_add(lines, "650-%s", k);
+ } else {
+ smartlist_asprintf_add(lines, "650-%s=%s", k, v);
+ }
+ }
+ result = smartlist_join_strings(lines, "\r\n", 0, NULL);
+ send_control_event(EVENT_CONF_CHANGED, 0,
+ "650-CONF_CHANGED\r\n%s\r\n650 OK\r\n", result);
+ tor_free(result);
+ SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp));
+ smartlist_free(lines);
+ return 0;
+}
+
/** Helper: Return a newly allocated string containing a path to the
* file where we store our authentication cookie. */
static char *
get_cookie_file(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->CookieAuthFile && strlen(options->CookieAuthFile)) {
return tor_strdup(options->CookieAuthFile);
} else {
@@ -4146,6 +4306,7 @@ control_event_bootstrap_problem(const char *warn, int reason)
const char *tag, *summary;
char buf[BOOTSTRAP_MSG_LEN];
const char *recommendation = "ignore";
+ int severity;
/* bootstrap_percent must not be in "undefined" state here. */
tor_assert(status >= 0);
@@ -4170,12 +4331,17 @@ control_event_bootstrap_problem(const char *warn, int reason)
status--; /* find a recognized status string based on current progress */
status = bootstrap_percent; /* set status back to the actual number */
- log_fn(!strcmp(recommendation, "warn") ? LOG_WARN : LOG_INFO,
+ severity = !strcmp(recommendation, "warn") ? LOG_WARN : LOG_INFO;
+
+ log_fn(severity,
LD_CONTROL, "Problem bootstrapping. Stuck at %d%%: %s. (%s; %s; "
"count %d; recommendation %s)",
status, summary, warn,
orconn_end_reason_to_control_string(reason),
bootstrap_problems, recommendation);
+
+ connection_or_report_broken_states(severity, LD_HANDSHAKE);
+
tor_snprintf(buf, sizeof(buf),
"BOOTSTRAP PROGRESS=%d TAG=%s SUMMARY=\"%s\" WARNING=\"%s\" REASON=%s "
"COUNT=%d RECOMMENDATION=%s",
diff --git a/src/or/control.h b/src/or/control.h
index ddea4cd54..0d9acd26e 100644
--- a/src/or/control.h
+++ b/src/or/control.h
@@ -37,7 +37,7 @@ int control_event_is_interesting(int event);
int control_event_circuit_status(origin_circuit_t *circ,
circuit_status_event_t e, int reason);
-int control_event_stream_status(edge_connection_t *conn,
+int control_event_stream_status(entry_connection_t *conn,
stream_status_event_t e,
int reason);
int control_event_or_conn_status(or_connection_t *conn,
@@ -57,7 +57,7 @@ int control_event_my_descriptor_changed(void);
int control_event_networkstatus_changed(smartlist_t *statuses);
int control_event_newconsensus(const networkstatus_t *consensus);
-int control_event_networkstatus_changed_single(routerstatus_t *rs);
+int control_event_networkstatus_changed_single(const routerstatus_t *rs);
int control_event_general_status(int severity, const char *format, ...)
CHECK_PRINTF(2,3);
int control_event_client_status(int severity, const char *format, ...)
@@ -66,8 +66,10 @@ int control_event_server_status(int severity, const char *format, ...)
CHECK_PRINTF(2,3);
int control_event_guard(const char *nickname, const char *digest,
const char *status);
+int control_event_conf_changed(smartlist_t *elements);
int control_event_buildtimeout_set(const circuit_build_times_t *cbt,
buildtimeout_set_event_t type);
+int control_event_signal(uintptr_t signal);
int init_cookie_authentication(int enabled);
smartlist_t *decode_hashed_passwords(config_line_t *passwords);
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index c5e4863f7..bf8964c29 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -62,7 +62,6 @@ connection_cpu_finished_flushing(connection_t *conn)
{
tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_CPUWORKER);
- connection_stop_writing(conn);
return 0;
}
@@ -141,13 +140,13 @@ connection_cpu_process_inbuf(connection_t *conn)
tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_CPUWORKER);
- if (!buf_datalen(conn->inbuf))
+ if (!connection_get_inbuf_len(conn))
return 0;
if (conn->state == CPUWORKER_STATE_BUSY_ONION) {
- if (buf_datalen(conn->inbuf) < LEN_ONION_RESPONSE) /* answer available? */
+ if (connection_get_inbuf_len(conn) < LEN_ONION_RESPONSE)
return 0; /* not yet */
- tor_assert(buf_datalen(conn->inbuf) == LEN_ONION_RESPONSE);
+ tor_assert(connection_get_inbuf_len(conn) == LEN_ONION_RESPONSE);
connection_fetch_from_buf(&success,1,conn);
connection_fetch_from_buf(buf,LEN_ONION_RESPONSE-1,conn);
@@ -367,7 +366,7 @@ spawn_cpuworker(void)
static void
spawn_enough_cpuworkers(void)
{
- int num_cpuworkers_needed = get_options()->NumCPUs;
+ int num_cpuworkers_needed = get_num_cpus(get_options());
if (num_cpuworkers_needed < MIN_CPUWORKERS)
num_cpuworkers_needed = MIN_CPUWORKERS;
diff --git a/src/or/directory.c b/src/or/directory.c
index 52fec6b61..776b7a25f 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -15,7 +15,9 @@
#include "dirvote.h"
#include "geoip.h"
#include "main.h"
+#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -78,6 +80,8 @@ static void dir_routerdesc_download_failed(smartlist_t *failed,
int router_purpose,
int was_extrainfo,
int was_descriptor_digests);
+static void dir_microdesc_download_failed(smartlist_t *failed,
+ int status_code);
static void note_client_request(int purpose, int compressed, size_t bytes);
static int client_likes_consensus(networkstatus_t *v, const char *want_url);
@@ -137,26 +141,28 @@ purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS ||
dir_purpose == DIR_PURPOSE_FETCH_CERTIFICATE ||
dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
- dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO)
+ dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
+ dir_purpose == DIR_PURPOSE_FETCH_MICRODESC)
return 0;
return 1;
}
-/** Return a newly allocated string describing <b>auth</b>. */
-char *
-authority_type_to_string(authority_type_t auth)
+/** Return a newly allocated string describing <b>auth</b>. Only describes
+ * authority features. */
+static char *
+authdir_type_to_string(dirinfo_type_t auth)
{
char *result;
smartlist_t *lst = smartlist_create();
- if (auth & V1_AUTHORITY)
+ if (auth & V1_DIRINFO)
smartlist_add(lst, (void*)"V1");
- if (auth & V2_AUTHORITY)
+ if (auth & V2_DIRINFO)
smartlist_add(lst, (void*)"V2");
- if (auth & V3_AUTHORITY)
+ if (auth & V3_DIRINFO)
smartlist_add(lst, (void*)"V3");
- if (auth & BRIDGE_AUTHORITY)
+ if (auth & BRIDGE_DIRINFO)
smartlist_add(lst, (void*)"Bridge");
- if (auth & HIDSERV_AUTHORITY)
+ if (auth & HIDSERV_DIRINFO)
smartlist_add(lst, (void*)"Hidden service");
if (smartlist_len(lst)) {
result = smartlist_join_strings(lst, ", ", 0, NULL);
@@ -201,6 +207,8 @@ dir_conn_purpose_to_string(int purpose)
return "hidden-service v2 descriptor fetch";
case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
return "hidden-service v2 descriptor upload";
+ case DIR_PURPOSE_FETCH_MICRODESC:
+ return "microdescriptor fetch";
}
log_warn(LD_BUG, "Called with unknown purpose %d", purpose);
@@ -213,17 +221,19 @@ dir_conn_purpose_to_string(int purpose)
int
router_supports_extrainfo(const char *identity_digest, int is_authority)
{
- routerinfo_t *ri = router_get_by_digest(identity_digest);
+ const node_t *node = node_get_by_id(identity_digest);
- if (ri) {
- if (ri->caches_extra_info)
+ if (node && node->ri) {
+ if (node->ri->caches_extra_info)
return 1;
- if (is_authority && ri->platform &&
- tor_version_as_new_as(ri->platform, "Tor 0.2.0.0-alpha-dev (r10070)"))
+ if (is_authority && node->ri->platform &&
+ tor_version_as_new_as(node->ri->platform,
+ "Tor 0.2.0.0-alpha-dev (r10070)"))
return 1;
}
if (is_authority) {
- routerstatus_t *rs = router_get_consensus_status_by_id(identity_digest);
+ const routerstatus_t *rs =
+ router_get_consensus_status_by_id(identity_digest);
if (rs && rs->version_supports_extrainfo_upload)
return 1;
}
@@ -242,7 +252,7 @@ int
directories_have_accepted_server_descriptor(void)
{
smartlist_t *servers = router_get_trusted_dir_servers();
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, {
if ((d->type & options->_PublishServerDescriptor) &&
d->has_accepted_serverdesc) {
@@ -271,11 +281,11 @@ directories_have_accepted_server_descriptor(void)
*/
void
directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
- authority_type_t type,
+ dirinfo_type_t type,
const char *payload,
size_t payload_len, size_t extrainfo_len)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int post_via_tor;
smartlist_t *dirservers = router_get_trusted_dir_servers();
int found = 0;
@@ -296,8 +306,8 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
if (exclude_self && router_digest_is_me(ds->digest))
continue;
- if (options->ExcludeNodes && options->StrictNodes &&
- routerset_contains_routerstatus(options->ExcludeNodes, rs)) {
+ if (options->StrictNodes &&
+ routerset_contains_routerstatus(options->ExcludeNodes, rs, -1)) {
log_warn(LD_DIR, "Wanted to contact authority '%s' for %s, but "
"it's in our ExcludedNodes list and StrictNodes is set. "
"Skipping.",
@@ -324,7 +334,7 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
NULL, payload, upload_len, 0);
} SMARTLIST_FOREACH_END(ds);
if (!found) {
- char *s = authority_type_to_string(type);
+ char *s = authdir_type_to_string(type);
log_warn(LD_DIR, "Publishing server descriptor to directory authorities "
"of type '%s', but no authorities of that type listed!", s);
tor_free(s);
@@ -341,39 +351,44 @@ void
directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
const char *resource, int pds_flags)
{
- routerstatus_t *rs = NULL;
- or_options_t *options = get_options();
+ const routerstatus_t *rs = NULL;
+ const or_options_t *options = get_options();
int prefer_authority = directory_fetches_from_authorities(options);
int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose);
- authority_type_t type;
+ dirinfo_type_t type;
time_t if_modified_since = 0;
/* FFFF we could break this switch into its own function, and call
* it elsewhere in directory.c. -RD */
switch (dir_purpose) {
case DIR_PURPOSE_FETCH_EXTRAINFO:
- type = EXTRAINFO_CACHE |
- (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
- V3_AUTHORITY);
+ type = EXTRAINFO_DIRINFO |
+ (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
+ V3_DIRINFO);
break;
case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS:
- type = V2_AUTHORITY;
+ type = V2_DIRINFO;
prefer_authority = 1; /* Only v2 authorities have these anyway. */
break;
case DIR_PURPOSE_FETCH_SERVERDESC:
- type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY :
- V3_AUTHORITY);
+ type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
+ V3_DIRINFO);
break;
case DIR_PURPOSE_FETCH_RENDDESC:
- type = HIDSERV_AUTHORITY;
+ type = HIDSERV_DIRINFO;
break;
case DIR_PURPOSE_FETCH_STATUS_VOTE:
case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
- type = V3_AUTHORITY;
+ case DIR_PURPOSE_FETCH_CERTIFICATE:
+ type = V3_DIRINFO;
break;
case DIR_PURPOSE_FETCH_CONSENSUS:
- case DIR_PURPOSE_FETCH_CERTIFICATE:
- type = V3_AUTHORITY;
+ type = V3_DIRINFO;
+ if (resource && !strcmp(resource,"microdesc"))
+ type |= MICRODESC_DIRINFO;
+ break;
+ case DIR_PURPOSE_FETCH_MICRODESC:
+ type = MICRODESC_DIRINFO;
break;
default:
log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose);
@@ -381,25 +396,42 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
}
if (dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
- networkstatus_t *v = networkstatus_get_latest_consensus();
- if (v)
- if_modified_since = v->valid_after + 180;
+ int flav = FLAV_NS;
+ networkstatus_t *v;
+ if (resource)
+ flav = networkstatus_parse_flavor_name(resource);
+
+ if (flav != -1) {
+ /* IF we have a parsed consensus of this type, we can do an
+ * if-modified-time based on it. */
+ v = networkstatus_get_latest_consensus_by_flavor(flav);
+ if (v)
+ if_modified_since = v->valid_after + 180;
+ } else {
+ /* Otherwise it might be a consensus we don't parse, but which we
+ * do cache. Look at the cached copy, perhaps. */
+ cached_dir_t *cd = dirserv_get_consensus(resource ? resource : "ns");
+ if (cd)
+ if_modified_since = cd->published + 180;
+ }
}
- if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
+ if (!options->FetchServerDescriptors && type != HIDSERV_DIRINFO)
return;
if (!get_via_tor) {
- if (options->UseBridges && type != BRIDGE_AUTHORITY) {
+ if (options->UseBridges && type != BRIDGE_DIRINFO) {
/* want to ask a running bridge for which we have a descriptor. */
/* XXX023 we assume that all of our bridges can answer any
* possible directory question. This won't be true forever. -RD */
/* It certainly is not true with conditional consensus downloading,
* so, for now, never assume the server supports that. */
- routerinfo_t *ri = choose_random_entry(NULL);
- if (ri) {
+ const node_t *node = choose_random_entry(NULL);
+ if (node && node->ri) {
+ /* every bridge has a routerinfo. */
tor_addr_t addr;
- tor_addr_from_ipv4h(&addr, ri->addr);
+ routerinfo_t *ri = node->ri;
+ node_get_addr(node, &addr);
directory_initiate_command(ri->address, &addr,
ri->or_port, 0,
0, /* don't use conditional consensus url */
@@ -412,10 +444,11 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
"nodes are available yet.");
return;
} else {
- if (prefer_authority || type == BRIDGE_AUTHORITY) {
+ if (prefer_authority || type == BRIDGE_DIRINFO) {
/* only ask authdirservers, and don't ask myself */
rs = router_pick_trusteddirserver(type, pds_flags);
- if (rs == NULL && (pds_flags & PDS_NO_EXISTING_SERVERDESC_FETCH)) {
+ if (rs == NULL && (pds_flags & (PDS_NO_EXISTING_SERVERDESC_FETCH|
+ PDS_NO_EXISTING_MICRODESC_FETCH))) {
/* We don't want to fetch from any authorities that we're currently
* fetching server descriptors from, and we got no match. Did we
* get no match because all the authorities have connections
@@ -423,7 +456,8 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
* return,) or because all the authorities are down or on fire or
* unreachable or something (in which case we should go on with
* our fallback code)? */
- pds_flags &= ~PDS_NO_EXISTING_SERVERDESC_FETCH;
+ pds_flags &= ~(PDS_NO_EXISTING_SERVERDESC_FETCH|
+ PDS_NO_EXISTING_MICRODESC_FETCH);
rs = router_pick_trusteddirserver(type, pds_flags);
if (rs) {
log_debug(LD_DIR, "Deferring serverdesc fetch: all authorities "
@@ -432,7 +466,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
}
}
}
- if (!rs && type != BRIDGE_AUTHORITY) {
+ if (!rs && type != BRIDGE_DIRINFO) {
/* anybody with a non-zero dirport will do */
rs = router_pick_directory_server(type, pds_flags);
if (!rs) {
@@ -449,7 +483,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
/* only ask hidserv authorities, any of them will do */
pds_flags |= PDS_IGNORE_FASCISTFIREWALL|PDS_ALLOW_SELF;
- rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, pds_flags);
+ rs = router_pick_trusteddirserver(HIDSERV_DIRINFO, pds_flags);
} else {
/* anybody with a non-zero dirport will do. Disregard firewalls. */
pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
@@ -495,7 +529,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose,
routerstatus_t *rs;
if (router_digest_is_me(ds->digest))
continue;
- if (!(ds->type & V3_AUTHORITY))
+ if (!(ds->type & V3_DIRINFO))
continue;
rs = &ds->fake_status;
directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose,
@@ -506,7 +540,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose,
/** Same as directory_initiate_command_routerstatus(), but accepts
* rendezvous data to fetch a hidden service descriptor. */
void
-directory_initiate_command_routerstatus_rend(routerstatus_t *status,
+directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
uint8_t dir_purpose,
uint8_t router_purpose,
int anonymized_connection,
@@ -516,21 +550,22 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status,
time_t if_modified_since,
const rend_data_t *rend_query)
{
- or_options_t *options = get_options();
- routerinfo_t *router;
+ const or_options_t *options = get_options();
+ const node_t *node;
char address_buf[INET_NTOA_BUF_LEN+1];
struct in_addr in;
const char *address;
tor_addr_t addr;
- router = router_get_by_digest(status->identity_digest);
+ node = node_get_by_id(status->identity_digest);
- if (!router && anonymized_connection) {
- log_info(LD_DIR, "Not sending anonymized request to directory %s; we "
+ if (!node && anonymized_connection) {
+ log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we "
"don't have its router descriptor.",
routerstatus_describe(status));
return;
- } else if (router) {
- address = router->address;
+ } else if (node) {
+ node_get_address_string(node, address_buf, sizeof(address_buf));
+ address = address_buf;
} else {
in.s_addr = htonl(status->addr);
tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
@@ -539,7 +574,7 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status,
tor_addr_from_ipv4h(&addr, status->addr);
if (options->ExcludeNodes && options->StrictNodes &&
- routerset_contains_routerstatus(options->ExcludeNodes, status)) {
+ routerset_contains_routerstatus(options->ExcludeNodes, status, -1)) {
log_warn(LD_DIR, "Wanted to contact directory mirror %s for %s, but "
"it's in our ExcludedNodes list and StrictNodes is set. "
"Skipping. This choice might make your Tor not work.",
@@ -574,7 +609,7 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status,
* want to fetch.
*/
void
-directory_initiate_command_routerstatus(routerstatus_t *status,
+directory_initiate_command_routerstatus(const routerstatus_t *status,
uint8_t dir_purpose,
uint8_t router_purpose,
int anonymized_connection,
@@ -598,7 +633,7 @@ directory_conn_is_self_reachability_test(dir_connection_t *conn)
{
if (conn->requested_resource &&
!strcmpstart(conn->requested_resource,"authority")) {
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (me &&
router_digest_is_me(conn->identity_digest) &&
tor_addr_eq_ipv4h(&conn->_base.addr, me->addr) && /*XXXX prop 118*/
@@ -612,7 +647,7 @@ directory_conn_is_self_reachability_test(dir_connection_t *conn)
* server due to a network error: Mark the router as down and try again if
* possible.
*/
-void
+static void
connection_dir_request_failed(dir_connection_t *conn)
{
if (directory_conn_is_self_reachability_test(conn)) {
@@ -626,15 +661,18 @@ connection_dir_request_failed(dir_connection_t *conn)
connection_dir_download_v2_networkstatus_failed(conn, -1);
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) {
- log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
+ log_info(LD_DIR, "Giving up on serverdesc/extrainfo fetch from "
+ "directory server at '%s'; retrying",
conn->_base.address);
if (conn->router_purpose == ROUTER_PURPOSE_BRIDGE)
connection_dir_bridge_routerdesc_failed(conn);
connection_dir_download_routerdesc_failed(conn);
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
- networkstatus_consensus_download_failed(0);
+ if (conn->requested_resource)
+ networkstatus_consensus_download_failed(0, conn->requested_resource);
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
- log_info(LD_DIR, "Giving up on directory server at '%s'; retrying",
+ log_info(LD_DIR, "Giving up on certificate fetch from directory server "
+ "at '%s'; retrying",
conn->_base.address);
connection_dir_download_cert_failed(conn, 0);
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
@@ -643,6 +681,10 @@ connection_dir_request_failed(dir_connection_t *conn)
} else if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
log_info(LD_DIR, "Giving up downloading votes from '%s'",
conn->_base.address);
+ } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
+ log_info(LD_DIR, "Giving up on downloading microdescriptors from "
+ " directory server at '%s'; will retry", conn->_base.address);
+ connection_dir_download_routerdesc_failed(conn);
}
}
@@ -713,7 +755,8 @@ connection_dir_download_routerdesc_failed(dir_connection_t *conn)
/* No need to relaunch descriptor downloads here: we already do it
* every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
- conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
+ conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
+ conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC);
(void) conn;
}
@@ -776,7 +819,7 @@ connection_dir_download_cert_failed(dir_connection_t *conn, int status)
* 3) Else yes.
*/
static int
-directory_command_should_use_begindir(or_options_t *options,
+directory_command_should_use_begindir(const or_options_t *options,
const tor_addr_t *addr,
int or_port, uint8_t router_purpose,
int anonymized_connection)
@@ -785,8 +828,7 @@ directory_command_should_use_begindir(or_options_t *options,
return 0; /* We don't know an ORPort -- no chance. */
if (!anonymized_connection)
if (!fascist_firewall_allows_address_or(addr, or_port) ||
- directory_fetches_from_authorities(options) ||
- (server_mode(options) && !options->Address))
+ directory_fetches_from_authorities(options))
return 0; /* We're firewalled or are acting like a relay -- also no. */
if (!options->TunnelDirConns &&
router_purpose != ROUTER_PURPOSE_BRIDGE)
@@ -817,6 +859,20 @@ directory_initiate_command(const char *address, const tor_addr_t *_addr,
if_modified_since, NULL);
}
+/** Return non-zero iff a directory connection with purpose
+ * <b>dir_purpose</b> reveals sensitive information about a Tor
+ * instance's client activities. (Such connections must be performed
+ * through normal three-hop Tor circuits.) */
+static int
+is_sensitive_dir_purpose(uint8_t dir_purpose)
+{
+ return ((dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) ||
+ (dir_purpose == DIR_PURPOSE_HAS_FETCHED_RENDDESC) ||
+ (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC) ||
+ (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) ||
+ (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC_V2));
+}
+
/** Same as directory_initiate_command(), but accepts rendezvous data to
* fetch a hidden service descriptor. */
static void
@@ -832,7 +888,7 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
const rend_data_t *rend_query)
{
dir_connection_t *conn;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int socket_error = 0;
int use_begindir = supports_begindir &&
directory_command_should_use_begindir(options, _addr,
@@ -851,6 +907,9 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose));
+ tor_assert(!(is_sensitive_dir_purpose(dir_purpose) &&
+ !anonymized_connection));
+
/* ensure that we don't make direct connections when a SOCKS server is
* configured. */
if (!anonymized_connection && !use_begindir && !options->HTTPProxy &&
@@ -912,7 +971,11 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
error indicates broken link in windowsland. */
}
} else { /* we want to connect via a tor connection */
- edge_connection_t *linked_conn;
+ entry_connection_t *linked_conn;
+ /* Anonymized tunneled connections can never share a circuit.
+ * One-hop directory connections can share circuits with each other
+ * but nothing else. */
+ int iso_flags = anonymized_connection ? ISO_STREAM : ISO_SESSIONGRP;
/* If it's an anonymized connection, remember the fact that we
* wanted it for later: maybe we'll want it again soon. */
@@ -926,14 +989,16 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
* hook up both sides
*/
linked_conn =
- connection_ap_make_link(conn->_base.address, conn->_base.port,
- digest, use_begindir, conn->dirconn_direct);
+ connection_ap_make_link(TO_CONN(conn),
+ conn->_base.address, conn->_base.port,
+ digest,
+ SESSION_GROUP_DIRCONN, iso_flags,
+ use_begindir, conn->dirconn_direct);
if (!linked_conn) {
log_warn(LD_NET,"Making tunnel to dirserver failed.");
connection_mark_for_close(TO_CONN(conn));
return;
}
- connection_link_connections(TO_CONN(conn), TO_CONN(linked_conn));
if (connection_add(TO_CONN(conn)) < 0) {
log_warn(LD_NET,"Unable to add connection for link to dirserver.");
@@ -946,8 +1011,13 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr,
payload, payload_len,
supports_conditional_consensus,
if_modified_since);
+
connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
- connection_start_reading(TO_CONN(linked_conn));
+ IF_HAS_BUFFEREVENT(ENTRY_TO_CONN(linked_conn), {
+ connection_watch_events(ENTRY_TO_CONN(linked_conn),
+ READ_EVENT|WRITE_EVENT);
+ }) ELSE_IF_NO_BUFFEREVENT
+ connection_start_reading(ENTRY_TO_CONN(linked_conn));
}
}
@@ -985,12 +1055,22 @@ _compare_strs(const void **a, const void **b)
* This url depends on whether or not the server we go to
* is sufficiently new to support conditional consensus downloading,
* i.e. GET .../consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b>
+ *
+ * If 'resource' is provided, it is the name of a consensus flavor to request.
*/
static char *
-directory_get_consensus_url(int supports_conditional_consensus)
+directory_get_consensus_url(int supports_conditional_consensus,
+ const char *resource)
{
- char *url;
- size_t len;
+ char *url = NULL;
+ const char *hyphen, *flavor;
+ if (resource==NULL || strcmp(resource, "ns")==0) {
+ flavor = ""; /* Request ns consensuses as "", so older servers will work*/
+ hyphen = "";
+ } else {
+ flavor = resource;
+ hyphen = "-";
+ }
if (supports_conditional_consensus) {
char *authority_id_list;
@@ -1000,7 +1080,7 @@ directory_get_consensus_url(int supports_conditional_consensus)
trusted_dir_server_t *, ds,
{
char *hex;
- if (!(ds->type & V3_AUTHORITY))
+ if (!(ds->type & V3_DIRINFO))
continue;
hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1);
@@ -1012,16 +1092,15 @@ directory_get_consensus_url(int supports_conditional_consensus)
authority_id_list = smartlist_join_strings(authority_digests,
"+", 0, NULL);
- len = strlen(authority_id_list)+64;
- url = tor_malloc(len);
- tor_snprintf(url, len, "/tor/status-vote/current/consensus/%s.z",
- authority_id_list);
+ tor_asprintf(&url, "/tor/status-vote/current/consensus%s%s/%s.z",
+ hyphen, flavor, authority_id_list);
SMARTLIST_FOREACH(authority_digests, char *, cp, tor_free(cp));
smartlist_free(authority_digests);
tor_free(authority_id_list);
} else {
- url = tor_strdup("/tor/status-vote/current/consensus.z");
+ tor_asprintf(&url, "/tor/status-vote/current/consensus%s%s.z",
+ hyphen, flavor);
}
return url;
}
@@ -1037,11 +1116,11 @@ directory_send_command(dir_connection_t *conn,
time_t if_modified_since)
{
char proxystring[256];
- char proxyauthstring[256];
char hoststring[128];
- char imsstring[RFC1123_TIME_LEN+32];
+ smartlist_t *headers = smartlist_create();
char *url;
char request[8192];
+ char *header;
const char *httpcommand = NULL;
size_t len;
@@ -1061,12 +1140,11 @@ directory_send_command(dir_connection_t *conn,
}
/* Format if-modified-since */
- if (!if_modified_since) {
- imsstring[0] = '\0';
- } else {
+ if (if_modified_since) {
char b[RFC1123_TIME_LEN+1];
format_rfc1123_time(b, if_modified_since);
- tor_snprintf(imsstring, sizeof(imsstring), "\r\nIf-Modified-Since: %s", b);
+ tor_asprintf(&header, "If-Modified-Since: %s\r\n", b);
+ smartlist_add(headers, header);
}
/* come up with some proxy lines, if we're using one. */
@@ -1081,16 +1159,14 @@ directory_send_command(dir_connection_t *conn,
log_warn(LD_BUG, "Encoding http authenticator failed");
}
if (base64_authenticator) {
- tor_snprintf(proxyauthstring, sizeof(proxyauthstring),
- "\r\nProxy-Authorization: Basic %s",
+ tor_asprintf(&header,
+ "Proxy-Authorization: Basic %s\r\n",
base64_authenticator);
tor_free(base64_authenticator);
- } else {
- proxyauthstring[0] = 0;
+ smartlist_add(headers, header);
}
} else {
proxystring[0] = 0;
- proxyauthstring[0] = 0;
}
switch (purpose) {
@@ -1102,10 +1178,11 @@ directory_send_command(dir_connection_t *conn,
tor_snprintf(url, len, "/tor/status/%s", resource);
break;
case DIR_PURPOSE_FETCH_CONSENSUS:
- tor_assert(!resource);
+ /* resource is optional. If present, it's a flavor name */
tor_assert(!payload);
httpcommand = "GET";
- url = directory_get_consensus_url(supports_conditional_consensus);
+ url = directory_get_consensus_url(supports_conditional_consensus,
+ resource);
log_info(LD_DIR, "Downloading consensus from %s using %s",
hoststring, url);
break;
@@ -1145,12 +1222,23 @@ directory_send_command(dir_connection_t *conn,
url = tor_malloc(len);
tor_snprintf(url, len, "/tor/extra/%s", resource);
break;
- case DIR_PURPOSE_UPLOAD_DIR:
+ case DIR_PURPOSE_FETCH_MICRODESC:
+ tor_assert(resource);
+ httpcommand = "GET";
+ tor_asprintf(&url, "/tor/micro/%s", resource);
+ break;
+ case DIR_PURPOSE_UPLOAD_DIR: {
+ const char *why = router_get_descriptor_gen_reason();
tor_assert(!resource);
tor_assert(payload);
httpcommand = "POST";
url = tor_strdup("/tor/");
+ if (why) {
+ tor_asprintf(&header, "X-Desc-Gen-Reason: %s\r\n", why);
+ smartlist_add(headers, header);
+ }
break;
+ }
case DIR_PURPOSE_UPLOAD_VOTE:
tor_assert(!resource);
tor_assert(payload);
@@ -1201,26 +1289,26 @@ directory_send_command(dir_connection_t *conn,
connection_write_to_buf(url, strlen(url), TO_CONN(conn));
tor_free(url);
- if (!strcmp(httpcommand, "GET") && !payload) {
- tor_snprintf(request, sizeof(request),
- " HTTP/1.0\r\nHost: %s%s%s\r\n\r\n",
- hoststring,
- imsstring,
- proxyauthstring);
- } else {
- tor_snprintf(request, sizeof(request),
- " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s%s\r\n\r\n",
- payload ? (unsigned long)payload_len : 0,
- hoststring,
- imsstring,
- proxyauthstring);
+ if (!strcmp(httpcommand, "POST") || payload) {
+ tor_asprintf(&header, "Content-Length: %lu\r\n",
+ payload ? (unsigned long)payload_len : 0);
+ smartlist_add(headers, header);
}
+
+ header = smartlist_join_strings(headers, "", 0, NULL);
+ tor_snprintf(request, sizeof(request), " HTTP/1.0\r\nHost: %s\r\n%s\r\n",
+ hoststring, header);
+ tor_free(header);
+
connection_write_to_buf(request, strlen(request), TO_CONN(conn));
if (payload) {
/* then send the payload afterwards too */
connection_write_to_buf(payload, payload_len, TO_CONN(conn));
}
+
+ SMARTLIST_FOREACH(headers, char *, h, tor_free(h));
+ smartlist_free(headers);
}
/** Parse an HTTP request string <b>headers</b> of the form
@@ -1420,6 +1508,9 @@ body_is_plausible(const char *body, size_t len, int purpose)
return 1; /* empty bodies don't need decompression */
if (len < 32)
return 0;
+ if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
+ return (!strcmpstart(body,"onion-key"));
+ }
if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
if (!strcmpstart(body,"router") ||
!strcmpstart(body,"signed-directory") ||
@@ -1496,11 +1587,12 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
int plausible;
int skewed=0;
int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
- conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO);
+ conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO ||
+ conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC);
int was_compressed=0;
time_t now = time(NULL);
- switch (fetch_from_buf_http(conn->_base.inbuf,
+ switch (connection_fetch_from_buf_http(TO_CONN(conn),
&headers, MAX_HEADERS_SIZE,
&body, &body_len, MAX_DIR_DL_SIZE,
allow_partial)) {
@@ -1575,13 +1667,14 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (status_code == 503) {
routerstatus_t *rs;
trusted_dir_server_t *ds;
+ const char *id_digest = conn->identity_digest;
log_info(LD_DIR,"Received http status code %d (%s) from server "
"'%s:%d'. I'll try again soon.",
status_code, escaped(reason), conn->_base.address,
conn->_base.port);
- if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
+ if ((rs = router_get_mutable_consensus_status_by_id(id_digest)))
rs->last_dir_503_at = now;
- if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
+ if ((ds = router_get_trusteddirserver_by_digest(id_digest)))
ds->fake_status.last_dir_503_at = now;
tor_free(body); tor_free(headers); tor_free(reason);
@@ -1720,6 +1813,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) {
int r;
+ const char *flavname = conn->requested_resource;
if (status_code != 200) {
int severity = (status_code == 304) ? LOG_INFO : LOG_WARN;
log(severity, LD_DIR,
@@ -1728,22 +1822,24 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
status_code, escaped(reason), conn->_base.address,
conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason);
- networkstatus_consensus_download_failed(status_code);
+ networkstatus_consensus_download_failed(status_code, flavname);
return -1;
}
log_info(LD_DIR,"Received consensus directory (size %d) from server "
"'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port);
- if ((r=networkstatus_set_current_consensus(body, "ns", 0))<0) {
+ if ((r=networkstatus_set_current_consensus(body, flavname, 0))<0) {
log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
- "Unable to load consensus directory downloaded from "
+ "Unable to load %s consensus directory downloaded from "
"server '%s:%d'. I'll try again soon.",
- conn->_base.address, conn->_base.port);
+ flavname, conn->_base.address, conn->_base.port);
tor_free(body); tor_free(headers); tor_free(reason);
- networkstatus_consensus_download_failed(0);
+ networkstatus_consensus_download_failed(0, flavname);
return -1;
}
/* launches router downloads as needed */
routers_update_all_from_networkstatus(now, 3);
+ update_microdescs_from_networkstatus(now);
+ update_microdesc_downloads(now);
directory_info_has_arrived(now, 0);
log_info(LD_DIR, "Successfully loaded consensus.");
}
@@ -1893,6 +1989,43 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
if (directory_conn_is_self_reachability_test(conn))
router_dirport_found_reachable();
}
+ if (conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC) {
+ smartlist_t *which = NULL;
+ log_info(LD_DIR,"Received answer to microdescriptor request (status %d, "
+ "size %d) from server '%s:%d'",
+ status_code, (int)body_len, conn->_base.address,
+ conn->_base.port);
+ tor_assert(conn->requested_resource &&
+ !strcmpstart(conn->requested_resource, "d/"));
+ which = smartlist_create();
+ dir_split_resource_into_fingerprints(conn->requested_resource+2,
+ which, NULL,
+ DSR_DIGEST256|DSR_BASE64);
+ if (status_code != 200) {
+ log_info(LD_DIR, "Received status code %d (%s) from server "
+ "'%s:%d' while fetching \"/tor/micro/%s\". I'll try again "
+ "soon.",
+ status_code, escaped(reason), conn->_base.address,
+ (int)conn->_base.port, conn->requested_resource);
+ dir_microdesc_download_failed(which, status_code);
+ SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
+ smartlist_free(which);
+ tor_free(body); tor_free(headers); tor_free(reason);
+ return 0;
+ } else {
+ smartlist_t *mds;
+ mds = microdescs_add_to_cache(get_microdesc_cache(),
+ body, body+body_len, SAVED_NOWHERE, 0,
+ now, which);
+ if (smartlist_len(which)) {
+ /* Mark remaining ones as failed. */
+ dir_microdesc_download_failed(which, status_code);
+ }
+ SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
+ smartlist_free(which);
+ smartlist_free(mds);
+ }
+ }
if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) {
switch (status_code) {
@@ -2167,7 +2300,7 @@ connection_dir_process_inbuf(dir_connection_t *conn)
return 0;
}
- if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) {
+ if (connection_get_inbuf_len(TO_CONN(conn)) > MAX_DIRECTORY_OBJECT_SIZE) {
log_warn(LD_HTTP, "Too much data received from directory connection: "
"denial of service attempt, or you need to upgrade?");
connection_mark_for_close(TO_CONN(conn));
@@ -2179,6 +2312,28 @@ connection_dir_process_inbuf(dir_connection_t *conn)
return 0;
}
+/** Called when we're about to finally unlink and free a directory connection:
+ * perform necessary accounting and cleanup */
+void
+connection_dir_about_to_close(dir_connection_t *dir_conn)
+{
+ connection_t *conn = TO_CONN(dir_conn);
+
+ if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) {
+ /* It's a directory connection and connecting or fetching
+ * failed: forget about this router, and maybe try again. */
+ connection_dir_request_failed(dir_conn);
+ }
+ /* If we were trying to fetch a v2 rend desc and did not succeed,
+ * retry as needed. (If a fetch is successful, the connection state
+ * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC to mark that
+ * refetching is unnecessary.) */
+ if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
+ dir_conn->rend_data &&
+ strlen(dir_conn->rend_data->onion_address) == REND_SERVICE_ID_LEN_BASE32)
+ rend_client_refetch_v2_renddesc(dir_conn->rend_data);
+}
+
/** Create an http response for the client <b>conn</b> out of
* <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>.
*/
@@ -2470,18 +2625,18 @@ client_likes_consensus(networkstatus_t *v, const char *want_url)
* Always return 0. */
static int
directory_handle_command_get(dir_connection_t *conn, const char *headers,
- const char *body, size_t body_len)
+ const char *req_body, size_t req_body_len)
{
size_t dlen;
char *url, *url_mem, *header;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
time_t if_modified_since = 0;
int compressed;
size_t url_len;
/* We ignore the body of a GET request. */
- (void)body;
- (void)body_len;
+ (void)req_body;
+ (void)req_body_len;
log_debug(LD_DIRSERV,"Received GET command.");
@@ -3190,7 +3345,7 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers,
const char *body, size_t body_len)
{
char *url = NULL;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
log_debug(LD_DIRSERV,"Received POST command.");
@@ -3334,7 +3489,7 @@ directory_handle_command(dir_connection_t *conn)
tor_assert(conn);
tor_assert(conn->_base.type == CONN_TYPE_DIR);
- switch (fetch_from_buf_http(conn->_base.inbuf,
+ switch (connection_fetch_from_buf_http(TO_CONN(conn),
&headers, MAX_HEADERS_SIZE,
&body, &body_len, MAX_DIR_UL_SIZE, 0)) {
case -1: /* overflow */
@@ -3387,14 +3542,27 @@ connection_dir_finished_flushing(dir_connection_t *conn)
DIRREQ_DIRECT,
DIRREQ_FLUSHING_DIR_CONN_FINISHED);
switch (conn->_base.state) {
+ case DIR_CONN_STATE_CONNECTING:
case DIR_CONN_STATE_CLIENT_SENDING:
log_debug(LD_DIR,"client finished sending command.");
conn->_base.state = DIR_CONN_STATE_CLIENT_READING;
- connection_stop_writing(TO_CONN(conn));
return 0;
case DIR_CONN_STATE_SERVER_WRITING:
- log_debug(LD_DIRSERV,"Finished writing server response. Closing.");
- connection_mark_for_close(TO_CONN(conn));
+ if (conn->dir_spool_src != DIR_SPOOL_NONE) {
+#ifdef USE_BUFFEREVENTS
+ /* This can happen with paired bufferevents, since a paired connection
+ * can flush immediately when you write to it, making the subsequent
+ * check in connection_handle_write_cb() decide that the connection
+ * is flushed. */
+ log_debug(LD_DIRSERV, "Emptied a dirserv buffer, but still spooling.");
+#else
+ log_warn(LD_BUG, "Emptied a dirserv buffer, but it's still spooling!");
+ connection_mark_for_close(TO_CONN(conn));
+#endif
+ } else {
+ log_debug(LD_DIRSERV, "Finished writing server response. Closing.");
+ connection_mark_for_close(TO_CONN(conn));
+ }
return 0;
default:
log_warn(LD_BUG,"called in unexpected state %d.",
@@ -3620,6 +3788,36 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
* every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
}
+/* DOCDOC NM */
+static void
+dir_microdesc_download_failed(smartlist_t *failed,
+ int status_code)
+{
+ networkstatus_t *consensus
+ = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
+ routerstatus_t *rs;
+ download_status_t *dls;
+ time_t now = time(NULL);
+ int server = directory_fetches_from_authorities(get_options());
+
+ if (! consensus)
+ return;
+ SMARTLIST_FOREACH_BEGIN(failed, const char *, d) {
+ rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus,d);
+ if (!rs)
+ continue;
+ dls = &rs->dl_status;
+ if (dls->n_download_failures >= MAX_MICRODESC_DOWNLOAD_FAILURES)
+ continue;
+ {
+ char buf[BASE64_DIGEST256_LEN+1];
+ digest256_to_base64(buf, d);
+ download_status_increment_failure(dls, status_code, buf,
+ server, now);
+ }
+ } SMARTLIST_FOREACH_END(d);
+}
+
/** Helper. Compare two fp_pair_t objects, and return negative, 0, or
* positive as appropriate. */
static int
diff --git a/src/or/directory.h b/src/or/directory.h
index 94dfb1764..8c63bb5df 100644
--- a/src/or/directory.h
+++ b/src/or/directory.h
@@ -13,9 +13,8 @@
#define _TOR_DIRECTORY_H
int directories_have_accepted_server_descriptor(void);
-char *authority_type_to_string(authority_type_t auth);
void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
- authority_type_t type, const char *payload,
+ dirinfo_type_t type, const char *payload,
size_t payload_len, size_t extrainfo_len);
void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
const char *resource,
@@ -23,7 +22,7 @@ void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
void directory_get_from_all_authorities(uint8_t dir_purpose,
uint8_t router_purpose,
const char *resource);
-void directory_initiate_command_routerstatus(routerstatus_t *status,
+void directory_initiate_command_routerstatus(const routerstatus_t *status,
uint8_t dir_purpose,
uint8_t router_purpose,
int anonymized_connection,
@@ -31,7 +30,7 @@ void directory_initiate_command_routerstatus(routerstatus_t *status,
const char *payload,
size_t payload_len,
time_t if_modified_since);
-void directory_initiate_command_routerstatus_rend(routerstatus_t *status,
+void directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
uint8_t dir_purpose,
uint8_t router_purpose,
int anonymized_connection,
@@ -49,7 +48,7 @@ int connection_dir_reached_eof(dir_connection_t *conn);
int connection_dir_process_inbuf(dir_connection_t *conn);
int connection_dir_finished_flushing(dir_connection_t *conn);
int connection_dir_finished_connecting(dir_connection_t *conn);
-void connection_dir_request_failed(dir_connection_t *conn);
+void connection_dir_about_to_close(dir_connection_t *dir_conn);
void directory_initiate_command(const char *address, const tor_addr_t *addr,
uint16_t or_port, uint16_t dir_port,
int supports_conditional_consensus,
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 7df9a2fca..d22a0538d 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -16,6 +16,7 @@
#include "hibernate.h"
#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "rephist.h"
#include "router.h"
@@ -67,8 +68,6 @@ static char *format_versions_list(config_line_t *ln);
struct authdir_config_t;
static int add_fingerprint_to_dir(const char *nickname, const char *fp,
struct authdir_config_t *list);
-static uint32_t dirserv_router_get_status(const routerinfo_t *router,
- const char **msg);
static uint32_t
dirserv_get_status_impl(const char *fp, const char *nickname,
const char *address,
@@ -76,7 +75,8 @@ dirserv_get_status_impl(const char *fp, const char *nickname,
const char *platform, const char *contact,
const char **msg, int should_log);
static void clear_cached_dir(cached_dir_t *d);
-static signed_descriptor_t *get_signed_descriptor_by_fp(const char *fp,
+static const signed_descriptor_t *get_signed_descriptor_by_fp(
+ const char *fp,
int extrainfo,
time_t publish_cutoff);
static int dirserv_add_extrainfo(extrainfo_t *ei, const char **msg);
@@ -212,7 +212,7 @@ dirserv_load_fingerprint_file(void)
authdir_config_t *fingerprint_list_new;
int result;
config_line_t *front=NULL, *list;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
fname = get_datadir_fname("approved-routers");
log_info(LD_GENERAL,
@@ -305,7 +305,7 @@ dirserv_load_fingerprint_file(void)
*
* If the status is 'FP_REJECT' and <b>msg</b> is provided, set
* *<b>msg</b> to an explanation of why. */
-static uint32_t
+uint32_t
dirserv_router_get_status(const routerinfo_t *router, const char **msg)
{
char d[DIGEST_LEN];
@@ -327,7 +327,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg)
/** Return true if there is no point in downloading the router described by
* <b>rs</b> because this directory would reject it. */
int
-dirserv_would_reject_router(routerstatus_t *rs)
+dirserv_would_reject_router(const routerstatus_t *rs)
{
uint32_t res;
@@ -362,7 +362,7 @@ dirserv_get_name_status(const char *id_digest, const char *nickname)
return 0;
}
-/** Helper: As dirserv_get_router_status, but takes the router fingerprint
+/** Helper: As dirserv_router_get_status, but takes the router fingerprint
* (hex, no spaces), nickname, address (used for logging only), IP address, OR
* port, platform (logging only) and contact info (logging only) as arguments.
*
@@ -377,7 +377,7 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname,
const char **msg, int should_log)
{
int reject_unlisted = get_options()->AuthDirRejectUnlisted;
- uint32_t result = 0;
+ uint32_t result;
router_status_t *status_by_digest;
if (!fingerprint_list)
@@ -542,7 +542,7 @@ dirserv_router_has_valid_address(routerinfo_t *ri)
*/
int
authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
- int complain)
+ int complain, int *valid_out)
{
/* Okay. Now check whether the fingerprint is recognized. */
uint32_t status = dirserv_router_get_status(ri, msg);
@@ -586,15 +586,24 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
*msg = "Rejected: Address is not an IP, or IP is a private address.";
return -1;
}
- /* Okay, looks like we're willing to accept this one. */
- ri->is_named = (status & FP_NAMED) ? 1 : 0;
- ri->is_valid = (status & FP_INVALID) ? 0 : 1;
- ri->is_bad_directory = (status & FP_BADDIR) ? 1 : 0;
- ri->is_bad_exit = (status & FP_BADEXIT) ? 1 : 0;
+
+ *valid_out = ! (status & FP_INVALID);
return 0;
}
+/** Update the relevant flags of <b>node</b> based on our opinion as a
+ * directory authority in <b>authstatus</b>, as returned by
+ * dirserv_router_get_status or equivalent. */
+void
+dirserv_set_node_flags_from_authoritative_status(node_t *node,
+ uint32_t authstatus)
+{
+ node->is_valid = (authstatus & FP_INVALID) ? 0 : 1;
+ node->is_bad_directory = (authstatus & FP_BADDIR) ? 1 : 0;
+ node->is_bad_exit = (authstatus & FP_BADEXIT) ? 1 : 0;
+}
+
/** True iff <b>a</b> is more severe than <b>b</b>. */
static int
WRA_MORE_SEVERE(was_router_added_t a, was_router_added_t b)
@@ -719,7 +728,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
* from this server. (We do this here and not in router_add_to_routerlist
* because we want to be able to accept the newest router descriptor that
* another authority has, so we all converge on the same one.) */
- ri_old = router_get_by_digest(ri->cache_info.identity_digest);
+ ri_old = router_get_mutable_by_digest(ri->cache_info.identity_digest);
if (ri_old && ri_old->cache_info.published_on < ri->cache_info.published_on
&& router_differences_are_cosmetic(ri_old, ri)
&& !router_is_me(ri)) {
@@ -763,8 +772,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
routerlist_descriptors_added(changed, 0);
smartlist_free(changed);
if (!*msg) {
- *msg = ri->is_valid ? "Descriptor for valid server accepted" :
- "Descriptor for invalid server accepted";
+ *msg = "Descriptor accepted";
}
log_info(LD_DIRSERV,
"Added descriptor from '%s' (source: %s): %s.",
@@ -779,12 +787,12 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source)
static was_router_added_t
dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
{
- routerinfo_t *ri;
+ const routerinfo_t *ri;
int r;
tor_assert(msg);
*msg = NULL;
- ri = router_get_by_digest(ei->cache_info.identity_digest);
+ ri = router_get_by_id_digest(ei->cache_info.identity_digest);
if (!ri) {
*msg = "No corresponding router descriptor for extra-info descriptor";
extrainfo_free(ei);
@@ -819,56 +827,67 @@ dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
static void
directory_remove_invalid(void)
{
- int i;
int changed = 0;
routerlist_t *rl = router_get_routerlist();
+ smartlist_t *nodes = smartlist_create();
+ smartlist_add_all(nodes, nodelist_get_list());
- routerlist_assert_ok(rl);
-
- for (i = 0; i < smartlist_len(rl->routers); ++i) {
+ SMARTLIST_FOREACH_BEGIN(nodes, node_t *, node) {
const char *msg;
- routerinfo_t *ent = smartlist_get(rl->routers, i);
+ routerinfo_t *ent = node->ri;
char description[NODE_DESC_BUF_LEN];
- uint32_t r = dirserv_router_get_status(ent, &msg);
+ uint32_t r;
+ if (!ent)
+ continue;
+ r = dirserv_router_get_status(ent, &msg);
router_get_description(description, ent);
if (r & FP_REJECT) {
log_info(LD_DIRSERV, "Router %s is now rejected: %s",
description, msg?msg:"");
routerlist_remove(rl, ent, 0, time(NULL));
- i--;
changed = 1;
continue;
}
- if (bool_neq((r & FP_NAMED), ent->is_named)) {
+#if 0
+ if (bool_neq((r & FP_NAMED), ent->auth_says_is_named)) {
log_info(LD_DIRSERV,
"Router %s is now %snamed.", description,
(r&FP_NAMED)?"":"un");
ent->is_named = (r&FP_NAMED)?1:0;
changed = 1;
}
- if (bool_neq((r & FP_INVALID), !ent->is_valid)) {
+ if (bool_neq((r & FP_UNNAMED), ent->auth_says_is_unnamed)) {
+ log_info(LD_DIRSERV,
+ "Router '%s' is now %snamed. (FP_UNNAMED)", description,
+ (r&FP_NAMED)?"":"un");
+ ent->is_named = (r&FP_NUNAMED)?0:1;
+ changed = 1;
+ }
+#endif
+ if (bool_neq((r & FP_INVALID), !node->is_valid)) {
log_info(LD_DIRSERV, "Router '%s' is now %svalid.", description,
(r&FP_INVALID) ? "in" : "");
- ent->is_valid = (r&FP_INVALID)?0:1;
+ node->is_valid = (r&FP_INVALID)?0:1;
changed = 1;
}
- if (bool_neq((r & FP_BADDIR), ent->is_bad_directory)) {
+ if (bool_neq((r & FP_BADDIR), node->is_bad_directory)) {
log_info(LD_DIRSERV, "Router '%s' is now a %s directory", description,
(r & FP_BADDIR) ? "bad" : "good");
- ent->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
+ node->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
changed = 1;
}
- if (bool_neq((r & FP_BADEXIT), ent->is_bad_exit)) {
+ if (bool_neq((r & FP_BADEXIT), node->is_bad_exit)) {
log_info(LD_DIRSERV, "Router '%s' is now a %s exit", description,
(r & FP_BADEXIT) ? "bad" : "good");
- ent->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
+ node->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
changed = 1;
}
- }
+ } SMARTLIST_FOREACH_END(node);
if (changed)
directory_set_dirty();
routerlist_assert_ok(rl);
+ smartlist_free(nodes);
}
/** Mark the directory as <b>dirty</b> -- when we're next asked for a
@@ -907,10 +926,11 @@ directory_set_dirty(void)
* as running iff <b>is_live</b> is true.
*/
static char *
-list_single_server_status(routerinfo_t *desc, int is_live)
+list_single_server_status(const routerinfo_t *desc, int is_live)
{
char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
char *cp;
+ const node_t *node;
tor_assert(desc);
@@ -918,7 +938,8 @@ list_single_server_status(routerinfo_t *desc, int is_live)
if (!is_live) {
*cp++ = '!';
}
- if (desc->is_valid) {
+ node = node_get_by_id(desc->cache_info.identity_digest);
+ if (node && node->is_valid) {
strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf));
cp += strlen(cp);
*cp++ = '=';
@@ -957,6 +978,8 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
unreachable.
*/
int answer;
+ node_t *node = node_get_mutable_by_id(router->cache_info.identity_digest);
+ tor_assert(node);
if (router_is_me(router)) {
/* We always know if we are down ourselves. */
@@ -991,7 +1014,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now)
rep_hist_note_router_unreachable(router->cache_info.identity_digest, when);
}
- router->is_running = answer;
+ node->is_running = answer;
}
/** Based on the routerinfo_ts in <b>routers</b>, allocate the
@@ -1009,7 +1032,7 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
smartlist_t *rs_entries;
time_t now = time(NULL);
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* We include v2 dir auths here too, because they need to answer
* controllers. Eventually we'll deprecate this whole function;
* see also networkstatus_getinfo_by_purpose(). */
@@ -1019,6 +1042,8 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
rs_entries = smartlist_create();
SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
+ const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
+ tor_assert(node);
if (authdir) {
/* Update router status in routerinfo_t. */
dirserv_set_router_is_running(ri, now);
@@ -1026,12 +1051,13 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out,
if (for_controller) {
char name_buf[MAX_VERBOSE_NICKNAME_LEN+2];
char *cp = name_buf;
- if (!ri->is_running)
+ if (!node->is_running)
*cp++ = '!';
router_get_verbose_nickname(cp, ri);
smartlist_add(rs_entries, tor_strdup(name_buf));
} else if (ri->cache_info.published_on >= cutoff) {
- smartlist_add(rs_entries, list_single_server_status(ri, ri->is_running));
+ smartlist_add(rs_entries, list_single_server_status(ri,
+ node->is_running));
}
} SMARTLIST_FOREACH_END(ri);
@@ -1069,12 +1095,12 @@ format_versions_list(config_line_t *ln)
* not hibernating, and not too old. Else return 0.
*/
static int
-router_is_active(routerinfo_t *ri, time_t now)
+router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
{
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
if (ri->cache_info.published_on < cutoff)
return 0;
- if (!ri->is_running || !ri->is_valid || ri->is_hibernating)
+ if (!node->is_running || !node->is_valid || ri->is_hibernating)
return 0;
return 1;
}
@@ -1173,9 +1199,9 @@ dirserv_dump_directory_to_string(char **dir_out,
/** Return 1 if we fetch our directory material directly from the
* authorities, rather than from a mirror. */
int
-directory_fetches_from_authorities(or_options_t *options)
+directory_fetches_from_authorities(const or_options_t *options)
{
- routerinfo_t *me;
+ const routerinfo_t *me;
uint32_t addr;
int refuseunknown;
if (options->FetchDirInfoEarly)
@@ -1200,7 +1226,7 @@ directory_fetches_from_authorities(or_options_t *options)
* on the "mirror" schedule rather than the "client" schedule.
*/
int
-directory_fetches_dir_info_early(or_options_t *options)
+directory_fetches_dir_info_early(const or_options_t *options)
{
return directory_fetches_from_authorities(options);
}
@@ -1212,7 +1238,7 @@ directory_fetches_dir_info_early(or_options_t *options)
* client as a directory guard.
*/
int
-directory_fetches_dir_info_later(or_options_t *options)
+directory_fetches_dir_info_later(const or_options_t *options)
{
return options->UseBridges != 0;
}
@@ -1220,7 +1246,7 @@ directory_fetches_dir_info_later(or_options_t *options)
/** Return 1 if we want to cache v2 dir info (each status file).
*/
int
-directory_caches_v2_dir_info(or_options_t *options)
+directory_caches_v2_dir_info(const or_options_t *options)
{
return options->DirPort != 0;
}
@@ -1229,7 +1255,7 @@ directory_caches_v2_dir_info(or_options_t *options)
* and we're willing to serve them to others. Else return 0.
*/
int
-directory_caches_dir_info(or_options_t *options)
+directory_caches_dir_info(const or_options_t *options)
{
if (options->BridgeRelay || options->DirPort)
return 1;
@@ -1245,7 +1271,7 @@ directory_caches_dir_info(or_options_t *options)
* requests via the "begin_dir" interface, which doesn't require
* having any separate port open. */
int
-directory_permits_begindir_requests(or_options_t *options)
+directory_permits_begindir_requests(const or_options_t *options)
{
return options->BridgeRelay != 0 || options->DirPort != 0;
}
@@ -1254,7 +1280,7 @@ directory_permits_begindir_requests(or_options_t *options)
* requests via the controller interface, which doesn't require
* having any separate port open. */
int
-directory_permits_controller_requests(or_options_t *options)
+directory_permits_controller_requests(const or_options_t *options)
{
return options->DirPort != 0;
}
@@ -1264,7 +1290,8 @@ directory_permits_controller_requests(or_options_t *options)
* lately.
*/
int
-directory_too_idle_to_fetch_descriptors(or_options_t *options, time_t now)
+directory_too_idle_to_fetch_descriptors(const or_options_t *options,
+ time_t now)
{
return !directory_caches_dir_info(options) &&
!options->FetchUselessDescriptors &&
@@ -1287,7 +1314,8 @@ static cached_dir_t cached_runningrouters;
* cached_dir_t. */
static digestmap_t *cached_v2_networkstatus = NULL;
-/** Map from flavor name to the v3 consensuses that we're currently serving. */
+/** Map from flavor name to the cached_dir_t for the v3 consensuses that we're
+ * currently serving. */
static strmap_t *cached_consensuses = NULL;
/** Possibly replace the contents of <b>d</b> with the value of
@@ -1531,11 +1559,11 @@ dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
cached_dir_t *auth_src,
time_t dirty, cached_dir_t *(*regenerate)(void),
const char *name,
- authority_type_t auth_type)
+ dirinfo_type_t auth_type)
{
- or_options_t *options = get_options();
- int authority = (auth_type == V1_AUTHORITY && authdir_mode_v1(options)) ||
- (auth_type == V2_AUTHORITY && authdir_mode_v2(options));
+ const or_options_t *options = get_options();
+ int authority = (auth_type == V1_DIRINFO && authdir_mode_v1(options)) ||
+ (auth_type == V2_DIRINFO && authdir_mode_v2(options));
if (!authority || authdir_mode_bridge(options)) {
return cache_src;
@@ -1564,7 +1592,7 @@ dirserv_get_directory(void)
return dirserv_pick_cached_dir_obj(cached_directory, the_directory,
the_directory_is_dirty,
dirserv_regenerate_directory,
- "v1 server directory", V1_AUTHORITY);
+ "v1 server directory", V1_DIRINFO);
}
/** Only called by v1 auth dirservers.
@@ -1657,7 +1685,7 @@ dirserv_get_runningrouters(void)
&cached_runningrouters, &the_runningrouters,
runningrouters_is_dirty,
generate_runningrouters,
- "v1 network status list", V1_AUTHORITY);
+ "v1 network status list", V1_DIRINFO);
}
/** Return the latest downloaded consensus networkstatus in encoded, signed,
@@ -1740,7 +1768,7 @@ static uint64_t total_exit_bandwidth = 0;
/** Helper: estimate the uptime of a router given its stated uptime and the
* amount of time since it last stated its stated uptime. */
static INLINE long
-real_uptime(routerinfo_t *router, time_t now)
+real_uptime(const routerinfo_t *router, time_t now)
{
if (now < router->cache_info.published_on)
return router->uptime;
@@ -1794,7 +1822,8 @@ dirserv_thinks_router_is_unreliable(time_t now,
* been set.
*/
static int
-dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now)
+dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
+ const node_t *node, time_t now)
{
long uptime;
@@ -1822,7 +1851,7 @@ dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now)
* to fix the bug was 0.2.2.25-alpha. */
return (router->wants_to_be_hs_dir && router->dir_port &&
uptime > get_options()->MinUptimeHidServDirectoryV2 &&
- router->is_running);
+ node->is_running);
}
/** Look through the routerlist, the Mean Time Between Failure history, and
@@ -1870,19 +1899,22 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
/* Weighted fractional uptime for each active router. */
wfus = tor_malloc(sizeof(double)*smartlist_len(rl->routers));
+ nodelist_assert_ok();
+
/* Now, fill in the arrays. */
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
- if (router_is_active(ri, now)) {
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
+ routerinfo_t *ri = node->ri;
+ if (ri && router_is_active(ri, node, now)) {
const char *id = ri->cache_info.identity_digest;
uint32_t bw;
- ri->is_exit = (!router_exit_policy_rejects_all(ri) &&
- exit_policy_is_general_exit(ri->exit_policy));
+ node->is_exit = (!router_exit_policy_rejects_all(ri) &&
+ exit_policy_is_general_exit(ri->exit_policy));
uptimes[n_active] = (uint32_t)real_uptime(ri, now);
mtbfs[n_active] = rep_hist_get_stability(id, now);
tks [n_active] = rep_hist_get_weighted_time_known(id, now);
bandwidths[n_active] = bw = router_get_advertised_bandwidth(ri);
total_bandwidth += bw;
- if (ri->is_exit && !ri->is_bad_exit) {
+ if (node->is_exit && !node->is_bad_exit) {
total_exit_bandwidth += bw;
} else {
bandwidths_excluding_exits[n_active_nonexit] = bw;
@@ -1890,7 +1922,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
}
++n_active;
}
- });
+ } SMARTLIST_FOREACH_END(node);
/* Now, compute thresholds. */
if (n_active) {
@@ -1916,15 +1948,17 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
/* 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. */
n_familiar = 0;
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
- if (router_is_active(ri, now)) {
+
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
+ routerinfo_t *ri = node->ri;
+ if (ri && router_is_active(ri, node, now)) {
const char *id = ri->cache_info.identity_digest;
long tk = rep_hist_get_weighted_time_known(id, now);
if (tk < guard_tk)
continue;
wfus[n_familiar++] = rep_hist_get_weighted_fractional_uptime(id, now);
}
- });
+ } SMARTLIST_FOREACH_END(node);
if (n_familiar)
guard_wfu = median_double(wfus, n_familiar);
if (guard_wfu > WFU_TO_GUARANTEE_GUARD)
@@ -1995,24 +2029,20 @@ version_from_platform(const char *platform)
*/
int
routerstatus_format_entry(char *buf, size_t buf_len,
- routerstatus_t *rs, const char *version,
+ const routerstatus_t *rs, const char *version,
routerstatus_format_type_t format)
{
int r;
- struct in_addr in;
char *cp;
char *summary;
char published[ISO_TIME_LEN+1];
- char ipaddr[INET_NTOA_BUF_LEN];
char identity64[BASE64_DIGEST_LEN+1];
char digest64[BASE64_DIGEST_LEN+1];
format_iso_time(published, rs->published_on);
digest_to_base64(identity64, rs->identity_digest);
digest_to_base64(digest64, rs->descriptor_digest);
- in.s_addr = htonl(rs->addr);
- tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
r = tor_snprintf(buf, buf_len,
"r %s %s %s%s%s %s %d %d\n",
@@ -2021,7 +2051,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
(format==NS_V3_CONSENSUS_MICRODESC)?"":digest64,
(format==NS_V3_CONSENSUS_MICRODESC)?"":" ",
published,
- ipaddr,
+ fmt_addr32(rs->addr),
(int)rs->or_port,
(int)rs->dir_port);
if (r<0) {
@@ -2049,7 +2079,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
rs->is_possible_guard?" Guard":"",
rs->is_hs_dir?" HSDir":"",
rs->is_named?" Named":"",
- rs->is_running?" Running":"",
+ rs->is_flagged_running?" Running":"",
rs->is_stable?" Stable":"",
rs->is_unnamed?" Unnamed":"",
rs->is_v2_dir?" V2Dir":"",
@@ -2071,7 +2101,7 @@ routerstatus_format_entry(char *buf, size_t buf_len,
}
if (format != NS_V2) {
- routerinfo_t* desc = router_get_by_digest(rs->identity_digest);
+ const routerinfo_t* desc = router_get_by_id_digest(rs->identity_digest);
uint32_t bw;
if (format != NS_CONTROL_PORT) {
@@ -2167,6 +2197,8 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b;
int first_is_auth, second_is_auth;
uint32_t bw_first, bw_second;
+ const node_t *node_first, *node_second;
+ int first_is_running, second_is_running;
/* we return -1 if first should appear before second... that is,
* if first is a better router. */
@@ -2189,9 +2221,14 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
else if (!first_is_auth && second_is_auth)
return 1;
- else if (first->is_running && !second->is_running)
+ node_first = node_get_by_id(first->cache_info.identity_digest);
+ node_second = node_get_by_id(second->cache_info.identity_digest);
+ first_is_running = node_first && node_first->is_running;
+ second_is_running = node_second && node_second->is_running;
+
+ if (first_is_running && !second_is_running)
return -1;
- else if (!first->is_running && second->is_running)
+ else if (!first_is_running && second_is_running)
return 1;
bw_first = router_get_advertised_bandwidth(first);
@@ -2215,7 +2252,7 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b)
static digestmap_t *
get_possible_sybil_list(const smartlist_t *routers)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
digestmap_t *omit_as_sybil;
smartlist_t *routers_by_ip = smartlist_create();
uint32_t last_addr;
@@ -2260,9 +2297,11 @@ get_possible_sybil_list(const smartlist_t *routers)
*/
void
set_routerstatus_from_routerinfo(routerstatus_t *rs,
- routerinfo_t *ri, time_t now,
+ node_t *node,
+ routerinfo_t *ri,
+ time_t now,
int naming, int listbadexits,
- int listbaddirs)
+ int listbaddirs, int vote_on_hsdirs)
{
int unstable_version =
!tor_version_as_new_as(ri->platform,"0.1.1.16-rc-cvs");
@@ -2272,48 +2311,47 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs,
router_digest_is_trusted_dir(ri->cache_info.identity_digest);
/* Already set by compute_performance_thresholds. */
- rs->is_exit = ri->is_exit;
- rs->is_stable = ri->is_stable =
- router_is_active(ri, now) &&
+ rs->is_exit = node->is_exit;
+ rs->is_stable = node->is_stable =
+ router_is_active(ri, node, now) &&
!dirserv_thinks_router_is_unreliable(now, ri, 1, 0) &&
!unstable_version;
- rs->is_fast = ri->is_fast =
- router_is_active(ri, now) &&
+ rs->is_fast = node->is_fast =
+ router_is_active(ri, node, now) &&
!dirserv_thinks_router_is_unreliable(now, ri, 0, 1);
- rs->is_running = ri->is_running; /* computed above */
+ rs->is_flagged_running = node->is_running; /* computed above */
if (naming) {
uint32_t name_status = dirserv_get_name_status(
- ri->cache_info.identity_digest, ri->nickname);
+ node->identity, ri->nickname);
rs->is_named = (naming && (name_status & FP_NAMED)) ? 1 : 0;
rs->is_unnamed = (naming && (name_status & FP_UNNAMED)) ? 1 : 0;
}
- rs->is_valid = ri->is_valid;
+ rs->is_valid = node->is_valid;
- if (rs->is_fast &&
+ 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))) {
- long tk = rep_hist_get_weighted_time_known(
- ri->cache_info.identity_digest, now);
- double wfu = rep_hist_get_weighted_fractional_uptime(
- ri->cache_info.identity_digest, now);
+ long tk = rep_hist_get_weighted_time_known(node->identity, now);
+ double wfu = rep_hist_get_weighted_fractional_uptime(node->identity, now);
rs->is_possible_guard = (wfu >= guard_wfu && tk >= guard_tk) ? 1 : 0;
} else {
rs->is_possible_guard = 0;
}
- rs->is_bad_directory = listbaddirs && ri->is_bad_directory;
- rs->is_bad_exit = listbadexits && ri->is_bad_exit;
- ri->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, now);
- rs->is_hs_dir = ri->is_hs_dir;
+
+ rs->is_bad_directory = listbaddirs && node->is_bad_directory;
+ rs->is_bad_exit = listbadexits && node->is_bad_exit;
+ node->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, node, now);
+ rs->is_hs_dir = vote_on_hsdirs && node->is_hs_dir;
rs->is_v2_dir = ri->dir_port != 0;
if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME))
rs->is_named = rs->is_unnamed = 0;
rs->published_on = ri->cache_info.published_on;
- memcpy(rs->identity_digest, ri->cache_info.identity_digest, DIGEST_LEN);
+ memcpy(rs->identity_digest, node->identity, DIGEST_LEN);
memcpy(rs->descriptor_digest, ri->cache_info.signed_descriptor_digest,
DIGEST_LEN);
rs->addr = ri->addr;
@@ -2330,7 +2368,7 @@ static void
clear_status_flags_on_sybil(routerstatus_t *rs)
{
rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
- rs->is_running = rs->is_named = rs->is_valid = rs->is_v2_dir =
+ rs->is_flagged_running = rs->is_named = rs->is_valid = rs->is_v2_dir =
rs->is_hs_dir = rs->is_possible_guard = rs->is_bad_exit =
rs->is_bad_directory = 0;
/* FFFF we might want some mechanism to check later on if we
@@ -2338,18 +2376,6 @@ clear_status_flags_on_sybil(routerstatus_t *rs)
* forget to add it to this clause. */
}
-/** Clear all the status flags in routerinfo <b>router</b>. We put this
- * function here because it's eerily similar to
- * clear_status_flags_on_sybil() above. One day we should merge them. */
-void
-router_clear_status_flags(routerinfo_t *router)
-{
- router->is_valid = router->is_running = router->is_hs_dir =
- router->is_fast = router->is_stable =
- router->is_possible_guard = router->is_exit =
- router->is_bad_exit = router->is_bad_directory = 0;
-}
-
/**
* Helper function to parse out a line in the measured bandwidth file
* into a measured_bw_line_t output structure. Returns -1 on failure
@@ -2467,7 +2493,7 @@ dirserv_read_measured_bandwidths(const char *from_file,
smartlist_t *routerstatuses)
{
char line[256];
- FILE *fp = fopen(from_file, "r");
+ FILE *fp = tor_fopen_cloexec(from_file, "r");
int applied_lines = 0;
time_t file_time;
int ok;
@@ -2527,7 +2553,7 @@ networkstatus_t *
dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
authority_cert_t *cert)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
networkstatus_t *v3_out = NULL;
uint32_t addr;
char *hostname = NULL, *client_versions = NULL, *server_versions = NULL;
@@ -2538,6 +2564,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
int naming = options->NamingAuthoritativeDir;
int listbadexits = options->AuthDirListBadExits;
int listbaddirs = options->AuthDirListBadDirs;
+ int vote_on_hsdirs = options->VoteOnHidServDirectoriesV2;
routerlist_t *rl = router_get_routerlist();
time_t now = time(NULL);
time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
@@ -2597,17 +2624,21 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
routerstatus_t *rs;
vote_routerstatus_t *vrs;
microdesc_t *md;
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ if (!node)
+ continue;
vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
rs = &vrs->status;
- set_routerstatus_from_routerinfo(rs, ri, now,
- naming, listbadexits, listbaddirs);
+ set_routerstatus_from_routerinfo(rs, node, ri, now,
+ naming, listbadexits, listbaddirs,
+ vote_on_hsdirs);
if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
clear_status_flags_on_sybil(rs);
if (!vote_on_reachability)
- rs->is_running = 0;
+ rs->is_flagged_running = 0;
vrs->version = version_from_platform(ri->platform);
md = dirvote_create_microdescriptor(ri);
@@ -2678,7 +2709,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
v3_out->server_versions = server_versions;
v3_out->known_flags = smartlist_create();
smartlist_split_string(v3_out->known_flags,
- "Authority Exit Fast Guard HSDir Stable V2Dir Valid",
+ "Authority Exit Fast Guard Stable V2Dir Valid",
0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
if (vote_on_reachability)
smartlist_add(v3_out->known_flags, tor_strdup("Running"));
@@ -2690,6 +2721,8 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
smartlist_add(v3_out->known_flags, tor_strdup("Named"));
smartlist_add(v3_out->known_flags, tor_strdup("Unnamed"));
}
+ if (vote_on_hsdirs)
+ smartlist_add(v3_out->known_flags, tor_strdup("HSDir"));
smartlist_sort_strings(v3_out->known_flags);
if (options->ConsensusParams) {
@@ -2739,12 +2772,10 @@ generate_v2_networkstatus_opinion(void)
char *status = NULL, *client_versions = NULL, *server_versions = NULL,
*identity_pkey = NULL, *hostname = NULL;
char *outp, *endp;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char fingerprint[FINGERPRINT_LEN+1];
- char ipaddr[INET_NTOA_BUF_LEN];
char published[ISO_TIME_LEN+1];
char digest[DIGEST_LEN];
- struct in_addr in;
uint32_t addr;
crypto_pk_env_t *private_key;
routerlist_t *rl = router_get_routerlist();
@@ -2754,6 +2785,7 @@ generate_v2_networkstatus_opinion(void)
int versioning = options->VersioningAuthoritativeDir;
int listbaddirs = options->AuthDirListBadDirs;
int listbadexits = options->AuthDirListBadExits;
+ int vote_on_hsdirs = options->VoteOnHidServDirectoriesV2;
const char *contact;
char *version_lines = NULL;
smartlist_t *routers = NULL;
@@ -2765,8 +2797,6 @@ generate_v2_networkstatus_opinion(void)
log_warn(LD_NET, "Couldn't resolve my hostname");
goto done;
}
- in.s_addr = htonl(addr);
- tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
format_iso_time(published, now);
@@ -2812,7 +2842,7 @@ generate_v2_networkstatus_opinion(void)
"dir-options%s%s%s%s\n"
"%s" /* client version line, server version line. */
"dir-signing-key\n%s",
- hostname, ipaddr,
+ hostname, fmt_addr32(addr),
(int)router_get_advertised_dir_port(options, 0),
fingerprint,
contact,
@@ -2844,9 +2874,14 @@ generate_v2_networkstatus_opinion(void)
if (ri->cache_info.published_on >= cutoff) {
routerstatus_t rs;
char *version = version_from_platform(ri->platform);
-
- set_routerstatus_from_routerinfo(&rs, ri, now,
- naming, listbadexits, listbaddirs);
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ if (!node) {
+ tor_free(version);
+ continue;
+ }
+ set_routerstatus_from_routerinfo(&rs, node, ri, now,
+ naming, listbadexits, listbaddirs,
+ vote_on_hsdirs);
if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
clear_status_flags_on_sybil(&rs);
@@ -2928,7 +2963,7 @@ dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
if (!strcmp(key,"authority")) {
if (authdir_mode_v2(get_options())) {
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (me)
smartlist_add(result,
tor_memdup(me->cache_info.identity_digest, DIGEST_LEN));
@@ -2947,7 +2982,7 @@ dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
} else {
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
- if (ds->type & V2_AUTHORITY)
+ if (ds->type & V2_DIRINFO)
smartlist_add(result, tor_memdup(ds->digest, DIGEST_LEN)));
}
smartlist_sort_digests(result);
@@ -3016,7 +3051,7 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
/* Treat "all" requests as if they were unencrypted */
for_unencrypted_conn = 1;
} else if (!strcmp(key, "authority")) {
- routerinfo_t *ri = router_get_my_routerinfo();
+ const routerinfo_t *ri = router_get_my_routerinfo();
if (ri)
smartlist_add(fps_out,
tor_memdup(ri->cache_info.identity_digest, DIGEST_LEN));
@@ -3036,8 +3071,8 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
if (for_unencrypted_conn) {
/* Remove anything that insists it not be sent unencrypted. */
- SMARTLIST_FOREACH(fps_out, char *, cp, {
- signed_descriptor_t *sd;
+ SMARTLIST_FOREACH_BEGIN(fps_out, char *, cp) {
+ const signed_descriptor_t *sd;
if (by_id)
sd = get_signed_descriptor_by_fp(cp,is_extrainfo,0);
else if (is_extrainfo)
@@ -3048,7 +3083,7 @@ dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
tor_free(cp);
SMARTLIST_DEL_CURRENT(fps_out, cp);
}
- });
+ } SMARTLIST_FOREACH_END(cp);
}
if (!smartlist_len(fps_out)) {
@@ -3087,9 +3122,9 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
smartlist_add(descs_out, &(r->cache_info)));
} else if (!strcmp(key, "/tor/server/authority")) {
- routerinfo_t *ri = router_get_my_routerinfo();
+ const routerinfo_t *ri = router_get_my_routerinfo();
if (ri)
- smartlist_add(descs_out, &(ri->cache_info));
+ smartlist_add(descs_out, (void*) &(ri->cache_info));
} else if (!strcmpstart(key, "/tor/server/d/")) {
smartlist_t *digests = smartlist_create();
key += strlen("/tor/server/d/");
@@ -3113,17 +3148,17 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
{
if (router_digest_is_me(d)) {
/* make sure desc_routerinfo exists */
- routerinfo_t *ri = router_get_my_routerinfo();
+ const routerinfo_t *ri = router_get_my_routerinfo();
if (ri)
- smartlist_add(descs_out, &(ri->cache_info));
+ smartlist_add(descs_out, (void*) &(ri->cache_info));
} else {
- routerinfo_t *ri = router_get_by_digest(d);
+ const routerinfo_t *ri = router_get_by_id_digest(d);
/* Don't actually serve a descriptor that everyone will think is
* expired. This is an (ugly) workaround to keep buggy 0.1.1.10
* Tors from downloading descriptors that they will throw away.
*/
if (ri && ri->cache_info.published_on > cutoff)
- smartlist_add(descs_out, &(ri->cache_info));
+ smartlist_add(descs_out, (void*) &(ri->cache_info));
}
});
SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
@@ -3190,7 +3225,8 @@ dirserv_orconn_tls_done(const char *address,
* an upload or a download. Used to decide whether to relaunch reachability
* testing for the server. */
int
-dirserv_should_launch_reachability_test(routerinfo_t *ri, routerinfo_t *ri_old)
+dirserv_should_launch_reachability_test(const routerinfo_t *ri,
+ const routerinfo_t *ri_old)
{
if (!authdir_mode_handles_descs(get_options(), ri->purpose))
return 0;
@@ -3314,7 +3350,7 @@ dirserv_remove_old_statuses(smartlist_t *fps, time_t cutoff)
* its extra-info document if <b>extrainfo</b> is true. Return
* NULL if not found or if the descriptor is older than
* <b>publish_cutoff</b>. */
-static signed_descriptor_t *
+static const signed_descriptor_t *
get_signed_descriptor_by_fp(const char *fp, int extrainfo,
time_t publish_cutoff)
{
@@ -3324,7 +3360,7 @@ get_signed_descriptor_by_fp(const char *fp, int extrainfo,
else
return &(router_get_my_routerinfo()->cache_info);
} else {
- routerinfo_t *ri = router_get_by_digest(fp);
+ const routerinfo_t *ri = router_get_by_id_digest(fp);
if (ri &&
ri->cache_info.published_on > publish_cutoff) {
if (extrainfo)
@@ -3392,7 +3428,7 @@ dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs,
tor_assert(fps);
if (is_serverdescs) {
int n = smartlist_len(fps);
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
result = (me?me->cache_info.signed_descriptor_len:2048) * n;
if (compressed)
result /= 2; /* observed compressibility is between 35 and 55%. */
@@ -3456,10 +3492,10 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn)
time_t publish_cutoff = time(NULL)-ROUTER_MAX_AGE_TO_PUBLISH;
while (smartlist_len(conn->fingerprint_stack) &&
- buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
+ connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
const char *body;
char *fp = smartlist_pop_last(conn->fingerprint_stack);
- signed_descriptor_t *sd = NULL;
+ const signed_descriptor_t *sd = NULL;
if (by_fp) {
sd = get_signed_descriptor_by_fp(fp, extra, publish_cutoff);
} else {
@@ -3517,7 +3553,7 @@ connection_dirserv_add_microdescs_to_outbuf(dir_connection_t *conn)
{
microdesc_cache_t *cache = get_microdesc_cache();
while (smartlist_len(conn->fingerprint_stack) &&
- buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
+ connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
char *fp256 = smartlist_pop_last(conn->fingerprint_stack);
microdesc_t *md = microdesc_cache_lookup_by_digest256(cache, fp256);
tor_free(fp256);
@@ -3556,7 +3592,7 @@ connection_dirserv_add_dir_bytes_to_outbuf(dir_connection_t *conn)
ssize_t bytes;
int64_t remaining;
- bytes = DIRSERV_BUFFER_MIN - buf_datalen(conn->_base.outbuf);
+ bytes = DIRSERV_BUFFER_MIN - connection_get_outbuf_len(TO_CONN(conn));
tor_assert(bytes > 0);
tor_assert(conn->cached_dir);
if (bytes < 8192)
@@ -3595,7 +3631,7 @@ static int
connection_dirserv_add_networkstatus_bytes_to_outbuf(dir_connection_t *conn)
{
- while (buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
+ while (connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
if (conn->cached_dir) {
int uncompressing = (conn->zlib_state != NULL);
int r = connection_dirserv_add_dir_bytes_to_outbuf(conn);
@@ -3641,7 +3677,7 @@ connection_dirserv_flushed_some(dir_connection_t *conn)
{
tor_assert(conn->_base.state == DIR_CONN_STATE_SERVER_WRITING);
- if (buf_datalen(conn->_base.outbuf) >= DIRSERV_BUFFER_MIN)
+ if (connection_get_outbuf_len(TO_CONN(conn)) >= DIRSERV_BUFFER_MIN)
return 0;
switch (conn->dir_spool_src) {
diff --git a/src/or/dirserv.h b/src/or/dirserv.h
index 569abfca2..d3fd90ceb 100644
--- a/src/or/dirserv.h
+++ b/src/or/dirserv.h
@@ -52,8 +52,6 @@
MAX_V_LINE_LEN \
)
-#define UNNAMED_ROUTER_NICKNAME "Unnamed"
-
int connection_dirserv_flushed_some(dir_connection_t *conn);
int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
@@ -73,15 +71,16 @@ int list_server_status_v1(smartlist_t *routers, char **router_status_out,
int dirserv_dump_directory_to_string(char **dir_out,
crypto_pk_env_t *private_key);
-int directory_fetches_from_authorities(or_options_t *options);
-int directory_fetches_dir_info_early(or_options_t *options);
-int directory_fetches_dir_info_later(or_options_t *options);
-int directory_caches_v2_dir_info(or_options_t *options);
+int directory_fetches_from_authorities(const or_options_t *options);
+int directory_fetches_dir_info_early(const or_options_t *options);
+int directory_fetches_dir_info_later(const or_options_t *options);
+int directory_caches_v2_dir_info(const or_options_t *options);
#define directory_caches_v1_dir_info(o) directory_caches_v2_dir_info(o)
-int directory_caches_dir_info(or_options_t *options);
-int directory_permits_begindir_requests(or_options_t *options);
-int directory_permits_controller_requests(or_options_t *options);
-int directory_too_idle_to_fetch_descriptors(or_options_t *options, time_t now);
+int directory_caches_dir_info(const or_options_t *options);
+int directory_permits_begindir_requests(const or_options_t *options);
+int directory_permits_controller_requests(const or_options_t *options);
+int directory_too_idle_to_fetch_descriptors(const or_options_t *options,
+ time_t now);
void directory_set_dirty(void);
cached_dir_t *dirserv_get_directory(void);
@@ -111,13 +110,19 @@ void dirserv_orconn_tls_done(const char *address,
uint16_t or_port,
const char *digest_rcvd,
int as_advertised);
-int dirserv_should_launch_reachability_test(routerinfo_t *ri,
- routerinfo_t *ri_old);
+int dirserv_should_launch_reachability_test(const routerinfo_t *ri,
+ const routerinfo_t *ri_old);
void dirserv_single_reachability_test(time_t now, routerinfo_t *router);
void dirserv_test_reachability(time_t now);
int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
- int complain);
-int dirserv_would_reject_router(routerstatus_t *rs);
+ int complain,
+ int *valid_out);
+uint32_t dirserv_router_get_status(const routerinfo_t *router,
+ const char **msg);
+void dirserv_set_node_flags_from_authoritative_status(node_t *node,
+ uint32_t authstatus);
+
+int dirserv_would_reject_router(const routerstatus_t *rs);
int dirserv_remove_old_statuses(smartlist_t *fps, time_t cutoff);
int dirserv_have_any_serverdesc(smartlist_t *fps, int spool_src);
int dirserv_have_any_microdesc(const smartlist_t *fps);
@@ -126,7 +131,7 @@ size_t dirserv_estimate_data_size(smartlist_t *fps, int is_serverdescs,
size_t dirserv_estimate_microdesc_size(const smartlist_t *fps, int compressed);
int routerstatus_format_entry(char *buf, size_t buf_len,
- routerstatus_t *rs, const char *platform,
+ const routerstatus_t *rs, const char *platform,
routerstatus_format_type_t format);
void dirserv_free_all(void);
void cached_dir_decref(cached_dir_t *d);
diff --git a/src/or/dirvote.c b/src/or/dirvote.c
index c6ce9f677..bf34c62af 100644
--- a/src/or/dirvote.c
+++ b/src/or/dirvote.c
@@ -83,9 +83,7 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
const char *client_versions = NULL, *server_versions = NULL;
char *outp, *endp;
char fingerprint[FINGERPRINT_LEN+1];
- char ipaddr[INET_NTOA_BUF_LEN];
char digest[DIGEST_LEN];
- struct in_addr in;
uint32_t addr;
routerlist_t *rl = router_get_routerlist();
char *version_lines = NULL;
@@ -98,8 +96,6 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
voter = smartlist_get(v3_ns->voters, 0);
addr = voter->addr;
- in.s_addr = htonl(addr);
- tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
base16_encode(fingerprint, sizeof(fingerprint),
v3_ns->cert->cache_info.identity_digest, DIGEST_LEN);
@@ -186,7 +182,8 @@ format_networkstatus_vote(crypto_pk_env_t *private_signing_key,
flags,
params,
voter->nickname, fingerprint, voter->address,
- ipaddr, voter->dir_port, voter->or_port, voter->contact);
+ fmt_addr32(addr), voter->dir_port, voter->or_port,
+ voter->contact);
if (r < 0) {
log_err(LD_BUG, "Insufficient memory for network status line");
@@ -1530,8 +1527,6 @@ networkstatus_compute_consensus(smartlist_t *votes,
smartlist_sort(dir_sources, _compare_dir_src_ents_by_authority_id);
SMARTLIST_FOREACH_BEGIN(dir_sources, const dir_src_ent_t *, e) {
- struct in_addr in;
- char ip[INET_NTOA_BUF_LEN];
char fingerprint[HEX_DIGEST_LEN+1];
char votedigest[HEX_DIGEST_LEN+1];
networkstatus_t *v = e->v;
@@ -1541,8 +1536,6 @@ networkstatus_compute_consensus(smartlist_t *votes,
if (e->is_legacy)
tor_assert(consensus_method >= 2);
- in.s_addr = htonl(voter->addr);
- tor_inet_ntoa(&in, ip, sizeof(ip));
base16_encode(fingerprint, sizeof(fingerprint), e->digest, DIGEST_LEN);
base16_encode(votedigest, sizeof(votedigest), voter->vote_digest,
DIGEST_LEN);
@@ -1550,7 +1543,7 @@ networkstatus_compute_consensus(smartlist_t *votes,
tor_asprintf(&buf,
"dir-source %s%s %s %s %s %d %d\n",
voter->nickname, e->is_legacy ? "-legacy" : "",
- fingerprint, voter->address, ip,
+ fingerprint, voter->address, fmt_addr32(voter->addr),
voter->dir_port,
voter->or_port);
smartlist_add(chunks, buf);
@@ -2511,7 +2504,7 @@ authority_cert_dup(authority_cert_t *cert)
void
dirvote_get_preferred_voting_intervals(vote_timing_t *timing_out)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
tor_assert(timing_out);
@@ -2585,7 +2578,7 @@ static struct {
/** Set voting_schedule to hold the timing for the next vote we should be
* doing. */
void
-dirvote_recalculate_timing(or_options_t *options, time_t now)
+dirvote_recalculate_timing(const or_options_t *options, time_t now)
{
int interval, vote_delay, dist_delay;
time_t start;
@@ -2636,7 +2629,7 @@ dirvote_recalculate_timing(or_options_t *options, time_t now)
/** Entry point: Take whatever voting actions are pending as of <b>now</b>. */
void
-dirvote_act(or_options_t *options, time_t now)
+dirvote_act(const or_options_t *options, time_t now)
{
if (!authdir_mode_v3(options))
return;
@@ -2751,7 +2744,7 @@ dirvote_perform_vote(void)
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_VOTE,
ROUTER_PURPOSE_GENERAL,
- V3_AUTHORITY,
+ V3_DIRINFO,
pending_vote->vote_body->dir,
pending_vote->vote_body->dir_len, 0);
log_notice(LD_DIR, "Vote posted.");
@@ -2770,7 +2763,7 @@ dirvote_fetch_missing_votes(void)
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
{
- if (!(ds->type & V3_AUTHORITY))
+ if (!(ds->type & V3_DIRINFO))
continue;
if (!dirvote_get_vote(ds->v3_identity_digest,
DGV_BY_ID|DGV_INCLUDE_PENDING)) {
@@ -2883,7 +2876,7 @@ list_v3_auth_ids(void)
char *keys;
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
- if ((ds->type & V3_AUTHORITY) &&
+ if ((ds->type & V3_DIRINFO) &&
!tor_digest_is_zero(ds->v3_identity_digest))
smartlist_add(known_v3_keys,
tor_strdup(hex_str(ds->v3_identity_digest, DIGEST_LEN))));
@@ -3078,7 +3071,7 @@ dirvote_compute_consensuses(void)
if (!pending_vote_list)
pending_vote_list = smartlist_create();
- n_voters = get_n_authorities(V3_AUTHORITY);
+ n_voters = get_n_authorities(V3_DIRINFO);
n_votes = smartlist_len(pending_vote_list);
if (n_votes <= n_voters/2) {
log_warn(LD_DIR, "We don't have enough votes to generate a consensus: "
@@ -3217,7 +3210,7 @@ dirvote_compute_consensuses(void)
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_SIGNATURES,
ROUTER_PURPOSE_GENERAL,
- V3_AUTHORITY,
+ V3_DIRINFO,
pending_consensus_signatures,
strlen(pending_consensus_signatures), 0);
log_notice(LD_DIR, "Signature(s) posted.");
diff --git a/src/or/dirvote.h b/src/or/dirvote.h
index 67540a37f..d19635173 100644
--- a/src/or/dirvote.h
+++ b/src/or/dirvote.h
@@ -41,8 +41,8 @@ authority_cert_t *authority_cert_dup(authority_cert_t *cert);
/* vote scheduling */
void dirvote_get_preferred_voting_intervals(vote_timing_t *timing_out);
time_t dirvote_get_start_of_next_interval(time_t now, int interval);
-void dirvote_recalculate_timing(or_options_t *options, time_t now);
-void dirvote_act(or_options_t *options, time_t now);
+void dirvote_recalculate_timing(const or_options_t *options, time_t now);
+void dirvote_act(const or_options_t *options, time_t now);
/* invoked on timers and by outside triggers. */
struct pending_vote_t * dirvote_add_vote(const char *vote_body,
@@ -60,9 +60,10 @@ const char *dirvote_get_pending_detached_signatures(void);
#define DGV_INCLUDE_PREVIOUS 4
const cached_dir_t *dirvote_get_vote(const char *fp, int flags);
void set_routerstatus_from_routerinfo(routerstatus_t *rs,
+ node_t *node,
routerinfo_t *ri, time_t now,
int naming, int listbadexits,
- int listbaddirs);
+ int listbaddirs, int vote_on_hsdirs);
void router_clear_status_flags(routerinfo_t *ri);
networkstatus_t *
dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
diff --git a/src/or/dns.c b/src/or/dns.c
index 9b6b98afa..5d86e81fa 100644
--- a/src/or/dns.c
+++ b/src/or/dns.c
@@ -276,7 +276,7 @@ dns_init(void)
int
dns_reset(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (! server_mode(options)) {
if (!the_evdns_base) {
@@ -675,7 +675,7 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve,
cached_resolve_t *resolve;
cached_resolve_t search;
pending_connection_t *pending_connection;
- routerinfo_t *me;
+ const routerinfo_t *me;
tor_addr_t addr;
time_t now = time(NULL);
uint8_t is_reverse = 0;
@@ -1026,7 +1026,7 @@ add_answer_to_cache(const char *address, uint8_t is_reverse, uint32_t addr,
static INLINE int
is_test_address(const char *address)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
return options->ServerDNSTestAddresses &&
smartlist_string_isin_case(options->ServerDNSTestAddresses, address);
}
@@ -1177,7 +1177,7 @@ evdns_err_is_transient(int err)
static int
configure_nameservers(int force)
{
- or_options_t *options;
+ const or_options_t *options;
const char *conf_fname;
struct stat st;
int r;
@@ -1595,7 +1595,7 @@ launch_wildcard_check(int min_len, int max_len, const char *suffix)
static void
launch_test_addresses(int fd, short event, void *args)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
struct evdns_request *req;
(void)fd;
(void)event;
diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c
index f2c473dfc..7f519398f 100644
--- a/src/or/dnsserv.c
+++ b/src/or/dnsserv.c
@@ -29,8 +29,10 @@
* DNSPort. We need to eventually answer the request <b>req</b>.
*/
static void
-evdns_server_callback(struct evdns_server_request *req, void *_data)
+evdns_server_callback(struct evdns_server_request *req, void *data_)
{
+ const listener_connection_t *listener = data_;
+ entry_connection_t *entry_conn;
edge_connection_t *conn;
int i = 0;
struct evdns_server_question *q = NULL;
@@ -43,7 +45,7 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
char *q_name;
tor_assert(req);
- tor_assert(_data == NULL);
+
log_info(LD_APP, "Got a new DNS request!");
req->flags |= 0x80; /* set RA */
@@ -114,8 +116,9 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
}
/* Make a new dummy AP connection, and attach the request to it. */
- conn = edge_connection_new(CONN_TYPE_AP, AF_INET);
- conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
+ entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET);
+ conn = ENTRY_TO_EDGE_CONN(entry_conn);
+ TO_CONN(conn)->state = AP_CONN_STATE_RESOLVE_WAIT;
conn->is_dns_request = 1;
tor_addr_copy(&TO_CONN(conn)->addr, &tor_addr);
@@ -123,23 +126,27 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
TO_CONN(conn)->address = tor_dup_addr(&tor_addr);
if (q->type == EVDNS_TYPE_A)
- conn->socks_request->command = SOCKS_COMMAND_RESOLVE;
+ entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE;
else
- conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
+ entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
- strlcpy(conn->socks_request->address, q->name,
- sizeof(conn->socks_request->address));
+ strlcpy(entry_conn->socks_request->address, q->name,
+ sizeof(entry_conn->socks_request->address));
- conn->dns_server_request = req;
+ entry_conn->socks_request->listener_type = listener->_base.type;
+ entry_conn->dns_server_request = req;
+ entry_conn->isolation_flags = listener->isolation_flags;
+ entry_conn->session_group = listener->session_group;
+ entry_conn->nym_epoch = get_signewnym_epoch();
- if (connection_add(TO_CONN(conn)) < 0) {
+ if (connection_add(ENTRY_TO_CONN(entry_conn)) < 0) {
log_warn(LD_APP, "Couldn't register dummy connection for DNS request");
evdns_server_request_respond(req, DNS_ERR_SERVERFAILED);
- connection_free(TO_CONN(conn));
+ connection_free(ENTRY_TO_CONN(entry_conn));
return;
}
- control_event_stream_status(conn, STREAM_EVENT_NEW, 0);
+ control_event_stream_status(entry_conn, STREAM_EVENT_NEW, 0);
/* Now, unless a controller asked us to leave streams unattached,
* throw the connection over to get rewritten (which will
@@ -148,7 +155,7 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
log_info(LD_APP, "Passing request for %s to rewrite_and_attach.",
escaped_safe_str_client(q->name));
q_name = tor_strdup(q->name); /* q could be freed in rewrite_and_attach */
- connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL);
+ connection_ap_rewrite_and_attach_if_allowed(entry_conn, NULL, NULL);
/* Now, the connection is marked if it was bad. */
log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.",
@@ -164,22 +171,30 @@ evdns_server_callback(struct evdns_server_request *req, void *_data)
int
dnsserv_launch_request(const char *name, int reverse)
{
+ entry_connection_t *entry_conn;
edge_connection_t *conn;
char *q_name;
/* Make a new dummy AP connection, and attach the request to it. */
- conn = edge_connection_new(CONN_TYPE_AP, AF_INET);
+ entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET);
+ conn = ENTRY_TO_EDGE_CONN(entry_conn);
conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT;
if (reverse)
- conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
+ entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR;
else
- conn->socks_request->command = SOCKS_COMMAND_RESOLVE;
+ entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE;
conn->is_dns_request = 1;
- strlcpy(conn->socks_request->address, name,
- sizeof(conn->socks_request->address));
+ strlcpy(entry_conn->socks_request->address, name,
+ sizeof(entry_conn->socks_request->address));
+
+ entry_conn->socks_request->listener_type = CONN_TYPE_CONTROL_LISTENER;
+ entry_conn->original_dest_address = tor_strdup(name);
+ entry_conn->session_group = SESSION_GROUP_CONTROL_RESOLVE;
+ entry_conn->nym_epoch = get_signewnym_epoch();
+ entry_conn->isolation_flags = ISO_DEFAULT;
if (connection_add(TO_CONN(conn))<0) {
log_warn(LD_APP, "Couldn't register dummy connection for RESOLVE request");
@@ -194,7 +209,7 @@ dnsserv_launch_request(const char *name, int reverse)
log_info(LD_APP, "Passing request for %s to rewrite_and_attach.",
escaped_safe_str_client(name));
q_name = tor_strdup(name); /* q could be freed in rewrite_and_attach */
- connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL);
+ connection_ap_rewrite_and_attach_if_allowed(entry_conn, NULL, NULL);
/* Now, the connection is marked if it was bad. */
log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.",
@@ -206,7 +221,7 @@ dnsserv_launch_request(const char *name, int reverse)
/** If there is a pending request on <b>conn</b> that's waiting for an answer,
* send back an error and free the request. */
void
-dnsserv_reject_request(edge_connection_t *conn)
+dnsserv_reject_request(entry_connection_t *conn)
{
if (conn->dns_server_request) {
evdns_server_request_respond(conn->dns_server_request,
@@ -252,7 +267,7 @@ evdns_get_orig_address(const struct evdns_server_request *req,
* <b>answer_len</b>, in <b>answer</b>, with TTL <b>ttl</b>. Doesn't do
* any caching; that's handled elsewhere. */
void
-dnsserv_resolved(edge_connection_t *conn,
+dnsserv_resolved(entry_connection_t *conn,
int answer_type,
size_t answer_len,
const char *answer,
@@ -305,12 +320,15 @@ dnsserv_resolved(edge_connection_t *conn,
void
dnsserv_configure_listener(connection_t *conn)
{
+ listener_connection_t *listener_conn;
tor_assert(conn);
tor_assert(SOCKET_OK(conn->s));
tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER);
- conn->dns_server_port =
- tor_evdns_add_server_port(conn->s, 0, evdns_server_callback, NULL);
+ listener_conn = TO_LISTENER_CONN(conn);
+ listener_conn->dns_server_port =
+ tor_evdns_add_server_port(conn->s, 0, evdns_server_callback,
+ listener_conn);
}
/** Free the evdns server port for <b>conn</b>, which must be an
@@ -318,12 +336,15 @@ dnsserv_configure_listener(connection_t *conn)
void
dnsserv_close_listener(connection_t *conn)
{
+ listener_connection_t *listener_conn;
tor_assert(conn);
tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER);
- if (conn->dns_server_port) {
- evdns_close_server_port(conn->dns_server_port);
- conn->dns_server_port = NULL;
+ listener_conn = TO_LISTENER_CONN(conn);
+
+ if (listener_conn->dns_server_port) {
+ evdns_close_server_port(listener_conn->dns_server_port);
+ listener_conn->dns_server_port = NULL;
}
}
diff --git a/src/or/dnsserv.h b/src/or/dnsserv.h
index fcca86888..73ec36564 100644
--- a/src/or/dnsserv.h
+++ b/src/or/dnsserv.h
@@ -14,12 +14,12 @@
void dnsserv_configure_listener(connection_t *conn);
void dnsserv_close_listener(connection_t *conn);
-void dnsserv_resolved(edge_connection_t *conn,
+void dnsserv_resolved(entry_connection_t *conn,
int answer_type,
size_t answer_len,
const char *answer,
int ttl);
-void dnsserv_reject_request(edge_connection_t *conn);
+void dnsserv_reject_request(entry_connection_t *conn);
int dnsserv_launch_request(const char *name, int is_reverse);
#endif
diff --git a/src/or/eventdns.c b/src/or/eventdns.c
index 42e16aec7..7fe376baf 100644
--- a/src/or/eventdns.c
+++ b/src/or/eventdns.c
@@ -1831,8 +1831,8 @@ evdns_server_request_respond(struct evdns_server_request *_req, int err)
r = sendto(port->socket, req->response, req->response_len, 0,
(struct sockaddr*) &req->addr, req->addrlen);
if (r<0) {
- int err = last_error(port->socket);
- if (! error_is_eagain(err))
+ int error = last_error(port->socket);
+ if (! error_is_eagain(error))
return -1;
if (port->pending_replies) {
@@ -2291,7 +2291,7 @@ _evdns_nameserver_add_impl(const struct sockaddr *address,
evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
- ns->socket = socket(address->sa_family, SOCK_DGRAM, 0);
+ ns->socket = tor_open_socket(address->sa_family, SOCK_DGRAM, 0);
if (ns->socket < 0) { err = 1; goto out1; }
#ifdef WIN32
{
@@ -3040,7 +3040,7 @@ evdns_resolv_conf_parse(int flags, const char *const filename) {
log(EVDNS_LOG_DEBUG, "Parsing resolv.conf file %s", filename);
- fd = open(filename, O_RDONLY);
+ fd = tor_open_cloexec(filename, O_RDONLY, 0);
if (fd < 0) {
evdns_resolv_set_defaults(flags);
return 1;
@@ -3460,7 +3460,7 @@ main(int c, char **v) {
if (servertest) {
int sock;
struct sockaddr_in my_addr;
- sock = socket(PF_INET, SOCK_DGRAM, 0);
+ sock = tor_open_socket(PF_INET, SOCK_DGRAM, 0);
fcntl(sock, F_SETFL, O_NONBLOCK);
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(10053);
diff --git a/src/or/geoip.c b/src/or/geoip.c
index c51142c82..67dea965f 100644
--- a/src/or/geoip.c
+++ b/src/or/geoip.c
@@ -44,6 +44,9 @@ static strmap_t *country_idxplus1_by_lc_code = NULL;
/** A list of all known geoip_entry_t, sorted by ip_low. */
static smartlist_t *geoip_entries = NULL;
+/** SHA1 digest of the GeoIP file to include in extra-info descriptors. */
+static char geoip_digest[DIGEST_LEN];
+
/** Return the index of the <b>country</b>'s entry in the GeoIP DB
* if it is a valid 2-letter country code, otherwise return -1.
*/
@@ -113,10 +116,10 @@ geoip_parse_entry(const char *line)
++line;
if (*line == '#')
return 0;
- if (sscanf(line,"%u,%u,%2s", &low, &high, b) == 3) {
+ if (tor_sscanf(line,"%u,%u,%2s", &low, &high, b) == 3) {
geoip_add_entry(low, high, b);
return 0;
- } else if (sscanf(line,"\"%u\",\"%u\",\"%2s\",", &low, &high, b) == 3) {
+ } else if (tor_sscanf(line,"\"%u\",\"%u\",\"%2s\",", &low, &high, b) == 3) {
geoip_add_entry(low, high, b);
return 0;
} else {
@@ -159,7 +162,7 @@ _geoip_compare_key_to_entry(const void *_key, const void **_member)
/** Return 1 if we should collect geoip stats on bridge users, and
* include them in our extrainfo descriptor. Else return 0. */
int
-should_record_bridge_info(or_options_t *options)
+should_record_bridge_info(const or_options_t *options)
{
return options->BridgeRelay && options->BridgeRecordUsageByCountry;
}
@@ -196,13 +199,14 @@ init_geoip_countries(void)
* with '#' (comments).
*/
int
-geoip_load_file(const char *filename, or_options_t *options)
+geoip_load_file(const char *filename, const or_options_t *options)
{
FILE *f;
const char *msg = "";
int severity = options_need_geoip_info(options, &msg) ? LOG_WARN : LOG_INFO;
+ crypto_digest_env_t *geoip_digest_env = NULL;
clear_geoip_db();
- if (!(f = fopen(filename, "r"))) {
+ if (!(f = tor_fopen_cloexec(filename, "r"))) {
log_fn(severity, LD_GENERAL, "Failed to open GEOIP file %s. %s",
filename, msg);
return -1;
@@ -214,11 +218,13 @@ geoip_load_file(const char *filename, or_options_t *options)
smartlist_free(geoip_entries);
}
geoip_entries = smartlist_create();
+ geoip_digest_env = crypto_new_digest_env();
log_notice(LD_GENERAL, "Parsing GEOIP file %s.", filename);
while (!feof(f)) {
char buf[512];
if (fgets(buf, (int)sizeof(buf), f) == NULL)
break;
+ crypto_digest_add_bytes(geoip_digest_env, buf, strlen(buf));
/* FFFF track full country name. */
geoip_parse_entry(buf);
}
@@ -231,6 +237,11 @@ geoip_load_file(const char *filename, or_options_t *options)
* country. */
refresh_all_country_info();
+ /* Remember file digest so that we can include it in our extra-info
+ * descriptors. */
+ crypto_digest_get_digest(geoip_digest_env, geoip_digest, DIGEST_LEN);
+ crypto_free_digest_env(geoip_digest_env);
+
return 0;
}
@@ -278,6 +289,15 @@ geoip_is_loaded(void)
return geoip_countries != NULL && geoip_entries != NULL;
}
+/** Return the hex-encoded SHA1 digest of the loaded GeoIP file. The
+ * result does not need to be deallocated, but will be overwritten by the
+ * next call of hex_str(). */
+const char *
+geoip_db_digest(void)
+{
+ return hex_str(geoip_digest, DIGEST_LEN);
+}
+
/** Entry in a map from IP address to the last time we've seen an incoming
* connection from that IP address. Used by bridges only, to track which
* countries have them blocked. */
@@ -404,7 +424,7 @@ void
geoip_note_client_seen(geoip_client_action_t action,
uint32_t addr, time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
clientmap_entry_t lookup, *ent;
if (action == GEOIP_CLIENT_CONNECT) {
/* Only remember statistics as entry guard or as bridge. */
@@ -910,10 +930,9 @@ geoip_dirreq_stats_init(time_t now)
start_of_dirreq_stats_interval = now;
}
-/** Stop collecting directory request stats in a way that we can re-start
- * doing so in geoip_dirreq_stats_init(). */
+/** Reset counters for dirreq stats. */
void
-geoip_dirreq_stats_term(void)
+geoip_reset_dirreq_stats(time_t now)
{
SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, {
c->n_v2_ns_requests = c->n_v3_ns_requests = 0;
@@ -945,59 +964,41 @@ geoip_dirreq_stats_term(void)
tor_free(this);
}
}
- start_of_dirreq_stats_interval = 0;
+ start_of_dirreq_stats_interval = now;
}
-/** Write dirreq statistics to $DATADIR/stats/dirreq-stats and return when
- * we would next want to write. */
-time_t
-geoip_dirreq_stats_write(time_t now)
+/** Stop collecting directory request stats in a way that we can re-start
+ * doing so in geoip_dirreq_stats_init(). */
+void
+geoip_dirreq_stats_term(void)
{
- char *statsdir = NULL, *filename = NULL;
- char *data_v2 = NULL, *data_v3 = NULL;
- char written[ISO_TIME_LEN+1];
- open_file_t *open_file = NULL;
+ geoip_reset_dirreq_stats(0);
+}
+
+/** Return a newly allocated string containing the dirreq statistics
+ * until <b>now</b>, or NULL if we're not collecting dirreq stats. */
+char *
+geoip_format_dirreq_stats(time_t now)
+{
+ char t[ISO_TIME_LEN+1];
double v2_share = 0.0, v3_share = 0.0;
- FILE *out;
int i;
+ char *v3_ips_string, *v2_ips_string, *v3_reqs_string, *v2_reqs_string,
+ *v2_share_string = NULL, *v3_share_string = NULL,
+ *v3_direct_dl_string, *v2_direct_dl_string,
+ *v3_tunneled_dl_string, *v2_tunneled_dl_string;
+ char *result;
if (!start_of_dirreq_stats_interval)
- return 0; /* Not initialized. */
- if (start_of_dirreq_stats_interval + WRITE_STATS_INTERVAL > now)
- goto done; /* Not ready to write. */
+ return NULL; /* Not initialized. */
- /* Discard all items in the client history that are too old. */
- geoip_remove_old_clients(start_of_dirreq_stats_interval);
+ format_iso_time(t, now);
+ v2_ips_string = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS_V2);
+ v3_ips_string = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS);
+ v2_reqs_string = geoip_get_request_history(
+ GEOIP_CLIENT_NETWORKSTATUS_V2);
+ v3_reqs_string = geoip_get_request_history(GEOIP_CLIENT_NETWORKSTATUS);
- statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0)
- goto done;
- filename = get_datadir_fname2("stats", "dirreq-stats");
- data_v2 = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS_V2);
- data_v3 = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS);
- format_iso_time(written, now);
- out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND | O_TEXT,
- 0600, &open_file);
- if (!out)
- goto done;
- if (fprintf(out, "dirreq-stats-end %s (%d s)\ndirreq-v3-ips %s\n"
- "dirreq-v2-ips %s\n", written,
- (unsigned) (now - start_of_dirreq_stats_interval),
- data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0)
- goto done;
- tor_free(data_v2);
- tor_free(data_v3);
-
- data_v2 = geoip_get_request_history(GEOIP_CLIENT_NETWORKSTATUS_V2);
- data_v3 = geoip_get_request_history(GEOIP_CLIENT_NETWORKSTATUS);
- if (fprintf(out, "dirreq-v3-reqs %s\ndirreq-v2-reqs %s\n",
- data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0)
- goto done;
- tor_free(data_v2);
- tor_free(data_v3);
- SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, {
- c->n_v2_ns_requests = c->n_v3_ns_requests = 0;
- });
#define RESPONSE_GRANULARITY 8
for (i = 0; i < GEOIP_NS_RESPONSE_NUM; i++) {
ns_v2_responses[i] = round_uint32_to_next_multiple_of(
@@ -1006,61 +1007,117 @@ geoip_dirreq_stats_write(time_t now)
ns_v3_responses[i], RESPONSE_GRANULARITY);
}
#undef RESPONSE_GRANULARITY
- if (fprintf(out, "dirreq-v3-resp ok=%u,not-enough-sigs=%u,unavailable=%u,"
- "not-found=%u,not-modified=%u,busy=%u\n",
- ns_v3_responses[GEOIP_SUCCESS],
- ns_v3_responses[GEOIP_REJECT_NOT_ENOUGH_SIGS],
- ns_v3_responses[GEOIP_REJECT_UNAVAILABLE],
- ns_v3_responses[GEOIP_REJECT_NOT_FOUND],
- ns_v3_responses[GEOIP_REJECT_NOT_MODIFIED],
- ns_v3_responses[GEOIP_REJECT_BUSY]) < 0)
- goto done;
- if (fprintf(out, "dirreq-v2-resp ok=%u,unavailable=%u,"
- "not-found=%u,not-modified=%u,busy=%u\n",
- ns_v2_responses[GEOIP_SUCCESS],
- ns_v2_responses[GEOIP_REJECT_UNAVAILABLE],
- ns_v2_responses[GEOIP_REJECT_NOT_FOUND],
- ns_v2_responses[GEOIP_REJECT_NOT_MODIFIED],
- ns_v2_responses[GEOIP_REJECT_BUSY]) < 0)
- goto done;
- memset(ns_v2_responses, 0, sizeof(ns_v2_responses));
- memset(ns_v3_responses, 0, sizeof(ns_v3_responses));
+
if (!geoip_get_mean_shares(now, &v2_share, &v3_share)) {
- if (fprintf(out, "dirreq-v2-share %0.2lf%%\n", v2_share*100) < 0)
- goto done;
- if (fprintf(out, "dirreq-v3-share %0.2lf%%\n", v3_share*100) < 0)
- goto done;
+ tor_asprintf(&v2_share_string, "dirreq-v2-share %0.2lf%%\n",
+ v2_share*100);
+ tor_asprintf(&v3_share_string, "dirreq-v3-share %0.2lf%%\n",
+ v3_share*100);
}
- data_v2 = geoip_get_dirreq_history(GEOIP_CLIENT_NETWORKSTATUS_V2,
- DIRREQ_DIRECT);
- data_v3 = geoip_get_dirreq_history(GEOIP_CLIENT_NETWORKSTATUS,
- DIRREQ_DIRECT);
- if (fprintf(out, "dirreq-v3-direct-dl %s\ndirreq-v2-direct-dl %s\n",
- data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0)
- goto done;
- tor_free(data_v2);
- tor_free(data_v3);
- data_v2 = geoip_get_dirreq_history(GEOIP_CLIENT_NETWORKSTATUS_V2,
- DIRREQ_TUNNELED);
- data_v3 = geoip_get_dirreq_history(GEOIP_CLIENT_NETWORKSTATUS,
- DIRREQ_TUNNELED);
- if (fprintf(out, "dirreq-v3-tunneled-dl %s\ndirreq-v2-tunneled-dl %s\n",
- data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0)
- goto done;
+ v2_direct_dl_string = geoip_get_dirreq_history(
+ GEOIP_CLIENT_NETWORKSTATUS_V2, DIRREQ_DIRECT);
+ v3_direct_dl_string = geoip_get_dirreq_history(
+ GEOIP_CLIENT_NETWORKSTATUS, DIRREQ_DIRECT);
+
+ v2_tunneled_dl_string = geoip_get_dirreq_history(
+ GEOIP_CLIENT_NETWORKSTATUS_V2, DIRREQ_TUNNELED);
+ v3_tunneled_dl_string = geoip_get_dirreq_history(
+ GEOIP_CLIENT_NETWORKSTATUS, DIRREQ_TUNNELED);
+
+ /* Put everything together into a single string. */
+ tor_asprintf(&result, "dirreq-stats-end %s (%d s)\n"
+ "dirreq-v3-ips %s\n"
+ "dirreq-v2-ips %s\n"
+ "dirreq-v3-reqs %s\n"
+ "dirreq-v2-reqs %s\n"
+ "dirreq-v3-resp ok=%u,not-enough-sigs=%u,unavailable=%u,"
+ "not-found=%u,not-modified=%u,busy=%u\n"
+ "dirreq-v2-resp ok=%u,unavailable=%u,"
+ "not-found=%u,not-modified=%u,busy=%u\n"
+ "%s"
+ "%s"
+ "dirreq-v3-direct-dl %s\n"
+ "dirreq-v2-direct-dl %s\n"
+ "dirreq-v3-tunneled-dl %s\n"
+ "dirreq-v2-tunneled-dl %s\n",
+ t,
+ (unsigned) (now - start_of_dirreq_stats_interval),
+ v3_ips_string ? v3_ips_string : "",
+ v2_ips_string ? v2_ips_string : "",
+ v3_reqs_string ? v3_reqs_string : "",
+ v2_reqs_string ? v2_reqs_string : "",
+ ns_v3_responses[GEOIP_SUCCESS],
+ ns_v3_responses[GEOIP_REJECT_NOT_ENOUGH_SIGS],
+ ns_v3_responses[GEOIP_REJECT_UNAVAILABLE],
+ ns_v3_responses[GEOIP_REJECT_NOT_FOUND],
+ ns_v3_responses[GEOIP_REJECT_NOT_MODIFIED],
+ ns_v3_responses[GEOIP_REJECT_BUSY],
+ ns_v2_responses[GEOIP_SUCCESS],
+ ns_v2_responses[GEOIP_REJECT_UNAVAILABLE],
+ ns_v2_responses[GEOIP_REJECT_NOT_FOUND],
+ ns_v2_responses[GEOIP_REJECT_NOT_MODIFIED],
+ ns_v2_responses[GEOIP_REJECT_BUSY],
+ v2_share_string ? v2_share_string : "",
+ v3_share_string ? v3_share_string : "",
+ v3_direct_dl_string ? v3_direct_dl_string : "",
+ v2_direct_dl_string ? v2_direct_dl_string : "",
+ v3_tunneled_dl_string ? v3_tunneled_dl_string : "",
+ v2_tunneled_dl_string ? v2_tunneled_dl_string : "");
+
+ /* Free partial strings. */
+ tor_free(v3_ips_string);
+ tor_free(v2_ips_string);
+ tor_free(v3_reqs_string);
+ tor_free(v2_reqs_string);
+ tor_free(v2_share_string);
+ tor_free(v3_share_string);
+ tor_free(v3_direct_dl_string);
+ tor_free(v2_direct_dl_string);
+ tor_free(v3_tunneled_dl_string);
+ tor_free(v2_tunneled_dl_string);
- finish_writing_to_file(open_file);
- open_file = NULL;
+ return result;
+}
- start_of_dirreq_stats_interval = now;
+/** If 24 hours have passed since the beginning of the current dirreq
+ * stats period, write dirreq stats to $DATADIR/stats/dirreq-stats
+ * (possibly overwriting an existing file) and reset counters. Return
+ * when we would next want to write dirreq stats or 0 if we never want to
+ * write. */
+time_t
+geoip_dirreq_stats_write(time_t now)
+{
+ char *statsdir = NULL, *filename = NULL, *str = NULL;
+
+ if (!start_of_dirreq_stats_interval)
+ return 0; /* Not initialized. */
+ if (start_of_dirreq_stats_interval + WRITE_STATS_INTERVAL > now)
+ goto done; /* Not ready to write. */
+
+ /* Discard all items in the client history that are too old. */
+ geoip_remove_old_clients(start_of_dirreq_stats_interval);
+
+ /* Generate history string .*/
+ str = geoip_format_dirreq_stats(now);
+
+ /* Write dirreq-stats string to disk. */
+ statsdir = get_datadir_fname("stats");
+ if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
+ log_warn(LD_HIST, "Unable to create stats/ directory!");
+ goto done;
+ }
+ filename = get_datadir_fname2("stats", "dirreq-stats");
+ if (write_str_to_file(filename, str, 0) < 0)
+ log_warn(LD_HIST, "Unable to write dirreq statistics to disk!");
+
+ /* Reset measurement interval start. */
+ geoip_reset_dirreq_stats(now);
done:
- if (open_file)
- abort_writing_to_file(open_file);
- tor_free(filename);
tor_free(statsdir);
- tor_free(data_v2);
- tor_free(data_v3);
+ tor_free(filename);
+ tor_free(str);
return start_of_dirreq_stats_interval + WRITE_STATS_INTERVAL;
}
@@ -1140,8 +1197,8 @@ static char *bridge_stats_extrainfo = NULL;
/** Return a newly allocated string holding our bridge usage stats by country
* in a format suitable for inclusion in an extrainfo document. Return NULL on
* failure. */
-static char *
-format_bridge_stats_extrainfo(time_t now)
+char *
+geoip_format_bridge_stats(time_t now)
{
char *out = NULL, *data = NULL;
long duration = now - start_of_bridge_stats_interval;
@@ -1149,6 +1206,8 @@ format_bridge_stats_extrainfo(time_t now)
if (duration < 0)
return NULL;
+ if (!start_of_bridge_stats_interval)
+ return NULL; /* Not initialized. */
format_iso_time(written, now);
data = geoip_get_client_history(GEOIP_CLIENT_CONNECT);
@@ -1198,7 +1257,7 @@ geoip_bridge_stats_write(time_t now)
geoip_remove_old_clients(start_of_bridge_stats_interval);
/* Generate formatted string */
- val = format_bridge_stats_extrainfo(now);
+ val = geoip_format_bridge_stats(now);
if (val == NULL)
goto done;
@@ -1275,25 +1334,51 @@ geoip_entry_stats_init(time_t now)
start_of_entry_stats_interval = now;
}
+/** Reset counters for entry stats. */
+void
+geoip_reset_entry_stats(time_t now)
+{
+ client_history_clear();
+ start_of_entry_stats_interval = now;
+}
+
/** Stop collecting entry stats in a way that we can re-start doing so in
* geoip_entry_stats_init(). */
void
geoip_entry_stats_term(void)
{
- client_history_clear();
- start_of_entry_stats_interval = 0;
+ geoip_reset_entry_stats(0);
+}
+
+/** Return a newly allocated string containing the entry statistics
+ * until <b>now</b>, or NULL if we're not collecting entry stats. */
+char *
+geoip_format_entry_stats(time_t now)
+{
+ char t[ISO_TIME_LEN+1];
+ char *data = NULL;
+ char *result;
+
+ if (!start_of_entry_stats_interval)
+ return NULL; /* Not initialized. */
+
+ data = geoip_get_client_history(GEOIP_CLIENT_CONNECT);
+ format_iso_time(t, now);
+ tor_asprintf(&result, "entry-stats-end %s (%u s)\nentry-ips %s\n",
+ t, (unsigned) (now - start_of_entry_stats_interval),
+ data ? data : "");
+ tor_free(data);
+ return result;
}
-/** Write entry statistics to $DATADIR/stats/entry-stats and return time
- * when we would next want to write. */
+/** If 24 hours have passed since the beginning of the current entry stats
+ * period, write entry stats to $DATADIR/stats/entry-stats (possibly
+ * overwriting an existing file) and reset counters. Return when we would
+ * next want to write entry stats or 0 if we never want to write. */
time_t
geoip_entry_stats_write(time_t now)
{
- char *statsdir = NULL, *filename = NULL;
- char *data = NULL;
- char written[ISO_TIME_LEN+1];
- open_file_t *open_file = NULL;
- FILE *out;
+ char *statsdir = NULL, *filename = NULL, *str = NULL;
if (!start_of_entry_stats_interval)
return 0; /* Not initialized. */
@@ -1303,31 +1388,26 @@ geoip_entry_stats_write(time_t now)
/* Discard all items in the client history that are too old. */
geoip_remove_old_clients(start_of_entry_stats_interval);
+ /* Generate history string .*/
+ str = geoip_format_entry_stats(now);
+
+ /* Write entry-stats string to disk. */
statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0)
+ if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
+ log_warn(LD_HIST, "Unable to create stats/ directory!");
goto done;
+ }
filename = get_datadir_fname2("stats", "entry-stats");
- data = geoip_get_client_history(GEOIP_CLIENT_CONNECT);
- format_iso_time(written, now);
- out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND | O_TEXT,
- 0600, &open_file);
- if (!out)
- goto done;
- if (fprintf(out, "entry-stats-end %s (%u s)\nentry-ips %s\n",
- written, (unsigned) (now - start_of_entry_stats_interval),
- data ? data : "") < 0)
- goto done;
+ if (write_str_to_file(filename, str, 0) < 0)
+ log_warn(LD_HIST, "Unable to write entry statistics to disk!");
- start_of_entry_stats_interval = now;
+ /* Reset measurement interval start. */
+ geoip_reset_entry_stats(now);
- finish_writing_to_file(open_file);
- open_file = NULL;
done:
- if (open_file)
- abort_writing_to_file(open_file);
- tor_free(filename);
tor_free(statsdir);
- tor_free(data);
+ tor_free(filename);
+ tor_free(str);
return start_of_entry_stats_interval + WRITE_STATS_INTERVAL;
}
diff --git a/src/or/geoip.h b/src/or/geoip.h
index 24f7c5b93..ce3841967 100644
--- a/src/or/geoip.h
+++ b/src/or/geoip.h
@@ -15,12 +15,13 @@
#ifdef GEOIP_PRIVATE
int geoip_parse_entry(const char *line);
#endif
-int should_record_bridge_info(or_options_t *options);
-int geoip_load_file(const char *filename, or_options_t *options);
+int should_record_bridge_info(const or_options_t *options);
+int geoip_load_file(const char *filename, const or_options_t *options);
int geoip_get_country_by_ip(uint32_t ipaddr);
int geoip_get_n_countries(void);
const char *geoip_get_country_name(country_t num);
int geoip_is_loaded(void);
+const char *geoip_db_digest(void);
country_t geoip_get_country(const char *countrycode);
void geoip_note_client_seen(geoip_client_action_t action,
@@ -42,12 +43,17 @@ void geoip_change_dirreq_state(uint64_t dirreq_id, dirreq_type_t type,
dirreq_state_t new_state);
void geoip_dirreq_stats_init(time_t now);
+void geoip_reset_dirreq_stats(time_t now);
+char *geoip_format_dirreq_stats(time_t now);
time_t geoip_dirreq_stats_write(time_t now);
void geoip_dirreq_stats_term(void);
void geoip_entry_stats_init(time_t now);
time_t geoip_entry_stats_write(time_t now);
void geoip_entry_stats_term(void);
+void geoip_reset_entry_stats(time_t now);
+char *geoip_format_entry_stats(time_t now);
void geoip_bridge_stats_init(time_t now);
+char *geoip_format_bridge_stats(time_t now);
time_t geoip_bridge_stats_write(time_t now);
void geoip_bridge_stats_term(void);
const char *geoip_get_bridge_stats_extrainfo(time_t);
diff --git a/src/or/hibernate.c b/src/or/hibernate.c
index 6b1217a44..c8357e5be 100644
--- a/src/or/hibernate.c
+++ b/src/or/hibernate.c
@@ -120,7 +120,7 @@ static void accounting_set_wakeup_time(void);
* options->AccountingStart. Return 0 on success, -1 on failure. If
* <b>validate_only</b> is true, do not change the current settings. */
int
-accounting_parse_options(or_options_t *options, int validate_only)
+accounting_parse_options(const or_options_t *options, int validate_only)
{
time_unit_t unit;
int ok, idx;
@@ -235,7 +235,7 @@ accounting_parse_options(or_options_t *options, int validate_only)
* hibernate, return 1, else return 0.
*/
int
-accounting_is_enabled(or_options_t *options)
+accounting_is_enabled(const or_options_t *options)
{
if (options->AccountingMax)
return 1;
@@ -397,7 +397,7 @@ static void
update_expected_bandwidth(void)
{
uint64_t expected;
- or_options_t *options= get_options();
+ const or_options_t *options= get_options();
uint64_t max_configured = (options->RelayBandwidthRate > 0 ?
options->RelayBandwidthRate :
options->BandwidthRate) * 60;
@@ -736,7 +736,7 @@ static void
hibernate_begin(hibernate_state_t new_state, time_t now)
{
connection_t *conn;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (new_state == HIBERNATE_STATE_EXITING &&
hibernate_state != HIBERNATE_STATE_LIVE) {
@@ -844,7 +844,7 @@ hibernate_go_dormant(time_t now)
connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_HIBERNATING);
log_info(LD_NET,"Closing conn type %d", conn->type);
if (conn->type == CONN_TYPE_AP) /* send socks failure if needed */
- connection_mark_unattached_ap(TO_EDGE_CONN(conn),
+ connection_mark_unattached_ap(TO_ENTRY_CONN(conn),
END_STREAM_REASON_HIBERNATING);
else
connection_mark_for_close(conn);
diff --git a/src/or/hibernate.h b/src/or/hibernate.h
index fc5b08fcc..78e7bb75e 100644
--- a/src/or/hibernate.h
+++ b/src/or/hibernate.h
@@ -12,8 +12,8 @@
#ifndef _TOR_HIBERNATE_H
#define _TOR_HIBERNATE_H
-int accounting_parse_options(or_options_t *options, int validate_only);
-int accounting_is_enabled(or_options_t *options);
+int accounting_parse_options(const or_options_t *options, int validate_only);
+int accounting_is_enabled(const or_options_t *options);
void configure_accounting(time_t now);
void accounting_run_housekeeping(time_t now);
void accounting_add_bytes(size_t n_read, size_t n_written, int seconds);
diff --git a/src/or/main.c b/src/or/main.c
index bc639dbdd..aa167e1e9 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -33,9 +33,11 @@
#include "main.h"
#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "ntmain.h"
#include "onion.h"
#include "policies.h"
+#include "transports.h"
#include "relay.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -44,6 +46,7 @@
#include "router.h"
#include "routerlist.h"
#include "routerparse.h"
+#include "status.h"
#ifdef USE_DMALLOC
#include <dmalloc.h>
#include <openssl/crypto.h>
@@ -56,6 +59,10 @@
#include <event.h>
#endif
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent.h>
+#endif
+
void evdns_shutdown(int);
/********* PROTOTYPES **********/
@@ -71,6 +78,7 @@ static int connection_should_read_from_linked_conn(connection_t *conn);
/********* START VARIABLES **********/
+#ifndef USE_BUFFEREVENTS
int global_read_bucket; /**< Max number of bytes I can read this second. */
int global_write_bucket; /**< Max number of bytes I can write this second. */
@@ -78,13 +86,17 @@ int global_write_bucket; /**< Max number of bytes I can write this second. */
int global_relayed_read_bucket;
/** Max number of relayed (bandwidth class 1) bytes I can write this second. */
int global_relayed_write_bucket;
-
/** What was the read bucket before the last second_elapsed_callback() call?
* (used to determine how many bytes we've read). */
static int stats_prev_global_read_bucket;
/** What was the write bucket before the last second_elapsed_callback() call?
* (used to determine how many bytes we've written). */
static int stats_prev_global_write_bucket;
+#endif
+
+static uint64_t stats_prev_n_read = 0;
+static uint64_t stats_prev_n_written = 0;
+
/* XXX we might want to keep stats about global_relayed_*_bucket too. Or not.*/
/** How many bytes have we read since we started the process? */
static uint64_t stats_n_bytes_read = 0;
@@ -103,6 +115,8 @@ static time_t time_to_check_for_correct_dns = 0;
static time_t time_of_last_signewnym = 0;
/** Is there a signewnym request we're currently waiting to handle? */
static int signewnym_is_pending = 0;
+/** How many times have we called newnym? */
+static unsigned newnym_epoch = 0;
/** Smartlist of all open connections. */
static smartlist_t *connection_array = NULL;
@@ -141,6 +155,12 @@ int can_complete_circuit=0;
* they are obsolete? */
#define TLS_HANDSHAKE_TIMEOUT (60)
+/** Decides our behavior when no logs are configured/before any
+ * logs have been configured. For 0, we log notice to stdout as normal.
+ * For 1, we log warnings only. For 2, we log nothing.
+ */
+int quiet_level = 0;
+
/********* END VARIABLES ************/
/****************************************************************************
@@ -150,12 +170,38 @@ int can_complete_circuit=0;
*
****************************************************************************/
+#if 0 && defined(USE_BUFFEREVENTS)
+static void
+free_old_inbuf(connection_t *conn)
+{
+ if (! conn->inbuf)
+ return;
+
+ tor_assert(conn->outbuf);
+ tor_assert(buf_datalen(conn->inbuf) == 0);
+ tor_assert(buf_datalen(conn->outbuf) == 0);
+ buf_free(conn->inbuf);
+ buf_free(conn->outbuf);
+ conn->inbuf = conn->outbuf = NULL;
+
+ if (conn->read_event) {
+ event_del(conn->read_event);
+ tor_event_free(conn->read_event);
+ }
+ if (conn->write_event) {
+ event_del(conn->read_event);
+ tor_event_free(conn->write_event);
+ }
+ conn->read_event = conn->write_event = NULL;
+}
+#endif
+
/** Add <b>conn</b> to the array of connections that we can poll on. The
* connection's socket must be set; the connection starts out
* non-reading and non-writing.
*/
int
-connection_add(connection_t *conn)
+connection_add_impl(connection_t *conn, int is_connecting)
{
tor_assert(conn);
tor_assert(SOCKET_OK(conn->s) ||
@@ -167,11 +213,63 @@ connection_add(connection_t *conn)
conn->conn_array_index = smartlist_len(connection_array);
smartlist_add(connection_array, conn);
- if (SOCKET_OK(conn->s) || conn->linked) {
+#ifdef USE_BUFFEREVENTS
+ if (connection_type_uses_bufferevent(conn)) {
+ if (SOCKET_OK(conn->s) && !conn->linked) {
+ conn->bufev = bufferevent_socket_new(
+ tor_libevent_get_base(),
+ conn->s,
+ BEV_OPT_DEFER_CALLBACKS);
+ if (!conn->bufev) {
+ log_warn(LD_BUG, "Unable to create socket bufferevent");
+ smartlist_del(connection_array, conn->conn_array_index);
+ conn->conn_array_index = -1;
+ return -1;
+ }
+ if (is_connecting) {
+ /* Put the bufferevent into a "connecting" state so that we'll get
+ * a "connected" event callback on successful write. */
+ bufferevent_socket_connect(conn->bufev, NULL, 0);
+ }
+ connection_configure_bufferevent_callbacks(conn);
+ } else if (conn->linked && conn->linked_conn &&
+ connection_type_uses_bufferevent(conn->linked_conn)) {
+ tor_assert(!(SOCKET_OK(conn->s)));
+ if (!conn->bufev) {
+ struct bufferevent *pair[2] = { NULL, NULL };
+ if (bufferevent_pair_new(tor_libevent_get_base(),
+ BEV_OPT_DEFER_CALLBACKS,
+ pair) < 0) {
+ log_warn(LD_BUG, "Unable to create bufferevent pair");
+ smartlist_del(connection_array, conn->conn_array_index);
+ conn->conn_array_index = -1;
+ return -1;
+ }
+ tor_assert(pair[0]);
+ conn->bufev = pair[0];
+ conn->linked_conn->bufev = pair[1];
+ } /* else the other side already was added, and got a bufferevent_pair */
+ connection_configure_bufferevent_callbacks(conn);
+ } else {
+ tor_assert(!conn->linked);
+ }
+
+ if (conn->bufev)
+ tor_assert(conn->inbuf == NULL);
+
+ if (conn->linked_conn && conn->linked_conn->bufev)
+ tor_assert(conn->linked_conn->inbuf == NULL);
+ }
+#else
+ (void) is_connecting;
+#endif
+
+ if (!HAS_BUFFEREVENT(conn) && (SOCKET_OK(conn->s) || conn->linked)) {
conn->read_event = tor_event_new(tor_libevent_get_base(),
conn->s, EV_READ|EV_PERSIST, conn_read_callback, conn);
conn->write_event = tor_event_new(tor_libevent_get_base(),
conn->s, EV_WRITE|EV_PERSIST, conn_write_callback, conn);
+ /* XXXX CHECK FOR NULL RETURN! */
}
log_debug(LD_NET,"new conn type %s, socket %d, address %s, n_conns %d.",
@@ -195,7 +293,13 @@ connection_unregister_events(connection_t *conn)
log_warn(LD_BUG, "Error removing write event for %d", (int)conn->s);
tor_free(conn->write_event);
}
- if (conn->dns_server_port) {
+#ifdef USE_BUFFEREVENTS
+ if (conn->bufev) {
+ bufferevent_free(conn->bufev);
+ conn->bufev = NULL;
+ }
+#endif
+ if (conn->type == CONN_TYPE_AP_DNS_LISTENER) {
dnsserv_close_listener(conn);
}
}
@@ -303,12 +407,37 @@ get_connection_array(void)
return connection_array;
}
+/** Provides the traffic read and written over the life of the process. */
+
+uint64_t
+get_bytes_read(void)
+{
+ return stats_n_bytes_read;
+}
+
+uint64_t
+get_bytes_written(void)
+{
+ return stats_n_bytes_written;
+}
+
/** Set the event mask on <b>conn</b> to <b>events</b>. (The event
* mask is a bitmask whose bits are READ_EVENT and WRITE_EVENT)
*/
void
connection_watch_events(connection_t *conn, watchable_events_t events)
{
+ IF_HAS_BUFFEREVENT(conn, {
+ short ev = ((short)events) & (EV_READ|EV_WRITE);
+ short old_ev = bufferevent_get_enabled(conn->bufev);
+ if ((ev & ~old_ev) != 0) {
+ bufferevent_enable(conn->bufev, ev);
+ }
+ if ((old_ev & ~ev) != 0) {
+ bufferevent_disable(conn->bufev, old_ev & ~ev);
+ }
+ return;
+ });
if (events & READ_EVENT)
connection_start_reading(conn);
else
@@ -326,6 +455,9 @@ connection_is_reading(connection_t *conn)
{
tor_assert(conn);
+ IF_HAS_BUFFEREVENT(conn,
+ return (bufferevent_get_enabled(conn->bufev) & EV_READ) != 0;
+ );
return conn->reading_from_linked_conn ||
(conn->read_event && event_pending(conn->read_event, EV_READ, NULL));
}
@@ -335,6 +467,12 @@ void
connection_stop_reading(connection_t *conn)
{
tor_assert(conn);
+
+ IF_HAS_BUFFEREVENT(conn, {
+ bufferevent_disable(conn->bufev, EV_READ);
+ return;
+ });
+
tor_assert(conn->read_event);
if (conn->linked) {
@@ -354,6 +492,12 @@ void
connection_start_reading(connection_t *conn)
{
tor_assert(conn);
+
+ IF_HAS_BUFFEREVENT(conn, {
+ bufferevent_enable(conn->bufev, EV_READ);
+ return;
+ });
+
tor_assert(conn->read_event);
if (conn->linked) {
@@ -375,6 +519,10 @@ connection_is_writing(connection_t *conn)
{
tor_assert(conn);
+ IF_HAS_BUFFEREVENT(conn,
+ return (bufferevent_get_enabled(conn->bufev) & EV_WRITE) != 0;
+ );
+
return conn->writing_to_linked_conn ||
(conn->write_event && event_pending(conn->write_event, EV_WRITE, NULL));
}
@@ -384,6 +532,12 @@ void
connection_stop_writing(connection_t *conn)
{
tor_assert(conn);
+
+ IF_HAS_BUFFEREVENT(conn, {
+ bufferevent_disable(conn->bufev, EV_WRITE);
+ return;
+ });
+
tor_assert(conn->write_event);
if (conn->linked) {
@@ -404,6 +558,12 @@ void
connection_start_writing(connection_t *conn)
{
tor_assert(conn);
+
+ IF_HAS_BUFFEREVENT(conn, {
+ bufferevent_enable(conn->bufev, EV_WRITE);
+ return;
+ });
+
tor_assert(conn->write_event);
if (conn->linked) {
@@ -590,9 +750,32 @@ conn_close_if_marked(int i)
assert_connection_ok(conn, now);
/* assert_all_pending_dns_resolves_ok(); */
- log_debug(LD_NET,"Cleaning up connection (fd %d).",(int)conn->s);
- if ((SOCKET_OK(conn->s) || conn->linked_conn)
- && connection_wants_to_flush(conn)) {
+#ifdef USE_BUFFEREVENTS
+ if (conn->bufev) {
+ if (conn->hold_open_until_flushed &&
+ evbuffer_get_length(bufferevent_get_output(conn->bufev))) {
+ /* don't close yet. */
+ return 0;
+ }
+ if (conn->linked_conn && ! conn->linked_conn->marked_for_close) {
+ /* We need to do this explicitly so that the linked connection
+ * notices that there was an EOF. */
+ bufferevent_flush(conn->bufev, EV_WRITE, BEV_FINISHED);
+ }
+ }
+#endif
+
+ log_debug(LD_NET,"Cleaning up connection (fd %d).",conn->s);
+
+ /* If the connection we are about to close was trying to connect to
+ a proxy server and failed, the client won't be able to use that
+ proxy. We should warn the user about this. */
+ if (conn->proxy_state == PROXY_INFANT)
+ log_failed_proxy_connection(conn);
+
+ IF_HAS_BUFFEREVENT(conn, goto unlink);
+ if ((SOCKET_OK(conn->s) || conn->linked_conn) &&
+ connection_wants_to_flush(conn)) {
/* s == -1 means it's an incomplete edge connection, or that the socket
* has already been closed as unflushable. */
ssize_t sz = connection_bucket_write_limit(conn, now);
@@ -614,8 +797,8 @@ conn_close_if_marked(int i)
}
log_debug(LD_GENERAL, "Flushed last %d bytes from a linked conn; "
"%d left; flushlen %d; wants-to-flush==%d", retval,
- (int)buf_datalen(conn->outbuf),
- (int)conn->outbuf_flushlen,
+ (int)connection_get_outbuf_len(conn),
+ (int)conn->outbuf_flushlen,
connection_wants_to_flush(conn));
} else if (connection_speaks_cells(conn)) {
if (conn->state == OR_CONN_STATE_OPEN) {
@@ -652,13 +835,17 @@ conn_close_if_marked(int i)
"something is wrong with your network connection, or "
"something is wrong with theirs. "
"(fd %d, type %s, state %d, marked at %s:%d).",
- (int)buf_datalen(conn->outbuf),
+ (int)connection_get_outbuf_len(conn),
escaped_safe_str_client(conn->address),
(int)conn->s, conn_type_to_string(conn->type), conn->state,
conn->marked_for_close_file,
conn->marked_for_close);
}
}
+
+#ifdef USE_BUFFEREVENTS
+ unlink:
+#endif
connection_unlink(conn); /* unlink, remove, free */
return 1;
}
@@ -679,13 +866,13 @@ directory_all_unreachable(time_t now)
while ((conn = connection_get_by_type_state(CONN_TYPE_AP,
AP_CONN_STATE_CIRCUIT_WAIT))) {
- edge_connection_t *edge_conn = TO_EDGE_CONN(conn);
+ entry_connection_t *entry_conn = TO_ENTRY_CONN(conn);
log_notice(LD_NET,
"Is your network connection down? "
"Failing connection to '%s:%d'.",
- safe_str_client(edge_conn->socks_request->address),
- edge_conn->socks_request->port);
- connection_mark_unattached_ap(edge_conn,
+ safe_str_client(entry_conn->socks_request->address),
+ entry_conn->socks_request->port);
+ connection_mark_unattached_ap(entry_conn,
END_STREAM_REASON_NET_UNREACHABLE);
}
control_event_general_status(LOG_ERR, "DIR_ALL_UNREACHABLE");
@@ -696,18 +883,19 @@ directory_all_unreachable(time_t now)
void
directory_info_has_arrived(time_t now, int from_cache)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!router_have_minimum_dir_info()) {
int quiet = directory_too_idle_to_fetch_descriptors(options, now);
log(quiet ? LOG_INFO : LOG_NOTICE, LD_DIR,
"I learned some more directory information, but not enough to "
"build a circuit: %s", get_dir_info_status_string());
- update_router_descriptor_downloads(now);
+ update_all_descriptor_downloads(now);
return;
} else {
- if (directory_fetches_from_authorities(options))
- update_router_descriptor_downloads(now);
+ if (directory_fetches_from_authorities(options)) {
+ update_all_descriptor_downloads(now);
+ }
/* if we have enough dir info, then update our guard status with
* whatever we just learned. */
@@ -740,12 +928,13 @@ run_connection_housekeeping(int i, time_t now)
{
cell_t cell;
connection_t *conn = smartlist_get(connection_array, i);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
or_connection_t *or_conn;
int past_keepalive =
now >= conn->timestamp_lastwritten + options->KeepalivePeriod;
- if (conn->outbuf && !buf_datalen(conn->outbuf) && conn->type == CONN_TYPE_OR)
+ if (conn->outbuf && !connection_get_outbuf_len(conn) &&
+ conn->type == CONN_TYPE_OR)
TO_OR_CONN(conn)->timestamp_lastempty = now;
if (conn->marked_for_close) {
@@ -765,7 +954,7 @@ run_connection_housekeeping(int i, time_t now)
/* This check is temporary; it's to let us know whether we should consider
* parsing partial serverdesc responses. */
if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC &&
- buf_datalen(conn->inbuf)>=1024) {
+ connection_get_inbuf_len(conn) >= 1024) {
log_info(LD_DIR,"Trying to extract information from wedged server desc "
"download.");
connection_dir_reached_eof(TO_DIR_CONN(conn));
@@ -782,7 +971,11 @@ run_connection_housekeeping(int i, time_t now)
the connection or send a keepalive, depending. */
or_conn = TO_OR_CONN(conn);
+#ifdef USE_BUFFEREVENTS
+ tor_assert(conn->bufev);
+#else
tor_assert(conn->outbuf);
+#endif
if (or_conn->is_bad_for_new_circs && !or_conn->n_circuits) {
/* It's bad for new circuits, and has no unmarked circuits on it:
@@ -794,8 +987,7 @@ run_connection_housekeeping(int i, time_t now)
connection_or_connect_failed(TO_OR_CONN(conn),
END_OR_CONN_REASON_TIMEOUT,
"Tor gave up on the connection");
- connection_mark_for_close(conn);
- conn->hold_open_until_flushed = 1;
+ connection_mark_and_flush(conn);
} else if (!connection_state_is_open(conn)) {
if (past_keepalive) {
/* We never managed to actually get this connection open and happy. */
@@ -804,13 +996,12 @@ run_connection_housekeeping(int i, time_t now)
connection_mark_for_close(conn);
}
} else if (we_are_hibernating() && !or_conn->n_circuits &&
- !buf_datalen(conn->outbuf)) {
+ !connection_get_outbuf_len(conn)) {
/* We're hibernating, there's no circuits, and nothing to flush.*/
log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
"[Hibernating or exiting].",
(int)conn->s,conn->address, conn->port);
- connection_mark_for_close(conn);
- conn->hold_open_until_flushed = 1;
+ connection_mark_and_flush(conn);
} else if (!or_conn->n_circuits &&
now >= or_conn->timestamp_last_added_nonpadding +
IDLE_OR_CONN_TIMEOUT) {
@@ -818,7 +1009,6 @@ run_connection_housekeeping(int i, time_t now)
"[idle %d].", (int)conn->s,conn->address, conn->port,
(int)(now - or_conn->timestamp_last_added_nonpadding));
connection_mark_for_close(conn);
- conn->hold_open_until_flushed = 1;
} else if (
now >= or_conn->timestamp_lastempty + options->KeepalivePeriod*10 &&
now >= conn->timestamp_lastwritten + options->KeepalivePeriod*10) {
@@ -826,10 +1016,10 @@ run_connection_housekeeping(int i, time_t now)
"Expiring stuck OR connection to fd %d (%s:%d). (%d bytes to "
"flush; %d seconds since last write)",
(int)conn->s, conn->address, conn->port,
- (int)buf_datalen(conn->outbuf),
+ (int)connection_get_outbuf_len(conn),
(int)(now-conn->timestamp_lastwritten));
connection_mark_for_close(conn);
- } else if (past_keepalive && !buf_datalen(conn->outbuf)) {
+ } else if (past_keepalive && !connection_get_outbuf_len(conn)) {
/* send a padding cell */
log_fn(LOG_DEBUG,LD_OR,"Sending keepalive to (%s:%d)",
conn->address, conn->port);
@@ -844,7 +1034,7 @@ run_connection_housekeeping(int i, time_t now)
static void
signewnym_impl(time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!proxy_mode(options)) {
log_info(LD_CONTROL, "Ignoring SIGNAL NEWNYM because client functionality "
"is disabled.");
@@ -856,6 +1046,17 @@ signewnym_impl(time_t now)
rend_client_purge_state();
time_of_last_signewnym = now;
signewnym_is_pending = 0;
+
+ ++newnym_epoch;
+
+ control_event_signal(SIGNEWNYM);
+}
+
+/** Return the number of times that signewnym has been called. */
+unsigned
+get_signewnym_epoch(void)
+{
+ return newnym_epoch;
}
/** Perform regular maintenance tasks. This function gets run once per
@@ -881,10 +1082,14 @@ run_scheduled_events(time_t now)
static time_t time_to_check_for_expired_networkstatus = 0;
static time_t time_to_write_stats_files = 0;
static time_t time_to_write_bridge_stats = 0;
+ static time_t time_to_check_port_forwarding = 0;
static time_t time_to_launch_reachability_tests = 0;
static int should_init_bridge_stats = 1;
static time_t time_to_retry_dns_init = 0;
- or_options_t *options = get_options();
+ static time_t time_to_next_heartbeat = 0;
+ static int has_validated_pt = 0;
+ const or_options_t *options = get_options();
+
int is_server = server_mode(options);
int i;
int have_dir_info;
@@ -895,6 +1100,16 @@ run_scheduled_events(time_t now)
*/
consider_hibernation(now);
+#if 0
+ {
+ static time_t nl_check_time = 0;
+ if (nl_check_time <= now) {
+ nodelist_assert_ok();
+ nl_check_time = now + 30;
+ }
+ }
+#endif
+
/* 0b. If we've deferred a signewnym, make sure it gets handled
* eventually. */
if (signewnym_is_pending &&
@@ -923,7 +1138,7 @@ run_scheduled_events(time_t now)
}
if (time_to_try_getting_descriptors < now) {
- update_router_descriptor_downloads(now);
+ update_all_descriptor_downloads(now);
update_extrainfo_downloads(now);
if (router_have_minimum_dir_info())
time_to_try_getting_descriptors = now + LAZY_DESCRIPTOR_RETRY_INTERVAL;
@@ -940,15 +1155,16 @@ run_scheduled_events(time_t now)
if (options->UseBridges)
fetch_bridge_descriptors(options, now);
- /** 1b. Every MAX_SSL_KEY_LIFETIME seconds, we change our TLS context. */
+ /** 1b. Every MAX_SSL_KEY_LIFETIME_INTERNAL seconds, we change our
+ * TLS context. */
if (!last_rotated_x509_certificate)
last_rotated_x509_certificate = now;
- if (last_rotated_x509_certificate+MAX_SSL_KEY_LIFETIME < now) {
+ if (last_rotated_x509_certificate+MAX_SSL_KEY_LIFETIME_INTERNAL < now) {
log_info(LD_GENERAL,"Rotating tls context.");
if (tor_tls_context_init(public_server_mode(options),
get_tlsclient_identity_key(),
is_server ? get_server_identity_key() : NULL,
- MAX_SSL_KEY_LIFETIME) < 0) {
+ MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) {
log_warn(LD_BUG, "Error reinitializing TLS context");
/* XXX is it a bug here, that we just keep going? -RD */
}
@@ -1047,6 +1263,11 @@ run_scheduled_events(time_t now)
if (next_write && next_write < next_time_to_write_stats_files)
next_time_to_write_stats_files = next_write;
}
+ if (options->ConnDirectionStatistics) {
+ time_t next_write = rep_hist_conn_stats_write(time_to_write_stats_files);
+ if (next_write && next_write < next_time_to_write_stats_files)
+ next_time_to_write_stats_files = next_write;
+ }
time_to_write_stats_files = next_time_to_write_stats_files;
}
@@ -1075,10 +1296,9 @@ run_scheduled_events(time_t now)
/* Remove old information from rephist and the rend cache. */
if (time_to_clean_caches < now) {
rep_history_clean(now - options->RephistTrackTime);
- rend_cache_clean();
- rend_cache_clean_v2_descs_as_dir();
- if (authdir_mode_v3(options))
- microdesc_cache_rebuild(NULL, 0);
+ rend_cache_clean(now);
+ rend_cache_clean_v2_descs_as_dir(now);
+ microdesc_cache_rebuild(NULL, 0);
#define CLEAN_CACHES_INTERVAL (30*60)
time_to_clean_caches = now + CLEAN_CACHES_INTERVAL;
}
@@ -1087,7 +1307,7 @@ run_scheduled_events(time_t now)
/* If we're a server and initializing dns failed, retry periodically. */
if (time_to_retry_dns_init < now) {
time_to_retry_dns_init = now + RETRY_DNS_INTERVAL;
- if (server_mode(options) && has_dns_init_failed())
+ if (is_server && has_dns_init_failed())
dns_init();
}
@@ -1110,15 +1330,11 @@ run_scheduled_events(time_t now)
time_to_check_ipaddress = now + CHECK_IPADDRESS_INTERVAL;
check_descriptor_ipaddress_changed(now);
}
-/** If our router descriptor ever goes this long without being regenerated
- * because something changed, we force an immediate regenerate-and-upload. */
-#define FORCE_REGENERATE_DESCRIPTOR_INTERVAL (18*60*60)
- mark_my_descriptor_dirty_if_older_than(
- now - FORCE_REGENERATE_DESCRIPTOR_INTERVAL);
+ mark_my_descriptor_dirty_if_too_old(now);
consider_publishable_server(0);
/* also, check religiously for reachability, if it's within the first
* 20 minutes of our uptime. */
- if (server_mode(options) &&
+ if (is_server &&
(can_complete_circuit || !any_predicted_circuits(now)) &&
!we_are_hibernating()) {
if (stats_n_seconds_working < TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
@@ -1129,7 +1345,7 @@ run_scheduled_events(time_t now)
/* If we haven't checked for 12 hours and our bandwidth estimate is
* low, do another bandwidth test. This is especially important for
* bridges, since they might go long periods without much use. */
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (time_to_recheck_bandwidth && me &&
me->bandwidthcapacity < me->bandwidthrate &&
me->bandwidthcapacity < 51200) {
@@ -1240,7 +1456,7 @@ run_scheduled_events(time_t now)
/** 9. and if we're a server, check whether our DNS is telling stories to
* us. */
- if (is_server && time_to_check_for_correct_dns < now) {
+ if (public_server_mode(options) && time_to_check_for_correct_dns < now) {
if (!time_to_check_for_correct_dns) {
time_to_check_for_correct_dns = now + 60 + crypto_rand_int(120);
} else {
@@ -1250,13 +1466,44 @@ run_scheduled_events(time_t now)
}
}
- /** 10b. write bridge networkstatus file to disk */
+ /** 10. write bridge networkstatus file to disk */
if (options->BridgeAuthoritativeDir &&
time_to_write_bridge_status_file < now) {
networkstatus_dump_bridge_status_to_file(now);
#define BRIDGE_STATUSFILE_INTERVAL (30*60)
time_to_write_bridge_status_file = now+BRIDGE_STATUSFILE_INTERVAL;
}
+
+ /** 11. check the port forwarding app */
+ if (time_to_check_port_forwarding < now &&
+ options->PortForwarding &&
+ is_server) {
+#define PORT_FORWARDING_CHECK_INTERVAL 5
+ tor_check_port_forwarding(options->PortForwardingHelper,
+ options->DirPort,
+ options->ORPort,
+ now);
+ time_to_check_port_forwarding = now+PORT_FORWARDING_CHECK_INTERVAL;
+ }
+
+ /** 11b. check pending unconfigured managed proxies */
+ if (pt_proxies_configuration_pending())
+ pt_configure_remaining_proxies();
+
+ /** 11c. validate pluggable transports configuration if we need to */
+ if (!has_validated_pt &&
+ (options->Bridges || options->ClientTransportPlugin)) {
+ if (validate_pluggable_transports_config() == 0) {
+ has_validated_pt = 1;
+ }
+ }
+
+ /** 12. write the heartbeat message */
+ if (options->HeartbeatPeriod &&
+ time_to_next_heartbeat < now) {
+ log_heartbeat(now);
+ time_to_next_heartbeat = now+options->HeartbeatPeriod;
+ }
}
/** Timer: used to invoke second_elapsed_callback() once per second. */
@@ -1276,7 +1523,7 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg)
size_t bytes_written;
size_t bytes_read;
int seconds_elapsed;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
(void)timer;
(void)arg;
@@ -1287,21 +1534,30 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg)
update_approx_time(now);
/* the second has rolled over. check more stuff. */
- bytes_written = stats_prev_global_write_bucket - global_write_bucket;
- bytes_read = stats_prev_global_read_bucket - global_read_bucket;
seconds_elapsed = current_second ? (int)(now - current_second) : 0;
- stats_n_bytes_read += bytes_read;
- stats_n_bytes_written += bytes_written;
- if (accounting_is_enabled(options) && seconds_elapsed >= 0)
- accounting_add_bytes(bytes_read, bytes_written, seconds_elapsed);
+#ifdef USE_BUFFEREVENTS
+ {
+ uint64_t cur_read,cur_written;
+ connection_get_rate_limit_totals(&cur_read, &cur_written);
+ bytes_written = (size_t)(cur_written - stats_prev_n_written);
+ bytes_read = (size_t)(cur_read - stats_prev_n_read);
+ stats_n_bytes_read += bytes_read;
+ stats_n_bytes_written += bytes_written;
+ if (accounting_is_enabled(options) && seconds_elapsed >= 0)
+ accounting_add_bytes(bytes_read, bytes_written, seconds_elapsed);
+ stats_prev_n_written = cur_written;
+ stats_prev_n_read = cur_read;
+ }
+#else
+ bytes_read = (size_t)(stats_n_bytes_read - stats_prev_n_read);
+ bytes_written = (size_t)(stats_n_bytes_written - stats_prev_n_written);
+ stats_prev_n_read = stats_n_bytes_read;
+ stats_prev_n_written = stats_n_bytes_written;
+#endif
+
control_event_bandwidth_used((uint32_t)bytes_read,(uint32_t)bytes_written);
control_event_stream_bandwidth_used();
- if (seconds_elapsed > 0)
- connection_bucket_refill(seconds_elapsed, now);
- stats_prev_global_read_bucket = global_read_bucket;
- stats_prev_global_write_bucket = global_write_bucket;
-
if (server_mode(options) &&
!we_are_hibernating() &&
seconds_elapsed > 0 &&
@@ -1310,7 +1566,7 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg)
(stats_n_seconds_working+seconds_elapsed) /
TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
/* every 20 minutes, check and complain if necessary */
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (me && !check_whether_orport_reachable()) {
log_warn(LD_CONFIG,"Your server (%s:%d) has not managed to confirm that "
"its ORPort is reachable. Please check your firewalls, ports, "
@@ -1349,6 +1605,57 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg)
current_second = now; /* remember which second it is, for next time */
}
+#ifndef USE_BUFFEREVENTS
+/** Timer: used to invoke refill_callback(). */
+static periodic_timer_t *refill_timer = NULL;
+
+/** Libevent callback: invoked periodically to refill token buckets
+ * and count r/w bytes. It is only used when bufferevents are disabled. */
+static void
+refill_callback(periodic_timer_t *timer, void *arg)
+{
+ static struct timeval current_millisecond;
+ struct timeval now;
+
+ size_t bytes_written;
+ size_t bytes_read;
+ int milliseconds_elapsed = 0;
+ int seconds_rolled_over = 0;
+
+ const or_options_t *options = get_options();
+
+ (void)timer;
+ (void)arg;
+
+ tor_gettimeofday(&now);
+
+ /* If this is our first time, no time has passed. */
+ if (current_millisecond.tv_sec) {
+ long mdiff = tv_mdiff(&current_millisecond, &now);
+ if (mdiff > INT_MAX)
+ mdiff = INT_MAX;
+ milliseconds_elapsed = (int)mdiff;
+ seconds_rolled_over = (int)(now.tv_sec - current_millisecond.tv_sec);
+ }
+
+ bytes_written = stats_prev_global_write_bucket - global_write_bucket;
+ bytes_read = stats_prev_global_read_bucket - global_read_bucket;
+
+ stats_n_bytes_read += bytes_read;
+ stats_n_bytes_written += bytes_written;
+ if (accounting_is_enabled(options) && milliseconds_elapsed >= 0)
+ accounting_add_bytes(bytes_read, bytes_written, seconds_rolled_over);
+
+ if (milliseconds_elapsed > 0)
+ connection_bucket_refill(milliseconds_elapsed, now.tv_sec);
+
+ stats_prev_global_read_bucket = global_read_bucket;
+ stats_prev_global_write_bucket = global_write_bucket;
+
+ current_millisecond = now; /* remember what time it is, for next time */
+}
+#endif
+
#ifndef MS_WINDOWS
/** Called when a possibly ignorable libevent error occurs; ensures that we
* don't get into an infinite loop by ignoring too many errors from
@@ -1408,7 +1715,7 @@ dns_servers_relaunch_checks(void)
static int
do_hup(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
#ifdef USE_DMALLOC
dmalloc_log_stats();
@@ -1500,8 +1807,10 @@ do_main_loop(void)
/* Set up our buckets */
connection_bucket_init();
+#ifndef USE_BUFFEREVENTS
stats_prev_global_read_bucket = global_read_bucket;
stats_prev_global_write_bucket = global_write_bucket;
+#endif
/* initialize the bootstrap status events to know we're starting up */
control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0);
@@ -1544,6 +1853,22 @@ do_main_loop(void)
tor_assert(second_timer);
}
+#ifndef USE_BUFFEREVENTS
+ if (!refill_timer) {
+ struct timeval refill_interval;
+ int msecs = get_options()->TokenBucketRefillInterval;
+
+ refill_interval.tv_sec = msecs/1000;
+ refill_interval.tv_usec = (msecs%1000)*1000;
+
+ refill_timer = periodic_timer_new(tor_libevent_get_base(),
+ &refill_interval,
+ refill_callback,
+ NULL);
+ tor_assert(refill_timer);
+ }
+#endif
+
for (;;) {
if (nt_service_is_stopping())
return 0;
@@ -1632,11 +1957,13 @@ process_signal(uintptr_t sig)
case SIGUSR1:
/* prefer to log it at INFO, but make sure we always see it */
dumpstats(get_min_log_level()<LOG_INFO ? get_min_log_level() : LOG_INFO);
+ control_event_signal(sig);
break;
case SIGUSR2:
switch_logs_debug();
log_debug(LD_GENERAL,"Caught USR2, going to loglevel debug. "
"Send HUP to change back.");
+ control_event_signal(sig);
break;
case SIGHUP:
if (do_hup() < 0) {
@@ -1644,6 +1971,7 @@ process_signal(uintptr_t sig)
tor_cleanup();
exit(1);
}
+ control_event_signal(sig);
break;
#ifdef SIGCHLD
case SIGCHLD:
@@ -1665,10 +1993,18 @@ process_signal(uintptr_t sig)
}
case SIGCLEARDNSCACHE:
addressmap_clear_transient();
+ control_event_signal(sig);
break;
}
}
+/** Returns Tor's uptime. */
+long
+get_uptime(void)
+{
+ return stats_n_seconds_working;
+}
+
extern uint64_t rephist_total_alloc;
extern uint32_t rephist_total_num;
@@ -1715,13 +2051,13 @@ dumpstats(int severity)
log(severity,LD_GENERAL,
"Conn %d: %d bytes waiting on inbuf (len %d, last read %d secs ago)",
i,
- (int)buf_datalen(conn->inbuf),
+ (int)connection_get_inbuf_len(conn),
(int)buf_allocation(conn->inbuf),
(int)(now - conn->timestamp_lastread));
log(severity,LD_GENERAL,
"Conn %d: %d bytes waiting on outbuf "
"(len %d, last written %d secs ago)",i,
- (int)buf_datalen(conn->outbuf),
+ (int)connection_get_outbuf_len(conn),
(int)buf_allocation(conn->outbuf),
(int)(now - conn->timestamp_lastwritten));
if (conn->type == CONN_TYPE_OR) {
@@ -1893,9 +2229,15 @@ tor_init(int argc, char *argv[])
default:
add_temp_log(LOG_NOTICE);
}
+ quiet_level = quiet;
- log(LOG_NOTICE, LD_GENERAL, "Tor v%s. This is experimental software. "
- "Do not rely on it for strong anonymity. (Running on %s)",get_version(),
+ 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(),
+#ifdef USE_BUFFEREVENTS
+ " (with bufferevents)",
+#else
+ "",
+#endif
get_uname());
if (network_init()<0) {
@@ -1936,7 +2278,7 @@ static tor_lockfile_t *lockfile = NULL;
* return -1 if we can't get the lockfile. Return 0 on success.
*/
int
-try_locking(or_options_t *options, int err_if_locked)
+try_locking(const or_options_t *options, int err_if_locked)
{
if (lockfile)
return 0;
@@ -2015,9 +2357,11 @@ tor_free_all(int postfork)
clear_pending_onions();
circuit_free_all();
entry_guards_free_all();
+ pt_free_all();
connection_free_all();
buf_shrink_freelists(1);
memarea_clear_freelist();
+ nodelist_free_all();
microdesc_free_all();
if (!postfork) {
config_free_all();
@@ -2049,7 +2393,7 @@ tor_free_all(int postfork)
void
tor_cleanup(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->command == CMD_RUN_TOR) {
time_t now = time(NULL);
/* Remove our pid file. We don't care if there was an error when we
diff --git a/src/or/main.h b/src/or/main.h
index 0551f7aaf..c8903642d 100644
--- a/src/or/main.h
+++ b/src/or/main.h
@@ -14,7 +14,9 @@
extern int can_complete_circuit;
-int connection_add(connection_t *conn);
+int connection_add_impl(connection_t *conn, int is_connecting);
+#define connection_add(conn) connection_add_impl((conn), 0)
+#define connection_add_connecting(conn) connection_add_impl((conn), 1)
int connection_remove(connection_t *conn);
void connection_unregister_events(connection_t *conn);
int connection_in_array(connection_t *conn);
@@ -22,10 +24,13 @@ void add_connection_to_closeable_list(connection_t *conn);
int connection_is_on_closeable_list(connection_t *conn);
smartlist_t *get_connection_array(void);
+uint64_t get_bytes_read(void);
+uint64_t get_bytes_written(void);
/** Bitmask for events that we can turn on and off with
* connection_watch_events. */
typedef enum watchable_events {
+ /* Yes, it is intentional that these match Libevent's EV_READ and EV_WRITE */
READ_EVENT=0x02, /**< We want to know when a connection is readable */
WRITE_EVENT=0x04 /**< We want to know when a connection is writable */
} watchable_events_t;
@@ -46,10 +51,13 @@ void directory_info_has_arrived(time_t now, int from_cache);
void ip_address_changed(int at_interface);
void dns_servers_relaunch_checks(void);
+long get_uptime(void);
+unsigned get_signewnym_epoch(void);
+
void handle_signals(int is_parent);
void process_signal(uintptr_t sig);
-int try_locking(or_options_t *options, int err_if_locked);
+int try_locking(const or_options_t *options, int err_if_locked);
int have_lockfile(void);
void release_lockfile(void);
diff --git a/src/or/microdesc.c b/src/or/microdesc.c
index 7c67d5144..92f5c0358 100644
--- a/src/or/microdesc.c
+++ b/src/or/microdesc.c
@@ -3,7 +3,14 @@
#include "or.h"
#include "config.h"
+#include "directory.h"
+#include "dirserv.h"
#include "microdesc.h"
+#include "networkstatus.h"
+#include "nodelist.h"
+#include "policies.h"
+#include "router.h"
+#include "routerlist.h"
#include "routerparse.h"
/** A data structure to hold a bunch of cached microdescriptors. There are
@@ -121,15 +128,19 @@ get_microdesc_cache(void)
* ending at <b>eos</b>, and store them in <b>cache</b>. If <b>no-save</b>,
* mark them as non-writable to disk. If <b>where</b> is SAVED_IN_CACHE,
* leave their bodies as pointers to the mmap'd cache. If where is
- * <b>SAVED_NOWHERE</b>, do not allow annotations. Return a list of the added
- * microdescriptors. */
+ * <b>SAVED_NOWHERE</b>, do not allow annotations. If listed_at is positive,
+ * set the last_listed field of every microdesc to listed_at. If
+ * requested_digests is non-null, then it contains a list of digests we mean
+ * to allow, so we should reject any non-requested microdesc with a different
+ * digest, and alter the list to contain only the digests of those microdescs
+ * we didn't find.
+ * Return a newly allocated list of the added microdescriptors, or NULL */
smartlist_t *
microdescs_add_to_cache(microdesc_cache_t *cache,
const char *s, const char *eos, saved_location_t where,
- int no_save)
+ int no_save, time_t listed_at,
+ smartlist_t *requested_digests256)
{
- /*XXXX need an argument that sets last_listed as appropriate. */
-
smartlist_t *descriptors, *added;
const int allow_annotations = (where != SAVED_NOWHERE);
const int copy_body = (where != SAVED_IN_CACHE);
@@ -137,6 +148,33 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
descriptors = microdescs_parse_from_string(s, eos,
allow_annotations,
copy_body);
+ if (listed_at > 0) {
+ SMARTLIST_FOREACH(descriptors, microdesc_t *, md,
+ md->last_listed = listed_at);
+ }
+ if (requested_digests256) {
+ digestmap_t *requested; /* XXXX actuqlly we should just use a
+ digest256map */
+ requested = digestmap_new();
+ SMARTLIST_FOREACH(requested_digests256, const char *, cp,
+ digestmap_set(requested, cp, (void*)1));
+ SMARTLIST_FOREACH_BEGIN(descriptors, microdesc_t *, md) {
+ if (digestmap_get(requested, md->digest)) {
+ digestmap_set(requested, md->digest, (void*)2);
+ } else {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Received non-requested microcdesc");
+ microdesc_free(md);
+ SMARTLIST_DEL_CURRENT(descriptors, md);
+ }
+ } SMARTLIST_FOREACH_END(md);
+ SMARTLIST_FOREACH_BEGIN(requested_digests256, char *, cp) {
+ if (digestmap_get(requested, cp) == (void*)2) {
+ tor_free(cp);
+ SMARTLIST_DEL_CURRENT(requested_digests256, cp);
+ }
+ } SMARTLIST_FOREACH_END(cp);
+ digestmap_free(requested, NULL);
+ }
added = microdescs_add_list_to_cache(cache, descriptors, where, no_save);
smartlist_free(descriptors);
@@ -144,7 +182,7 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
}
/* As microdescs_add_to_cache, but takes a list of micrdescriptors instead of
- * a string to encode. Frees any members of <b>descriptors</b> that it does
+ * a string to decode. Frees any members of <b>descriptors</b> that it does
* not add. */
smartlist_t *
microdescs_add_list_to_cache(microdesc_cache_t *cache,
@@ -200,6 +238,7 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache,
md->no_save = no_save;
HT_INSERT(microdesc_map, &cache->map, md);
+ md->held_in_map = 1;
smartlist_add(added, md);
++cache->n_seen;
cache->total_len_seen += md->bodylen;
@@ -208,6 +247,15 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache,
if (f)
finish_writing_to_file(open_file); /*XXX Check me.*/
+ {
+ networkstatus_t *ns = networkstatus_get_latest_consensus();
+ if (ns && ns->flavor == FLAV_MICRODESC)
+ SMARTLIST_FOREACH(added, microdesc_t *, md, nodelist_add_microdesc(md));
+ }
+
+ if (smartlist_len(added))
+ router_dir_info_changed();
+
return added;
}
@@ -219,6 +267,7 @@ microdesc_cache_clear(microdesc_cache_t *cache)
for (entry = HT_START(microdesc_map, &cache->map); entry; entry = next) {
microdesc_t *md = *entry;
next = HT_NEXT_RMV(microdesc_map, &cache->map, entry);
+ md->held_in_map = 0;
microdesc_free(md);
}
HT_CLEAR(microdesc_map, &cache->map);
@@ -247,7 +296,7 @@ microdesc_cache_reload(microdesc_cache_t *cache)
mm = cache->cache_content = tor_mmap_file(cache->cache_fname);
if (mm) {
added = microdescs_add_to_cache(cache, mm->data, mm->data+mm->size,
- SAVED_IN_CACHE, 0);
+ SAVED_IN_CACHE, 0, -1, NULL);
if (added) {
total += smartlist_len(added);
smartlist_free(added);
@@ -260,7 +309,7 @@ microdesc_cache_reload(microdesc_cache_t *cache)
cache->journal_len = (size_t) st.st_size;
added = microdescs_add_to_cache(cache, journal_content,
journal_content+st.st_size,
- SAVED_IN_JOURNAL, 0);
+ SAVED_IN_JOURNAL, 0, -1, NULL);
if (added) {
total += smartlist_len(added);
smartlist_free(added);
@@ -293,9 +342,11 @@ microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force)
size_t bytes_dropped = 0;
time_t now = time(NULL);
- (void) force;
- /* In 0.2.2, we let this proceed unconditionally: only authorities have
- * microdesc caches. */
+ /* If we don't know a live consensus, don't believe last_listed values: we
+ * might be starting up after being down for a while. */
+ if (! force &&
+ ! networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC))
+ return;
if (cutoff <= 0)
cutoff = now - TOLERATE_MICRODESC_AGE;
@@ -305,6 +356,7 @@ microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force)
++dropped;
victim = *mdp;
mdp = HT_NEXT_RMV(microdesc_map, &cache->map, mdp);
+ victim->held_in_map = 0;
bytes_dropped += victim->bodylen;
microdesc_free(victim);
} else {
@@ -390,6 +442,7 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
/* log? return -1? die? coredump the universe? */
continue;
}
+ tor_assert(((size_t)size) == annotation_len + md->bodylen);
md->off = off + annotation_len;
off += size;
if (md->saved_location != SAVED_IN_CACHE) {
@@ -415,7 +468,21 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
SMARTLIST_FOREACH_BEGIN(wrote, microdesc_t *, md) {
tor_assert(md->saved_location == SAVED_IN_CACHE);
md->body = (char*)cache->cache_content->data + md->off;
- tor_assert(fast_memeq(md->body, "onion-key", 9));
+ if (PREDICT_UNLIKELY(
+ md->bodylen < 9 || fast_memneq(md->body, "onion-key", 9) != 0)) {
+ /* XXXX023 once bug 2022 is solved, we can kill this block and turn it
+ * into just the tor_assert(!memcmp) */
+ off_t avail = cache->cache_content->size - md->off;
+ char *bad_str;
+ tor_assert(avail >= 0);
+ bad_str = tor_strndup(md->body, MIN(128, (size_t)avail));
+ log_err(LD_BUG, "After rebuilding microdesc cache, offsets seem wrong. "
+ " At offset %d, I expected to find a microdescriptor starting "
+ " with \"onion-key\". Instead I got %s.",
+ (int)md->off, escaped(bad_str));
+ tor_free(bad_str);
+ tor_assert(fast_memeq(md->body, "onion-key", 9));
+ }
} SMARTLIST_FOREACH_END(md);
smartlist_free(wrote);
@@ -432,6 +499,28 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force)
return 0;
}
+/** Make sure that the reference count of every microdescriptor in cache is
+ * accurate. */
+void
+microdesc_check_counts(void)
+{
+ microdesc_t **mdp;
+ if (!the_microdesc_cache)
+ return;
+
+ HT_FOREACH(mdp, microdesc_map, &the_microdesc_cache->map) {
+ microdesc_t *md = *mdp;
+ unsigned int found=0;
+ const smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, node_t *, node, {
+ if (node->md == md) {
+ ++found;
+ }
+ });
+ tor_assert(found == md->held_by_nodes);
+ }
+}
+
/** Deallocate a single microdescriptor. Note: the microdescriptor MUST have
* previously been removed from the cache if it had ever been inserted. */
void
@@ -439,7 +528,43 @@ microdesc_free(microdesc_t *md)
{
if (!md)
return;
- /* Must be removed from hash table! */
+
+ /* Make sure that the microdesc was really removed from the appropriate data
+ structures. */
+ if (md->held_in_map) {
+ microdesc_cache_t *cache = get_microdesc_cache();
+ microdesc_t *md2 = HT_FIND(microdesc_map, &cache->map, md);
+ if (md2 == md) {
+ log_warn(LD_BUG, "microdesc_free() called, but md was still in "
+ "microdesc_map");
+ HT_REMOVE(microdesc_map, &cache->map, md);
+ } else {
+ log_warn(LD_BUG, "microdesc_free() called with held_in_map set, but "
+ "microdesc was not in the map.");
+ }
+ tor_fragile_assert();
+ }
+ if (md->held_by_nodes) {
+ int found=0;
+ const smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, node_t *, node, {
+ if (node->md == md) {
+ ++found;
+ node->md = NULL;
+ }
+ });
+ if (found) {
+ log_warn(LD_BUG, "microdesc_free() called, but md was still referenced "
+ "%d node(s); held_by_nodes == %u", found, md->held_by_nodes);
+ } else {
+ log_warn(LD_BUG, "microdesc_free() called with held_by_nodes set to %u, "
+ "but md was not referenced by any nodes", md->held_by_nodes);
+ }
+ tor_fragile_assert();
+ }
+ //tor_assert(md->held_in_map == 0);
+ //tor_assert(md->held_by_nodes == 0);
+
if (md->onion_pkey)
crypto_free_pk_env(md->onion_pkey);
if (md->body && md->saved_location != SAVED_IN_CACHE)
@@ -449,7 +574,7 @@ microdesc_free(microdesc_t *md)
SMARTLIST_FOREACH(md->family, char *, cp, tor_free(cp));
smartlist_free(md->family);
}
- tor_free(md->exitsummary);
+ short_policy_free(md->exit_policy);
tor_free(md);
}
@@ -491,3 +616,147 @@ microdesc_average_size(microdesc_cache_t *cache)
return (size_t)(cache->total_len_seen / cache->n_seen);
}
+/** Return a smartlist of all the sha256 digest of the microdescriptors that
+ * are listed in <b>ns</b> but not present in <b>cache</b>. Returns pointers
+ * to internals of <b>ns</b>; you should not free the members of the resulting
+ * smartlist. Omit all microdescriptors whose digest appear in <b>skip</b>. */
+smartlist_t *
+microdesc_list_missing_digest256(networkstatus_t *ns, microdesc_cache_t *cache,
+ int downloadable_only, digestmap_t *skip)
+{
+ smartlist_t *result = smartlist_create();
+ time_t now = time(NULL);
+ tor_assert(ns->flavor == FLAV_MICRODESC);
+ SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
+ if (microdesc_cache_lookup_by_digest256(cache, rs->descriptor_digest))
+ continue;
+ if (downloadable_only &&
+ !download_status_is_ready(&rs->dl_status, now,
+ MAX_MICRODESC_DOWNLOAD_FAILURES))
+ continue;
+ if (skip && digestmap_get(skip, rs->descriptor_digest))
+ continue;
+ if (tor_mem_is_zero(rs->descriptor_digest, DIGEST256_LEN))
+ continue; /* This indicates a bug somewhere XXXX023*/
+ /* XXXX Also skip if we're a noncache and wouldn't use this router.
+ * XXXX NM Microdesc
+ */
+ smartlist_add(result, rs->descriptor_digest);
+ } SMARTLIST_FOREACH_END(rs);
+ return result;
+}
+
+/** Launch download requests for mircodescriptors as appropriate.
+ *
+ * Specifically, we should launch download requests if we are configured to
+ * download mirodescriptors, and there are some microdescriptors listed the
+ * current microdesc consensus that we don't have, and either we never asked
+ * for them, or we failed to download them but we're willing to retry.
+ */
+void
+update_microdesc_downloads(time_t now)
+{
+ const or_options_t *options = get_options();
+ networkstatus_t *consensus;
+ smartlist_t *missing;
+ digestmap_t *pending;
+
+ if (should_delay_dir_fetches(options))
+ return;
+ if (directory_too_idle_to_fetch_descriptors(options, now))
+ return;
+
+ consensus = networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC);
+ if (!consensus)
+ return;
+
+ if (!we_fetch_microdescriptors(options))
+ return;
+
+ pending = digestmap_new();
+ list_pending_microdesc_downloads(pending);
+
+ missing = microdesc_list_missing_digest256(consensus,
+ get_microdesc_cache(),
+ 1,
+ pending);
+ digestmap_free(pending, NULL);
+
+ launch_descriptor_downloads(DIR_PURPOSE_FETCH_MICRODESC,
+ missing, NULL, now);
+
+ smartlist_free(missing);
+}
+
+/** For every microdescriptor listed in the current microdecriptor consensus,
+ * update its last_listed field to be at least as recent as the publication
+ * time of the current microdescriptor consensus.
+ */
+void
+update_microdescs_from_networkstatus(time_t now)
+{
+ microdesc_cache_t *cache = get_microdesc_cache();
+ microdesc_t *md;
+ networkstatus_t *ns =
+ networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC);
+
+ if (! ns)
+ return;
+
+ tor_assert(ns->flavor == FLAV_MICRODESC);
+
+ SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
+ md = microdesc_cache_lookup_by_digest256(cache, rs->descriptor_digest);
+ if (md && ns->valid_after > md->last_listed)
+ md->last_listed = ns->valid_after;
+ } SMARTLIST_FOREACH_END(rs);
+}
+
+/** Return true iff we should prefer to use microdescriptors rather than
+ * routerdescs for building circuits. */
+int
+we_use_microdescriptors_for_circuits(const or_options_t *options)
+{
+ int ret = options->UseMicrodescriptors;
+ if (ret == -1) {
+ /* UseMicrodescriptors is "auto"; we need to decide: */
+ /* So we decide that we'll use microdescriptors iff we are not a server,
+ * and we're not autofetching everything. */
+ ret = !server_mode(options) && !options->FetchUselessDescriptors;
+ }
+ return ret;
+}
+
+/** Return true iff we should try to download microdescriptors at all. */
+int
+we_fetch_microdescriptors(const or_options_t *options)
+{
+ if (directory_caches_dir_info(options))
+ return 1;
+ if (options->FetchUselessDescriptors)
+ return 1;
+ return we_use_microdescriptors_for_circuits(options);
+}
+
+/** Return true iff we should try to download router descriptors at all. */
+int
+we_fetch_router_descriptors(const or_options_t *options)
+{
+ if (directory_caches_dir_info(options))
+ return 1;
+ if (options->FetchUselessDescriptors)
+ return 1;
+ return ! we_use_microdescriptors_for_circuits(options);
+}
+
+/** Return the consensus flavor we actually want to use to build circuits. */
+int
+usable_consensus_flavor(void)
+{
+ if (we_use_microdescriptors_for_circuits(get_options())) {
+ return FLAV_MICRODESC;
+ } else {
+ return FLAV_NS;
+ }
+}
+
diff --git a/src/or/microdesc.h b/src/or/microdesc.h
index 77ce8536b..456413281 100644
--- a/src/or/microdesc.h
+++ b/src/or/microdesc.h
@@ -14,9 +14,12 @@
microdesc_cache_t *get_microdesc_cache(void);
+void microdesc_check_counts(void);
+
smartlist_t *microdescs_add_to_cache(microdesc_cache_t *cache,
const char *s, const char *eos, saved_location_t where,
- int no_save);
+ int no_save, time_t listed_at,
+ smartlist_t *requested_digests256);
smartlist_t *microdescs_add_list_to_cache(microdesc_cache_t *cache,
smartlist_t *descriptors, saved_location_t where,
int no_save);
@@ -31,8 +34,21 @@ microdesc_t *microdesc_cache_lookup_by_digest256(microdesc_cache_t *cache,
size_t microdesc_average_size(microdesc_cache_t *cache);
+smartlist_t *microdesc_list_missing_digest256(networkstatus_t *ns,
+ microdesc_cache_t *cache,
+ int downloadable_only,
+ digestmap_t *skip);
+
void microdesc_free(microdesc_t *md);
void microdesc_free_all(void);
+void update_microdesc_downloads(time_t now);
+void update_microdescs_from_networkstatus(time_t now);
+
+int usable_consensus_flavor(void);
+int we_fetch_microdescriptors(const or_options_t *options);
+int we_fetch_router_descriptors(const or_options_t *options);
+int we_use_microdescriptors_for_circuits(const or_options_t *options);
+
#endif
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c
index 1aa4e4a23..7cd9d02c3 100644
--- a/src/or/networkstatus.c
+++ b/src/or/networkstatus.c
@@ -20,7 +20,9 @@
#include "dirserv.h"
#include "dirvote.h"
#include "main.h"
+#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "relay.h"
#include "router.h"
#include "routerlist.h"
@@ -44,8 +46,21 @@ static strmap_t *named_server_map = NULL;
* as unnamed for some server in the consensus. */
static strmap_t *unnamed_server_map = NULL;
-/** Most recently received and validated v3 consensus network status. */
-static networkstatus_t *current_consensus = NULL;
+/** Most recently received and validated v3 consensus network status,
+ * of whichever type we are using for our own circuits. This will be the same
+ * as one of current_ns_consensus or current_md_consensus.
+ */
+#define current_consensus \
+ (we_use_microdescriptors_for_circuits(get_options()) ? \
+ current_md_consensus : current_ns_consensus)
+
+/** Most recently received and validated v3 "ns"-flavored consensus network
+ * status. */
+static networkstatus_t *current_ns_consensus = NULL;
+
+/** Most recently received and validated v3 "microdec"-flavored consensus
+ * network status. */
+static networkstatus_t *current_md_consensus = NULL;
/** A v3 consensus networkstatus that we've received, but which we don't
* have enough certificates to be happy about. */
@@ -94,9 +109,8 @@ void
networkstatus_reset_warnings(void)
{
if (current_consensus) {
- SMARTLIST_FOREACH(current_consensus->routerstatus_list,
- routerstatus_t *, rs,
- rs->name_lookup_warned = 0);
+ SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node,
+ node->name_lookup_warned = 0);
}
have_warned_about_old_version = 0;
@@ -199,7 +213,7 @@ router_reload_consensus_networkstatus(void)
char *filename;
char *s;
struct stat st;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
const unsigned int flags = NSSET_FROM_CACHE | NSSET_DONT_DOWNLOAD_CERTS;
int flav;
@@ -271,6 +285,7 @@ router_reload_consensus_networkstatus(void)
update_certificate_downloads(time(NULL));
routers_update_all_from_networkstatus(time(NULL), 3);
+ update_microdescs_from_networkstatus(time(NULL));
return 0;
}
@@ -469,7 +484,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus,
int n_bad = 0;
int n_unknown = 0;
int n_no_signature = 0;
- int n_v3_authorities = get_n_authorities(V3_AUTHORITY);
+ int n_v3_authorities = get_n_authorities(V3_DIRINFO);
int n_required = n_v3_authorities/2 + 1;
smartlist_t *need_certs_from = smartlist_create();
smartlist_t *unrecognized = smartlist_create();
@@ -540,7 +555,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus,
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
trusted_dir_server_t *, ds,
{
- if ((ds->type & V3_AUTHORITY) &&
+ if ((ds->type & V3_DIRINFO) &&
!networkstatus_get_voter_by_id(consensus, ds->v3_identity_digest))
smartlist_add(missing_authorities, ds);
});
@@ -723,7 +738,7 @@ router_set_networkstatus_v2(const char *s, time_t arrived_at,
base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN);
if (!(trusted_dir =
router_get_trusteddirserver_by_digest(ns->identity_digest)) ||
- !(trusted_dir->type & V2_AUTHORITY)) {
+ !(trusted_dir->type & V2_DIRINFO)) {
log_info(LD_DIR, "Network status was signed, but not by an authoritative "
"directory we recognize.");
source_desc = fp;
@@ -927,10 +942,9 @@ compare_digest_to_routerstatus_entry(const void *_key, const void **_member)
return tor_memcmp(key, rs->identity_digest, DIGEST_LEN);
}
-/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
- * NULL if none was found. */
+/** As networkstatus_v2_find_entry, but do not return a const pointer */
routerstatus_t *
-networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest)
+networkstatus_v2_find_mutable_entry(networkstatus_v2_t *ns, const char *digest)
{
return smartlist_bsearch(ns->entries, digest,
compare_digest_to_routerstatus_entry);
@@ -938,14 +952,29 @@ networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest)
/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
* NULL if none was found. */
+const routerstatus_t *
+networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest)
+{
+ return networkstatus_v2_find_mutable_entry(ns, digest);
+}
+
+/** As networkstatus_find_entry, but do not return a const pointer */
routerstatus_t *
-networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest)
+networkstatus_vote_find_mutable_entry(networkstatus_t *ns, const char *digest)
{
return smartlist_bsearch(ns->routerstatus_list, digest,
compare_digest_to_routerstatus_entry);
}
-/*XXXX make this static once functions are moved into this file. */
+/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or
+ * NULL if none was found. */
+const routerstatus_t *
+networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest)
+{
+ return networkstatus_vote_find_mutable_entry(ns, digest);
+}
+
+/*XXXX MOVE make this static once functions are moved into this file. */
/** Search the routerstatuses in <b>ns</b> for one whose identity digest is
* <b>digest</b>. Return value and set *<b>found_out</b> as for
* smartlist_bsearch_idx(). */
@@ -967,22 +996,37 @@ networkstatus_get_v2_list(void)
return networkstatus_v2_list;
}
-/** Return the consensus view of the status of the router whose current
- * <i>descriptor</i> digest is <b>digest</b>, or NULL if no such router is
- * known. */
+/* As router_get_consensus_status_by_descriptor_digest, but does not return
+ * a const pointer */
routerstatus_t *
-router_get_consensus_status_by_descriptor_digest(const char *digest)
+router_get_mutable_consensus_status_by_descriptor_digest(
+ networkstatus_t *consensus,
+ const char *digest)
{
- if (!current_consensus) return NULL;
- if (!current_consensus->desc_digest_map) {
- digestmap_t * m = current_consensus->desc_digest_map = digestmap_new();
- SMARTLIST_FOREACH(current_consensus->routerstatus_list,
+ if (!consensus)
+ consensus = current_consensus;
+ if (!consensus)
+ return NULL;
+ if (!consensus->desc_digest_map) {
+ digestmap_t *m = consensus->desc_digest_map = digestmap_new();
+ SMARTLIST_FOREACH(consensus->routerstatus_list,
routerstatus_t *, rs,
{
digestmap_set(m, rs->descriptor_digest, rs);
});
}
- return digestmap_get(current_consensus->desc_digest_map, digest);
+ return digestmap_get(consensus->desc_digest_map, digest);
+}
+
+/** Return the consensus view of the status of the router whose current
+ * <i>descriptor</i> digest in <b>consensus</b> is <b>digest</b>, or NULL if
+ * no such router is known. */
+const routerstatus_t *
+router_get_consensus_status_by_descriptor_digest(networkstatus_t *consensus,
+ const char *digest)
+{
+ return router_get_mutable_consensus_status_by_descriptor_digest(
+ consensus, digest);
}
/** Given the digest of a router descriptor, return its current download
@@ -991,7 +1035,10 @@ download_status_t *
router_get_dl_status_by_descriptor_digest(const char *d)
{
routerstatus_t *rs;
- if ((rs = router_get_consensus_status_by_descriptor_digest(d)))
+ if (!current_ns_consensus)
+ return NULL;
+ if ((rs = router_get_mutable_consensus_status_by_descriptor_digest(
+ current_ns_consensus, d)))
return &rs->dl_status;
if (v2_download_status_map)
return digestmap_get(v2_download_status_map, d);
@@ -999,10 +1046,9 @@ router_get_dl_status_by_descriptor_digest(const char *d)
return NULL;
}
-/** Return the consensus view of the status of the router whose identity
- * digest is <b>digest</b>, or NULL if we don't know about any such router. */
+/** As router_get_consensus_status_by_id, but do not return a const pointer */
routerstatus_t *
-router_get_consensus_status_by_id(const char *digest)
+router_get_mutable_consensus_status_by_id(const char *digest)
{
if (!current_consensus)
return NULL;
@@ -1010,100 +1056,27 @@ router_get_consensus_status_by_id(const char *digest)
compare_digest_to_routerstatus_entry);
}
+/** Return the consensus view of the status of the router whose identity
+ * digest is <b>digest</b>, or NULL if we don't know about any such router. */
+const routerstatus_t *
+router_get_consensus_status_by_id(const char *digest)
+{
+ return router_get_mutable_consensus_status_by_id(digest);
+}
+
/** Given a nickname (possibly verbose, possibly a hexadecimal digest), return
* the corresponding routerstatus_t, or NULL if none exists. Warn the
* user if <b>warn_if_unnamed</b> is set, and they have specified a router by
* nickname, but the Named flag isn't set for that router. */
-routerstatus_t *
+const routerstatus_t *
router_get_consensus_status_by_nickname(const char *nickname,
int warn_if_unnamed)
{
- char digest[DIGEST_LEN];
- routerstatus_t *best=NULL;
- smartlist_t *matches=NULL;
- const char *named_id=NULL;
-
- if (!current_consensus || !nickname)
- return NULL;
-
- /* Is this name really a hexadecimal identity digest? */
- if (nickname[0] == '$') {
- if (base16_decode(digest, DIGEST_LEN, nickname+1, strlen(nickname+1))<0)
- return NULL;
- return networkstatus_vote_find_entry(current_consensus, digest);
- } else if (strlen(nickname) == HEX_DIGEST_LEN &&
- (base16_decode(digest, DIGEST_LEN, nickname, strlen(nickname))==0)) {
- return networkstatus_vote_find_entry(current_consensus, digest);
- }
-
- /* Is there a server that is Named with this name? */
- if (named_server_map)
- named_id = strmap_get_lc(named_server_map, nickname);
- if (named_id)
- return networkstatus_vote_find_entry(current_consensus, named_id);
-
- /* Okay; is this name listed as Unnamed? */
- if (unnamed_server_map &&
- strmap_get_lc(unnamed_server_map, nickname)) {
- log_info(LD_GENERAL, "The name %s is listed as Unnamed; it is not the "
- "canonical name of any server we know.", escaped(nickname));
+ const node_t *node = node_get_by_nickname(nickname, warn_if_unnamed);
+ if (node)
+ return node->rs;
+ else
return NULL;
- }
-
- /* This name is not canonical for any server; go through the list and
- * see who it matches. */
- /*XXXX This is inefficient; optimize it if it matters. */
- matches = smartlist_create();
- SMARTLIST_FOREACH(current_consensus->routerstatus_list,
- routerstatus_t *, lrs,
- {
- if (!strcasecmp(lrs->nickname, nickname)) {
- if (lrs->is_named) {
- tor_fragile_assert() /* This should never happen. */
- smartlist_free(matches);
- return lrs;
- } else {
- if (lrs->is_unnamed) {
- tor_fragile_assert(); /* nor should this. */
- smartlist_clear(matches);
- best=NULL;
- break;
- }
- smartlist_add(matches, lrs);
- best = lrs;
- }
- }
- });
-
- if (smartlist_len(matches)>1 && warn_if_unnamed) {
- int any_unwarned=0;
- SMARTLIST_FOREACH(matches, routerstatus_t *, lrs,
- {
- if (! lrs->name_lookup_warned) {
- lrs->name_lookup_warned=1;
- any_unwarned=1;
- }
- });
- if (any_unwarned) {
- log_warn(LD_CONFIG,"There are multiple matches for the nickname \"%s\","
- " but none is listed as named by the directory authorities. "
- "Choosing one arbitrarily.", nickname);
- }
- } else if (warn_if_unnamed && best && !best->name_lookup_warned) {
- char fp[HEX_DIGEST_LEN+1];
- base16_encode(fp, sizeof(fp),
- best->identity_digest, DIGEST_LEN);
- log_warn(LD_CONFIG,
- "When looking up a status, you specified a server \"%s\" by name, "
- "but the directory authorities do not have any key registered for "
- "this nickname -- so it could be used by any server, "
- "not just the one you meant. "
- "To make sure you get the same server in the future, refer to "
- "it by key, as \"$%s\".", nickname, fp);
- best->name_lookup_warned = 1;
- }
- smartlist_free(matches);
- return best;
}
/** Return the identity digest that's mapped to officially by
@@ -1159,7 +1132,7 @@ update_v2_networkstatus_cache_downloads(time_t now)
{
char resource[HEX_DIGEST_LEN+6]; /* fp/hexdigit.z\0 */
tor_addr_t addr;
- if (!(ds->type & V2_AUTHORITY))
+ if (!(ds->type & V2_DIRINFO))
continue;
if (router_digest_is_me(ds->digest))
continue;
@@ -1200,6 +1173,29 @@ update_v2_networkstatus_cache_downloads(time_t now)
}
}
+/** DOCDOC */
+static int
+we_want_to_fetch_flavor(const or_options_t *options, int flavor)
+{
+ if (flavor < 0 || flavor > N_CONSENSUS_FLAVORS) {
+ /* This flavor is crazy; we don't want it */
+ /*XXXX handle unrecognized flavors later */
+ return 0;
+ }
+ if (authdir_mode_v3(options) || directory_caches_dir_info(options)) {
+ /* We want to serve all flavors to others, regardless if we would use
+ * it ourselves. */
+ return 1;
+ }
+ if (options->FetchUselessDescriptors) {
+ /* In order to get all descriptors, we need to fetch all consensuses. */
+ return 1;
+ }
+ /* Otherwise, we want the flavor only if we want to use it to build
+ * circuits. */
+ return flavor == usable_consensus_flavor();
+}
+
/** How many times will we try to fetch a consensus before we give up? */
#define CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES 8
/** How long will we hang onto a possibly live consensus for which we're
@@ -1212,48 +1208,65 @@ static void
update_consensus_networkstatus_downloads(time_t now)
{
int i;
+ const or_options_t *options = get_options();
+
if (!networkstatus_get_live_consensus(now))
time_to_download_next_consensus = now; /* No live consensus? Get one now!*/
if (time_to_download_next_consensus > now)
return; /* Wait until the current consensus is older. */
- /* XXXXNM Microdescs: may need to download more types. */
- if (!download_status_is_ready(&consensus_dl_status[FLAV_NS], now,
- CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES))
- return; /* We failed downloading a consensus too recently. */
- if (connection_get_by_type_purpose(CONN_TYPE_DIR,
- DIR_PURPOSE_FETCH_CONSENSUS))
- return; /* There's an in-progress download.*/
for (i=0; i < N_CONSENSUS_FLAVORS; ++i) {
- consensus_waiting_for_certs_t *waiting = &consensus_waiting_for_certs[i];
+ /* XXXX need some way to download unknown flavors if we are caching. */
+ const char *resource;
+ consensus_waiting_for_certs_t *waiting;
+
+ if (! we_want_to_fetch_flavor(options, i))
+ continue;
+
+ resource = networkstatus_get_flavor_name(i);
+
+ if (!download_status_is_ready(&consensus_dl_status[i], now,
+ CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES))
+ continue; /* We failed downloading a consensus too recently. */
+ if (connection_dir_get_by_purpose_and_resource(
+ DIR_PURPOSE_FETCH_CONSENSUS, resource))
+ continue; /* There's an in-progress download.*/
+
+ waiting = &consensus_waiting_for_certs[i];
if (waiting->consensus) {
/* XXXX make sure this doesn't delay sane downloads. */
- if (waiting->set_at + DELAY_WHILE_FETCHING_CERTS > now)
- return; /* We're still getting certs for this one. */
- else {
+ if (waiting->set_at + DELAY_WHILE_FETCHING_CERTS > now) {
+ continue; /* We're still getting certs for this one. */
+ } else {
if (!waiting->dl_failed) {
- download_status_failed(&consensus_dl_status[FLAV_NS], 0);
+ download_status_failed(&consensus_dl_status[i], 0);
waiting->dl_failed=1;
}
}
}
- }
- log_info(LD_DIR, "Launching networkstatus consensus download.");
- directory_get_from_dirserver(DIR_PURPOSE_FETCH_CONSENSUS,
- ROUTER_PURPOSE_GENERAL, NULL,
- PDS_RETRY_IF_NO_SERVERS);
+ log_info(LD_DIR, "Launching %s networkstatus consensus download.",
+ networkstatus_get_flavor_name(i));
+
+ directory_get_from_dirserver(DIR_PURPOSE_FETCH_CONSENSUS,
+ ROUTER_PURPOSE_GENERAL, resource,
+ PDS_RETRY_IF_NO_SERVERS);
+ }
}
/** Called when an attempt to download a consensus fails: note that the
* failure occurred, and possibly retry. */
void
-networkstatus_consensus_download_failed(int status_code)
+networkstatus_consensus_download_failed(int status_code, const char *flavname)
{
- /* XXXXNM Microdescs: may need to handle more types. */
- download_status_failed(&consensus_dl_status[FLAV_NS], status_code);
- /* Retry immediately, if appropriate. */
- update_consensus_networkstatus_downloads(time(NULL));
+ int flav = networkstatus_parse_flavor_name(flavname);
+ if (flav >= 0) {
+ tor_assert(flav < N_CONSENSUS_FLAVORS);
+ /* XXXX handle unrecognized flavors */
+ download_status_failed(&consensus_dl_status[flav], status_code);
+ /* Retry immediately, if appropriate. */
+ update_consensus_networkstatus_downloads(time(NULL));
+ }
}
/** How long do we (as a cache) wait after a consensus becomes non-fresh
@@ -1265,7 +1278,7 @@ networkstatus_consensus_download_failed(int status_code)
void
update_consensus_networkstatus_fetch_time(time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
networkstatus_t *c = networkstatus_get_live_consensus(now);
if (c) {
long dl_interval;
@@ -1339,7 +1352,7 @@ update_consensus_networkstatus_fetch_time(time_t now)
* fetches yet (e.g. we demand bridges and none are yet known).
* Else return 0. */
int
-should_delay_dir_fetches(or_options_t *options)
+should_delay_dir_fetches(const or_options_t *options)
{
if (options->UseBridges && !any_bridge_descriptors_known()) {
log_info(LD_DIR, "delaying dir fetches (no running bridges known)");
@@ -1353,7 +1366,7 @@ should_delay_dir_fetches(or_options_t *options)
void
update_networkstatus_downloads(time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (should_delay_dir_fetches(options))
return;
if (authdir_mode_any_main(options) || options->FetchV2Networkstatus)
@@ -1374,7 +1387,10 @@ update_certificate_downloads(time_t now)
now);
}
- authority_certs_fetch_missing(current_consensus, now);
+ if (current_ns_consensus)
+ authority_certs_fetch_missing(current_ns_consensus, now);
+ if (current_md_consensus)
+ authority_certs_fetch_missing(current_md_consensus, now);
}
/** Return 1 if we have a consensus but we don't have enough certificates
@@ -1382,7 +1398,7 @@ update_certificate_downloads(time_t now)
int
consensus_is_waiting_for_certs(void)
{
- return consensus_waiting_for_certs[USABLE_CONSENSUS_FLAVOR].consensus
+ return consensus_waiting_for_certs[usable_consensus_flavor()].consensus
? 1 : 0;
}
@@ -1406,6 +1422,18 @@ networkstatus_get_latest_consensus(void)
return current_consensus;
}
+/** DOCDOC */
+networkstatus_t *
+networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
+{
+ if (f == FLAV_NS)
+ return current_ns_consensus;
+ else if (f == FLAV_MICRODESC)
+ return current_md_consensus;
+ else
+ tor_assert(0);
+}
+
/** Return the most recent consensus that we have downloaded, or NULL if it is
* no longer live. */
networkstatus_t *
@@ -1425,13 +1453,15 @@ networkstatus_get_live_consensus(time_t now)
/** As networkstatus_get_live_consensus(), but is way more tolerant of expired
* consensuses. */
networkstatus_t *
-networkstatus_get_reasonably_live_consensus(time_t now)
+networkstatus_get_reasonably_live_consensus(time_t now, int flavor)
{
#define REASONABLY_LIVE_TIME (24*60*60)
- if (current_consensus &&
- current_consensus->valid_after <= now &&
- now <= current_consensus->valid_until+REASONABLY_LIVE_TIME)
- return current_consensus;
+ networkstatus_t *consensus =
+ networkstatus_get_latest_consensus_by_flavor(flavor);
+ if (consensus &&
+ consensus->valid_after <= now &&
+ now <= consensus->valid_until+REASONABLY_LIVE_TIME)
+ return consensus;
else
return NULL;
}
@@ -1452,7 +1482,7 @@ routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b)
a->is_exit != b->is_exit ||
a->is_stable != b->is_stable ||
a->is_fast != b->is_fast ||
- a->is_running != b->is_running ||
+ a->is_flagged_running != b->is_flagged_running ||
a->is_named != b->is_named ||
a->is_unnamed != b->is_unnamed ||
a->is_valid != b->is_valid ||
@@ -1493,13 +1523,14 @@ notify_control_networkstatus_changed(const networkstatus_t *old_c,
}
changed = smartlist_create();
- SMARTLIST_FOREACH_JOIN(old_c->routerstatus_list, routerstatus_t *, rs_old,
- new_c->routerstatus_list, routerstatus_t *, rs_new,
- tor_memcmp(rs_old->identity_digest,
- rs_new->identity_digest, DIGEST_LEN),
- smartlist_add(changed, rs_new)) {
+ SMARTLIST_FOREACH_JOIN(
+ old_c->routerstatus_list, const routerstatus_t *, rs_old,
+ new_c->routerstatus_list, const routerstatus_t *, rs_new,
+ tor_memcmp(rs_old->identity_digest,
+ rs_new->identity_digest, DIGEST_LEN),
+ smartlist_add(changed, (void*) rs_new)) {
if (routerstatus_has_changed(rs_old, rs_new))
- smartlist_add(changed, rs_new);
+ smartlist_add(changed, (void*)rs_new);
} SMARTLIST_FOREACH_JOIN_END(rs_old, rs_new);
control_event_networkstatus_changed(changed);
@@ -1523,7 +1554,6 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c,
rs_new->identity_digest, DIGEST_LEN),
STMT_NIL) {
/* Okay, so we're looking at the same identity. */
- rs_new->name_lookup_warned = rs_old->name_lookup_warned;
rs_new->last_dir_503_at = rs_old->last_dir_503_at;
if (tor_memeq(rs_old->descriptor_digest, rs_new->descriptor_digest,
@@ -1559,7 +1589,7 @@ networkstatus_set_current_consensus(const char *consensus,
networkstatus_t *c=NULL;
int r, result = -1;
time_t now = time(NULL);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char *unverified_fname = NULL, *consensus_fname = NULL;
int flav = networkstatus_parse_flavor_name(flavor);
const unsigned from_cache = flags & NSSET_FROM_CACHE;
@@ -1597,7 +1627,7 @@ networkstatus_set_current_consensus(const char *consensus,
flavor = networkstatus_get_flavor_name(flav);
}
- if (flav != USABLE_CONSENSUS_FLAVOR &&
+ if (flav != usable_consensus_flavor() &&
!directory_caches_dir_info(options)) {
/* This consensus is totally boring to us: we won't use it, and we won't
* serve it. Drop it. */
@@ -1616,9 +1646,16 @@ networkstatus_set_current_consensus(const char *consensus,
if (!strcmp(flavor, "ns")) {
consensus_fname = get_datadir_fname("cached-consensus");
unverified_fname = get_datadir_fname("unverified-consensus");
- if (current_consensus) {
- current_digests = &current_consensus->digests;
- current_valid_after = current_consensus->valid_after;
+ if (current_ns_consensus) {
+ current_digests = &current_ns_consensus->digests;
+ current_valid_after = current_ns_consensus->valid_after;
+ }
+ } else if (!strcmp(flavor, "microdesc")) {
+ consensus_fname = get_datadir_fname("cached-microdesc-consensus");
+ unverified_fname = get_datadir_fname("unverified-microdesc-consensus");
+ if (current_md_consensus) {
+ current_digests = &current_md_consensus->digests;
+ current_valid_after = current_md_consensus->valid_after;
}
} else {
cached_dir_t *cur;
@@ -1695,24 +1732,36 @@ networkstatus_set_current_consensus(const char *consensus,
}
}
- if (!from_cache && flav == USABLE_CONSENSUS_FLAVOR)
+ if (!from_cache && flav == usable_consensus_flavor())
control_event_client_status(LOG_NOTICE, "CONSENSUS_ARRIVED");
/* Are we missing any certificates at all? */
if (r != 1 && dl_certs)
authority_certs_fetch_missing(c, now);
- if (flav == USABLE_CONSENSUS_FLAVOR) {
+ if (flav == usable_consensus_flavor()) {
notify_control_networkstatus_changed(current_consensus, c);
-
- if (current_consensus) {
- networkstatus_copy_old_consensus_info(c, current_consensus);
- networkstatus_vote_free(current_consensus);
+ }
+ if (flav == FLAV_NS) {
+ if (current_ns_consensus) {
+ networkstatus_copy_old_consensus_info(c, current_ns_consensus);
+ networkstatus_vote_free(current_ns_consensus);
/* Defensive programming : we should set current_consensus very soon,
* but we're about to call some stuff in the meantime, and leaving this
* dangling pointer around has proven to be trouble. */
- current_consensus = NULL;
+ current_ns_consensus = NULL;
+ }
+ current_ns_consensus = c;
+ free_consensus = 0; /* avoid free */
+ } else if (flav == FLAV_MICRODESC) {
+ if (current_md_consensus) {
+ networkstatus_copy_old_consensus_info(c, current_md_consensus);
+ networkstatus_vote_free(current_md_consensus);
+ /* more defensive programming */
+ current_md_consensus = NULL;
}
+ current_md_consensus = c;
+ free_consensus = 0; /* avoid free */
}
waiting = &consensus_waiting_for_certs[flav];
@@ -1737,12 +1786,12 @@ networkstatus_set_current_consensus(const char *consensus,
download_status_failed(&consensus_dl_status[flav], 0);
}
- if (flav == USABLE_CONSENSUS_FLAVOR) {
- current_consensus = c;
- free_consensus = 0; /* Prevent free. */
-
- /* XXXXNM Microdescs: needs a non-ns variant. */
+ if (flav == usable_consensus_flavor()) {
+ /* XXXXNM Microdescs: needs a non-ns variant. ???? NM*/
update_consensus_networkstatus_fetch_time(now);
+
+ nodelist_set_consensus(current_consensus);
+
dirvote_recalculate_timing(options, now);
routerstatus_list_update_named_server_map();
cell_ewma_set_scale_factor(options, current_consensus);
@@ -1769,11 +1818,11 @@ networkstatus_set_current_consensus(const char *consensus,
* valid-after time, declare that our clock is skewed. */
#define EARLY_CONSENSUS_NOTICE_SKEW 60
- if (now < current_consensus->valid_after - EARLY_CONSENSUS_NOTICE_SKEW) {
+ if (now < c->valid_after - EARLY_CONSENSUS_NOTICE_SKEW) {
char tbuf[ISO_TIME_LEN+1];
char dbuf[64];
- long delta = now - current_consensus->valid_after;
- format_iso_time(tbuf, current_consensus->valid_after);
+ long delta = now - c->valid_after;
+ format_iso_time(tbuf, c->valid_after);
format_time_interval(dbuf, sizeof(dbuf), delta);
log_warn(LD_GENERAL, "Our clock is %s behind the time published in the "
"consensus network status document (%s GMT). Tor needs an "
@@ -1824,7 +1873,8 @@ void
routers_update_all_from_networkstatus(time_t now, int dir_version)
{
routerlist_t *rl = router_get_routerlist();
- networkstatus_t *consensus = networkstatus_get_live_consensus(now);
+ networkstatus_t *consensus = networkstatus_get_reasonably_live_consensus(now,
+ FLAV_NS);
if (networkstatus_v2_list_has_changed)
download_status_map_update_from_v2_networkstatus();
@@ -1896,7 +1946,7 @@ download_status_map_update_from_v2_networkstatus(void)
dl_status = digestmap_new();
SMARTLIST_FOREACH_BEGIN(networkstatus_v2_list, networkstatus_v2_t *, ns) {
- SMARTLIST_FOREACH_BEGIN(ns->entries, routerstatus_t *, rs) {
+ SMARTLIST_FOREACH_BEGIN(ns->entries, const routerstatus_t *, rs) {
const char *d = rs->descriptor_digest;
download_status_t *s;
if (digestmap_get(dl_status, d))
@@ -1924,7 +1974,8 @@ routerstatus_list_update_named_server_map(void)
named_server_map = strmap_new();
strmap_free(unnamed_server_map, NULL);
unnamed_server_map = strmap_new();
- SMARTLIST_FOREACH(current_consensus->routerstatus_list, routerstatus_t *, rs,
+ SMARTLIST_FOREACH(current_consensus->routerstatus_list,
+ const routerstatus_t *, rs,
{
if (rs->is_named) {
strmap_set_lc(named_server_map, rs->nickname,
@@ -1944,9 +1995,8 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
int reset_failures)
{
trusted_dir_server_t *ds;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
- int namingdir = authdir && options->NamingAuthoritativeDir;
networkstatus_t *ns = current_consensus;
if (!ns || !smartlist_len(ns->routerstatus_list))
return;
@@ -1960,25 +2010,12 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
tor_memcmp(rs->identity_digest,
router->cache_info.identity_digest, DIGEST_LEN),
{
- /* We have no routerstatus for this router. Clear flags and skip it. */
- if (!namingdir)
- router->is_named = 0;
- if (!authdir) {
- if (router->purpose == ROUTER_PURPOSE_GENERAL)
- router_clear_status_flags(router);
- }
}) {
/* We have a routerstatus for this router. */
const char *digest = router->cache_info.identity_digest;
ds = router_get_trusteddirserver_by_digest(digest);
- if (!namingdir) {
- if (rs->is_named && !strcasecmp(router->nickname, rs->nickname))
- router->is_named = 1;
- else
- router->is_named = 0;
- }
/* Is it the same descriptor, or only the same identity? */
if (tor_memeq(router->cache_info.signed_descriptor_digest,
rs->descriptor_digest, DIGEST_LEN)) {
@@ -1986,28 +2023,17 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
router->cache_info.last_listed_as_valid_until = ns->valid_until;
}
- if (!authdir) {
- /* If we're not an authdir, believe others. */
- router->is_valid = rs->is_valid;
- router->is_running = rs->is_running;
- router->is_fast = rs->is_fast;
- router->is_stable = rs->is_stable;
- router->is_possible_guard = rs->is_possible_guard;
- router->is_exit = rs->is_exit;
- router->is_bad_directory = rs->is_bad_directory;
- router->is_bad_exit = rs->is_bad_exit;
- router->is_hs_dir = rs->is_hs_dir;
- } else {
+ if (authdir) {
/* If we _are_ an authority, we should check whether this router
* is one that will cause us to need a reachability test. */
routerinfo_t *old_router =
- router_get_by_digest(router->cache_info.identity_digest);
+ router_get_mutable_by_digest(router->cache_info.identity_digest);
if (old_router != router) {
router->needs_retest_if_added =
dirserv_should_launch_reachability_test(router, old_router);
}
}
- if (router->is_running && ds) {
+ if (rs->is_flagged_running && ds) {
download_status_reset(&ds->v2_ns_dl_status);
}
if (reset_failures) {
@@ -2016,10 +2042,9 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
} SMARTLIST_FOREACH_JOIN_END(rs, router);
/* Now update last_listed_as_valid_until from v2 networkstatuses. */
- /* XXXX If this is slow, we need to rethink the code. */
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, {
time_t live_until = ns->published_on + V2_NETWORKSTATUS_ROUTER_LIFETIME;
- SMARTLIST_FOREACH_JOIN(ns->entries, routerstatus_t *, rs,
+ SMARTLIST_FOREACH_JOIN(ns->entries, const routerstatus_t *, rs,
routers, routerinfo_t *, ri,
tor_memcmp(rs->identity_digest,
ri->cache_info.identity_digest, DIGEST_LEN),
@@ -2040,7 +2065,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
void
signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs)
{
- networkstatus_t *ns = current_consensus;
+ networkstatus_t *ns = current_ns_consensus;
if (!ns)
return;
@@ -2048,11 +2073,11 @@ signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs)
char dummy[DIGEST_LEN];
/* instantiates the digest map. */
memset(dummy, 0, sizeof(dummy));
- router_get_consensus_status_by_descriptor_digest(dummy);
+ router_get_consensus_status_by_descriptor_digest(ns, dummy);
}
SMARTLIST_FOREACH(descs, signed_descriptor_t *, d,
{
- routerstatus_t *rs = digestmap_get(ns->desc_digest_map,
+ const routerstatus_t *rs = digestmap_get(ns->desc_digest_map,
d->signed_descriptor_digest);
if (rs) {
if (ns->valid_until > d->last_listed_as_valid_until)
@@ -2065,7 +2090,7 @@ signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs)
* return the result in a newly allocated string. Used only by controller
* interface (for now.) */
char *
-networkstatus_getinfo_helper_single(routerstatus_t *rs)
+networkstatus_getinfo_helper_single(const routerstatus_t *rs)
{
char buf[RS_ENTRY_LEN+1];
routerstatus_format_entry(buf, sizeof(buf), rs, NULL, NS_CONTROL_PORT);
@@ -2098,6 +2123,9 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now)
statuses = smartlist_create();
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ if (!node)
+ continue;
if (ri->cache_info.published_on < cutoff)
continue;
if (ri->purpose != purpose)
@@ -2105,7 +2133,7 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now)
if (bridge_auth && ri->purpose == ROUTER_PURPOSE_BRIDGE)
dirserv_set_router_is_running(ri, now);
/* then generate and write out status lines for each of them */
- set_routerstatus_from_routerinfo(&rs, ri, now, 0, 0, 0);
+ set_routerstatus_from_routerinfo(&rs, node, ri, now, 0, 0, 0, 0);
smartlist_add(statuses, networkstatus_getinfo_helper_single(&rs));
});
@@ -2120,7 +2148,7 @@ void
networkstatus_dump_bridge_status_to_file(time_t now)
{
char *status = networkstatus_getinfo_by_purpose("bridge", now);
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
size_t len = strlen(options->DataDirectory) + 32;
char *fname = tor_malloc(len);
tor_snprintf(fname, len, "%s"PATH_SEPARATOR"networkstatus-bridges",
@@ -2174,7 +2202,7 @@ get_net_param_from_list(smartlist_t *net_params, const char *param_name,
* <b>min_val</b> and at most <b>max_val</b> and raise/cap the parsed value
* if necessary. */
int32_t
-networkstatus_get_param(networkstatus_t *ns, const char *param_name,
+networkstatus_get_param(const networkstatus_t *ns, const char *param_name,
int32_t default_val, int32_t min_val, int32_t max_val)
{
if (!ns) /* if they pass in null, go find it ourselves */
@@ -2253,7 +2281,7 @@ getinfo_helper_networkstatus(control_connection_t *conn,
const char *question, char **answer,
const char **errmsg)
{
- routerstatus_t *status;
+ const routerstatus_t *status;
(void) conn;
if (!current_consensus) {
@@ -2264,7 +2292,7 @@ getinfo_helper_networkstatus(control_connection_t *conn,
if (!strcmp(question, "ns/all")) {
smartlist_t *statuses = smartlist_create();
SMARTLIST_FOREACH(current_consensus->routerstatus_list,
- routerstatus_t *, rs,
+ const routerstatus_t *, rs,
{
smartlist_add(statuses, networkstatus_getinfo_helper_single(rs));
});
@@ -2308,8 +2336,9 @@ networkstatus_free_all(void)
digestmap_free(v2_download_status_map, _tor_free);
v2_download_status_map = NULL;
- networkstatus_vote_free(current_consensus);
- current_consensus = NULL;
+ networkstatus_vote_free(current_ns_consensus);
+ networkstatus_vote_free(current_md_consensus);
+ current_md_consensus = current_ns_consensus = NULL;
for (i=0; i < N_CONSENSUS_FLAVORS; ++i) {
consensus_waiting_for_certs_t *waiting = &consensus_waiting_for_certs[i];
diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h
index ec2e8f884..1b10f2738 100644
--- a/src/or/networkstatus.h
+++ b/src/or/networkstatus.h
@@ -38,31 +38,46 @@ int router_set_networkstatus_v2(const char *s, time_t arrived_at,
void networkstatus_v2_list_clean(time_t now);
int compare_digest_to_routerstatus_entry(const void *_key,
const void **_member);
-routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns,
+const routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns,
const char *digest);
-routerstatus_t *networkstatus_vote_find_entry(networkstatus_t *ns,
+const routerstatus_t *networkstatus_vote_find_entry(networkstatus_t *ns,
+ const char *digest);
+routerstatus_t *networkstatus_v2_find_mutable_entry(networkstatus_v2_t *ns,
+ const char *digest);
+routerstatus_t *networkstatus_vote_find_mutable_entry(networkstatus_t *ns,
const char *digest);
int networkstatus_vote_find_entry_idx(networkstatus_t *ns,
const char *digest, int *found_out);
const smartlist_t *networkstatus_get_v2_list(void);
download_status_t *router_get_dl_status_by_descriptor_digest(const char *d);
-routerstatus_t *router_get_consensus_status_by_id(const char *digest);
-routerstatus_t *router_get_consensus_status_by_descriptor_digest(
- const char *digest);
-routerstatus_t *router_get_consensus_status_by_nickname(const char *nickname,
- int warn_if_unnamed);
+const routerstatus_t *router_get_consensus_status_by_id(const char *digest);
+routerstatus_t *router_get_mutable_consensus_status_by_id(
+ const char *digest);
+const routerstatus_t *router_get_consensus_status_by_descriptor_digest(
+ networkstatus_t *consensus,
+ const char *digest);
+routerstatus_t *router_get_mutable_consensus_status_by_descriptor_digest(
+ networkstatus_t *consensus,
+ const char *digest);
+const routerstatus_t *router_get_consensus_status_by_nickname(
+ const char *nickname,
+ int warn_if_unnamed);
const char *networkstatus_get_router_digest_by_nickname(const char *nickname);
int networkstatus_nickname_is_unnamed(const char *nickname);
-void networkstatus_consensus_download_failed(int status_code);
+void networkstatus_consensus_download_failed(int status_code,
+ const char *flavname);
void update_consensus_networkstatus_fetch_time(time_t now);
-int should_delay_dir_fetches(or_options_t *options);
+int should_delay_dir_fetches(const or_options_t *options);
void update_networkstatus_downloads(time_t now);
void update_certificate_downloads(time_t now);
int consensus_is_waiting_for_certs(void);
networkstatus_v2_t *networkstatus_v2_get_by_digest(const char *digest);
networkstatus_t *networkstatus_get_latest_consensus(void);
+networkstatus_t *networkstatus_get_latest_consensus_by_flavor(
+ consensus_flavor_t f);
networkstatus_t *networkstatus_get_live_consensus(time_t now);
-networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now);
+networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now,
+ int flavor);
#define NSSET_FROM_CACHE 1
#define NSSET_WAS_WAITING_FOR_CERTS 2
#define NSSET_DONT_DOWNLOAD_CERTS 4
@@ -78,10 +93,11 @@ void routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
void signed_descs_update_status_from_consensus_networkstatus(
smartlist_t *descs);
-char *networkstatus_getinfo_helper_single(routerstatus_t *rs);
+char *networkstatus_getinfo_helper_single(const routerstatus_t *rs);
char *networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now);
void networkstatus_dump_bridge_status_to_file(time_t now);
-int32_t networkstatus_get_param(networkstatus_t *ns, const char *param_name,
+int32_t networkstatus_get_param(const networkstatus_t *ns,
+ const char *param_name,
int32_t default_val, int32_t min_val,
int32_t max_val);
int getinfo_helper_networkstatus(control_connection_t *conn,
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
new file mode 100644
index 000000000..b93b919c1
--- /dev/null
+++ b/src/or/nodelist.c
@@ -0,0 +1,758 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * 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 */
+
+#include "or.h"
+#include "config.h"
+#include "dirserv.h"
+#include "microdesc.h"
+#include "networkstatus.h"
+#include "nodelist.h"
+#include "policies.h"
+#include "router.h"
+#include "routerlist.h"
+
+#include <string.h>
+
+static void nodelist_drop_node(node_t *node, int remove_from_ht);
+static void node_free(node_t *node);
+
+/** A nodelist_t holds a node_t object for every router we're "willing to use
+ * for something". Specifically, it should hold a node_t for every node that
+ * is currently in the routerlist, or currently in the consensus we're using.
+ */
+typedef struct nodelist_t {
+ /* A list of all the nodes. */
+ smartlist_t *nodes;
+ /* Hash table to map from node ID digest to node. */
+ HT_HEAD(nodelist_map, node_t) nodes_by_id;
+
+} nodelist_t;
+
+static INLINE unsigned int
+node_id_hash(const node_t *node)
+{
+#if SIZEOF_INT == 4
+ const uint32_t *p = (const uint32_t*)node->identity;
+ return p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4];
+#elif SIZEOF_INT == 8
+ const uint64_t *p = (const uint32_t*)node->identity;
+ const uint32_t *p32 = (const uint32_t*)node->identity;
+ return p[0] ^ p[1] ^ p32[4];
+#endif
+}
+
+static INLINE unsigned int
+node_id_eq(const node_t *node1, const node_t *node2)
+{
+ return tor_memeq(node1->identity, node2->identity, DIGEST_LEN);
+}
+
+HT_PROTOTYPE(nodelist_map, node_t, ht_ent, node_id_hash, node_id_eq);
+HT_GENERATE(nodelist_map, node_t, ht_ent, node_id_hash, node_id_eq,
+ 0.6, malloc, realloc, free);
+
+/** The global nodelist. */
+static nodelist_t *the_nodelist=NULL;
+
+/** Create an empty nodelist if we haven't done so already. */
+static void
+init_nodelist(void)
+{
+ if (PREDICT_UNLIKELY(the_nodelist == NULL)) {
+ the_nodelist = tor_malloc_zero(sizeof(nodelist_t));
+ HT_INIT(nodelist_map, &the_nodelist->nodes_by_id);
+ the_nodelist->nodes = smartlist_create();
+ }
+}
+
+/** As node_get_by_id, but returns a non-const pointer */
+node_t *
+node_get_mutable_by_id(const char *identity_digest)
+{
+ node_t search, *node;
+ if (PREDICT_UNLIKELY(the_nodelist == NULL))
+ return NULL;
+
+ memcpy(&search.identity, identity_digest, DIGEST_LEN);
+ node = HT_FIND(nodelist_map, &the_nodelist->nodes_by_id, &search);
+ return node;
+}
+
+/** Return the node_t whose identity is <b>identity_digest</b>, or NULL
+ * if no such node exists. */
+const node_t *
+node_get_by_id(const char *identity_digest)
+{
+ return node_get_mutable_by_id(identity_digest);
+}
+
+/** Internal: return the node_t whose identity_digest is
+ * <b>identity_digest</b>. If none exists, create a new one, add it to the
+ * nodelist, and return it.
+ *
+ * Requires that the nodelist be initialized.
+ */
+static node_t *
+node_get_or_create(const char *identity_digest)
+{
+ node_t *node;
+
+ if ((node = node_get_mutable_by_id(identity_digest)))
+ return node;
+
+ node = tor_malloc_zero(sizeof(node_t));
+ memcpy(node->identity, identity_digest, DIGEST_LEN);
+ HT_INSERT(nodelist_map, &the_nodelist->nodes_by_id, node);
+
+ smartlist_add(the_nodelist->nodes, node);
+ node->nodelist_idx = smartlist_len(the_nodelist->nodes) - 1;
+
+ node->country = -1;
+
+ return node;
+}
+
+/** Add <b>ri</b> to the nodelist. */
+node_t *
+nodelist_add_routerinfo(routerinfo_t *ri)
+{
+ node_t *node;
+ init_nodelist();
+ node = node_get_or_create(ri->cache_info.identity_digest);
+ node->ri = ri;
+
+ if (node->country == -1)
+ node_set_country(node);
+
+ if (authdir_mode(get_options())) {
+ const char *discard=NULL;
+ uint32_t status = dirserv_router_get_status(ri, &discard);
+ dirserv_set_node_flags_from_authoritative_status(node, status);
+ }
+
+ return node;
+}
+
+/** Set the appropriate node_t to use <b>md</b> as its microdescriptor.
+ *
+ * Called when a new microdesc has arrived and the usable consensus flavor
+ * is "microdesc".
+ **/
+node_t *
+nodelist_add_microdesc(microdesc_t *md)
+{
+ networkstatus_t *ns =
+ networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
+ const routerstatus_t *rs;
+ node_t *node;
+ if (ns == NULL)
+ return NULL;
+ init_nodelist();
+
+ /* Microdescriptors don't carry an identity digest, so we need to figure
+ * it out by looking up the routerstatus. */
+ rs = router_get_consensus_status_by_descriptor_digest(ns, md->digest);
+ if (rs == NULL)
+ return NULL;
+ node = node_get_mutable_by_id(rs->identity_digest);
+ if (node) {
+ if (node->md)
+ node->md->held_by_nodes--;
+ node->md = md;
+ md->held_by_nodes++;
+ }
+ return node;
+}
+
+/** Tell the nodelist that the current usable consensus to <b>ns</b>.
+ * This makes the nodelist change all of the routerstatus entries for
+ * the nodes, drop nodes that no longer have enough info to get used,
+ * and grab microdescriptors into nodes as appropriate.
+ */
+void
+nodelist_set_consensus(networkstatus_t *ns)
+{
+ const or_options_t *options = get_options();
+ int authdir = authdir_mode_v2(options) || authdir_mode_v3(options);
+
+ init_nodelist();
+ if (ns->flavor == FLAV_MICRODESC)
+ (void) get_microdesc_cache(); /* Make sure it exists first. */
+
+ SMARTLIST_FOREACH(the_nodelist->nodes, node_t *, node,
+ node->rs = NULL);
+
+ SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
+ node_t *node = node_get_or_create(rs->identity_digest);
+ node->rs = rs;
+ if (ns->flavor == FLAV_MICRODESC) {
+ if (node->md == NULL ||
+ tor_memneq(node->md->digest,rs->descriptor_digest,DIGEST256_LEN)) {
+ if (node->md)
+ node->md->held_by_nodes--;
+ node->md = microdesc_cache_lookup_by_digest256(NULL,
+ rs->descriptor_digest);
+ if (node->md)
+ node->md->held_by_nodes++;
+ }
+ }
+
+ node_set_country(node);
+
+ /* If we're not an authdir, believe others. */
+ if (!authdir) {
+ node->is_valid = rs->is_valid;
+ node->is_running = rs->is_flagged_running;
+ node->is_fast = rs->is_fast;
+ node->is_stable = rs->is_stable;
+ node->is_possible_guard = rs->is_possible_guard;
+ node->is_exit = rs->is_exit;
+ node->is_bad_directory = rs->is_bad_directory;
+ node->is_bad_exit = rs->is_bad_exit;
+ node->is_hs_dir = rs->is_hs_dir;
+ }
+
+ } SMARTLIST_FOREACH_END(rs);
+
+ nodelist_purge();
+
+ if (! authdir) {
+ SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+ /* We have no routerstatus for this router. Clear flags so we can skip
+ * it, maybe.*/
+ if (!node->rs) {
+ tor_assert(node->ri); /* if it had only an md, or nothing, purge
+ * would have removed it. */
+ if (node->ri->purpose == ROUTER_PURPOSE_GENERAL) {
+ /* Clear all flags. */
+ node->is_valid = node->is_running = node->is_hs_dir =
+ node->is_fast = node->is_stable =
+ node->is_possible_guard = node->is_exit =
+ node->is_bad_exit = node->is_bad_directory = 0;
+ }
+ }
+ } SMARTLIST_FOREACH_END(node);
+ }
+}
+
+/** Helper: return true iff a node has a usable amount of information*/
+static INLINE int
+node_is_usable(const node_t *node)
+{
+ return (node->rs) || (node->ri);
+}
+
+/** Tell the nodelist that <b>md</b> is no longer a microdescriptor for the
+ * node with <b>identity_digest</b>. */
+void
+nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md)
+{
+ node_t *node = node_get_mutable_by_id(identity_digest);
+ if (node && node->md == md) {
+ node->md = NULL;
+ md->held_by_nodes--;
+ }
+}
+
+/** Tell the nodelist that <b>ri</b> is no longer in the routerlist. */
+void
+nodelist_remove_routerinfo(routerinfo_t *ri)
+{
+ node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
+ if (node && node->ri == ri) {
+ node->ri = NULL;
+ if (! node_is_usable(node)) {
+ nodelist_drop_node(node, 1);
+ node_free(node);
+ }
+ }
+}
+
+/** Remove <b>node</b> from the nodelist. (Asserts that it was there to begin
+ * with.) */
+static void
+nodelist_drop_node(node_t *node, int remove_from_ht)
+{
+ node_t *tmp;
+ int idx;
+ if (remove_from_ht) {
+ tmp = HT_REMOVE(nodelist_map, &the_nodelist->nodes_by_id, node);
+ tor_assert(tmp == node);
+ }
+
+ idx = node->nodelist_idx;
+ tor_assert(idx >= 0);
+
+ tor_assert(node == smartlist_get(the_nodelist->nodes, idx));
+ smartlist_del(the_nodelist->nodes, idx);
+ if (idx < smartlist_len(the_nodelist->nodes)) {
+ tmp = smartlist_get(the_nodelist->nodes, idx);
+ tmp->nodelist_idx = idx;
+ }
+ node->nodelist_idx = -1;
+}
+
+/** Release storage held by <b>node</b> */
+static void
+node_free(node_t *node)
+{
+ if (!node)
+ return;
+ if (node->md)
+ node->md->held_by_nodes--;
+ tor_assert(node->nodelist_idx == -1);
+ tor_free(node);
+}
+
+/** Remove all entries from the nodelist that don't have enough info to be
+ * usable for anything. */
+void
+nodelist_purge(void)
+{
+ node_t **iter;
+ if (PREDICT_UNLIKELY(the_nodelist == NULL))
+ return;
+
+ /* Remove the non-usable nodes. */
+ for (iter = HT_START(nodelist_map, &the_nodelist->nodes_by_id); iter; ) {
+ node_t *node = *iter;
+
+ if (node->md && !node->rs) {
+ /* An md is only useful if there is an rs. */
+ node->md->held_by_nodes--;
+ node->md = NULL;
+ }
+
+ if (node_is_usable(node)) {
+ iter = HT_NEXT(nodelist_map, &the_nodelist->nodes_by_id, iter);
+ } else {
+ iter = HT_NEXT_RMV(nodelist_map, &the_nodelist->nodes_by_id, iter);
+ nodelist_drop_node(node, 0);
+ node_free(node);
+ }
+ }
+ nodelist_assert_ok();
+}
+
+/** Release all storage held by the nodelist. */
+void
+nodelist_free_all(void)
+{
+ if (PREDICT_UNLIKELY(the_nodelist == NULL))
+ return;
+
+ HT_CLEAR(nodelist_map, &the_nodelist->nodes_by_id);
+ SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+ node->nodelist_idx = -1;
+ node_free(node);
+ } SMARTLIST_FOREACH_END(node);
+
+ smartlist_free(the_nodelist->nodes);
+
+ tor_free(the_nodelist);
+}
+
+/** Check that the nodelist is internally consistent, and consistent with
+ * the directory info it's derived from.
+ */
+void
+nodelist_assert_ok(void)
+{
+ routerlist_t *rl = router_get_routerlist();
+ networkstatus_t *ns = networkstatus_get_latest_consensus();
+ digestmap_t *dm;
+
+ if (!the_nodelist)
+ return;
+
+ dm = digestmap_new();
+
+ /* every routerinfo in rl->routers should be in the nodelist. */
+ if (rl) {
+ SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, ri) {
+ const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
+ tor_assert(node && node->ri == ri);
+ tor_assert(fast_memeq(ri->cache_info.identity_digest,
+ node->identity, DIGEST_LEN));
+ tor_assert(! digestmap_get(dm, node->identity));
+ digestmap_set(dm, node->identity, (void*)node);
+ } SMARTLIST_FOREACH_END(ri);
+ }
+
+ /* every routerstatus in ns should be in the nodelist */
+ if (ns) {
+ SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
+ const node_t *node = node_get_by_id(rs->identity_digest);
+ tor_assert(node && node->rs == rs);
+ tor_assert(fast_memeq(rs->identity_digest, node->identity, DIGEST_LEN));
+ digestmap_set(dm, node->identity, (void*)node);
+ if (ns->flavor == FLAV_MICRODESC) {
+ /* If it's a microdesc consensus, every entry that has a
+ * microdescriptor should be in the nodelist.
+ */
+ microdesc_t *md =
+ microdesc_cache_lookup_by_digest256(NULL, rs->descriptor_digest);
+ tor_assert(md == node->md);
+ if (md)
+ tor_assert(md->held_by_nodes >= 1);
+ }
+ } SMARTLIST_FOREACH_END(rs);
+ }
+
+ /* The nodelist should have no other entries, and its entries should be
+ * well-formed. */
+ SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+ tor_assert(digestmap_get(dm, node->identity) != NULL);
+ tor_assert(node_sl_idx == node->nodelist_idx);
+ } SMARTLIST_FOREACH_END(node);
+
+ tor_assert((long)smartlist_len(the_nodelist->nodes) ==
+ (long)HT_SIZE(&the_nodelist->nodes_by_id));
+
+ digestmap_free(dm, NULL);
+}
+
+/** Return a list of a node_t * for every node we know about. The caller
+ * MUST NOT modify the list. (You can set and clear flags in the nodes if
+ * you must, but you must not add or remove nodes.) */
+smartlist_t *
+nodelist_get_list(void)
+{
+ init_nodelist();
+ return the_nodelist->nodes;
+}
+
+/** Given a hex-encoded nickname of the format DIGEST, $DIGEST, $DIGEST=name,
+ * or $DIGEST~name, return the node with the matching identity digest and
+ * nickname (if any). Return NULL if no such node exists, or if <b>hex_id</b>
+ * is not well-formed. */
+const node_t *
+node_get_by_hex_id(const char *hex_id)
+{
+ char digest_buf[DIGEST_LEN];
+ char nn_buf[MAX_NICKNAME_LEN+1];
+ char nn_char='\0';
+
+ if (hex_digest_nickname_decode(hex_id, digest_buf, &nn_char, nn_buf)==0) {
+ const node_t *node = node_get_by_id(digest_buf);
+ if (!node)
+ return NULL;
+ if (nn_char) {
+ const char *real_name = node_get_nickname(node);
+ if (!real_name || strcasecmp(real_name, nn_buf))
+ return NULL;
+ if (nn_char == '=') {
+ const char *named_id =
+ networkstatus_get_router_digest_by_nickname(nn_buf);
+ if (!named_id || tor_memneq(named_id, digest_buf, DIGEST_LEN))
+ return NULL;
+ }
+ }
+ return node;
+ }
+
+ return NULL;
+}
+
+/** Given a nickname (possibly verbose, possibly a hexadecimal digest), return
+ * the corresponding node_t, or NULL if none exists. Warn the user if
+ * <b>warn_if_unnamed</b> is set, and they have specified a router by
+ * nickname, but the Named flag isn't set for that router. */
+const node_t *
+node_get_by_nickname(const char *nickname, int warn_if_unnamed)
+{
+ const node_t *node;
+ if (!the_nodelist)
+ return NULL;
+
+ /* Handle these cases: DIGEST, $DIGEST, $DIGEST=name, $DIGEST~name. */
+ if ((node = node_get_by_hex_id(nickname)) != NULL)
+ return node;
+
+ if (!strcasecmp(nickname, UNNAMED_ROUTER_NICKNAME))
+ return NULL;
+
+ /* Okay, so if we get here, the nickname is just a nickname. Is there
+ * a binding for it in the consensus? */
+ {
+ const char *named_id =
+ networkstatus_get_router_digest_by_nickname(nickname);
+ if (named_id)
+ return node_get_by_id(named_id);
+ }
+
+ /* Is it marked as owned-by-someone-else? */
+ if (networkstatus_nickname_is_unnamed(nickname)) {
+ log_info(LD_GENERAL, "The name %s is listed as Unnamed: there is some "
+ "router that holds it, but not one listed in the current "
+ "consensus.", escaped(nickname));
+ return NULL;
+ }
+
+ /* Okay, so the name is not canonical for anybody. */
+ {
+ smartlist_t *matches = smartlist_create();
+ const node_t *choice = NULL;
+
+ SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) {
+ if (!strcasecmp(node_get_nickname(node), nickname))
+ smartlist_add(matches, node);
+ } SMARTLIST_FOREACH_END(node);
+
+ if (smartlist_len(matches)>1 && warn_if_unnamed) {
+ int any_unwarned = 0;
+ SMARTLIST_FOREACH_BEGIN(matches, node_t *, node) {
+ if (!node->name_lookup_warned) {
+ node->name_lookup_warned = 1;
+ any_unwarned = 1;
+ }
+ } SMARTLIST_FOREACH_END(node);
+
+ if (any_unwarned) {
+ log_warn(LD_CONFIG, "There are multiple matches for the name %s, "
+ "but none is listed as Named in the directory consensus. "
+ "Choosing one arbitrarily.", nickname);
+ }
+ } else if (smartlist_len(matches)>1 && warn_if_unnamed) {
+ char fp[HEX_DIGEST_LEN+1];
+ node_t *node = smartlist_get(matches, 0);
+ if (node->name_lookup_warned) {
+ base16_encode(fp, sizeof(fp), node->identity, DIGEST_LEN);
+ log_warn(LD_CONFIG,
+ "You specified a server \"%s\" by name, but the directory "
+ "authorities do not have any key registered for this "
+ "nickname -- so it could be used by any server, not just "
+ "the one you meant. "
+ "To make sure you get the same server in the future, refer "
+ "to it by key, as \"$%s\".", nickname, fp);
+ node->name_lookup_warned = 1;
+ }
+ }
+
+ if (smartlist_len(matches))
+ choice = smartlist_get(matches, 0);
+
+ smartlist_free(matches);
+ return choice;
+ }
+}
+
+/** Return the nickname of <b>node</b>, or NULL if we can't find one. */
+const char *
+node_get_nickname(const node_t *node)
+{
+ tor_assert(node);
+ if (node->rs)
+ return node->rs->nickname;
+ else if (node->ri)
+ return node->ri->nickname;
+ else
+ return NULL;
+}
+
+/** Return true iff the nickname of <b>node</b> is canonical, based on the
+ * latest consensus. */
+int
+node_is_named(const node_t *node)
+{
+ const char *named_id;
+ const char *nickname = node_get_nickname(node);
+ if (!nickname)
+ return 0;
+ named_id = networkstatus_get_router_digest_by_nickname(nickname);
+ if (!named_id)
+ return 0;
+ return tor_memeq(named_id, node->identity, DIGEST_LEN);
+}
+
+/** Return true iff <b>node</b> appears to be a directory authority or
+ * directory cache */
+int
+node_is_dir(const node_t *node)
+{
+ if (node->rs)
+ return node->rs->dir_port != 0;
+ else if (node->ri)
+ return node->ri->dir_port != 0;
+ else
+ return 0;
+}
+
+/** Return true iff <b>node</b> has either kind of usable descriptor -- that
+ * is, a routerdecriptor or a microdescriptor. */
+int
+node_has_descriptor(const node_t *node)
+{
+ return (node->ri ||
+ (node->rs && node->md));
+}
+
+/** Return the router_purpose of <b>node</b>. */
+int
+node_get_purpose(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->purpose;
+ else
+ return ROUTER_PURPOSE_GENERAL;
+}
+
+/** Compute the verbose ("extended") nickname of <b>node</b> and store it
+ * into the MAX_VERBOSE_NICKNAME_LEN+1 character buffer at
+ * <b>verbose_nickname_out</b> */
+void
+node_get_verbose_nickname(const node_t *node,
+ char *verbose_name_out)
+{
+ const char *nickname = node_get_nickname(node);
+ int is_named = node_is_named(node);
+ verbose_name_out[0] = '$';
+ base16_encode(verbose_name_out+1, HEX_DIGEST_LEN+1, node->identity,
+ DIGEST_LEN);
+ if (!nickname)
+ return;
+ verbose_name_out[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
+ strlcpy(verbose_name_out+1+HEX_DIGEST_LEN+1, nickname, MAX_NICKNAME_LEN+1);
+}
+
+/** Return true iff it seems that <b>node</b> allows circuits to exit
+ * through it directlry from the client. */
+int
+node_allows_single_hop_exits(const node_t *node)
+{
+ if (node && node->ri)
+ return node->ri->allow_single_hop_exits;
+ else
+ return 0;
+}
+
+/** Return true iff it seems that <b>node</b> has an exit policy that doesn't
+ * actually permit anything to exit, or we don't know its exit policy */
+int
+node_exit_policy_rejects_all(const node_t *node)
+{
+ if (node->rejects_all)
+ return 1;
+
+ if (node->ri)
+ return node->ri->policy_is_reject_star;
+ else if (node->md)
+ return node->md->exit_policy == NULL ||
+ short_policy_is_reject_star(node->md->exit_policy);
+ else
+ return 1;
+}
+
+/** Copy the address for <b>node</b> into *<b>addr_out</b>. */
+int
+node_get_addr(const node_t *node, tor_addr_t *addr_out)
+{
+ if (node->ri) {
+ tor_addr_from_ipv4h(addr_out, node->ri->addr);
+ return 0;
+ } else if (node->rs) {
+ tor_addr_from_ipv4h(addr_out, node->rs->addr);
+ return 0;
+ }
+ return -1;
+}
+
+/** Return the host-order IPv4 address for <b>node</b>, or 0 if it doesn't
+ * seem to have one. */
+uint32_t
+node_get_addr_ipv4h(const node_t *node)
+{
+ if (node->ri) {
+ return node->ri->addr;
+ } else if (node->rs) {
+ return node->rs->addr;
+ }
+ return 0;
+}
+
+/** Copy a string representation of the IP address for <b>node</b> into the
+ * <b>len</b>-byte buffer at <b>buf</b>.
+ */
+void
+node_get_address_string(const node_t *node, char *buf, size_t len)
+{
+ if (node->ri) {
+ strlcpy(buf, node->ri->address, len);
+ } else if (node->rs) {
+ tor_addr_t addr;
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+ tor_addr_to_str(buf, &addr, len, 0);
+ } else {
+ buf[0] = '\0';
+ }
+}
+
+/** Return <b>node</b>'s declared uptime, or -1 if it doesn't seem to have
+ * one. */
+long
+node_get_declared_uptime(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->uptime;
+ else
+ return -1;
+}
+
+/** Return <b>node</b>'s declared or_port */
+uint16_t
+node_get_orport(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->or_port;
+ else if (node->rs)
+ return node->rs->or_port;
+ else
+ return 0;
+}
+
+/** Return <b>node</b>'s platform string, or NULL if we don't know it. */
+const char *
+node_get_platform(const node_t *node)
+{
+ /* If we wanted, we could record the version in the routerstatus_t, since
+ * the consensus lists it. We don't, though, so this function just won't
+ * work with microdescriptors. */
+ if (node->ri)
+ return node->ri->platform;
+ else
+ return NULL;
+}
+
+/** Return <b>node</b>'s time of publication, or 0 if we don't have one. */
+time_t
+node_get_published_on(const node_t *node)
+{
+ if (node->ri)
+ return node->ri->cache_info.published_on;
+ else
+ return 0;
+}
+
+/** Return true iff <b>node</b> is one representing this router. */
+int
+node_is_me(const node_t *node)
+{
+ return router_digest_is_me(node->identity);
+}
+
+/** Return <b>node</b> declared family (as a list of names), or NULL if
+ * the node didn't declare a family. */
+const smartlist_t *
+node_get_declared_family(const node_t *node)
+{
+ if (node->ri && node->ri->declared_family)
+ return node->ri->declared_family;
+ else if (node->md && node->md->family)
+ return node->md->family;
+ else
+ return NULL;
+}
+
diff --git a/src/or/nodelist.h b/src/or/nodelist.h
new file mode 100644
index 000000000..bd2e63953
--- /dev/null
+++ b/src/or/nodelist.h
@@ -0,0 +1,60 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * 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 */
+
+/**
+ * \file microdesc.h
+ * \brief Header file for microdesc.c.
+ **/
+
+#ifndef _TOR_NODELIST_H
+#define _TOR_NODELIST_H
+
+node_t *node_get_mutable_by_id(const char *identity_digest);
+const node_t *node_get_by_id(const char *identity_digest);
+const node_t *node_get_by_hex_id(const char *identity_digest);
+node_t *nodelist_add_routerinfo(routerinfo_t *ri);
+node_t *nodelist_add_microdesc(microdesc_t *md);
+void nodelist_set_consensus(networkstatus_t *ns);
+
+void nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md);
+void nodelist_remove_routerinfo(routerinfo_t *ri);
+void nodelist_purge(void);
+
+void nodelist_free_all(void);
+void nodelist_assert_ok(void);
+
+const node_t *node_get_by_nickname(const char *nickname, int warn_if_unnamed);
+void node_get_verbose_nickname(const node_t *node,
+ char *verbose_name_out);
+int node_is_named(const node_t *node);
+int node_is_dir(const node_t *node);
+int node_has_descriptor(const node_t *node);
+int node_get_purpose(const node_t *node);
+#define node_is_bridge(node) \
+ (node_get_purpose((node)) == ROUTER_PURPOSE_BRIDGE)
+int node_is_me(const node_t *node);
+int node_exit_policy_rejects_all(const node_t *node);
+int node_get_addr(const node_t *node, tor_addr_t *addr_out);
+uint32_t node_get_addr_ipv4h(const node_t *node);
+int node_allows_single_hop_exits(const node_t *node);
+uint16_t node_get_orport(const node_t *node);
+const char *node_get_nickname(const node_t *node);
+const char *node_get_platform(const node_t *node);
+void node_get_address_string(const node_t *node, char *cp, size_t len);
+long node_get_declared_uptime(const node_t *node);
+time_t node_get_published_on(const node_t *node);
+const smartlist_t *node_get_declared_family(const node_t *node);
+
+smartlist_t *nodelist_get_list(void);
+
+/* XXXX These need to move out of routerlist.c */
+void nodelist_refresh_countries(void);
+void node_set_country(node_t *node);
+void nodelist_add_node_and_family(smartlist_t *nodes, const node_t *node);
+int nodes_in_same_family(const node_t *node1, const node_t *node2);
+
+#endif
+
diff --git a/src/or/ntmain.c b/src/or/ntmain.c
index b2fee648c..4eb487e97 100644
--- a/src/or/ntmain.c
+++ b/src/or/ntmain.c
@@ -193,7 +193,6 @@ nt_service_loadlibrary(void)
*/
int
nt_service_is_stopping(void)
-/* XXXX this function would probably _love_ to be inline, in 0.2.0. */
{
/* If we haven't loaded the function pointers, we can't possibly be an NT
* service trying to shut down. */
diff --git a/src/or/or.h b/src/or/or.h
index 1909887bb..d6eaeb6f1 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -23,8 +23,12 @@
#endif
#ifdef MS_WINDOWS
+#ifndef WIN32_WINNT
#define WIN32_WINNT 0x400
+#endif
+#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x400
+#endif
#define WIN32_LEAN_AND_MEAN
#endif
@@ -83,6 +87,13 @@
#define snprintf _snprintf
#endif
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent.h>
+#include <event2/buffer.h>
+#include <event2/util.h>
+#endif
+
+#include "crypto.h"
#include "tortls.h"
#include "../common/torlog.h"
#include "container.h"
@@ -163,7 +174,9 @@
/** How often do we rotate onion keys? */
#define MIN_ONION_KEY_LIFETIME (7*24*60*60)
/** How often do we rotate TLS contexts? */
-#define MAX_SSL_KEY_LIFETIME (2*60*60)
+#define MAX_SSL_KEY_LIFETIME_INTERNAL (2*60*60)
+/** What expiry time shall we place on our SSL certs? */
+#define MAX_SSL_KEY_LIFETIME_ADVERTISED (365*24*60*60)
/** How old do we allow a router to get before removing it
* from the router list? In seconds. */
@@ -223,15 +236,30 @@ typedef enum {
#define PROXY_CONNECT 1
#define PROXY_SOCKS4 2
#define PROXY_SOCKS5 3
+/* !!!! If there is ever a PROXY_* type over 2, we must grow the proxy_type
+ * field in or_connection_t */
+/* pluggable transports proxy type */
+#define PROXY_PLUGGABLE 4
/* Proxy client handshake states */
-#define PROXY_HTTPS_WANT_CONNECT_OK 1
-#define PROXY_SOCKS4_WANT_CONNECT_OK 2
-#define PROXY_SOCKS5_WANT_AUTH_METHOD_NONE 3
-#define PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929 4
-#define PROXY_SOCKS5_WANT_AUTH_RFC1929_OK 5
-#define PROXY_SOCKS5_WANT_CONNECT_OK 6
-#define PROXY_CONNECTED 7
+/* We use a proxy but we haven't even connected to it yet. */
+#define PROXY_INFANT 1
+/* We use an HTTP proxy and we've sent the CONNECT command. */
+#define PROXY_HTTPS_WANT_CONNECT_OK 2
+/* We use a SOCKS4 proxy and we've sent the CONNECT command. */
+#define PROXY_SOCKS4_WANT_CONNECT_OK 3
+/* We use a SOCKS5 proxy and we try to negotiate without
+ any authentication . */
+#define PROXY_SOCKS5_WANT_AUTH_METHOD_NONE 4
+/* We use a SOCKS5 proxy and we try to negotiate with
+ Username/Password authentication . */
+#define PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929 5
+/* We use a SOCKS5 proxy and we just sent our credentials. */
+#define PROXY_SOCKS5_WANT_AUTH_RFC1929_OK 6
+/* We use a SOCKS5 proxy and we just sent our CONNECT command. */
+#define PROXY_SOCKS5_WANT_CONNECT_OK 7
+/* We use a proxy and we CONNECTed successfully!. */
+#define PROXY_CONNECTED 8
/** True iff <b>x</b> is an edge connection. */
#define CONN_IS_EDGE(x) \
@@ -384,7 +412,9 @@ typedef enum {
/** A connection to a hidden service directory server: download a v2 rendezvous
* descriptor. */
#define DIR_PURPOSE_FETCH_RENDDESC_V2 18
-#define _DIR_PURPOSE_MAX 18
+/** A connection to a directory server: download a microdescriptor. */
+#define DIR_PURPOSE_FETCH_MICRODESC 19
+#define _DIR_PURPOSE_MAX 19
/** True iff <b>p</b> is a purpose corresponding to uploading data to a
* directory server. */
@@ -805,6 +835,9 @@ typedef enum {
* Tor 0.1.2.x is obsolete, we can remove this. */
#define DEFAULT_CLIENT_NICKNAME "client"
+/** Name chosen by routers that don't configure nicknames */
+#define UNNAMED_ROUTER_NICKNAME "Unnamed"
+
/** Number of bytes in a SOCKS4 header. */
#define SOCKS4_NETWORK_LEN 8
@@ -855,7 +888,7 @@ typedef struct var_cell_t {
/** Number of bytes actually stored in <b>payload</b> */
uint16_t payload_len;
/** Payload of this cell */
- uint8_t payload[1];
+ uint8_t payload[FLEXIBLE_ARRAY_MEMBER];
} var_cell_t;
/** A cell as packed for writing to the network. */
@@ -899,14 +932,21 @@ typedef struct {
typedef struct buf_t buf_t;
typedef struct socks_request_t socks_request_t;
+#ifdef USE_BUFFEREVENTS
+#define generic_buffer_t struct evbuffer
+#else
+#define generic_buffer_t buf_t
+#endif
/* Values for connection_t.magic: used to make sure that downcasts (casts from
* connection_t to foo_connection_t) are safe. */
#define BASE_CONNECTION_MAGIC 0x7C3C304Eu
#define OR_CONNECTION_MAGIC 0x7D31FF03u
#define EDGE_CONNECTION_MAGIC 0xF0374013u
+#define ENTRY_CONNECTION_MAGIC 0xbb4a5703
#define DIR_CONNECTION_MAGIC 0x9988ffeeu
#define CONTROL_CONNECTION_MAGIC 0x8abc765du
+#define LISTENER_CONNECTION_MAGIC 0x1a1ac741u
/** Description of a connection to another host or process, and associated
* data.
@@ -972,6 +1012,7 @@ typedef struct connection_t {
/** Our socket; -1 if this connection is closed, or has no socket. */
tor_socket_t s;
int conn_array_index; /**< Index into the global connection array. */
+
struct event *read_event; /**< Libevent event structure. */
struct event *write_event; /**< Libevent event structure. */
buf_t *inbuf; /**< Buffer holding data read over this connection. */
@@ -982,6 +1023,11 @@ typedef struct connection_t {
* read? */
time_t timestamp_lastwritten; /**< When was the last time libevent said we
* could write? */
+
+#ifdef USE_BUFFEREVENTS
+ struct bufferevent *bufev; /**< A Libevent buffered IO structure. */
+#endif
+
time_t timestamp_created; /**< When was this connection_t created? */
/* XXXX_IP6 make this IPv6-capable */
@@ -1006,15 +1052,31 @@ typedef struct connection_t {
/** Unique identifier for this connection on this Tor instance. */
uint64_t global_identifier;
- /* XXXX023 move this field, and all the listener-only fields (just
- socket_family, I think), into a new listener_connection_t subtype. */
+ /** Unique ID for measuring tunneled network status requests. */
+ uint64_t dirreq_id;
+} connection_t;
+
+typedef struct listener_connection_t {
+ connection_t _base;
+
/** If the connection is a CONN_TYPE_AP_DNS_LISTENER, this field points
* to the evdns_server_port it uses to listen to and answer connections. */
struct evdns_server_port *dns_server_port;
- /** Unique ID for measuring tunneled network status requests. */
- uint64_t dirreq_id;
-} connection_t;
+ /** @name Isolation parameters
+ *
+ * For an AP listener, these fields describe how to isolate streams that
+ * arrive on the listener.
+ *
+ * @{
+ */
+ /** The session group for this listener. */
+ int session_group;
+ /** One or more ISO_ flags to describe how to isolate streams. */
+ uint8_t isolation_flags;
+ /**@}*/
+
+} listener_connection_t;
/** Stores flags and information related to the portion of a v2 Tor OR
* connection handshake that happens after the TLS handshake is finished.
@@ -1066,6 +1128,7 @@ typedef struct or_connection_t {
* router itself has a problem.
*/
unsigned int is_bad_for_new_circs:1;
+ unsigned int proxy_type:2; /**< One of PROXY_NONE...PROXY_SOCKS5 */
uint8_t link_proto; /**< What protocol version are we using? 0 for
* "none negotiated yet." */
circid_t next_circ_id; /**< Which circ_id do we try to use next on
@@ -1081,10 +1144,16 @@ typedef struct or_connection_t {
/* bandwidth* and *_bucket only used by ORs in OPEN state: */
int bandwidthrate; /**< Bytes/s added to the bucket. (OPEN ORs only.) */
int bandwidthburst; /**< Max bucket size for this conn. (OPEN ORs only.) */
+#ifndef USE_BUFFEREVENTS
int read_bucket; /**< When this hits 0, stop receiving. Every second we
* add 'bandwidthrate' to this, capping it at
* bandwidthburst. (OPEN ORs only) */
int write_bucket; /**< When this hits 0, stop writing. Like read_bucket. */
+#else
+ /** DOCDOC */
+ /* XXXX we could share this among all connections. */
+ struct ev_token_bucket_cfg *bucket_cfg;
+#endif
int n_circuits; /**< How many circuits use this connection as p_conn or
* n_conn ? */
@@ -1107,27 +1176,27 @@ typedef struct or_connection_t {
* identity digest as this one. */
} or_connection_t;
-/** Subtype of connection_t for an "edge connection" -- that is, a socks (ap)
+/** Subtype of connection_t for an "edge connection" -- that is, an entry (ap)
* connection, or an exit. */
typedef struct edge_connection_t {
connection_t _base;
struct edge_connection_t *next_stream; /**< Points to the next stream at this
* edge, if any */
- struct crypt_path_t *cpath_layer; /**< A pointer to which node in the circ
- * this conn exits at. */
int package_window; /**< How many more relay cells can I send into the
* circuit? */
int deliver_window; /**< How many more relay cells can end at me? */
- /** Nickname of planned exit node -- used with .exit support. */
- char *chosen_exit_name;
-
- socks_request_t *socks_request; /**< SOCKS structure describing request (AP
- * only.) */
struct circuit_t *on_circuit; /**< The circuit (if any) that this edge
* connection is using. */
+ /** A pointer to which node in the circ this conn exits at. Set for AP
+ * connections and for hidden service exit connections. */
+ struct crypt_path_t *cpath_layer;
+ /** What rendezvous service are we querying for (if an AP) or providing (if
+ * an exit)? */
+ rend_data_t *rend_data;
+
uint32_t address_ttl; /**< TTL for address-to-addr mapping on exit
* connection. Exit connections only. */
@@ -1143,14 +1212,62 @@ typedef struct edge_connection_t {
/** Bytes written since last call to control_event_stream_bandwidth_used() */
uint32_t n_written;
- /** What rendezvous service are we querying for? (AP only) */
- rend_data_t *rend_data;
+ /** True iff this connection is for a DNS request only. */
+ unsigned int is_dns_request:1;
+
+ unsigned int edge_has_sent_end:1; /**< For debugging; only used on edge
+ * connections. Set once we've set the stream end,
+ * and check in connection_about_to_close_connection().
+ */
+ /** True iff we've blocked reading until the circuit has fewer queued
+ * cells. */
+ unsigned int edge_blocked_on_circ:1;
+
+} edge_connection_t;
+
+/** Subtype of edge_connection_t for an "entry connection" -- that is, a SOCKS
+ * connection, a DNS request, a TransPort connection or a NATD connection */
+typedef struct entry_connection_t {
+ edge_connection_t _edge;
+
+ /** Nickname of planned exit node -- used with .exit support. */
+ char *chosen_exit_name;
+
+ socks_request_t *socks_request; /**< SOCKS structure describing request (AP
+ * only.) */
+
+ /* === Isolation related, AP only. === */
+ /** AP only: based on which factors do we isolate this stream? */
+ uint8_t isolation_flags;
+ /** AP only: what session group is this stream in? */
+ int session_group;
+ /** AP only: The newnym epoch in which we created this connection. */
+ unsigned nym_epoch;
+ /** AP only: The original requested address before we rewrote it. */
+ char *original_dest_address;
+ /* Other fields to isolate on already exist. The ClientAddr is addr. The
+ ClientProtocol is a combination of type and socks_request->
+ socks_version. SocksAuth is socks_request->username/password.
+ DestAddr is in socks_request->address. */
/** Number of times we've reassigned this application connection to
* a new circuit. We keep track because the timeout is longer if we've
* already retried several times. */
uint8_t num_socks_retries;
+ /** For AP connections only: buffer for data that we have sent
+ * optimistically, which we might need to re-send if we have to
+ * retry this connection. */
+ generic_buffer_t *pending_optimistic_data;
+ /* For AP connections only: buffer for data that we previously sent
+ * optimistically which we are currently re-sending as we retry this
+ * connection. */
+ generic_buffer_t *sending_optimistic_data;
+
+ /** If this is a DNSPort connection, this field holds the pending DNS
+ * request that we're going to try to answer. */
+ struct evdns_server_request *dns_server_request;
+
#define NUM_CIRCUITS_LAUNCHED_THRESHOLD 10
/** Number of times we've launched a circuit to handle this stream. If
* it gets too high, that could indicate an inconsistency between our
@@ -1158,9 +1275,6 @@ typedef struct edge_connection_t {
* stream to one of the available circuits" logic. */
unsigned int num_circuits_launched:4;
- /** True iff this connection is for a DNS request only. */
- unsigned int is_dns_request:1;
-
/** True iff this stream must attach to a one-hop circuit (e.g. for
* begin_dir). */
unsigned int want_onehop:1;
@@ -1168,13 +1282,6 @@ typedef struct edge_connection_t {
* itself rather than BEGIN (either via onehop or via a whole circuit). */
unsigned int use_begindir:1;
- unsigned int edge_has_sent_end:1; /**< For debugging; only used on edge
- * connections. Set once we've set the stream end,
- * and check in connection_about_to_close_connection().
- */
- /** True iff we've blocked reading until the circuit has fewer queued
- * cells. */
- unsigned int edge_blocked_on_circ:1;
/** For AP connections only. If 1, and we fail to reach the chosen exit,
* stop requiring it. */
unsigned int chosen_exit_optional:1;
@@ -1188,19 +1295,26 @@ typedef struct edge_connection_t {
* NATd connection */
unsigned int is_transparent_ap:1;
- /** If this is a DNSPort connection, this field holds the pending DNS
- * request that we're going to try to answer. */
- struct evdns_server_request *dns_server_request;
+ /** For AP connections only: Set if this connection's target exit node
+ * allows optimistic data (that is, data sent on this stream before
+ * the exit has sent a CONNECTED cell) and we have chosen to use it.
+ */
+ unsigned int may_use_optimistic_data : 1;
-} edge_connection_t;
+} entry_connection_t;
/** Subtype of connection_t for an "directory connection" -- that is, an HTTP
* connection to retrieve or serve directory material. */
typedef struct dir_connection_t {
connection_t _base;
- char *requested_resource; /**< Which 'resource' did we ask the directory
- * for? */
+ /** Which 'resource' did we ask the directory for? This is typically the part
+ * of the URL string that defines, relative to the directory conn purpose,
+ * what thing we want. For example, in router descriptor downloads by
+ * descriptor digest, it contains "d/", then one ore more +-separated
+ * fingerprints.
+ **/
+ char *requested_resource;
unsigned int dirconn_direct:1; /**< Is this dirconn direct, or via Tor? */
/* Used only for server sides of some dir connections, to implement
@@ -1260,6 +1374,11 @@ typedef struct control_connection_t {
/** Helper macro: Given a pointer to to._base, of type from*, return &to. */
#define DOWNCAST(to, ptr) ((to*)SUBTYPE_P(ptr, to, _base))
+/** Cast a entry_connection_t subtype pointer to a edge_connection_t **/
+#define ENTRY_TO_EDGE_CONN(c) (&(((c))->_edge))
+/** Cast a entry_connection_t subtype pointer to a connection_t **/
+#define ENTRY_TO_CONN(c) (TO_CONN(ENTRY_TO_EDGE_CONN(c)))
+
/** Convert a connection_t* to an or_connection_t*; assert if the cast is
* invalid. */
static or_connection_t *TO_OR_CONN(connection_t *);
@@ -1269,9 +1388,18 @@ static dir_connection_t *TO_DIR_CONN(connection_t *);
/** Convert a connection_t* to an edge_connection_t*; assert if the cast is
* invalid. */
static edge_connection_t *TO_EDGE_CONN(connection_t *);
+/** Convert a connection_t* to an entry_connection_t*; assert if the cast is
+ * invalid. */
+static entry_connection_t *TO_ENTRY_CONN(connection_t *);
+/** Convert a edge_connection_t* to an entry_connection_t*; assert if the cast
+ * is invalid. */
+static entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *);
/** Convert a connection_t* to an control_connection_t*; assert if the cast is
* invalid. */
static control_connection_t *TO_CONTROL_CONN(connection_t *);
+/** Convert a connection_t* to an listener_connection_t*; assert if the cast is
+ * invalid. */
+static listener_connection_t *TO_LISTENER_CONN(connection_t *);
static INLINE or_connection_t *TO_OR_CONN(connection_t *c)
{
@@ -1285,14 +1413,75 @@ static INLINE dir_connection_t *TO_DIR_CONN(connection_t *c)
}
static INLINE edge_connection_t *TO_EDGE_CONN(connection_t *c)
{
- tor_assert(c->magic == EDGE_CONNECTION_MAGIC);
+ tor_assert(c->magic == EDGE_CONNECTION_MAGIC ||
+ c->magic == ENTRY_CONNECTION_MAGIC);
return DOWNCAST(edge_connection_t, c);
}
+static INLINE entry_connection_t *TO_ENTRY_CONN(connection_t *c)
+{
+ tor_assert(c->magic == ENTRY_CONNECTION_MAGIC);
+ return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, _edge._base);
+}
+static INLINE entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *c)
+{
+ tor_assert(c->_base.magic == ENTRY_CONNECTION_MAGIC);
+ return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, _edge);
+}
static INLINE control_connection_t *TO_CONTROL_CONN(connection_t *c)
{
tor_assert(c->magic == CONTROL_CONNECTION_MAGIC);
return DOWNCAST(control_connection_t, c);
}
+static INLINE listener_connection_t *TO_LISTENER_CONN(connection_t *c)
+{
+ tor_assert(c->magic == LISTENER_CONNECTION_MAGIC);
+ return DOWNCAST(listener_connection_t, c);
+}
+
+/* Conditional macros to help write code that works whether bufferevents are
+ disabled or not.
+
+ We can't just write:
+ if (conn->bufev) {
+ do bufferevent stuff;
+ } else {
+ do other stuff;
+ }
+ because the bufferevent stuff won't even compile unless we have a fairly
+ new version of Libevent. Instead, we say:
+ IF_HAS_BUFFEREVENT(conn, { do_bufferevent_stuff } );
+ or:
+ IF_HAS_BUFFEREVENT(conn, {
+ do bufferevent stuff;
+ }) ELSE_IF_NO_BUFFEREVENT {
+ do non-bufferevent stuff;
+ }
+ If we're compiling with bufferevent support, then the macros expand more or
+ less to:
+ if (conn->bufev) {
+ do_bufferevent_stuff;
+ } else {
+ do non-bufferevent stuff;
+ }
+ and if we aren't using bufferevents, they expand more or less to:
+ { do non-bufferevent stuff; }
+*/
+#ifdef USE_BUFFEREVENTS
+#define HAS_BUFFEREVENT(c) (((c)->bufev) != NULL)
+#define IF_HAS_BUFFEREVENT(c, stmt) \
+ if ((c)->bufev) do { \
+ stmt ; \
+ } while (0)
+#define ELSE_IF_NO_BUFFEREVENT ; else
+#define IF_HAS_NO_BUFFEREVENT(c) \
+ if (NULL == (c)->bufev)
+#else
+#define HAS_BUFFEREVENT(c) (0)
+#define IF_HAS_BUFFEREVENT(c, stmt) (void)0
+#define ELSE_IF_NO_BUFFEREVENT ;
+#define IF_HAS_NO_BUFFEREVENT(c) \
+ if (1)
+#endif
/** What action type does an address policy indicate: accept or reject? */
typedef enum {
@@ -1457,59 +1646,49 @@ typedef struct {
char *contact_info; /**< Declared contact info for this router. */
unsigned int is_hibernating:1; /**< Whether the router claims to be
* hibernating */
- unsigned int has_old_dnsworkers:1; /**< Whether the router is using
- * dnsworker code. */
- unsigned int caches_extra_info:1; /**< Whether the router caches and serves
- * extrainfo documents. */
- unsigned int allow_single_hop_exits:1; /**< Whether the router allows
- * single hop exits. */
-
- /* local info */
- unsigned int is_running:1; /**< As far as we know, is this OR currently
- * running? */
- unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR?
- * (For Authdir: Have we validated this OR?)
- */
- unsigned int is_named:1; /**< Do we believe the nickname that this OR gives
- * us? */
- unsigned int is_fast:1; /** Do we think this is a fast OR? */
- unsigned int is_stable:1; /** Do we think this is a stable OR? */
- unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */
- unsigned int is_exit:1; /**< Do we think this is an OK exit? */
- unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked,
- * or otherwise nasty? */
- unsigned int is_bad_directory:1; /**< Do we think this directory is junky,
- * underpowered, or otherwise useless? */
+ unsigned int caches_extra_info:1; /**< Whether the router says it caches and
+ * serves extrainfo documents. */
+ unsigned int allow_single_hop_exits:1; /**< Whether the router says
+ * it allows single hop exits. */
+
unsigned int wants_to_be_hs_dir:1; /**< True iff this router claims to be
* a hidden service directory. */
- unsigned int is_hs_dir:1; /**< True iff this router is a hidden service
- * directory according to the authorities. */
unsigned int policy_is_reject_star:1; /**< True iff the exit policy for this
* router rejects everything. */
/** True if, after we have added this router, we should re-launch
* tests for it. */
unsigned int needs_retest_if_added:1;
-/** Tor can use this router for general positions in circuits. */
+/** Tor can use this router for general positions in circuits; we got it
+ * from a directory server as usual, or we're an authority and a server
+ * uploaded it. */
#define ROUTER_PURPOSE_GENERAL 0
-/** Tor should avoid using this router for circuit-building. */
+/** Tor should avoid using this router for circuit-building: we got it
+ * from a crontroller. If the controller wants to use it, it'll have to
+ * ask for it by identity. */
#define ROUTER_PURPOSE_CONTROLLER 1
-/** Tor should use this router only for bridge positions in circuits. */
+/** Tor should use this router only for bridge positions in circuits: we got
+ * it via a directory request from the bridge itself, or a bridge
+ * authority. x*/
#define ROUTER_PURPOSE_BRIDGE 2
/** Tor should not use this router; it was marked in cached-descriptors with
* a purpose we didn't recognize. */
#define ROUTER_PURPOSE_UNKNOWN 255
- uint8_t purpose; /** What positions in a circuit is this router good for? */
+ /* In what way did we find out about this router? One of ROUTER_PURPOSE_*.
+ * Routers of different purposes are kept segregated and used for different
+ * things; see notes on ROUTER_PURPOSE_* macros above.
+ */
+ uint8_t purpose;
/* The below items are used only by authdirservers for
* reachability testing. */
+
/** When was the last time we could reach this OR? */
time_t last_reachable;
/** When did we start testing reachability for this OR? */
time_t testing_since;
- /** According to the geoip db what country is this router in? */
- country_t country;
+
} routerinfo_t;
/** Information needed to keep and cache a signed extra-info document. */
@@ -1535,8 +1714,9 @@ typedef struct routerstatus_t {
* has. */
char identity_digest[DIGEST_LEN]; /**< Digest of the router's identity
* key. */
- char descriptor_digest[DIGEST_LEN]; /**< Digest of the router's most recent
- * descriptor. */
+ /** Digest of the router's most recent descriptor or microdescriptor.
+ * If it's a descriptor, we only use the first DIGEST_LEN bytes. */
+ char descriptor_digest[DIGEST256_LEN];
uint32_t addr; /**< IPv4 address for this router. */
uint16_t or_port; /**< OR port for this router. */
uint16_t dir_port; /**< Directory port for this router. */
@@ -1544,7 +1724,11 @@ typedef struct routerstatus_t {
unsigned int is_exit:1; /**< True iff this router is a good exit. */
unsigned int is_stable:1; /**< True iff this router stays up a long time. */
unsigned int is_fast:1; /**< True iff this router has good bandwidth. */
- unsigned int is_running:1; /**< True iff this router is up. */
+ /** True iff this router is called 'running' in the consensus. We give it
+ * this funny name so that we don't accidentally use this bit as a view of
+ * whether we think the router is *currently* running. If that's what you
+ * want to know, look at is_running in node_t. */
+ unsigned int is_flagged_running:1;
unsigned int is_named:1; /**< True iff "nickname" belongs to this router. */
unsigned int is_unnamed:1; /**< True iff "nickname" belongs to another
* router. */
@@ -1575,6 +1759,12 @@ typedef struct routerstatus_t {
/** True iff this router is a version that, if it caches directory info,
* we can get v3 downloads from. */
unsigned int version_supports_v3_dir:1;
+ /** True iff this router is a version that, if it caches directory info,
+ * we can get microdescriptors from. */
+ unsigned int version_supports_microdesc_cache:1;
+ /** True iff this router is a version that allows DATA cells to arrive on
+ * a stream before it has sent a CONNECTED cell. */
+ unsigned int version_supports_optimistic_data:1;
unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */
unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */
@@ -1596,15 +1786,31 @@ typedef struct routerstatus_t {
* from this authority.) Applies in v2 networkstatus document only.
*/
unsigned int need_to_mirror:1;
- unsigned int name_lookup_warned:1; /**< Have we warned the user for referring
- * to this (unnamed) router by nickname?
- */
time_t last_dir_503_at; /**< When did this router last tell us that it
* was too busy to serve directory info? */
download_status_t dl_status;
} routerstatus_t;
+/** A single entry in a parsed policy summary, describing a range of ports. */
+typedef struct short_policy_entry_t {
+ uint16_t min_port, max_port;
+} short_policy_entry_t;
+
+/** A short_poliy_t is the parsed version of a policy summary. */
+typedef struct short_policy_t {
+ /** True if the members of 'entries' are port ranges to accept; false if
+ * they are port ranges to reject */
+ unsigned int is_accept : 1;
+ /** The actual number of values in 'entries'. */
+ unsigned int n_entries : 31;
+ /** An array of 0 or more short_policy_entry_t values, each describing a
+ * range of ports that this policy accepts or rejects (depending on the
+ * value of is_accept).
+ */
+ short_policy_entry_t entries[FLEXIBLE_ARRAY_MEMBER];
+} short_policy_t;
+
/** A microdescriptor is the smallest amount of information needed to build a
* circuit through a router. They are generated by the directory authorities,
* using information from the uploaded routerinfo documents. They are not
@@ -1624,6 +1830,11 @@ typedef struct microdesc_t {
saved_location_t saved_location : 3;
/** If true, do not attempt to cache this microdescriptor on disk. */
unsigned int no_save : 1;
+ /** If true, this microdesc has an entry in the microdesc_map */
+ unsigned int held_in_map : 1;
+ /** Reference count: how many node_ts have a reference to this microdesc? */
+ unsigned int held_by_nodes;
+
/** If saved_location == SAVED_IN_CACHE, this field holds the offset of the
* microdescriptor in the cache. */
off_t off;
@@ -1646,15 +1857,83 @@ typedef struct microdesc_t {
crypto_pk_env_t *onion_pkey;
/** As routerinfo_t.family */
smartlist_t *family;
- /** Encoded exit policy summary */
- char *exitsummary; /**< exit policy summary -
- * XXX this probably should not stay a string. */
+ /** Exit policy summary */
+ short_policy_t *exit_policy;
} microdesc_t;
+/** A node_t represents a Tor router.
+ *
+ * Specifically, a node_t is a Tor router as we are using it: a router that
+ * we are considering for circuits, connections, and so on. A node_t is a
+ * thin wrapper around the routerstatus, routerinfo, and microdesc for a
+ * single wrapper, and provides a consistent interface for all of them.
+ *
+ * Also, a node_t has mutable state. While a routerinfo, a routerstatus,
+ * and a microdesc have[*] only the information read from a router
+ * descriptor, a consensus entry, and a microdescriptor (respectively)...
+ * a node_t has flags based on *our own current opinion* of the node.
+ *
+ * [*] Actually, there is some leftover information in each that is mutable.
+ * We should try to excise that.
+ */
+typedef struct node_t {
+ /* Indexing information */
+
+ /** Used to look up the node_t by its identity digest. */
+ HT_ENTRY(node_t) ht_ent;
+ /** Position of the node within the list of nodes */
+ int nodelist_idx;
+
+ /** The identity digest of this node_t. No more than one node_t per
+ * identity may exist at a time. */
+ char identity[DIGEST_LEN];
+
+ microdesc_t *md;
+ routerinfo_t *ri;
+ routerstatus_t *rs;
+
+ /* local info: copied from routerstatus, then possibly frobbed based
+ * on experience. Authorities set this stuff directly. */
+
+ unsigned int is_running:1; /**< As far as we know, is this OR currently
+ * running? */
+ unsigned int is_valid:1; /**< Has a trusted dirserver validated this OR?
+ * (For Authdir: Have we validated this OR?)
+ */
+ unsigned int is_fast:1; /** Do we think this is a fast OR? */
+ unsigned int is_stable:1; /** Do we think this is a stable OR? */
+ unsigned int is_possible_guard:1; /**< Do we think this is an OK guard? */
+ unsigned int is_exit:1; /**< Do we think this is an OK exit? */
+ unsigned int is_bad_exit:1; /**< Do we think this exit is censored, borked,
+ * or otherwise nasty? */
+ unsigned int is_bad_directory:1; /**< Do we think this directory is junky,
+ * underpowered, or otherwise useless? */
+ unsigned int is_hs_dir:1; /**< True iff this router is a hidden service
+ * directory according to the authorities. */
+
+ /* Local info: warning state. */
+
+ unsigned int name_lookup_warned:1; /**< Have we warned the user for referring
+ * to this (unnamed) router by nickname?
+ */
+
+ /** Local info: we treat this node as if it rejects everything */
+ unsigned int rejects_all:1;
+
+ /* Local info: derived. */
+
+ /** According to the geoip db what country is this router in? */
+ country_t country;
+} node_t;
+
/** How many times will we try to download a router's descriptor before giving
* up? */
#define MAX_ROUTERDESC_DOWNLOAD_FAILURES 8
+/** How many times will we try to download a microdescriptor before giving
+ * up? */
+#define MAX_MICRODESC_DOWNLOAD_FAILURES 8
+
/** Contents of a v2 (non-consensus, non-vote) network status object. */
typedef struct networkstatus_v2_t {
/** When did we receive the network-status document? */
@@ -1768,9 +2047,6 @@ typedef enum {
FLAV_MICRODESC = 1,
} consensus_flavor_t;
-/** Which consensus flavor do we actually want to use to build circuits? */
-#define USABLE_CONSENSUS_FLAVOR FLAV_NS
-
/** How many different consensus flavors are there? */
#define N_CONSENSUS_FLAVORS ((int)(FLAV_MICRODESC)+1)
@@ -1940,24 +2216,33 @@ typedef struct authority_cert_t {
uint8_t is_cross_certified;
} authority_cert_t;
-/** Bitfield enum type listing types of directory authority/directory
- * server. */
+/** Bitfield enum type listing types of information that directory authorities
+ * can be authoritative about, and that directory caches may or may not cache.
+ *
+ * Note that the granularity here is based on authority granularity and on
+ * cache capabilities. Thus, one particular bit may correspond in practice to
+ * a few types of directory info, so long as every authority that pronounces
+ * officially about one of the types prounounces officially about all of them,
+ * and so long as every cache that caches one of them caches all of them.
+ */
typedef enum {
- NO_AUTHORITY = 0,
+ NO_DIRINFO = 0,
/** Serves/signs v1 directory information: Big lists of routers, and short
* routerstatus documents. */
- V1_AUTHORITY = 1 << 0,
+ V1_DIRINFO = 1 << 0,
/** Serves/signs v2 directory information: i.e. v2 networkstatus documents */
- V2_AUTHORITY = 1 << 1,
+ V2_DIRINFO = 1 << 1,
/** Serves/signs v3 directory information: votes, consensuses, certs */
- V3_AUTHORITY = 1 << 2,
+ V3_DIRINFO = 1 << 2,
/** Serves hidden service descriptors. */
- HIDSERV_AUTHORITY = 1 << 3,
+ HIDSERV_DIRINFO = 1 << 3,
/** Serves bridge descriptors. */
- BRIDGE_AUTHORITY = 1 << 4,
- /** Serves extrainfo documents. (XXX Not precisely an authority type)*/
- EXTRAINFO_CACHE = 1 << 5,
-} authority_type_t;
+ BRIDGE_DIRINFO = 1 << 4,
+ /** Serves extrainfo documents. */
+ EXTRAINFO_DIRINFO=1 << 5,
+ /** Serves microdescriptors. */
+ MICRODESC_DIRINFO=1 << 6,
+} dirinfo_type_t;
#define CRYPT_PATH_MAGIC 0x70127012u
@@ -2030,15 +2315,15 @@ typedef struct {
/** How to extend to the planned exit node. */
extend_info_t *chosen_exit;
/** Whether every node in the circ must have adequate uptime. */
- int need_uptime;
+ unsigned int need_uptime : 1;
/** Whether every node in the circ must have adequate capacity. */
- int need_capacity;
+ unsigned int need_capacity : 1;
/** Whether the last hop was picked with exiting in mind. */
- int is_internal;
- /** Did we pick this as a one-hop tunnel (not safe for other conns)?
- * These are for encrypted connections that exit to this router, not
+ unsigned int is_internal : 1;
+ /** Did we pick this as a one-hop tunnel (not safe for other streams)?
+ * These are for encrypted dir conns that exit to this router, not
* for arbitrary exits from the circuit. */
- int onehop_tunnel;
+ unsigned int onehop_tunnel : 1;
/** The crypt_path_t to append after rendezvous: used for rendezvous. */
crypt_path_t *pending_final_cpath;
/** How many times has building a circuit for this task failed? */
@@ -2136,7 +2421,10 @@ typedef struct circuit_t {
* length ONIONSKIN_CHALLENGE_LEN. */
char *n_conn_onionskin;
- struct timeval timestamp_created; /**< When was the circuit created? */
+ /** When was this circuit created? We keep this timestamp with a higher
+ * resolution than most so that the circuit-build-time tracking code can
+ * get millisecond resolution. */
+ struct timeval timestamp_created;
/** When the circuit was first used, or 0 if the circuit is clean.
*
* XXXX023 Note that some code will artifically adjust this value backward
@@ -2234,6 +2522,55 @@ typedef struct origin_circuit_t {
/* XXXX NM This can get re-used after 2**32 circuits. */
uint32_t global_identifier;
+ /** True if we have associated one stream to this circuit, thereby setting
+ * the isolation paramaters for this circuit. Note that this doesn't
+ * necessarily mean that we've <em>attached</em> any streams to the circuit:
+ * we may only have marked up this circuit during the launch process.
+ */
+ unsigned int isolation_values_set : 1;
+ /** True iff any stream has <em>ever</em> been attached to this circuit.
+ *
+ * In a better world we could use timestamp_dirty for this, but
+ * timestamp_dirty is far too overloaded at the moment.
+ */
+ unsigned int isolation_any_streams_attached : 1;
+
+ /** A bitfield of ISO_* flags for every isolation field such that this
+ * circuit has had streams with more than one value for that field
+ * attached to it. */
+ uint8_t isolation_flags_mixed;
+
+ /** @name Isolation parameters
+ *
+ * If any streams have been associated with this circ (isolation_values_set
+ * == 1), and all streams associated with the circuit have had the same
+ * value for some field ((isolation_flags_mixed & ISO_FOO) == 0), then these
+ * elements hold the value for that field.
+ *
+ * Note again that "associated" is not the same as "attached": we
+ * preliminarily associate streams with a circuit while the circuit is being
+ * launched, so that we can tell whether we need to launch more circuits.
+ *
+ * @{
+ */
+ uint8_t client_proto_type;
+ uint8_t client_proto_socksver;
+ uint16_t dest_port;
+ tor_addr_t client_addr;
+ char *dest_address;
+ int session_group;
+ unsigned nym_epoch;
+ size_t socks_username_len;
+ uint8_t socks_password_len;
+ /* Note that the next two values are NOT NUL-terminated; see
+ socks_username_len and socks_password_len for their lengths. */
+ char *socks_username;
+ char *socks_password;
+ /** Global identifier for the first stream attached here; used by
+ * ISO_STREAM. */
+ uint64_t associated_isolated_stream_global_id;
+ /**@}*/
+
} origin_circuit_t;
/** An or_circuit_t holds information needed to implement a circuit at an
@@ -2352,6 +2689,60 @@ typedef enum invalid_router_usage_t {
#define MIN_CONSTRAINED_TCP_BUFFER 2048
#define MAX_CONSTRAINED_TCP_BUFFER 262144 /* 256k */
+/** @name Isolation flags
+
+ Ways to isolate client streams
+
+ @{
+*/
+/** Isolate based on destination port */
+#define ISO_DESTPORT (1u<<0)
+/** Isolate based on destination address */
+#define ISO_DESTADDR (1u<<1)
+/** Isolate based on SOCKS authentication */
+#define ISO_SOCKSAUTH (1u<<2)
+/** Isolate based on client protocol choice */
+#define ISO_CLIENTPROTO (1u<<3)
+/** Isolate based on client address */
+#define ISO_CLIENTADDR (1u<<4)
+/** Isolate based on session group (always on). */
+#define ISO_SESSIONGRP (1u<<5)
+/** Isolate based on newnym epoch (always on). */
+#define ISO_NYM_EPOCH (1u<<6)
+/** Isolate all streams (Internal only). */
+#define ISO_STREAM (1u<<7)
+/**@}*/
+
+/** Default isolation level for ports. */
+#define ISO_DEFAULT (ISO_CLIENTADDR|ISO_SOCKSAUTH|ISO_SESSIONGRP|ISO_NYM_EPOCH)
+
+/** Indicates that we haven't yet set a session group on a port_cfg_t. */
+#define SESSION_GROUP_UNSET -1
+/** Session group reserved for directory connections */
+#define SESSION_GROUP_DIRCONN -2
+/** Session group reserved for resolve requests launched by a controller */
+#define SESSION_GROUP_CONTROL_RESOLVE -3
+/** First automatically allocated session group number */
+#define SESSION_GROUP_FIRST_AUTO -4
+
+/** Configuration for a single port that we're listening on. */
+typedef struct port_cfg_t {
+ tor_addr_t addr; /**< The actual IP to listen on, if !is_unix_addr. */
+ int port; /**< The configured port, or CFG_AUTO_PORT to tell Tor to pick its
+ * own port. */
+ uint8_t type; /**< One of CONN_TYPE_*_LISTENER */
+ unsigned is_unix_addr : 1; /**< True iff this is an AF_UNIX address. */
+
+ /* Client port types (socks, dns, trans, natd) only: */
+ uint8_t isolation_flags; /**< Zero or more isolation flags */
+ int session_group; /**< A session group, or -1 if this port is not in a
+ * session group. */
+
+ /* Unix sockets only: */
+ /** Path for an AF_UNIX address */
+ char unix_addr[FLEXIBLE_ARRAY_MEMBER];
+} port_cfg_t;
+
/** A linked list of lines in a config file. */
typedef struct config_line_t {
char *key;
@@ -2378,6 +2769,7 @@ typedef struct {
config_line_t *Logs; /**< New-style list of configuration lines
* for logs */
+ int LogTimeGranularity; /**< Log resolution in milliseconds. */
int LogMessageDomains; /**< Boolean: Should we log the domain(s) in which
* each log message occurs? */
@@ -2446,16 +2838,17 @@ typedef struct {
char *User; /**< Name of user to run Tor as. */
char *Group; /**< Name of group to run Tor as. */
int ORPort; /**< Port to listen on for OR connections. */
- int SocksPort; /**< Port to listen on for SOCKS connections. */
- /** Port to listen on for transparent pf/netfilter connections. */
- int TransPort;
- int NATDPort; /**< Port to listen on for transparent natd connections. */
+ config_line_t *SocksPort; /**< Ports to listen on for SOCKS connections. */
+ /** Ports to listen on for transparent pf/netfilter connections. */
+ config_line_t *TransPort;
+ config_line_t *NATDPort; /**< Ports to listen on for transparent natd
+ * connections. */
int ControlPort; /**< Port to listen on for control connections. */
config_line_t *ControlSocket; /**< List of Unix Domain Sockets to listen on
* for control connections. */
int ControlSocketsGroupWritable; /**< Boolean: Are control sockets g+rw? */
int DirPort; /**< Port to listen on for directory connections. */
- int DNSPort; /**< Port to listen on for DNS requests. */
+ config_line_t *DNSPort; /**< Port to listen on for DNS requests. */
int AssumeReachable; /**< Whether to publish our descriptor regardless. */
int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */
int V1AuthoritativeDir; /**< Boolean: is this an authoritative directory
@@ -2483,6 +2876,12 @@ typedef struct {
int UseBridges; /**< Boolean: should we start all circuits with a bridge? */
config_line_t *Bridges; /**< List of bootstrap bridge addresses. */
+ config_line_t *ClientTransportPlugin; /**< List of client
+ transport plugins. */
+
+ config_line_t *ServerTransportPlugin; /**< List of client
+ transport plugins. */
+
int BridgeRelay; /**< Boolean: are we acting as a bridge relay? We make
* this explicit so we can change how we behave in the
* future. */
@@ -2497,8 +2896,8 @@ typedef struct {
/** To what authority types do we publish our descriptor? Choices are
* "v1", "v2", "v3", "bridge", or "". */
smartlist_t *PublishServerDescriptor;
- /** An authority type, derived from PublishServerDescriptor. */
- authority_type_t _PublishServerDescriptor;
+ /** A bitfield of authority types, derived from PublishServerDescriptor. */
+ dirinfo_type_t _PublishServerDescriptor;
/** Boolean: do we publish hidden service descriptors to the HS auths? */
int PublishHidServDescriptors;
int FetchServerDescriptors; /**< Do we fetch server descriptors as normal? */
@@ -2507,8 +2906,11 @@ typedef struct {
* we don't need to? */
int HidServDirectoryV2; /**< Do we participate in the HS DHT? */
+ int VoteOnHidServDirectoriesV2; /**< As a directory authority, vote on
+ * assignment of the HSDir flag? */
int MinUptimeHidServDirectoryV2; /**< As directory authority, accept hidden
* service directories after what time? */
+
int FetchUselessDescriptors; /**< Do we fetch non-running descriptors too? */
int AllDirActionsPrivate; /**< Should every directory action be sent
* through a Tor circuit? */
@@ -2527,12 +2929,10 @@ typedef struct {
uint64_t ConstrainedSockSize; /**< Size of constrained buffers. */
/** Whether we should drop exit streams from Tors that we don't know are
- * relays. One of "0" (never refuse), "1" (always refuse), or "auto" (do
+ * relays. One of "0" (never refuse), "1" (always refuse), or "-1" (do
* what the consensus says, defaulting to 'refuse' if the consensus says
* nothing). */
- char *RefuseUnknownExits;
- /** Parsed version of RefuseUnknownExits. -1 for auto. */
- int RefuseUnknownExits_;
+ int RefuseUnknownExits;
/** Application ports that require all nodes in circ to have sufficient
* uptime. */
@@ -2603,6 +3003,9 @@ typedef struct {
* authorizations for hidden services */
char *ContactInfo; /**< Contact info to be published in the directory. */
+ int HeartbeatPeriod; /**< Log heartbeat messages after this many seconds
+ * have passed. */
+
char *HTTPProxy; /**< hostname[:port] to use as http proxy, if any. */
tor_addr_t HTTPProxyAddr; /**< Parsed IPv4 addr for http proxy, if any. */
uint16_t HTTPProxyPort; /**< Parsed port for http proxy, if any. */
@@ -2640,7 +3043,8 @@ typedef struct {
char *MyFamily; /**< Declared family for this OR. */
config_line_t *NodeFamilies; /**< List of config lines for
- * node families */
+ * node families */
+ smartlist_t *NodeFamilySets; /**< List of parsed NodeFamilies values. */
config_line_t *AuthDirBadDir; /**< Address policy for descriptors to
* mark as bad dir mirrors. */
config_line_t *AuthDirBadExit; /**< Address policy for descriptors to
@@ -2706,6 +3110,8 @@ typedef struct {
* log whether it was DNS-leaking or not? */
int HardwareAccel; /**< Boolean: Should we enable OpenSSL hardware
* acceleration where available? */
+ /** Token Bucket Refill resolution in milliseconds. */
+ int TokenBucketRefillInterval;
char *AccelName; /**< Optional hardware acceleration engine name. */
char *AccelDir; /**< Optional hardware acceleration engine search dir. */
int UseEntryGuards; /**< Boolean: Do we try to enter from a smallish number
@@ -2740,7 +3146,9 @@ typedef struct {
/** Boolean: if set, we start even if our resolv.conf file is missing
* or broken. */
int ServerDNSAllowBrokenConfig;
-
+ /** Boolean: if set, then even connections to private addresses will get
+ * rate-limited. */
+ int CountPrivateBandwidth;
smartlist_t *ServerDNSTestAddresses; /**< A list of addresses that definitely
* should be resolvable. Used for
* testing our DNS server. */
@@ -2750,6 +3158,10 @@ typedef struct {
* possible. */
int PreferTunneledDirConns; /**< If true, avoid dirservers that don't
* support BEGIN_DIR, when possible. */
+ int PortForwarding; /**< If true, use NAT-PMP or UPnP to automatically
+ * forward the DirPort and ORPort on the NAT device */
+ char *PortForwardingHelper; /** < Filename or full path of the port
+ forwarding helper executable */
int AllowNonRFC953Hostnames; /**< If true, we allow connections to hostnames
* with weird characters. */
/** If true, we try resolving hostnames with weird characters. */
@@ -2787,6 +3199,9 @@ typedef struct {
/** If true, the user wants us to collect statistics on port usage. */
int ExitPortStatistics;
+ /** If true, the user wants us to collect connection statistics. */
+ int ConnDirectionStatistics;
+
/** If true, the user wants us to collect cell statistics. */
int CellStatistics;
@@ -2883,16 +3298,35 @@ typedef struct {
*/
double CircuitPriorityHalflife;
+ /** If true, do not enable IOCP on windows with bufferevents, even if
+ * we think we could. */
+ int DisableIOCP;
+ /** For testing only: will go away in 0.2.3.x. */
+ int _UseFilteringSSLBufferevents;
+
/** Set to true if the TestingTorNetwork configuration option is set.
* This is used so that options_validate() has a chance to realize that
* the defaults have changed. */
int _UsingTestNetworkDefaults;
+ /** If 1, we try to use microdescriptors to build circuits. If 0, we don't.
+ * If -1, Tor decides. */
+ int UseMicrodescriptors;
+
/** File where we should write the ControlPort. */
char *ControlPortWriteToFile;
/** Should that file be group-readable? */
int ControlPortFileGroupReadable;
+#define MAX_MAX_CLIENT_CIRCUITS_PENDING 1024
+ /** Maximum number of non-open general-purpose origin circuits to allow at
+ * once. */
+ int MaxClientCircuitsPending;
+
+ /** If 1, we always send optimistic data when it's supported. If 0, we
+ * never use it. If -1, we do what the consensus says. */
+ int OptimisticData;
+
} or_options_t;
/** Persistent state for an onion router, as saved to disk. */
@@ -2919,6 +3353,8 @@ typedef struct {
/** A list of Entry Guard-related configuration lines. */
config_line_t *EntryGuards;
+ config_line_t *TransportProxies;
+
/** These fields hold information on the history of bandwidth usage for
* servers. The "Ends" fields hold the time when we last updated the
* bandwidth usage. The "Interval" fields hold the granularity, in seconds,
@@ -2971,6 +3407,8 @@ static INLINE void or_state_mark_dirty(or_state_t *state, time_t when)
#define MAX_SOCKS_REPLY_LEN 1024
#define MAX_SOCKS_ADDR_LEN 256
+#define SOCKS_NO_AUTH 0x00
+#define SOCKS_USER_PASS 0x02
/** Please open a TCP connection to this addr:port. */
#define SOCKS_COMMAND_CONNECT 0x01
@@ -2990,10 +3428,17 @@ struct socks_request_t {
/** Which version of SOCKS did the client use? One of "0, 4, 5" -- where
* 0 means that no socks handshake ever took place, and this is just a
* stub connection (e.g. see connection_ap_make_link()). */
- char socks_version;
- int command; /**< What is this stream's goal? One from the above list. */
+ uint8_t socks_version;
+ /** If using socks5 authentication, which authentication type did we
+ * negotiate? currently we support 0 (no authentication) and 2
+ * (username/password). */
+ uint8_t auth_type;
+ /** What is this stream's goal? One of the SOCKS_COMMAND_* values */
+ uint8_t command;
+ /** Which kind of listener created this stream? */
+ uint8_t listener_type;
size_t replylen; /**< Length of <b>reply</b>. */
- char reply[MAX_SOCKS_REPLY_LEN]; /**< Write an entry into this string if
+ uint8_t reply[MAX_SOCKS_REPLY_LEN]; /**< Write an entry into this string if
* we want to specify our own socks reply,
* rather than using the default socks4 or
* socks5 socks reply. We use this for the
@@ -3005,10 +3450,21 @@ struct socks_request_t {
unsigned int has_finished : 1; /**< Has the SOCKS handshake finished? Used to
* make sure we send back a socks reply for
* every connection. */
+ unsigned int got_auth : 1; /**< Have we received any authentication data? */
+
+ /** Number of bytes in username; 0 if username is NULL */
+ size_t usernamelen;
+ /** Number of bytes in password; 0 if password is NULL */
+ uint8_t passwordlen;
+ /** The negotiated username value if any (for socks5), or the entire
+ * authentication string (for socks4). This value is NOT nul-terminated;
+ * see usernamelen for its length. */
+ char *username;
+ /** The negotiated password value if any (for socks5). This value is NOT
+ * nul-terminated; see passwordlen for its length. */
+ char *password;
};
-/* all the function prototypes go here */
-
/********************************* circuitbuild.c **********************/
/** How many hops does a general-purpose circuit have by default? */
@@ -3421,7 +3877,7 @@ typedef enum {
ADDR_POLICY_PROBABLY_ACCEPTED=1,
/** Part of the address was unknown, but as far as we can tell, it was
* rejected. */
- ADDR_POLICY_PROBABLY_REJECTED=2
+ ADDR_POLICY_PROBABLY_REJECTED=2,
} addr_policy_result_t;
/********************************* rephist.c ***************************/
@@ -3451,14 +3907,34 @@ typedef struct rend_encoded_v2_service_descriptor_t {
char *desc_str; /**< Descriptor string. */
} rend_encoded_v2_service_descriptor_t;
-/** Introduction point information. */
+/** The maximum number of non-circuit-build-timeout failures a hidden
+ * service client will tolerate while trying to build a circuit to an
+ * introduction point. See also rend_intro_point_t.unreachable_count. */
+#define MAX_INTRO_POINT_REACHABILITY_FAILURES 5
+
+/** Introduction point information. Used both in rend_service_t (on
+ * the service side) and in rend_service_descriptor_t (on both the
+ * client and service side). */
typedef struct rend_intro_point_t {
extend_info_t *extend_info; /**< Extend info of this introduction point. */
crypto_pk_env_t *intro_key; /**< Introduction key that replaces the service
* key, if this descriptor is V2. */
+
+ /** (Client side only) Flag indicating that a timeout has occurred
+ * after sending an INTRODUCE cell to this intro point. After a
+ * timeout, an intro point should not be tried again during the same
+ * hidden service connection attempt, but it may be tried again
+ * during a future connection attempt. */
+ unsigned int timed_out : 1;
+
+ /** (Client side only) The number of times we have failed to build a
+ * circuit to this intro point for some reason other than our
+ * circuit-build timeout. See also MAX_INTRO_POINT_REACHABILITY_FAILURES. */
+ unsigned int unreachable_count : 3;
} rend_intro_point_t;
-/** Information used to connect to a hidden service. */
+/** Information used to connect to a hidden service. Used on both the
+ * service side and the client side. */
typedef struct rend_service_descriptor_t {
crypto_pk_env_t *pk; /**< This service's public key. */
int version; /**< Version of the descriptor format: 0 or 2. */
@@ -3506,7 +3982,7 @@ typedef struct trusted_dir_server_t {
unsigned int has_accepted_serverdesc:1;
/** What kind of authority is this? (Bitfield.) */
- authority_type_t type;
+ dirinfo_type_t type;
download_status_t v2_ns_dl_status; /**< Status of downloading this server's
* v2 network status. */
@@ -3552,6 +4028,8 @@ typedef struct trusted_dir_server_t {
* fetches to _any_ single directory server.]
*/
#define PDS_NO_EXISTING_SERVERDESC_FETCH (1<<3)
+#define PDS_NO_EXISTING_MICRODESC_FETCH (1<<4)
+
#define _PDS_PREFER_TUNNELED_DIR_CONNS (1<<16)
/** Possible ways to weight routers when choosing one randomly. See
@@ -3569,7 +4047,8 @@ typedef enum {
CRN_NEED_GUARD = 1<<2,
CRN_ALLOW_INVALID = 1<<3,
/* XXXX not used, apparently. */
- CRN_WEIGHT_AS_EXIT = 1<<5
+ CRN_WEIGHT_AS_EXIT = 1<<5,
+ CRN_NEED_DESC = 1<<6
} router_crn_flags_t;
/** Return value for router_add_to_routerlist() and dirserv_add_descriptor() */
diff --git a/src/or/policies.c b/src/or/policies.c
index c87036013..40e527747 100644
--- a/src/or/policies.c
+++ b/src/or/policies.c
@@ -11,6 +11,7 @@
#include "or.h"
#include "config.h"
#include "dirserv.h"
+#include "nodelist.h"
#include "policies.h"
#include "routerparse.h"
#include "ht.h"
@@ -82,15 +83,15 @@ policy_expand_private(smartlist_t **policy)
continue;
}
for (i = 0; private_nets[i]; ++i) {
- addr_policy_t policy;
- memcpy(&policy, p, sizeof(addr_policy_t));
- policy.is_private = 0;
- policy.is_canonical = 0;
- if (tor_addr_parse_mask_ports(private_nets[i], &policy.addr,
- &policy.maskbits, &port_min, &port_max)<0) {
+ addr_policy_t newpolicy;
+ memcpy(&newpolicy, p, sizeof(addr_policy_t));
+ newpolicy.is_private = 0;
+ newpolicy.is_canonical = 0;
+ if (tor_addr_parse_mask_ports(private_nets[i], &newpolicy.addr,
+ &newpolicy.maskbits, &port_min, &port_max)<0) {
tor_assert(0);
}
- smartlist_add(tmp, addr_policy_get_canonical_entry(&policy));
+ smartlist_add(tmp, addr_policy_get_canonical_entry(&newpolicy));
}
addr_policy_free(p);
});
@@ -163,7 +164,7 @@ parse_addr_policy(config_line_t *cfg, smartlist_t **dest,
static int
parse_reachable_addresses(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int ret = 0;
if (options->ReachableDirAddresses &&
@@ -261,7 +262,7 @@ fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port)
/** Return true iff we think our firewall will let us make an OR connection to
* <b>ri</b>. */
int
-fascist_firewall_allows_or(routerinfo_t *ri)
+fascist_firewall_allows_or(const routerinfo_t *ri)
{
/* XXXX proposal 118 */
tor_addr_t addr;
@@ -269,6 +270,22 @@ fascist_firewall_allows_or(routerinfo_t *ri)
return fascist_firewall_allows_address_or(&addr, ri->or_port);
}
+/** Return true iff we think our firewall will let us make an OR connection to
+ * <b>node</b>. */
+int
+fascist_firewall_allows_node(const node_t *node)
+{
+ if (node->ri) {
+ return fascist_firewall_allows_or(node->ri);
+ } else if (node->rs) {
+ tor_addr_t addr;
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+ return fascist_firewall_allows_address_or(&addr, node->rs->or_port);
+ } else {
+ return 1;
+ }
+}
+
/** Return true iff we think our firewall will let us make a directory
* connection to addr:port. */
int
@@ -339,7 +356,7 @@ authdir_policy_badexit_address(uint32_t addr, uint16_t port)
* options in <b>options</b>, return -1 and set <b>msg</b> to a newly
* allocated description of the error. Else return 0. */
int
-validate_addr_policies(or_options_t *options, char **msg)
+validate_addr_policies(const or_options_t *options, char **msg)
{
/* XXXX Maybe merge this into parse_policies_from_options, to make sure
* that the two can't go out of sync. */
@@ -423,7 +440,7 @@ load_policy_from_option(config_line_t *config, smartlist_t **policy,
/** Set all policies based on <b>options</b>, which should have been validated
* first by validate_addr_policies. */
int
-policies_parse_from_options(or_options_t *options)
+policies_parse_from_options(const or_options_t *options)
{
int ret = 0;
if (load_policy_from_option(options->SocksPolicy, &socks_policy, -1) < 0)
@@ -553,18 +570,6 @@ addr_policy_get_canonical_entry(addr_policy_t *e)
return found->policy;
}
-/** As compare_tor_addr_to_addr_policy, but instead of a tor_addr_t, takes
- * in host order. */
-addr_policy_result_t
-compare_addr_to_addr_policy(uint32_t addr, uint16_t port,
- const smartlist_t *policy)
-{
- /*XXXX deprecate this function when possible. */
- tor_addr_t a;
- tor_addr_from_ipv4h(&a, addr);
- return compare_tor_addr_to_addr_policy(&a, port, policy);
-}
-
/** Helper for compare_tor_addr_to_addr_policy. Implements the case where
* addr and port are both known. */
static addr_policy_result_t
@@ -684,7 +689,7 @@ compare_tor_addr_to_addr_policy(const tor_addr_t *addr, uint16_t port,
if (!policy) {
/* no policy? accept all. */
return ADDR_POLICY_ACCEPTED;
- } else if (tor_addr_is_null(addr)) {
+ } else if (addr == NULL || tor_addr_is_null(addr)) {
tor_assert(port != 0);
return compare_unknown_tor_addr_to_addr_policy(port, policy);
} else if (port == 0) {
@@ -866,15 +871,11 @@ policies_exit_policy_append_reject_star(smartlist_t **dest)
append_exit_policy_string(dest, "reject *:*");
}
-/** Replace the exit policy of <b>r</b> with reject *:*. */
+/** Replace the exit policy of <b>node</b> with reject *:* */
void
-policies_set_router_exitpolicy_to_reject_all(routerinfo_t *r)
+policies_set_node_exitpolicy_to_reject_all(node_t *node)
{
- addr_policy_t *item;
- addr_policy_list_free(r->exit_policy);
- r->exit_policy = smartlist_create();
- item = router_parse_addr_policy_item_from_string("reject *:*", -1);
- smartlist_add(r->exit_policy, item);
+ node->rejects_all = 1;
}
/** Return 1 if there is at least one /8 subnet in <b>policy</b> that
@@ -1085,7 +1086,7 @@ policy_summary_split(smartlist_t *summary,
int start_at_index;
int i = 0;
- /* XXXX Do a binary search if run time matters */
+
while (AT(i)->prt_max < prt_min)
i++;
if (AT(i)->prt_min != prt_min) {
@@ -1298,6 +1299,186 @@ policy_summarize(smartlist_t *policy)
return result;
}
+/** Convert a summarized policy string into a short_policy_t. Return NULL
+ * if the string is not well-formed. */
+short_policy_t *
+parse_short_policy(const char *summary)
+{
+ const char *orig_summary = summary;
+ short_policy_t *result;
+ int is_accept;
+ int n_entries;
+ short_policy_entry_t entries[MAX_EXITPOLICY_SUMMARY_LEN]; /* overkill */
+ const char *next;
+
+ if (!strcmpstart(summary, "accept ")) {
+ is_accept = 1;
+ summary += strlen("accept ");
+ } else if (!strcmpstart(summary, "reject ")) {
+ is_accept = 0;
+ summary += strlen("reject ");
+ } else {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Unrecognized policy summary keyword");
+ return NULL;
+ }
+
+ n_entries = 0;
+ for ( ; *summary; summary = next) {
+ const char *comma = strchr(summary, ',');
+ unsigned low, high;
+ char dummy;
+ char ent_buf[32];
+
+ next = comma ? comma+1 : strchr(summary, '\0');
+
+ if (n_entries == MAX_EXITPOLICY_SUMMARY_LEN) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Impossibly long policy summary %s",
+ escaped(orig_summary));
+ return NULL;
+ }
+
+ if (! TOR_ISDIGIT(*summary) || next-summary > (int)(sizeof(ent_buf)-1)) {
+ /* unrecognized entry format. skip it. */
+ continue;
+ }
+ if (next-summary < 2) {
+ /* empty; skip it. */
+ continue;
+ }
+
+ memcpy(ent_buf, summary, next-summary-1);
+ ent_buf[next-summary-1] = '\0';
+
+ if (tor_sscanf(ent_buf, "%u-%u%c", &low, &high, &dummy) == 2) {
+ if (low<1 || low>65535 || high<1 || high>65535) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,
+ "Found bad entry in policy summary %s", escaped(orig_summary));
+ return NULL;
+ }
+ } else if (tor_sscanf(ent_buf, "%u%c", &low, &dummy) == 1) {
+ if (low<1 || low>65535) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,
+ "Found bad entry in policy summary %s", escaped(orig_summary));
+ return NULL;
+ }
+ high = low;
+ } else {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,"Found bad entry in policy summary %s",
+ escaped(orig_summary));
+ return NULL;
+ }
+
+ entries[n_entries].min_port = low;
+ entries[n_entries].max_port = high;
+ n_entries++;
+ }
+
+ if (n_entries == 0) {
+ log_fn(LOG_PROTOCOL_WARN, LD_DIR,
+ "Found no port-range entries in summary %s", escaped(orig_summary));
+ return NULL;
+ }
+
+ {
+ size_t size = STRUCT_OFFSET(short_policy_t, entries) +
+ sizeof(short_policy_entry_t)*(n_entries);
+ result = tor_malloc_zero(size);
+
+ tor_assert( (char*)&result->entries[n_entries-1] < ((char*)result)+size);
+ }
+
+ result->is_accept = is_accept;
+ result->n_entries = n_entries;
+ memcpy(result->entries, entries, sizeof(short_policy_entry_t)*n_entries);
+ return result;
+}
+
+/** Release all storage held in <b>policy</b>. */
+void
+short_policy_free(short_policy_t *policy)
+{
+ tor_free(policy);
+}
+
+/** See whether the <b>addr</b>:<b>port</b> address is likely to be accepted
+ * or rejected by the summarized policy <b>policy</b>. Return values are as
+ * for compare_tor_addr_to_addr_policy. Unlike the regular addr_policy
+ * functions, requires the <b>port</b> be specified. */
+addr_policy_result_t
+compare_tor_addr_to_short_policy(const tor_addr_t *addr, uint16_t port,
+ const short_policy_t *policy)
+{
+ int i;
+ int found_match = 0;
+ int accept;
+ (void)addr;
+
+ tor_assert(port != 0);
+
+ if (addr && tor_addr_is_null(addr))
+ addr = NULL; /* Unspec means 'no address at all,' in this context. */
+
+ if (addr && (tor_addr_is_internal(addr, 0) ||
+ tor_addr_is_loopback(addr)))
+ return ADDR_POLICY_REJECTED;
+
+ for (i=0; i < policy->n_entries; ++i) {
+ const short_policy_entry_t *e = &policy->entries[i];
+ if (e->min_port <= port && port <= e->max_port) {
+ found_match = 1;
+ break;
+ }
+ }
+
+ if (found_match)
+ accept = policy->is_accept;
+ else
+ accept = ! policy->is_accept;
+
+ /* ???? are these right? */
+ if (accept)
+ return ADDR_POLICY_PROBABLY_ACCEPTED;
+ else
+ return ADDR_POLICY_REJECTED;
+}
+
+/** Return true iff <b>policy</b> seems reject all ports */
+int
+short_policy_is_reject_star(const short_policy_t *policy)
+{
+ /* This doesn't need to be as much on the lookout as policy_is_reject_star,
+ * since policy summaries are from the consensus or from consensus
+ * microdescs.
+ */
+ tor_assert(policy);
+ /* Check for an exact match of "reject 1-65535". */
+ return (policy->is_accept == 0 && policy->n_entries == 1 &&
+ policy->entries[0].min_port == 1 &&
+ policy->entries[0].max_port == 65535);
+}
+
+/** Decides whether addr:port is probably or definitely accepted or rejcted by
+ * <b>node</b>. See compare_tor_addr_to_addr_policy for details on addr/port
+ * interpretation. */
+addr_policy_result_t
+compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port,
+ const node_t *node)
+{
+ if (node->rejects_all)
+ return ADDR_POLICY_REJECTED;
+
+ if (node->ri)
+ return compare_tor_addr_to_addr_policy(addr, port, node->ri->exit_policy);
+ else if (node->md) {
+ if (node->md->exit_policy == NULL)
+ return ADDR_POLICY_REJECTED;
+ else
+ return compare_tor_addr_to_short_policy(addr, port,
+ node->md->exit_policy);
+ } else
+ return ADDR_POLICY_PROBABLY_REJECTED;
+}
+
/** Implementation for GETINFO control command: knows the answer for questions
* about "exit-policy/..." */
int
diff --git a/src/or/policies.h b/src/or/policies.h
index b2947c67e..51716ab0a 100644
--- a/src/or/policies.h
+++ b/src/or/policies.h
@@ -19,7 +19,8 @@
int firewall_is_fascist_or(void);
int fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port);
-int fascist_firewall_allows_or(routerinfo_t *ri);
+int fascist_firewall_allows_or(const routerinfo_t *ri);
+int fascist_firewall_allows_node(const node_t *node);
int fascist_firewall_allows_address_dir(const tor_addr_t *addr, uint16_t port);
int dir_policy_permits_address(const tor_addr_t *addr);
int socks_policy_permits_address(const tor_addr_t *addr);
@@ -28,21 +29,23 @@ int authdir_policy_valid_address(uint32_t addr, uint16_t port);
int authdir_policy_baddir_address(uint32_t addr, uint16_t port);
int authdir_policy_badexit_address(uint32_t addr, uint16_t port);
-int validate_addr_policies(or_options_t *options, char **msg);
+int validate_addr_policies(const or_options_t *options, char **msg);
void policy_expand_private(smartlist_t **policy);
-int policies_parse_from_options(or_options_t *options);
+int policies_parse_from_options(const or_options_t *options);
addr_policy_t *addr_policy_get_canonical_entry(addr_policy_t *ent);
int cmp_addr_policies(smartlist_t *a, smartlist_t *b);
addr_policy_result_t compare_tor_addr_to_addr_policy(const tor_addr_t *addr,
uint16_t port, const smartlist_t *policy);
-addr_policy_result_t compare_addr_to_addr_policy(uint32_t addr,
- uint16_t port, const smartlist_t *policy);
+
+addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr,
+ uint16_t port, const node_t *node);
+
int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest,
int rejectprivate, const char *local_address,
int add_default_policy);
void policies_exit_policy_append_reject_star(smartlist_t **dest);
-void policies_set_router_exitpolicy_to_reject_all(routerinfo_t *exitrouter);
+void policies_set_node_exitpolicy_to_reject_all(node_t *exitrouter);
int exit_policy_is_general_exit(smartlist_t *policy);
int policy_is_reject_star(const smartlist_t *policy);
int getinfo_helper_policies(control_connection_t *conn,
@@ -57,5 +60,12 @@ void policies_free_all(void);
char *policy_summarize(smartlist_t *policy);
+short_policy_t *parse_short_policy(const char *summary);
+void short_policy_free(short_policy_t *policy);
+int short_policy_is_reject_star(const short_policy_t *policy);
+addr_policy_result_t compare_tor_addr_to_short_policy(
+ const tor_addr_t *addr, uint16_t port,
+ const short_policy_t *policy);
+
#endif
diff --git a/src/or/relay.c b/src/or/relay.c
index 46e852217..51a29a20e 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -24,6 +24,7 @@
#include "main.h"
#include "mempool.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "reasons.h"
#include "relay.h"
@@ -648,6 +649,7 @@ connection_edge_send_command(edge_connection_t *fromconn,
{
/* XXXX NM Split this function into a separate versions per circuit type? */
circuit_t *circ;
+ crypt_path_t *cpath_layer = fromconn->cpath_layer;
tor_assert(fromconn);
circ = fromconn->on_circuit;
@@ -662,7 +664,8 @@ connection_edge_send_command(edge_connection_t *fromconn,
if (!circ) {
if (fromconn->_base.type == CONN_TYPE_AP) {
log_info(LD_APP,"no circ. Closing conn.");
- connection_mark_unattached_ap(fromconn, END_STREAM_REASON_INTERNAL);
+ connection_mark_unattached_ap(EDGE_TO_ENTRY_CONN(fromconn),
+ END_STREAM_REASON_INTERNAL);
} else {
log_info(LD_EXIT,"no circ. Closing conn.");
fromconn->edge_has_sent_end = 1; /* no circ to send to */
@@ -674,7 +677,7 @@ connection_edge_send_command(edge_connection_t *fromconn,
return relay_send_command_from_edge(fromconn->stream_id, circ,
relay_command, payload,
- payload_len, fromconn->cpath_layer);
+ payload_len, cpath_layer);
}
/** How many times will I retry a stream that fails due to DNS
@@ -702,22 +705,24 @@ edge_reason_is_retriable(int reason)
static int
connection_ap_process_end_not_open(
relay_header_t *rh, cell_t *cell, origin_circuit_t *circ,
- edge_connection_t *conn, crypt_path_t *layer_hint)
+ entry_connection_t *conn, crypt_path_t *layer_hint)
{
struct in_addr in;
- routerinfo_t *exitrouter;
+ node_t *exitrouter;
int reason = *(cell->payload+RELAY_HEADER_SIZE);
int control_reason = reason | END_STREAM_REASON_FLAG_REMOTE;
+ edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn);
(void) layer_hint; /* unused */
if (rh->length > 0 && edge_reason_is_retriable(reason) &&
- !connection_edge_is_rendezvous_stream(conn) /* avoid retry if rend */
- ) {
+ /* avoid retry if rend */
+ !connection_edge_is_rendezvous_stream(edge_conn)) {
+ const char *chosen_exit_digest =
+ circ->build_state->chosen_exit->identity_digest;
log_info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.",
safe_str(conn->socks_request->address),
stream_end_reason_to_string(reason));
- exitrouter =
- router_get_by_digest(circ->build_state->chosen_exit->identity_digest);
+ exitrouter = node_get_mutable_by_id(chosen_exit_digest);
switch (reason) {
case END_STREAM_REASON_EXITPOLICY:
if (rh->length >= 5) {
@@ -752,8 +757,8 @@ connection_ap_process_end_not_open(
log_info(LD_APP,
"Exitrouter %s seems to be more restrictive than its exit "
"policy. Not using this router as exit for now.",
- router_describe(exitrouter));
- policies_set_router_exitpolicy_to_reject_all(exitrouter);
+ node_describe(exitrouter));
+ policies_set_node_exitpolicy_to_reject_all(exitrouter);
}
/* rewrite it to an IP if we learned one. */
if (addressmap_rewrite(conn->socks_request->address,
@@ -818,7 +823,7 @@ connection_ap_process_end_not_open(
case END_STREAM_REASON_HIBERNATING:
case END_STREAM_REASON_RESOURCELIMIT:
if (exitrouter) {
- policies_set_router_exitpolicy_to_reject_all(exitrouter);
+ policies_set_node_exitpolicy_to_reject_all(exitrouter);
}
if (conn->chosen_exit_optional) {
/* stop wanting a specific exit */
@@ -838,7 +843,7 @@ connection_ap_process_end_not_open(
stream_end_reason_to_string(rh->length > 0 ? reason : -1));
circuit_log_path(LOG_INFO,LD_APP,circ);
/* need to test because of detach_retriable */
- if (!conn->_base.marked_for_close)
+ if (!ENTRY_TO_CONN(conn)->marked_for_close)
connection_mark_unattached_ap(conn, control_reason);
return 0;
}
@@ -847,7 +852,7 @@ connection_ap_process_end_not_open(
* dotted-quad representation of <b>new_addr</b> (given in host order),
* and send an appropriate REMAP event. */
static void
-remap_event_helper(edge_connection_t *conn, uint32_t new_addr)
+remap_event_helper(entry_connection_t *conn, uint32_t new_addr)
{
struct in_addr in;
@@ -873,7 +878,8 @@ connection_edge_process_relay_cell_not_open(
if (rh->command == RELAY_COMMAND_END) {
if (CIRCUIT_IS_ORIGIN(circ) && conn->_base.type == CONN_TYPE_AP) {
return connection_ap_process_end_not_open(rh, cell,
- TO_ORIGIN_CIRCUIT(circ), conn,
+ TO_ORIGIN_CIRCUIT(circ),
+ EDGE_TO_ENTRY_CONN(conn),
layer_hint);
} else {
/* we just got an 'end', don't need to send one */
@@ -887,6 +893,7 @@ connection_edge_process_relay_cell_not_open(
if (conn->_base.type == CONN_TYPE_AP &&
rh->command == RELAY_COMMAND_CONNECTED) {
+ entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
tor_assert(CIRCUIT_IS_ORIGIN(circ));
if (conn->_base.state != AP_CONN_STATE_CONNECT_WAIT) {
log_fn(LOG_PROTOCOL_WARN, LD_APP,
@@ -901,29 +908,26 @@ connection_edge_process_relay_cell_not_open(
int ttl;
if (!addr || (get_options()->ClientDNSRejectInternalAddresses &&
is_internal_IP(addr, 0))) {
- char buf[INET_NTOA_BUF_LEN];
- struct in_addr a;
- a.s_addr = htonl(addr);
- tor_inet_ntoa(&a, buf, sizeof(buf));
- log_info(LD_APP,
- "...but it claims the IP address was %s. Closing.", buf);
+ log_info(LD_APP, "...but it claims the IP address was %s. Closing.",
+ fmt_addr32(addr));
connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL);
- connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ connection_mark_unattached_ap(entry_conn,
+ END_STREAM_REASON_TORPROTOCOL);
return 0;
}
if (rh->length >= 8)
ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+4));
else
ttl = -1;
- client_dns_set_addressmap(conn->socks_request->address, addr,
- conn->chosen_exit_name, ttl);
+ client_dns_set_addressmap(entry_conn->socks_request->address, addr,
+ entry_conn->chosen_exit_name, ttl);
- remap_event_helper(conn, addr);
+ remap_event_helper(entry_conn, addr);
}
circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ));
/* don't send a socks reply to transparent conns */
- if (!conn->socks_request->has_finished)
- connection_ap_handshake_socks_reply(conn, NULL, 0, 0);
+ if (!entry_conn->socks_request->has_finished)
+ connection_ap_handshake_socks_reply(entry_conn, NULL, 0, 0);
/* Was it a linked dir conn? If so, a dir request just started to
* fetch something; this could be a bootstrap status milestone. */
@@ -946,6 +950,12 @@ connection_edge_process_relay_cell_not_open(
break;
}
}
+ /* This is definitely a success, so forget about any pending data we
+ * had sent. */
+ if (entry_conn->pending_optimistic_data) {
+ generic_buffer_free(entry_conn->pending_optimistic_data);
+ entry_conn->pending_optimistic_data = NULL;
+ }
/* handle anything that might have queued */
if (connection_edge_package_raw_inbuf(conn, 1, NULL) < 0) {
@@ -960,17 +970,18 @@ connection_edge_process_relay_cell_not_open(
int ttl;
int answer_len;
uint8_t answer_type;
+ entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
if (conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT) {
log_fn(LOG_PROTOCOL_WARN, LD_APP, "Got a 'resolved' cell while "
"not in state resolve_wait. Dropping.");
return 0;
}
- tor_assert(SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command));
+ tor_assert(SOCKS_COMMAND_IS_RESOLVE(entry_conn->socks_request->command));
answer_len = cell->payload[RELAY_HEADER_SIZE+1];
if (rh->length < 2 || answer_len+2>rh->length) {
log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
"Dropping malformed 'resolved' cell");
- connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TORPROTOCOL);
return 0;
}
answer_type = cell->payload[RELAY_HEADER_SIZE];
@@ -983,19 +994,17 @@ connection_edge_process_relay_cell_not_open(
uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
if (get_options()->ClientDNSRejectInternalAddresses &&
is_internal_IP(addr, 0)) {
- char buf[INET_NTOA_BUF_LEN];
- struct in_addr a;
- a.s_addr = htonl(addr);
- tor_inet_ntoa(&a, buf, sizeof(buf));
- log_info(LD_APP,"Got a resolve with answer %s. Rejecting.", buf);
- connection_ap_handshake_socks_resolved(conn,
+ log_info(LD_APP,"Got a resolve with answer %s. Rejecting.",
+ fmt_addr32(addr));
+ connection_ap_handshake_socks_resolved(entry_conn,
RESOLVED_TYPE_ERROR_TRANSIENT,
0, NULL, 0, TIME_MAX);
- connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL);
+ connection_mark_unattached_ap(entry_conn,
+ END_STREAM_REASON_TORPROTOCOL);
return 0;
}
}
- connection_ap_handshake_socks_resolved(conn,
+ connection_ap_handshake_socks_resolved(entry_conn,
answer_type,
cell->payload[RELAY_HEADER_SIZE+1], /*answer_len*/
cell->payload+RELAY_HEADER_SIZE+2, /*answer*/
@@ -1003,9 +1012,9 @@ connection_edge_process_relay_cell_not_open(
-1);
if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) {
uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2));
- remap_event_helper(conn, addr);
+ remap_event_helper(entry_conn, addr);
}
- connection_mark_unattached_ap(conn,
+ connection_mark_unattached_ap(entry_conn,
END_STREAM_REASON_DONE |
END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED);
return 0;
@@ -1039,6 +1048,9 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
relay_header_t rh;
unsigned domain = layer_hint?LD_APP:LD_EXIT;
int reason;
+ int optimistic_data = 0; /* Set to 1 if we receive data on a stream
+ * that's in the EXIT_CONN_STATE_RESOLVING
+ * or EXIT_CONN_STATE_CONNECTING states. */
tor_assert(cell);
tor_assert(circ);
@@ -1058,9 +1070,20 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
/* either conn is NULL, in which case we've got a control cell, or else
* conn points to the recognized stream. */
- if (conn && !connection_state_is_open(TO_CONN(conn)))
- return connection_edge_process_relay_cell_not_open(
- &rh, cell, circ, conn, layer_hint);
+ if (conn && !connection_state_is_open(TO_CONN(conn))) {
+ if (conn->_base.type == CONN_TYPE_EXIT &&
+ (conn->_base.state == EXIT_CONN_STATE_CONNECTING ||
+ conn->_base.state == EXIT_CONN_STATE_RESOLVING) &&
+ rh.command == RELAY_COMMAND_DATA) {
+ /* Allow DATA cells to be delivered to an exit node in state
+ * EXIT_CONN_STATE_CONNECTING or EXIT_CONN_STATE_RESOLVING.
+ * This speeds up HTTP, for example. */
+ optimistic_data = 1;
+ } else {
+ return connection_edge_process_relay_cell_not_open(
+ &rh, cell, circ, conn, layer_hint);
+ }
+ }
switch (rh.command) {
case RELAY_COMMAND_DROP:
@@ -1127,7 +1150,14 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
stats_n_data_bytes_received += rh.length;
connection_write_to_buf((char*)(cell->payload + RELAY_HEADER_SIZE),
rh.length, TO_CONN(conn));
- connection_edge_consider_sending_sendme(conn);
+
+ if (!optimistic_data) {
+ /* Only send a SENDME if we're not getting optimistic data; otherwise
+ * a SENDME could arrive before the CONNECTED.
+ */
+ connection_edge_consider_sending_sendme(conn);
+ }
+
return 0;
case RELAY_COMMAND_END:
reason = rh.length > 0 ?
@@ -1142,9 +1172,13 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
conn->_base.s,
stream_end_reason_to_string(reason),
conn->stream_id);
- if (conn->socks_request && !conn->socks_request->has_finished)
- log_warn(LD_BUG,
- "open stream hasn't sent socks answer yet? Closing.");
+ if (conn->_base.type == CONN_TYPE_AP) {
+ entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn);
+ if (entry_conn->socks_request &&
+ !entry_conn->socks_request->has_finished)
+ log_warn(LD_BUG,
+ "open stream hasn't sent socks answer yet? Closing.");
+ }
/* We just *got* an end; no reason to send one. */
conn->edge_has_sent_end = 1;
if (!conn->end_reason)
@@ -1152,8 +1186,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
if (!conn->_base.marked_for_close) {
/* only mark it if not already marked. it's possible to
* get the 'end' right around when the client hangs up on us. */
- connection_mark_for_close(TO_CONN(conn));
- conn->_base.hold_open_until_flushed = 1;
+ connection_mark_and_flush(TO_CONN(conn));
}
return 0;
case RELAY_COMMAND_EXTEND:
@@ -1324,10 +1357,17 @@ int
connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
int *max_cells)
{
- size_t amount_to_process, length;
+ size_t bytes_to_process, length;
char payload[CELL_PAYLOAD_SIZE];
circuit_t *circ;
- unsigned domain = conn->cpath_layer ? LD_APP : LD_EXIT;
+ const unsigned domain = conn->_base.type == CONN_TYPE_AP ? LD_APP : LD_EXIT;
+ int sending_from_optimistic = 0;
+ const int sending_optimistically =
+ conn->_base.type == CONN_TYPE_AP &&
+ conn->_base.state != AP_CONN_STATE_OPEN;
+ entry_connection_t *entry_conn =
+ conn->_base.type == CONN_TYPE_AP ? EDGE_TO_ENTRY_CONN(conn) : NULL;
+ crypt_path_t *cpath_layer = conn->cpath_layer;
tor_assert(conn);
@@ -1350,7 +1390,7 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
return -1;
}
- if (circuit_consider_stop_edge_reading(circ, conn->cpath_layer))
+ if (circuit_consider_stop_edge_reading(circ, cpath_layer))
return 0;
if (conn->package_window <= 0) {
@@ -1360,44 +1400,75 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial,
return 0;
}
- amount_to_process = buf_datalen(conn->_base.inbuf);
+ sending_from_optimistic = entry_conn &&
+ entry_conn->sending_optimistic_data != NULL;
- if (!amount_to_process)
+ if (PREDICT_UNLIKELY(sending_from_optimistic)) {
+ bytes_to_process = generic_buffer_len(entry_conn->sending_optimistic_data);
+ if (PREDICT_UNLIKELY(!bytes_to_process)) {
+ log_warn(LD_BUG, "sending_optimistic_data was non-NULL but empty");
+ bytes_to_process = connection_get_inbuf_len(TO_CONN(conn));
+ sending_from_optimistic = 0;
+ }
+ } else {
+ bytes_to_process = connection_get_inbuf_len(TO_CONN(conn));
+ }
+
+ if (!bytes_to_process)
return 0;
- if (!package_partial && amount_to_process < RELAY_PAYLOAD_SIZE)
+ if (!package_partial && bytes_to_process < RELAY_PAYLOAD_SIZE)
return 0;
- if (amount_to_process > RELAY_PAYLOAD_SIZE) {
+ if (bytes_to_process > RELAY_PAYLOAD_SIZE) {
length = RELAY_PAYLOAD_SIZE;
} else {
- length = amount_to_process;
+ length = bytes_to_process;
}
stats_n_data_bytes_packaged += length;
stats_n_data_cells_packaged += 1;
- connection_fetch_from_buf(payload, length, TO_CONN(conn));
+ if (PREDICT_UNLIKELY(sending_from_optimistic)) {
+ /* XXX023 We could be more efficient here by sometimes packing
+ * previously-sent optimistic data in the same cell with data
+ * from the inbuf. */
+ generic_buffer_get(entry_conn->sending_optimistic_data, payload, length);
+ if (!generic_buffer_len(entry_conn->sending_optimistic_data)) {
+ generic_buffer_free(entry_conn->sending_optimistic_data);
+ entry_conn->sending_optimistic_data = NULL;
+ }
+ } else {
+ connection_fetch_from_buf(payload, length, TO_CONN(conn));
+ }
log_debug(domain,"(%d) Packaging %d bytes (%d waiting).", conn->_base.s,
- (int)length, (int)buf_datalen(conn->_base.inbuf));
+ (int)length, (int)connection_get_inbuf_len(TO_CONN(conn)));
+
+ if (sending_optimistically && !sending_from_optimistic) {
+ /* This is new optimistic data; remember it in case we need to detach and
+ retry */
+ if (!entry_conn->pending_optimistic_data)
+ entry_conn->pending_optimistic_data = generic_buffer_new();
+ generic_buffer_add(entry_conn->pending_optimistic_data, payload, length);
+ }
if (connection_edge_send_command(conn, RELAY_COMMAND_DATA,
payload, length) < 0 )
/* circuit got marked for close, don't continue, don't need to mark conn */
return 0;
- if (!conn->cpath_layer) { /* non-rendezvous exit */
+ if (!cpath_layer) { /* non-rendezvous exit */
tor_assert(circ->package_window > 0);
circ->package_window--;
} else { /* we're an AP, or an exit on a rendezvous circ */
- tor_assert(conn->cpath_layer->package_window > 0);
- conn->cpath_layer->package_window--;
+ tor_assert(cpath_layer->package_window > 0);
+ cpath_layer->package_window--;
}
if (--conn->package_window <= 0) { /* is it 0 after decrement? */
connection_stop_reading(TO_CONN(conn));
log_debug(domain,"conn->package_window reached 0.");
- circuit_consider_stop_edge_reading(circ, conn->cpath_layer);
+ circuit_consider_stop_edge_reading(circ, cpath_layer);
return 0; /* don't process the inbuf any more */
}
log_debug(domain,"conn->package_window is now %d",conn->package_window);
@@ -1436,7 +1507,7 @@ connection_edge_consider_sending_sendme(edge_connection_t *conn)
}
while (conn->deliver_window <= STREAMWINDOW_START - STREAMWINDOW_INCREMENT) {
- log_debug(conn->cpath_layer?LD_APP:LD_EXIT,
+ log_debug(conn->_base.type == CONN_TYPE_AP ?LD_APP:LD_EXIT,
"Outbuf %d, Queuing stream sendme.",
(int)conn->_base.outbuf_flushlen);
conn->deliver_window += STREAMWINDOW_INCREMENT;
@@ -1532,7 +1603,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
if (!layer_hint || conn->cpath_layer == layer_hint) {
connection_start_reading(TO_CONN(conn));
- if (buf_datalen(conn->_base.inbuf) > 0)
+ if (connection_get_inbuf_len(TO_CONN(conn)) > 0)
++n_packaging_streams;
}
}
@@ -1543,7 +1614,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
if (!layer_hint || conn->cpath_layer == layer_hint) {
connection_start_reading(TO_CONN(conn));
- if (buf_datalen(conn->_base.inbuf) > 0)
+ if (connection_get_inbuf_len(TO_CONN(conn)) > 0)
++n_packaging_streams;
}
}
@@ -1582,7 +1653,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn,
}
/* If there's still data to read, we'll be coming back to this stream. */
- if (buf_datalen(conn->_base.inbuf))
+ if (connection_get_inbuf_len(TO_CONN(conn)))
++n_streams_left;
/* If the circuit won't accept any more data, return without looking
@@ -1638,9 +1709,10 @@ circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint)
if (layer_hint->package_window <= 0) {
log_debug(domain,"yes, at-origin. stopped.");
for (conn = TO_ORIGIN_CIRCUIT(circ)->p_streams; conn;
- conn=conn->next_stream)
+ conn=conn->next_stream) {
if (conn->cpath_layer == layer_hint)
connection_stop_reading(TO_CONN(conn));
+ }
return 1;
}
return 0;
@@ -1995,7 +2067,8 @@ static int ewma_enabled = 0;
/** Adjust the global cell scale factor based on <b>options</b> */
void
-cell_ewma_set_scale_factor(or_options_t *options, networkstatus_t *consensus)
+cell_ewma_set_scale_factor(const or_options_t *options,
+ const networkstatus_t *consensus)
{
int32_t halflife_ms;
double halflife;
@@ -2028,7 +2101,7 @@ cell_ewma_set_scale_factor(or_options_t *options, networkstatus_t *consensus)
ewma_enabled = 1;
log_info(LD_OR,
"Enabled cell_ewma algorithm because of value in %s; "
- "scale factor is %lf per %d seconds",
+ "scale factor is %f per %d seconds",
source, ewma_scale_factor, EWMA_TICK_LEN);
}
}
@@ -2246,7 +2319,7 @@ set_streams_blocked_on_circ(circuit_t *circ, or_connection_t *orconn,
edge->edge_blocked_on_circ = block;
}
- if (!conn->read_event) {
+ if (!conn->read_event && !HAS_BUFFEREVENT(conn)) {
/* This connection is a placeholder for something; probably a DNS
* request. It can't actually stop or start reading.*/
continue;
@@ -2321,13 +2394,13 @@ connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max,
/* Calculate the exact time that this cell has spent in the queue. */
if (get_options()->CellStatistics && !CIRCUIT_IS_ORIGIN(circ)) {
- struct timeval now;
+ struct timeval tvnow;
uint32_t flushed;
uint32_t cell_waiting_time;
insertion_time_queue_t *it_queue = queue->insertion_times;
- tor_gettimeofday_cached(&now);
- flushed = (uint32_t)((now.tv_sec % SECONDS_IN_A_DAY) * 100L +
- (uint32_t)now.tv_usec / (uint32_t)10000L);
+ tor_gettimeofday_cached(&tvnow);
+ flushed = (uint32_t)((tvnow.tv_sec % SECONDS_IN_A_DAY) * 100L +
+ (uint32_t)tvnow.tv_usec / (uint32_t)10000L);
if (!it_queue || !it_queue->first) {
log_info(LD_GENERAL, "Cannot determine insertion time of cell. "
"Looks like the CellStatistics option was "
@@ -2447,7 +2520,7 @@ append_cell_to_circuit_queue(circuit_t *circ, or_connection_t *orconn,
make_circuit_active_on_conn(circ, orconn);
}
- if (! buf_datalen(orconn->_base.outbuf)) {
+ if (! connection_get_outbuf_len(TO_CONN(orconn))) {
/* There is no data at all waiting to be sent on the outbuf. Add a
* cell, so that we can notice when it gets flushed, flushed_some can
* get called, and we can start putting more data onto the buffer then.
diff --git a/src/or/relay.h b/src/or/relay.h
index f64752da5..7fce8edca 100644
--- a/src/or/relay.h
+++ b/src/or/relay.h
@@ -60,8 +60,8 @@ const uint8_t *decode_address_from_payload(tor_addr_t *addr_out,
const uint8_t *payload,
int payload_len);
unsigned cell_ewma_get_tick(void);
-void cell_ewma_set_scale_factor(or_options_t *options,
- networkstatus_t *consensus);
+void cell_ewma_set_scale_factor(const or_options_t *options,
+ const networkstatus_t *consensus);
void circuit_clear_cell_queue(circuit_t *circ, or_connection_t *orconn);
void tor_gettimeofday_cache_clear(void);
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 533dfb8a9..47fda2317 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -16,6 +16,7 @@
#include "connection_edge.h"
#include "directory.h"
#include "main.h"
+#include "nodelist.h"
#include "relay.h"
#include "rendclient.h"
#include "rendcommon.h"
@@ -144,6 +145,8 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
tor_assert(rendcirc->rend_data);
tor_assert(!rend_cmp_service_ids(introcirc->rend_data->onion_address,
rendcirc->rend_data->onion_address));
+ tor_assert(!(introcirc->build_state->onehop_tunnel));
+ tor_assert(!(rendcirc->build_state->onehop_tunnel));
if (rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1,
&entry) < 1) {
@@ -334,6 +337,7 @@ rend_client_introduction_acked(origin_circuit_t *circ,
}
tor_assert(circ->build_state->chosen_exit);
+ tor_assert(!(circ->build_state->onehop_tunnel));
tor_assert(circ->rend_data);
if (request_len == 0) {
@@ -345,6 +349,7 @@ rend_client_introduction_acked(origin_circuit_t *circ,
rendcirc = circuit_get_by_rend_query_and_purpose(
circ->rend_data->onion_address, CIRCUIT_PURPOSE_C_REND_READY);
if (rendcirc) { /* remember the ack */
+ tor_assert(!(rendcirc->build_state->onehop_tunnel));
rendcirc->_base.purpose = CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED;
/* Set timestamp_dirty, because circuit_expire_building expects
* it to specify when a circuit entered the
@@ -366,8 +371,9 @@ rend_client_introduction_acked(origin_circuit_t *circ,
log_info(LD_REND, "Got nack for %s from %s...",
safe_str_client(circ->rend_data->onion_address),
safe_str_client(extend_info_describe(circ->build_state->chosen_exit)));
- if (rend_client_remove_intro_point(circ->build_state->chosen_exit,
- circ->rend_data) > 0) {
+ if (rend_client_report_intro_point_failure(circ->build_state->chosen_exit,
+ circ->rend_data,
+ INTRO_POINT_FAILURE_GENERIC)>0){
/* There are introduction points left. Re-extend the circuit to
* another intro point and try again. */
int result = rend_client_reextend_intro_circuit(circ);
@@ -384,9 +390,12 @@ rend_client_introduction_acked(origin_circuit_t *circ,
#define REND_HID_SERV_DIR_REQUERY_PERIOD (15 * 60)
/** Contains the last request times to hidden service directories for
- * certain queries; keys are strings consisting of base32-encoded
- * hidden service directory identities and base32-encoded descriptor IDs;
- * values are pointers to timestamps of the last requests. */
+ * certain queries; each key is a string consisting of the
+ * concatenation of a base32-encoded HS directory identity digest, a
+ * base32-encoded HS descriptor ID, and a hidden service address
+ * (without the ".onion" part); each value is a pointer to a time_t
+ * holding the time of the last request for that descriptor ID to that
+ * HS directory. */
static strmap_t *last_hid_serv_requests_ = NULL;
/** Returns last_hid_serv_requests_, initializing it to a new strmap if
@@ -399,23 +408,34 @@ get_last_hid_serv_requests(void)
return last_hid_serv_requests_;
}
+#define LAST_HID_SERV_REQUEST_KEY_LEN (REND_DESC_ID_V2_LEN_BASE32 + \
+ REND_DESC_ID_V2_LEN_BASE32 + \
+ REND_SERVICE_ID_LEN_BASE32)
+
/** Look up the last request time to hidden service directory <b>hs_dir</b>
- * for descriptor ID <b>desc_id_base32</b>. If <b>set</b> is non-zero,
+ * for descriptor ID <b>desc_id_base32</b> for the service specified in
+ * <b>rend_query</b>. If <b>set</b> is non-zero,
* assign the current time <b>now</b> and return that. Otherwise, return
* the most recent request time, or 0 if no such request has been sent
* before. */
static time_t
lookup_last_hid_serv_request(routerstatus_t *hs_dir,
- const char *desc_id_base32, time_t now, int set)
+ const char *desc_id_base32,
+ const rend_data_t *rend_query,
+ time_t now, int set)
{
char hsdir_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
- char hsdir_desc_comb_id[2 * REND_DESC_ID_V2_LEN_BASE32 + 1];
+ char hsdir_desc_comb_id[LAST_HID_SERV_REQUEST_KEY_LEN + 1];
time_t *last_request_ptr;
strmap_t *last_hid_serv_requests = get_last_hid_serv_requests();
base32_encode(hsdir_id_base32, sizeof(hsdir_id_base32),
hs_dir->identity_digest, DIGEST_LEN);
- tor_snprintf(hsdir_desc_comb_id, sizeof(hsdir_desc_comb_id), "%s%s",
- hsdir_id_base32, desc_id_base32);
+ tor_snprintf(hsdir_desc_comb_id, sizeof(hsdir_desc_comb_id), "%s%s%s",
+ hsdir_id_base32,
+ desc_id_base32,
+ rend_query->onion_address);
+ /* XXX023 tor_assert(strlen(hsdir_desc_comb_id) ==
+ LAST_HID_SERV_REQUEST_KEY_LEN); */
if (set) {
time_t *oldptr;
last_request_ptr = tor_malloc_zero(sizeof(time_t));
@@ -433,10 +453,10 @@ lookup_last_hid_serv_request(routerstatus_t *hs_dir,
* it does not contain requests older than REND_HID_SERV_DIR_REQUERY_PERIOD
* seconds any more. */
static void
-directory_clean_last_hid_serv_requests(void)
+directory_clean_last_hid_serv_requests(time_t now)
{
strmap_iter_t *iter;
- time_t cutoff = time(NULL) - REND_HID_SERV_DIR_REQUERY_PERIOD;
+ time_t cutoff = now - REND_HID_SERV_DIR_REQUERY_PERIOD;
strmap_t *last_hid_serv_requests = get_last_hid_serv_requests();
for (iter = strmap_iter_init(last_hid_serv_requests);
!strmap_iter_done(iter); ) {
@@ -454,6 +474,33 @@ directory_clean_last_hid_serv_requests(void)
}
}
+/** Remove all requests related to the hidden service named
+ * <b>onion_address</b> from the history of times of requests to
+ * hidden service directories. */
+static void
+purge_hid_serv_from_last_hid_serv_requests(const char *onion_address)
+{
+ strmap_iter_t *iter;
+ strmap_t *last_hid_serv_requests = get_last_hid_serv_requests();
+ /* XXX023 tor_assert(strlen(onion_address) == REND_SERVICE_ID_LEN_BASE32); */
+ for (iter = strmap_iter_init(last_hid_serv_requests);
+ !strmap_iter_done(iter); ) {
+ const char *key;
+ void *val;
+ strmap_iter_get(iter, &key, &val);
+ /* XXX023 tor_assert(strlen(key) == LAST_HID_SERV_REQUEST_KEY_LEN); */
+ if (tor_memeq(key + LAST_HID_SERV_REQUEST_KEY_LEN -
+ REND_SERVICE_ID_LEN_BASE32,
+ onion_address,
+ REND_SERVICE_ID_LEN_BASE32)) {
+ iter = strmap_iter_next_rmv(last_hid_serv_requests, iter);
+ tor_free(val);
+ } else {
+ iter = strmap_iter_next(last_hid_serv_requests, iter);
+ }
+ }
+}
+
/** Purge the history of request times to hidden service directories,
* so that future lookups of an HS descriptor will not fail because we
* accessed all of the HSDir relays responsible for the descriptor
@@ -475,12 +522,11 @@ rend_client_purge_last_hid_serv_requests(void)
}
/** Determine the responsible hidden service directories for <b>desc_id</b>
- * and fetch the descriptor belonging to that ID from one of them. Only
- * send a request to hidden service directories that we did not try within
- * the last REND_HID_SERV_DIR_REQUERY_PERIOD seconds; on success, return 1,
+ * and fetch the descriptor with that ID from one of them. Only
+ * send a request to a hidden service directory that we have not yet tried
+ * during this attempt to connect to this hidden service; on success, return 1,
* in the case that no hidden service directory is left to ask for the
- * descriptor, return 0, and in case of a failure -1. <b>query</b> is only
- * passed for pretty log statements. */
+ * descriptor, return 0, and in case of a failure -1. */
static int
directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query)
{
@@ -500,12 +546,16 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query)
/* Only select those hidden service directories to which we did not send
* a request recently and for which we have a router descriptor here. */
- directory_clean_last_hid_serv_requests(); /* Clean request history first. */
+
+ /* Clean request history first. */
+ directory_clean_last_hid_serv_requests(now);
SMARTLIST_FOREACH(responsible_dirs, routerstatus_t *, dir, {
- if (lookup_last_hid_serv_request(dir, desc_id_base32, 0, 0) +
- REND_HID_SERV_DIR_REQUERY_PERIOD >= now ||
- !router_get_by_digest(dir->identity_digest))
+ time_t last = lookup_last_hid_serv_request(
+ dir, desc_id_base32, rend_query, 0, 0);
+ const node_t *node = node_get_by_id(dir->identity_digest);
+ if (last + REND_HID_SERV_DIR_REQUERY_PERIOD >= now ||
+ !node || !node_has_descriptor(node))
SMARTLIST_DEL_CURRENT(responsible_dirs, dir);
});
@@ -518,9 +568,9 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query)
return 0;
}
- /* Remember, that we are requesting a descriptor from this hidden service
+ /* Remember that we are requesting a descriptor from this hidden service
* directory now. */
- lookup_last_hid_serv_request(hs_dir, desc_id_base32, now, 1);
+ lookup_last_hid_serv_request(hs_dir, desc_id_base32, rend_query, now, 1);
/* Encode descriptor cookie for logging purposes. */
if (rend_query->auth_type != REND_NO_AUTH) {
@@ -574,10 +624,11 @@ rend_client_refetch_v2_renddesc(const rend_data_t *rend_query)
"service descriptor, but are not fetching service descriptors.");
return;
}
- /* Before fetching, check if we already have the descriptor here. */
- if (rend_cache_lookup_entry(rend_query->onion_address, -1, &e) > 0) {
+ /* Before fetching, check if we already have a usable descriptor here. */
+ if (rend_cache_lookup_entry(rend_query->onion_address, -1, &e) > 0 &&
+ rend_client_any_intro_points_usable(e)) {
log_info(LD_REND, "We would fetch a v2 rendezvous descriptor, but we "
- "already have that descriptor here. Not fetching.");
+ "already have a usable descriptor here. Not fetching.");
return;
}
log_debug(LD_REND, "Fetching v2 rendezvous descriptor for service %s",
@@ -647,16 +698,31 @@ rend_client_cancel_descriptor_fetches(void)
} SMARTLIST_FOREACH_END(conn);
}
-/** Remove failed_intro from ent. If ent now has no intro points, or
- * service is unrecognized, then launch a new renddesc fetch.
-
+/** Mark <b>failed_intro</b> as a failed introduction point for the
+ * hidden service specified by <b>rend_query</b>. If the HS now has no
+ * usable intro points, or we do not have an HS descriptor for it,
+ * then launch a new renddesc fetch.
*
- * Return -1 if error, 0 if no intro points remain or service
+ * If <b>failure_type</b> is INTRO_POINT_FAILURE_GENERIC, remove the
+ * intro point from (our parsed copy of) the HS descriptor.
+ *
+ * If <b>failure_type</b> is INTRO_POINT_FAILURE_TIMEOUT, mark the
+ * intro point as 'timed out'; it will not be retried until the
+ * current hidden service connection attempt has ended or it has
+ * appeared in a newly fetched rendezvous descriptor.
+ *
+ * If <b>failure_type</b> is INTRO_POINT_FAILURE_UNREACHABLE,
+ * increment the intro point's reachability-failure count; if it has
+ * now failed MAX_INTRO_POINT_REACHABILITY_FAILURES or more times,
+ * remove the intro point from (our parsed copy of) the HS descriptor.
+ *
+ * Return -1 if error, 0 if no usable intro points remain or service
* unrecognized, 1 if recognized and some intro points remain.
*/
int
-rend_client_remove_intro_point(extend_info_t *failed_intro,
- const rend_data_t *rend_query)
+rend_client_report_intro_point_failure(extend_info_t *failed_intro,
+ const rend_data_t *rend_query,
+ unsigned int failure_type)
{
int i, r;
rend_cache_entry_t *ent;
@@ -679,8 +745,34 @@ rend_client_remove_intro_point(extend_info_t *failed_intro,
rend_intro_point_t *intro = smartlist_get(ent->parsed->intro_nodes, i);
if (tor_memeq(failed_intro->identity_digest,
intro->extend_info->identity_digest, DIGEST_LEN)) {
- rend_intro_point_free(intro);
- smartlist_del(ent->parsed->intro_nodes, i);
+ switch (failure_type) {
+ default:
+ log_warn(LD_BUG, "Unknown failure type %u. Removing intro point.",
+ failure_type);
+ tor_fragile_assert();
+ /* fall through */
+ case INTRO_POINT_FAILURE_GENERIC:
+ rend_intro_point_free(intro);
+ smartlist_del(ent->parsed->intro_nodes, i);
+ break;
+ case INTRO_POINT_FAILURE_TIMEOUT:
+ intro->timed_out = 1;
+ break;
+ case INTRO_POINT_FAILURE_UNREACHABLE:
+ ++(intro->unreachable_count);
+ {
+ int zap_intro_point =
+ intro->unreachable_count >= MAX_INTRO_POINT_REACHABILITY_FAILURES;
+ log_info(LD_REND, "Failed to reach this intro point %u times.%s",
+ intro->unreachable_count,
+ zap_intro_point ? " Removing from descriptor.": "");
+ if (zap_intro_point) {
+ rend_intro_point_free(intro);
+ smartlist_del(ent->parsed->intro_nodes, i);
+ }
+ }
+ break;
+ }
break;
}
}
@@ -816,40 +908,42 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request,
void
rend_client_desc_trynow(const char *query)
{
- edge_connection_t *conn;
+ entry_connection_t *conn;
rend_cache_entry_t *entry;
+ const rend_data_t *rend_data;
time_t now = time(NULL);
smartlist_t *conns = get_connection_array();
- SMARTLIST_FOREACH_BEGIN(conns, connection_t *, _conn) {
- if (_conn->type != CONN_TYPE_AP ||
- _conn->state != AP_CONN_STATE_RENDDESC_WAIT ||
- _conn->marked_for_close)
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) {
+ if (base_conn->type != CONN_TYPE_AP ||
+ base_conn->state != AP_CONN_STATE_RENDDESC_WAIT ||
+ base_conn->marked_for_close)
continue;
- conn = TO_EDGE_CONN(_conn);
- if (!conn->rend_data)
+ conn = TO_ENTRY_CONN(base_conn);
+ rend_data = ENTRY_TO_EDGE_CONN(conn)->rend_data;
+ if (!rend_data)
continue;
- if (rend_cmp_service_ids(query, conn->rend_data->onion_address))
+ if (rend_cmp_service_ids(query, rend_data->onion_address))
continue;
- assert_connection_ok(TO_CONN(conn), now);
- if (rend_cache_lookup_entry(conn->rend_data->onion_address, -1,
+ assert_connection_ok(base_conn, now);
+ if (rend_cache_lookup_entry(rend_data->onion_address, -1,
&entry) == 1 &&
rend_client_any_intro_points_usable(entry)) {
/* either this fetch worked, or it failed but there was a
* valid entry from before which we should reuse */
log_info(LD_REND,"Rend desc is usable. Launching circuits.");
- conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT;
+ base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
/* restart their timeout values, so they get a fair shake at
* connecting to the hidden service. */
- conn->_base.timestamp_created = now;
- conn->_base.timestamp_lastread = now;
- conn->_base.timestamp_lastwritten = now;
+ base_conn->timestamp_created = now;
+ base_conn->timestamp_lastread = now;
+ base_conn->timestamp_lastwritten = now;
if (connection_ap_handshake_attach_circuit(conn) < 0) {
/* it will never work */
log_warn(LD_REND,"Rendezvous attempt failed. Closing.");
- if (!conn->_base.marked_for_close)
+ if (!base_conn->marked_for_close)
connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH);
}
} else { /* 404, or fetch didn't get that far */
@@ -857,8 +951,34 @@ rend_client_desc_trynow(const char *query)
"unavailable (try again later).",
safe_str_client(query));
connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED);
+ rend_client_note_connection_attempt_ended(query);
}
- } SMARTLIST_FOREACH_END(_conn);
+ } SMARTLIST_FOREACH_END(base_conn);
+}
+
+/** Clear temporary state used only during an attempt to connect to
+ * the hidden service named <b>onion_address</b>. Called when a
+ * connection attempt has ended; may be called occasionally at other
+ * times, and should be reasonably harmless. */
+void
+rend_client_note_connection_attempt_ended(const char *onion_address)
+{
+ rend_cache_entry_t *cache_entry = NULL;
+ rend_cache_lookup_entry(onion_address, -1, &cache_entry);
+
+ log_info(LD_REND, "Connection attempt for %s has ended; "
+ "cleaning up temporary state.",
+ safe_str_client(onion_address));
+
+ /* Clear the timed_out flag on all remaining intro points for this HS. */
+ if (cache_entry != NULL) {
+ SMARTLIST_FOREACH(cache_entry->parsed->intro_nodes,
+ rend_intro_point_t *, ip,
+ ip->timed_out = 0; );
+ }
+
+ /* Remove the HS's entries in last_hid_serv_requests. */
+ purge_hid_serv_from_last_hid_serv_requests(onion_address);
}
/** Return a newly allocated extend_info_t* for a randomly chosen introduction
@@ -900,8 +1020,7 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry,
int i;
rend_intro_point_t *intro;
- routerinfo_t *router;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
smartlist_t *usable_nodes;
int n_excluded = 0;
@@ -910,6 +1029,13 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry,
usable_nodes = smartlist_create();
smartlist_add_all(usable_nodes, entry->parsed->intro_nodes);
+ /* Remove the intro points that have timed out during this HS
+ * connection attempt from our list of usable nodes. */
+ SMARTLIST_FOREACH(usable_nodes, rend_intro_point_t *, ip,
+ if (ip->timed_out) {
+ SMARTLIST_DEL_CURRENT(usable_nodes, ip);
+ });
+
again:
if (smartlist_len(usable_nodes) == 0) {
if (n_excluded && get_options()->StrictNodes && warnings) {
@@ -927,21 +1053,22 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry,
intro = smartlist_get(usable_nodes, i);
/* Do we need to look up the router or is the extend info complete? */
if (!intro->extend_info->onion_key) {
+ const node_t *node;
if (tor_digest_is_zero(intro->extend_info->identity_digest))
- router = router_get_by_hexdigest(intro->extend_info->nickname);
+ node = node_get_by_hex_id(intro->extend_info->nickname);
else
- router = router_get_by_digest(intro->extend_info->identity_digest);
- if (!router) {
+ node = node_get_by_id(intro->extend_info->identity_digest);
+ if (!node) {
log_info(LD_REND, "Unknown router with nickname '%s'; trying another.",
intro->extend_info->nickname);
smartlist_del(usable_nodes, i);
goto again;
}
extend_info_free(intro->extend_info);
- intro->extend_info = extend_info_from_router(router);
+ intro->extend_info = extend_info_from_node(node);
}
/* Check if we should refuse to talk to this router. */
- if (options->ExcludeNodes && strict &&
+ if (strict &&
routerset_contains_extendinfo(options->ExcludeNodes,
intro->extend_info)) {
n_excluded++;
@@ -1007,7 +1134,8 @@ rend_service_authorization_free_all(void)
* service and add it to the local map of hidden service authorizations.
* Return 0 for success and -1 for failure. */
int
-rend_parse_service_authorization(or_options_t *options, int validate_only)
+rend_parse_service_authorization(const or_options_t *options,
+ int validate_only)
{
config_line_t *line;
int res = -1;
diff --git a/src/or/rendclient.h b/src/or/rendclient.h
index c6cf82b3d..89da47789 100644
--- a/src/or/rendclient.h
+++ b/src/or/rendclient.h
@@ -22,8 +22,15 @@ int rend_client_introduction_acked(origin_circuit_t *circ,
void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query);
void rend_client_cancel_descriptor_fetches(void);
void rend_client_purge_last_hid_serv_requests(void);
-int rend_client_remove_intro_point(extend_info_t *failed_intro,
- const rend_data_t *rend_query);
+
+#define INTRO_POINT_FAILURE_GENERIC 0
+#define INTRO_POINT_FAILURE_TIMEOUT 1
+#define INTRO_POINT_FAILURE_UNREACHABLE 2
+
+int rend_client_report_intro_point_failure(extend_info_t *failed_intro,
+ const rend_data_t *rend_query,
+ unsigned int failure_type);
+
int rend_client_rendezvous_acked(origin_circuit_t *circ,
const uint8_t *request,
size_t request_len);
@@ -32,12 +39,14 @@ int rend_client_receive_rendezvous(origin_circuit_t *circ,
size_t request_len);
void rend_client_desc_trynow(const char *query);
+void rend_client_note_connection_attempt_ended(const char *onion_address);
+
extend_info_t *rend_client_get_random_intro(const rend_data_t *rend_query);
int rend_client_any_intro_points_usable(const rend_cache_entry_t *entry);
int rend_client_send_introduction(origin_circuit_t *introcirc,
origin_circuit_t *rendcirc);
-int rend_parse_service_authorization(or_options_t *options,
+int rend_parse_service_authorization(const or_options_t *options,
int validate_only);
rend_service_authorization_t *rend_client_lookup_service_authorization(
const char *onion_address);
diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c
index c5bf88163..94bb00221 100644
--- a/src/or/rendcommon.c
+++ b/src/or/rendcommon.c
@@ -814,14 +814,13 @@ rend_cache_free_all(void)
/** Removes all old entries from the service descriptor cache.
*/
void
-rend_cache_clean(void)
+rend_cache_clean(time_t now)
{
strmap_iter_t *iter;
const char *key;
void *val;
rend_cache_entry_t *ent;
- time_t cutoff;
- cutoff = time(NULL) - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW;
+ time_t cutoff = now - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW;
for (iter = strmap_iter_init(rend_cache); !strmap_iter_done(iter); ) {
strmap_iter_get(iter, &key, &val);
ent = (rend_cache_entry_t*)val;
@@ -849,10 +848,10 @@ rend_cache_purge(void)
/** Remove all old v2 descriptors and those for which this hidden service
* directory is not responsible for any more. */
void
-rend_cache_clean_v2_descs_as_dir(void)
+rend_cache_clean_v2_descs_as_dir(time_t now)
{
digestmap_iter_t *iter;
- time_t cutoff = time(NULL) - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW;
+ time_t cutoff = now - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW;
for (iter = digestmap_iter_init(rend_cache_v2_dir);
!digestmap_iter_done(iter); ) {
const char *key;
diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h
index c51039f1f..0d64466db 100644
--- a/src/or/rendcommon.h
+++ b/src/or/rendcommon.h
@@ -34,8 +34,8 @@ void rend_encoded_v2_service_descriptor_free(
void rend_intro_point_free(rend_intro_point_t *intro);
void rend_cache_init(void);
-void rend_cache_clean(void);
-void rend_cache_clean_v2_descs_as_dir(void);
+void rend_cache_clean(time_t now);
+void rend_cache_clean_v2_descs_as_dir(time_t now);
void rend_cache_purge(void);
void rend_cache_free_all(void);
int rend_valid_service_id(const char *query);
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 8a0171170..440359a32 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -14,6 +14,7 @@
#include "config.h"
#include "directory.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "rendclient.h"
#include "rendcommon.h"
#include "rendservice.h"
@@ -291,7 +292,7 @@ parse_port_config(const char *string)
* normal, but don't actually change the configured services.)
*/
int
-rend_config_services(or_options_t *options, int validate_only)
+rend_config_services(const or_options_t *options, int validate_only)
{
config_line_t *line;
rend_service_t *service = NULL;
@@ -409,7 +410,7 @@ rend_config_services(or_options_t *options, int validate_only)
if (strspn(client_name, REND_LEGAL_CLIENTNAME_CHARACTERS) != len) {
log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains an "
"illegal client name: '%s'. Valid "
- "characters are [A-Za-z0-9+-_].",
+ "characters are [A-Za-z0-9+_-].",
client_name);
SMARTLIST_FOREACH(clients, char *, cp, tor_free(cp));
smartlist_free(clients);
@@ -904,8 +905,9 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
time_t now = time(NULL);
char diffie_hellman_hash[DIGEST_LEN];
time_t *access_time;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
+ tor_assert(!(circuit->build_state->onehop_tunnel));
tor_assert(circuit->rend_data);
base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
@@ -956,6 +958,29 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
"PK-encrypted portion of INTRODUCE2 cell was truncated.");
return -1;
}
+
+ if (!service->accepted_intros)
+ service->accepted_intros = digestmap_new();
+
+ {
+ char pkpart_digest[DIGEST_LEN];
+ /* Check for replay of PK-encrypted portion. It is slightly naughty to
+ use the same digestmap to check for this and for g^x replays, but
+ collisions are tremendously unlikely.
+ */
+ crypto_digest(pkpart_digest, (char*)request+DIGEST_LEN, keylen);
+ access_time = digestmap_get(service->accepted_intros, pkpart_digest);
+ if (access_time != NULL) {
+ log_warn(LD_REND, "Possible replay detected! We received an "
+ "INTRODUCE2 cell with same PK-encrypted part %d seconds ago. "
+ "Dropping cell.", (int)(now-*access_time));
+ return -1;
+ }
+ access_time = tor_malloc(sizeof(time_t));
+ *access_time = now;
+ digestmap_set(service->accepted_intros, pkpart_digest, access_time);
+ }
+
/* Next N bytes is encrypted with service key */
note_crypto_pk_op(REND_SERVER);
r = crypto_pk_private_hybrid_decrypt(
@@ -996,7 +1021,9 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
v3_shift += 4;
if ((now - ts) < -1 * REND_REPLAY_TIME_INTERVAL / 2 ||
(now - ts) > REND_REPLAY_TIME_INTERVAL / 2) {
- log_warn(LD_REND, "INTRODUCE2 cell is too %s. Discarding.",
+ /* This is far more likely to mean that a client's clock is
+ * skewed than that a replay attack is in progress. */
+ log_info(LD_REND, "INTRODUCE2 cell is too %s. Discarding.",
(now - ts) < 0 ? "old" : "new");
return -1;
}
@@ -1033,7 +1060,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
} else {
char *rp_nickname;
size_t nickname_field_len;
- routerinfo_t *router;
+ const node_t *node;
int version;
if (*buf == 1) {
rp_nickname = buf+1;
@@ -1060,8 +1087,8 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
len -= nickname_field_len;
len -= rp_nickname - buf; /* also remove header space used by version, if
* any */
- router = router_get_by_nickname(rp_nickname, 0);
- if (!router) {
+ node = node_get_by_nickname(rp_nickname, 0);
+ if (!node) {
log_info(LD_REND, "Couldn't find router %s named in introduce2 cell.",
escaped_safe_str_client(rp_nickname));
/* XXXX Add a no-such-router reason? */
@@ -1069,7 +1096,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
goto err;
}
- extend_info = extend_info_from_router(router);
+ extend_info = extend_info_from_node(node);
}
if (len != REND_COOKIE_LEN+DH_KEY_LEN) {
@@ -1079,7 +1106,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
}
/* Check if we'd refuse to talk to this router */
- if (options->ExcludeNodes && options->StrictNodes &&
+ if (options->StrictNodes &&
routerset_contains_extendinfo(options->ExcludeNodes, extend_info)) {
log_warn(LD_REND, "Client asked to rendezvous at a relay that we "
"exclude, and StrictNodes is set. Refusing service.");
@@ -1098,12 +1125,16 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
/* Check whether there is a past request with the same Diffie-Hellman,
* part 1. */
- if (!service->accepted_intros)
- service->accepted_intros = digestmap_new();
-
access_time = digestmap_get(service->accepted_intros, diffie_hellman_hash);
if (access_time != NULL) {
- log_warn(LD_REND, "Possible replay detected! We received an "
+ /* A Tor client will send a new INTRODUCE1 cell with the same rend
+ * cookie and DH public key as its previous one if its intro circ
+ * times out while in state CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT .
+ * If we received the first INTRODUCE1 cell (the intro-point relay
+ * converts it into an INTRODUCE2 cell), we are already trying to
+ * connect to that rend point (and may have already succeeded);
+ * drop this cell. */
+ log_info(LD_REND, "We received an "
"INTRODUCE2 cell with same first part of "
"Diffie-Hellman handshake %d seconds ago. Dropping "
"cell.",
@@ -1360,6 +1391,7 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
crypto_pk_env_t *intro_key;
tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO);
+ tor_assert(!(circuit->build_state->onehop_tunnel));
tor_assert(circuit->cpath);
tor_assert(circuit->rend_data);
@@ -1378,7 +1410,7 @@ rend_service_intro_has_opened(origin_circuit_t *circuit)
/* If we already have enough introduction circuits for this service,
* redefine this one as a general circuit or close it, depending. */
if (count_established_intro_points(serviceid) > NUM_INTRO_POINTS) {
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->ExcludeNodes) {
/* XXXX in some future version, we can test whether the transition is
allowed or not given the actual nodes in the circuit. But for now,
@@ -1502,6 +1534,7 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
tor_assert(circuit->_base.purpose == CIRCUIT_PURPOSE_S_CONNECT_REND);
tor_assert(circuit->cpath);
tor_assert(circuit->build_state);
+ tor_assert(!(circuit->build_state->onehop_tunnel));
tor_assert(circuit->rend_data);
hop = circuit->build_state->pending_final_cpath;
tor_assert(hop);
@@ -1630,12 +1663,14 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc,
for (j = 0; j < smartlist_len(responsible_dirs); j++) {
char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
char *hs_dir_ip;
+ const node_t *node;
hs_dir = smartlist_get(responsible_dirs, j);
if (smartlist_digest_isin(renddesc->successful_uploads,
hs_dir->identity_digest))
/* Don't upload descriptor if we succeeded in doing so last time. */
continue;
- if (!router_get_by_digest(hs_dir->identity_digest)) {
+ node = node_get_by_id(hs_dir->identity_digest);
+ if (!node || !node_has_descriptor(node)) {
log_info(LD_REND, "Not sending publish request for v2 descriptor to "
"hidden service directory %s; we don't have its "
"router descriptor. Queuing for later upload.",
@@ -1812,19 +1847,19 @@ void
rend_services_introduce(void)
{
int i,j,r;
- routerinfo_t *router;
+ const node_t *node;
rend_service_t *service;
rend_intro_point_t *intro;
int changed, prev_intro_nodes;
- smartlist_t *intro_routers;
+ smartlist_t *intro_nodes;
time_t now;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
- intro_routers = smartlist_create();
+ intro_nodes = smartlist_create();
now = time(NULL);
for (i=0; i < smartlist_len(rend_service_list); ++i) {
- smartlist_clear(intro_routers);
+ smartlist_clear(intro_nodes);
service = smartlist_get(rend_service_list, i);
tor_assert(service);
@@ -1844,8 +1879,8 @@ rend_services_introduce(void)
service. */
for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
intro = smartlist_get(service->intro_nodes, j);
- router = router_get_by_digest(intro->extend_info->identity_digest);
- if (!router || !find_intro_circuit(intro, service->pk_digest)) {
+ node = node_get_by_id(intro->extend_info->identity_digest);
+ if (!node || !find_intro_circuit(intro, service->pk_digest)) {
log_info(LD_REND,"Giving up on %s as intro point for %s.",
safe_str_client(extend_info_describe(intro->extend_info)),
safe_str_client(service->service_id));
@@ -1865,8 +1900,8 @@ rend_services_introduce(void)
smartlist_del(service->intro_nodes,j--);
changed = 1;
}
- if (router)
- smartlist_add(intro_routers, router);
+ if (node)
+ smartlist_add(intro_nodes, (void*)node);
}
/* We have enough intro points, and the intro points we thought we had were
@@ -1895,26 +1930,26 @@ rend_services_introduce(void)
#define NUM_INTRO_POINTS_INIT (NUM_INTRO_POINTS + 2)
for (j=prev_intro_nodes; j < (prev_intro_nodes == 0 ?
NUM_INTRO_POINTS_INIT : NUM_INTRO_POINTS); ++j) {
- router_crn_flags_t flags = CRN_NEED_UPTIME;
+ router_crn_flags_t flags = CRN_NEED_UPTIME|CRN_NEED_DESC;
if (get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION)
flags |= CRN_ALLOW_INVALID;
- router = router_choose_random_node(intro_routers,
- options->ExcludeNodes, flags);
- if (!router) {
+ node = router_choose_random_node(intro_nodes,
+ options->ExcludeNodes, flags);
+ if (!node) {
log_warn(LD_REND,
"Could only establish %d introduction points for %s.",
smartlist_len(service->intro_nodes), service->service_id);
break;
}
changed = 1;
- smartlist_add(intro_routers, router);
+ smartlist_add(intro_nodes, (void*)node);
intro = tor_malloc_zero(sizeof(rend_intro_point_t));
- intro->extend_info = extend_info_from_router(router);
+ intro->extend_info = extend_info_from_node(node);
intro->intro_key = crypto_new_pk_env();
tor_assert(!crypto_pk_generate_key(intro->intro_key));
smartlist_add(service->intro_nodes, intro);
log_info(LD_REND, "Picked router %s as an intro point for %s.",
- safe_str_client(router_describe(router)),
+ safe_str_client(node_describe(node)),
safe_str_client(service->service_id));
}
@@ -1933,7 +1968,7 @@ rend_services_introduce(void)
}
}
}
- smartlist_free(intro_routers);
+ smartlist_free(intro_nodes);
}
/** Regenerate and upload rendezvous service descriptors for all
diff --git a/src/or/rendservice.h b/src/or/rendservice.h
index 70389afe9..8a2994c4c 100644
--- a/src/or/rendservice.h
+++ b/src/or/rendservice.h
@@ -13,7 +13,7 @@
#define _TOR_RENDSERVICE_H
int num_rend_services(void);
-int rend_config_services(or_options_t *options, int validate_only);
+int rend_config_services(const or_options_t *options, int validate_only);
int rend_service_load_keys(void);
void rend_services_introduce(void);
void rend_consider_services_upload(time_t now);
diff --git a/src/or/rephist.c b/src/or/rephist.c
index 24447004e..de4a1ef43 100644
--- a/src/or/rephist.c
+++ b/src/or/rephist.c
@@ -7,7 +7,7 @@
* \brief Basic history and "reputation" functionality to remember
* which servers have worked in the past, how much bandwidth we've
* been using, which ports we tend to want, and so on; further,
- * exit port statistics and cell statistics.
+ * exit port statistics, cell statistics, and connection statistics.
**/
#include "or.h"
@@ -15,6 +15,7 @@
#include "circuituse.h"
#include "config.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "rephist.h"
#include "router.h"
#include "routerlist.h"
@@ -445,7 +446,7 @@ rep_hist_downrate_old_runs(time_t now)
alpha *= STABILITY_ALPHA;
}
- log_info(LD_HIST, "Discounting all old stability info by a factor of %lf",
+ log_info(LD_HIST, "Discounting all old stability info by a factor of %f",
alpha);
/* Multiply every w_r_l, t_r_w pair by alpha. */
@@ -643,7 +644,7 @@ rep_hist_dump_stats(time_t now, int severity)
size_t len;
int ret;
unsigned long upt, downt;
- routerinfo_t *r;
+ const node_t *node;
rep_history_clean(now - get_options()->RephistTrackTime);
@@ -657,8 +658,8 @@ rep_hist_dump_stats(time_t now, int severity)
digestmap_iter_get(orhist_it, &digest1, &or_history_p);
or_history = (or_history_t*) or_history_p;
- if ((r = router_get_by_digest(digest1)))
- name1 = r->nickname;
+ if ((node = node_get_by_id(digest1)) && node_get_nickname(node))
+ name1 = node_get_nickname(node);
else
name1 = "(unknown)";
base16_encode(hexdigest1, sizeof(hexdigest1), digest1, DIGEST_LEN);
@@ -688,8 +689,8 @@ rep_hist_dump_stats(time_t now, int severity)
lhist_it = digestmap_iter_next(or_history->link_history_map,
lhist_it)) {
digestmap_iter_get(lhist_it, &digest2, &link_history_p);
- if ((r = router_get_by_digest(digest2)))
- name2 = r->nickname;
+ if ((node = node_get_by_id(digest2)) && node_get_nickname(node))
+ name2 = node_get_nickname(node);
else
name2 = "(unknown)";
@@ -823,7 +824,7 @@ rep_hist_record_mtbf_data(time_t now, int missing_means_down)
base16_encode(dbuf, sizeof(dbuf), digest, DIGEST_LEN);
if (missing_means_down && hist->start_of_run &&
- !router_get_by_digest(digest)) {
+ !router_get_by_id_digest(digest)) {
/* We think this relay is running, but it's not listed in our
* routerlist. Somehow it fell out without telling us it went
* down. Complain and also correct it. */
@@ -893,7 +894,7 @@ rep_hist_format_router_status(or_history_t *hist, time_t now)
" weighted-uptime %lu\n"
"mtbf %0.1lf\n"
" weighted-run-length %lu\n"
- " total-run-weights %lf\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,
@@ -938,28 +939,32 @@ rep_hist_get_router_stability_doc(time_t now)
}
DIGESTMAP_FOREACH(history_map, id, or_history_t *, hist) {
- routerinfo_t *ri;
+ const node_t *node;
char dbuf[BASE64_DIGEST_LEN+1];
char header_buf[512];
char *info;
digest_to_base64(dbuf, id);
- ri = router_get_by_digest(id);
- if (ri) {
- char *ip = tor_dup_ip(ri->addr);
+ node = node_get_by_id(id);
+ if (node) {
+ char ip[INET_NTOA_BUF_LEN+1];
char tbuf[ISO_TIME_LEN+1];
- format_iso_time(tbuf, ri->cache_info.published_on);
+ 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));
tor_snprintf(header_buf, sizeof(header_buf),
"router %s %s %s\n"
"published %s\n"
"relevant-flags %s%s%s\n"
"declared-uptime %ld\n",
- dbuf, ri->nickname, ip,
+ dbuf, node_get_nickname(node), ip,
tbuf,
- ri->is_running ? "Running " : "",
- ri->is_valid ? "Valid " : "",
- ri->is_hibernating ? "Hibernating " : "",
- ri->uptime);
- tor_free(ip);
+ node->is_running ? "Running " : "",
+ node->is_valid ? "Valid " : "",
+ node->ri && node->ri->is_hibernating ? "Hibernating " : "",
+ node_get_declared_uptime(node));
} else {
tor_snprintf(header_buf, sizeof(header_buf),
"router %s {no descriptor}\n", dbuf);
@@ -1474,7 +1479,7 @@ rep_hist_fill_bandwidth_history(char *buf, size_t len, const bw_array_t *b)
{
char *cp = buf;
int i, n;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
uint64_t cutoff;
if (b->num_maxes_set <= b->next_max_idx) {
@@ -1770,10 +1775,13 @@ rep_hist_load_state(or_state_t *state, char **err)
/*********************************************************************/
+typedef struct predicted_port_t {
+ uint16_t port;
+ time_t time;
+} predicted_port_t;
+
/** A list of port numbers that have been used recently. */
static smartlist_t *predicted_ports_list=NULL;
-/** The corresponding most recently used time for each port. */
-static smartlist_t *predicted_ports_times=NULL;
/** We just got an application request for a connection with
* port <b>port</b>. Remember it for the future, so we can keep
@@ -1782,14 +1790,11 @@ static smartlist_t *predicted_ports_times=NULL;
static void
add_predicted_port(time_t now, uint16_t port)
{
- /* XXXX we could just use uintptr_t here, I think. -NM */
- uint16_t *tmp_port = tor_malloc(sizeof(uint16_t));
- time_t *tmp_time = tor_malloc(sizeof(time_t));
- *tmp_port = port;
- *tmp_time = now;
- rephist_total_alloc += sizeof(uint16_t) + sizeof(time_t);
- smartlist_add(predicted_ports_list, tmp_port);
- smartlist_add(predicted_ports_times, tmp_time);
+ predicted_port_t *pp = tor_malloc(sizeof(predicted_port_t));
+ pp->port = port;
+ pp->time = now;
+ rephist_total_alloc += sizeof(*pp);
+ smartlist_add(predicted_ports_list, pp);
}
/** Initialize whatever memory and structs are needed for predicting
@@ -1800,7 +1805,6 @@ static void
predicted_ports_init(void)
{
predicted_ports_list = smartlist_create();
- predicted_ports_times = smartlist_create();
add_predicted_port(time(NULL), 80); /* add one to kickstart us */
}
@@ -1810,12 +1814,11 @@ predicted_ports_init(void)
static void
predicted_ports_free(void)
{
- rephist_total_alloc -= smartlist_len(predicted_ports_list)*sizeof(uint16_t);
- SMARTLIST_FOREACH(predicted_ports_list, char *, cp, tor_free(cp));
+ rephist_total_alloc -=
+ smartlist_len(predicted_ports_list)*sizeof(predicted_port_t);
+ SMARTLIST_FOREACH(predicted_ports_list, predicted_port_t *,
+ pp, tor_free(pp));
smartlist_free(predicted_ports_list);
- rephist_total_alloc -= smartlist_len(predicted_ports_times)*sizeof(time_t);
- SMARTLIST_FOREACH(predicted_ports_times, char *, cp, tor_free(cp));
- smartlist_free(predicted_ports_times);
}
/** Remember that <b>port</b> has been asked for as of time <b>now</b>.
@@ -1825,24 +1828,17 @@ predicted_ports_free(void)
void
rep_hist_note_used_port(time_t now, uint16_t port)
{
- int i;
- uint16_t *tmp_port;
- time_t *tmp_time;
-
tor_assert(predicted_ports_list);
- tor_assert(predicted_ports_times);
if (!port) /* record nothing */
return;
- for (i = 0; i < smartlist_len(predicted_ports_list); ++i) {
- tmp_port = smartlist_get(predicted_ports_list, i);
- tmp_time = smartlist_get(predicted_ports_times, i);
- if (*tmp_port == port) {
- *tmp_time = now;
+ SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
+ if (pp->port == port) {
+ pp->time = now;
return;
}
- }
+ } SMARTLIST_FOREACH_END(pp);
/* it's not there yet; we need to add it */
add_predicted_port(now, port);
}
@@ -1851,36 +1847,28 @@ rep_hist_note_used_port(time_t now, uint16_t port)
* we'll want to make connections to the same port in the future. */
#define PREDICTED_CIRCS_RELEVANCE_TIME (60*60)
-/** Return a pointer to the list of port numbers that
+/** Return a newly allocated pointer to a list of uint16_t * for ports that
* are likely to be asked for in the near future.
- *
- * The caller promises not to mess with it.
*/
smartlist_t *
rep_hist_get_predicted_ports(time_t now)
{
- int i;
- uint16_t *tmp_port;
- time_t *tmp_time;
-
+ smartlist_t *out = smartlist_create();
tor_assert(predicted_ports_list);
- tor_assert(predicted_ports_times);
/* clean out obsolete entries */
- for (i = 0; i < smartlist_len(predicted_ports_list); ++i) {
- tmp_time = smartlist_get(predicted_ports_times, i);
- if (*tmp_time + PREDICTED_CIRCS_RELEVANCE_TIME < now) {
- tmp_port = smartlist_get(predicted_ports_list, i);
- log_debug(LD_CIRC, "Expiring predicted port %d", *tmp_port);
- smartlist_del(predicted_ports_list, i);
- smartlist_del(predicted_ports_times, i);
- rephist_total_alloc -= sizeof(uint16_t)+sizeof(time_t);
- tor_free(tmp_port);
- tor_free(tmp_time);
- i--;
+ SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) {
+ if (pp->time + PREDICTED_CIRCS_RELEVANCE_TIME < now) {
+ log_debug(LD_CIRC, "Expiring predicted port %d", pp->port);
+
+ rephist_total_alloc -= sizeof(predicted_port_t);
+ tor_free(pp);
+ SMARTLIST_DEL_CURRENT(predicted_ports_list, pp);
+ } else {
+ smartlist_add(out, tor_memdup(&pp->port, sizeof(uint16_t)));
}
- }
- return predicted_ports_list;
+ } SMARTLIST_FOREACH_END(pp);
+ return out;
}
/** The user asked us to do a resolve. Rather than keeping track of
@@ -2116,7 +2104,9 @@ rep_hist_exit_stats_term(void)
tor_free(exit_streams);
}
-/** Helper for qsort: compare two ints. */
+/** Helper for qsort: compare two ints. Does not handle overflow properly,
+ * but works fine for sorting an array of port numbers, which is what we use
+ * it for. */
static int
_compare_int(const void *x, const void *y)
{
@@ -2374,41 +2364,60 @@ typedef struct circ_buffer_stats_t {
/** List of circ_buffer_stats_t. */
static smartlist_t *circuits_for_buffer_stats = NULL;
+/** Remember cell statistics <b>mean_num_cells_in_queue</b>,
+ * <b>mean_time_cells_in_queue</b>, and <b>processed_cells</b> of a
+ * circuit. */
+void
+rep_hist_add_buffer_stats(double mean_num_cells_in_queue,
+ double mean_time_cells_in_queue, uint32_t processed_cells)
+{
+ circ_buffer_stats_t *stat;
+ if (!start_of_buffer_stats_interval)
+ return; /* Not initialized. */
+ stat = tor_malloc_zero(sizeof(circ_buffer_stats_t));
+ stat->mean_num_cells_in_queue = mean_num_cells_in_queue;
+ stat->mean_time_cells_in_queue = mean_time_cells_in_queue;
+ stat->processed_cells = processed_cells;
+ if (!circuits_for_buffer_stats)
+ circuits_for_buffer_stats = smartlist_create();
+ smartlist_add(circuits_for_buffer_stats, stat);
+}
+
/** Remember cell statistics for circuit <b>circ</b> at time
* <b>end_of_interval</b> and reset cell counters in case the circuit
* remains open in the next measurement interval. */
void
rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval)
{
- circ_buffer_stats_t *stat;
time_t start_of_interval;
int interval_length;
or_circuit_t *orcirc;
+ double mean_num_cells_in_queue, mean_time_cells_in_queue;
+ uint32_t processed_cells;
if (CIRCUIT_IS_ORIGIN(circ))
return;
orcirc = TO_OR_CIRCUIT(circ);
if (!orcirc->processed_cells)
return;
- if (!circuits_for_buffer_stats)
- circuits_for_buffer_stats = smartlist_create();
- start_of_interval = circ->timestamp_created.tv_sec >
- start_of_buffer_stats_interval ?
+ start_of_interval = (circ->timestamp_created.tv_sec >
+ start_of_buffer_stats_interval) ?
circ->timestamp_created.tv_sec :
start_of_buffer_stats_interval;
interval_length = (int) (end_of_interval - start_of_interval);
if (interval_length <= 0)
return;
- stat = tor_malloc_zero(sizeof(circ_buffer_stats_t));
- stat->processed_cells = orcirc->processed_cells;
+ processed_cells = orcirc->processed_cells;
/* 1000.0 for s -> ms; 2.0 because of app-ward and exit-ward queues */
- stat->mean_num_cells_in_queue = (double) orcirc->total_cell_waiting_time /
+ mean_num_cells_in_queue = (double) orcirc->total_cell_waiting_time /
(double) interval_length / 1000.0 / 2.0;
- stat->mean_time_cells_in_queue =
+ mean_time_cells_in_queue =
(double) orcirc->total_cell_waiting_time /
(double) orcirc->processed_cells;
- smartlist_add(circuits_for_buffer_stats, stat);
orcirc->total_cell_waiting_time = 0;
orcirc->processed_cells = 0;
+ rep_hist_add_buffer_stats(mean_num_cells_in_queue,
+ mean_time_cells_in_queue,
+ processed_cells);
}
/** Sorting helper: return -1, 1, or 0 based on comparison of two
@@ -2430,136 +2439,382 @@ _buffer_stats_compare_entries(const void **_a, const void **_b)
void
rep_hist_buffer_stats_term(void)
{
- start_of_buffer_stats_interval = 0;
+ rep_hist_reset_buffer_stats(0);
+}
+
+/** Clear history of circuit statistics and set the measurement interval
+ * start to <b>now</b>. */
+void
+rep_hist_reset_buffer_stats(time_t now)
+{
if (!circuits_for_buffer_stats)
circuits_for_buffer_stats = smartlist_create();
SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *,
stat, tor_free(stat));
smartlist_clear(circuits_for_buffer_stats);
+ start_of_buffer_stats_interval = now;
}
-/** Write buffer statistics to $DATADIR/stats/buffer-stats and return when
- * we would next want to write exit stats. */
-time_t
-rep_hist_buffer_stats_write(time_t now)
+/** Return a newly allocated string containing the buffer statistics until
+ * <b>now</b>, or NULL if we're not collecting buffer stats. */
+char *
+rep_hist_format_buffer_stats(time_t now)
{
- char *statsdir = NULL, *filename = NULL;
- char written[ISO_TIME_LEN+1];
- open_file_t *open_file = NULL;
- FILE *out;
#define SHARES 10
int processed_cells[SHARES], circs_in_share[SHARES],
number_of_circuits, i;
double queued_cells[SHARES], time_in_queue[SHARES];
- smartlist_t *str_build = NULL;
- char *str = NULL, *buf = NULL;
- circuit_t *circ;
+ char *buf = NULL;
+ smartlist_t *processed_cells_strings, *queued_cells_strings,
+ *time_in_queue_strings;
+ char *processed_cells_string, *queued_cells_string,
+ *time_in_queue_string;
+ char t[ISO_TIME_LEN+1];
+ char *result;
if (!start_of_buffer_stats_interval)
- return 0; /* Not initialized. */
- if (start_of_buffer_stats_interval + WRITE_STATS_INTERVAL > now)
- goto done; /* Not ready to write */
-
- str_build = smartlist_create();
+ return NULL; /* Not initialized. */
- /* add current circuits to stats */
- for (circ = _circuit_get_global_list(); circ; circ = circ->next)
- rep_hist_buffer_stats_add_circ(circ, now);
- /* calculate deciles */
+ /* Calculate deciles if we saw at least one circuit. */
memset(processed_cells, 0, SHARES * sizeof(int));
memset(circs_in_share, 0, SHARES * sizeof(int));
memset(queued_cells, 0, SHARES * sizeof(double));
memset(time_in_queue, 0, SHARES * sizeof(double));
if (!circuits_for_buffer_stats)
circuits_for_buffer_stats = smartlist_create();
- smartlist_sort(circuits_for_buffer_stats,
- _buffer_stats_compare_entries);
number_of_circuits = smartlist_len(circuits_for_buffer_stats);
- if (number_of_circuits < 1) {
- log_info(LD_HIST, "Attempt to write cell statistics to disk failed. "
- "We haven't seen a single circuit to report about.");
- goto done;
+ if (number_of_circuits > 0) {
+ smartlist_sort(circuits_for_buffer_stats,
+ _buffer_stats_compare_entries);
+ i = 0;
+ SMARTLIST_FOREACH_BEGIN(circuits_for_buffer_stats,
+ circ_buffer_stats_t *, stat)
+ {
+ int share = i++ * SHARES / number_of_circuits;
+ processed_cells[share] += stat->processed_cells;
+ queued_cells[share] += stat->mean_num_cells_in_queue;
+ time_in_queue[share] += stat->mean_time_cells_in_queue;
+ circs_in_share[share]++;
+ }
+ SMARTLIST_FOREACH_END(stat);
}
- i = 0;
- SMARTLIST_FOREACH_BEGIN(circuits_for_buffer_stats,
- circ_buffer_stats_t *, stat)
- {
- int share = i++ * SHARES / number_of_circuits;
- processed_cells[share] += stat->processed_cells;
- queued_cells[share] += stat->mean_num_cells_in_queue;
- time_in_queue[share] += stat->mean_time_cells_in_queue;
- circs_in_share[share]++;
- }
- SMARTLIST_FOREACH_END(stat);
- /* clear buffer stats history */
- SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *,
- stat, tor_free(stat));
- smartlist_clear(circuits_for_buffer_stats);
- /* write to file */
- statsdir = get_datadir_fname("stats");
- if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0)
- goto done;
- filename = get_datadir_fname2("stats", "buffer-stats");
- out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND | O_TEXT,
- 0600, &open_file);
- if (!out)
- goto done;
- format_iso_time(written, now);
- if (fprintf(out, "cell-stats-end %s (%d s)\n", written,
- (unsigned) (now - start_of_buffer_stats_interval)) < 0)
- goto done;
+
+ /* Write deciles to strings. */
+ processed_cells_strings = smartlist_create();
+ queued_cells_strings = smartlist_create();
+ time_in_queue_strings = smartlist_create();
for (i = 0; i < SHARES; i++) {
tor_asprintf(&buf,"%d", !circs_in_share[i] ? 0 :
processed_cells[i] / circs_in_share[i]);
- smartlist_add(str_build, buf);
+ smartlist_add(processed_cells_strings, buf);
}
- str = smartlist_join_strings(str_build, ",", 0, NULL);
- if (fprintf(out, "cell-processed-cells %s\n", str) < 0)
- goto done;
- tor_free(str);
- SMARTLIST_FOREACH(str_build, char *, c, tor_free(c));
- smartlist_clear(str_build);
for (i = 0; i < SHARES; i++) {
tor_asprintf(&buf, "%.2f", circs_in_share[i] == 0 ? 0.0 :
queued_cells[i] / (double) circs_in_share[i]);
- smartlist_add(str_build, buf);
+ smartlist_add(queued_cells_strings, buf);
}
- str = smartlist_join_strings(str_build, ",", 0, NULL);
- if (fprintf(out, "cell-queued-cells %s\n", str) < 0)
- goto done;
- tor_free(str);
- SMARTLIST_FOREACH(str_build, char *, c, tor_free(c));
- smartlist_clear(str_build);
for (i = 0; i < SHARES; i++) {
tor_asprintf(&buf, "%.0f", circs_in_share[i] == 0 ? 0.0 :
time_in_queue[i] / (double) circs_in_share[i]);
- smartlist_add(str_build, buf);
+ smartlist_add(time_in_queue_strings, buf);
}
- str = smartlist_join_strings(str_build, ",", 0, NULL);
- if (fprintf(out, "cell-time-in-queue %s\n", str) < 0)
- goto done;
- tor_free(str);
- SMARTLIST_FOREACH(str_build, char *, c, tor_free(c));
- smartlist_free(str_build);
- str_build = NULL;
- if (fprintf(out, "cell-circuits-per-decile %d\n",
- (number_of_circuits + SHARES - 1) / SHARES) < 0)
+
+ /* Join all observations in single strings. */
+ processed_cells_string = smartlist_join_strings(processed_cells_strings,
+ ",", 0, NULL);
+ queued_cells_string = smartlist_join_strings(queued_cells_strings,
+ ",", 0, NULL);
+ time_in_queue_string = smartlist_join_strings(time_in_queue_strings,
+ ",", 0, NULL);
+ SMARTLIST_FOREACH(processed_cells_strings, char *, cp, tor_free(cp));
+ SMARTLIST_FOREACH(queued_cells_strings, char *, cp, tor_free(cp));
+ SMARTLIST_FOREACH(time_in_queue_strings, char *, cp, tor_free(cp));
+ smartlist_free(processed_cells_strings);
+ smartlist_free(queued_cells_strings);
+ smartlist_free(time_in_queue_strings);
+
+ /* Put everything together. */
+ format_iso_time(t, now);
+ tor_asprintf(&result, "cell-stats-end %s (%d s)\n"
+ "cell-processed-cells %s\n"
+ "cell-queued-cells %s\n"
+ "cell-time-in-queue %s\n"
+ "cell-circuits-per-decile %d\n",
+ t, (unsigned) (now - start_of_buffer_stats_interval),
+ processed_cells_string,
+ queued_cells_string,
+ time_in_queue_string,
+ (number_of_circuits + SHARES - 1) / SHARES);
+ tor_free(processed_cells_string);
+ tor_free(queued_cells_string);
+ tor_free(time_in_queue_string);
+ return result;
+#undef SHARES
+}
+
+/** If 24 hours have passed since the beginning of the current buffer
+ * stats period, write buffer stats to $DATADIR/stats/buffer-stats
+ * (possibly overwriting an existing file) and reset counters. Return
+ * when we would next want to write buffer stats or 0 if we never want to
+ * write. */
+time_t
+rep_hist_buffer_stats_write(time_t now)
+{
+ circuit_t *circ;
+ char *statsdir = NULL, *filename = NULL, *str = NULL;
+
+ if (!start_of_buffer_stats_interval)
+ return 0; /* Not initialized. */
+ if (start_of_buffer_stats_interval + WRITE_STATS_INTERVAL > now)
+ goto done; /* Not ready to write */
+
+ /* Add open circuits to the history. */
+ for (circ = _circuit_get_global_list(); circ; circ = circ->next) {
+ rep_hist_buffer_stats_add_circ(circ, now);
+ }
+
+ /* Generate history string. */
+ str = rep_hist_format_buffer_stats(now);
+
+ /* Reset both buffer history and counters of open circuits. */
+ rep_hist_reset_buffer_stats(now);
+
+ /* Try to write to disk. */
+ statsdir = get_datadir_fname("stats");
+ if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
+ log_warn(LD_HIST, "Unable to create stats/ directory!");
goto done;
- finish_writing_to_file(open_file);
- open_file = NULL;
- start_of_buffer_stats_interval = now;
+ }
+ filename = get_datadir_fname2("stats", "buffer-stats");
+ if (write_str_to_file(filename, str, 0) < 0)
+ log_warn(LD_HIST, "Unable to write buffer stats to disk!");
+
done:
- if (open_file)
- abort_writing_to_file(open_file);
+ tor_free(str);
tor_free(filename);
tor_free(statsdir);
- if (str_build) {
- SMARTLIST_FOREACH(str_build, char *, c, tor_free(c));
- smartlist_free(str_build);
+ return start_of_buffer_stats_interval + WRITE_STATS_INTERVAL;
+}
+
+/*** Connection statistics ***/
+
+/** Start of the current connection stats interval or 0 if we're not
+ * collecting connection statistics. */
+static time_t start_of_conn_stats_interval;
+
+/** Initialize connection stats. */
+void
+rep_hist_conn_stats_init(time_t now)
+{
+ start_of_conn_stats_interval = now;
+}
+
+/* Count connections that we read and wrote less than these many bytes
+ * from/to as below threshold. */
+#define BIDI_THRESHOLD 20480
+
+/* Count connections that we read or wrote at least this factor as many
+ * bytes from/to than we wrote or read to/from as mostly reading or
+ * writing. */
+#define BIDI_FACTOR 10
+
+/* Interval length in seconds for considering read and written bytes for
+ * connection stats. */
+#define BIDI_INTERVAL 10
+
+/* Start of next BIDI_INTERVAL second interval. */
+static time_t bidi_next_interval = 0;
+
+/* Number of connections that we read and wrote less than BIDI_THRESHOLD
+ * bytes from/to in BIDI_INTERVAL seconds. */
+static uint32_t below_threshold = 0;
+
+/* Number of connections that we read at least BIDI_FACTOR times more
+ * bytes from than we wrote to in BIDI_INTERVAL seconds. */
+static uint32_t mostly_read = 0;
+
+/* Number of connections that we wrote at least BIDI_FACTOR times more
+ * bytes to than we read from in BIDI_INTERVAL seconds. */
+static uint32_t mostly_written = 0;
+
+/* Number of connections that we read and wrote at least BIDI_THRESHOLD
+ * bytes from/to, but not BIDI_FACTOR times more in either direction in
+ * BIDI_INTERVAL seconds. */
+static uint32_t both_read_and_written = 0;
+
+/* Entry in a map from connection ID to the number of read and written
+ * bytes on this connection in a BIDI_INTERVAL second interval. */
+typedef struct bidi_map_entry_t {
+ HT_ENTRY(bidi_map_entry_t) node;
+ uint64_t conn_id; /**< Connection ID */
+ size_t read; /**< Number of read bytes */
+ size_t written; /**< Number of written bytes */
+} bidi_map_entry_t;
+
+/** Map of OR connections together with the number of read and written
+ * bytes in the current BIDI_INTERVAL second interval. */
+static HT_HEAD(bidimap, bidi_map_entry_t) bidi_map =
+ HT_INITIALIZER();
+
+static int
+bidi_map_ent_eq(const bidi_map_entry_t *a, const bidi_map_entry_t *b)
+{
+ return a->conn_id == b->conn_id;
+}
+
+static unsigned
+bidi_map_ent_hash(const bidi_map_entry_t *entry)
+{
+ return (unsigned) entry->conn_id;
+}
+
+HT_PROTOTYPE(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash,
+ bidi_map_ent_eq);
+HT_GENERATE(bidimap, bidi_map_entry_t, node, bidi_map_ent_hash,
+ bidi_map_ent_eq, 0.6, malloc, realloc, free);
+
+static void
+bidi_map_free(void)
+{
+ bidi_map_entry_t **ptr, **next, *ent;
+ for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) {
+ ent = *ptr;
+ next = HT_NEXT_RMV(bidimap, &bidi_map, ptr);
+ tor_free(ent);
+ }
+ HT_CLEAR(bidimap, &bidi_map);
+}
+
+/** Reset counters for conn statistics. */
+void
+rep_hist_reset_conn_stats(time_t now)
+{
+ start_of_conn_stats_interval = now;
+ below_threshold = 0;
+ mostly_read = 0;
+ mostly_written = 0;
+ both_read_and_written = 0;
+ bidi_map_free();
+}
+
+/** Stop collecting connection stats in a way that we can re-start doing
+ * so in rep_hist_conn_stats_init(). */
+void
+rep_hist_conn_stats_term(void)
+{
+ rep_hist_reset_conn_stats(0);
+}
+
+/** We read <b>num_read</b> bytes and wrote <b>num_written</b> from/to OR
+ * connection <b>conn_id</b> in second <b>when</b>. If this is the first
+ * observation in a new interval, sum up the last observations. Add bytes
+ * for this connection. */
+void
+rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read,
+ size_t num_written, time_t when)
+{
+ if (!start_of_conn_stats_interval)
+ return;
+ /* Initialize */
+ if (bidi_next_interval == 0)
+ bidi_next_interval = when + BIDI_INTERVAL;
+ /* Sum up last period's statistics */
+ if (when >= bidi_next_interval) {
+ bidi_map_entry_t **ptr, **next, *ent;
+ for (ptr = HT_START(bidimap, &bidi_map); ptr; ptr = next) {
+ ent = *ptr;
+ if (ent->read + ent->written < BIDI_THRESHOLD)
+ below_threshold++;
+ else if (ent->read >= ent->written * BIDI_FACTOR)
+ mostly_read++;
+ else if (ent->written >= ent->read * BIDI_FACTOR)
+ mostly_written++;
+ else
+ both_read_and_written++;
+ next = HT_NEXT_RMV(bidimap, &bidi_map, ptr);
+ tor_free(ent);
+ }
+ while (when >= bidi_next_interval)
+ bidi_next_interval += BIDI_INTERVAL;
+ log_info(LD_GENERAL, "%d below threshold, %d mostly read, "
+ "%d mostly written, %d both read and written.",
+ below_threshold, mostly_read, mostly_written,
+ both_read_and_written);
+ }
+ /* Add this connection's bytes. */
+ if (num_read > 0 || num_written > 0) {
+ bidi_map_entry_t *entry, lookup;
+ lookup.conn_id = conn_id;
+ entry = HT_FIND(bidimap, &bidi_map, &lookup);
+ if (entry) {
+ entry->written += num_written;
+ entry->read += num_read;
+ } else {
+ entry = tor_malloc_zero(sizeof(bidi_map_entry_t));
+ entry->conn_id = conn_id;
+ entry->written = num_written;
+ entry->read = num_read;
+ HT_INSERT(bidimap, &bidi_map, entry);
+ }
+ }
+}
+
+/** Return a newly allocated string containing the connection statistics
+ * until <b>now</b>, or NULL if we're not collecting conn stats. */
+char *
+rep_hist_format_conn_stats(time_t now)
+{
+ char *result, written[ISO_TIME_LEN+1];
+
+ if (!start_of_conn_stats_interval)
+ return NULL; /* Not initialized. */
+
+ format_iso_time(written, now);
+ tor_asprintf(&result, "conn-bi-direct %s (%d s) %d,%d,%d,%d\n",
+ written,
+ (unsigned) (now - start_of_conn_stats_interval),
+ below_threshold,
+ mostly_read,
+ mostly_written,
+ both_read_and_written);
+ return result;
+}
+
+/** If 24 hours have passed since the beginning of the current conn stats
+ * period, write conn stats to $DATADIR/stats/conn-stats (possibly
+ * overwriting an existing file) and reset counters. Return when we would
+ * next want to write conn stats or 0 if we never want to write. */
+time_t
+rep_hist_conn_stats_write(time_t now)
+{
+ char *statsdir = NULL, *filename = NULL, *str = NULL;
+
+ if (!start_of_conn_stats_interval)
+ return 0; /* Not initialized. */
+ if (start_of_conn_stats_interval + WRITE_STATS_INTERVAL > now)
+ goto done; /* Not ready to write */
+
+ /* Generate history string. */
+ str = rep_hist_format_conn_stats(now);
+
+ /* Reset counters. */
+ rep_hist_reset_conn_stats(now);
+
+ /* Try to write to disk. */
+ statsdir = get_datadir_fname("stats");
+ if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) {
+ log_warn(LD_HIST, "Unable to create stats/ directory!");
+ goto done;
}
+ filename = get_datadir_fname2("stats", "conn-stats");
+ if (write_str_to_file(filename, str, 0) < 0)
+ log_warn(LD_HIST, "Unable to write conn stats to disk!");
+
+ done:
tor_free(str);
-#undef SHARES
- return start_of_buffer_stats_interval + WRITE_STATS_INTERVAL;
+ tor_free(filename);
+ tor_free(statsdir);
+ return start_of_conn_stats_interval + WRITE_STATS_INTERVAL;
}
/** Free all storage held by the OR/link history caches, by the
@@ -2576,6 +2831,8 @@ rep_hist_free_all(void)
tor_free(exit_streams);
built_last_stability_doc_at = 0;
predicted_ports_free();
+ bidi_map_free();
+
if (circuits_for_buffer_stats) {
SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *, s,
tor_free(s));
diff --git a/src/or/rephist.h b/src/or/rephist.h
index b06a39ed5..e59065944 100644
--- a/src/or/rephist.h
+++ b/src/or/rephist.h
@@ -77,6 +77,18 @@ void rep_hist_buffer_stats_add_circ(circuit_t *circ,
time_t end_of_interval);
time_t rep_hist_buffer_stats_write(time_t now);
void rep_hist_buffer_stats_term(void);
+void rep_hist_add_buffer_stats(double mean_num_cells_in_queue,
+ double mean_time_cells_in_queue, uint32_t processed_cells);
+char *rep_hist_format_buffer_stats(time_t now);
+void rep_hist_reset_buffer_stats(time_t now);
+
+void rep_hist_conn_stats_init(time_t now);
+void rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read,
+ size_t num_written, time_t when);
+void rep_hist_reset_conn_stats(time_t now);
+char *rep_hist_format_conn_stats(time_t now);
+time_t rep_hist_conn_stats_write(time_t now);
+void rep_hist_conn_stats_term(void);
#endif
diff --git a/src/or/router.c b/src/or/router.c
index 2165e6ea9..c9f141b7f 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -7,6 +7,7 @@
#define ROUTER_PRIVATE
#include "or.h"
+#include "circuitbuild.h"
#include "circuitlist.h"
#include "circuituse.h"
#include "config.h"
@@ -19,6 +20,7 @@
#include "hibernate.h"
#include "main.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "relay.h"
#include "rephist.h"
@@ -82,6 +84,11 @@ static authority_cert_t *legacy_key_certificate = NULL;
static void
set_onion_key(crypto_pk_env_t *k)
{
+ if (onionkey && !crypto_pk_cmp_keys(onionkey, k)) {
+ /* k is already our onion key; free it and return */
+ crypto_free_pk_env(k);
+ return;
+ }
tor_mutex_acquire(key_lock);
crypto_free_pk_env(onionkey);
onionkey = k;
@@ -149,8 +156,8 @@ assert_identity_keys_ok(void)
} else {
/* assert that we have set the client and server keys to be unequal */
if (server_identitykey)
- tor_assert(0!=crypto_pk_cmp_keys(client_identitykey,
- server_identitykey));
+ tor_assert(0!=crypto_pk_cmp_keys(client_identitykey,
+ server_identitykey));
}
}
@@ -493,8 +500,8 @@ init_keys(void)
char digest[DIGEST_LEN];
char v3_digest[DIGEST_LEN];
char *cp;
- or_options_t *options = get_options();
- authority_type_t type;
+ const or_options_t *options = get_options();
+ dirinfo_type_t type;
time_t now = time(NULL);
trusted_dir_server_t *ds;
int v3_digest_set = 0;
@@ -526,7 +533,7 @@ init_keys(void)
if (tor_tls_context_init(0,
get_tlsclient_identity_key(),
NULL,
- MAX_SSL_KEY_LIFETIME) < 0) {
+ MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) {
log_err(LD_GENERAL,"Error creating TLS context for Tor client.");
return -1;
}
@@ -622,7 +629,7 @@ init_keys(void)
if (tor_tls_context_init(public_server_mode(options),
get_tlsclient_identity_key(),
get_server_identity_key(),
- MAX_SSL_KEY_LIFETIME) < 0) {
+ MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) {
log_err(LD_GENERAL,"Error initializing TLS context");
return -1;
}
@@ -695,11 +702,12 @@ init_keys(void)
}
/* 6b. [authdirserver only] add own key to approved directories. */
crypto_pk_get_digest(get_server_identity_key(), digest);
- type = ((options->V1AuthoritativeDir ? V1_AUTHORITY : NO_AUTHORITY) |
- (options->V2AuthoritativeDir ? V2_AUTHORITY : NO_AUTHORITY) |
- (options->V3AuthoritativeDir ? V3_AUTHORITY : NO_AUTHORITY) |
- (options->BridgeAuthoritativeDir ? BRIDGE_AUTHORITY : NO_AUTHORITY) |
- (options->HSAuthoritativeDir ? HIDSERV_AUTHORITY : NO_AUTHORITY));
+ type = ((options->V1AuthoritativeDir ? V1_DIRINFO : NO_DIRINFO) |
+ (options->V2AuthoritativeDir ? V2_DIRINFO : NO_DIRINFO) |
+ (options->V3AuthoritativeDir ?
+ (V3_DIRINFO|MICRODESC_DIRINFO|EXTRAINFO_DIRINFO) : NO_DIRINFO) |
+ (options->BridgeAuthoritativeDir ? BRIDGE_DIRINFO : NO_DIRINFO) |
+ (options->HSAuthoritativeDir ? HIDSERV_DIRINFO : NO_DIRINFO));
ds = router_get_trusteddirserver_by_digest(digest);
if (!ds) {
@@ -721,7 +729,7 @@ init_keys(void)
type, ds->type);
ds->type = type;
}
- if (v3_digest_set && (ds->type & V3_AUTHORITY) &&
+ if (v3_digest_set && (ds->type & V3_DIRINFO) &&
tor_memneq(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) {
log_warn(LD_DIR, "V3 identity key does not match identity declared in "
"DirServer line. Adjusting.");
@@ -760,7 +768,7 @@ router_reset_reachability(void)
int
check_whether_orport_reachable(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
return options->AssumeReachable ||
can_reach_or_port;
}
@@ -769,7 +777,7 @@ check_whether_orport_reachable(void)
int
check_whether_dirport_reachable(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
return !options->DirPort ||
options->AssumeReachable ||
we_are_hibernating() ||
@@ -784,7 +792,7 @@ check_whether_dirport_reachable(void)
* a DirPort.
*/
static int
-decide_to_advertise_dirport(or_options_t *options, uint16_t dir_port)
+decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port)
{
static int advertising=1; /* start out assuming we will advertise */
int new_choice=1;
@@ -849,14 +857,14 @@ decide_to_advertise_dirport(or_options_t *options, uint16_t dir_port)
void
consider_testing_reachability(int test_or, int test_dir)
{
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
int orport_reachable = check_whether_orport_reachable();
tor_addr_t addr;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!me)
return;
- if (routerset_contains_router(options->ExcludeNodes, me) &&
+ if (routerset_contains_router(options->ExcludeNodes, me, -1) &&
options->StrictNodes) {
/* If we've excluded ourself, and StrictNodes is set, we can't test
* ourself. */
@@ -876,11 +884,14 @@ consider_testing_reachability(int test_or, int test_dir)
}
if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) {
+ extend_info_t *ei;
log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.",
!orport_reachable ? "reachability" : "bandwidth",
me->address, me->or_port);
- circuit_launch_by_router(CIRCUIT_PURPOSE_TESTING, me,
- CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
+ ei = extend_info_from_router(me);
+ circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei,
+ CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL);
+ extend_info_free(ei);
}
tor_addr_from_ipv4h(&addr, me->addr);
@@ -903,11 +914,11 @@ consider_testing_reachability(int test_or, int test_dir)
void
router_orport_found_reachable(void)
{
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!can_reach_or_port && me) {
log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from "
"the outside. Excellent.%s",
- get_options()->_PublishServerDescriptor != NO_AUTHORITY ?
+ get_options()->_PublishServerDescriptor != NO_DIRINFO ?
" Publishing server descriptor." : "");
can_reach_or_port = 1;
mark_my_descriptor_dirty("ORPort found reachable");
@@ -921,7 +932,7 @@ router_orport_found_reachable(void)
void
router_dirport_found_reachable(void)
{
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!can_reach_dir_port && me) {
log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable "
"from the outside. Excellent.");
@@ -967,7 +978,7 @@ router_perform_bandwidth_test(int num_circs, time_t now)
* directory server.
*/
int
-authdir_mode(or_options_t *options)
+authdir_mode(const or_options_t *options)
{
return options->AuthoritativeDir != 0;
}
@@ -975,7 +986,7 @@ authdir_mode(or_options_t *options)
* directory server.
*/
int
-authdir_mode_v1(or_options_t *options)
+authdir_mode_v1(const or_options_t *options)
{
return authdir_mode(options) && options->V1AuthoritativeDir != 0;
}
@@ -983,7 +994,7 @@ authdir_mode_v1(or_options_t *options)
* directory server.
*/
int
-authdir_mode_v2(or_options_t *options)
+authdir_mode_v2(const or_options_t *options)
{
return authdir_mode(options) && options->V2AuthoritativeDir != 0;
}
@@ -991,13 +1002,13 @@ authdir_mode_v2(or_options_t *options)
* directory server.
*/
int
-authdir_mode_v3(or_options_t *options)
+authdir_mode_v3(const or_options_t *options)
{
return authdir_mode(options) && options->V3AuthoritativeDir != 0;
}
/** Return true iff we are a v1, v2, or v3 directory authority. */
int
-authdir_mode_any_main(or_options_t *options)
+authdir_mode_any_main(const or_options_t *options)
{
return options->V1AuthoritativeDir ||
options->V2AuthoritativeDir ||
@@ -1006,7 +1017,7 @@ authdir_mode_any_main(or_options_t *options)
/** Return true if we believe ourselves to be any kind of
* authoritative directory beyond just a hidserv authority. */
int
-authdir_mode_any_nonhidserv(or_options_t *options)
+authdir_mode_any_nonhidserv(const or_options_t *options)
{
return options->BridgeAuthoritativeDir ||
authdir_mode_any_main(options);
@@ -1015,7 +1026,7 @@ authdir_mode_any_nonhidserv(or_options_t *options)
* authoritative about receiving and serving descriptors of type
* <b>purpose</b> its dirport. Use -1 for "any purpose". */
int
-authdir_mode_handles_descs(or_options_t *options, int purpose)
+authdir_mode_handles_descs(const or_options_t *options, int purpose)
{
if (purpose < 0)
return authdir_mode_any_nonhidserv(options);
@@ -1030,7 +1041,7 @@ authdir_mode_handles_descs(or_options_t *options, int purpose)
* publishes its own network statuses.
*/
int
-authdir_mode_publishes_statuses(or_options_t *options)
+authdir_mode_publishes_statuses(const or_options_t *options)
{
if (authdir_mode_bridge(options))
return 0;
@@ -1040,7 +1051,7 @@ authdir_mode_publishes_statuses(or_options_t *options)
* tests reachability of the descriptors it learns about.
*/
int
-authdir_mode_tests_reachability(or_options_t *options)
+authdir_mode_tests_reachability(const or_options_t *options)
{
return authdir_mode_handles_descs(options, -1);
}
@@ -1048,7 +1059,7 @@ authdir_mode_tests_reachability(or_options_t *options)
* directory server.
*/
int
-authdir_mode_bridge(or_options_t *options)
+authdir_mode_bridge(const or_options_t *options)
{
return authdir_mode(options) && options->BridgeAuthoritativeDir != 0;
}
@@ -1056,7 +1067,7 @@ authdir_mode_bridge(or_options_t *options)
/** Return true iff we are trying to be a server.
*/
int
-server_mode(or_options_t *options)
+server_mode(const or_options_t *options)
{
if (options->ClientOnly) return 0;
return (options->ORPort != 0 || options->ORListenAddress);
@@ -1065,7 +1076,7 @@ server_mode(or_options_t *options)
/** Return true iff we are trying to be a non-bridge server.
*/
int
-public_server_mode(or_options_t *options)
+public_server_mode(const or_options_t *options)
{
if (!server_mode(options)) return 0;
return (!options->BridgeRelay);
@@ -1075,10 +1086,10 @@ public_server_mode(or_options_t *options)
* in the consensus mean that we don't want to allow exits from circuits
* we got from addresses not known to be servers. */
int
-should_refuse_unknown_exits(or_options_t *options)
+should_refuse_unknown_exits(const or_options_t *options)
{
- if (options->RefuseUnknownExits_ != -1) {
- return options->RefuseUnknownExits_;
+ if (options->RefuseUnknownExits != -1) {
+ return options->RefuseUnknownExits;
} else {
return networkstatus_get_param(NULL, "refuseunknownexits", 1, 0, 1);
}
@@ -1105,14 +1116,12 @@ set_server_advertised(int s)
server_is_advertised = s;
}
-/** Return true iff we are trying to be a socks proxy. */
+/** Return true iff we are trying to proxy client connections. */
int
-proxy_mode(or_options_t *options)
+proxy_mode(const or_options_t *options)
{
- return (options->SocksPort != 0 ||
- options->TransPort != 0 ||
- options->NATDPort != 0 ||
- options->DNSPort != 0);
+ (void)options;
+ return smartlist_len(get_configured_client_ports()) > 0;
}
/** Decide if we're a publishable server. We are a publishable server if:
@@ -1128,11 +1137,11 @@ proxy_mode(or_options_t *options)
static int
decide_if_publishable_server(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->ClientOnly)
return 0;
- if (options->_PublishServerDescriptor == NO_AUTHORITY)
+ if (options->_PublishServerDescriptor == NO_DIRINFO)
return 0;
if (!server_mode(options))
return 0;
@@ -1173,7 +1182,7 @@ consider_publishable_server(int force)
* the one configured in the ORPort option, or the one we actually bound to
* if ORPort is "auto". */
uint16_t
-router_get_advertised_or_port(or_options_t *options)
+router_get_advertised_or_port(const or_options_t *options)
{
if (options->ORPort == CFG_AUTO_PORT) {
connection_t *c = connection_get_by_type(CONN_TYPE_OR_LISTENER);
@@ -1190,7 +1199,7 @@ router_get_advertised_or_port(or_options_t *options)
* the one configured in the DirPort option,
* or the one we actually bound to if DirPort is "auto". */
uint16_t
-router_get_advertised_dir_port(or_options_t *options, uint16_t dirport)
+router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport)
{
if (!options->DirPort)
return dirport;
@@ -1211,9 +1220,14 @@ router_get_advertised_dir_port(or_options_t *options, uint16_t dirport)
static routerinfo_t *desc_routerinfo = NULL;
/** My extrainfo */
static extrainfo_t *desc_extrainfo = NULL;
+/** Why did we most recently decide to regenerate our descriptor? Used to
+ * tell the authorities why we're sending it to them. */
+static const char *desc_gen_reason = NULL;
/** Since when has our descriptor been "clean"? 0 if we need to regenerate it
* now. */
static time_t desc_clean_since = 0;
+/** Why did we mark the descriptor dirty? */
+static const char *desc_dirty_reason = NULL;
/** Boolean: do we need to regenerate the above? */
static int desc_needs_upload = 0;
@@ -1224,11 +1238,11 @@ static int desc_needs_upload = 0;
void
router_upload_dir_desc_to_dirservers(int force)
{
- routerinfo_t *ri;
+ const routerinfo_t *ri;
extrainfo_t *ei;
char *msg;
size_t desc_len, extra_len = 0, total_len;
- authority_type_t auth = get_options()->_PublishServerDescriptor;
+ dirinfo_type_t auth = get_options()->_PublishServerDescriptor;
ri = router_get_my_routerinfo();
if (!ri) {
@@ -1236,7 +1250,7 @@ router_upload_dir_desc_to_dirservers(int force)
return;
}
ei = router_get_my_extrainfo();
- if (auth == NO_AUTHORITY)
+ if (auth == NO_DIRINFO)
return;
if (!force && !desc_needs_upload)
return;
@@ -1257,7 +1271,7 @@ router_upload_dir_desc_to_dirservers(int force)
msg[desc_len+extra_len] = 0;
directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_DIR,
- (auth & BRIDGE_AUTHORITY) ?
+ (auth & BRIDGE_DIRINFO) ?
ROUTER_PURPOSE_BRIDGE :
ROUTER_PURPOSE_GENERAL,
auth, msg, desc_len, extra_len);
@@ -1322,7 +1336,7 @@ router_extrainfo_digest_is_me(const char *digest)
/** A wrapper around router_digest_is_me(). */
int
-router_is_me(routerinfo_t *router)
+router_is_me(const routerinfo_t *router)
{
return router_digest_is_me(router->cache_info.identity_digest);
}
@@ -1341,7 +1355,7 @@ router_fingerprint_is_me(const char *fp)
/** Return a routerinfo for this OR, rebuilding a fresh one if
* necessary. Return NULL on error, or if called on an OP. */
-routerinfo_t *
+const routerinfo_t *
router_get_my_routerinfo(void)
{
if (!server_mode(get_options()))
@@ -1380,6 +1394,14 @@ router_get_my_extrainfo(void)
return desc_extrainfo;
}
+/** Return a human-readable string describing what triggered us to generate
+ * our current descriptor, or NULL if we don't know. */
+const char *
+router_get_descriptor_gen_reason(void)
+{
+ return desc_gen_reason;
+}
+
/** A list of nicknames that we've warned about including in our family
* declaration verbatim rather than as digests. */
static smartlist_t *warned_nonexistent_family = NULL;
@@ -1391,10 +1413,8 @@ static int router_guess_address_from_dir_headers(uint32_t *guess);
* dirserver headers. Place the answer in *<b>addr</b> and return
* 0 on success, else return -1 if we have no guess. */
int
-router_pick_published_address(or_options_t *options, uint32_t *addr)
+router_pick_published_address(const or_options_t *options, uint32_t *addr)
{
- char buf[INET_NTOA_BUF_LEN];
- struct in_addr a;
if (resolve_my_address(LOG_INFO, options, addr, NULL) < 0) {
log_info(LD_CONFIG, "Could not determine our address locally. "
"Checking if directory headers provide any hints.");
@@ -1404,9 +1424,7 @@ router_pick_published_address(or_options_t *options, uint32_t *addr)
return -1;
}
}
- a.s_addr = htonl(*addr);
- tor_inet_ntoa(&a, buf, sizeof(buf));
- log_info(LD_CONFIG,"Success: chose address '%s'.", buf);
+ log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr32(*addr));
return 0;
}
@@ -1422,7 +1440,7 @@ router_rebuild_descriptor(int force)
uint32_t addr;
char platform[256];
int hibernating = we_are_hibernating();
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (desc_clean_since && !force)
return 0;
@@ -1476,13 +1494,12 @@ router_rebuild_descriptor(int force)
ri->policy_is_reject_star =
policy_is_reject_star(ri->exit_policy);
- if (desc_routerinfo) { /* inherit values */
- ri->is_valid = desc_routerinfo->is_valid;
- ri->is_running = desc_routerinfo->is_running;
- ri->is_named = desc_routerinfo->is_named;
- }
+#if 0
+ /* XXXX NM NM I belive this is safe to remove */
if (authdir_mode(options))
ri->is_valid = ri->is_named = 1; /* believe in yourself */
+#endif
+
if (options->MyFamily) {
smartlist_t *family;
if (!warned_nonexistent_family)
@@ -1491,13 +1508,12 @@ router_rebuild_descriptor(int force)
ri->declared_family = smartlist_create();
smartlist_split_string(family, options->MyFamily, ",",
SPLIT_SKIP_SPACE|SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
- SMARTLIST_FOREACH(family, char *, name,
- {
- routerinfo_t *member;
+ SMARTLIST_FOREACH_BEGIN(family, char *, name) {
+ const node_t *member;
if (!strcasecmp(name, options->Nickname))
- member = ri;
+ goto skip; /* Don't list ourself, that's redundant */
else
- member = router_get_by_nickname(name, 1);
+ member = node_get_by_nickname(name, 1);
if (!member) {
int is_legal = is_legal_nickname_or_hexdigest(name);
if (!smartlist_string_isin(warned_nonexistent_family, name) &&
@@ -1517,19 +1533,21 @@ router_rebuild_descriptor(int force)
smartlist_add(ri->declared_family, name);
name = NULL;
}
- } else if (router_is_me(member)) {
+ } else if (router_digest_is_me(member->identity)) {
/* Don't list ourself in our own family; that's redundant */
+ /* XXX shouldn't be possible */
} else {
char *fp = tor_malloc(HEX_DIGEST_LEN+2);
fp[0] = '$';
base16_encode(fp+1,HEX_DIGEST_LEN+1,
- member->cache_info.identity_digest, DIGEST_LEN);
+ member->identity, DIGEST_LEN);
smartlist_add(ri->declared_family, fp);
if (smartlist_string_isin(warned_nonexistent_family, name))
smartlist_string_remove(warned_nonexistent_family, name);
}
+ skip:
tor_free(name);
- });
+ } SMARTLIST_FOREACH_END(name);
/* remove duplicates from the list */
smartlist_sort_strings(ri->declared_family);
@@ -1590,8 +1608,6 @@ router_rebuild_descriptor(int force)
strlen(ri->cache_info.signed_descriptor_body),
ri->cache_info.signed_descriptor_digest);
- routerinfo_set_country(ri);
-
if (ei) {
tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei, NULL, NULL));
}
@@ -1603,16 +1619,56 @@ router_rebuild_descriptor(int force)
desc_clean_since = time(NULL);
desc_needs_upload = 1;
+ desc_gen_reason = desc_dirty_reason;
+ desc_dirty_reason = NULL;
control_event_my_descriptor_changed();
return 0;
}
-/** Mark descriptor out of date if it's older than <b>when</b> */
+/** If our router descriptor ever goes this long without being regenerated
+ * because something changed, we force an immediate regenerate-and-upload. */
+#define FORCE_REGENERATE_DESCRIPTOR_INTERVAL (18*60*60)
+
+/** If our router descriptor seems to be missing or unacceptable according
+ * to the authorities, regenerate and reupload it _this_ often. */
+#define FAST_RETRY_DESCRIPTOR_INTERVAL (90*60)
+
+/** Mark descriptor out of date if it's been "too long" since we last tried
+ * to upload one. */
void
-mark_my_descriptor_dirty_if_older_than(time_t when)
+mark_my_descriptor_dirty_if_too_old(time_t now)
{
- if (desc_clean_since < when)
+ networkstatus_t *ns;
+ const routerstatus_t *rs;
+ const char *retry_fast_reason = NULL; /* Set if we should retry frequently */
+ const time_t slow_cutoff = now - FORCE_REGENERATE_DESCRIPTOR_INTERVAL;
+ const time_t fast_cutoff = now - FAST_RETRY_DESCRIPTOR_INTERVAL;
+
+ /* If it's already dirty, don't mark it. */
+ if (! desc_clean_since)
+ return;
+
+ /* If it's older than FORCE_REGENERATE_DESCRIPTOR_INTERVAL, it's always
+ * time to rebuild it. */
+ if (desc_clean_since < slow_cutoff) {
mark_my_descriptor_dirty("time for new descriptor");
+ return;
+ }
+ /* Now we see whether we want to be retrying frequently or no. The
+ * rule here is that we'll retry frequently if we aren't listed in the
+ * live consensus we have, or if the publication time of the
+ * descriptor listed for us in the consensus is very old. */
+ ns = networkstatus_get_live_consensus(now);
+ if (ns) {
+ rs = networkstatus_vote_find_entry(ns, server_identitykey_digest);
+ if (rs == NULL)
+ retry_fast_reason = "not listed in consensus";
+ else if (rs->published_on < slow_cutoff)
+ retry_fast_reason = "version listed in consensus is quite old";
+ }
+
+ if (retry_fast_reason && desc_clean_since < fast_cutoff)
+ mark_my_descriptor_dirty(retry_fast_reason);
}
/** Call when the current descriptor is out of date. */
@@ -1621,6 +1677,8 @@ mark_my_descriptor_dirty(const char *reason)
{
desc_clean_since = 0;
log_info(LD_OR, "Decided to publish new relay descriptor: %s", reason);
+ if (!desc_dirty_reason)
+ desc_dirty_reason = reason;
}
/** How frequently will we republish our descriptor because of large (factor
@@ -1686,7 +1744,7 @@ void
check_descriptor_ipaddress_changed(time_t now)
{
uint32_t prev, cur;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
(void) now;
if (!desc_routerinfo)
@@ -1718,7 +1776,7 @@ router_new_address_suggestion(const char *suggestion,
{
uint32_t addr, cur = 0;
struct in_addr in;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* first, learn what the IP address actually is */
if (!tor_inet_aton(suggestion, &in)) {
@@ -1817,7 +1875,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
int result=0;
addr_policy_t *tmpe;
char *family_line;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
/* Make sure the identity key matches the one in the routerinfo. */
if (crypto_pk_cmp_keys(ident_key, router->identity_pkey)) {
@@ -2059,7 +2117,7 @@ int
extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
crypto_pk_env_t *ident_key)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
char identity[HEX_DIGEST_LEN+1];
char published[ISO_TIME_LEN+1];
char digest[DIGEST_LEN];
@@ -2083,6 +2141,12 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
tor_free(bandwidth_usage);
smartlist_add(chunks, pre);
+ if (geoip_is_loaded()) {
+ char *chunk=NULL;
+ tor_asprintf(&chunk, "geoip-db-digest %s\n", geoip_db_digest());
+ smartlist_add(chunks, chunk);
+ }
+
if (options->ExtraInfoStatistics && write_stats_to_extrainfo) {
log_info(LD_GENERAL, "Adding stats to extra-info descriptor.");
if (options->DirReqStatistics &&
@@ -2105,6 +2169,11 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
"exit-stats-end", now, &contents) > 0) {
smartlist_add(chunks, contents);
}
+ if (options->ConnDirectionStatistics &&
+ load_stats_file("stats"PATH_SEPARATOR"conn-stats",
+ "conn-bi-direct", now, &contents) > 0) {
+ smartlist_add(chunks, contents);
+ }
}
if (should_record_bridge_info(options) && write_stats_to_extrainfo) {
@@ -2291,13 +2360,45 @@ router_get_description(char *buf, const routerinfo_t *ri)
return "<null>";
return format_node_description(buf,
ri->cache_info.identity_digest,
- ri->is_named,
+ router_is_named(ri),
ri->nickname,
NULL,
ri->addr);
}
/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
+ * hold a human-readable description of <b>node</b>.
+ *
+ * Return a pointer to the front of <b>buf</b>.
+ */
+const char *
+node_get_description(char *buf, const node_t *node)
+{
+ const char *nickname = NULL;
+ uint32_t addr32h = 0;
+ int is_named = 0;
+
+ if (!node)
+ return "<null>";
+
+ if (node->rs) {
+ nickname = node->rs->nickname;
+ is_named = node->rs->is_named;
+ addr32h = node->rs->addr;
+ } else if (node->ri) {
+ nickname = node->ri->nickname;
+ addr32h = node->ri->addr;
+ }
+
+ return format_node_description(buf,
+ node->identity,
+ is_named,
+ nickname,
+ NULL,
+ addr32h);
+}
+
+/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to
* hold a human-readable description of <b>rs</b>.
*
* Return a pointer to the front of <b>buf</b>.
@@ -2345,6 +2446,18 @@ router_describe(const routerinfo_t *ri)
return router_get_description(buf, ri);
}
+/** Return a human-readable description of the node_t <b>node</b>.
+ *
+ * This function is not thread-safe. Each call to this function invalidates
+ * previous values returned by this function.
+ */
+const char *
+node_describe(const node_t *node)
+{
+ static char buf[NODE_DESC_BUF_LEN];
+ return node_get_description(buf, node);
+}
+
/** Return a human-readable description of the routerstatus_t <b>rs</b>.
*
* This function is not thread-safe. Each call to this function invalidates
@@ -2379,10 +2492,15 @@ extend_info_describe(const extend_info_t *ei)
void
router_get_verbose_nickname(char *buf, const routerinfo_t *router)
{
+ const char *good_digest = networkstatus_get_router_digest_by_nickname(
+ router->nickname);
+ int is_named = good_digest && tor_memeq(good_digest,
+ router->cache_info.identity_digest,
+ DIGEST_LEN);
buf[0] = '$';
base16_encode(buf+1, HEX_DIGEST_LEN+1, router->cache_info.identity_digest,
DIGEST_LEN);
- buf[1+HEX_DIGEST_LEN] = router->is_named ? '=' : '~';
+ buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~';
strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1);
}
diff --git a/src/or/router.h b/src/or/router.h
index 3733099f9..f9d156cb0 100644
--- a/src/or/router.h
+++ b/src/or/router.h
@@ -39,30 +39,30 @@ void router_orport_found_reachable(void);
void router_dirport_found_reachable(void);
void router_perform_bandwidth_test(int num_circs, time_t now);
-int authdir_mode(or_options_t *options);
-int authdir_mode_v1(or_options_t *options);
-int authdir_mode_v2(or_options_t *options);
-int authdir_mode_v3(or_options_t *options);
-int authdir_mode_any_main(or_options_t *options);
-int authdir_mode_any_nonhidserv(or_options_t *options);
-int authdir_mode_handles_descs(or_options_t *options, int purpose);
-int authdir_mode_publishes_statuses(or_options_t *options);
-int authdir_mode_tests_reachability(or_options_t *options);
-int authdir_mode_bridge(or_options_t *options);
+int authdir_mode(const or_options_t *options);
+int authdir_mode_v1(const or_options_t *options);
+int authdir_mode_v2(const or_options_t *options);
+int authdir_mode_v3(const or_options_t *options);
+int authdir_mode_any_main(const or_options_t *options);
+int authdir_mode_any_nonhidserv(const or_options_t *options);
+int authdir_mode_handles_descs(const or_options_t *options, int purpose);
+int authdir_mode_publishes_statuses(const or_options_t *options);
+int authdir_mode_tests_reachability(const or_options_t *options);
+int authdir_mode_bridge(const or_options_t *options);
-uint16_t router_get_advertised_or_port(or_options_t *options);
-uint16_t router_get_advertised_dir_port(or_options_t *options,
+uint16_t router_get_advertised_or_port(const or_options_t *options);
+uint16_t router_get_advertised_dir_port(const or_options_t *options,
uint16_t dirport);
-int server_mode(or_options_t *options);
-int public_server_mode(or_options_t *options);
+int server_mode(const or_options_t *options);
+int public_server_mode(const or_options_t *options);
int advertised_server_mode(void);
-int proxy_mode(or_options_t *options);
+int proxy_mode(const or_options_t *options);
void consider_publishable_server(int force);
-int should_refuse_unknown_exits(or_options_t *options);
+int should_refuse_unknown_exits(const or_options_t *options);
void router_upload_dir_desc_to_dirservers(int force);
-void mark_my_descriptor_dirty_if_older_than(time_t when);
+void mark_my_descriptor_dirty_if_too_old(time_t now);
void mark_my_descriptor_dirty(const char *reason);
void check_descriptor_bandwidth_changed(time_t now);
void check_descriptor_ipaddress_changed(time_t now);
@@ -70,14 +70,15 @@ void router_new_address_suggestion(const char *suggestion,
const dir_connection_t *d_conn);
int router_compare_to_my_exit_policy(edge_connection_t *conn);
int router_my_exit_policy_is_reject_star(void);
-routerinfo_t *router_get_my_routerinfo(void);
+const routerinfo_t *router_get_my_routerinfo(void);
extrainfo_t *router_get_my_extrainfo(void);
const char *router_get_my_descriptor(void);
+const char *router_get_descriptor_gen_reason(void);
int router_digest_is_me(const char *digest);
int router_extrainfo_digest_is_me(const char *digest);
-int router_is_me(routerinfo_t *router);
+int router_is_me(const routerinfo_t *router);
int router_fingerprint_is_me(const char *fp);
-int router_pick_published_address(or_options_t *options, uint32_t *addr);
+int router_pick_published_address(const or_options_t *options, uint32_t *addr);
int router_rebuild_descriptor(int force);
int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
crypto_pk_env_t *ident_key);
@@ -102,9 +103,11 @@ const char *format_node_description(char *buf,
const tor_addr_t *addr,
uint32_t addr32h);
const char *router_get_description(char *buf, const routerinfo_t *ri);
+const char *node_get_description(char *buf, const node_t *node);
const char *routerstatus_get_description(char *buf, const routerstatus_t *rs);
const char *extend_info_get_description(char *buf, const extend_info_t *ei);
const char *router_describe(const routerinfo_t *ri);
+const char *node_describe(const node_t *node);
const char *routerstatus_describe(const routerstatus_t *ri);
const char *extend_info_describe(const extend_info_t *ei);
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 47a57a872..d97b978f4 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -22,7 +22,9 @@
#include "geoip.h"
#include "hibernate.h"
#include "main.h"
+#include "microdesc.h"
#include "networkstatus.h"
+#include "nodelist.h"
#include "policies.h"
#include "reasons.h"
#include "rendcommon.h"
@@ -37,22 +39,25 @@
/****************************************************************************/
/* static function prototypes */
-static routerstatus_t *router_pick_directory_server_impl(
- authority_type_t auth, int flags);
-static routerstatus_t *router_pick_trusteddirserver_impl(
- authority_type_t auth, int flags, int *n_busy_out);
+static const routerstatus_t *router_pick_directory_server_impl(
+ dirinfo_type_t auth, int flags);
+static const routerstatus_t *router_pick_trusteddirserver_impl(
+ dirinfo_type_t auth, int flags, int *n_busy_out);
static void mark_all_trusteddirservers_up(void);
-static int router_nickname_matches(routerinfo_t *router, const char *nickname);
+static int router_nickname_matches(const routerinfo_t *router,
+ const char *nickname);
+static int node_nickname_matches(const node_t *router,
+ const char *nickname);
static void trusted_dir_server_free(trusted_dir_server_t *ds);
-static void launch_router_descriptor_downloads(smartlist_t *downloadable,
- routerstatus_t *source,
- time_t now);
static int signed_desc_digest_is_recognized(signed_descriptor_t *desc);
static void update_router_have_minimum_dir_info(void);
-static const char *signed_descriptor_get_body_impl(signed_descriptor_t *desc,
- int with_annotations);
+static const char *signed_descriptor_get_body_impl(
+ const signed_descriptor_t *desc,
+ int with_annotations);
static void list_pending_downloads(digestmap_t *result,
int purpose, const char *prefix);
+static void launch_dummy_descriptor_download_as_needed(time_t now,
+ const or_options_t *options);
DECLARE_TYPED_DIGESTMAP_FNS(sdmap_, digest_sd_map_t, signed_descriptor_t)
DECLARE_TYPED_DIGESTMAP_FNS(rimap_, digest_ri_map_t, routerinfo_t)
@@ -94,7 +99,7 @@ static smartlist_t *warned_nicknames = NULL;
/** The last time we tried to download any routerdesc, or 0 for "never". We
* use this to rate-limit download attempts when the number of routerdescs to
* download is low. */
-static time_t last_routerdesc_download_attempted = 0;
+static time_t last_descriptor_download_attempted = 0;
/** When we last computed the weights to use for bandwidths on directory
* requests, what were the total weighted bandwidth, and our share of that
@@ -106,7 +111,7 @@ static uint64_t sl_last_total_weighted_bw = 0,
/** Return the number of directory authorities whose type matches some bit set
* in <b>type</b> */
int
-get_n_authorities(authority_type_t type)
+get_n_authorities(dirinfo_type_t type)
{
int n = 0;
if (!trusted_dir_servers)
@@ -117,7 +122,7 @@ get_n_authorities(authority_type_t type)
return n;
}
-#define get_n_v2_authorities() get_n_authorities(V2_AUTHORITY)
+#define get_n_v2_authorities() get_n_authorities(V2_DIRINFO)
/** Helper: Return the cert_list_t for an authority whose authority ID is
* <b>id_digest</b>, allocating a new list if necessary. */
@@ -312,6 +317,7 @@ trusted_dirs_remove_old_certs(void)
time_t now = time(NULL);
#define DEAD_CERT_LIFETIME (2*24*60*60)
#define OLD_CERT_LIFETIME (7*24*60*60)
+#define CERT_EXPIRY_SKEW (60*60)
if (!trusted_dir_certs)
return;
@@ -514,7 +520,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now)
}
SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, trusted_dir_server_t *, ds) {
int found = 0;
- if (!(ds->type & V3_AUTHORITY))
+ if (!(ds->type & V3_DIRINFO))
continue;
if (smartlist_digest_isin(missing_digests, ds->v3_identity_digest))
continue;
@@ -600,7 +606,7 @@ router_should_rebuild_store(desc_store_t *store)
/** Return the desc_store_t in <b>rl</b> that should be used to store
* <b>sd</b>. */
static INLINE desc_store_t *
-desc_get_store(routerlist_t *rl, signed_descriptor_t *sd)
+desc_get_store(routerlist_t *rl, const signed_descriptor_t *sd)
{
if (sd->is_extrainfo)
return &rl->extrainfo_store;
@@ -926,10 +932,10 @@ router_get_trusted_dir_servers(void)
* Don't pick an authority if any non-authority is viable; try to avoid using
* servers that have returned 503 recently.
*/
-routerstatus_t *
-router_pick_directory_server(authority_type_t type, int flags)
+const routerstatus_t *
+router_pick_directory_server(dirinfo_type_t type, int flags)
{
- routerstatus_t *choice;
+ const routerstatus_t *choice;
if (get_options()->PreferTunneledDirConns)
flags |= _PDS_PREFER_TUNNELED_DIR_CONNS;
@@ -958,8 +964,8 @@ int
router_get_my_share_of_directory_requests(double *v2_share_out,
double *v3_share_out)
{
- routerinfo_t *me = router_get_my_routerinfo();
- routerstatus_t *rs;
+ const routerinfo_t *me = router_get_my_routerinfo();
+ const routerstatus_t *rs;
const int pds_flags = PDS_ALLOW_SELF|PDS_IGNORE_FASCISTFIREWALL;
*v2_share_out = *v3_share_out = 0.0;
if (!me)
@@ -972,7 +978,7 @@ router_get_my_share_of_directory_requests(double *v2_share_out,
/* XXXX This is a bit of a kludge */
if (rs->is_v2_dir) {
sl_last_total_weighted_bw = 0;
- router_pick_directory_server(V2_AUTHORITY, pds_flags);
+ router_pick_directory_server(V2_DIRINFO, pds_flags);
if (sl_last_total_weighted_bw != 0) {
*v2_share_out = U64_TO_DBL(sl_last_weighted_bw_of_me) /
U64_TO_DBL(sl_last_total_weighted_bw);
@@ -981,7 +987,7 @@ router_get_my_share_of_directory_requests(double *v2_share_out,
if (rs->version_supports_v3_dir) {
sl_last_total_weighted_bw = 0;
- router_pick_directory_server(V3_AUTHORITY, pds_flags);
+ router_pick_directory_server(V3_DIRINFO, pds_flags);
if (sl_last_total_weighted_bw != 0) {
*v3_share_out = U64_TO_DBL(sl_last_weighted_bw_of_me) /
U64_TO_DBL(sl_last_total_weighted_bw);
@@ -1022,7 +1028,7 @@ trusteddirserver_get_by_v3_auth_digest(const char *digest)
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
{
if (tor_memeq(ds->v3_identity_digest, digest, DIGEST_LEN) &&
- (ds->type & V3_AUTHORITY))
+ (ds->type & V3_DIRINFO))
return ds;
});
@@ -1032,10 +1038,10 @@ trusteddirserver_get_by_v3_auth_digest(const char *digest)
/** Try to find a running trusted dirserver. Flags are as for
* router_pick_directory_server.
*/
-routerstatus_t *
-router_pick_trusteddirserver(authority_type_t type, int flags)
+const routerstatus_t *
+router_pick_trusteddirserver(dirinfo_type_t type, int flags)
{
- routerstatus_t *choice;
+ const routerstatus_t *choice;
int busy = 0;
if (get_options()->PreferTunneledDirConns)
flags |= _PDS_PREFER_TUNNELED_DIR_CONNS;
@@ -1047,7 +1053,8 @@ router_pick_trusteddirserver(authority_type_t type, int flags)
/* If the reason that we got no server is that servers are "busy",
* we must be excluding good servers because we already have serverdesc
* fetches with them. Do not mark down servers up because of this. */
- tor_assert((flags & PDS_NO_EXISTING_SERVERDESC_FETCH));
+ tor_assert((flags & (PDS_NO_EXISTING_SERVERDESC_FETCH|
+ PDS_NO_EXISTING_MICRODESC_FETCH)));
return NULL;
}
@@ -1067,11 +1074,11 @@ router_pick_trusteddirserver(authority_type_t type, int flags)
* If the _PDS_PREFER_TUNNELED_DIR_CONNS flag is set, prefer directory servers
* that we can use with BEGINDIR.
*/
-static routerstatus_t *
-router_pick_directory_server_impl(authority_type_t type, int flags)
+static const routerstatus_t *
+router_pick_directory_server_impl(dirinfo_type_t type, int flags)
{
- or_options_t *options = get_options();
- routerstatus_t *result;
+ const or_options_t *options = get_options();
+ const node_t *result;
smartlist_t *direct, *tunnel;
smartlist_t *trusted_direct, *trusted_tunnel;
smartlist_t *overloaded_direct, *overloaded_tunnel;
@@ -1095,54 +1102,64 @@ router_pick_directory_server_impl(authority_type_t type, int flags)
overloaded_tunnel = smartlist_create();
/* Find all the running dirservers we know about. */
- SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *,
- status) {
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
int is_trusted;
- int is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now;
+ int is_overloaded;
tor_addr_t addr;
- if (!status->is_running || !status->dir_port || !status->is_valid)
+ const routerstatus_t *status = node->rs;
+ const country_t country = node->country;
+ if (!status)
continue;
- if (status->is_bad_directory)
+
+ if (!node->is_running || !status->dir_port || !node->is_valid)
+ continue;
+ if (node->is_bad_directory)
continue;
- if (requireother && router_digest_is_me(status->identity_digest))
+ if (requireother && router_digest_is_me(node->identity))
continue;
- if (type & V3_AUTHORITY) {
+ if (type & V3_DIRINFO) {
if (!(status->version_supports_v3_dir ||
- router_digest_is_trusted_dir_type(status->identity_digest,
- V3_AUTHORITY)))
+ router_digest_is_trusted_dir_type(node->identity,
+ V3_DIRINFO)))
continue;
}
- is_trusted = router_digest_is_trusted_dir(status->identity_digest);
- if ((type & V2_AUTHORITY) && !(status->is_v2_dir || is_trusted))
+ is_trusted = router_digest_is_trusted_dir(node->identity);
+ if ((type & V2_DIRINFO) && !(node->rs->is_v2_dir || is_trusted))
+ continue;
+ if ((type & EXTRAINFO_DIRINFO) &&
+ !router_supports_extrainfo(node->identity, 0))
continue;
- if ((type & EXTRAINFO_CACHE) &&
- !router_supports_extrainfo(status->identity_digest, 0))
+ if ((type & MICRODESC_DIRINFO) && !is_trusted &&
+ !node->rs->version_supports_microdesc_cache)
continue;
- if (try_excluding && options->ExcludeNodes &&
- routerset_contains_routerstatus(options->ExcludeNodes, status)) {
+ if (try_excluding &&
+ routerset_contains_routerstatus(options->ExcludeNodes, status,
+ country)) {
++n_excluded;
continue;
}
/* XXXX IP6 proposal 118 */
- tor_addr_from_ipv4h(&addr, status->addr);
+ tor_addr_from_ipv4h(&addr, node->rs->addr);
+
+ is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now;
if (prefer_tunnel &&
status->version_supports_begindir &&
(!fascistfirewall ||
fascist_firewall_allows_address_or(&addr, status->or_port)))
smartlist_add(is_trusted ? trusted_tunnel :
- is_overloaded ? overloaded_tunnel : tunnel, status);
+ is_overloaded ? overloaded_tunnel : tunnel, (void*)node);
else if (!fascistfirewall ||
fascist_firewall_allows_address_dir(&addr, status->dir_port))
smartlist_add(is_trusted ? trusted_direct :
- is_overloaded ? overloaded_direct : direct, status);
- } SMARTLIST_FOREACH_END(status);
+ is_overloaded ? overloaded_direct : direct, (void*)node);
+ } SMARTLIST_FOREACH_END(node);
if (smartlist_len(tunnel)) {
- result = routerstatus_sl_choose_by_bandwidth(tunnel, WEIGHT_FOR_DIR);
+ result = node_sl_choose_by_bandwidth(tunnel, WEIGHT_FOR_DIR);
} else if (smartlist_len(overloaded_tunnel)) {
- result = routerstatus_sl_choose_by_bandwidth(overloaded_tunnel,
+ result = node_sl_choose_by_bandwidth(overloaded_tunnel,
WEIGHT_FOR_DIR);
} else if (smartlist_len(trusted_tunnel)) {
/* FFFF We don't distinguish between trusteds and overloaded trusteds
@@ -1151,10 +1168,10 @@ router_pick_directory_server_impl(authority_type_t type, int flags)
* is a feature, but it could easily be a bug. -RD */
result = smartlist_choose(trusted_tunnel);
} else if (smartlist_len(direct)) {
- result = routerstatus_sl_choose_by_bandwidth(direct, WEIGHT_FOR_DIR);
+ result = node_sl_choose_by_bandwidth(direct, WEIGHT_FOR_DIR);
} else if (smartlist_len(overloaded_direct)) {
- result = routerstatus_sl_choose_by_bandwidth(overloaded_direct,
- WEIGHT_FOR_DIR);
+ result = node_sl_choose_by_bandwidth(overloaded_direct,
+ WEIGHT_FOR_DIR);
} else {
result = smartlist_choose(trusted_direct);
}
@@ -1173,26 +1190,27 @@ router_pick_directory_server_impl(authority_type_t type, int flags)
goto retry_without_exclude;
}
- return result;
+ return result ? result->rs : NULL;
}
/** Choose randomly from among the trusted dirservers that are up. Flags
* are as for router_pick_directory_server_impl().
*/
-static routerstatus_t *
-router_pick_trusteddirserver_impl(authority_type_t type, int flags,
+static const routerstatus_t *
+router_pick_trusteddirserver_impl(dirinfo_type_t type, int flags,
int *n_busy_out)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
smartlist_t *direct, *tunnel;
smartlist_t *overloaded_direct, *overloaded_tunnel;
- routerinfo_t *me = router_get_my_routerinfo();
- routerstatus_t *result;
+ const routerinfo_t *me = router_get_my_routerinfo();
+ const routerstatus_t *result;
time_t now = time(NULL);
const int requireother = ! (flags & PDS_ALLOW_SELF);
const int fascistfirewall = ! (flags & PDS_IGNORE_FASCISTFIREWALL);
const int prefer_tunnel = (flags & _PDS_PREFER_TUNNELED_DIR_CONNS);
const int no_serverdesc_fetching =(flags & PDS_NO_EXISTING_SERVERDESC_FETCH);
+ const int no_microdesc_fetching =(flags & PDS_NO_EXISTING_MICRODESC_FETCH);
int n_busy = 0;
int try_excluding = 1, n_excluded = 0;
@@ -1214,14 +1232,14 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags,
if (!d->is_running) continue;
if ((type & d->type) == 0)
continue;
- if ((type & EXTRAINFO_CACHE) &&
+ if ((type & EXTRAINFO_DIRINFO) &&
!router_supports_extrainfo(d->digest, 1))
continue;
if (requireother && me && router_digest_is_me(d->digest))
continue;
- if (try_excluding && options->ExcludeNodes &&
+ if (try_excluding &&
routerset_contains_routerstatus(options->ExcludeNodes,
- &d->fake_status)) {
+ &d->fake_status, -1)) {
++n_excluded;
continue;
}
@@ -1240,6 +1258,13 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags,
continue;
}
}
+ if (no_microdesc_fetching) {
+ if (connection_get_by_type_addr_port_purpose(
+ CONN_TYPE_DIR, &addr, d->dir_port, DIR_PURPOSE_FETCH_MICRODESC)) {
+ ++n_busy;
+ continue;
+ }
+ }
if (prefer_tunnel &&
d->or_port &&
@@ -1287,22 +1312,18 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags,
static void
mark_all_trusteddirservers_up(void)
{
- if (routerlist) {
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- if (router_digest_is_trusted_dir(router->cache_info.identity_digest) &&
- router->dir_port > 0) {
- router->is_running = 1;
- });
- }
+ SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node, {
+ if (router_digest_is_trusted_dir(node->identity))
+ node->is_running = 1;
+ });
if (trusted_dir_servers) {
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, dir,
{
routerstatus_t *rs;
dir->is_running = 1;
download_status_reset(&dir->v2_ns_dl_status);
- rs = router_get_consensus_status_by_id(dir->digest);
- if (rs && !rs->is_running) {
- rs->is_running = 1;
+ rs = router_get_mutable_consensus_status_by_id(dir->digest);
+ if (rs) {
rs->last_dir_503_at = 0;
control_event_networkstatus_changed_single(rs);
}
@@ -1326,148 +1347,160 @@ router_reset_status_download_failures(void)
mark_all_trusteddirservers_up();
}
-/** Return true iff router1 and router2 have the same /16 network. */
+/** Return true iff router1 and router2 have similar enough network addresses
+ * that we should treat them as being in the same family */
static INLINE int
-routers_in_same_network_family(routerinfo_t *r1, routerinfo_t *r2)
+addrs_in_same_network_family(const tor_addr_t *a1,
+ const tor_addr_t *a2)
{
- return (r1->addr & 0xffff0000) == (r2->addr & 0xffff0000);
+ /* XXXX MOVE ? */
+ return 0 == tor_addr_compare_masked(a1, a2, 16, CMP_SEMANTIC);
}
-/** Look through the routerlist and identify routers that
- * advertise the same /16 network address as <b>router</b>.
- * Add each of them to <b>sl</b>.
+/**
+ * Add all the family of <b>node</b>, including <b>node</b> itself, to
+ * the smartlist <b>sl</b>.
+ *
+ * This is used to make sure we don't pick siblings in a single path, or
+ * pick more than one relay from a family for our entry guard list.
+ * Note that a node may be added to <b>sl</b> more than once if it is
+ * part of <b>node</b>'s family for more than one reason.
*/
-static void
-routerlist_add_network_family(smartlist_t *sl, routerinfo_t *router)
+void
+nodelist_add_node_and_family(smartlist_t *sl, const node_t *node)
{
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, r,
+ /* XXXX MOVE */
+ const smartlist_t *all_nodes = nodelist_get_list();
+ const smartlist_t *declared_family;
+ const or_options_t *options = get_options();
+
+ tor_assert(node);
+
+ declared_family = node_get_declared_family(node);
+
+ /* Let's make sure that we have the node itself, if it's a real node. */
{
- if (router != r && routers_in_same_network_family(router, r))
- smartlist_add(sl, r);
- });
-}
+ const node_t *real_node = node_get_by_id(node->identity);
+ if (real_node)
+ smartlist_add(sl, (node_t*)real_node);
+ }
-/** Add all the family of <b>router</b> to the smartlist <b>sl</b>.
- * This is used to make sure we don't pick siblings in a single path,
- * or pick more than one relay from a family for our entry guard list.
- */
-void
-routerlist_add_family(smartlist_t *sl, routerinfo_t *router)
-{
- routerinfo_t *r;
- config_line_t *cl;
- or_options_t *options = get_options();
+ /* First, add any nodes with similar network addresses. */
+ if (options->EnforceDistinctSubnets) {
+ tor_addr_t node_addr;
+ node_get_addr(node, &node_addr);
- /* First, add any routers with similar network addresses. */
- if (options->EnforceDistinctSubnets)
- routerlist_add_network_family(sl, router);
+ SMARTLIST_FOREACH_BEGIN(all_nodes, const node_t *, node2) {
+ tor_addr_t a;
+ node_get_addr(node2, &a);
+ if (addrs_in_same_network_family(&a, &node_addr))
+ smartlist_add(sl, (void*)node2);
+ } SMARTLIST_FOREACH_END(node2);
+ }
- if (router->declared_family) {
- /* Add every r such that router declares familyness with r, and r
+ /* Now, add all nodes in the declared_family of this node, if they
+ * also declare this node to be in their family. */
+ if (declared_family) {
+ /* Add every r such that router declares familyness with node, and node
* declares familyhood with router. */
- SMARTLIST_FOREACH(router->declared_family, const char *, n,
- {
- if (!(r = router_get_by_nickname(n, 0)))
- continue;
- if (!r->declared_family)
- continue;
- SMARTLIST_FOREACH(r->declared_family, const char *, n2,
- {
- if (router_nickname_matches(router, n2))
- smartlist_add(sl, r);
- });
- });
+ SMARTLIST_FOREACH_BEGIN(declared_family, const char *, name) {
+ const node_t *node2;
+ const smartlist_t *family2;
+ if (!(node2 = node_get_by_nickname(name, 0)))
+ continue;
+ if (!(family2 = node_get_declared_family(node2)))
+ continue;
+ SMARTLIST_FOREACH_BEGIN(family2, const char *, name2) {
+ if (node_nickname_matches(node, name2)) {
+ smartlist_add(sl, (void*)node2);
+ break;
+ }
+ } SMARTLIST_FOREACH_END(name2);
+ } SMARTLIST_FOREACH_END(name);
}
/* If the user declared any families locally, honor those too. */
- for (cl = options->NodeFamilies; cl; cl = cl->next) {
- if (router_nickname_is_in_list(router, cl->value)) {
- add_nickname_list_to_smartlist(sl, cl->value, 0);
- }
+ if (options->NodeFamilySets) {
+ SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, {
+ if (routerset_contains_node(rs, node)) {
+ routerset_get_all_nodes(sl, rs, NULL, 0);
+ }
+ });
}
}
-/** Return true iff r is named by some nickname in <b>lst</b>. */
+/** Given a <b>router</b>, add every node_t in its family (including the
+ * node itself</b>) to <b>sl</b>.
+ *
+ * Note the type mismatch: This function takes a routerinfo, but adds nodes
+ * to the smartlist!
+ */
+static void
+routerlist_add_node_and_family(smartlist_t *sl, const routerinfo_t *router)
+{
+ /* XXXX MOVE ? */
+ node_t fake_node;
+ const node_t *node = node_get_by_id(router->cache_info.identity_digest);;
+ if (node == NULL) {
+ memset(&fake_node, 0, sizeof(fake_node));
+ fake_node.ri = (routerinfo_t *)router;
+ memcpy(fake_node.identity, router->cache_info.identity_digest, DIGEST_LEN);
+ node = &fake_node;
+ }
+ nodelist_add_node_and_family(sl, node);
+}
+
+/** Return true iff <b>node</b> is named by some nickname in <b>lst</b>. */
static INLINE int
-router_in_nickname_smartlist(smartlist_t *lst, routerinfo_t *r)
+node_in_nickname_smartlist(const smartlist_t *lst, const node_t *node)
{
+ /* XXXX MOVE */
if (!lst) return 0;
- SMARTLIST_FOREACH(lst, const char *, name,
- if (router_nickname_matches(r, name))
- return 1;);
+ SMARTLIST_FOREACH(lst, const char *, name, {
+ if (node_nickname_matches(node, name))
+ return 1;
+ });
return 0;
}
/** Return true iff r1 and r2 are in the same family, but not the same
* router. */
int
-routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2)
+nodes_in_same_family(const node_t *node1, const node_t *node2)
{
- or_options_t *options = get_options();
- config_line_t *cl;
-
- if (options->EnforceDistinctSubnets && routers_in_same_network_family(r1,r2))
- return 1;
-
- if (router_in_nickname_smartlist(r1->declared_family, r2) &&
- router_in_nickname_smartlist(r2->declared_family, r1))
- return 1;
+ /* XXXX MOVE */
+ const or_options_t *options = get_options();
- for (cl = options->NodeFamilies; cl; cl = cl->next) {
- if (router_nickname_is_in_list(r1, cl->value) &&
- router_nickname_is_in_list(r2, cl->value))
+ /* Are they in the same family because of their addresses? */
+ if (options->EnforceDistinctSubnets) {
+ tor_addr_t a1, a2;
+ node_get_addr(node1, &a1);
+ node_get_addr(node2, &a2);
+ if (addrs_in_same_network_family(&a1, &a2))
return 1;
}
- return 0;
-}
-
-/** Given a (possibly NULL) comma-and-whitespace separated list of nicknames,
- * see which nicknames in <b>list</b> name routers in our routerlist, and add
- * the routerinfos for those routers to <b>sl</b>. If <b>must_be_running</b>,
- * only include routers that we think are running.
- * Warn if any non-Named routers are specified by nickname.
- */
-void
-add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
- int must_be_running)
-{
- routerinfo_t *router;
- smartlist_t *nickname_list;
- int have_dir_info = router_have_minimum_dir_info();
- if (!list)
- return; /* nothing to do */
- tor_assert(sl);
-
- nickname_list = smartlist_create();
- if (!warned_nicknames)
- warned_nicknames = smartlist_create();
+ /* Are they in the same family because the agree they are? */
+ {
+ const smartlist_t *f1, *f2;
+ f1 = node_get_declared_family(node1);
+ f2 = node_get_declared_family(node2);
+ if (f1 && f2 &&
+ node_in_nickname_smartlist(f1, node2) &&
+ node_in_nickname_smartlist(f2, node1))
+ return 1;
+ }
- smartlist_split_string(nickname_list, list, ",",
- SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ /* Are they in the same option because the user says they are? */
+ if (options->NodeFamilySets) {
+ SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, {
+ if (routerset_contains_node(rs, node1) &&
+ routerset_contains_node(rs, node2))
+ return 1;
+ });
+ }
- SMARTLIST_FOREACH(nickname_list, const char *, nick, {
- int warned;
- if (!is_legal_nickname_or_hexdigest(nick)) {
- log_warn(LD_CONFIG, "Nickname '%s' is misformed; skipping", nick);
- continue;
- }
- router = router_get_by_nickname(nick, 1);
- warned = smartlist_string_isin(warned_nicknames, nick);
- if (router) {
- if (!must_be_running || router->is_running) {
- smartlist_add(sl,router);
- }
- } else if (!router_get_consensus_status_by_nickname(nick,1)) {
- if (!warned) {
- log_fn(have_dir_info ? LOG_WARN : LOG_INFO, LD_CONFIG,
- "Nickname list includes '%s' which isn't a known router.",nick);
- smartlist_add(warned_nicknames, tor_strdup(nick));
- }
- }
- });
- SMARTLIST_FOREACH(nickname_list, char *, nick, tor_free(nick));
- smartlist_free(nickname_list);
+ return 0;
}
/** Return 1 iff any member of the (possibly NULL) comma-separated list
@@ -1475,7 +1508,7 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
* return 0.
*/
int
-router_nickname_is_in_list(routerinfo_t *router, const char *list)
+router_nickname_is_in_list(const routerinfo_t *router, const char *list)
{
smartlist_t *nickname_list;
int v = 0;
@@ -1494,34 +1527,32 @@ router_nickname_is_in_list(routerinfo_t *router, const char *list)
return v;
}
-/** Add every suitable router from our routerlist to <b>sl</b>, so that
+/** Add every suitable node from our nodelist to <b>sl</b>, so that
* we can pick a node for a circuit.
*/
static void
-router_add_running_routers_to_smartlist(smartlist_t *sl, int allow_invalid,
- int need_uptime, int need_capacity,
- int need_guard)
-{
- if (!routerlist)
- return;
+router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid,
+ int need_uptime, int need_capacity,
+ int need_guard, int need_desc)
+{ /* XXXX MOVE */
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
+ if (!node->is_running ||
+ (!node->is_valid && !allow_invalid))
+ continue;
+ if (need_desc && !(node->ri || (node->rs && node->md)))
+ continue;
+ if (node->ri && node->ri->purpose != ROUTER_PURPOSE_GENERAL)
+ continue;
+ if (node_is_unreliable(node, need_uptime, need_capacity, need_guard))
+ continue;
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- {
- if (router->is_running &&
- router->purpose == ROUTER_PURPOSE_GENERAL &&
- (router->is_valid || allow_invalid) &&
- !router_is_unreliable(router, need_uptime,
- need_capacity, need_guard)) {
- /* If it's running, and it's suitable according to the
- * other flags we had in mind */
- smartlist_add(sl, router);
- }
- });
+ smartlist_add(sl, (void *)node);
+ } SMARTLIST_FOREACH_END(node);
}
/** Look through the routerlist until we find a router that has my key.
Return it. */
-routerinfo_t *
+const routerinfo_t *
routerlist_find_my_routerinfo(void)
{
if (!routerlist)
@@ -1541,13 +1572,13 @@ routerlist_find_my_routerinfo(void)
* Don't exit enclave to excluded relays -- it wouldn't actually
* hurt anything, but this way there are fewer confused users.
*/
-routerinfo_t *
+const node_t *
router_find_exact_exit_enclave(const char *address, uint16_t port)
-{
+{/*XXXX MOVE*/
uint32_t addr;
struct in_addr in;
tor_addr_t a;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (!tor_inet_aton(address, &in))
return NULL; /* it's not an IP already */
@@ -1555,14 +1586,13 @@ router_find_exact_exit_enclave(const char *address, uint16_t port)
tor_addr_from_ipv4h(&a, addr);
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- {
- if (router->addr == addr &&
- router->is_running &&
- compare_tor_addr_to_addr_policy(&a, port, router->exit_policy) ==
+ SMARTLIST_FOREACH(nodelist_get_list(), const node_t *, node, {
+ if (node_get_addr_ipv4h(node) == addr &&
+ node->is_running &&
+ compare_tor_addr_to_node_policy(&a, port, node) ==
ADDR_POLICY_ACCEPTED &&
- !routerset_contains_router(options->_ExcludeExitNodesUnion, router))
- return router;
+ !routerset_contains_node(options->_ExcludeExitNodesUnion, node))
+ return node;
});
return NULL;
}
@@ -1574,14 +1604,14 @@ router_find_exact_exit_enclave(const char *address, uint16_t port)
* If <b>need_guard</b>, we require that the router is a possible entry guard.
*/
int
-router_is_unreliable(routerinfo_t *router, int need_uptime,
- int need_capacity, int need_guard)
+node_is_unreliable(const node_t *node, int need_uptime,
+ int need_capacity, int need_guard)
{
- if (need_uptime && !router->is_stable)
+ if (need_uptime && !node->is_stable)
return 1;
- if (need_capacity && !router->is_fast)
+ if (need_capacity && !node->is_fast)
return 1;
- if (need_guard && !router->is_possible_guard)
+ if (need_guard && !node->is_possible_guard)
return 1;
return 0;
}
@@ -1589,7 +1619,7 @@ router_is_unreliable(routerinfo_t *router, int need_uptime,
/** Return the smaller of the router's configured BandwidthRate
* and its advertised capacity. */
uint32_t
-router_get_advertised_bandwidth(routerinfo_t *router)
+router_get_advertised_bandwidth(const routerinfo_t *router)
{
if (router->bandwidthcapacity < router->bandwidthrate)
return router->bandwidthcapacity;
@@ -1603,7 +1633,7 @@ router_get_advertised_bandwidth(routerinfo_t *router)
/** Return the smaller of the router's configured BandwidthRate
* and its advertised capacity, capped by max-believe-bw. */
uint32_t
-router_get_advertised_bandwidth_capped(routerinfo_t *router)
+router_get_advertised_bandwidth_capped(const routerinfo_t *router)
{
uint32_t result = router->bandwidthcapacity;
if (result > router->bandwidthrate)
@@ -1645,13 +1675,10 @@ kb_to_bytes(uint32_t bw)
}
/** Helper function:
- * choose a random element of smartlist <b>sl</b>, weighted by
+ * choose a random element of smartlist <b>sl</b> of nodes, weighted by
* the advertised bandwidth of each element using the consensus
* bandwidth weights.
*
- * If <b>statuses</b> is zero, then <b>sl</b> is a list of
- * routerinfo_t's. Otherwise it's a list of routerstatus_t's.
- *
* If <b>rule</b>==WEIGHT_FOR_EXIT. we're picking an exit node: consider all
* nodes' bandwidth equally regardless of their Exit status, since there may
* be some in the list because they exit to obscure ports. If
@@ -1661,10 +1688,9 @@ kb_to_bytes(uint32_t bw)
* guard node: consider all guard's bandwidth equally. Otherwise, weight
* guards proportionally less.
*/
-static void *
-smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
- bandwidth_weight_rule_t rule,
- int statuses)
+static const node_t *
+smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl,
+ bandwidth_weight_rule_t rule)
{
int64_t weight_scale;
int64_t rand_bw;
@@ -1758,15 +1784,14 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
bandwidths = tor_malloc_zero(sizeof(double)*smartlist_len(sl));
// Cycle through smartlist and total the bandwidth.
- for (i = 0; i < (unsigned)smartlist_len(sl); ++i) {
+ SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) {
int is_exit = 0, is_guard = 0, is_dir = 0, this_bw = 0, is_me = 0;
double weight = 1;
- if (statuses) {
- routerstatus_t *status = smartlist_get(sl, i);
- is_exit = status->is_exit && !status->is_bad_exit;
- is_guard = status->is_possible_guard;
- is_dir = (status->dir_port != 0);
- if (!status->has_bandwidth) {
+ is_exit = node->is_exit && ! node->is_bad_exit;
+ is_guard = node->is_possible_guard;
+ is_dir = node_is_dir(node);
+ if (node->rs) {
+ if (!node->rs->has_bandwidth) {
tor_free(bandwidths);
/* This should never happen, unless all the authorites downgrade
* to 0.2.0 or rogue routerstatuses get inserted into our consensus. */
@@ -1775,26 +1800,17 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
"old router selection algorithm.");
return NULL;
}
- this_bw = kb_to_bytes(status->bandwidth);
- if (router_digest_is_me(status->identity_digest))
- is_me = 1;
+ this_bw = kb_to_bytes(node->rs->bandwidth);
+ } else if (node->ri) {
+ /* bridge or other descriptor not in our consensus */
+ this_bw = bridge_get_advertised_bandwidth_bounded(node->ri);
+ have_unknown = 1;
} else {
- routerstatus_t *rs;
- routerinfo_t *router = smartlist_get(sl, i);
- rs = router_get_consensus_status_by_id(
- router->cache_info.identity_digest);
- is_exit = router->is_exit && !router->is_bad_exit;
- is_guard = router->is_possible_guard;
- is_dir = (router->dir_port != 0);
- if (rs && rs->has_bandwidth) {
- this_bw = kb_to_bytes(rs->bandwidth);
- } else { /* bridge or other descriptor not in our consensus */
- this_bw = bridge_get_advertised_bandwidth_bounded(router);
- have_unknown = 1;
- }
- if (router_digest_is_me(router->cache_info.identity_digest))
- is_me = 1;
+ /* We can't use this one. */
+ continue;
}
+ is_me = router_digest_is_me(node->identity);
+
if (is_guard && is_exit) {
weight = (is_dir ? Wdb*Wd : Wd);
} else if (is_guard) {
@@ -1805,17 +1821,17 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
weight = (is_dir ? Wmb*Wm : Wm);
}
- bandwidths[i] = weight*this_bw;
+ bandwidths[node_sl_idx] = weight*this_bw;
weighted_bw += weight*this_bw;
if (is_me)
sl_last_weighted_bw_of_me = weight*this_bw;
- }
+ } SMARTLIST_FOREACH_END(node);
/* XXXX023 this is a kludge to expose these values. */
sl_last_total_weighted_bw = weighted_bw;
log_debug(LD_CIRC, "Choosing node for rule %s based on weights "
- "Wg=%lf Wm=%lf We=%lf Wd=%lf with total bw %lf",
+ "Wg=%f Wm=%f We=%f Wd=%f with total bw %f",
bandwidth_weight_rule_to_string(rule),
Wg, Wm, We, Wd, weighted_bw);
@@ -1824,7 +1840,7 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
/* Don't warn when using bridges/relays not in the consensus */
if (!have_unknown)
log_warn(LD_CIRC,
- "Weighted bandwidth is %lf in node selection for rule %s",
+ "Weighted bandwidth is %f in node selection for rule %s",
weighted_bw, bandwidth_weight_rule_to_string(rule));
tor_free(bandwidths);
return smartlist_choose(sl);
@@ -1849,7 +1865,7 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
--i;
log_warn(LD_BUG, "Round-off error in computing bandwidth had an effect on "
" which router we chose. Please tell the developers. "
- "%lf " U64_FORMAT " %lf", tmp, U64_PRINTF_ARG(rand_bw),
+ "%f " U64_FORMAT " %f", tmp, U64_PRINTF_ARG(rand_bw),
weighted_bw);
}
tor_free(bandwidths);
@@ -1857,12 +1873,9 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
}
/** Helper function:
- * choose a random element of smartlist <b>sl</b>, weighted by
+ * choose a random node_t element of smartlist <b>sl</b>, weighted by
* the advertised bandwidth of each element.
*
- * If <b>statuses</b> is zero, then <b>sl</b> is a list of
- * routerinfo_t's. Otherwise it's a list of routerstatus_t's.
- *
* If <b>rule</b>==WEIGHT_FOR_EXIT. we're picking an exit node: consider all
* nodes' bandwidth equally regardless of their Exit status, since there may
* be some in the list because they exit to obscure ports. If
@@ -1872,13 +1885,11 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl,
* guard node: consider all guard's bandwidth equally. Otherwise, weight
* guards proportionally less.
*/
-static void *
-smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
- int statuses)
+static const node_t *
+smartlist_choose_node_by_bandwidth(smartlist_t *sl,
+ bandwidth_weight_rule_t rule)
{
- unsigned int i;
- routerinfo_t *router;
- routerstatus_t *status=NULL;
+ unsigned i;
int32_t *bandwidths;
int is_exit;
int is_guard;
@@ -1919,49 +1930,34 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
guard_bits = bitarray_init_zero(smartlist_len(sl));
/* Iterate over all the routerinfo_t or routerstatus_t, and */
- for (i = 0; i < (unsigned)smartlist_len(sl); ++i) {
+ SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) {
/* first, learn what bandwidth we think i has */
int is_known = 1;
int32_t flags = 0;
uint32_t this_bw = 0;
- if (statuses) {
- status = smartlist_get(sl, i);
- if (router_digest_is_me(status->identity_digest))
- me_idx = i;
- router = router_get_by_digest(status->identity_digest);
- is_exit = status->is_exit;
- is_guard = status->is_possible_guard;
- if (status->has_bandwidth) {
- this_bw = kb_to_bytes(status->bandwidth);
+ i = node_sl_idx;
+
+ if (router_digest_is_me(node->identity))
+ me_idx = node_sl_idx;
+
+ is_exit = node->is_exit;
+ is_guard = node->is_possible_guard;
+ if (node->rs) {
+ if (node->rs->has_bandwidth) {
+ this_bw = kb_to_bytes(node->rs->bandwidth);
} else { /* guess */
/* XXX023 once consensuses always list bandwidths, we can take
* this guessing business out. -RD */
is_known = 0;
- flags = status->is_fast ? 1 : 0;
+ flags = node->rs->is_fast ? 1 : 0;
flags |= is_exit ? 2 : 0;
flags |= is_guard ? 4 : 0;
}
- } else {
- routerstatus_t *rs;
- router = smartlist_get(sl, i);
- rs = router_get_consensus_status_by_id(
- router->cache_info.identity_digest);
- if (router_digest_is_me(router->cache_info.identity_digest))
- me_idx = i;
- is_exit = router->is_exit;
- is_guard = router->is_possible_guard;
- if (rs && rs->has_bandwidth) {
- this_bw = kb_to_bytes(rs->bandwidth);
- } else if (rs) { /* guess; don't trust the descriptor */
- /* XXX023 once consensuses always list bandwidths, we can take
- * this guessing business out. -RD */
- is_known = 0;
- flags = router->is_fast ? 1 : 0;
- flags |= is_exit ? 2 : 0;
- flags |= is_guard ? 4 : 0;
- } else /* bridge or other descriptor not in our consensus */
- this_bw = bridge_get_advertised_bandwidth_bounded(router);
+ } else if (node->ri) {
+ /* Must be a bridge if we're willing to use it */
+ this_bw = bridge_get_advertised_bandwidth_bounded(node->ri);
}
+
if (is_exit)
bitarray_set(exit_bits, i);
if (is_guard)
@@ -1981,9 +1977,9 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
total_nonexit_bw += this_bw;
} else {
++n_unknown;
- bandwidths[i] = -flags;
+ bandwidths[node_sl_idx] = -flags;
}
- }
+ } SMARTLIST_FOREACH_END(node);
/* Now, fill in the unknown values. */
if (n_unknown) {
@@ -2074,10 +2070,10 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
log_debug(LD_CIRC, "Total weighted bw = "U64_FORMAT
", exit bw = "U64_FORMAT
- ", nonexit bw = "U64_FORMAT", exit weight = %lf "
+ ", nonexit bw = "U64_FORMAT", exit weight = %f "
"(for exit == %d)"
", guard bw = "U64_FORMAT
- ", nonguard bw = "U64_FORMAT", guard weight = %lf "
+ ", nonguard bw = "U64_FORMAT", guard weight = %f "
"(for guard == %d)",
U64_PRINTF_ARG(total_bw),
U64_PRINTF_ARG(total_exit_bw), U64_PRINTF_ARG(total_nonexit_bw),
@@ -2125,40 +2121,23 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule,
return smartlist_get(sl, i);
}
-/** Choose a random element of router list <b>sl</b>, weighted by
- * the advertised bandwidth of each router.
- */
-routerinfo_t *
-routerlist_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule)
-{
- routerinfo_t *ret;
- if ((ret = smartlist_choose_by_bandwidth_weights(sl, rule, 0))) {
- return ret;
- } else {
- return smartlist_choose_by_bandwidth(sl, rule, 0);
- }
-}
-
/** Choose a random element of status list <b>sl</b>, weighted by
- * the advertised bandwidth of each status.
- */
-routerstatus_t *
-routerstatus_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule)
-{
- /* We are choosing neither exit nor guard here. Weight accordingly. */
- routerstatus_t *ret;
- if ((ret = smartlist_choose_by_bandwidth_weights(sl, rule, 1))) {
+ * the advertised bandwidth of each node */
+const node_t *
+node_sl_choose_by_bandwidth(smartlist_t *sl,
+ bandwidth_weight_rule_t rule)
+{ /*XXXX MOVE */
+ const node_t *ret;
+ if ((ret = smartlist_choose_node_by_bandwidth_weights(sl, rule))) {
return ret;
} else {
- return smartlist_choose_by_bandwidth(sl, rule, 1);
+ return smartlist_choose_node_by_bandwidth(sl, rule);
}
}
-/** Return a random running router from the routerlist. Never
- * pick a node whose routerinfo is in
- * <b>excludedsmartlist</b>, or whose routerinfo matches <b>excludedset</b>,
+/** Return a random running node from the nodelist. Never
+ * pick a node that is in
+ * <b>excludedsmartlist</b>, or which matches <b>excludedset</b>,
* even if they are the only nodes available.
* If <b>CRN_NEED_UPTIME</b> is set in flags and any router has more than
* a minimum uptime, return one of those.
@@ -2170,21 +2149,26 @@ routerstatus_sl_choose_by_bandwidth(smartlist_t *sl,
* If <b>CRN_WEIGHT_AS_EXIT</b> is set in flags, we weight bandwidths as if
* picking an exit node, otherwise we weight bandwidths for picking a relay
* node (that is, possibly discounting exit nodes).
+ * If <b>CRN_NEED_DESC</b> is set in flags, we only consider nodes that
+ * have a routerinfo or microdescriptor -- that is, enough info to be
+ * used to build a circuit.
*/
-routerinfo_t *
+const node_t *
router_choose_random_node(smartlist_t *excludedsmartlist,
routerset_t *excludedset,
router_crn_flags_t flags)
-{
+{ /* XXXX MOVE */
const int need_uptime = (flags & CRN_NEED_UPTIME) != 0;
const int need_capacity = (flags & CRN_NEED_CAPACITY) != 0;
const int need_guard = (flags & CRN_NEED_GUARD) != 0;
const int allow_invalid = (flags & CRN_ALLOW_INVALID) != 0;
const int weight_for_exit = (flags & CRN_WEIGHT_AS_EXIT) != 0;
+ const int need_desc = (flags & CRN_NEED_DESC) != 0;
smartlist_t *sl=smartlist_create(),
- *excludednodes=smartlist_create();
- routerinfo_t *choice = NULL, *r;
+ *excludednodes=smartlist_create();
+ const node_t *choice = NULL;
+ const routerinfo_t *r;
bandwidth_weight_rule_t rule;
tor_assert(!(weight_for_exit && need_guard));
@@ -2194,29 +2178,26 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
/* Exclude relays that allow single hop exit circuits, if the user
* wants to (such relays might be risky) */
if (get_options()->ExcludeSingleHopRelays) {
- routerlist_t *rl = router_get_routerlist();
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
- if (r->allow_single_hop_exits) {
- smartlist_add(excludednodes, r);
+ SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node,
+ if (node_allows_single_hop_exits(node)) {
+ smartlist_add(excludednodes, node);
});
}
- if ((r = routerlist_find_my_routerinfo())) {
- smartlist_add(excludednodes, r);
- routerlist_add_family(excludednodes, r);
- }
+ if ((r = routerlist_find_my_routerinfo()))
+ routerlist_add_node_and_family(excludednodes, r);
- router_add_running_routers_to_smartlist(sl, allow_invalid,
- need_uptime, need_capacity,
- need_guard);
+ router_add_running_nodes_to_smartlist(sl, allow_invalid,
+ need_uptime, need_capacity,
+ need_guard, need_desc);
smartlist_subtract(sl,excludednodes);
if (excludedsmartlist)
smartlist_subtract(sl,excludedsmartlist);
if (excludedset)
- routerset_subtract_routers(sl,excludedset);
+ routerset_subtract_nodes(sl,excludedset);
// Always weight by bandwidth
- choice = routerlist_sl_choose_by_bandwidth(sl, rule);
+ choice = node_sl_choose_by_bandwidth(sl, rule);
smartlist_free(sl);
if (!choice && (need_uptime || need_capacity || need_guard)) {
@@ -2239,35 +2220,90 @@ router_choose_random_node(smartlist_t *excludedsmartlist,
return choice;
}
-/** Helper: Return true iff the <b>identity_digest</b> and <b>nickname</b>
- * combination of a router, encoded in hexadecimal, matches <b>hexdigest</b>
- * (which is optionally prefixed with a single dollar sign). Return false if
- * <b>hexdigest</b> is malformed, or it doesn't match. */
-static INLINE int
-hex_digest_matches(const char *hexdigest, const char *identity_digest,
- const char *nickname, int is_named)
+/** Helper: given an extended nickname in <b>hexdigest</b> try to decode it.
+ * Return 0 on success, -1 on failure. Store the result into the
+ * DIGEST_LEN-byte buffer at <b>digest_out</b>, the single character at
+ * <b>nickname_qualifier_char_out</b>, and the MAXNICKNAME_LEN+1-byte buffer
+ * at <b>nickname_out</b>.
+ *
+ * The recognized format is:
+ * HexName = Dollar? HexDigest NamePart?
+ * Dollar = '?'
+ * HexDigest = HexChar*20
+ * HexChar = 'a'..'f' | 'A'..'F' | '0'..'9'
+ * NamePart = QualChar Name
+ * QualChar = '=' | '~'
+ * Name = NameChar*(1..MAX_NICKNAME_LEN)
+ * NameChar = Any ASCII alphanumeric character
+ */
+int
+hex_digest_nickname_decode(const char *hexdigest,
+ char *digest_out,
+ char *nickname_qualifier_char_out,
+ char *nickname_out)
{
- char digest[DIGEST_LEN];
size_t len;
+
tor_assert(hexdigest);
if (hexdigest[0] == '$')
++hexdigest;
len = strlen(hexdigest);
- if (len < HEX_DIGEST_LEN)
+ if (len < HEX_DIGEST_LEN) {
+ return -1;
+ } else if (len > HEX_DIGEST_LEN && (hexdigest[HEX_DIGEST_LEN] == '=' ||
+ hexdigest[HEX_DIGEST_LEN] == '~') &&
+ len <= HEX_DIGEST_LEN+1+MAX_NICKNAME_LEN) {
+ *nickname_qualifier_char_out = hexdigest[HEX_DIGEST_LEN];
+ strlcpy(nickname_out, hexdigest+HEX_DIGEST_LEN+1 , MAX_NICKNAME_LEN+1);
+ } else if (len == HEX_DIGEST_LEN) {
+ ;
+ } else {
+ return -1;
+ }
+
+ if (base16_decode(digest_out, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0)
+ return -1;
+ return 0;
+}
+
+/** Helper: Return true iff the <b>identity_digest</b> and <b>nickname</b>
+ * combination of a router, encoded in hexadecimal, matches <b>hexdigest</b>
+ * (which is optionally prefixed with a single dollar sign). Return false if
+ * <b>hexdigest</b> is malformed, or it doesn't match. */
+static int
+hex_digest_nickname_matches(const char *hexdigest, const char *identity_digest,
+ const char *nickname, int is_named)
+{
+ char digest[DIGEST_LEN];
+ char nn_char='\0';
+ char nn_buf[MAX_NICKNAME_LEN+1];
+
+ if (hex_digest_nickname_decode(hexdigest, digest, &nn_char, nn_buf) == -1)
return 0;
- else if (len > HEX_DIGEST_LEN &&
- (hexdigest[HEX_DIGEST_LEN] == '=' ||
- hexdigest[HEX_DIGEST_LEN] == '~')) {
- if (strcasecmp(hexdigest+HEX_DIGEST_LEN+1, nickname))
+
+ if (nn_char == '=' || nn_char == '~') {
+ if (!nickname)
return 0;
- if (hexdigest[HEX_DIGEST_LEN] == '=' && !is_named)
+ if (strcasecmp(nn_buf, nickname))
+ return 0;
+ if (nn_char == '=' && !is_named)
return 0;
}
- if (base16_decode(digest, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0)
- return 0;
- return (tor_memeq(digest, identity_digest, DIGEST_LEN));
+ return tor_memeq(digest, identity_digest, DIGEST_LEN);
+}
+
+/* Return true iff <b>router</b> is listed as named in the current
+ * consensus. */
+int
+router_is_named(const routerinfo_t *router)
+{
+ const char *digest =
+ networkstatus_get_router_digest_by_nickname(router->nickname);
+
+ return (digest &&
+ tor_memeq(digest, router->cache_info.identity_digest, DIGEST_LEN));
}
/** Return true iff the digest of <b>router</b>'s identity key,
@@ -2275,10 +2311,12 @@ hex_digest_matches(const char *hexdigest, const char *identity_digest,
* optionally prefixed with a single dollar sign). Return false if
* <b>hexdigest</b> is malformed, or it doesn't match. */
static INLINE int
-router_hex_digest_matches(routerinfo_t *router, const char *hexdigest)
+router_hex_digest_matches(const routerinfo_t *router, const char *hexdigest)
{
- return hex_digest_matches(hexdigest, router->cache_info.identity_digest,
- router->nickname, router->is_named);
+ return hex_digest_nickname_matches(hexdigest,
+ router->cache_info.identity_digest,
+ router->nickname,
+ router_is_named(router));
}
/** Return true if <b>router</b>'s nickname matches <b>nickname</b>
@@ -2286,20 +2324,43 @@ router_hex_digest_matches(routerinfo_t *router, const char *hexdigest)
* matches a hexadecimal value stored in <b>nickname</b>. Return
* false otherwise. */
static int
-router_nickname_matches(routerinfo_t *router, const char *nickname)
+router_nickname_matches(const routerinfo_t *router, const char *nickname)
{
if (nickname[0]!='$' && !strcasecmp(router->nickname, nickname))
return 1;
return router_hex_digest_matches(router, nickname);
}
+/** Return true if <b>node</b>'s nickname matches <b>nickname</b>
+ * (case-insensitive), or if <b>node's</b> identity key digest
+ * matches a hexadecimal value stored in <b>nickname</b>. Return
+ * false otherwise. */
+static int
+node_nickname_matches(const node_t *node, const char *nickname)
+{
+ const char *n = node_get_nickname(node);
+ if (n && nickname[0]!='$' && !strcasecmp(n, nickname))
+ return 1;
+ return hex_digest_nickname_matches(nickname,
+ node->identity,
+ n,
+ node_is_named(node));
+}
+
/** Return the router in our routerlist whose (case-insensitive)
* nickname or (case-sensitive) hexadecimal key digest is
* <b>nickname</b>. Return NULL if no such router is known.
*/
-routerinfo_t *
+const routerinfo_t *
router_get_by_nickname(const char *nickname, int warn_if_unnamed)
{
+#if 1
+ const node_t *node = node_get_by_nickname(nickname, warn_if_unnamed);
+ if (node)
+ return node->ri;
+ else
+ return NULL;
+#else
int maybedigest;
char digest[DIGEST_LEN];
routerinfo_t *best_match=NULL;
@@ -2345,15 +2406,14 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
if (warn_if_unnamed && n_matches > 1) {
smartlist_t *fps = smartlist_create();
int any_unwarned = 0;
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- {
+ SMARTLIST_FOREACH_BEGIN(routerlist->routers, routerinfo_t *, router) {
routerstatus_t *rs;
char *desc;
size_t dlen;
char fp[HEX_DIGEST_LEN+1];
if (strcasecmp(router->nickname, nickname))
continue;
- rs = router_get_consensus_status_by_id(
+ rs = router_get_mutable_consensus_status_by_id(
router->cache_info.identity_digest);
if (rs && !rs->name_lookup_warned) {
rs->name_lookup_warned = 1;
@@ -2366,7 +2426,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
tor_snprintf(desc, dlen, "\"$%s\" for the one at %s:%d",
fp, router->address, router->or_port);
smartlist_add(fps, desc);
- });
+ } SMARTLIST_FOREACH_END(router);
if (any_unwarned) {
char *alternatives = smartlist_join_strings(fps, "; ",0,NULL);
log_warn(LD_CONFIG,
@@ -2379,7 +2439,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
SMARTLIST_FOREACH(fps, char *, cp, tor_free(cp));
smartlist_free(fps);
} else if (warn_if_unnamed) {
- routerstatus_t *rs = router_get_consensus_status_by_id(
+ routerstatus_t *rs = router_get_mutable_consensus_status_by_id(
best_match->cache_info.identity_digest);
if (rs && !rs->name_lookup_warned) {
char fp[HEX_DIGEST_LEN+1];
@@ -2395,27 +2455,15 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
}
return best_match;
}
-
return NULL;
-}
-
-/** Try to find a routerinfo for <b>digest</b>. If we don't have one,
- * return 1. If we do, ask tor_version_as_new_as() for the answer.
- */
-int
-router_digest_version_as_new_as(const char *digest, const char *cutoff)
-{
- routerinfo_t *router = router_get_by_digest(digest);
- if (!router)
- return 1;
- return tor_version_as_new_as(router->platform, cutoff);
+#endif
}
/** Return true iff <b>digest</b> is the digest of the identity key of a
* trusted directory matching at least one bit of <b>type</b>. If <b>type</b>
* is zero, any authority is okay. */
int
-router_digest_is_trusted_dir_type(const char *digest, authority_type_t type)
+router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type)
{
if (!trusted_dir_servers)
return 0;
@@ -2459,44 +2507,20 @@ hexdigest_to_digest(const char *hexdigest, char *digest)
/** Return the router in our routerlist whose hexadecimal key digest
* is <b>hexdigest</b>. Return NULL if no such router is known. */
-routerinfo_t *
+const routerinfo_t *
router_get_by_hexdigest(const char *hexdigest)
{
- char digest[DIGEST_LEN];
- size_t len;
- routerinfo_t *ri;
-
- tor_assert(hexdigest);
- if (!routerlist)
- return NULL;
- if (hexdigest[0]=='$')
- ++hexdigest;
- len = strlen(hexdigest);
- if (hexdigest_to_digest(hexdigest, digest) < 0)
+ if (is_legal_nickname(hexdigest))
return NULL;
- ri = router_get_by_digest(digest);
-
- if (ri && len > HEX_DIGEST_LEN) {
- if (hexdigest[HEX_DIGEST_LEN] == '=') {
- if (strcasecmp(ri->nickname, hexdigest+HEX_DIGEST_LEN+1) ||
- !ri->is_named)
- return NULL;
- } else if (hexdigest[HEX_DIGEST_LEN] == '~') {
- if (strcasecmp(ri->nickname, hexdigest+HEX_DIGEST_LEN+1))
- return NULL;
- } else {
- return NULL;
- }
- }
-
- return ri;
+ /* It's not a legal nickname, so it must be a hexdigest or nothing. */
+ return router_get_by_nickname(hexdigest, 1);
}
-/** Return the router in our routerlist whose 20-byte key digest
- * is <b>digest</b>. Return NULL if no such router is known. */
+/** As router_get_by_id_digest,but return a pointer that you're allowed to
+ * modify */
routerinfo_t *
-router_get_by_digest(const char *digest)
+router_get_mutable_by_digest(const char *digest)
{
tor_assert(digest);
@@ -2507,6 +2531,14 @@ router_get_by_digest(const char *digest)
return rimap_get(routerlist->identity_map, digest);
}
+/** Return the router in our routerlist whose 20-byte key digest
+ * is <b>digest</b>. Return NULL if no such router is known. */
+const routerinfo_t *
+router_get_by_id_digest(const char *digest)
+{
+ return router_get_mutable_by_digest(digest);
+}
+
/** Return the router in our routerlist whose 20-byte descriptor
* is <b>digest</b>. Return NULL if no such router is known. */
signed_descriptor_t *
@@ -2557,7 +2589,7 @@ extrainfo_get_by_descriptor_digest(const char *digest)
* The caller must not free the string returned.
*/
static const char *
-signed_descriptor_get_body_impl(signed_descriptor_t *desc,
+signed_descriptor_get_body_impl(const signed_descriptor_t *desc,
int with_annotations)
{
const char *r = NULL;
@@ -2606,7 +2638,7 @@ signed_descriptor_get_body_impl(signed_descriptor_t *desc,
* The caller must not free the string returned.
*/
const char *
-signed_descriptor_get_body(signed_descriptor_t *desc)
+signed_descriptor_get_body(const signed_descriptor_t *desc)
{
return signed_descriptor_get_body_impl(desc, 0);
}
@@ -2614,7 +2646,7 @@ signed_descriptor_get_body(signed_descriptor_t *desc)
/** As signed_descriptor_get_body(), but points to the beginning of the
* annotations section rather than the beginning of the descriptor. */
const char *
-signed_descriptor_get_annotations(signed_descriptor_t *desc)
+signed_descriptor_get_annotations(const signed_descriptor_t *desc)
{
return signed_descriptor_get_body_impl(desc, 1);
}
@@ -2667,7 +2699,6 @@ routerinfo_free(routerinfo_t *router)
}
addr_policy_list_free(router->exit_policy);
- /* XXXX Remove if this turns out to affect performance. */
memset(router, 77, sizeof(routerinfo_t));
tor_free(router);
@@ -2682,7 +2713,6 @@ extrainfo_free(extrainfo_t *extrainfo)
tor_free(extrainfo->cache_info.signed_descriptor_body);
tor_free(extrainfo->pending_sig);
- /* XXXX remove this if it turns out to slow us down. */
memset(extrainfo, 88, sizeof(extrainfo_t)); /* debug bad memory usage */
tor_free(extrainfo);
}
@@ -2696,7 +2726,6 @@ signed_descriptor_free(signed_descriptor_t *sd)
tor_free(sd->signed_descriptor_body);
- /* XXXX remove this once more bugs go away. */
memset(sd, 99, sizeof(signed_descriptor_t)); /* Debug bad mem usage */
tor_free(sd);
}
@@ -2802,8 +2831,7 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri)
routerinfo_t *ri_old;
signed_descriptor_t *sd_old;
{
- /* XXXX Remove if this slows us down. */
- routerinfo_t *ri_generated = router_get_my_routerinfo();
+ const routerinfo_t *ri_generated = router_get_my_routerinfo();
tor_assert(ri_generated != ri);
}
tor_assert(ri->cache_info.routerlist_index == -1);
@@ -2825,6 +2853,7 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri)
&ri->cache_info);
smartlist_add(rl->routers, ri);
ri->cache_info.routerlist_index = smartlist_len(rl->routers) - 1;
+ nodelist_add_routerinfo(ri);
router_dir_info_changed();
#ifdef DEBUG_ROUTERLIST
routerlist_assert_ok(rl);
@@ -2845,7 +2874,6 @@ extrainfo_insert(routerlist_t *rl, extrainfo_t *ei)
extrainfo_t *ei_tmp;
{
- /* XXXX remove this code if it slows us down. */
extrainfo_t *ei_generated = router_get_my_extrainfo();
tor_assert(ei_generated != ei);
}
@@ -2891,8 +2919,7 @@ static void
routerlist_insert_old(routerlist_t *rl, routerinfo_t *ri)
{
{
- /* XXXX remove this code if it slows us down. */
- routerinfo_t *ri_generated = router_get_my_routerinfo();
+ const routerinfo_t *ri_generated = router_get_my_routerinfo();
tor_assert(ri_generated != ri);
}
tor_assert(ri->cache_info.routerlist_index == -1);
@@ -2932,6 +2959,8 @@ routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int make_old, time_t now)
tor_assert(0 <= idx && idx < smartlist_len(rl->routers));
tor_assert(smartlist_get(rl->routers, idx) == ri);
+ nodelist_remove_routerinfo(ri);
+
/* make sure the rephist module knows that it's not running */
rep_hist_note_router_unreachable(ri->cache_info.identity_digest, now);
@@ -3043,8 +3072,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old,
routerinfo_t *ri_tmp;
extrainfo_t *ei_tmp;
{
- /* XXXX Remove this if it turns out to slow us down. */
- routerinfo_t *ri_generated = router_get_my_routerinfo();
+ const routerinfo_t *ri_generated = router_get_my_routerinfo();
tor_assert(ri_generated != ri_new);
}
tor_assert(ri_old != ri_new);
@@ -3054,6 +3082,9 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old,
tor_assert(0 <= idx && idx < smartlist_len(rl->routers));
tor_assert(smartlist_get(rl->routers, idx) == ri_old);
+ nodelist_remove_routerinfo(ri_old);
+ nodelist_add_routerinfo(ri_new);
+
router_dir_info_changed();
if (idx >= 0) {
smartlist_set(rl->routers, idx, ri_new);
@@ -3200,28 +3231,25 @@ routerlist_reset_warnings(void)
void
router_set_status(const char *digest, int up)
{
- routerinfo_t *router;
- routerstatus_t *status;
+ node_t *node;
tor_assert(digest);
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d,
if (tor_memeq(d->digest, digest, DIGEST_LEN))
d->is_running = up);
- router = router_get_by_digest(digest);
- if (router) {
+ node = node_get_mutable_by_id(digest);
+ if (node) {
+#if 0
log_debug(LD_DIR,"Marking router %s as %s.",
- router_describe(router), up ? "up" : "down");
- if (!up && router_is_me(router) && !we_are_hibernating())
+ node_describe(node), up ? "up" : "down");
+#endif
+ if (!up && node_is_me(node) && !we_are_hibernating())
log_warn(LD_NET, "We just marked ourself as down. Are your external "
"addresses reachable?");
- router->is_running = up;
- }
- status = router_get_consensus_status_by_id(digest);
- if (status && status->is_running != up) {
- status->is_running = up;
- control_event_networkstatus_changed_single(status);
+ node->is_running = up;
}
+
router_dir_info_changed();
}
@@ -3250,11 +3278,12 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
int from_cache, int from_fetch)
{
const char *id_digest;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
int authdir = authdir_mode_handles_descs(options, router->purpose);
int authdir_believes_valid = 0;
routerinfo_t *old_router;
- networkstatus_t *consensus = networkstatus_get_latest_consensus();
+ networkstatus_t *consensus =
+ networkstatus_get_latest_consensus_by_flavor(FLAV_NS);
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
int in_consensus = 0;
@@ -3265,7 +3294,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
id_digest = router->cache_info.identity_digest;
- old_router = router_get_by_digest(id_digest);
+ old_router = router_get_mutable_by_digest(id_digest);
/* Make sure that we haven't already got this exact descriptor. */
if (sdmap_get(routerlist->desc_digest_map,
@@ -3297,12 +3326,12 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
if (authdir) {
if (authdir_wants_to_reject_router(router, msg,
- !from_cache && !from_fetch)) {
+ !from_cache && !from_fetch,
+ &authdir_believes_valid)) {
tor_assert(*msg);
routerinfo_free(router);
return ROUTER_AUTHDIR_REJECTS;
}
- authdir_believes_valid = router->is_valid;
} else if (from_fetch) {
/* Only check the descriptor digest against the network statuses when
* we are receiving in response to a fetch. */
@@ -3329,14 +3358,15 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
{
routerstatus_t *rs =
- networkstatus_v2_find_entry(ns, id_digest);
+ networkstatus_v2_find_mutable_entry(ns, id_digest);
if (rs && tor_memeq(rs->descriptor_digest,
router->cache_info.signed_descriptor_digest,
DIGEST_LEN))
rs->need_to_mirror = 0;
});
if (consensus) {
- routerstatus_t *rs = networkstatus_vote_find_entry(consensus, id_digest);
+ routerstatus_t *rs = networkstatus_vote_find_mutable_entry(
+ consensus, id_digest);
if (rs && tor_memeq(rs->descriptor_digest,
router->cache_info.signed_descriptor_digest,
DIGEST_LEN)) {
@@ -3950,7 +3980,7 @@ router_load_extrainfo_from_string(const char *s, const char *eos,
static int
signed_desc_digest_is_recognized(signed_descriptor_t *desc)
{
- routerstatus_t *rs;
+ const routerstatus_t *rs;
networkstatus_t *consensus = networkstatus_get_latest_consensus();
int caches = directory_caches_dir_info(get_options());
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
@@ -3974,6 +4004,16 @@ signed_desc_digest_is_recognized(signed_descriptor_t *desc)
return 0;
}
+/** Update downloads for router descriptors and/or microdescriptors as
+ * appropriate. */
+void
+update_all_descriptor_downloads(time_t now)
+{
+ update_router_descriptor_downloads(now);
+ update_microdesc_downloads(now);
+ launch_dummy_descriptor_download_as_needed(now, get_options());
+}
+
/** Clear all our timeouts for fetching v2 and v3 directory stuff, and then
* give it all a try again. */
void
@@ -3982,34 +4022,34 @@ routerlist_retry_directory_downloads(time_t now)
router_reset_status_download_failures();
router_reset_descriptor_download_failures();
update_networkstatus_downloads(now);
- update_router_descriptor_downloads(now);
+ update_all_descriptor_downloads(now);
}
-/** Return 1 if all running sufficiently-stable routers will reject
+/** Return 1 if all running sufficiently-stable routers we can use will reject
* addr:port, return 0 if any might accept it. */
int
-router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port,
- int need_uptime)
-{
+router_exit_policy_all_nodes_reject(const tor_addr_t *addr, uint16_t port,
+ int need_uptime)
+{ /* XXXX MOVE */
addr_policy_result_t r;
- if (!routerlist) return 1;
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
- {
- if (router->is_running &&
- !router_is_unreliable(router, need_uptime, 0, 0)) {
- r = compare_addr_to_addr_policy(addr, port, router->exit_policy);
+ SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) {
+ if (node->is_running &&
+ !node_is_unreliable(node, need_uptime, 0, 0)) {
+
+ r = compare_tor_addr_to_node_policy(addr, port, node);
+
if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED)
return 0; /* this one could be ok. good enough. */
}
- });
+ } SMARTLIST_FOREACH_END(node);
return 1; /* all will reject. */
}
/** Return true iff <b>router</b> does not permit exit streams.
*/
int
-router_exit_policy_rejects_all(routerinfo_t *router)
+router_exit_policy_rejects_all(const routerinfo_t *router)
{
return router->policy_is_reject_star;
}
@@ -4022,7 +4062,7 @@ trusted_dir_server_t *
add_trusted_dir_server(const char *nickname, const char *address,
uint16_t dir_port, uint16_t or_port,
const char *digest, const char *v3_auth_digest,
- authority_type_t type)
+ dirinfo_type_t type)
{
trusted_dir_server_t *ent;
uint32_t a;
@@ -4057,7 +4097,7 @@ add_trusted_dir_server(const char *nickname, const char *address,
ent->is_running = 1;
ent->type = type;
memcpy(ent->digest, digest, DIGEST_LEN);
- if (v3_auth_digest && (type & V3_AUTHORITY))
+ if (v3_auth_digest && (type & V3_DIRINFO))
memcpy(ent->v3_identity_digest, v3_auth_digest, DIGEST_LEN);
dlen = 64 + strlen(hostname) + (nickname?strlen(nickname):0);
@@ -4136,7 +4176,7 @@ int
any_trusted_dir_is_v1_authority(void)
{
if (trusted_dir_servers)
- return get_n_authorities(V1_AUTHORITY) > 0;
+ return get_n_authorities(V1_DIRINFO) > 0;
return 0;
}
@@ -4144,7 +4184,9 @@ any_trusted_dir_is_v1_authority(void)
/** For every current directory connection whose purpose is <b>purpose</b>,
* and where the resource being downloaded begins with <b>prefix</b>, split
* rest of the resource into base16 fingerprints, decode them, and set the
- * corresponding elements of <b>result</b> to a nonzero value. */
+ * corresponding elements of <b>result</b> to a nonzero value.
+ * DOCDOC purpose==microdesc
+ */
static void
list_pending_downloads(digestmap_t *result,
int purpose, const char *prefix)
@@ -4152,20 +4194,23 @@ list_pending_downloads(digestmap_t *result,
const size_t p_len = strlen(prefix);
smartlist_t *tmp = smartlist_create();
smartlist_t *conns = get_connection_array();
+ int flags = DSR_HEX;
+ if (purpose == DIR_PURPOSE_FETCH_MICRODESC)
+ flags = DSR_DIGEST256|DSR_BASE64;
tor_assert(result);
- SMARTLIST_FOREACH(conns, connection_t *, conn,
- {
+ SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
if (conn->type == CONN_TYPE_DIR &&
conn->purpose == purpose &&
!conn->marked_for_close) {
const char *resource = TO_DIR_CONN(conn)->requested_resource;
if (!strcmpstart(resource, prefix))
dir_split_resource_into_fingerprints(resource + p_len,
- tmp, NULL, DSR_HEX);
+ tmp, NULL, flags);
}
- });
+ } SMARTLIST_FOREACH_END(conn);
+
SMARTLIST_FOREACH(tmp, char *, d,
{
digestmap_set(result, d, (void*)1);
@@ -4185,13 +4230,21 @@ list_pending_descriptor_downloads(digestmap_t *result, int extrainfo)
list_pending_downloads(result, purpose, "d/");
}
-/** Launch downloads for all the descriptors whose digests are listed
- * as digests[i] for lo <= i < hi. (Lo and hi may be out of range.)
- * If <b>source</b> is given, download from <b>source</b>; otherwise,
- * download from an appropriate random directory server.
+/** DOCDOC */
+/*XXXX NM should use digest256, if one comes into being. */
+void
+list_pending_microdesc_downloads(digestmap_t *result)
+{
+ list_pending_downloads(result, DIR_PURPOSE_FETCH_MICRODESC, "d/");
+}
+
+/** Launch downloads for all the descriptors whose digests or digests256
+ * are listed as digests[i] for lo <= i < hi. (Lo and hi may be out of
+ * range.) If <b>source</b> is given, download from <b>source</b>;
+ * otherwise, download from an appropriate random directory server.
*/
static void
-initiate_descriptor_downloads(routerstatus_t *source,
+initiate_descriptor_downloads(const routerstatus_t *source,
int purpose,
smartlist_t *digests,
int lo, int hi, int pds_flags)
@@ -4199,6 +4252,20 @@ initiate_descriptor_downloads(routerstatus_t *source,
int i, n = hi-lo;
char *resource, *cp;
size_t r_len;
+
+ int digest_len = DIGEST_LEN, enc_digest_len = HEX_DIGEST_LEN;
+ char sep = '+';
+ int b64_256 = 0;
+
+ if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
+ /* Microdescriptors are downloaded by "-"-separated base64-encoded
+ * 256-bit digests. */
+ digest_len = DIGEST256_LEN;
+ enc_digest_len = BASE64_DIGEST256_LEN;
+ sep = '-';
+ b64_256 = 1;
+ }
+
if (n <= 0)
return;
if (lo < 0)
@@ -4206,15 +4273,19 @@ initiate_descriptor_downloads(routerstatus_t *source,
if (hi > smartlist_len(digests))
hi = smartlist_len(digests);
- r_len = 8 + (HEX_DIGEST_LEN+1)*n;
+ r_len = 8 + (enc_digest_len+1)*n;
cp = resource = tor_malloc(r_len);
memcpy(cp, "d/", 2);
cp += 2;
for (i = lo; i < hi; ++i) {
- base16_encode(cp, r_len-(cp-resource),
- smartlist_get(digests,i), DIGEST_LEN);
- cp += HEX_DIGEST_LEN;
- *cp++ = '+';
+ if (b64_256) {
+ digest256_to_base64(cp, smartlist_get(digests, i));
+ } else {
+ base16_encode(cp, r_len-(cp-resource),
+ smartlist_get(digests,i), digest_len);
+ }
+ cp += enc_digest_len;
+ *cp++ = sep;
}
memcpy(cp-1, ".z", 3);
@@ -4235,9 +4306,10 @@ initiate_descriptor_downloads(routerstatus_t *source,
* running, or otherwise not a descriptor that we would make any
* use of even if we had it. Else return 1. */
static INLINE int
-client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options)
+client_would_use_router(const routerstatus_t *rs, time_t now,
+ const or_options_t *options)
{
- if (!rs->is_running && !options->FetchUselessDescriptors) {
+ if (!rs->is_flagged_running && !options->FetchUselessDescriptors) {
/* If we had this router descriptor, we wouldn't even bother using it.
* But, if we want to have a complete list, fetch it anyway. */
return 0;
@@ -4261,6 +4333,7 @@ client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options)
* So use 96 because it's a nice number.
*/
#define MAX_DL_PER_REQUEST 96
+#define MAX_MICRODESC_DL_PER_REQUEST 92
/** Don't split our requests so finely that we are requesting fewer than
* this number per server. */
#define MIN_DL_PER_REQUEST 4
@@ -4275,35 +4348,49 @@ client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options)
* them until they have more, or until this amount of time has passed. */
#define MAX_CLIENT_INTERVAL_WITHOUT_REQUEST (10*60)
-/** Given a list of router descriptor digests in <b>downloadable</b>, decide
- * whether to delay fetching until we have more. If we don't want to delay,
- * launch one or more requests to the appropriate directory authorities. */
-static void
-launch_router_descriptor_downloads(smartlist_t *downloadable,
- routerstatus_t *source, time_t now)
+/** Given a <b>purpose</b> (FETCH_MICRODESC or FETCH_SERVERDESC) and a list of
+ * router descriptor digests or microdescriptor digest256s in
+ * <b>downloadable</b>, decide whether to delay fetching until we have more.
+ * If we don't want to delay, launch one or more requests to the appropriate
+ * directory authorities.
+ */
+void
+launch_descriptor_downloads(int purpose,
+ smartlist_t *downloadable,
+ const routerstatus_t *source, time_t now)
{
int should_delay = 0, n_downloadable;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
+ const char *descname;
+
+ tor_assert(purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
+ purpose == DIR_PURPOSE_FETCH_MICRODESC);
+
+ descname = (purpose == DIR_PURPOSE_FETCH_SERVERDESC) ?
+ "routerdesc" : "microdesc";
n_downloadable = smartlist_len(downloadable);
if (!directory_fetches_dir_info_early(options)) {
if (n_downloadable >= MAX_DL_TO_DELAY) {
log_debug(LD_DIR,
- "There are enough downloadable routerdescs to launch requests.");
+ "There are enough downloadable %ss to launch requests.",
+ descname);
should_delay = 0;
} else {
- should_delay = (last_routerdesc_download_attempted +
+ should_delay = (last_descriptor_download_attempted +
MAX_CLIENT_INTERVAL_WITHOUT_REQUEST) > now;
if (!should_delay && n_downloadable) {
- if (last_routerdesc_download_attempted) {
+ if (last_descriptor_download_attempted) {
log_info(LD_DIR,
- "There are not many downloadable routerdescs, but we've "
+ "There are not many downloadable %ss, but we've "
"been waiting long enough (%d seconds). Downloading.",
- (int)(now-last_routerdesc_download_attempted));
+ descname,
+ (int)(now-last_descriptor_download_attempted));
} else {
log_info(LD_DIR,
- "There are not many downloadable routerdescs, but we haven't "
- "tried downloading descriptors recently. Downloading.");
+ "There are not many downloadable %ss, but we haven't "
+ "tried downloading descriptors recently. Downloading.",
+ descname);
}
}
}
@@ -4330,12 +4417,19 @@ launch_router_descriptor_downloads(smartlist_t *downloadable,
* update_router_descriptor_downloads() later on, once the connections
* have succeeded or failed.
*/
- pds_flags |= PDS_NO_EXISTING_SERVERDESC_FETCH;
+ pds_flags |= (purpose == DIR_PURPOSE_FETCH_MICRODESC) ?
+ PDS_NO_EXISTING_MICRODESC_FETCH :
+ PDS_NO_EXISTING_SERVERDESC_FETCH;
}
n_per_request = CEIL_DIV(n_downloadable, MIN_REQUESTS);
- if (n_per_request > MAX_DL_PER_REQUEST)
- n_per_request = MAX_DL_PER_REQUEST;
+ if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
+ if (n_per_request > MAX_MICRODESC_DL_PER_REQUEST)
+ n_per_request = MAX_MICRODESC_DL_PER_REQUEST;
+ } else {
+ if (n_per_request > MAX_DL_PER_REQUEST)
+ n_per_request = MAX_DL_PER_REQUEST;
+ }
if (n_per_request < MIN_DL_PER_REQUEST)
n_per_request = MIN_DL_PER_REQUEST;
@@ -4350,11 +4444,11 @@ launch_router_descriptor_downloads(smartlist_t *downloadable,
req_plural, n_downloadable, rtr_plural, n_per_request);
smartlist_sort_digests(downloadable);
for (i=0; i < n_downloadable; i += n_per_request) {
- initiate_descriptor_downloads(source, DIR_PURPOSE_FETCH_SERVERDESC,
+ initiate_descriptor_downloads(source, purpose,
downloadable, i, i+n_per_request,
pds_flags);
}
- last_routerdesc_download_attempted = now;
+ last_descriptor_download_attempted = now;
}
}
@@ -4370,7 +4464,7 @@ update_router_descriptor_cache_downloads_v2(time_t now)
digestmap_t *map; /* Which descs are in progress, or assigned? */
int i, j, n;
int n_download;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
if (! directory_fetches_dir_info_early(options)) {
@@ -4512,7 +4606,7 @@ void
update_consensus_router_descriptor_downloads(time_t now, int is_vote,
networkstatus_t *consensus)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
digestmap_t *map = NULL;
smartlist_t *no_longer_old = smartlist_create();
smartlist_t *downloadable = smartlist_create();
@@ -4540,15 +4634,14 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
map = digestmap_new();
list_pending_descriptor_downloads(map, 0);
- SMARTLIST_FOREACH(consensus->routerstatus_list, void *, rsp,
- {
+ SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, void *, rsp) {
routerstatus_t *rs =
is_vote ? &(((vote_routerstatus_t *)rsp)->status) : rsp;
signed_descriptor_t *sd;
if ((sd = router_get_by_descriptor_digest(rs->descriptor_digest))) {
- routerinfo_t *ri;
+ const routerinfo_t *ri;
++n_have;
- if (!(ri = router_get_by_digest(rs->identity_digest)) ||
+ if (!(ri = router_get_by_id_digest(rs->identity_digest)) ||
tor_memneq(ri->cache_info.signed_descriptor_digest,
sd->signed_descriptor_digest, DIGEST_LEN)) {
/* We have a descriptor with this digest, but either there is no
@@ -4581,7 +4674,8 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
if (is_vote && source) {
char time_bufnew[ISO_TIME_LEN+1];
char time_bufold[ISO_TIME_LEN+1];
- routerinfo_t *oldrouter = router_get_by_digest(rs->identity_digest);
+ const routerinfo_t *oldrouter;
+ oldrouter = router_get_by_id_digest(rs->identity_digest);
format_iso_time(time_bufnew, rs->published_on);
if (oldrouter)
format_iso_time(time_bufold, oldrouter->cache_info.published_on);
@@ -4592,7 +4686,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
source->nickname, oldrouter ? "known" : "unknown");
}
smartlist_add(downloadable, rs->descriptor_digest);
- });
+ } SMARTLIST_FOREACH_END(rsp);
if (!authdir_mode_handles_descs(options, ROUTER_PURPOSE_GENERAL)
&& smartlist_len(no_longer_old)) {
@@ -4624,7 +4718,8 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
smartlist_len(downloadable), n_delayed, n_have, n_in_oldrouters,
n_would_reject, n_wouldnt_use, n_inprogress);
- launch_router_descriptor_downloads(downloadable, source, now);
+ launch_descriptor_downloads(DIR_PURPOSE_FETCH_SERVERDESC,
+ downloadable, source, now);
digestmap_free(map, NULL);
done:
@@ -4638,27 +4733,20 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote,
* do this only when we aren't seeing incoming data. see bug 652. */
#define DUMMY_DOWNLOAD_INTERVAL (20*60)
-/** Launch downloads for router status as needed. */
-void
-update_router_descriptor_downloads(time_t now)
+/** As needed, launch a dummy router descriptor fetch to see if our
+ * address has changed. */
+static void
+launch_dummy_descriptor_download_as_needed(time_t now,
+ const or_options_t *options)
{
- or_options_t *options = get_options();
static time_t last_dummy_download = 0;
- if (should_delay_dir_fetches(options))
- return;
- if (directory_fetches_dir_info_early(options)) {
- update_router_descriptor_cache_downloads_v2(now);
- }
- update_consensus_router_descriptor_downloads(now, 0,
- networkstatus_get_reasonably_live_consensus(now));
-
/* XXXX023 we could be smarter here; see notes on bug 652. */
/* If we're a server that doesn't have a configured address, we rely on
* directory fetches to learn when our address changes. So if we haven't
* tried to get any routerdescs in a long time, try a dummy fetch now. */
if (!options->Address &&
server_mode(options) &&
- last_routerdesc_download_attempted + DUMMY_DOWNLOAD_INTERVAL < now &&
+ last_descriptor_download_attempted + DUMMY_DOWNLOAD_INTERVAL < now &&
last_dummy_download + DUMMY_DOWNLOAD_INTERVAL < now) {
last_dummy_download = now;
directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC,
@@ -4667,11 +4755,28 @@ update_router_descriptor_downloads(time_t now)
}
}
+/** Launch downloads for router status as needed. */
+void
+update_router_descriptor_downloads(time_t now)
+{
+ const or_options_t *options = get_options();
+ if (should_delay_dir_fetches(options))
+ return;
+ if (!we_fetch_router_descriptors(options))
+ return;
+ if (directory_fetches_dir_info_early(options)) {
+ update_router_descriptor_cache_downloads_v2(now);
+ }
+
+ update_consensus_router_descriptor_downloads(now, 0,
+ networkstatus_get_reasonably_live_consensus(now, FLAV_NS));
+}
+
/** Launch extrainfo downloads as needed. */
void
update_extrainfo_downloads(time_t now)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
routerlist_t *rl;
smartlist_t *wanted;
digestmap_t *pending;
@@ -4699,7 +4804,7 @@ update_extrainfo_downloads(time_t now)
sd = &((routerinfo_t*)smartlist_get(lst, i))->cache_info;
if (sd->is_extrainfo)
continue; /* This should never happen. */
- if (old_routers && !router_get_by_digest(sd->identity_digest))
+ if (old_routers && !router_get_by_id_digest(sd->identity_digest))
continue; /* Couldn't check the signature if we got it. */
if (sd->extrainfo_is_bogus)
continue;
@@ -4793,23 +4898,31 @@ get_dir_info_status_string(void)
static void
count_usable_descriptors(int *num_present, int *num_usable,
const networkstatus_t *consensus,
- or_options_t *options, time_t now,
+ const or_options_t *options, time_t now,
routerset_t *in_set)
{
+ const int md = (consensus->flavor == FLAV_MICRODESC);
*num_present = 0, *num_usable=0;
- SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
- {
- if (in_set && ! routerset_contains_routerstatus(in_set, rs))
+ SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *, rs)
+ {
+ if (in_set && ! routerset_contains_routerstatus(in_set, rs, -1))
continue;
if (client_would_use_router(rs, now, options)) {
+ const char * const digest = rs->descriptor_digest;
+ int present;
++*num_usable; /* the consensus says we want it. */
- if (router_get_by_descriptor_digest(rs->descriptor_digest)) {
+ if (md)
+ present = NULL != microdesc_cache_lookup_by_digest256(NULL, digest);
+ else
+ present = NULL != router_get_by_descriptor_digest(digest);
+ if (present) {
/* we have the descriptor listed in the consensus. */
++*num_present;
}
}
- });
+ }
+ SMARTLIST_FOREACH_END(rs);
log_debug(LD_DIR, "%d usable, %d present.", *num_usable, *num_present);
}
@@ -4823,7 +4936,7 @@ count_loading_descriptors_progress(void)
int num_present = 0, num_usable=0;
time_t now = time(NULL);
const networkstatus_t *consensus =
- networkstatus_get_reasonably_live_consensus(now);
+ networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor());
double fraction;
if (!consensus)
@@ -4851,16 +4964,17 @@ update_router_have_minimum_dir_info(void)
int num_present = 0, num_usable=0;
time_t now = time(NULL);
int res;
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
const networkstatus_t *consensus =
- networkstatus_get_reasonably_live_consensus(now);
+ networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor());
+ int using_md;
if (!consensus) {
if (!networkstatus_get_latest_consensus())
- strlcpy(dir_info_status, "We have no network-status consensus.",
+ strlcpy(dir_info_status, "We have no usable consensus.",
sizeof(dir_info_status));
else
- strlcpy(dir_info_status, "We have no recent network-status consensus.",
+ strlcpy(dir_info_status, "We have no recent usable consensus.",
sizeof(dir_info_status));
res = 0;
goto done;
@@ -4874,19 +4988,22 @@ update_router_have_minimum_dir_info(void)
goto done;
}
+ using_md = consensus->flavor == FLAV_MICRODESC;
+
count_usable_descriptors(&num_present, &num_usable, consensus, options, now,
NULL);
if (num_present < num_usable/4) {
tor_snprintf(dir_info_status, sizeof(dir_info_status),
- "We have only %d/%d usable descriptors.", num_present, num_usable);
+ "We have only %d/%d usable %sdescriptors.",
+ num_present, num_usable, using_md ? "micro" : "");
res = 0;
control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0);
goto done;
} else if (num_present < 2) {
tor_snprintf(dir_info_status, sizeof(dir_info_status),
- "Only %d descriptor%s here and believed reachable!",
- num_present, num_present ? "" : "s");
+ "Only %d %sdescriptor%s here and believed reachable!",
+ num_present, using_md ? "micro" : "", num_present ? "" : "s");
res = 0;
goto done;
}
@@ -4898,8 +5015,8 @@ update_router_have_minimum_dir_info(void)
if (!num_usable || !num_present) {
tor_snprintf(dir_info_status, sizeof(dir_info_status),
- "We have only %d/%d usable entry node descriptors.",
- num_present, num_usable);
+ "We have only %d/%d usable entry node %sdescriptors.",
+ num_present, num_usable, using_md?"micro":"");
res = 0;
goto done;
}
@@ -4939,7 +5056,7 @@ void
router_reset_descriptor_download_failures(void)
{
networkstatus_reset_download_failures();
- last_routerdesc_download_attempted = 0;
+ last_descriptor_download_attempted = 0;
if (!routerlist)
return;
SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
@@ -4963,7 +5080,7 @@ router_reset_descriptor_download_failures(void)
* would not cause a recent (post 0.1.1.6) dirserver to republish.
*/
int
-router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
+router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2)
{
time_t r1pub, r2pub;
long time_difference;
@@ -4971,7 +5088,7 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
/* r1 should be the one that was published first. */
if (r1->cache_info.published_on > r2->cache_info.published_on) {
- routerinfo_t *ri_tmp = r2;
+ const routerinfo_t *ri_tmp = r2;
r2 = r1;
r1 = ri_tmp;
}
@@ -4990,7 +5107,6 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
(r1->contact_info && r2->contact_info &&
strcasecmp(r1->contact_info, r2->contact_info)) ||
r1->is_hibernating != r2->is_hibernating ||
- r1->has_old_dnsworkers != r2->has_old_dnsworkers ||
cmp_addr_policies(r1->exit_policy, r2->exit_policy))
return 0;
if ((r1->declared_family == NULL) != (r2->declared_family == NULL))
@@ -5045,7 +5161,8 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2)
* incompatibility (if any).
**/
int
-routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
+routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri,
+ extrainfo_t *ei,
signed_descriptor_t *sd,
const char **msg)
{
@@ -5053,7 +5170,7 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
tor_assert(ri);
tor_assert(ei);
if (!sd)
- sd = &ri->cache_info;
+ sd = (signed_descriptor_t*)&ri->cache_info;
if (ei->bad_sig) {
if (msg) *msg = "Extrainfo signature was bad, or signed with wrong key.";
@@ -5118,7 +5235,7 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
/** Assert that the internal representation of <b>rl</b> is
* self-consistent. */
void
-routerlist_assert_ok(routerlist_t *rl)
+routerlist_assert_ok(const routerlist_t *rl)
{
routerinfo_t *r2;
signed_descriptor_t *sd2;
@@ -5208,7 +5325,7 @@ routerlist_assert_ok(routerlist_t *rl)
* If <b>router</b> is NULL, it just frees its internal memory and returns.
*/
const char *
-esc_router_info(routerinfo_t *router)
+esc_router_info(const routerinfo_t *router)
{
static char *info=NULL;
char *esc_contact, *esc_platform;
@@ -5310,38 +5427,6 @@ routerset_get_countryname(const char *c)
return country;
}
-#if 0
-/** Add the GeoIP database's integer index (+1) of a valid two-character
- * country code to the routerset's <b>countries</b> bitarray. Return the
- * integer index if the country code is valid, -1 otherwise.*/
-static int
-routerset_add_country(const char *c)
-{
- char country[3];
- country_t cc;
-
- /* XXXX: Country codes must be of the form \{[a-z\?]{2}\} but this accepts
- \{[.]{2}\}. Do we need to be strict? -RH */
- /* Nope; if the country code is bad, we'll get 0 when we look it up. */
-
- if (!geoip_is_loaded()) {
- log(LOG_WARN, LD_CONFIG, "GeoIP database not loaded: Cannot add country"
- "entry %s, ignoring.", c);
- return -1;
- }
-
- memcpy(country, c+1, 2);
- country[2] = '\0';
- tor_strlower(country);
-
- if ((cc=geoip_get_country(country))==-1) {
- log(LOG_WARN, LD_CONFIG, "Country code '%s' is not valid, ignoring.",
- country);
- }
- return cc;
-}
-#endif
-
/** Update the routerset's <b>countries</b> bitarray_t. Called whenever
* the GeoIP database is reloaded.
*/
@@ -5430,7 +5515,7 @@ routerset_parse(routerset_t *target, const char *s, const char *description)
void
refresh_all_country_info(void)
{
- or_options_t *options = get_options();
+ const or_options_t *options = get_options();
if (options->EntryNodes)
routerset_refresh_countries(options->EntryNodes);
@@ -5443,7 +5528,7 @@ refresh_all_country_info(void)
if (options->_ExcludeExitNodesUnion)
routerset_refresh_countries(options->_ExcludeExitNodesUnion);
- routerlist_refresh_countries();
+ nodelist_refresh_countries();
}
/** Add all members of the set <b>source</b> to <b>target</b>. */
@@ -5493,11 +5578,11 @@ routerset_is_empty(const routerset_t *set)
static int
routerset_contains(const routerset_t *set, const tor_addr_t *addr,
uint16_t orport,
- const char *nickname, const char *id_digest, int is_named,
+ const char *nickname, const char *id_digest,
country_t country)
{
- if (!set || !set->list) return 0;
- (void) is_named; /* not supported */
+ if (!set || !set->list)
+ return 0;
if (nickname && strmap_get_lc(set->names, nickname))
return 4;
if (id_digest && digestmap_get(set->digests, id_digest))
@@ -5525,13 +5610,14 @@ routerset_contains_extendinfo(const routerset_t *set, const extend_info_t *ei)
ei->port,
ei->nickname,
ei->identity_digest,
- -1, /*is_named*/
-1 /*country*/);
}
-/** Return true iff <b>ri</b> is in <b>set</b>. */
+/** Return true iff <b>ri</b> is in <b>set</b>. If country is <b>-1</b>, we
+ * look up the country. */
int
-routerset_contains_router(const routerset_t *set, routerinfo_t *ri)
+routerset_contains_router(const routerset_t *set, const routerinfo_t *ri,
+ country_t country)
{
tor_addr_t addr;
tor_addr_from_ipv4h(&addr, ri->addr);
@@ -5540,13 +5626,15 @@ routerset_contains_router(const routerset_t *set, routerinfo_t *ri)
ri->or_port,
ri->nickname,
ri->cache_info.identity_digest,
- ri->is_named,
- ri->country);
+ country);
}
-/** Return true iff <b>rs</b> is in <b>set</b>. */
+/** Return true iff <b>rs</b> is in <b>set</b>. If country is <b>-1</b>, we
+ * look up the country. */
int
-routerset_contains_routerstatus(const routerset_t *set, routerstatus_t *rs)
+routerset_contains_routerstatus(const routerset_t *set,
+ const routerstatus_t *rs,
+ country_t country)
{
tor_addr_t addr;
tor_addr_from_ipv4h(&addr, rs->addr);
@@ -5555,50 +5643,59 @@ routerset_contains_routerstatus(const routerset_t *set, routerstatus_t *rs)
rs->or_port,
rs->nickname,
rs->identity_digest,
- rs->is_named,
- -1);
+ country);
+}
+
+/** Return true iff <b>node</b> is in <b>set</b>. */
+int
+routerset_contains_node(const routerset_t *set, const node_t *node)
+{
+ if (node->rs)
+ return routerset_contains_routerstatus(set, node->rs, node->country);
+ else if (node->ri)
+ return routerset_contains_router(set, node->ri, node->country);
+ else
+ return 0;
}
-/** Add every known routerinfo_t that is a member of <b>routerset</b> to
+/** Add every known node_t that is a member of <b>routerset</b> to
* <b>out</b>, but never add any that are part of <b>excludeset</b>.
* If <b>running_only</b>, only add the running ones. */
void
-routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
- const routerset_t *excludeset, int running_only)
-{
+routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
+ const routerset_t *excludeset, int running_only)
+{ /* XXXX MOVE */
tor_assert(out);
if (!routerset || !routerset->list)
return;
- if (!warned_nicknames)
- warned_nicknames = smartlist_create();
- if (routerset_is_list(routerset)) {
+ if (routerset_is_list(routerset)) {
/* No routers are specified by type; all are given by name or digest.
* we can do a lookup in O(len(routerset)). */
SMARTLIST_FOREACH(routerset->list, const char *, name, {
- routerinfo_t *router = router_get_by_nickname(name, 1);
- if (router) {
- if (!running_only || router->is_running)
- if (!routerset_contains_router(excludeset, router))
- smartlist_add(out, router);
+ const node_t *node = node_get_by_nickname(name, 1);
+ if (node) {
+ if (!running_only || node->is_running)
+ if (!routerset_contains_node(excludeset, node))
+ smartlist_add(out, (void*)node);
}
});
} else {
/* We need to iterate over the routerlist to get all the ones of the
* right kind. */
- routerlist_t *rl = router_get_routerlist();
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, router, {
- if (running_only && !router->is_running)
+ smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, const node_t *, node, {
+ if (running_only && !node->is_running)
continue;
- if (routerset_contains_router(routerset, router) &&
- !routerset_contains_router(excludeset, router))
- smartlist_add(out, router);
+ if (routerset_contains_node(routerset, node) &&
+ !routerset_contains_node(excludeset, node))
+ smartlist_add(out, (void*)node);
});
}
}
#if 0
-/** Add to <b>target</b> every routerinfo_t from <b>source</b> except:
+/** Add to <b>target</b> every node_t from <b>source</b> except:
*
* 1) Don't add it if <b>include</b> is non-empty and the relay isn't in
* <b>include</b>; and
@@ -5607,40 +5704,40 @@ routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
* 3) If <b>running_only</b>, don't add non-running routers.
*/
void
-routersets_get_disjunction(smartlist_t *target,
+routersets_get_node_disjunction(smartlist_t *target,
const smartlist_t *source,
const routerset_t *include,
const routerset_t *exclude, int running_only)
{
- SMARTLIST_FOREACH(source, routerinfo_t *, router, {
+ SMARTLIST_FOREACH(source, const node_t *, node, {
int include_result;
- if (running_only && !router->is_running)
+ if (running_only && !node->is_running)
continue;
if (!routerset_is_empty(include))
- include_result = routerset_contains_router(include, router);
+ include_result = routerset_contains_node(include, node);
else
include_result = 1;
if (include_result) {
- int exclude_result = routerset_contains_router(exclude, router);
+ int exclude_result = routerset_contains_node(exclude, node);
if (include_result >= exclude_result)
- smartlist_add(target, router);
+ smartlist_add(target, (void*)node);
}
});
}
#endif
-/** Remove every routerinfo_t from <b>lst</b> that is in <b>routerset</b>. */
+/** Remove every node_t from <b>lst</b> that is in <b>routerset</b>. */
void
-routerset_subtract_routers(smartlist_t *lst, const routerset_t *routerset)
-{
+routerset_subtract_nodes(smartlist_t *lst, const routerset_t *routerset)
+{ /*XXXX MOVE ? */
tor_assert(lst);
if (!routerset)
return;
- SMARTLIST_FOREACH(lst, routerinfo_t *, r, {
- if (routerset_contains_router(routerset, r)) {
+ SMARTLIST_FOREACH(lst, const node_t *, node, {
+ if (routerset_contains_node(routerset, node)) {
//log_debug(LD_DIR, "Subtracting %s",r->nickname);
- SMARTLIST_DEL_CURRENT(lst, r);
+ SMARTLIST_DEL_CURRENT(lst, node);
}
});
}
@@ -5706,18 +5803,23 @@ routerset_free(routerset_t *routerset)
/** Refresh the country code of <b>ri</b>. This function MUST be called on
* each router when the GeoIP database is reloaded, and on all new routers. */
void
-routerinfo_set_country(routerinfo_t *ri)
+node_set_country(node_t *node)
{
- ri->country = geoip_get_country_by_ip(ri->addr);
+ if (node->rs)
+ node->country = geoip_get_country_by_ip(node->rs->addr);
+ else if (node->ri)
+ node->country = geoip_get_country_by_ip(node->ri->addr);
+ else
+ node->country = -1;
}
/** Set the country code of all routers in the routerlist. */
void
-routerlist_refresh_countries(void)
+nodelist_refresh_countries(void) /* MOVE */
{
- routerlist_t *rl = router_get_routerlist();
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri,
- routerinfo_set_country(ri));
+ smartlist_t *nodes = nodelist_get_list();
+ SMARTLIST_FOREACH(nodes, node_t *, node,
+ node_set_country(node));
}
/** Determine the routers that are responsible for <b>id</b> (binary) and
@@ -5760,7 +5862,7 @@ hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
int
hid_serv_acting_as_directory(void)
{
- routerinfo_t *me = router_get_my_routerinfo();
+ const routerinfo_t *me = router_get_my_routerinfo();
if (!me)
return 0;
if (!get_options()->HidServDirectoryV2) {
@@ -5776,7 +5878,7 @@ hid_serv_acting_as_directory(void)
int
hid_serv_responsible_for_desc_id(const char *query)
{
- routerinfo_t *me;
+ const routerinfo_t *me;
routerstatus_t *last_rs;
const char *my_id, *last_id;
int result;
diff --git a/src/or/routerlist.h b/src/or/routerlist.h
index fec18705b..cae881433 100644
--- a/src/or/routerlist.h
+++ b/src/or/routerlist.h
@@ -11,7 +11,7 @@
#ifndef _TOR_ROUTERLIST_H
#define _TOR_ROUTERLIST_H
-int get_n_authorities(authority_type_t type);
+int get_n_authorities(dirinfo_type_t type);
int trusted_dirs_reload_certs(void);
int trusted_dirs_load_certs_from_string(const char *contents, int from_store,
int flush);
@@ -27,53 +27,50 @@ int router_reload_router_list(void);
int authority_cert_dl_looks_uncertain(const char *id_digest);
smartlist_t *router_get_trusted_dir_servers(void);
-routerstatus_t *router_pick_directory_server(authority_type_t type, int flags);
+const routerstatus_t *router_pick_directory_server(dirinfo_type_t type,
+ int flags);
trusted_dir_server_t *router_get_trusteddirserver_by_digest(const char *d);
trusted_dir_server_t *trusteddirserver_get_by_v3_auth_digest(const char *d);
-routerstatus_t *router_pick_trusteddirserver(authority_type_t type, int flags);
+const routerstatus_t *router_pick_trusteddirserver(dirinfo_type_t type,
+ int flags);
int router_get_my_share_of_directory_requests(double *v2_share_out,
double *v3_share_out);
void router_reset_status_download_failures(void);
-void routerlist_add_family(smartlist_t *sl, routerinfo_t *router);
-int routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2);
int routers_have_same_or_addr(const routerinfo_t *r1, const routerinfo_t *r2);
-void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
- int must_be_running);
-int router_nickname_is_in_list(routerinfo_t *router, const char *list);
-routerinfo_t *routerlist_find_my_routerinfo(void);
-routerinfo_t *router_find_exact_exit_enclave(const char *address,
+int router_nickname_is_in_list(const routerinfo_t *router, const char *list);
+const routerinfo_t *routerlist_find_my_routerinfo(void);
+const node_t *router_find_exact_exit_enclave(const char *address,
uint16_t port);
-int router_is_unreliable(routerinfo_t *router, int need_uptime,
+int node_is_unreliable(const node_t *router, int need_uptime,
int need_capacity, int need_guard);
-uint32_t router_get_advertised_bandwidth(routerinfo_t *router);
-uint32_t router_get_advertised_bandwidth_capped(routerinfo_t *router);
+uint32_t router_get_advertised_bandwidth(const routerinfo_t *router);
+uint32_t router_get_advertised_bandwidth_capped(const routerinfo_t *router);
-routerinfo_t *routerlist_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule);
-routerstatus_t *routerstatus_sl_choose_by_bandwidth(smartlist_t *sl,
- bandwidth_weight_rule_t rule);
+const node_t *node_sl_choose_by_bandwidth(smartlist_t *sl,
+ bandwidth_weight_rule_t rule);
-routerinfo_t *router_choose_random_node(smartlist_t *excludedsmartlist,
+const node_t *router_choose_random_node(smartlist_t *excludedsmartlist,
struct routerset_t *excludedset,
router_crn_flags_t flags);
-routerinfo_t *router_get_by_nickname(const char *nickname,
+const routerinfo_t *router_get_by_nickname(const char *nickname,
int warn_if_unnamed);
-int router_digest_version_as_new_as(const char *digest, const char *cutoff);
+int router_is_named(const routerinfo_t *router);
int router_digest_is_trusted_dir_type(const char *digest,
- authority_type_t type);
+ dirinfo_type_t type);
#define router_digest_is_trusted_dir(d) \
- router_digest_is_trusted_dir_type((d), NO_AUTHORITY)
+ router_digest_is_trusted_dir_type((d), NO_DIRINFO)
int router_addr_is_trusted_dir(uint32_t addr);
int hexdigest_to_digest(const char *hexdigest, char *digest);
-routerinfo_t *router_get_by_hexdigest(const char *hexdigest);
-routerinfo_t *router_get_by_digest(const char *digest);
+const routerinfo_t *router_get_by_hexdigest(const char *hexdigest);
+const routerinfo_t *router_get_by_id_digest(const char *digest);
+routerinfo_t *router_get_mutable_by_digest(const char *digest);
signed_descriptor_t *router_get_by_descriptor_digest(const char *digest);
signed_descriptor_t *router_get_by_extrainfo_digest(const char *digest);
signed_descriptor_t *extrainfo_get_by_descriptor_digest(const char *digest);
-const char *signed_descriptor_get_body(signed_descriptor_t *desc);
-const char *signed_descriptor_get_annotations(signed_descriptor_t *desc);
+const char *signed_descriptor_get_body(const signed_descriptor_t *desc);
+const char *signed_descriptor_get_annotations(const signed_descriptor_t *desc);
routerlist_t *router_get_routerlist(void);
void routerinfo_free(routerinfo_t *router);
void extrainfo_free(extrainfo_t *extrainfo);
@@ -132,63 +129,71 @@ void router_load_extrainfo_from_string(const char *s, const char *eos,
int descriptor_digests);
void routerlist_retry_directory_downloads(time_t now);
-int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port,
- int need_uptime);
-int router_exit_policy_rejects_all(routerinfo_t *router);
+int router_exit_policy_all_nodes_reject(const tor_addr_t *addr, uint16_t port,
+ int need_uptime);
+
+int router_exit_policy_rejects_all(const routerinfo_t *router);
trusted_dir_server_t *add_trusted_dir_server(const char *nickname,
const char *address,
uint16_t dir_port, uint16_t or_port,
const char *digest, const char *v3_auth_digest,
- authority_type_t type);
+ dirinfo_type_t type);
void authority_cert_free(authority_cert_t *cert);
void clear_trusted_dir_servers(void);
int any_trusted_dir_is_v1_authority(void);
void update_consensus_router_descriptor_downloads(time_t now, int is_vote,
networkstatus_t *consensus);
void update_router_descriptor_downloads(time_t now);
+void update_all_descriptor_downloads(time_t now);
void update_extrainfo_downloads(time_t now);
int router_have_minimum_dir_info(void);
void router_dir_info_changed(void);
const char *get_dir_info_status_string(void);
int count_loading_descriptors_progress(void);
void router_reset_descriptor_download_failures(void);
-int router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2);
-int routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei,
+int router_differences_are_cosmetic(const routerinfo_t *r1,
+ const routerinfo_t *r2);
+int routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri,
+ extrainfo_t *ei,
signed_descriptor_t *sd,
const char **msg);
-void routerlist_assert_ok(routerlist_t *rl);
-const char *esc_router_info(routerinfo_t *router);
+void routerlist_assert_ok(const routerlist_t *rl);
+const char *esc_router_info(const routerinfo_t *router);
void routers_sort_by_identity(smartlist_t *routers);
routerset_t *routerset_new(void);
+void routerset_refresh_countries(routerset_t *rs);
int routerset_parse(routerset_t *target, const char *s,
const char *description);
void routerset_union(routerset_t *target, const routerset_t *source);
int routerset_is_list(const routerset_t *set);
int routerset_needs_geoip(const routerset_t *set);
int routerset_is_empty(const routerset_t *set);
-int routerset_contains_router(const routerset_t *set, routerinfo_t *ri);
+int routerset_contains_router(const routerset_t *set, const routerinfo_t *ri,
+ country_t country);
int routerset_contains_routerstatus(const routerset_t *set,
- routerstatus_t *rs);
+ const routerstatus_t *rs,
+ country_t country);
int routerset_contains_extendinfo(const routerset_t *set,
const extend_info_t *ei);
-void routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset,
- const routerset_t *excludeset,
- int running_only);
+
+int routerset_contains_node(const routerset_t *set, const node_t *node);
+void routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset,
+ const routerset_t *excludeset,
+ int running_only);
#if 0
-void routersets_get_disjunction(smartlist_t *target, const smartlist_t *source,
+void routersets_get_node_disjunction(smartlist_t *target,
+ const smartlist_t *source,
const routerset_t *include,
const routerset_t *exclude, int running_only);
#endif
-void routerset_subtract_routers(smartlist_t *out,
+void routerset_subtract_nodes(smartlist_t *out,
const routerset_t *routerset);
+
char *routerset_to_string(const routerset_t *routerset);
-void routerset_refresh_countries(routerset_t *target);
int routerset_equal(const routerset_t *old, const routerset_t *new);
void routerset_free(routerset_t *routerset);
-void routerinfo_set_country(routerinfo_t *ri);
-void routerlist_refresh_countries(void);
void refresh_all_country_info(void);
int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
@@ -196,5 +201,16 @@ int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs,
int hid_serv_acting_as_directory(void);
int hid_serv_responsible_for_desc_id(const char *id);
+void list_pending_microdesc_downloads(digestmap_t *result);
+void launch_descriptor_downloads(int purpose,
+ smartlist_t *downloadable,
+ const routerstatus_t *source,
+ time_t now);
+
+int hex_digest_nickname_decode(const char *hexdigest,
+ char *digest_out,
+ char *nickname_qualifier_out,
+ char *nickname_out);
+
#endif
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 42dbcacb5..5c553b81f 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -70,7 +70,6 @@ typedef enum {
K_V,
K_W,
K_M,
- K_EVENTDNS,
K_EXTRA_INFO,
K_EXTRA_INFO_DIGEST,
K_CACHES_EXTRA_INFO,
@@ -287,7 +286,6 @@ static token_rule_t routerdesc_token_table[] = {
T01("family", K_FAMILY, ARGS, NO_OBJ ),
T01("caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ ),
- T01("eventdns", K_EVENTDNS, ARGS, NO_OBJ ),
T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ),
@@ -1358,7 +1356,6 @@ router_parse_entry_from_string(const char *s, const char *end,
tor_assert(tok->n_args >= 5);
router = tor_malloc_zero(sizeof(routerinfo_t));
- router->country = -1;
router->cache_info.routerlist_index = -1;
router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
router->cache_info.signed_descriptor_len = end-s;
@@ -1504,13 +1501,6 @@ router_parse_entry_from_string(const char *s, const char *end,
router->contact_info = tor_strdup(tok->args[0]);
}
- if ((tok = find_opt_by_keyword(tokens, K_EVENTDNS))) {
- router->has_old_dnsworkers = tok->n_args && !strcmp(tok->args[0], "0");
- } else if (router->platform) {
- if (! tor_version_as_new_as(router->platform, "0.1.2.2-alpha"))
- router->has_old_dnsworkers = 1;
- }
-
if (find_opt_by_keyword(tokens, K_REJECT6) ||
find_opt_by_keyword(tokens, K_ACCEPT6)) {
log_warn(LD_DIR, "Rejecting router with reject6/accept6 line: they crash "
@@ -1575,8 +1565,6 @@ router_parse_entry_from_string(const char *s, const char *end,
"router descriptor") < 0)
goto err;
- routerinfo_set_country(router);
-
if (!router->or_port) {
log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
goto err;
@@ -1976,6 +1964,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
if (!consensus_method)
flav = FLAV_NS;
+ tor_assert(flav == FLAV_NS || flav == FLAV_MICRODESC);
eos = find_start_of_next_routerstatus(*s);
@@ -1988,15 +1977,16 @@ routerstatus_parse_entry_from_string(memarea_t *area,
goto err;
}
tok = find_by_keyword(tokens, K_R);
- tor_assert(tok->n_args >= 7);
+ tor_assert(tok->n_args >= 7); /* guaranteed by GE(7) in K_R setup */
if (flav == FLAV_NS) {
if (tok->n_args < 8) {
log_warn(LD_DIR, "Too few arguments to r");
goto err;
}
- } else {
- offset = -1;
+ } else if (flav == FLAV_MICRODESC) {
+ offset = -1; /* There is no identity digest */
}
+
if (vote_rs) {
rs = &vote_rs->status;
} else {
@@ -2070,7 +2060,7 @@ routerstatus_parse_entry_from_string(memarea_t *area,
else if (!strcmp(tok->args[i], "Fast"))
rs->is_fast = 1;
else if (!strcmp(tok->args[i], "Running"))
- rs->is_running = 1;
+ rs->is_flagged_running = 1;
else if (!strcmp(tok->args[i], "Named"))
rs->is_named = 1;
else if (!strcmp(tok->args[i], "Valid"))
@@ -2101,6 +2091,8 @@ routerstatus_parse_entry_from_string(memarea_t *area,
rs->version_supports_begindir = 1;
rs->version_supports_extrainfo_upload = 1;
rs->version_supports_conditional_consensus = 1;
+ rs->version_supports_microdesc_cache = 1;
+ rs->version_supports_optimistic_data = 1;
} else {
rs->version_supports_begindir =
tor_version_as_new_as(tok->args[0], "0.2.0.1-alpha");
@@ -2110,6 +2102,16 @@ routerstatus_parse_entry_from_string(memarea_t *area,
tor_version_as_new_as(tok->args[0], "0.2.0.8-alpha");
rs->version_supports_conditional_consensus =
tor_version_as_new_as(tok->args[0], "0.2.1.1-alpha");
+ /* XXXX023 NM microdescs: 0.2.3.1-alpha isn't widely used yet, but
+ * not all 0.2.3.0-alpha "versions" actually support microdesc cacheing
+ * right. There's a compromise here. Since this is 5 May, let's
+ * err on the side of having some possible caches to use. Once more
+ * caches are running 0.2.3.1-alpha, we can bump this version number.
+ */
+ rs->version_supports_microdesc_cache =
+ tor_version_as_new_as(tok->args[0], "0.2.3.0-alpha");
+ rs->version_supports_optimistic_data =
+ tor_version_as_new_as(tok->args[0], "0.2.3.1-alpha");
}
if (vote_rs) {
vote_rs->version = tor_strdup(tok->args[0]);
@@ -2172,6 +2174,16 @@ routerstatus_parse_entry_from_string(memarea_t *area,
vote_rs->microdesc = line;
}
} SMARTLIST_FOREACH_END(t);
+ } else if (flav == FLAV_MICRODESC) {
+ tok = find_opt_by_keyword(tokens, K_M);
+ if (tok) {
+ tor_assert(tok->n_args);
+ if (digest256_from_base64(rs->descriptor_digest, tok->args[0])) {
+ log_warn(LD_DIR, "Error decoding microdescriptor digest %s",
+ escaped(tok->args[0]));
+ goto err;
+ }
+ }
}
if (!strcasecmp(rs->nickname, UNNAMED_ROUTER_NICKNAME))
@@ -2419,40 +2431,40 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
// We use > 1 as the check for these because they are computed as integers.
// Sometimes there are rounding errors.
if (fabs(Wmm - weight_scale) > 1) {
- log_warn(LD_BUG, "Wmm=%lf != "I64_FORMAT,
+ log_warn(LD_BUG, "Wmm=%f != "I64_FORMAT,
Wmm, I64_PRINTF_ARG(weight_scale));
valid = 0;
}
if (fabs(Wem - Wee) > 1) {
- log_warn(LD_BUG, "Wem=%lf != Wee=%lf", Wem, Wee);
+ log_warn(LD_BUG, "Wem=%f != Wee=%f", Wem, Wee);
valid = 0;
}
if (fabs(Wgm - Wgg) > 1) {
- log_warn(LD_BUG, "Wgm=%lf != Wgg=%lf", Wgm, Wgg);
+ log_warn(LD_BUG, "Wgm=%f != Wgg=%f", Wgm, Wgg);
valid = 0;
}
if (fabs(Weg - Wed) > 1) {
- log_warn(LD_BUG, "Wed=%lf != Weg=%lf", Wed, Weg);
+ log_warn(LD_BUG, "Wed=%f != Weg=%f", Wed, Weg);
valid = 0;
}
if (fabs(Wgg + Wmg - weight_scale) > 0.001*weight_scale) {
- log_warn(LD_BUG, "Wgg=%lf != "I64_FORMAT" - Wmg=%lf", Wgg,
+ log_warn(LD_BUG, "Wgg=%f != "I64_FORMAT" - Wmg=%f", Wgg,
I64_PRINTF_ARG(weight_scale), Wmg);
valid = 0;
}
if (fabs(Wee + Wme - weight_scale) > 0.001*weight_scale) {
- log_warn(LD_BUG, "Wee=%lf != "I64_FORMAT" - Wme=%lf", Wee,
+ log_warn(LD_BUG, "Wee=%f != "I64_FORMAT" - Wme=%f", Wee,
I64_PRINTF_ARG(weight_scale), Wme);
valid = 0;
}
if (fabs(Wgd + Wmd + Wed - weight_scale) > 0.001*weight_scale) {
- log_warn(LD_BUG, "Wgd=%lf + Wmd=%lf + Wed=%lf != "I64_FORMAT,
+ log_warn(LD_BUG, "Wgd=%f + Wmd=%f + Wed=%f != "I64_FORMAT,
Wgd, Wmd, Wed, I64_PRINTF_ARG(weight_scale));
valid = 0;
}
@@ -2507,10 +2519,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
casename = "Case 1";
if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: Etotal %lf != Mtotal %lf. "
+ "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
"G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Etotal, Mtotal,
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2519,10 +2531,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
}
if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: Etotal %lf != Gtotal %lf. "
+ "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
"G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Etotal, Gtotal,
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2531,10 +2543,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
}
if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: Mtotal %lf != Gtotal %lf. "
+ "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
"G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Mtotal, Gtotal,
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2563,10 +2575,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
// Rtotal < Stotal
if (Rtotal > Stotal) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: Rtotal %lf > Stotal %lf. "
+ "Bw Weight Failure for %s: Rtotal %f > Stotal %f. "
"G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Rtotal, Stotal,
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2576,10 +2588,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
// Rtotal < T/3
if (3*Rtotal > T) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: 3*Rtotal %lf > T "
+ "Bw Weight Failure for %s: 3*Rtotal %f > T "
I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
" D="I64_FORMAT" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Rtotal*3, I64_PRINTF_ARG(T),
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2589,10 +2601,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
// Stotal < T/3
if (3*Stotal > T) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: 3*Stotal %lf > T "
+ "Bw Weight Failure for %s: 3*Stotal %f > T "
I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
" D="I64_FORMAT" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Stotal*3, I64_PRINTF_ARG(T),
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2602,11 +2614,11 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
// Mtotal > T/3
if (3*Mtotal < T) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: 3*Mtotal %lf < T "
+ "Bw Weight Failure for %s: 3*Mtotal %f < T "
I64_FORMAT". "
"G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Mtotal*3, I64_PRINTF_ARG(T),
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2621,10 +2633,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
casename = "Case 2b (balanced)";
if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: Etotal %lf != Mtotal %lf. "
+ "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
"G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Etotal, Mtotal,
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2633,10 +2645,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
}
if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: Etotal %lf != Gtotal %lf. "
+ "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
"G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Etotal, Gtotal,
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2645,10 +2657,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
}
if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: Mtotal %lf != Gtotal %lf. "
+ "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
"G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Mtotal, Gtotal,
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2658,10 +2670,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
} else {
if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: Etotal %lf != Gtotal %lf. "
+ "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
"G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Etotal, Gtotal,
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2688,10 +2700,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
// Stotal < T/3
if (3*Stotal > T) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: 3*Stotal %lf > T "
+ "Bw Weight Failure for %s: 3*Stotal %f > T "
I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
" D="I64_FORMAT" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Stotal*3, I64_PRINTF_ARG(T),
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2701,10 +2713,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
if (NS >= M) {
if (fabs(NStotal-Mtotal) > 0.01*MAX(NStotal,Mtotal)) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: NStotal %lf != Mtotal %lf. "
+ "Bw Weight Failure for %s: NStotal %f != Mtotal %f. "
"G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, NStotal, Mtotal,
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2715,10 +2727,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
// if NS < M, NStotal > T/3 because only one of G or E is scarce
if (3*NStotal < T) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: 3*NStotal %lf < T "
+ "Bw Weight Failure for %s: 3*NStotal %f < T "
I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT
" E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, NStotal*3, I64_PRINTF_ARG(T),
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2730,10 +2742,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
casename = "Case 3b";
if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: Etotal %lf != Mtotal %lf. "
+ "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
"G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Etotal, Mtotal,
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2742,10 +2754,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
}
if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: Etotal %lf != Gtotal %lf. "
+ "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
"G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Etotal, Gtotal,
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -2754,10 +2766,10 @@ networkstatus_verify_bw_weights(networkstatus_t *ns)
}
if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
log_warn(LD_DIR,
- "Bw Weight Failure for %s: Mtotal %lf != Gtotal %lf. "
+ "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
"G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
" T="I64_FORMAT". "
- "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
+ "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
casename, Mtotal, Gtotal,
I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
@@ -3503,10 +3515,10 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos)
siglist = detached_get_signatures(sigs, flavor);
is_duplicate = 0;
- SMARTLIST_FOREACH(siglist, document_signature_t *, s, {
- if (s->alg == alg &&
- tor_memeq(id_digest, s->identity_digest, DIGEST_LEN) &&
- tor_memeq(sk_digest, s->signing_key_digest, DIGEST_LEN)) {
+ SMARTLIST_FOREACH(siglist, document_signature_t *, dsig, {
+ if (dsig->alg == alg &&
+ tor_memeq(id_digest, dsig->identity_digest, DIGEST_LEN) &&
+ tor_memeq(sk_digest, dsig->signing_key_digest, DIGEST_LEN)) {
is_duplicate = 1;
}
});
@@ -4359,7 +4371,7 @@ microdescs_parse_from_string(const char *s, const char *eos,
}
if ((tok = find_opt_by_keyword(tokens, K_P))) {
- md->exitsummary = tor_strdup(tok->args[0]);
+ md->exit_policy = parse_short_policy(tok->args[0]);
}
crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256);
diff --git a/src/or/status.c b/src/or/status.c
new file mode 100644
index 000000000..3e4cb779a
--- /dev/null
+++ b/src/or/status.c
@@ -0,0 +1,115 @@
+/* Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file status.c
+ * \brief Keep status information and log the heartbeat messages.
+ **/
+
+#include "or.h"
+#include "config.h"
+#include "status.h"
+#include "nodelist.h"
+#include "router.h"
+#include "circuitlist.h"
+#include "main.h"
+
+/** Return the total number of circuits. */
+static int
+count_circuits(void)
+{
+ circuit_t *circ;
+ int nr=0;
+
+ for (circ = _circuit_get_global_list(); circ; circ = circ->next)
+ nr++;
+
+ return nr;
+}
+
+/** Take seconds <b>secs</b> and return a newly allocated human-readable
+ * uptime string */
+static char *
+secs_to_uptime(long secs)
+{
+ long int days = secs / 86400;
+ int hours = (int)((secs - (days * 86400)) / 3600);
+ int minutes = (int)((secs - (days * 86400) - (hours * 3600)) / 60);
+ char *uptime_string = NULL;
+
+ switch (days) {
+ case 0:
+ tor_asprintf(&uptime_string, "%d:%02d hours", hours, minutes);
+ break;
+ case 1:
+ tor_asprintf(&uptime_string, "%ld day %d:%02d hours",
+ days, hours, minutes);
+ break;
+ default:
+ tor_asprintf(&uptime_string, "%ld days %d:%02d hours",
+ days, hours, minutes);
+ break;
+ }
+
+ return uptime_string;
+}
+
+/** Take <b>bytes</b> and returns a newly allocated human-readable usage
+ * string. */
+static char *
+bytes_to_usage(uint64_t bytes)
+{
+ char *bw_string = NULL;
+
+ if (bytes < (1<<20)) { /* Less than a megabyte. */
+ tor_asprintf(&bw_string, U64_FORMAT" kB", U64_PRINTF_ARG(bytes>>10));
+ } else if (bytes < (1<<30)) { /* Megabytes. Let's add some precision. */
+ double bw = U64_TO_DBL(bytes);
+ tor_asprintf(&bw_string, "%.2f MB", bw/(1<<20));
+ } else { /* Gigabytes. */
+ double bw = U64_TO_DBL(bytes);
+ tor_asprintf(&bw_string, "%.2f GB", bw/(1<<30));
+ }
+
+ return bw_string;
+}
+
+/** Log a "heartbeat" message describing Tor's status and history so that the
+ * user can know that there is indeed a running Tor. Return 0 on success and
+ * -1 on failure. */
+int
+log_heartbeat(time_t now)
+{
+ char *bw_sent = NULL;
+ char *bw_rcvd = NULL;
+ char *uptime = NULL;
+ const routerinfo_t *me;
+
+ const or_options_t *options = get_options();
+ (void)now;
+
+ if (public_server_mode(options)) {
+ /* Let's check if we are in the current cached consensus. */
+ if (!(me = router_get_my_routerinfo()))
+ return -1; /* Something stinks, we won't even attempt this. */
+ else
+ if (!node_get_by_id(me->cache_info.identity_digest))
+ log_fn(LOG_NOTICE, LD_HEARTBEAT, "Heartbeat: It seems like we are not "
+ "in the cached consensus.");
+ }
+
+ uptime = secs_to_uptime(get_uptime());
+ bw_rcvd = bytes_to_usage(get_bytes_read());
+ bw_sent = bytes_to_usage(get_bytes_written());
+
+ log_fn(LOG_NOTICE, LD_HEARTBEAT, "Heartbeat: Tor's uptime is %s, with %d "
+ "circuits open. I've sent %s and received %s.",
+ uptime, count_circuits(),bw_sent,bw_rcvd);
+
+ tor_free(uptime);
+ tor_free(bw_sent);
+ tor_free(bw_rcvd);
+
+ return 0;
+}
+
diff --git a/src/or/status.h b/src/or/status.h
new file mode 100644
index 000000000..ac726a1d2
--- /dev/null
+++ b/src/or/status.h
@@ -0,0 +1,10 @@
+/* Copyright (c) 2010, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef _TOR_STATUS_H
+#define _TOR_STATUS_H
+
+int log_heartbeat(time_t now);
+
+#endif
+
diff --git a/src/or/transports.c b/src/or/transports.c
new file mode 100644
index 000000000..3c533ccd9
--- /dev/null
+++ b/src/or/transports.c
@@ -0,0 +1,1048 @@
+/* Copyright (c) 2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file transports.c
+ * \brief Pluggable Transports related code.
+ **/
+
+#define PT_PRIVATE
+#include "or.h"
+#include "config.h"
+#include "circuitbuild.h"
+#include "transports.h"
+#include "util.h"
+
+static void set_managed_proxy_environment(char ***envp,
+ const managed_proxy_t *mp);
+static INLINE int proxy_configuration_finished(const managed_proxy_t *mp);
+
+static void managed_proxy_destroy(managed_proxy_t *mp);
+
+static void handle_finished_proxy(managed_proxy_t *mp);
+static void configure_proxy(managed_proxy_t *mp);
+
+static void parse_method_error(const char *line, int is_server_method);
+#define parse_server_method_error(l) parse_method_error(l, 1)
+#define parse_client_method_error(l) parse_method_error(l, 0)
+
+static INLINE void free_execve_args(char **arg);
+
+/** Managed proxy protocol strings */
+#define PROTO_ENV_ERROR "ENV-ERROR"
+#define PROTO_NEG_SUCCESS "VERSION"
+#define PROTO_NEG_FAIL "VERSION-ERROR no-version"
+#define PROTO_CMETHOD "CMETHOD"
+#define PROTO_SMETHOD "SMETHOD"
+#define PROTO_CMETHOD_ERROR "CMETHOD-ERROR"
+#define PROTO_SMETHOD_ERROR "SMETHOD-ERROR"
+#define PROTO_CMETHODS_DONE "CMETHODS DONE"
+#define PROTO_SMETHODS_DONE "SMETHODS DONE"
+
+/* The smallest valid managed proxy protocol line that can
+ appear. It's the size of "VERSION 1" */
+#define SMALLEST_MANAGED_LINE_SIZE 9
+
+/** Number of environment variables for managed proxy clients/servers. */
+#define ENVIRON_SIZE_CLIENT 5
+#define ENVIRON_SIZE_SERVER 8
+
+/** The first and only supported - at the moment - configuration
+ protocol version. */
+#define PROTO_VERSION_ONE 1
+
+/** List of unconfigured managed proxies. */
+static smartlist_t *managed_proxy_list = NULL;
+/** Number of still unconfigured proxies. */
+static int unconfigured_proxies_n = 0;
+
+/** "The main idea is:"
+
+ Each managed proxy is represented by a 'managed_proxy_t'.
+ Each managed proxy can support multiple transports.
+ Each managed proxy gets configured through a multistep process.
+
+ 'managed_proxy_list' contains all the managed proxies this tor
+ instance is supporting.
+ In the 'managed_proxy_list' there are 'unconfigured_proxies_n'
+ managed proxies that are still unconfigured.
+
+ In every run_scheduled_event() tick, we attempt to launch and then
+ configure the unconfiged managed proxies, using the configuration
+ protocol defined in the 180_pluggable_transport.txt proposal. A
+ managed proxy might need several ticks to get fully configured.
+
+ When a managed proxy is fully configured, we register all its
+ transports to the circuitbuild.c subsystem. At that point the
+ transports are owned by the circuitbuild.c subsystem.
+
+ When a managed proxy fails to follow the 180 configuration
+ protocol, it gets marked as broken and gets destroyed.
+
+ "In a little more technical detail:"
+
+ While we are serially parsing torrc, we store all the transports
+ that a proxy should spawn in its 'transports_to_launch' element.
+
+ When we finish reading the torrc, we spawn the managed proxy and
+ expect {S,C}METHOD lines from its output. We add transports
+ described by METHOD lines to its 'transports' element, as
+ 'transport_t' structs.
+
+ When the managed proxy stops spitting METHOD lines (signified by a
+ '{S,C}METHODS DONE' message) we register all the transports
+ collected to the circuitbuild.c subsystem. At this point, the
+ 'transport_t's can be transformed into dangling pointers at any
+ point by the circuitbuild.c subsystem, and so we replace all
+ 'transport_t's with strings describing the transport names. We
+ can still go from a transport name to a 'transport_t' using the
+ fact that transport names uniquely identify 'transport_t's.
+
+ "In even more technical detail I shall describe what happens when
+ the SIGHUP bell tolls:"
+
+ We immediately destroy all unconfigured proxies (We shouldn't have
+ unconfigured proxies in the first place, except when SIGHUP rings
+ immediately after tor is launched.).
+
+ We mark all managed proxies and transports to signify that they
+ must be removed if they don't contribute by the new torrc
+ (marked_for_removal).
+ We also mark all managed proxies to signify that they might need
+ to be restarted so that they end up supporting all the transports
+ the new torrc wants them to support (got_hup).
+ We also clear their 'transports_to_launch' list so that we can put
+ there the transports we need to launch according to the new torrc.
+
+ We then start parsing torrc again.
+
+ Everytime we encounter a transport line using a known pre-SIGHUP
+ managed proxy, we cleanse that proxy from the removal mark.
+
+ We also mark it as unconfigured so that on the next scheduled
+ events tick, we investigate whether we need to restart the proxy
+ so that it also spawns the new transports.
+ If the post-SIGHUP 'transports_to_launch' list is identical to the
+ pre-SIGHUP one, it means that no changes were introduced to this
+ proxy during the SIGHUP and no restart has to take place.
+
+ During the post-SIGHUP torrc parsing, we unmark all transports
+ spawned by managed proxies that we find in our torrc.
+ We do that so that if we don't need to restart a managed proxy, we
+ can continue using its old transports normally.
+ If we end up restarting the proxy, we destroy and unregister all
+ old transports from the circuitbuild.c subsystem.
+*/
+
+/** Return true if there are still unconfigured managed proxies. */
+int
+pt_proxies_configuration_pending(void)
+{
+ return !! unconfigured_proxies_n;
+}
+
+/** Return true if <b>mp</b> has the same argv as <b>proxy_argv</b> */
+static int
+managed_proxy_has_argv(const managed_proxy_t *mp, char **proxy_argv)
+{
+ char **tmp1=proxy_argv;
+ char **tmp2=mp->argv;
+
+ tor_assert(tmp1);
+ tor_assert(tmp2);
+
+ while (*tmp1 && *tmp2) {
+ if (strcmp(*tmp1++, *tmp2++))
+ return 0;
+ }
+
+ if (!*tmp1 && !*tmp2)
+ return 1;
+
+ return 0;
+}
+
+/** Return a managed proxy with the same argv as <b>proxy_argv</b>.
+ * If no such managed proxy exists, return NULL. */
+static managed_proxy_t *
+get_managed_proxy_by_argv_and_type(char **proxy_argv, int is_server)
+{
+ if (!managed_proxy_list)
+ return NULL;
+
+ SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
+ if (managed_proxy_has_argv(mp, proxy_argv) &&
+ mp->is_server == is_server)
+ return mp;
+ } SMARTLIST_FOREACH_END(mp);
+
+ return NULL;
+}
+
+/** Add <b>transport</b> to managed proxy <b>mp</b>. */
+static void
+add_transport_to_proxy(const char *transport, managed_proxy_t *mp)
+{
+ tor_assert(mp->transports_to_launch);
+ if (!smartlist_string_isin(mp->transports_to_launch, transport))
+ smartlist_add(mp->transports_to_launch, tor_strdup(transport));
+}
+
+/** Called when a SIGHUP occurs. Returns true if managed proxy
+ * <b>mp</b> needs to be restarted after the SIGHUP, based on the new
+ * torrc. */
+static int
+proxy_needs_restart(const managed_proxy_t *mp)
+{
+ /* mp->transport_to_launch is populated with the names of the
+ transports that must be launched *after* the SIGHUP.
+ mp->transports is populated with the names of the transports that
+ were launched *before* the SIGHUP.
+
+ If the two lists contain the same strings, we don't need to
+ restart the proxy, since it already does what we want. */
+
+ tor_assert(smartlist_len(mp->transports_to_launch) > 0);
+ tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
+
+ if (smartlist_len(mp->transports_to_launch) != smartlist_len(mp->transports))
+ goto needs_restart;
+
+ SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t_t_l) {
+ if (!smartlist_string_isin(mp->transports, t_t_l))
+ goto needs_restart;
+
+ } SMARTLIST_FOREACH_END(t_t_l);
+
+ return 0;
+
+ needs_restart:
+ return 1;
+}
+
+/** Managed proxy <b>mp</b> must be restarted. Do all the necessary
+ * preparations and then flag its state so that it will be relaunched
+ * in the next tick. */
+static void
+proxy_prepare_for_restart(managed_proxy_t *mp)
+{
+ transport_t *t_tmp = NULL;
+
+ tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
+ tor_assert(mp->pid);
+
+ /* kill the old obfsproxy process */
+ tor_terminate_process(mp->pid);
+ mp->pid = 0;
+ fclose(mp->_stdout);
+
+ /* destroy all its old transports. we no longer use them. */
+ SMARTLIST_FOREACH_BEGIN(mp->transports, const char *, t_name) {
+ t_tmp = transport_get_by_name(t_name);
+ if (t_tmp)
+ t_tmp->marked_for_removal = 1;
+ } SMARTLIST_FOREACH_END(t_name);
+ sweep_transport_list();
+
+ /* free the transport names in mp->transports */
+ SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name));
+ smartlist_clear(mp->transports);
+
+ /* flag it as an infant proxy so that it gets launched on next tick */
+ mp->conf_state = PT_PROTO_INFANT;
+}
+
+/** Launch managed proxy <b>mp</b>. */
+static int
+launch_managed_proxy(managed_proxy_t *mp)
+{
+ (void) mp;
+ (void) set_managed_proxy_environment;
+ return -1;
+#if 0
+ /* XXXX023 we must reenable this code for managed proxies to work.
+ * "All it needs" is revision to work with the new tor_spawn_background
+ * API. */
+ char **envp=NULL;
+ int pid;
+ process_handle_t proc;
+ FILE *stdout_read = NULL;
+ int stdout_pipe=-1, stderr_pipe=-1;
+
+ /* prepare the environment variables for the managed proxy */
+ set_managed_proxy_environment(&envp, mp);
+
+ pid = tor_spawn_background(mp->argv[0], (const char **)mp->argv,
+ (const char **)envp, &proc);
+ if (pid < 0) {
+ log_warn(LD_GENERAL, "Managed proxy at '%s' failed at launch.",
+ mp->argv[0]);
+ return -1;
+ }
+
+ /* free the memory allocated by set_managed_proxy_environment(). */
+ free_execve_args(envp);
+
+ /* Set stdout/stderr pipes to be non-blocking */
+#ifdef _WIN32
+ {
+ u_long nonblocking = 1;
+ ioctlsocket(stdout_pipe, FIONBIO, &nonblocking);
+ }
+#else
+ fcntl(stdout_pipe, F_SETFL, O_NONBLOCK);
+#endif
+
+ /* Open the buffered IO streams */
+ stdout_read = fdopen(stdout_pipe, "r");
+
+ log_info(LD_CONFIG, "Managed proxy has spawned at PID %d.", pid);
+
+ mp->conf_state = PT_PROTO_LAUNCHED;
+ mp->_stdout = stdout_read;
+ mp->pid = pid;
+#endif
+ return 0;
+}
+
+/** Check if any of the managed proxies we are currently trying to
+ * configure have anything new to say. This is called from
+ * run_scheduled_events(). */
+void
+pt_configure_remaining_proxies(void)
+{
+ log_debug(LD_CONFIG, "Configuring remaining managed proxies (%d)!",
+ unconfigured_proxies_n);
+ SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
+ tor_assert(mp->conf_state != PT_PROTO_BROKEN);
+
+ if (mp->got_hup) {
+ mp->got_hup = 0;
+
+ /* This proxy is marked by a SIGHUP. Check whether we need to
+ restart it. */
+ if (proxy_needs_restart(mp)) {
+ log_info(LD_GENERAL, "Preparing managed proxy for restart.");
+ proxy_prepare_for_restart(mp);
+ continue;
+ } else { /* it doesn't need to be restarted. */
+ log_info(LD_GENERAL, "Nothing changed for managed proxy after HUP: "
+ "not restarting.");
+ unconfigured_proxies_n--;
+ tor_assert(unconfigured_proxies_n >= 0);
+ }
+
+ continue;
+ }
+
+ /* If the proxy is not fully configured, try to configure it
+ futher. */
+ if (!proxy_configuration_finished(mp))
+ configure_proxy(mp);
+
+ } SMARTLIST_FOREACH_END(mp);
+}
+
+/** Attempt to continue configuring managed proxy <b>mp</b>. */
+static void
+configure_proxy(managed_proxy_t *mp)
+{
+ enum stream_status r;
+ char stdout_buf[200];
+
+ /* if we haven't launched the proxy yet, do it now */
+ if (mp->conf_state == PT_PROTO_INFANT) {
+ launch_managed_proxy(mp);
+ return;
+ }
+
+ tor_assert(mp->conf_state != PT_PROTO_INFANT);
+
+ while (1) {
+ r = get_string_from_pipe(mp->_stdout, stdout_buf,
+ sizeof(stdout_buf) - 1);
+
+ if (r == IO_STREAM_OKAY) { /* got a line; handle it! */
+ handle_proxy_line((const char *)stdout_buf, mp);
+ } else if (r == IO_STREAM_EAGAIN) { /* check back later */
+ return;
+ } else if (r == IO_STREAM_CLOSED || r == IO_STREAM_TERM) { /* snap! */
+ log_notice(LD_GENERAL, "Managed proxy stream closed. "
+ "Most probably application stopped running");
+ mp->conf_state = PT_PROTO_BROKEN;
+ } else { /* unknown stream status */
+ log_notice(LD_GENERAL, "Unknown stream status while configuring proxy.");
+ }
+
+ /* if the proxy finished configuring, exit the loop. */
+ if (proxy_configuration_finished(mp)) {
+ handle_finished_proxy(mp);
+ return;
+ }
+ }
+}
+
+/** Register server managed proxy <b>mp</b> transports to state */
+static void
+register_server_proxy(managed_proxy_t *mp)
+{
+ /* After we register this proxy's transports, we switch its
+ mp->transports to a list containing strings of its transport
+ names. (See transports.h) */
+ smartlist_t *sm_tmp = smartlist_create();
+
+ tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
+ SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
+ save_transport_to_state(t->name, &t->addr, t->port);
+ smartlist_add(sm_tmp, tor_strdup(t->name));
+ } SMARTLIST_FOREACH_END(t);
+
+ /* Since server proxies don't register their transports in the
+ circuitbuild.c subsystem, it's our duty to free them when we
+ switch mp->transports to strings. */
+ SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
+ smartlist_free(mp->transports);
+
+ mp->transports = sm_tmp;
+}
+
+/** Register all the transports supported by client managed proxy
+ * <b>mp</b> to the bridge subsystem. */
+static void
+register_client_proxy(managed_proxy_t *mp)
+{
+ int r;
+ /* After we register this proxy's transports, we switch its
+ mp->transports to a list containing strings of its transport
+ names. (See transports.h) */
+ smartlist_t *sm_tmp = smartlist_create();
+
+ tor_assert(mp->conf_state != PT_PROTO_COMPLETED);
+ SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) {
+ r = transport_add(t);
+ switch (r) {
+ case -1:
+ log_notice(LD_GENERAL, "Could not add transport %s. Skipping.", t->name);
+ transport_free(t);
+ break;
+ case 0:
+ log_info(LD_GENERAL, "Succesfully registered transport %s", t->name);
+ smartlist_add(sm_tmp, tor_strdup(t->name));
+ break;
+ case 1:
+ log_info(LD_GENERAL, "Succesfully registered transport %s", t->name);
+ smartlist_add(sm_tmp, tor_strdup(t->name));
+ transport_free(t);
+ break;
+ }
+ } SMARTLIST_FOREACH_END(t);
+
+ smartlist_free(mp->transports);
+ mp->transports = sm_tmp;
+}
+
+/** Register the transports of managed proxy <b>mp</b>. */
+static INLINE void
+register_proxy(managed_proxy_t *mp)
+{
+ if (mp->is_server)
+ register_server_proxy(mp);
+ else
+ register_client_proxy(mp);
+}
+
+/** Free memory allocated by managed proxy <b>mp</b>. */
+static void
+managed_proxy_destroy(managed_proxy_t *mp)
+{
+ if (mp->conf_state != PT_PROTO_COMPLETED)
+ SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
+ else
+ SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name));
+
+ /* free the transports smartlist */
+ smartlist_free(mp->transports);
+
+ /* free the transports_to_launch smartlist */
+ SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
+ smartlist_free(mp->transports_to_launch);
+
+ /* remove it from the list of managed proxies */
+ smartlist_remove(managed_proxy_list, mp);
+
+ /* close its stdout stream */
+ if (mp->_stdout)
+ fclose(mp->_stdout);
+
+ /* free the argv */
+ free_execve_args(mp->argv);
+
+ if (mp->pid)
+ tor_terminate_process(mp->pid);
+
+ tor_free(mp);
+}
+
+/** Handle a configured or broken managed proxy <b>mp</b>. */
+static void
+handle_finished_proxy(managed_proxy_t *mp)
+{
+ switch (mp->conf_state) {
+ case PT_PROTO_BROKEN: /* if broken: */
+ managed_proxy_destroy(mp); /* annihilate it. */
+ break;
+ case PT_PROTO_CONFIGURED: /* if configured correctly: */
+ register_proxy(mp); /* register its transports */
+ mp->conf_state = PT_PROTO_COMPLETED; /* and mark it as completed. */
+ break;
+ case PT_PROTO_INFANT:
+ case PT_PROTO_LAUNCHED:
+ case PT_PROTO_ACCEPTING_METHODS:
+ case PT_PROTO_COMPLETED:
+ default:
+ log_warn(LD_CONFIG, "Unexpected managed proxy state in "
+ "handle_finished_proxy().");
+ tor_assert(0);
+ }
+
+ unconfigured_proxies_n--;
+ tor_assert(unconfigured_proxies_n >= 0);
+}
+
+/** Return true if the configuration of the managed proxy <b>mp</b> is
+ finished. */
+static INLINE int
+proxy_configuration_finished(const managed_proxy_t *mp)
+{
+ return (mp->conf_state == PT_PROTO_CONFIGURED ||
+ mp->conf_state == PT_PROTO_BROKEN);
+}
+
+/** This function is called when a proxy sends an {S,C}METHODS DONE message. */
+static void
+handle_methods_done(const managed_proxy_t *mp)
+{
+ tor_assert(mp->transports);
+
+ if (smartlist_len(mp->transports) == 0)
+ log_notice(LD_GENERAL, "Proxy was spawned successfully, "
+ "but it didn't laucn any pluggable transport listeners!");
+
+ log_info(LD_CONFIG, "%s managed proxy configuration completed!",
+ mp->is_server ? "Server" : "Client");
+}
+
+/** Handle a configuration protocol <b>line</b> received from a
+ * managed proxy <b>mp</b>. */
+void
+handle_proxy_line(const char *line, managed_proxy_t *mp)
+{
+ log_debug(LD_GENERAL, "Got a line from managed proxy: %s\n", line);
+
+ if (strlen(line) < SMALLEST_MANAGED_LINE_SIZE) {
+ log_warn(LD_GENERAL, "Managed proxy configuration line is too small. "
+ "Discarding");
+ goto err;
+ }
+
+ if (!strcmpstart(line, PROTO_ENV_ERROR)) {
+ if (mp->conf_state != PT_PROTO_LAUNCHED)
+ goto err;
+
+ parse_env_error(line);
+ goto err;
+ } else if (!strcmpstart(line, PROTO_NEG_FAIL)) {
+ if (mp->conf_state != PT_PROTO_LAUNCHED)
+ goto err;
+
+ log_warn(LD_CONFIG, "Managed proxy could not pick a "
+ "configuration protocol version.");
+ goto err;
+ } else if (!strcmpstart(line, PROTO_NEG_SUCCESS)) {
+ if (mp->conf_state != PT_PROTO_LAUNCHED)
+ goto err;
+
+ if (parse_version(line,mp) < 0)
+ goto err;
+
+ tor_assert(mp->conf_protocol != 0);
+ mp->conf_state = PT_PROTO_ACCEPTING_METHODS;
+ return;
+ } else if (!strcmpstart(line, PROTO_CMETHODS_DONE)) {
+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
+ goto err;
+
+ handle_methods_done(mp);
+
+ mp->conf_state = PT_PROTO_CONFIGURED;
+ return;
+ } else if (!strcmpstart(line, PROTO_SMETHODS_DONE)) {
+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
+ goto err;
+
+ handle_methods_done(mp);
+
+ mp->conf_state = PT_PROTO_CONFIGURED;
+ return;
+ } else if (!strcmpstart(line, PROTO_CMETHOD_ERROR)) {
+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
+ goto err;
+
+ parse_client_method_error(line);
+ goto err;
+ } else if (!strcmpstart(line, PROTO_SMETHOD_ERROR)) {
+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
+ goto err;
+
+ parse_server_method_error(line);
+ goto err;
+ } else if (!strcmpstart(line, PROTO_CMETHOD)) {
+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
+ goto err;
+
+ if (parse_cmethod_line(line, mp) < 0)
+ goto err;
+
+ return;
+ } else if (!strcmpstart(line, PROTO_SMETHOD)) {
+ if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS)
+ goto err;
+
+ if (parse_smethod_line(line, mp) < 0)
+ goto err;
+
+ return;
+ } else if (!strcmpstart(line, SPAWN_ERROR_MESSAGE)) {
+ log_warn(LD_GENERAL, "Could not launch managed proxy executable!");
+ goto err;
+ }
+
+ log_warn(LD_CONFIG, "Unknown line received by managed proxy. (%s)", line);
+
+ err:
+ mp->conf_state = PT_PROTO_BROKEN;
+ return;
+}
+
+/** Parses an ENV-ERROR <b>line</b> and warns the user accordingly. */
+void
+parse_env_error(const char *line)
+{
+ /* (Length of the protocol string) plus (a space) and (the first char of
+ the error message) */
+ if (strlen(line) < (strlen(PROTO_ENV_ERROR) + 2))
+ log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error "
+ "message.", PROTO_ENV_ERROR);
+
+ log_warn(LD_CONFIG, "Managed proxy couldn't understand the "
+ "pluggable transport environment variables. (%s)",
+ line+strlen(PROTO_ENV_ERROR)+1);
+}
+
+/** Handles a VERSION <b>line</b>. Updates the configuration protocol
+ * version in <b>mp</b>. */
+int
+parse_version(const char *line, managed_proxy_t *mp)
+{
+ if (strlen(line) < (strlen(PROTO_NEG_SUCCESS) + 2)) {
+ log_warn(LD_CONFIG, "Managed proxy sent us malformed %s line.",
+ PROTO_NEG_SUCCESS);
+ return -1;
+ }
+
+ if (strcmp("1", line+strlen(PROTO_NEG_SUCCESS)+1)) { /* hardcoded temp */
+ log_warn(LD_CONFIG, "Managed proxy tried to negotiate on version '%s'. "
+ "We only support version '1'", line+strlen(PROTO_NEG_SUCCESS)+1);
+ return -1;
+ }
+
+ mp->conf_protocol = PROTO_VERSION_ONE; /* temp. till more versions appear */
+ return 0;
+}
+
+/** Parses {C,S}METHOD-ERROR <b>line</b> and warns the user
+ * accordingly. If <b>is_server</b> it is an SMETHOD-ERROR,
+ * otherwise it is a CMETHOD-ERROR. */
+static void
+parse_method_error(const char *line, int is_server)
+{
+ const char* error = is_server ?
+ PROTO_SMETHOD_ERROR : PROTO_CMETHOD_ERROR;
+
+ /* (Length of the protocol string) plus (a space) and (the first char of
+ the error message) */
+ if (strlen(line) < (strlen(error) + 2))
+ log_warn(LD_CONFIG, "Managed proxy sent us an %s without an error "
+ "message.", error);
+
+ log_warn(LD_CONFIG, "%s managed proxy encountered a method error. (%s)",
+ is_server ? "Server" : "Client",
+ line+strlen(error)+1);
+}
+
+/** Parses an SMETHOD <b>line</b> and if well-formed it registers the
+ * new transport in <b>mp</b>. */
+int
+parse_smethod_line(const char *line, managed_proxy_t *mp)
+{
+ int r;
+ smartlist_t *items = NULL;
+
+ char *method_name=NULL;
+
+ char *addrport=NULL;
+ tor_addr_t addr;
+ uint16_t port = 0;
+
+ transport_t *transport=NULL;
+
+ items = smartlist_create();
+ smartlist_split_string(items, line, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+ if (smartlist_len(items) < 3) {
+ log_warn(LD_CONFIG, "Server managed proxy sent us a SMETHOD line "
+ "with too few arguments.");
+ goto err;
+ }
+
+ tor_assert(!strcmp(smartlist_get(items,0),PROTO_SMETHOD));
+
+ method_name = smartlist_get(items,1);
+ if (!string_is_C_identifier(method_name)) {
+ log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
+ method_name);
+ goto err;
+ }
+
+ addrport = smartlist_get(items, 2);
+ if (tor_addr_port_parse(addrport, &addr, &port)<0) {
+ log_warn(LD_CONFIG, "Error parsing transport "
+ "address '%s'", addrport);
+ goto err;
+ }
+
+ if (!port) {
+ log_warn(LD_CONFIG,
+ "Transport address '%s' has no port.", addrport);
+ goto err;
+ }
+
+ transport = transport_create(&addr, port, method_name, PROXY_NONE);
+ if (!transport)
+ goto err;
+
+ smartlist_add(mp->transports, transport);
+
+ /* For now, notify the user so that he knows where the server
+ transport is listening. */
+ log_info(LD_CONFIG, "Server transport %s at %s:%d.",
+ method_name, fmt_addr(&addr), (int)port);
+
+ r=0;
+ goto done;
+
+ err:
+ r = -1;
+
+ done:
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+ return r;
+}
+
+/** Parses a CMETHOD <b>line</b>, and if well-formed it registers
+ * the new transport in <b>mp</b>. */
+int
+parse_cmethod_line(const char *line, managed_proxy_t *mp)
+{
+ int r;
+ smartlist_t *items = NULL;
+
+ char *method_name=NULL;
+
+ char *socks_ver_str=NULL;
+ int socks_ver=PROXY_NONE;
+
+ char *addrport=NULL;
+ tor_addr_t addr;
+ uint16_t port = 0;
+
+ transport_t *transport=NULL;
+
+ items = smartlist_create();
+ smartlist_split_string(items, line, NULL,
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
+ if (smartlist_len(items) < 4) {
+ log_warn(LD_CONFIG, "Client managed proxy sent us a CMETHOD line "
+ "with too few arguments.");
+ goto err;
+ }
+
+ tor_assert(!strcmp(smartlist_get(items,0),PROTO_CMETHOD));
+
+ method_name = smartlist_get(items,1);
+ if (!string_is_C_identifier(method_name)) {
+ log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).",
+ method_name);
+ goto err;
+ }
+
+ socks_ver_str = smartlist_get(items,2);
+
+ if (!strcmp(socks_ver_str,"socks4")) {
+ socks_ver = PROXY_SOCKS4;
+ } else if (!strcmp(socks_ver_str,"socks5")) {
+ socks_ver = PROXY_SOCKS5;
+ } else {
+ log_warn(LD_CONFIG, "Client managed proxy sent us a proxy protocol "
+ "we don't recognize. (%s)", socks_ver_str);
+ goto err;
+ }
+
+ addrport = smartlist_get(items, 3);
+ if (tor_addr_port_parse(addrport, &addr, &port)<0) {
+ log_warn(LD_CONFIG, "Error parsing transport "
+ "address '%s'", addrport);
+ goto err;
+ }
+
+ if (!port) {
+ log_warn(LD_CONFIG,
+ "Transport address '%s' has no port.", addrport);
+ goto err;
+ }
+
+ transport = transport_create(&addr, port, method_name, socks_ver);
+ if (!transport)
+ goto err;
+
+ smartlist_add(mp->transports, transport);
+
+ log_info(LD_CONFIG, "Transport %s at %s:%d with SOCKS %d. "
+ "Attached to managed proxy.",
+ method_name, fmt_addr(&addr), (int)port, socks_ver);
+
+ r=0;
+ goto done;
+
+ err:
+ r = -1;
+
+ done:
+ SMARTLIST_FOREACH(items, char*, s, tor_free(s));
+ smartlist_free(items);
+ return r;
+}
+
+/** Return a string containing the address:port that <b>transport</b>
+ * should use. It's the responsibility of the caller to free() the
+ * received string. */
+static char *
+get_bindaddr_for_proxy(const managed_proxy_t *mp)
+{
+ char *bindaddr = NULL;
+ smartlist_t *string_tmp = smartlist_create();
+
+ tor_assert(mp->is_server);
+
+ SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t) {
+ tor_asprintf(&bindaddr, "%s-%s", t, get_bindaddr_for_transport(t));
+ smartlist_add(string_tmp, bindaddr);
+ } SMARTLIST_FOREACH_END(t);
+
+ bindaddr = smartlist_join_strings(string_tmp, ",", 0, NULL);
+
+ SMARTLIST_FOREACH(string_tmp, char *, t, tor_free(t));
+ smartlist_free(string_tmp);
+
+ return bindaddr;
+}
+
+/** Prepare the <b>envp</b> of managed proxy <b>mp</b> */
+static void
+set_managed_proxy_environment(char ***envp, const managed_proxy_t *mp)
+{
+ const or_options_t *options = get_options();
+ char **tmp=NULL;
+ char *state_loc=NULL;
+ char *transports_to_launch=NULL;
+ char *bindaddr=NULL;
+
+ int n_envs = mp->is_server ? ENVIRON_SIZE_SERVER : ENVIRON_SIZE_CLIENT;
+
+ /* allocate enough space for our env. vars and a NULL pointer */
+ *envp = tor_malloc(sizeof(char*)*(n_envs+1));
+ tmp = *envp;
+
+ state_loc = get_datadir_fname("pt_state/"); /* XXX temp */
+ transports_to_launch =
+ smartlist_join_strings(mp->transports_to_launch, ",", 0, NULL);
+
+ tor_asprintf(tmp++, "HOME=%s", getenv("HOME"));
+ tor_asprintf(tmp++, "PATH=%s", getenv("PATH"));
+ tor_asprintf(tmp++, "TOR_PT_STATE_LOCATION=%s", state_loc);
+ tor_asprintf(tmp++, "TOR_PT_MANAGED_TRANSPORT_VER=1"); /* temp */
+ if (mp->is_server) {
+ bindaddr = get_bindaddr_for_proxy(mp);
+
+ /* XXX temp */
+ tor_asprintf(tmp++, "TOR_PT_ORPORT=127.0.0.1:%d", options->ORPort);
+ tor_asprintf(tmp++, "TOR_PT_SERVER_BINDADDR=%s", bindaddr);
+ tor_asprintf(tmp++, "TOR_PT_SERVER_TRANSPORTS=%s", transports_to_launch);
+ /* XXX temp*/
+ tor_asprintf(tmp++, "TOR_PT_EXTENDED_SERVER_PORT=127.0.0.1:4200");
+ } else {
+ tor_asprintf(tmp++, "TOR_PT_CLIENT_TRANSPORTS=%s", transports_to_launch);
+ }
+ *tmp = NULL;
+
+ tor_free(state_loc);
+ tor_free(transports_to_launch);
+ tor_free(bindaddr);
+}
+
+/** Create and return a new managed proxy for <b>transport</b> using
+ * <b>proxy_argv</b>. If <b>is_server</b> is true, it's a server
+ * managed proxy. */
+static managed_proxy_t *
+managed_proxy_create(const smartlist_t *transport_list,
+ char **proxy_argv, int is_server)
+{
+ managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t));
+ mp->conf_state = PT_PROTO_INFANT;
+ mp->is_server = is_server;
+ mp->argv = proxy_argv;
+ mp->transports = smartlist_create();
+
+ mp->transports_to_launch = smartlist_create();
+ SMARTLIST_FOREACH(transport_list, const char *, transport,
+ add_transport_to_proxy(transport, mp));
+
+ /* register the managed proxy */
+ if (!managed_proxy_list)
+ managed_proxy_list = smartlist_create();
+ smartlist_add(managed_proxy_list, mp);
+ unconfigured_proxies_n++;
+
+ return mp;
+}
+
+/** Register <b>transport</b> using proxy with <b>proxy_argv</b> to
+ * the managed proxy subsystem.
+ * If <b>is_server</b> is true, then the proxy is a server proxy. */
+void
+pt_kickstart_proxy(const smartlist_t *transport_list,
+ char **proxy_argv, int is_server)
+{
+ managed_proxy_t *mp=NULL;
+ transport_t *old_transport = NULL;
+
+ mp = get_managed_proxy_by_argv_and_type(proxy_argv, is_server);
+
+ if (!mp) { /* we haven't seen this proxy before */
+ managed_proxy_create(transport_list, proxy_argv, is_server);
+
+ } else { /* known proxy. add its transport to its transport list */
+ if (mp->got_hup) {
+ /* If the managed proxy we found is marked by a SIGHUP, it means
+ that it's not useless and should be kept. If it's marked for
+ removal, unmark it and increase the unconfigured proxies so
+ that we try to restart it if we need to. Afterwards, check if
+ a transport_t for 'transport' used to exist before the SIGHUP
+ and make sure it doesn't get deleted because we might reuse
+ it. */
+ if (mp->marked_for_removal) {
+ mp->marked_for_removal = 0;
+ unconfigured_proxies_n++;
+ }
+
+ SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport) {
+ old_transport = transport_get_by_name(transport);
+ if (old_transport)
+ old_transport->marked_for_removal = 0;
+ } SMARTLIST_FOREACH_END(transport);
+ }
+
+ SMARTLIST_FOREACH(transport_list, const char *, transport,
+ add_transport_to_proxy(transport, mp));
+ free_execve_args(proxy_argv);
+ }
+}
+
+/** Frees the array of pointers in <b>arg</b> used as arguments to
+ execve(2). */
+static INLINE void
+free_execve_args(char **arg)
+{
+ char **tmp = arg;
+ while (*tmp) /* use the fact that the last element of the array is a
+ NULL pointer to know when to stop freeing */
+ _tor_free(*tmp++);
+
+ tor_free(arg);
+}
+
+/** Tor will read its config.
+ * Prepare the managed proxy list so that proxies not used in the new
+ * config will shutdown, and proxies that need to spawn different
+ * transports will do so. */
+void
+pt_prepare_proxy_list_for_config_read(void)
+{
+ if (!managed_proxy_list)
+ return;
+
+ SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
+ /* Destroy unconfigured proxies. */
+ if (mp->conf_state != PT_PROTO_COMPLETED) {
+ managed_proxy_destroy(mp);
+ unconfigured_proxies_n--;
+ continue;
+ }
+
+ tor_assert(mp->conf_state == PT_PROTO_COMPLETED);
+
+ mp->marked_for_removal = 1;
+ mp->got_hup = 1;
+ SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t));
+ smartlist_clear(mp->transports_to_launch);
+ } SMARTLIST_FOREACH_END(mp);
+
+ tor_assert(unconfigured_proxies_n == 0);
+}
+
+/** The tor config was read.
+ * Destroy all managed proxies that were marked by a previous call to
+ * prepare_proxy_list_for_config_read() and are not used by the new
+ * config. */
+void
+sweep_proxy_list(void)
+{
+ if (!managed_proxy_list)
+ return;
+
+ SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) {
+ if (mp->marked_for_removal) {
+ SMARTLIST_DEL_CURRENT(managed_proxy_list, mp);
+ managed_proxy_destroy(mp);
+ }
+ } SMARTLIST_FOREACH_END(mp);
+}
+
+/** Release all storage held by the pluggable transports subsystem. */
+void
+pt_free_all(void)
+{
+ if (managed_proxy_list) {
+ /* If the proxy is in PT_PROTO_COMPLETED, it has registered its
+ transports and it's the duty of the circuitbuild.c subsystem to
+ free them. Otherwise, it hasn't registered its transports yet
+ and we should free them here. */
+ SMARTLIST_FOREACH(managed_proxy_list, managed_proxy_t *, mp,
+ managed_proxy_destroy(mp));
+
+ smartlist_free(managed_proxy_list);
+ managed_proxy_list=NULL;
+ }
+}
+
diff --git a/src/or/transports.h b/src/or/transports.h
new file mode 100644
index 000000000..4a9338759
--- /dev/null
+++ b/src/or/transports.h
@@ -0,0 +1,105 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file transports.h
+ * \brief Headers for transports.c
+ **/
+
+#ifndef TOR_TRANSPORTS_H
+#define TOR_TRANSPORTS_H
+
+void pt_kickstart_proxy(const smartlist_t *transport_list, char **proxy_argv,
+ int is_server);
+
+#define pt_kickstart_client_proxy(tl, pa) \
+ pt_kickstart_proxy(tl, pa, 0)
+#define pt_kickstart_server_proxy(tl, pa) \
+ pt_kickstart_proxy(tl, pa, 1)
+
+void pt_configure_remaining_proxies(void);
+
+int pt_proxies_configuration_pending(void);
+
+void pt_free_all(void);
+
+void pt_prepare_proxy_list_for_config_read(void);
+void sweep_proxy_list(void);
+
+#ifdef PT_PRIVATE
+/** State of the managed proxy configuration protocol. */
+enum pt_proto_state {
+ PT_PROTO_INFANT, /* was just born */
+ PT_PROTO_LAUNCHED, /* was just launched */
+ PT_PROTO_ACCEPTING_METHODS, /* accepting methods */
+ PT_PROTO_CONFIGURED, /* configured successfully */
+ PT_PROTO_COMPLETED, /* configure and registered its transports */
+ PT_PROTO_BROKEN
+};
+
+/** Structure containing information of a managed proxy. */
+typedef struct {
+ enum pt_proto_state conf_state; /* the current configuration state */
+ char **argv; /* the cli arguments of this proxy */
+ int conf_protocol; /* the configuration protocol version used */
+
+ int is_server; /* is it a server proxy? */
+
+ FILE *_stdout; /* a stream to its stdout
+ (closed in managed_proxy_destroy()) */
+
+ int pid; /* The Process ID this managed proxy is using. */
+
+ /** Boolean: We are re-parsing our config, and we are going to
+ * remove this managed proxy if we don't find it any transport
+ * plugins that use it. */
+ unsigned int marked_for_removal : 1;
+
+ /** Boolean: We got a SIGHUP while this proxy was running. We use
+ * this flag to signify that this proxy might need to be restarted
+ * so that it can listen for other transports according to the new
+ * torrc. */
+ unsigned int got_hup : 1;
+
+ /* transports to-be-launched by this proxy */
+ smartlist_t *transports_to_launch;
+
+ /* The 'transports' list contains all the transports this proxy has
+ launched.
+
+ Before a managed_proxy_t reaches the PT_PROTO_COMPLETED phase,
+ this smartlist contains a 'transport_t' for every transport it
+ has launched.
+
+ When the managed_proxy_t reaches the PT_PROTO_COMPLETED phase, it
+ registers all its transports to the circuitbuild.c subsystem. At
+ that point the 'transport_t's are owned by the circuitbuild.c
+ subsystem.
+
+ To avoid carrying dangling 'transport_t's in this smartlist,
+ right before the managed_proxy_t reaches the PT_PROTO_COMPLETED
+ phase we replace all 'transport_t's with strings of their
+ transport names.
+
+ So, tl;dr:
+ When (conf_state != PT_PROTO_COMPLETED) this list carries
+ (transport_t *).
+ When (conf_state == PT_PROTO_COMPLETED) this list carries
+ (char *).
+ */
+ smartlist_t *transports;
+} managed_proxy_t;
+
+int parse_cmethod_line(const char *line, managed_proxy_t *mp);
+int parse_smethod_line(const char *line, managed_proxy_t *mp);
+
+int parse_version(const char *line, managed_proxy_t *mp);
+void parse_env_error(const char *line);
+void handle_proxy_line(const char *line, managed_proxy_t *mp);
+
+#endif
+
+#endif
+
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
index 904719d94..301452b4e 100644
--- a/src/test/Makefile.am
+++ b/src/test/Makefile.am
@@ -1,6 +1,6 @@
TESTS = test
-noinst_PROGRAMS = test
+noinst_PROGRAMS = test test-child
AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
-DLOCALSTATEDIR="\"$(localstatedir)\"" \
@@ -12,12 +12,14 @@ AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \
# matters a lot there, and is quite hard to debug if you forget to do it.
test_SOURCES = \
- test_data.c \
test.c \
test_addr.c \
+ test_containers.c \
test_crypto.c \
+ test_data.c \
test_dir.c \
- test_containers.c \
+ test_microdesc.c \
+ test_pt.c \
test_util.c \
tinytest.c
@@ -25,6 +27,12 @@ test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
@TOR_LDFLAGS_libevent@
test_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@
+ @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \
+ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+
+noinst_HEADERS = \
+ tinytest.h \
+ tinytest_macros.h \
+ test.h
+
-noinst_HEADERS = tinytest.h tinytest_macros.h test.h
diff --git a/src/test/test-child.c b/src/test/test-child.c
new file mode 100644
index 000000000..1b9c5e3d5
--- /dev/null
+++ b/src/test/test-child.c
@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include "orconfig.h"
+#ifdef MS_WINDOWS
+#define WINDOWS_LEAN_AND_MEAN
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+/** Trivial test program which prints out its command line arguments so we can
+ * check if tor_spawn_background() works */
+int
+main(int argc, char **argv)
+{
+ int i;
+
+ fprintf(stdout, "OUT\n");
+ fprintf(stderr, "ERR\n");
+ for (i = 1; i < argc; i++)
+ fprintf(stdout, "%s\n", argv[i]);
+ fprintf(stdout, "SLEEPING\n");
+ /* We need to flush stdout so that test_util_spawn_background_partial_read()
+ succeed. Otherwise ReadFile() will get the entire output in one */
+ // XXX: Can we make stdio flush on newline?
+ fflush(stdout);
+#ifdef MS_WINDOWS
+ Sleep(1000);
+#else
+ sleep(1);
+#endif
+ fprintf(stdout, "DONE\n");
+#ifdef MS_WINDOWS
+ Sleep(1000);
+#else
+ sleep(1);
+#endif
+
+ return 0;
+}
+
diff --git a/src/test/test.c b/src/test/test.c
index 9b24a99b5..aca7f10e6 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -119,30 +119,46 @@ get_fname(const char *name)
return buf;
}
-/** Remove all files stored under the temporary directory, and the directory
- * itself. Called by atexit(). */
+/* Remove a directory and all of its subdirectories */
static void
-remove_directory(void)
+rm_rf(const char *dir)
{
+ struct stat st;
smartlist_t *elements;
- if (getpid() != temp_dir_setup_in_pid) {
- /* Only clean out the tempdir when the main process is exiting. */
- return;
- }
- elements = tor_listdir(temp_dir);
+
+ elements = tor_listdir(dir);
if (elements) {
SMARTLIST_FOREACH(elements, const char *, cp,
{
- size_t len = strlen(cp)+strlen(temp_dir)+16;
- char *tmp = tor_malloc(len);
- tor_snprintf(tmp, len, "%s"PATH_SEPARATOR"%s", temp_dir, cp);
- unlink(tmp);
+ char *tmp = NULL;
+ tor_asprintf(&tmp, "%s"PATH_SEPARATOR"%s", dir, cp);
+ if (0 == stat(tmp,&st) && (st.st_mode & S_IFDIR)) {
+ rm_rf(tmp);
+ } else {
+ if (unlink(tmp)) {
+ fprintf(stderr, "Error removing %s: %s\n", tmp, strerror(errno));
+ }
+ }
tor_free(tmp);
});
SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp));
smartlist_free(elements);
}
- rmdir(temp_dir);
+ if (rmdir(dir))
+ fprintf(stderr, "Error removing directory %s: %s\n", dir, strerror(errno));
+}
+
+/** Remove all files stored under the temporary directory, and the directory
+ * itself. Called by atexit(). */
+static void
+remove_directory(void)
+{
+ if (getpid() != temp_dir_setup_in_pid) {
+ /* Only clean out the tempdir when the main process is exiting. */
+ return;
+ }
+
+ rm_rf(temp_dir);
}
/** Define this if unit tests spend too much time generating public keys*/
@@ -187,6 +203,437 @@ free_pregenerated_keys(void)
}
}
+typedef struct socks_test_data_t {
+ socks_request_t *req;
+ buf_t *buf;
+} socks_test_data_t;
+
+static void *
+socks_test_setup(const struct testcase_t *testcase)
+{
+ socks_test_data_t *data = tor_malloc(sizeof(socks_test_data_t));
+ (void)testcase;
+ data->buf = buf_new_with_capacity(256);
+ data->req = socks_request_new();
+ config_register_addressmaps(get_options());
+ return data;
+}
+static int
+socks_test_cleanup(const struct testcase_t *testcase, void *ptr)
+{
+ socks_test_data_t *data = ptr;
+ (void)testcase;
+ buf_free(data->buf);
+ socks_request_free(data->req);
+ tor_free(data);
+ return 1;
+}
+
+const struct testcase_setup_t socks_setup = {
+ socks_test_setup, socks_test_cleanup
+};
+
+#define SOCKS_TEST_INIT() \
+ socks_test_data_t *testdata = ptr; \
+ buf_t *buf = testdata->buf; \
+ socks_request_t *socks = testdata->req;
+#define ADD_DATA(buf, s) \
+ write_to_buf(s, sizeof(s)-1, buf)
+
+static void
+socks_request_clear(socks_request_t *socks)
+{
+ tor_free(socks->username);
+ tor_free(socks->password);
+ memset(socks, 0, sizeof(socks_request_t));
+}
+
+/** Perform unsupported SOCKS 4 commands */
+static void
+test_socks_4_unsupported_commands(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /* SOCKS 4 Send BIND [02] to IP address 2.2.2.2:4369 */
+ ADD_DATA(buf, "\x04\x02\x11\x11\x02\x02\x02\x02\x00");
+ test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks) == -1);
+ test_eq(4, socks->socks_version);
+ test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */
+
+ done:
+ ;
+}
+
+/** Perform supported SOCKS 4 commands */
+static void
+test_socks_4_supported_commands(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ test_eq(0, buf_datalen(buf));
+
+ /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4370 */
+ ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x03\x00");
+ test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks) == 1);
+ test_eq(4, socks->socks_version);
+ test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */
+ test_eq(SOCKS_COMMAND_CONNECT, socks->command);
+ test_streq("2.2.2.3", socks->address);
+ test_eq(4370, socks->port);
+ test_assert(socks->got_auth == 0);
+ test_assert(! socks->username);
+
+ test_eq(0, buf_datalen(buf));
+ socks_request_clear(socks);
+
+ /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4369 with userid*/
+ ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x04me\x00");
+ test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks) == 1);
+ test_eq(4, socks->socks_version);
+ test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */
+ test_eq(SOCKS_COMMAND_CONNECT, socks->command);
+ test_streq("2.2.2.4", socks->address);
+ test_eq(4370, socks->port);
+ test_assert(socks->got_auth == 1);
+ test_assert(socks->username);
+ test_eq(2, socks->usernamelen);
+ test_memeq("me", socks->username, 2);
+
+ test_eq(0, buf_datalen(buf));
+ socks_request_clear(socks);
+
+ /* SOCKS 4a Send RESOLVE [F0] request for torproject.org */
+ ADD_DATA(buf, "\x04\xF0\x01\x01\x00\x00\x00\x02me\x00torproject.org\x00");
+ test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks) == 1);
+ test_eq(4, socks->socks_version);
+ test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */
+ test_streq("torproject.org", socks->address);
+
+ test_eq(0, buf_datalen(buf));
+
+ done:
+ ;
+}
+
+/** Perform unsupported SOCKS 5 commands */
+static void
+test_socks_5_unsupported_commands(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /* SOCKS 5 Send unsupported BIND [02] command */
+ ADD_DATA(buf, "\x05\x02\x00\x01");
+
+ test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), 0);
+ test_eq(0, buf_datalen(buf));
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+ ADD_DATA(buf, "\x05\x02\x00\x01\x02\x02\x02\x01\x01\x01");
+ test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), -1);
+ /* XXX: shouldn't tor reply 'command not supported' [07]? */
+
+ buf_clear(buf);
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Send unsupported UDP_ASSOCIATE [03] command */
+ ADD_DATA(buf, "\x05\x03\x00\x01\x02");
+ test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), 0);
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+ ADD_DATA(buf, "\x05\x03\x00\x01\x02\x02\x02\x01\x01\x01");
+ test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), -1);
+ /* XXX: shouldn't tor reply 'command not supported' [07]? */
+
+ done:
+ ;
+}
+
+/** Perform supported SOCKS 5 commands */
+static void
+test_socks_5_supported_commands(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /* SOCKS 5 Send CONNECT [01] to IP address 2.2.2.2:4369 */
+ ADD_DATA(buf, "\x05\x01\x00");
+ test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), 0);
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+
+ ADD_DATA(buf, "\x05\x01\x00\x01\x02\x02\x02\x02\x11\x11");
+ test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), 1);
+ test_streq("2.2.2.2", socks->address);
+ test_eq(4369, socks->port);
+
+ test_eq(0, buf_datalen(buf));
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Send CONNECT [01] to FQDN torproject.org:4369 */
+ ADD_DATA(buf, "\x05\x01\x00");
+ ADD_DATA(buf, "\x05\x01\x00\x03\x0Etorproject.org\x11\x11");
+ test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks), 1);
+
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+ test_streq("torproject.org", socks->address);
+ test_eq(4369, socks->port);
+
+ test_eq(0, buf_datalen(buf));
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Send RESOLVE [F0] request for torproject.org:4369 */
+ ADD_DATA(buf, "\x05\x01\x00");
+ ADD_DATA(buf, "\x05\xF0\x00\x03\x0Etorproject.org\x01\x02");
+ test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks) == 1);
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+ test_streq("torproject.org", socks->address);
+
+ test_eq(0, buf_datalen(buf));
+ socks_request_clear(socks);
+
+ /* SOCKS 5 Send RESOLVE_PTR [F1] for IP address 2.2.2.5 */
+ ADD_DATA(buf, "\x05\x01\x00");
+ ADD_DATA(buf, "\x05\xF1\x00\x01\x02\x02\x02\x05\x01\x03");
+ test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks,
+ get_options()->SafeSocks) == 1);
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+ test_streq("2.2.2.5", socks->address);
+
+ test_eq(0, buf_datalen(buf));
+
+ done:
+ ;
+}
+
+/** Perform SOCKS 5 authentication */
+static void
+test_socks_5_no_authenticate(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /*SOCKS 5 No Authentication */
+ ADD_DATA(buf,"\x05\x01\x00");
+ test_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(SOCKS_NO_AUTH, socks->reply[1]);
+
+ test_eq(0, buf_datalen(buf));
+
+ /*SOCKS 5 Send username/password anyway - pretend to be broken */
+ ADD_DATA(buf,"\x01\x02\x01\x01\x02\x01\x01");
+ test_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+
+ test_eq(2, socks->usernamelen);
+ test_eq(2, socks->passwordlen);
+
+ test_memeq("\x01\x01", socks->username, 2);
+ test_memeq("\x01\x01", socks->password, 2);
+
+ done:
+ ;
+}
+
+/** Perform SOCKS 5 authentication */
+static void
+test_socks_5_authenticate(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /* SOCKS 5 Negotiate username/password authentication */
+ ADD_DATA(buf, "\x05\x01\x02");
+
+ test_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(SOCKS_USER_PASS, socks->reply[1]);
+ test_eq(5, socks->socks_version);
+
+ test_eq(0, buf_datalen(buf));
+
+ /* SOCKS 5 Send username/password */
+ ADD_DATA(buf, "\x01\x02me\x08mypasswd");
+ test_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+
+ test_eq(2, socks->usernamelen);
+ test_eq(8, socks->passwordlen);
+
+ test_memeq("me", socks->username, 2);
+ test_memeq("mypasswd", socks->password, 8);
+
+ done:
+ ;
+}
+
+/** Perform SOCKS 5 authentication and send data all in one go */
+static void
+test_socks_5_authenticate_with_data(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /* SOCKS 5 Negotiate username/password authentication */
+ ADD_DATA(buf, "\x05\x01\x02");
+
+ test_assert(!fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks));
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(SOCKS_USER_PASS, socks->reply[1]);
+ test_eq(5, socks->socks_version);
+
+ test_eq(0, buf_datalen(buf));
+
+ /* SOCKS 5 Send username/password */
+ /* SOCKS 5 Send CONNECT [01] to IP address 2.2.2.2:4369 */
+ ADD_DATA(buf, "\x01\x02me\x03you\x05\x01\x00\x01\x02\x02\x02\x02\x11\x11");
+ test_assert(fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks) == 1);
+ test_eq(5, socks->socks_version);
+ test_eq(2, socks->replylen);
+ test_eq(5, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+
+ test_streq("2.2.2.2", socks->address);
+ test_eq(4369, socks->port);
+
+ test_eq(2, socks->usernamelen);
+ test_eq(3, socks->passwordlen);
+ test_memeq("me", socks->username, 2);
+ test_memeq("you", socks->password, 3);
+
+ done:
+ ;
+}
+
+/** Perform SOCKS 5 authentication before method negotiated */
+static void
+test_socks_5_auth_before_negotiation(void *ptr)
+{
+ SOCKS_TEST_INIT();
+
+ /* SOCKS 5 Send username/password */
+ ADD_DATA(buf, "\x01\x02me\x02me");
+ test_assert(fetch_from_buf_socks(buf, socks,
+ get_options()->TestSocks,
+ get_options()->SafeSocks) == -1);
+ test_eq(0, socks->socks_version);
+ test_eq(0, socks->replylen);
+ test_eq(0, socks->reply[0]);
+ test_eq(0, socks->reply[1]);
+
+ done:
+ ;
+}
+
+static void
+test_buffer_copy(void *arg)
+{
+ generic_buffer_t *buf=NULL, *buf2=NULL;
+ const char *s;
+ size_t len;
+ char b[256];
+ int i;
+ (void)arg;
+
+ buf = generic_buffer_new();
+ tt_assert(buf);
+
+ /* Copy an empty buffer. */
+ tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
+ tt_assert(buf2);
+ tt_int_op(0, ==, generic_buffer_len(buf2));
+
+ /* Now try with a short buffer. */
+ s = "And now comes an act of enormous enormance!";
+ len = strlen(s);
+ generic_buffer_add(buf, s, len);
+ tt_int_op(len, ==, generic_buffer_len(buf));
+ /* Add junk to buf2 so we can test replacing.*/
+ generic_buffer_add(buf2, "BLARG", 5);
+ tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
+ tt_int_op(len, ==, generic_buffer_len(buf2));
+ generic_buffer_get(buf2, b, len);
+ test_mem_op(b, ==, s, len);
+ /* Now free buf2 and retry so we can test allocating */
+ generic_buffer_free(buf2);
+ buf2 = NULL;
+ tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
+ tt_int_op(len, ==, generic_buffer_len(buf2));
+ generic_buffer_get(buf2, b, len);
+ test_mem_op(b, ==, s, len);
+ /* Clear buf for next test */
+ generic_buffer_get(buf, b, len);
+ tt_int_op(generic_buffer_len(buf),==,0);
+
+ /* Okay, now let's try a bigger buffer. */
+ s = "Quis autem vel eum iure reprehenderit qui in ea voluptate velit "
+ "esse quam nihil molestiae consequatur, vel illum qui dolorem eum "
+ "fugiat quo voluptas nulla pariatur?";
+ len = strlen(s);
+ for (i = 0; i < 256; ++i) {
+ b[0]=i;
+ generic_buffer_add(buf, b, 1);
+ generic_buffer_add(buf, s, len);
+ }
+ tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf));
+ tt_int_op(generic_buffer_len(buf2), ==, generic_buffer_len(buf));
+ for (i = 0; i < 256; ++i) {
+ generic_buffer_get(buf2, b, len+1);
+ tt_int_op((unsigned char)b[0],==,i);
+ test_mem_op(b+1, ==, s, len);
+ }
+
+ done:
+ if (buf)
+ generic_buffer_free(buf);
+ if (buf2)
+ generic_buffer_free(buf2);
+}
+
/** Run unit tests for buffers.c */
static void
test_buffers(void)
@@ -455,7 +902,7 @@ test_circuit_timeout(void)
timeout1 = circuit_build_times_calculate_timeout(&estimate,
CBT_DEFAULT_QUANTILE_CUTOFF/100.0);
circuit_build_times_set_timeout(&estimate);
- log_notice(LD_CIRC, "Timeout1 is %lf, Xm is %d", timeout1, estimate.Xm);
+ log_notice(LD_CIRC, "Timeout1 is %f, Xm is %d", timeout1, estimate.Xm);
/* 2% error */
} while (fabs(circuit_build_times_cdf(&initial, timeout0) -
circuit_build_times_cdf(&initial, timeout1)) > 0.02);
@@ -470,7 +917,7 @@ test_circuit_timeout(void)
CBT_DEFAULT_QUANTILE_CUTOFF/100.0);
circuit_build_times_set_timeout(&final);
- log_notice(LD_CIRC, "Timeout2 is %lf, Xm is %d", timeout2, final.Xm);
+ log_notice(LD_CIRC, "Timeout2 is %f, Xm is %d", timeout2, final.Xm);
/* 5% here because some accuracy is lost due to histogram conversion */
test_assert(fabs(circuit_build_times_cdf(&initial, timeout0) -
@@ -566,6 +1013,7 @@ test_policy_summary_helper(const char *policy_str,
smartlist_t *policy = smartlist_create();
char *summary = NULL;
int r;
+ short_policy_t *short_policy = NULL;
line.key = (char*)"foo";
line.value = (char *)policy_str;
@@ -578,10 +1026,14 @@ test_policy_summary_helper(const char *policy_str,
test_assert(summary != NULL);
test_streq(summary, expected_summary);
+ short_policy = parse_short_policy(summary);
+ tt_assert(short_policy);
+
done:
tor_free(summary);
if (policy)
addr_policy_list_free(policy);
+ short_policy_free(short_policy);
}
/** Run unit tests for generating summary lines of exit policies */
@@ -611,12 +1063,15 @@ test_policies(void)
smartlist_add(policy, p);
+ tor_addr_from_ipv4h(&tar, 0x01020304u);
test_assert(ADDR_POLICY_ACCEPTED ==
- compare_addr_to_addr_policy(0x01020304u, 2, policy));
+ compare_tor_addr_to_addr_policy(&tar, 2, policy));
+ tor_addr_make_unspec(&tar);
test_assert(ADDR_POLICY_PROBABLY_ACCEPTED ==
- compare_addr_to_addr_policy(0, 2, policy));
+ compare_tor_addr_to_addr_policy(&tar, 2, policy));
+ tor_addr_from_ipv4h(&tar, 0xc0a80102);
test_assert(ADDR_POLICY_REJECTED ==
- compare_addr_to_addr_policy(0xc0a80102, 2, policy));
+ compare_tor_addr_to_addr_policy(&tar, 2, policy));
test_assert(0 == policies_parse_exit_policy(NULL, &policy2, 1, NULL, 1));
test_assert(policy2);
@@ -1026,8 +1481,73 @@ static void
test_geoip(void)
{
int i, j;
- time_t now = time(NULL);
+ time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
char *s = NULL;
+ const char *bridge_stats_1 =
+ "bridge-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "bridge-ips zz=24,xy=8\n",
+ *dirreq_stats_1 =
+ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "dirreq-v3-ips ab=8\n"
+ "dirreq-v2-ips \n"
+ "dirreq-v3-reqs ab=8\n"
+ "dirreq-v2-reqs \n"
+ "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0,"
+ "not-modified=0,busy=0\n"
+ "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0,"
+ "busy=0\n"
+ "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n",
+ *dirreq_stats_2 =
+ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "dirreq-v3-ips \n"
+ "dirreq-v2-ips \n"
+ "dirreq-v3-reqs \n"
+ "dirreq-v2-reqs \n"
+ "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0,"
+ "not-modified=0,busy=0\n"
+ "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0,"
+ "busy=0\n"
+ "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n",
+ *dirreq_stats_3 =
+ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "dirreq-v3-ips \n"
+ "dirreq-v2-ips \n"
+ "dirreq-v3-reqs \n"
+ "dirreq-v2-reqs \n"
+ "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0,"
+ "not-modified=0,busy=0\n"
+ "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0,"
+ "busy=0\n"
+ "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n",
+ *dirreq_stats_4 =
+ "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "dirreq-v3-ips \n"
+ "dirreq-v2-ips \n"
+ "dirreq-v3-reqs \n"
+ "dirreq-v2-reqs \n"
+ "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0,"
+ "not-modified=0,busy=0\n"
+ "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0,"
+ "busy=0\n"
+ "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n"
+ "dirreq-v3-tunneled-dl complete=0,timeout=0,running=4\n"
+ "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n",
+ *entry_stats_1 =
+ "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "entry-ips ab=8\n",
+ *entry_stats_2 =
+ "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "entry-ips \n";
/* Populate the DB a bit. Add these in order, since we can't do the final
* 'sort' step. These aren't very good IP addresses, but they're perfectly
@@ -1053,8 +1573,8 @@ test_geoip(void)
test_streq("??", NAMEFOR(2000));
#undef NAMEFOR
- get_options()->BridgeRelay = 1;
- get_options()->BridgeRecordUsageByCountry = 1;
+ get_options_mutable()->BridgeRelay = 1;
+ get_options_mutable()->BridgeRecordUsageByCountry = 1;
/* Put 9 observations in AB... */
for (i=32; i < 40; ++i)
geoip_note_client_seen(GEOIP_CLIENT_CONNECT, i, now-7200);
@@ -1077,6 +1597,114 @@ test_geoip(void)
test_assert(s);
test_streq("zz=24,xy=8", s);
+ /* Start testing bridge statistics by making sure that we don't output
+ * bridge stats without initializing them. */
+ s = geoip_format_bridge_stats(now + 86400);
+ test_assert(!s);
+
+ /* Initialize stats and generate the bridge-stats history string out of
+ * the connecting clients added above. */
+ geoip_bridge_stats_init(now);
+ s = geoip_format_bridge_stats(now + 86400);
+ test_streq(bridge_stats_1, s);
+ tor_free(s);
+
+ /* Stop collecting bridge stats and make sure we don't write a history
+ * string anymore. */
+ geoip_bridge_stats_term();
+ s = geoip_format_bridge_stats(now + 86400);
+ test_assert(!s);
+
+ /* Stop being a bridge and start being a directory mirror that gathers
+ * directory request statistics. */
+ geoip_bridge_stats_term();
+ get_options_mutable()->BridgeRelay = 0;
+ get_options_mutable()->BridgeRecordUsageByCountry = 0;
+ get_options_mutable()->DirReqStatistics = 1;
+
+ /* Start testing dirreq statistics by making sure that we don't collect
+ * dirreq stats without initializing them. */
+ geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, 100, now);
+ s = geoip_format_dirreq_stats(now + 86400);
+ test_assert(!s);
+
+ /* Initialize stats, note one connecting client, and generate the
+ * dirreq-stats history string. */
+ geoip_dirreq_stats_init(now);
+ geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, 100, now);
+ s = geoip_format_dirreq_stats(now + 86400);
+ test_streq(dirreq_stats_1, s);
+ tor_free(s);
+
+ /* Stop collecting stats, add another connecting client, and ensure we
+ * don't generate a history string. */
+ geoip_dirreq_stats_term();
+ geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, 101, now);
+ s = geoip_format_dirreq_stats(now + 86400);
+ test_assert(!s);
+
+ /* Re-start stats, add a connecting client, reset stats, and make sure
+ * that we get an all empty history string. */
+ geoip_dirreq_stats_init(now);
+ geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, 100, now);
+ geoip_reset_dirreq_stats(now);
+ s = geoip_format_dirreq_stats(now + 86400);
+ test_streq(dirreq_stats_2, s);
+ tor_free(s);
+
+ /* Note a successful network status response and make sure that it
+ * appears in the history string. */
+ geoip_note_ns_response(GEOIP_CLIENT_NETWORKSTATUS, GEOIP_SUCCESS);
+ s = geoip_format_dirreq_stats(now + 86400);
+ test_streq(dirreq_stats_3, s);
+ tor_free(s);
+
+ /* Start a tunneled directory request. */
+ geoip_start_dirreq((uint64_t) 1, 1024, GEOIP_CLIENT_NETWORKSTATUS,
+ DIRREQ_TUNNELED);
+ s = geoip_format_dirreq_stats(now + 86400);
+ test_streq(dirreq_stats_4, s);
+
+ /* Stop collecting directory request statistics and start gathering
+ * entry stats. */
+ geoip_dirreq_stats_term();
+ get_options_mutable()->DirReqStatistics = 0;
+ get_options_mutable()->EntryStatistics = 1;
+
+ /* Start testing entry statistics by making sure that we don't collect
+ * anything without initializing entry stats. */
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 100, now);
+ s = geoip_format_entry_stats(now + 86400);
+ test_assert(!s);
+
+ /* Initialize stats, note one connecting client, and generate the
+ * entry-stats history string. */
+ geoip_entry_stats_init(now);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 100, now);
+ s = geoip_format_entry_stats(now + 86400);
+ test_streq(entry_stats_1, s);
+ tor_free(s);
+
+ /* Stop collecting stats, add another connecting client, and ensure we
+ * don't generate a history string. */
+ geoip_entry_stats_term();
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 101, now);
+ s = geoip_format_entry_stats(now + 86400);
+ test_assert(!s);
+
+ /* Re-start stats, add a connecting client, reset stats, and make sure
+ * that we get an all empty history string. */
+ geoip_entry_stats_init(now);
+ geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 100, now);
+ geoip_reset_entry_stats(now);
+ s = geoip_format_entry_stats(now + 86400);
+ test_streq(entry_stats_2, s);
+ tor_free(s);
+
+ /* Stop collecting entry statistics. */
+ geoip_entry_stats_term();
+ get_options_mutable()->EntryStatistics = 0;
+
done:
tor_free(s);
}
@@ -1089,7 +1717,8 @@ test_stats(void)
char *s = NULL;
int i;
- /* We shouldn't collect exit stats without initializing them. */
+ /* Start with testing exit port statistics; we shouldn't collect exit
+ * stats without initializing them. */
rep_hist_note_exit_stream_opened(80);
rep_hist_note_exit_bytes(80, 100, 10000);
s = rep_hist_format_exit_stats(now + 86400);
@@ -1134,7 +1763,7 @@ test_stats(void)
test_assert(!s);
/* Re-start stats, add some bytes, reset stats, and see what history we
- * get when observing no streams or bytes at all. */
+ * get when observing no streams or bytes at all. */
rep_hist_exit_stats_init(now);
rep_hist_note_exit_stream_opened(80);
rep_hist_note_exit_bytes(80, 100, 10000);
@@ -1144,6 +1773,96 @@ test_stats(void)
"exit-kibibytes-written other=0\n"
"exit-kibibytes-read other=0\n"
"exit-streams-opened other=0\n", s);
+ tor_free(s);
+
+ /* Continue with testing connection statistics; we shouldn't collect
+ * conn stats without initializing them. */
+ rep_hist_note_or_conn_bytes(1, 20, 400, now);
+ s = rep_hist_format_conn_stats(now + 86400);
+ test_assert(!s);
+
+ /* Initialize stats, note bytes, and generate history string. */
+ rep_hist_conn_stats_init(now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
+ s = rep_hist_format_conn_stats(now + 86400);
+ test_streq("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n", s);
+ tor_free(s);
+
+ /* Stop collecting stats, add some bytes, and ensure we don't generate
+ * a history string. */
+ rep_hist_conn_stats_term();
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
+ s = rep_hist_format_conn_stats(now + 86400);
+ test_assert(!s);
+
+ /* Re-start stats, add some bytes, reset stats, and see what history we
+ * get when observing no bytes at all. */
+ rep_hist_conn_stats_init(now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now);
+ rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10);
+ rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15);
+ rep_hist_reset_conn_stats(now);
+ s = rep_hist_format_conn_stats(now + 86400);
+ test_streq("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n", s);
+ tor_free(s);
+
+ /* Continue with testing buffer statistics; we shouldn't collect buffer
+ * stats without initializing them. */
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ test_assert(!s);
+
+ /* Initialize stats, add statistics for a single circuit, and generate
+ * the history string. */
+ rep_hist_buffer_stats_init(now);
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ test_streq("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "cell-processed-cells 20,0,0,0,0,0,0,0,0,0\n"
+ "cell-queued-cells 2.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
+ "0.00,0.00\n"
+ "cell-time-in-queue 2,0,0,0,0,0,0,0,0,0\n"
+ "cell-circuits-per-decile 1\n", s);
+ tor_free(s);
+
+ /* Add nineteen more circuit statistics to the one that's already in the
+ * history to see that the math works correctly. */
+ for (i = 21; i < 30; i++)
+ rep_hist_add_buffer_stats(2.0, 2.0, i);
+ for (i = 20; i < 30; i++)
+ rep_hist_add_buffer_stats(3.5, 3.5, i);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ test_streq("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "cell-processed-cells 29,28,27,26,25,24,23,22,21,20\n"
+ "cell-queued-cells 2.75,2.75,2.75,2.75,2.75,2.75,2.75,2.75,"
+ "2.75,2.75\n"
+ "cell-time-in-queue 3,3,3,3,3,3,3,3,3,3\n"
+ "cell-circuits-per-decile 2\n", s);
+ tor_free(s);
+
+ /* Stop collecting stats, add statistics for one circuit, and ensure we
+ * don't generate a history string. */
+ rep_hist_buffer_stats_term();
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ test_assert(!s);
+
+ /* Re-start stats, add statistics for one circuit, reset stats, and make
+ * sure that the history has all zeros. */
+ rep_hist_buffer_stats_init(now);
+ rep_hist_add_buffer_stats(2.0, 2.0, 20);
+ rep_hist_reset_buffer_stats(now);
+ s = rep_hist_format_buffer_stats(now + 86400);
+ test_streq("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n"
+ "cell-processed-cells 0,0,0,0,0,0,0,0,0,0\n"
+ "cell-queued-cells 0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,"
+ "0.00,0.00\n"
+ "cell-time-in-queue 0,0,0,0,0,0,0,0,0,0\n"
+ "cell-circuits-per-decile 0\n", s);
done:
tor_free(s);
@@ -1186,6 +1905,7 @@ const struct testcase_setup_t legacy_setup = {
static struct testcase_t test_array[] = {
ENT(buffers),
+ { "buffer_copy", test_buffer_copy, 0, NULL, NULL },
ENT(onion_handshake),
ENT(circuit_timeout),
ENT(policies),
@@ -1198,19 +1918,41 @@ static struct testcase_t test_array[] = {
END_OF_TESTCASES
};
+#define SOCKSENT(name) \
+ { #name, test_socks_##name, TT_FORK, &socks_setup, NULL }
+
+static struct testcase_t socks_tests[] = {
+ SOCKSENT(4_unsupported_commands),
+ SOCKSENT(4_supported_commands),
+
+ SOCKSENT(5_unsupported_commands),
+ SOCKSENT(5_supported_commands),
+ SOCKSENT(5_no_authenticate),
+ SOCKSENT(5_auth_before_negotiation),
+ SOCKSENT(5_authenticate),
+ SOCKSENT(5_authenticate_with_data),
+
+ END_OF_TESTCASES
+};
+
extern struct testcase_t addr_tests[];
extern struct testcase_t crypto_tests[];
extern struct testcase_t container_tests[];
extern struct testcase_t util_tests[];
extern struct testcase_t dir_tests[];
+extern struct testcase_t microdesc_tests[];
+extern struct testcase_t pt_tests[];
static struct testgroup_t testgroups[] = {
{ "", test_array },
+ { "socks/", socks_tests },
{ "addr/", addr_tests },
{ "crypto/", crypto_tests },
{ "container/", container_tests },
{ "util/", util_tests },
{ "dir/", dir_tests },
+ { "dir/md/", microdesc_tests },
+ { "pt/", pt_tests },
END_OF_GROUPS
};
@@ -1259,7 +2001,10 @@ main(int c, const char **v)
}
options->command = CMD_RUN_UNITTESTS;
- crypto_global_init(0, NULL, NULL);
+ if (crypto_global_init(0, NULL, NULL)) {
+ printf("Can't initialize crypto subsystem; exiting.\n");
+ return 1;
+ }
rep_hist_init();
network_init();
setup_directory();
diff --git a/src/test/test.h b/src/test/test.h
index f7ae46ce6..a053a7ac4 100644
--- a/src/test/test.h
+++ b/src/test/test.h
@@ -45,7 +45,8 @@
_print = tor_malloc(printlen); \
base16_encode(_print, printlen, _value, \
(len)); }, \
- { tor_free(_print); } \
+ { tor_free(_print); }, \
+ TT_EXIT_TEST_FUNCTION \
);
#define test_memeq(expr1, expr2, len) test_mem_op((expr1), ==, (expr2), len)
diff --git a/src/test/test_addr.c b/src/test/test_addr.c
index 1dab0e011..ec0c50897 100644
--- a/src/test/test_addr.c
+++ b/src/test/test_addr.c
@@ -74,7 +74,9 @@ test_addr_basic(void)
cp += 2; \
if (i != 15) *cp++ = ':'; \
} \
- }, { tor_free(_print); } \
+ }, \
+ { tor_free(_print); }, \
+ TT_EXIT_TEST_FUNCTION \
); \
STMT_END
diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c
index 121af279c..dca0d3a28 100644
--- a/src/test/test_crypto.c
+++ b/src/test/test_crypto.c
@@ -630,7 +630,7 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 4095);
- tor_assert(encrypted_size > 0); /* This is obviously true, since 4111 is
+ tt_assert(encrypted_size > 0); /* This is obviously true, since 4111 is
* greater than 0, but its truth is not
* obvious to all analysis tools. */
cipher = crypto_create_init_cipher(key1, 0);
@@ -639,7 +639,7 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(decrypted_size, 4095);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain, decrypted1, 4095);
/* Encrypt a second time (with a new random initialization vector). */
cipher = crypto_create_init_cipher(key1, 1);
@@ -648,14 +648,14 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 4095);
- tor_assert(encrypted_size > 0);
+ tt_assert(encrypted_size > 0);
cipher = crypto_create_init_cipher(key1, 0);
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted2, 4095,
encrypted2, encrypted_size);
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(decrypted_size, 4095);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain, decrypted2, 4095);
test_memneq(encrypted1, encrypted2, encrypted_size);
/* Decrypt with the wrong key. */
@@ -680,14 +680,14 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 1);
- tor_assert(encrypted_size > 0);
+ tt_assert(encrypted_size > 0);
cipher = crypto_create_init_cipher(key1, 0);
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 1,
encrypted1, encrypted_size);
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(decrypted_size, 1);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain_1, decrypted1, 1);
/* Special length case: 15. */
cipher = crypto_create_init_cipher(key1, 1);
@@ -696,14 +696,14 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 15);
- tor_assert(encrypted_size > 0);
+ tt_assert(encrypted_size > 0);
cipher = crypto_create_init_cipher(key1, 0);
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 15,
encrypted1, encrypted_size);
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(decrypted_size, 15);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain_15, decrypted1, 15);
/* Special length case: 16. */
cipher = crypto_create_init_cipher(key1, 1);
@@ -712,14 +712,14 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 16);
- tor_assert(encrypted_size > 0);
+ tt_assert(encrypted_size > 0);
cipher = crypto_create_init_cipher(key1, 0);
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 16,
encrypted1, encrypted_size);
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(decrypted_size, 16);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain_16, decrypted1, 16);
/* Special length case: 17. */
cipher = crypto_create_init_cipher(key1, 1);
@@ -728,12 +728,12 @@ test_crypto_aes_iv(void)
crypto_free_cipher_env(cipher);
cipher = NULL;
test_eq(encrypted_size, 16 + 17);
- tor_assert(encrypted_size > 0);
+ tt_assert(encrypted_size > 0);
cipher = crypto_create_init_cipher(key1, 0);
decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 17,
encrypted1, encrypted_size);
test_eq(decrypted_size, 17);
- tor_assert(decrypted_size > 0);
+ tt_assert(decrypted_size > 0);
test_memeq(plain_17, decrypted1, 17);
done:
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 8a0fe9a67..205d7b577 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -302,7 +302,7 @@ test_dir_versions(void)
#define tt_versionstatus_op(vs1, op, vs2) \
tt_assert_test_type(vs1,vs2,#vs1" "#op" "#vs2,version_status_t, \
- (_val1 op _val2),"%d")
+ (_val1 op _val2),"%d",TT_EXIT_TEST_FUNCTION)
#define test_v_i_o(val, ver, lst) \
tt_versionstatus_op(val, ==, tor_version_is_obsolete(ver, lst))
@@ -807,7 +807,7 @@ test_dir_v3_networkstatus(void)
rs->or_port = 443;
rs->dir_port = 8000;
/* all flags but running cleared */
- rs->is_running = 1;
+ rs->is_flagged_running = 1;
smartlist_add(vote->routerstatus_list, vrs);
test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
@@ -822,7 +822,7 @@ test_dir_v3_networkstatus(void)
rs->addr = 0x99009901;
rs->or_port = 443;
rs->dir_port = 0;
- rs->is_exit = rs->is_stable = rs->is_fast = rs->is_running =
+ rs->is_exit = rs->is_stable = rs->is_fast = rs->is_flagged_running =
rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1;
smartlist_add(vote->routerstatus_list, vrs);
test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
@@ -839,7 +839,8 @@ test_dir_v3_networkstatus(void)
rs->or_port = 400;
rs->dir_port = 9999;
rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
- rs->is_running = rs->is_valid = rs->is_v2_dir = rs->is_possible_guard = 1;
+ rs->is_flagged_running = rs->is_valid = rs->is_v2_dir =
+ rs->is_possible_guard = 1;
smartlist_add(vote->routerstatus_list, vrs);
test_assert(router_add_to_routerlist(generate_ri_from_rs(vrs), &msg,0,0)>=0);
@@ -1079,7 +1080,8 @@ test_dir_v3_networkstatus(void)
test_assert(!rs->is_fast);
test_assert(!rs->is_possible_guard);
test_assert(!rs->is_stable);
- test_assert(rs->is_running); /* If it wasn't running it wouldn't be here */
+ /* (If it wasn't running it wouldn't be here) */
+ test_assert(rs->is_flagged_running);
test_assert(!rs->is_v2_dir);
test_assert(!rs->is_valid);
test_assert(!rs->is_named);
@@ -1101,7 +1103,7 @@ test_dir_v3_networkstatus(void)
test_assert(rs->is_fast);
test_assert(rs->is_possible_guard);
test_assert(rs->is_stable);
- test_assert(rs->is_running);
+ test_assert(rs->is_flagged_running);
test_assert(rs->is_v2_dir);
test_assert(rs->is_valid);
test_assert(!rs->is_named);
@@ -1171,10 +1173,10 @@ test_dir_v3_networkstatus(void)
/* Extract a detached signature from con3. */
detached_text1 = get_detached_sigs(con3, con_md3);
- tor_assert(detached_text1);
+ tt_assert(detached_text1);
/* Try to parse it. */
dsig1 = networkstatus_parse_detached_signatures(detached_text1, NULL);
- tor_assert(dsig1);
+ tt_assert(dsig1);
/* Are parsed values as expected? */
test_eq(dsig1->valid_after, con3->valid_after);
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
new file mode 100644
index 000000000..b807265c8
--- /dev/null
+++ b/src/test/test_microdesc.c
@@ -0,0 +1,233 @@
+/* Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "orconfig.h"
+#include "or.h"
+
+#include "config.h"
+#include "microdesc.h"
+
+#include "test.h"
+
+#ifdef MS_WINDOWS
+/* For mkdir() */
+#include <direct.h>
+#else
+#include <dirent.h>
+#endif
+
+static const char test_md1[] =
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMjlHH/daN43cSVRaHBwgUfnszzAhg98EvivJ9Qxfv51mvQUxPjQ07es\n"
+ "gV/3n8fyh3Kqr/ehi9jxkdgSRfSnmF7giaHL1SLZ29kA7KtST+pBvmTpDtHa3ykX\n"
+ "Xorc7hJvIyTZoc1HU+5XSynj3gsBE5IGK1ZRzrNS688LnuZMVp1tAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char test_md2[] =
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMIixIowh2DyPmDNMDwBX2DHcYcqdcH1zdIQJZkyV6c6rQHnvbcaDoSg\n"
+ "jgFSLJKpnGmh71FVRqep+yVB0zI1JY43kuEnXry2HbZCD9UDo3d3n7t015X5S7ON\n"
+ "bSSYtQGPwOr6Epf96IF6DoQxy4iDnPUAlejuhAG51s1y6/rZQ3zxAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n";
+
+static const char test_md3[] =
+ "@last-listed 2009-06-22\n"
+ "onion-key\n"
+ "-----BEGIN RSA PUBLIC KEY-----\n"
+ "MIGJAoGBAMH3340d4ENNGrqx7UxT+lB7x6DNUKOdPEOn4teceE11xlMyZ9TPv41c\n"
+ "qj2fRZzfxlc88G/tmiaHshmdtEpklZ740OFqaaJVj4LjPMKFNE+J7Xc1142BE9Ci\n"
+ "KgsbjGYe2RY261aADRWLetJ8T9QDMm+JngL4288hc8pq1uB/3TAbAgMBAAE=\n"
+ "-----END RSA PUBLIC KEY-----\n"
+ "p accept 1-700,800-1000\n"
+ "family nodeX nodeY nodeZ\n";
+
+static void
+test_md_cache(void *data)
+{
+ or_options_t *options = NULL;
+ microdesc_cache_t *mc = NULL ;
+ smartlist_t *added = NULL, *wanted = NULL;
+ microdesc_t *md1, *md2, *md3;
+ char d1[DIGEST256_LEN], d2[DIGEST256_LEN], d3[DIGEST256_LEN];
+ const char *test_md3_noannotation = strchr(test_md3, '\n')+1;
+ time_t time1, time2, time3;
+ char *fn = NULL, *s = NULL;
+ (void)data;
+
+ options = get_options_mutable();
+ tt_assert(options);
+
+ time1 = time(NULL);
+ time2 = time(NULL) - 2*24*60*60;
+ time3 = time(NULL) - 15*24*60*60;
+
+ /* Possibly, turn this into a test setup/cleanup pair */
+ tor_free(options->DataDirectory);
+ options->DataDirectory = tor_strdup(get_fname("md_datadir_test"));
+#ifdef MS_WINDOWS
+ tt_int_op(0, ==, mkdir(options->DataDirectory));
+#else
+ tt_int_op(0, ==, mkdir(options->DataDirectory, 0700));
+#endif
+
+ tt_assert(!strcmpstart(test_md3_noannotation, "onion-key"));
+
+ crypto_digest256(d1, test_md1, strlen(test_md1), DIGEST_SHA256);
+ crypto_digest256(d2, test_md2, strlen(test_md1), DIGEST_SHA256);
+ crypto_digest256(d3, test_md3_noannotation, strlen(test_md3_noannotation),
+ DIGEST_SHA256);
+
+ mc = get_microdesc_cache();
+
+ added = microdescs_add_to_cache(mc, test_md1, NULL, SAVED_NOWHERE, 0,
+ time1, NULL);
+ tt_int_op(1, ==, smartlist_len(added));
+ md1 = smartlist_get(added, 0);
+ smartlist_free(added);
+ added = NULL;
+
+ wanted = smartlist_create();
+ added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
+ time2, wanted);
+ /* Should fail, since we didn't list test_md2's digest in wanted */
+ tt_int_op(0, ==, smartlist_len(added));
+ smartlist_free(added);
+ added = NULL;
+
+ smartlist_add(wanted, tor_memdup(d2, DIGEST256_LEN));
+ smartlist_add(wanted, tor_memdup(d3, DIGEST256_LEN));
+ added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0,
+ time2, wanted);
+ /* Now it can work. md2 should have been added */
+ tt_int_op(1, ==, smartlist_len(added));
+ md2 = smartlist_get(added, 0);
+ /* And it should have gotten removed from 'wanted' */
+ tt_int_op(smartlist_len(wanted), ==, 1);
+ test_mem_op(smartlist_get(wanted, 0), ==, d3, DIGEST256_LEN);
+ smartlist_free(added);
+ added = NULL;
+
+ added = microdescs_add_to_cache(mc, test_md3, NULL,
+ SAVED_NOWHERE, 0, -1, NULL);
+ /* Must fail, since SAVED_NOWHERE precludes annotations */
+ tt_int_op(0, ==, smartlist_len(added));
+ smartlist_free(added);
+ added = NULL;
+
+ added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL,
+ SAVED_NOWHERE, 0, time3, NULL);
+ /* Now it can work */
+ tt_int_op(1, ==, smartlist_len(added));
+ md3 = smartlist_get(added, 0);
+ smartlist_free(added);
+ added = NULL;
+
+ /* Okay. We added 1...3. Let's poke them to see how they look, and make
+ * sure they're really in the journal. */
+ tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
+ tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
+ tt_ptr_op(md3, ==, microdesc_cache_lookup_by_digest256(mc, d3));
+
+ tt_int_op(md1->last_listed, ==, time1);
+ tt_int_op(md2->last_listed, ==, time2);
+ tt_int_op(md3->last_listed, ==, time3);
+
+ tt_int_op(md1->saved_location, ==, SAVED_IN_JOURNAL);
+ tt_int_op(md2->saved_location, ==, SAVED_IN_JOURNAL);
+ tt_int_op(md3->saved_location, ==, SAVED_IN_JOURNAL);
+
+ tt_int_op(md1->bodylen, ==, strlen(test_md1));
+ tt_int_op(md2->bodylen, ==, strlen(test_md2));
+ tt_int_op(md3->bodylen, ==, strlen(test_md3_noannotation));
+ test_mem_op(md1->body, ==, test_md1, strlen(test_md1));
+ test_mem_op(md2->body, ==, test_md2, strlen(test_md2));
+ test_mem_op(md3->body, ==, test_md3_noannotation,
+ strlen(test_md3_noannotation));
+
+ tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs.new",
+ options->DataDirectory);
+ s = read_file_to_str(fn, RFTS_BIN, NULL);
+ tt_assert(s);
+ test_mem_op(md1->body, ==, s + md1->off, md1->bodylen);
+ test_mem_op(md2->body, ==, s + md2->off, md2->bodylen);
+ test_mem_op(md3->body, ==, s + md3->off, md3->bodylen);
+
+ tt_ptr_op(md1->family, ==, NULL);
+ tt_ptr_op(md3->family, !=, NULL);
+ tt_int_op(smartlist_len(md3->family), ==, 3);
+ tt_str_op(smartlist_get(md3->family, 0), ==, "nodeX");
+
+ /* Now rebuild the cache! */
+ tt_int_op(microdesc_cache_rebuild(mc, 1), ==, 0);
+
+ tt_int_op(md1->saved_location, ==, SAVED_IN_CACHE);
+ tt_int_op(md2->saved_location, ==, SAVED_IN_CACHE);
+ tt_int_op(md3->saved_location, ==, SAVED_IN_CACHE);
+
+ /* The journal should be empty now */
+ tor_free(s);
+ s = read_file_to_str(fn, RFTS_BIN, NULL);
+ tt_str_op(s, ==, "");
+ tor_free(s);
+ tor_free(fn);
+
+ /* read the cache. */
+ tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs",
+ options->DataDirectory);
+ s = read_file_to_str(fn, RFTS_BIN, NULL);
+ test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
+ test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
+ test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
+
+ /* Okay, now we are going to forget about the cache entirely, and reload it
+ * from the disk. */
+ microdesc_free_all();
+ mc = get_microdesc_cache();
+ md1 = microdesc_cache_lookup_by_digest256(mc, d1);
+ md2 = microdesc_cache_lookup_by_digest256(mc, d2);
+ md3 = microdesc_cache_lookup_by_digest256(mc, d3);
+ test_assert(md1);
+ test_assert(md2);
+ test_assert(md3);
+ test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1));
+ test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2));
+ test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation));
+
+ tt_int_op(md1->last_listed, ==, time1);
+ tt_int_op(md2->last_listed, ==, time2);
+ tt_int_op(md3->last_listed, ==, time3);
+
+ /* Okay, now we are going to clear out everything older than a week old.
+ * In practice, that means md3 */
+ microdesc_cache_clean(mc, time(NULL)-7*24*60*60, 1/*force*/);
+ tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
+ tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
+ tt_ptr_op(NULL, ==, microdesc_cache_lookup_by_digest256(mc, d3));
+ md3 = NULL; /* it's history now! */
+
+ /* rebuild again, make sure it stays gone. */
+ microdesc_cache_rebuild(mc, 1);
+ tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1));
+ tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2));
+ tt_ptr_op(NULL, ==, microdesc_cache_lookup_by_digest256(mc, d3));
+
+ done:
+ if (options)
+ tor_free(options->DataDirectory);
+ microdesc_free_all();
+
+ smartlist_free(added);
+ if (wanted)
+ SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
+ smartlist_free(wanted);
+ tor_free(s);
+ tor_free(fn);
+}
+
+struct testcase_t microdesc_tests[] = {
+ { "cache", test_md_cache, TT_FORK, NULL, NULL },
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_pt.c b/src/test/test_pt.c
new file mode 100644
index 000000000..f97b21fa0
--- /dev/null
+++ b/src/test/test_pt.c
@@ -0,0 +1,147 @@
+/* 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 */
+
+#include "orconfig.h"
+#define PT_PRIVATE
+#include "or.h"
+#include "transports.h"
+#include "circuitbuild.h"
+#include "test.h"
+
+static void
+reset_mp(managed_proxy_t *mp)
+{
+ mp->conf_state = PT_PROTO_LAUNCHED;
+ SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t));
+ smartlist_clear(mp->transports);
+}
+
+static void
+test_pt_parsing(void)
+{
+ char line[200];
+
+ managed_proxy_t *mp = tor_malloc(sizeof(managed_proxy_t));
+ mp->conf_state = PT_PROTO_INFANT;
+ mp->transports = smartlist_create();
+
+ /* incomplete cmethod */
+ strcpy(line,"CMETHOD trebuchet");
+ test_assert(parse_cmethod_line(line, mp) < 0);
+
+ reset_mp(mp);
+
+ /* wrong proxy type */
+ strcpy(line,"CMETHOD trebuchet dog 127.0.0.1:1999");
+ test_assert(parse_cmethod_line(line, mp) < 0);
+
+ reset_mp(mp);
+
+ /* wrong addrport */
+ strcpy(line,"CMETHOD trebuchet socks4 abcd");
+ test_assert(parse_cmethod_line(line, mp) < 0);
+
+ reset_mp(mp);
+
+ /* correct line */
+ strcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999");
+ test_assert(parse_cmethod_line(line, mp) == 0);
+ test_assert(smartlist_len(mp->transports));
+
+ reset_mp(mp);
+
+ /* incomplete smethod */
+ strcpy(line,"SMETHOD trebuchet");
+ test_assert(parse_smethod_line(line, mp) < 0);
+
+ reset_mp(mp);
+
+ /* wrong addr type */
+ strcpy(line,"SMETHOD trebuchet abcd");
+ test_assert(parse_smethod_line(line, mp) < 0);
+
+ reset_mp(mp);
+
+ /* cowwect */
+ strcpy(line,"SMETHOD trebuchy 127.0.0.1:1999");
+ test_assert(parse_smethod_line(line, mp) == 0);
+
+ reset_mp(mp);
+
+ /* unsupported version */
+ strcpy(line,"VERSION 666");
+ test_assert(parse_version(line, mp) < 0);
+
+ /* incomplete VERSION */
+ strcpy(line,"VERSION ");
+ test_assert(parse_version(line, mp) < 0);
+
+ /* correct VERSION */
+ strcpy(line,"VERSION 1");
+ test_assert(parse_version(line, mp) == 0);
+
+ done:
+ tor_free(mp);
+}
+
+static void
+test_pt_protocol(void)
+{
+ char line[200];
+
+ managed_proxy_t *mp = tor_malloc(sizeof(managed_proxy_t));
+ mp->conf_state = PT_PROTO_LAUNCHED;
+ mp->transports = smartlist_create();
+
+ /* various wrong protocol runs: */
+
+ strcpy(line, "TEST TEST");
+ handle_proxy_line(line, mp);
+ test_assert(mp->conf_state == PT_PROTO_BROKEN);
+
+ reset_mp(mp);
+
+ strcpy(line,"VERSION 1");
+ handle_proxy_line(line, mp);
+ test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
+
+ strcpy(line,"VERSION 1");
+ handle_proxy_line(line, mp);
+ test_assert(mp->conf_state == PT_PROTO_BROKEN);
+
+ reset_mp(mp);
+
+ strcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999");
+ handle_proxy_line(line, mp);
+ test_assert(mp->conf_state == PT_PROTO_BROKEN);
+
+ reset_mp(mp);
+
+ /* correct protocol run: */
+ strcpy(line,"VERSION 1");
+ handle_proxy_line(line, mp);
+ test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
+
+ strcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999");
+ handle_proxy_line(line, mp);
+ test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS);
+
+ strcpy(line,"CMETHODS DONE");
+ handle_proxy_line(line, mp);
+ test_assert(mp->conf_state == PT_PROTO_CONFIGURED);
+
+ done:
+ tor_free(mp);
+}
+
+#define PT_LEGACY(name) \
+ { #name, legacy_test_helper, 0, &legacy_setup, test_pt_ ## name }
+
+struct testcase_t pt_tests[] = {
+ PT_LEGACY(parsing),
+ PT_LEGACY(protocol),
+ END_OF_TESTCASES
+};
+
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 23cd059cf..6603ab00d 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -6,6 +6,7 @@
#include "orconfig.h"
#define CONTROL_PRIVATE
#define MEMPOOL_PRIVATE
+#define UTIL_PRIVATE
#include "or.h"
#include "config.h"
#include "control.h"
@@ -375,7 +376,7 @@ test_util_strmisc(void)
/* Test memmem and memstr */
{
const char *haystack = "abcde";
- tor_assert(!tor_memmem(haystack, 5, "ef", 2));
+ tt_assert(!tor_memmem(haystack, 5, "ef", 2));
test_eq_ptr(tor_memmem(haystack, 5, "cd", 2), haystack + 2);
test_eq_ptr(tor_memmem(haystack, 5, "cde", 3), haystack + 2);
haystack = "ababcad";
@@ -639,26 +640,26 @@ test_util_gzip(void)
tor_strdup("String with low redundancy that won't be compressed much.");
test_assert(!tor_gzip_compress(&buf2, &len1, buf1, strlen(buf1)+1,
ZLIB_METHOD));
- tor_assert(len1>16);
+ tt_assert(len1>16);
/* when we allow an incomplete string, we should succeed.*/
- tor_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
+ tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
ZLIB_METHOD, 0, LOG_INFO));
buf3[len2]='\0';
- tor_assert(len2 > 5);
- tor_assert(!strcmpstart(buf1, buf3));
+ tt_assert(len2 > 5);
+ tt_assert(!strcmpstart(buf1, buf3));
/* when we demand a complete string, this must fail. */
tor_free(buf3);
- tor_assert(tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
+ tt_assert(tor_gzip_uncompress(&buf3, &len2, buf2, len1-16,
ZLIB_METHOD, 1, LOG_INFO));
- tor_assert(!buf3);
+ tt_assert(!buf3);
/* Now, try streaming compression. */
tor_free(buf1);
tor_free(buf2);
tor_free(buf3);
state = tor_zlib_new(1, ZLIB_METHOD);
- tor_assert(state);
+ tt_assert(state);
cp1 = buf1 = tor_malloc(1024);
len1 = 1024;
ccp2 = "ABCDEFGHIJABCDEFGHIJ";
@@ -675,7 +676,7 @@ test_util_gzip(void)
test_eq(len2, 0);
test_assert(cp1 > cp2); /* Make sure we really added something. */
- tor_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1,
+ tt_assert(!tor_gzip_uncompress(&buf3, &len2, buf1, 1024-len1,
ZLIB_METHOD, 1, LOG_WARN));
test_streq(buf3, "ABCDEFGHIJABCDEFGHIJ"); /*Make sure it compressed right.*/
@@ -832,6 +833,18 @@ test_util_sscanf(void)
test_eq(u2, 3u);
test_eq(u3, 99u);
+ /* %x should work. */
+ r = tor_sscanf("1234 02aBcdEf", "%x %x", &u1, &u2);
+ test_eq(r, 2);
+ test_eq(u1, 0x1234);
+ test_eq(u2, 0x2ABCDEF);
+ /* Width works on %x */
+ r = tor_sscanf("f00dcafe444", "%4x%4x%u", &u1, &u2, &u3);
+ test_eq(r, 3);
+ test_eq(u1, 0xf00d);
+ test_eq(u2, 0xcafe);
+ test_eq(u3, 444);
+
r = tor_sscanf("99% fresh", "%3u%% fresh", &u1); /* percents are scannable.*/
test_eq(r, 1);
test_eq(u1, 99);
@@ -1239,6 +1252,440 @@ test_util_load_win_lib(void *ptr)
#endif
static void
+clear_hex_errno(char *hex_errno)
+{
+ memset(hex_errno, '\0', HEX_ERRNO_SIZE + 1);
+}
+
+static void
+test_util_exit_status(void *ptr)
+{
+ /* Leave an extra byte for a \0 so we can do string comparison */
+ char hex_errno[HEX_ERRNO_SIZE + 1];
+
+ (void)ptr;
+
+ clear_hex_errno(hex_errno);
+ format_helper_exit_status(0, 0, hex_errno);
+ tt_str_op(hex_errno, ==, " 0/0\n");
+
+ clear_hex_errno(hex_errno);
+ format_helper_exit_status(0, 0x7FFFFFFF, hex_errno);
+ tt_str_op(hex_errno, ==, " 0/7FFFFFFF\n");
+
+ clear_hex_errno(hex_errno);
+ format_helper_exit_status(0xFF, -0x80000000, hex_errno);
+ tt_str_op(hex_errno, ==, "FF/-80000000\n");
+
+ clear_hex_errno(hex_errno);
+ format_helper_exit_status(0x7F, 0, hex_errno);
+ tt_str_op(hex_errno, ==, " 7F/0\n");
+
+ clear_hex_errno(hex_errno);
+ format_helper_exit_status(0x08, -0x242, hex_errno);
+ tt_str_op(hex_errno, ==, " 8/-242\n");
+
+ done:
+ ;
+}
+
+#ifndef MS_WINDOWS
+/** Check that fgets waits until a full line, and not return a partial line, on
+ * a EAGAIN with a non-blocking pipe */
+static void
+test_util_fgets_eagain(void *ptr)
+{
+ int test_pipe[2] = {-1, -1};
+ int retval;
+ ssize_t retlen;
+ char *retptr;
+ FILE *test_stream = NULL;
+ char buf[10];
+
+ (void)ptr;
+
+ /* Set up a pipe to test on */
+ retval = pipe(test_pipe);
+ tt_int_op(retval, >=, 0);
+
+ /* Set up the read-end to be non-blocking */
+ retval = fcntl(test_pipe[0], F_SETFL, O_NONBLOCK);
+ tt_int_op(retval, >=, 0);
+
+ /* Open it as a stdio stream */
+ test_stream = fdopen(test_pipe[0], "r");
+ tt_ptr_op(test_stream, !=, NULL);
+
+ /* Send in a partial line */
+ retlen = write(test_pipe[1], "A", 1);
+ tt_int_op(retlen, ==, 1);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_want(retptr == NULL);
+ tt_int_op(errno, ==, EAGAIN);
+
+ /* Send in the rest */
+ retlen = write(test_pipe[1], "B\n", 2);
+ tt_int_op(retlen, ==, 2);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, buf);
+ tt_str_op(buf, ==, "AB\n");
+
+ /* Send in a full line */
+ retlen = write(test_pipe[1], "CD\n", 3);
+ tt_int_op(retlen, ==, 3);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, buf);
+ tt_str_op(buf, ==, "CD\n");
+
+ /* Send in a partial line */
+ retlen = write(test_pipe[1], "E", 1);
+ tt_int_op(retlen, ==, 1);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, NULL);
+ tt_int_op(errno, ==, EAGAIN);
+
+ /* Send in the rest */
+ retlen = write(test_pipe[1], "F\n", 2);
+ tt_int_op(retlen, ==, 2);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, buf);
+ tt_str_op(buf, ==, "EF\n");
+
+ /* Send in a full line and close */
+ retlen = write(test_pipe[1], "GH", 2);
+ tt_int_op(retlen, ==, 2);
+ retval = close(test_pipe[1]);
+ test_pipe[1] = -1;
+ tt_int_op(retval, ==, 0);
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, buf);
+ tt_str_op(buf, ==, "GH");
+
+ /* Check for EOF */
+ retptr = fgets(buf, sizeof(buf), test_stream);
+ tt_ptr_op(retptr, ==, NULL);
+ tt_int_op(feof(test_stream), >, 0);
+
+ done:
+ if (test_stream != NULL)
+ fclose(test_stream);
+ if (test_pipe[0] != -1)
+ close(test_pipe[0]);
+ if (test_pipe[1] != -1)
+ close(test_pipe[1]);
+}
+#endif
+
+/** Helper function for testing tor_spawn_background */
+static void
+run_util_spawn_background(const char *argv[], const char *expected_out,
+ const char *expected_err, int expected_exit,
+ int expected_status)
+{
+ int retval, exit_code;
+ ssize_t pos;
+ process_handle_t process_handle;
+ char stdout_buf[100], stderr_buf[100];
+
+ /* Start the program */
+#ifdef MS_WINDOWS
+ tor_spawn_background(NULL, argv, NULL, &process_handle);
+#else
+ tor_spawn_background(argv[0], argv, NULL, &process_handle);
+#endif
+
+ tt_int_op(process_handle.status, ==, expected_status);
+
+ /* If the process failed to start, don't bother continuing */
+ if (process_handle.status == PROCESS_STATUS_ERROR)
+ return;
+
+ tt_int_op(process_handle.stdout_pipe, >, 0);
+ tt_int_op(process_handle.stderr_pipe, >, 0);
+
+ /* Check stdout */
+ pos = tor_read_all_from_process_stdout(&process_handle, stdout_buf,
+ sizeof(stdout_buf) - 1);
+ tt_assert(pos >= 0);
+ stdout_buf[pos] = '\0';
+ tt_str_op(stdout_buf, ==, expected_out);
+ tt_int_op(pos, ==, strlen(expected_out));
+
+ /* Check it terminated correctly */
+ retval = tor_get_exit_code(process_handle, 1, &exit_code);
+ tt_int_op(retval, ==, PROCESS_EXIT_EXITED);
+ tt_int_op(exit_code, ==, expected_exit);
+ // TODO: Make test-child exit with something other than 0
+
+ /* Check stderr */
+ pos = tor_read_all_from_process_stderr(&process_handle, stderr_buf,
+ sizeof(stderr_buf) - 1);
+ tt_assert(pos >= 0);
+ stderr_buf[pos] = '\0';
+ tt_str_op(stderr_buf, ==, expected_err);
+ tt_int_op(pos, ==, strlen(expected_err));
+
+ done:
+ ;
+}
+
+/** Check that we can launch a process and read the output */
+static void
+test_util_spawn_background_ok(void *ptr)
+{
+#ifdef MS_WINDOWS
+ const char *argv[] = {"test-child.exe", "--test", NULL};
+ const char *expected_out = "OUT\r\n--test\r\nSLEEPING\r\nDONE\r\n";
+ const char *expected_err = "ERR\r\n";
+#else
+ const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL};
+ const char *expected_out = "OUT\n--test\nSLEEPING\nDONE\n";
+ const char *expected_err = "ERR\n";
+#endif
+
+ (void)ptr;
+
+ run_util_spawn_background(argv, expected_out, expected_err, 0,
+ PROCESS_STATUS_RUNNING);
+}
+
+/** Check that failing to find the executable works as expected */
+static void
+test_util_spawn_background_fail(void *ptr)
+{
+#ifdef MS_WINDOWS
+ const char *argv[] = {BUILDDIR "/src/test/no-such-file", "--test", NULL};
+ const char *expected_out = "ERR: Failed to spawn background process "
+ "- code 9/2\n";
+ const char *expected_err = "";
+ const int expected_status = PROCESS_STATUS_ERROR;
+#else
+ const char *argv[] = {BUILDDIR "/src/test/no-such-file", "--test", NULL};
+ const char *expected_out = "ERR: Failed to spawn background process "
+ "- code 9/2\n";
+ const char *expected_err = "";
+ /* TODO: Once we can signal failure to exec, set this to be
+ * PROCESS_STATUS_ERROR */
+ const int expected_status = PROCESS_STATUS_RUNNING;
+#endif
+
+ (void)ptr;
+
+ run_util_spawn_background(argv, expected_out, expected_err, 255,
+ expected_status);
+}
+
+/** Test that reading from a handle returns a partial read rather than
+ * blocking */
+static void
+test_util_spawn_background_partial_read(void *ptr)
+{
+ const int expected_exit = 0;
+ const int expected_status = PROCESS_STATUS_RUNNING;
+
+ int retval, exit_code;
+ ssize_t pos = -1;
+ process_handle_t process_handle;
+ char stdout_buf[100], stderr_buf[100];
+#ifdef MS_WINDOWS
+ const char *argv[] = {"test-child.exe", "--test", NULL};
+ const char *expected_out[] = { "OUT\r\n--test\r\nSLEEPING\r\n",
+ "DONE\r\n",
+ NULL };
+ const char *expected_err = "ERR\r\n";
+#else
+ const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL};
+ const char *expected_out[] = { "OUT\n--test\nSLEEPING\n",
+ "DONE\n",
+ NULL };
+ const char *expected_err = "ERR\n";
+ int eof = 0;
+#endif
+ int expected_out_ctr;
+ (void)ptr;
+
+ /* Start the program */
+#ifdef MS_WINDOWS
+ tor_spawn_background(NULL, argv, NULL, &process_handle);
+#else
+ tor_spawn_background(argv[0], argv, NULL, &process_handle);
+#endif
+ tt_int_op(process_handle.status, ==, expected_status);
+
+ /* Check stdout */
+ for (expected_out_ctr =0; expected_out[expected_out_ctr] != NULL;) {
+#ifdef MS_WINDOWS
+ pos = tor_read_all_handle(process_handle.stdout_pipe, stdout_buf,
+ sizeof(stdout_buf) - 1, NULL);
+#else
+ /* Check that we didn't read the end of file last time */
+ tt_assert(!eof);
+ pos = tor_read_all_handle(process_handle.stdout_handle, stdout_buf,
+ sizeof(stdout_buf) - 1, NULL, &eof);
+#endif
+ log_info(LD_GENERAL, "tor_read_all_handle() returned %d", (int)pos);
+
+ /* We would have blocked, keep on trying */
+ if (0 == pos)
+ continue;
+
+ tt_int_op(pos, >, 0);
+ stdout_buf[pos] = '\0';
+ tt_str_op(stdout_buf, ==, expected_out[expected_out_ctr]);
+ tt_int_op(pos, ==, strlen(expected_out[expected_out_ctr]));
+ expected_out_ctr++;
+ }
+
+ /* The process should have exited without writing more */
+#ifdef MS_WINDOWS
+ pos = tor_read_all_handle(process_handle.stdout_pipe, stdout_buf,
+ sizeof(stdout_buf) - 1,
+ &process_handle);
+ tt_int_op(pos, ==, 0);
+#else
+ if (!eof) {
+ /* We should have got all the data, but maybe not the EOF flag */
+ pos = tor_read_all_handle(process_handle.stdout_handle, stdout_buf,
+ sizeof(stdout_buf) - 1,
+ &process_handle, &eof);
+ tt_int_op(pos, ==, 0);
+ tt_assert(eof);
+ }
+ /* Otherwise, we got the EOF on the last read */
+#endif
+
+ /* Check it terminated correctly */
+ retval = tor_get_exit_code(process_handle, 1, &exit_code);
+ tt_int_op(retval, ==, PROCESS_EXIT_EXITED);
+ tt_int_op(exit_code, ==, expected_exit);
+
+ // TODO: Make test-child exit with something other than 0
+
+ /* Check stderr */
+ pos = tor_read_all_from_process_stderr(&process_handle, stderr_buf,
+ sizeof(stderr_buf) - 1);
+ tt_assert(pos >= 0);
+ stderr_buf[pos] = '\0';
+ tt_str_op(stderr_buf, ==, expected_err);
+ tt_int_op(pos, ==, strlen(expected_err));
+
+ done:
+ ;
+}
+
+/**
+ * Test that we can properly format q Windows command line
+ */
+static void
+test_util_join_win_cmdline(void *ptr)
+{
+ /* Based on some test cases from "Parsing C++ Command-Line Arguments" in
+ * MSDN but we don't exercise all quoting rules because tor_join_win_cmdline
+ * will try to only generate simple cases for the child process to parse;
+ * i.e. we never embed quoted strings in arguments. */
+
+ const char *argvs[][4] = {
+ {"a", "bb", "CCC", NULL}, // Normal
+ {NULL, NULL, NULL, NULL}, // Empty argument list
+ {"", NULL, NULL, NULL}, // Empty argument
+ {"\"a", "b\"b", "CCC\"", NULL}, // Quotes
+ {"a\tbc", "dd dd", "E", NULL}, // Whitespace
+ {"a\\\\\\b", "de fg", "H", NULL}, // Backslashes
+ {"a\\\"b", "\\c", "D\\", NULL}, // Backslashes before quote
+ {"a\\\\b c", "d", "E", NULL}, // Backslashes not before quote
+ {} // Terminator
+ };
+
+ const char *cmdlines[] = {
+ "a bb CCC",
+ "",
+ "\"\"",
+ "\\\"a b\\\"b CCC\\\"",
+ "\"a\tbc\" \"dd dd\" E",
+ "a\\\\\\b \"de fg\" H",
+ "a\\\\\\\"b \\c D\\",
+ "\"a\\\\b c\" d E",
+ NULL // Terminator
+ };
+
+ int i;
+ char *joined_argv;
+
+ (void)ptr;
+
+ for (i=0; cmdlines[i]!=NULL; i++) {
+ log_info(LD_GENERAL, "Joining argvs[%d], expecting <%s>", i, cmdlines[i]);
+ joined_argv = tor_join_win_cmdline(argvs[i]);
+ tt_str_op(joined_argv, ==, cmdlines[i]);
+ tor_free(joined_argv);
+ }
+
+ done:
+ ;
+}
+
+#define MAX_SPLIT_LINE_COUNT 3
+struct split_lines_test_t {
+ const char *orig_line; // Line to be split (may contain \0's)
+ int orig_length; // Length of orig_line
+ const char *split_line[MAX_SPLIT_LINE_COUNT]; // Split lines
+};
+
+/**
+ * Test that we properly split a buffer into lines
+ */
+static void
+test_util_split_lines(void *ptr)
+{
+ /* Test cases. orig_line of last test case must be NULL.
+ * The last element of split_line[i] must be NULL. */
+ struct split_lines_test_t tests[] = {
+ {"", 0, {NULL}},
+ {"foo", 3, {"foo", NULL}},
+ {"\n\rfoo\n\rbar\r\n", 12, {"foo", "bar", NULL}},
+ {"fo o\r\nb\tar", 10, {"fo o", "b.ar", NULL}},
+ {"\x0f""f\0o\0\n\x01""b\0r\0\r", 12, {".f.o.", ".b.r.", NULL}},
+ {NULL, 0, {}}
+ };
+
+ int i, j;
+ char *orig_line;
+ smartlist_t *sl;
+
+ (void)ptr;
+
+ for (i=0; tests[i].orig_line; i++) {
+ sl = smartlist_create();
+ /* Allocate space for string and trailing NULL */
+ orig_line = tor_memdup(tests[i].orig_line, tests[i].orig_length + 1);
+ tor_split_lines(sl, orig_line, tests[i].orig_length);
+
+ j = 0;
+ log_info(LD_GENERAL, "Splitting test %d of length %d",
+ i, tests[i].orig_length);
+ SMARTLIST_FOREACH(sl, const char *, line,
+ {
+ /* Check we have not got too many lines */
+ tt_int_op(j, <, MAX_SPLIT_LINE_COUNT);
+ /* Check that there actually should be a line here */
+ tt_assert(tests[i].split_line[j] != NULL);
+ log_info(LD_GENERAL, "Line %d of test %d, should be <%s>",
+ j, i, tests[i].split_line[j]);
+ /* Check that the line is as expected */
+ tt_str_op(tests[i].split_line[j], ==, line);
+ j++;
+ });
+ /* Check that we didn't miss some lines */
+ tt_assert(tests[i].split_line[j] == NULL);
+ tor_free(orig_line);
+ smartlist_free(sl);
+ }
+
+ done:
+ ;
+}
+
+static void
test_util_di_ops(void)
{
#define LT -1
@@ -1319,6 +1766,15 @@ struct testcase_t util_tests[] = {
#ifdef MS_WINDOWS
UTIL_TEST(load_win_lib, 0),
#endif
+ UTIL_TEST(exit_status, 0),
+#ifndef MS_WINDOWS
+ UTIL_TEST(fgets_eagain, TT_SKIP),
+#endif
+ UTIL_TEST(spawn_background_ok, 0),
+ UTIL_TEST(spawn_background_fail, 0),
+ UTIL_TEST(spawn_background_partial_read, 0),
+ UTIL_TEST(join_win_cmdline, 0),
+ UTIL_TEST(split_lines, 0),
END_OF_TESTCASES
};
diff --git a/src/test/tinytest.c b/src/test/tinytest.c
index 11ffc2fe5..8caa4f545 100644
--- a/src/test/tinytest.c
+++ b/src/test/tinytest.c
@@ -28,7 +28,11 @@
#include <string.h>
#include <assert.h>
-#ifdef WIN32
+#ifdef TINYTEST_LOCAL
+#include "tinytest_local.h"
+#endif
+
+#ifdef _WIN32
#include <windows.h>
#else
#include <sys/types.h>
@@ -40,9 +44,6 @@
#define __attribute__(x)
#endif
-#ifdef TINYTEST_LOCAL
-#include "tinytest_local.h"
-#endif
#include "tinytest.h"
#include "tinytest_macros.h"
@@ -64,7 +65,7 @@ const char *cur_test_prefix = NULL; /**< prefix of the current test group */
/** Name of the current test, if we haven't logged is yet. Used for --quiet */
const char *cur_test_name = NULL;
-#ifdef WIN32
+#ifdef _WIN32
/** Pointer to argv[0] for win32. */
static const char *commandname = NULL;
#endif
@@ -103,7 +104,7 @@ static enum outcome
_testcase_run_forked(const struct testgroup_t *group,
const struct testcase_t *testcase)
{
-#ifdef WIN32
+#ifdef _WIN32
/* Fork? On Win32? How primitive! We'll do what the smart kids do:
we'll invoke our own exe (whose name we recall from the command
line) with a command line that tells it to run just the test we
@@ -174,6 +175,7 @@ _testcase_run_forked(const struct testgroup_t *group,
exit(1);
}
exit(0);
+ return FAIL; /* unreachable */
} else {
/* parent */
int status, r;
@@ -239,6 +241,7 @@ testcase_run_one(const struct testgroup_t *group,
if (opt_forked) {
exit(outcome==OK ? 0 : (outcome==SKIP?MAGIC_EXITCODE : 1));
+ return 1; /* unreachable */
} else {
return (int)outcome;
}
@@ -287,7 +290,7 @@ tinytest_main(int c, const char **v, struct testgroup_t *groups)
{
int i, j, n=0;
-#ifdef WIN32
+#ifdef _WIN32
commandname = v[0];
#endif
for (i=1; i<c; ++i) {
diff --git a/src/test/tinytest_demo.c b/src/test/tinytest_demo.c
index 4d2f58843..98cb773d1 100644
--- a/src/test/tinytest_demo.c
+++ b/src/test/tinytest_demo.c
@@ -1,4 +1,4 @@
-/* tinytest_demo.c -- Copyright 2009 Nick Mathewson
+/* tinytest_demo.c -- Copyright 2009-2010 Nick Mathewson
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -53,7 +53,7 @@ test_strcmp(void *data)
}
/* Pretty often, calling tt_abort_msg to indicate failure is more
- heavy-weight than you want. Instead, just say: */
+ heavy-weight than you want. Instead, just say: */
tt_assert(strcmp("testcase", "testcase") == 0);
/* Occasionally, you don't want to stop the current testcase just
@@ -91,7 +91,7 @@ test_strcmp(void *data)
/* First you declare a type to hold the environment info, and functions to
set it up and tear it down. */
struct data_buffer {
- /* We're just going to have couple of character buffer. Using
+ /* We're just going to have couple of character buffer. Using
setup/teardown functions is probably overkill for this case.
You could also do file descriptors, complicated handles, temporary
@@ -164,7 +164,7 @@ test_memcpy(void *ptr)
/* ============================================================ */
-/* Now we need to make sure that our tests get invoked. First, you take
+/* Now we need to make sure that our tests get invoked. First, you take
a bunch of related tests and put them into an array of struct testcase_t.
*/
@@ -189,15 +189,15 @@ struct testgroup_t groups[] = {
/* Every group has a 'prefix', and an array of tests. That's it. */
{ "demo/", demo_tests },
- END_OF_GROUPS
+ END_OF_GROUPS
};
int
main(int c, const char **v)
{
- /* Finally, just call tinytest_main(). It lets you specify verbose
- or quiet output with --verbose and --quiet. You can list
+ /* Finally, just call tinytest_main(). It lets you specify verbose
+ or quiet output with --verbose and --quiet. You can list
specific tests:
tinytest-demo demo/memcpy
diff --git a/src/test/tinytest_macros.h b/src/test/tinytest_macros.h
index a7fa64a82..032393ccf 100644
--- a/src/test/tinytest_macros.h
+++ b/src/test/tinytest_macros.h
@@ -90,10 +90,10 @@
TT_STMT_BEGIN \
if (!(b)) { \
_tinytest_set_test_failed(); \
- TT_GRIPE((msg)); \
+ TT_GRIPE(("%s",msg)); \
fail; \
} else { \
- TT_BLATHER((msg)); \
+ TT_BLATHER(("%s",msg)); \
} \
TT_STMT_END
@@ -111,7 +111,7 @@
#define tt_assert(b) tt_assert_msg((b), "assert("#b")")
#define tt_assert_test_fmt_type(a,b,str_test,type,test,printf_type,printf_fmt, \
- setup_block,cleanup_block) \
+ setup_block,cleanup_block,die_on_fail) \
TT_STMT_BEGIN \
type _val1 = (type)(a); \
type _val2 = (type)(b); \
@@ -135,33 +135,50 @@
cleanup_block; \
if (!_tt_status) { \
_tinytest_set_test_failed(); \
- TT_EXIT_TEST_FUNCTION; \
+ die_on_fail ; \
} \
} \
TT_STMT_END
-#define tt_assert_test_type(a,b,str_test,type,test,fmt) \
+#define tt_assert_test_type(a,b,str_test,type,test,fmt,die_on_fail) \
tt_assert_test_fmt_type(a,b,str_test,type,test,type,fmt, \
- {_print=_value;},{})
+ {_print=_value;},{},die_on_fail)
/* Helper: assert that a op b, when cast to type. Format the values with
* printf format fmt on failure. */
#define tt_assert_op_type(a,op,b,type,fmt) \
- tt_assert_test_type(a,b,#a" "#op" "#b,type,(_val1 op _val2),fmt)
+ tt_assert_test_type(a,b,#a" "#op" "#b,type,(_val1 op _val2),fmt, \
+ TT_EXIT_TEST_FUNCTION)
#define tt_int_op(a,op,b) \
- tt_assert_test_type(a,b,#a" "#op" "#b,long,(_val1 op _val2),"%ld")
+ tt_assert_test_type(a,b,#a" "#op" "#b,long,(_val1 op _val2), \
+ "%ld",TT_EXIT_TEST_FUNCTION)
#define tt_uint_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \
- (_val1 op _val2),"%lu")
+ (_val1 op _val2),"%lu",TT_EXIT_TEST_FUNCTION)
#define tt_ptr_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,void*, \
- (_val1 op _val2),"%p")
+ (_val1 op _val2),"%p",TT_EXIT_TEST_FUNCTION)
#define tt_str_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \
- (strcmp(_val1,_val2) op 0),"<%s>")
+ (strcmp(_val1,_val2) op 0),"<%s>",TT_EXIT_TEST_FUNCTION)
+
+#define tt_want_int_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,long,(_val1 op _val2),"%ld",(void)0)
+
+#define tt_want_uint_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,unsigned long, \
+ (_val1 op _val2),"%lu",(void)0)
+
+#define tt_want_ptr_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,void*, \
+ (_val1 op _val2),"%p",(void)0)
+
+#define tt_want_str_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \
+ (strcmp(_val1,_val2) op 0),"<%s>",(void)0)
#endif
diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am
index 1bb507684..a9a619757 100644
--- a/src/tools/Makefile.am
+++ b/src/tools/Makefile.am
@@ -2,17 +2,19 @@ bin_PROGRAMS = tor-resolve tor-gencert
noinst_PROGRAMS = tor-checkkey
tor_resolve_SOURCES = tor-resolve.c
-tor_resolve_LDFLAGS = @TOR_LDFLAGS_libevent@
-tor_resolve_LDADD = ../common/libor.a -lm @TOR_LIBEVENT_LIBS@ @TOR_LIB_WS32@
+tor_resolve_LDFLAGS =
+tor_resolve_LDADD = ../common/libor.a -lm @TOR_LIB_WS32@
tor_gencert_SOURCES = tor-gencert.c
-tor_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
- @TOR_LDFLAGS_libevent@
+tor_gencert_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
tor_gencert_LDADD = ../common/libor.a ../common/libor-crypto.a \
- -lm @TOR_ZLIB_LIBS@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+ -lm @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
tor_checkkey_SOURCES = tor-checkkey.c
-tor_checkkey_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \
- @TOR_LDFLAGS_libevent@
+tor_checkkey_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@
tor_checkkey_LDADD = ../common/libor.a ../common/libor-crypto.a \
- -lm @TOR_ZLIB_LIBS@ @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+ -lm @TOR_ZLIB_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+
+SUBDIRS = tor-fw-helper
+DIST_SUBDIRS = tor-fw-helper
+
diff --git a/src/tools/tor-fw-helper/Makefile.am b/src/tools/tor-fw-helper/Makefile.am
new file mode 100644
index 000000000..8f64ad2ba
--- /dev/null
+++ b/src/tools/tor-fw-helper/Makefile.am
@@ -0,0 +1,38 @@
+if USE_FW_HELPER
+bin_PROGRAMS = tor-fw-helper
+else
+bin_PROGRAMS =
+endif
+
+tor_fw_helper_SOURCES = \
+ tor-fw-helper.c \
+ tor-fw-helper-natpmp.c \
+ tor-fw-helper-upnp.c
+noinst_HEADERS = \
+ tor-fw-helper.h \
+ tor-fw-helper-natpmp.h \
+ tor-fw-helper-upnp.h
+
+if NAT_PMP
+nat_pmp_ldflags = @TOR_LDFLAGS_libnatpmp@
+nat_pmp_ldadd = -lnatpmp
+nat_pmp_cppflags = @TOR_CPPFLAGS_libnatpmp@
+else
+nat_pmp_ldflags =
+nat_pmp_ldadd =
+nat_pmp_cppflags =
+endif
+
+if MINIUPNPC
+miniupnpc_ldflags = @TOR_LDFLAGS_libminiupnpc@
+miniupnpc_ldadd = -lminiupnpc -lm @TOR_LIB_IPHLPAPI@
+miniupnpc_cppflags = @TOR_CPPFLAGS_libminiupnpc@
+else
+miniupnpc_ldflags =
+miniupnpc_ldadd =
+miniupnpc_cppflags =
+endif
+
+tor_fw_helper_LDFLAGS = $(nat_pmp_ldflags) $(miniupnpc_ldflags)
+tor_fw_helper_LDADD = ../../common/libor.a $(nat_pmp_ldadd) $(miniupnpc_ldadd) @TOR_LIB_WS32@
+tor_fw_helper_CPPFLAGS = $(nat_pmp_cppflags) $(miniupnpc_cppflags)
diff --git a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c
new file mode 100644
index 000000000..f9d5d0d58
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c
@@ -0,0 +1,233 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper-natpmp.c
+ * \brief The implementation of our NAT-PMP firewall helper.
+ **/
+
+#include "orconfig.h"
+#ifdef NAT_PMP
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+// debugging stuff
+#include <assert.h>
+
+#include "tor-fw-helper.h"
+#include "tor-fw-helper-natpmp.h"
+
+/** This hooks NAT-PMP into our multi-backend API. */
+static tor_fw_backend_t tor_natpmp_backend = {
+ "natpmp",
+ sizeof(struct natpmp_state_t),
+ tor_natpmp_init,
+ tor_natpmp_cleanup,
+ tor_natpmp_fetch_public_ip,
+ tor_natpmp_add_tcp_mapping
+};
+
+/** Return the backend for NAT-PMP. */
+const tor_fw_backend_t *
+tor_fw_get_natpmp_backend(void)
+{
+ return &tor_natpmp_backend;
+}
+
+/** Initialize the NAT-PMP backend and store the results in
+ * <b>backend_state</b>.*/
+int
+tor_natpmp_init(tor_fw_options_t *tor_fw_options, void *backend_state)
+{
+ natpmp_state_t *state = (natpmp_state_t *) backend_state;
+ int r = 0;
+
+ memset(&(state->natpmp), 0, sizeof(natpmp_t));
+ memset(&(state->response), 0, sizeof(natpmpresp_t));
+ state->init = 0;
+ state->protocol = NATPMP_PROTOCOL_TCP;
+ state->lease = NATPMP_DEFAULT_LEASE;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: natpmp init...\n");
+
+ r = initnatpmp(&(state->natpmp), 0, 0);
+ if (r == 0) {
+ state->init = 1;
+ fprintf(stdout, "tor-fw-helper: natpmp initialized...\n");
+ return r;
+ } else {
+ fprintf(stderr, "tor-fw-helper: natpmp failed to initialize...\n");
+ return r;
+ }
+}
+
+/** Tear down the NAT-PMP connection stored in <b>backend_state</b>.*/
+int
+tor_natpmp_cleanup(tor_fw_options_t *tor_fw_options, void *backend_state)
+{
+ natpmp_state_t *state = (natpmp_state_t *) backend_state;
+ int r = 0;
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: natpmp cleanup...\n");
+ r = closenatpmp(&(state->natpmp));
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: closing natpmp socket: %d\n", r);
+ return r;
+}
+
+/** Use select() to wait until we can read on fd. */
+static int
+wait_until_fd_readable(int fd, struct timeval *timeout)
+{
+ int r;
+ fd_set fds;
+ if (fd >= FD_SETSIZE) {
+ fprintf(stderr, "E: NAT-PMP FD_SETSIZE error %d\n", fd);
+ return -1;
+ }
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ r = select(fd+1, &fds, NULL, NULL, timeout);
+ if (r == -1) {
+ fprintf(stdout, "V: select failed in wait_until_fd_readable: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ /* XXXX we should really check to see whether fd was readable, or we timed
+ out. */
+ return 0;
+}
+
+/** Add a TCP port mapping for a single port stored in <b>tor_fw_options</b>
+ * using the <b>natpmp_t</b> stored in <b>backend_state</b>. */
+int
+tor_natpmp_add_tcp_mapping(tor_fw_options_t *tor_fw_options,
+ void *backend_state)
+{
+ natpmp_state_t *state = (natpmp_state_t *) backend_state;
+ int r = 0;
+ int x = 0;
+ int sav_errno;
+
+ struct timeval timeout;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: sending natpmp portmapping request...\n");
+ r = sendnewportmappingrequest(&(state->natpmp), state->protocol,
+ tor_fw_options->internal_port,
+ tor_fw_options->external_port,
+ state->lease);
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "tor-fw-helper: NAT-PMP sendnewportmappingrequest "
+ "returned %d (%s)\n", r, r==12?"SUCCESS":"FAILED");
+
+ do {
+ getnatpmprequesttimeout(&(state->natpmp), &timeout);
+ x = wait_until_fd_readable(state->natpmp.s, &timeout);
+ if (x == -1)
+ return -1;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: attempting to readnatpmpreponseorretry...\n");
+ r = readnatpmpresponseorretry(&(state->natpmp), &(state->response));
+ sav_errno = errno;
+
+ if (r<0 && r!=NATPMP_TRYAGAIN) {
+ fprintf(stderr, "E: readnatpmpresponseorretry failed %d\n", r);
+ fprintf(stderr, "E: errno=%d '%s'\n", sav_errno,
+ strerror(sav_errno));
+ }
+
+ } while (r == NATPMP_TRYAGAIN);
+
+ if (r != 0) {
+ /* XXX TODO: NATPMP_* should be formatted into useful error strings */
+ fprintf(stderr, "E: NAT-PMP It appears that something went wrong:"
+ " %d\n", r);
+ if (r == -51)
+ fprintf(stderr, "E: NAT-PMP It appears that the request was "
+ "unauthorized\n");
+ return r;
+ }
+
+ if (r == NATPMP_SUCCESS) {
+ fprintf(stdout, "tor-fw-helper: NAT-PMP mapped public port %hu to"
+ " localport %hu liftime %u\n",
+ (state->response).pnu.newportmapping.mappedpublicport,
+ (state->response).pnu.newportmapping.privateport,
+ (state->response).pnu.newportmapping.lifetime);
+ }
+
+ tor_fw_options->nat_pmp_status = 1;
+
+ return r;
+}
+
+/** Fetch our likely public IP from our upstream NAT-PMP enabled NAT device.
+ * Use the connection context stored in <b>backend_state</b>. */
+int
+tor_natpmp_fetch_public_ip(tor_fw_options_t *tor_fw_options,
+ void *backend_state)
+{
+ int r = 0;
+ int x = 0;
+ int sav_errno;
+ natpmp_state_t *state = (natpmp_state_t *) backend_state;
+
+ struct timeval timeout;
+
+ r = sendpublicaddressrequest(&(state->natpmp));
+ fprintf(stdout, "tor-fw-helper: NAT-PMP sendpublicaddressrequest returned"
+ " %d (%s)\n", r, r==2?"SUCCESS":"FAILED");
+
+ do {
+ getnatpmprequesttimeout(&(state->natpmp), &timeout);
+
+ x = wait_until_fd_readable(state->natpmp.s, &timeout);
+ if (x == -1)
+ return -1;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: NAT-PMP attempting to read reponse...\n");
+ r = readnatpmpresponseorretry(&(state->natpmp), &(state->response));
+ sav_errno = errno;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: NAT-PMP readnatpmpresponseorretry returned"
+ " %d\n", r);
+
+ if ( r < 0 && r != NATPMP_TRYAGAIN) {
+ fprintf(stderr, "E: NAT-PMP readnatpmpresponseorretry failed %d\n",
+ r);
+ fprintf(stderr, "E: NAT-PMP errno=%d '%s'\n", sav_errno,
+ strerror(sav_errno));
+ }
+
+ } while (r == NATPMP_TRYAGAIN );
+
+ if (r != 0) {
+ fprintf(stderr, "E: NAT-PMP It appears that something went wrong:"
+ " %d\n", r);
+ return r;
+ }
+
+ fprintf(stdout, "tor-fw-helper: ExternalIPAddress = %s\n",
+ inet_ntoa((state->response).pnu.publicaddress.addr));
+ tor_fw_options->public_ip_status = 1;
+
+ if (tor_fw_options->verbose) {
+ fprintf(stdout, "V: result = %u\n", r);
+ fprintf(stdout, "V: type = %u\n", (state->response).type);
+ fprintf(stdout, "V: resultcode = %u\n", (state->response).resultcode);
+ fprintf(stdout, "V: epoch = %u\n", (state->response).epoch);
+ }
+
+ return r;
+}
+#endif
+
diff --git a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h
new file mode 100644
index 000000000..0190379a2
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.h
@@ -0,0 +1,47 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper-natpmp.h
+ **/
+
+#ifdef NAT_PMP
+#ifndef _TOR_FW_HELPER_NATPMP_H
+#define _TOR_FW_HELPER_NATPMP_H
+
+#include <natpmp.h>
+
+/** This is the default NAT-PMP lease time in seconds. */
+#define NATPMP_DEFAULT_LEASE 3600
+/** NAT-PMP has many codes for success; this is one of them. */
+#define NATPMP_SUCCESS 0
+
+/** This is our NAT-PMP meta structure - it holds our request data, responses,
+ * various NAT-PMP parameters, and of course the status of the motion in the
+ * NAT-PMP ocean. */
+typedef struct natpmp_state_t {
+ natpmp_t natpmp;
+ natpmpresp_t response;
+ int fetch_public_ip;
+ int status;
+ int init; /**< Have we been initialized? */
+ int protocol; /**< This will only be TCP. */
+ int lease;
+} natpmp_state_t;
+
+const tor_fw_backend_t *tor_fw_get_natpmp_backend(void);
+
+int tor_natpmp_init(tor_fw_options_t *tor_fw_options, void *backend_state);
+
+int tor_natpmp_cleanup(tor_fw_options_t *tor_fw_options, void *backend_state);
+
+int tor_natpmp_add_tcp_mapping(tor_fw_options_t *tor_fw_options,
+ void *backend_state);
+
+int tor_natpmp_fetch_public_ip(tor_fw_options_t *tor_fw_options,
+ void *backend_state);
+
+#endif
+#endif
+
diff --git a/src/tools/tor-fw-helper/tor-fw-helper-upnp.c b/src/tools/tor-fw-helper/tor-fw-helper-upnp.c
new file mode 100644
index 000000000..c4b14a84e
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper-upnp.c
@@ -0,0 +1,189 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper-upnp.c
+ * \brief The implementation of our UPnP firewall helper.
+ **/
+
+#include "orconfig.h"
+#ifdef MINIUPNPC
+#ifdef MS_WINDOWS
+#define STATICLIB
+#endif
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <assert.h>
+
+#include "compat.h"
+#include "tor-fw-helper.h"
+#include "tor-fw-helper-upnp.h"
+
+/** UPnP timeout value. */
+#define UPNP_DISCOVER_TIMEOUT 2000
+/** Description of the port mapping in the UPnP table. */
+#define UPNP_DESC "Tor relay"
+
+/* XXX TODO: We should print these as a useful user string when we return the
+ * number to a user */
+/** Magic numbers as miniupnpc return codes. */
+#define UPNP_ERR_SUCCESS 0
+#define UPNP_ERR_NODEVICESFOUND 1
+#define UPNP_ERR_NOIGDFOUND 2
+#define UPNP_ERR_ADDPORTMAPPING 3
+#define UPNP_ERR_GETPORTMAPPING 4
+#define UPNP_ERR_DELPORTMAPPING 5
+#define UPNP_ERR_GETEXTERNALIP 6
+#define UPNP_ERR_INVAL 7
+#define UPNP_ERR_OTHER 8
+#define UPNP_SUCCESS 1
+
+/** This hooks miniupnpc into our multi-backend API. */
+static tor_fw_backend_t tor_miniupnp_backend = {
+ "miniupnp",
+ sizeof(struct miniupnpc_state_t),
+ tor_upnp_init,
+ tor_upnp_cleanup,
+ tor_upnp_fetch_public_ip,
+ tor_upnp_add_tcp_mapping
+};
+
+/** Return the backend for miniupnp. */
+const tor_fw_backend_t *
+tor_fw_get_miniupnp_backend(void)
+{
+ return &tor_miniupnp_backend;
+}
+
+/** Initialize the UPnP backend and store the results in
+ * <b>backend_state</b>.*/
+int
+tor_upnp_init(tor_fw_options_t *options, void *backend_state)
+{
+ /*
+ This leaks the user agent from the client to the router - perhaps we don't
+ want to do that? eg:
+
+ User-Agent: Ubuntu/10.04, UPnP/1.0, MiniUPnPc/1.4
+
+ */
+ miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state;
+ struct UPNPDev *devlist;
+ int r;
+
+ memset(&(state->urls), 0, sizeof(struct UPNPUrls));
+ memset(&(state->data), 0, sizeof(struct IGDdatas));
+ state->init = 0;
+
+ devlist = upnpDiscover(UPNP_DISCOVER_TIMEOUT, NULL, NULL, 0);
+ if (NULL == devlist) {
+ fprintf(stderr, "E: upnpDiscover returned: NULL\n");
+ return UPNP_ERR_NODEVICESFOUND;
+ }
+
+ assert(options);
+ r = UPNP_GetValidIGD(devlist, &(state->urls), &(state->data),
+ state->lanaddr, UPNP_LANADDR_SZ);
+ fprintf(stdout, "tor-fw-helper: UPnP GetValidIGD returned: %d (%s)\n", r,
+ r==UPNP_SUCCESS?"SUCCESS":"FAILED");
+
+ freeUPNPDevlist(devlist);
+
+ if (r != 1 && r != 2)
+ return UPNP_ERR_NOIGDFOUND;
+
+ state->init = 1;
+ return UPNP_ERR_SUCCESS;
+}
+
+/** Tear down the UPnP connection stored in <b>backend_state</b>.*/
+int
+tor_upnp_cleanup(tor_fw_options_t *options, void *backend_state)
+{
+
+ miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state;
+ assert(options);
+
+ if (state->init)
+ FreeUPNPUrls(&(state->urls));
+ state->init = 0;
+
+ return UPNP_ERR_SUCCESS;
+}
+
+/** Fetch our likely public IP from our upstream UPnP IGD enabled NAT device.
+ * Use the connection context stored in <b>backend_state</b>. */
+int
+tor_upnp_fetch_public_ip(tor_fw_options_t *options, void *backend_state)
+{
+ miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state;
+ int r;
+ char externalIPAddress[16];
+
+ if (!state->init) {
+ r = tor_upnp_init(options, state);
+ if (r != UPNP_ERR_SUCCESS)
+ return r;
+ }
+
+ r = UPNP_GetExternalIPAddress(state->urls.controlURL,
+ state->data.first.servicetype,
+ externalIPAddress);
+
+ if (r != UPNPCOMMAND_SUCCESS)
+ goto err;
+
+ if (externalIPAddress[0]) {
+ fprintf(stdout, "tor-fw-helper: ExternalIPAddress = %s\n",
+ externalIPAddress); tor_upnp_cleanup(options, state);
+ options->public_ip_status = 1;
+ return UPNP_ERR_SUCCESS;
+ } else {
+ goto err;
+ }
+
+ err:
+ tor_upnp_cleanup(options, state);
+ return UPNP_ERR_GETEXTERNALIP;
+}
+
+/** Add a TCP port mapping for a single port stored in <b>tor_fw_options</b>
+ * and store the results in <b>backend_state</b>. */
+int
+tor_upnp_add_tcp_mapping(tor_fw_options_t *options, void *backend_state)
+{
+ miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state;
+ int r;
+ char internal_port_str[6];
+ char external_port_str[6];
+
+ if (!state->init) {
+ r = tor_upnp_init(options, state);
+ if (r != UPNP_ERR_SUCCESS)
+ return r;
+ }
+
+ if (options->verbose)
+ fprintf(stdout, "V: internal port: %d, external port: %d\n",
+ (int)options->internal_port, (int)options->external_port);
+
+ tor_snprintf(internal_port_str, sizeof(internal_port_str),
+ "%d", (int)options->internal_port);
+ tor_snprintf(external_port_str, sizeof(external_port_str),
+ "%d", (int)options->external_port);
+
+ r = UPNP_AddPortMapping(state->urls.controlURL,
+ state->data.first.servicetype,
+ external_port_str, internal_port_str,
+ state->lanaddr, UPNP_DESC, "TCP", 0);
+ if (r != UPNPCOMMAND_SUCCESS)
+ return UPNP_ERR_ADDPORTMAPPING;
+
+ options->upnp_status = 1;
+ return UPNP_ERR_SUCCESS;
+}
+#endif
+
diff --git a/src/tools/tor-fw-helper/tor-fw-helper-upnp.h b/src/tools/tor-fw-helper/tor-fw-helper-upnp.h
new file mode 100644
index 000000000..021a8e0aa
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper-upnp.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper-upnp.h
+ * \brief The main header for our firewall helper.
+ **/
+
+#ifdef MINIUPNPC
+#ifndef _TOR_FW_HELPER_UPNP_H
+#define _TOR_FW_HELPER_UPNP_H
+
+#include <miniupnpc/miniwget.h>
+#include <miniupnpc/miniupnpc.h>
+#include <miniupnpc/upnpcommands.h>
+#include <miniupnpc/upnperrors.h>
+
+/** This is a magic number for miniupnpc lan address size. */
+#define UPNP_LANADDR_SZ 64
+
+/** This is our miniupnpc meta structure - it holds our request data,
+ * responses, and various miniupnpc parameters. */
+typedef struct miniupnpc_state_t {
+ struct UPNPUrls urls;
+ struct IGDdatas data;
+ char lanaddr[UPNP_LANADDR_SZ];
+ int init;
+} miniupnpc_state_t;
+
+const tor_fw_backend_t *tor_fw_get_miniupnp_backend(void);
+
+int tor_upnp_init(tor_fw_options_t *options, void *backend_state);
+
+int tor_upnp_cleanup(tor_fw_options_t *options, void *backend_state);
+
+int tor_upnp_fetch_public_ip(tor_fw_options_t *options, void *backend_state);
+
+int tor_upnp_add_tcp_mapping(tor_fw_options_t *options, void *backend_state);
+
+#endif
+#endif
+
diff --git a/src/tools/tor-fw-helper/tor-fw-helper.c b/src/tools/tor-fw-helper/tor-fw-helper.c
new file mode 100644
index 000000000..002239745
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper.c
@@ -0,0 +1,396 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper.c
+ * \brief The main wrapper around our firewall helper logic.
+ **/
+
+/*
+ * tor-fw-helper is a tool for opening firewalls with NAT-PMP and UPnP; this
+ * tool is designed to be called by hand or by Tor by way of a exec() at a
+ * later date.
+ */
+
+#include "orconfig.h"
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <time.h>
+#include <string.h>
+
+#ifdef MS_WINDOWS
+#include <winsock2.h>
+#endif
+
+#include "tor-fw-helper.h"
+#ifdef NAT_PMP
+#include "tor-fw-helper-natpmp.h"
+#endif
+#ifdef MINIUPNPC
+#include "tor-fw-helper-upnp.h"
+#endif
+
+/** This is our meta storage type - it holds information about each helper
+ including the total number of helper backends, function pointers, and helper
+ state. */
+typedef struct backends_t {
+ /** The total number of backends */
+ int n_backends;
+ /** The backend functions as an array */
+ tor_fw_backend_t backend_ops[MAX_BACKENDS];
+ /** The internal backend state */
+ void *backend_state[MAX_BACKENDS];
+} backends_t;
+
+/** Initalize each backend helper with the user input stored in <b>options</b>
+ * and put the results in the <b>backends</b> struct. */
+static int
+init_backends(tor_fw_options_t *options, backends_t *backends)
+{
+ int n_available = 0;
+ int i, r, n;
+ tor_fw_backend_t *backend_ops_list[MAX_BACKENDS];
+ void *data = NULL;
+ /* First, build a list of the working backends. */
+ n = 0;
+#ifdef MINIUPNPC
+ backend_ops_list[n++] = (tor_fw_backend_t *) tor_fw_get_miniupnp_backend();
+#endif
+#ifdef NAT_PMP
+ backend_ops_list[n++] = (tor_fw_backend_t *) tor_fw_get_natpmp_backend();
+#endif
+ n_available = n;
+
+ /* Now, for each backend that might work, try to initialize it.
+ * That's how we roll, initialized.
+ */
+ n = 0;
+ for (i=0; i<n_available; ++i) {
+ data = calloc(1, backend_ops_list[i]->state_len);
+ if (!data) {
+ perror("calloc");
+ exit(1);
+ }
+ r = backend_ops_list[i]->init(options, data);
+ if (r == 0) {
+ backends->backend_ops[n] = *backend_ops_list[i];
+ backends->backend_state[n] = data;
+ n++;
+ } else {
+ free(data);
+ }
+ }
+ backends->n_backends = n;
+
+ return n;
+}
+
+/** Return the proper commandline switches when the user needs information. */
+static void
+usage(void)
+{
+ fprintf(stderr, "tor-fw-helper usage:\n"
+ " [-h|--help]\n"
+ " [-T|--Test]\n"
+ " [-v|--verbose]\n"
+ " [-g|--fetch-public-ip]\n"
+ " -i|--internal-or-port [TCP port]\n"
+ " [-e|--external-or-port [TCP port]]\n"
+ " [-d|--internal-dir-port [TCP port]\n"
+ " [-p|--external-dir-port [TCP port]]]\n");
+}
+
+/** Log commandline options to a hardcoded file <b>tor-fw-helper.log</b> in the
+ * current working directory. */
+static int
+log_commandline_options(int argc, char **argv)
+{
+ int i, retval;
+ FILE *logfile;
+ time_t now;
+
+ /* Open the log file */
+ logfile = fopen("tor-fw-helper.log", "a");
+ if (NULL == logfile)
+ return -1;
+
+ /* Send all commandline arguments to the file */
+ now = time(NULL);
+ retval = fprintf(logfile, "START: %s\n", ctime(&now));
+ for (i = 0; i < argc; i++) {
+ retval = fprintf(logfile, "ARG: %d: %s\n", i, argv[i]);
+ if (retval < 0)
+ goto error;
+
+ retval = fprintf(stdout, "ARG: %d: %s\n", i, argv[i]);
+ if (retval < 0)
+ goto error;
+ }
+ now = time(NULL);
+ retval = fprintf(logfile, "END: %s\n", ctime(&now));
+
+ /* Close and clean up */
+ retval = fclose(logfile);
+ return retval;
+
+ /* If there was an error during writing */
+ error:
+ fclose(logfile);
+ return -1;
+}
+
+/** Iterate over over each of the supported <b>backends</b> and attempt to
+ * fetch the public ip. */
+static void
+tor_fw_fetch_public_ip(tor_fw_options_t *tor_fw_options,
+ backends_t *backends)
+{
+ int i;
+ int r = 0;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: tor_fw_fetch_public_ip\n");
+
+ for (i=0; i<backends->n_backends; ++i) {
+ if (tor_fw_options->verbose) {
+ fprintf(stdout, "V: running backend_state now: %i\n", i);
+ fprintf(stdout, "V: size of backend state: %u\n",
+ (int)(backends->backend_ops)[i].state_len);
+ fprintf(stdout, "V: backend state name: %s\n",
+ (char *)(backends->backend_ops)[i].name);
+ }
+ r = backends->backend_ops[i].fetch_public_ip(tor_fw_options,
+ backends->backend_state[i]);
+ fprintf(stdout, "tor-fw-helper: tor_fw_fetch_public_ip backend %s "
+ " returned: %i\n", (char *)(backends->backend_ops)[i].name, r);
+ }
+}
+
+/** Iterate over each of the supported <b>backends</b> and attempt to add a
+ * port forward for the OR port stored in <b>tor_fw_options</b>. */
+static void
+tor_fw_add_or_port(tor_fw_options_t *tor_fw_options,
+ backends_t *backends)
+{
+ int i;
+ int r = 0;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: tor_fw_add_or_port\n");
+
+ for (i=0; i<backends->n_backends; ++i) {
+ if (tor_fw_options->verbose) {
+ fprintf(stdout, "V: running backend_state now: %i\n", i);
+ fprintf(stdout, "V: size of backend state: %u\n",
+ (int)(backends->backend_ops)[i].state_len);
+ fprintf(stdout, "V: backend state name: %s\n",
+ (const char *) backends->backend_ops[i].name);
+ }
+ r = backends->backend_ops[i].add_tcp_mapping(tor_fw_options,
+ backends->backend_state[i]);
+ fprintf(stdout, "tor-fw-helper: tor_fw_add_or_port backend %s "
+ "returned: %i\n", (const char *) backends->backend_ops[i].name, r);
+ }
+}
+
+/** Iterate over each of the supported <b>backends</b> and attempt to add a
+ * port forward for the Dir port stored in <b>tor_fw_options</b>. */
+static void
+tor_fw_add_dir_port(tor_fw_options_t *tor_fw_options,
+ backends_t *backends)
+{
+ int i;
+ int r = 0;
+
+ if (tor_fw_options->verbose)
+ fprintf(stdout, "V: tor_fw_add_dir_port\n");
+
+ for (i=0; i<backends->n_backends; ++i) {
+ if (tor_fw_options->verbose) {
+ fprintf(stdout, "V: running backend_state now: %i\n", i);
+ fprintf(stdout, "V: size of backend state: %u\n",
+ (int)(backends->backend_ops)[i].state_len);
+ fprintf(stdout, "V: backend state name: %s\n",
+ (char *)(backends->backend_ops)[i].name);
+ }
+ r = backends->backend_ops[i].add_tcp_mapping(tor_fw_options,
+ backends->backend_state[i]);
+ fprintf(stdout, "tor-fw-helper: tor_fw_add_dir_port backend %s "
+ "returned: %i\n", (const char *)backends->backend_ops[i].name, r);
+ }
+}
+
+/** Called before we make any calls to network-related functions.
+ * (Some operating systems require their network libraries to be
+ * initialized.) (from common/compat.c) */
+static int
+network_init(void)
+{
+#ifdef MS_WINDOWS
+ /* This silly exercise is necessary before windows will allow
+ * gethostbyname to work. */
+ WSADATA WSAData;
+ int r;
+ r = WSAStartup(0x101, &WSAData);
+ if (r) {
+ fprintf(stderr, "E: Error initializing Windows network layer "
+ "- code was %d", r);
+ return -1;
+ }
+ /* WSAData.iMaxSockets might show the max sockets we're allowed to use.
+ * We might use it to complain if we're trying to be a server but have
+ * too few sockets available. */
+#endif
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ int r = 0;
+ int c = 0;
+
+ tor_fw_options_t tor_fw_options;
+ backends_t backend_state;
+
+ memset(&tor_fw_options, 0, sizeof(tor_fw_options));
+ memset(&backend_state, 0, sizeof(backend_state));
+
+ while (1) {
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"verbose", 0, 0, 'v'},
+ {"help", 0, 0, 'h'},
+ {"internal-or-port", 1, 0, 'i'},
+ {"external-or-port", 1, 0, 'e'},
+ {"internal-dir-port", 1, 0, 'd'},
+ {"external-dir-port", 1, 0, 'p'},
+ {"fetch-public-ip", 0, 0, 'g'},
+ {"test-commandline", 0, 0, 'T'},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long(argc, argv, "vhi:e:d:p:gT",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'v': tor_fw_options.verbose = 1; break;
+ case 'h': tor_fw_options.help = 1; usage(); exit(1); break;
+ case 'i': sscanf(optarg, "%hu", &tor_fw_options.private_or_port);
+ break;
+ case 'e': sscanf(optarg, "%hu", &tor_fw_options.public_or_port);
+ break;
+ case 'd': sscanf(optarg, "%hu", &tor_fw_options.private_dir_port);
+ break;
+ case 'p': sscanf(optarg, "%hu", &tor_fw_options.public_dir_port);
+ break;
+ case 'g': tor_fw_options.fetch_public_ip = 1; break;
+ case 'T': tor_fw_options.test_commandline = 1; break;
+ case '?': break;
+ default : fprintf(stderr, "Unknown option!\n"); usage(); exit(1);
+ }
+ }
+
+ if (tor_fw_options.verbose) {
+ fprintf(stderr, "V: tor-fw-helper version %s\n"
+ "V: We were called with the following arguments:\n"
+ "V: verbose = %d, help = %d, pub or port = %u, "
+ "priv or port = %u\n"
+ "V: pub dir port = %u, priv dir port = %u\n"
+ "V: fetch_public_ip = %u\n",
+ tor_fw_version, tor_fw_options.verbose, tor_fw_options.help,
+ tor_fw_options.private_or_port, tor_fw_options.public_or_port,
+ tor_fw_options.private_dir_port, tor_fw_options.public_dir_port,
+ tor_fw_options.fetch_public_ip);
+ }
+
+ if (tor_fw_options.test_commandline) {
+ return log_commandline_options(argc, argv);
+ }
+
+ /* At the very least, we require an ORPort;
+ Given a private ORPort, we can ask for a mapping that matches the port
+ externally.
+ */
+ if (!tor_fw_options.private_or_port && !tor_fw_options.fetch_public_ip) {
+ fprintf(stderr, "E: We require an ORPort or fetch_public_ip"
+ " request!\n");
+ usage();
+ exit(1);
+ } else {
+ /* When we only have one ORPort, internal/external are
+ set to be the same.*/
+ if (!tor_fw_options.public_or_port && tor_fw_options.private_or_port) {
+ if (tor_fw_options.verbose)
+ fprintf(stdout, "V: We're setting public_or_port = "
+ "private_or_port.\n");
+ tor_fw_options.public_or_port = tor_fw_options.private_or_port;
+ }
+ }
+ if (!tor_fw_options.private_dir_port) {
+ if (tor_fw_options.verbose)
+ fprintf(stdout, "V: We have no DirPort; no hole punching for "
+ "DirPorts\n");
+
+ } else {
+ /* When we only have one DirPort, internal/external are
+ set to be the same.*/
+ if (!tor_fw_options.public_dir_port && tor_fw_options.private_dir_port) {
+ if (tor_fw_options.verbose)
+ fprintf(stdout, "V: We're setting public_or_port = "
+ "private_or_port.\n");
+
+ tor_fw_options.public_dir_port = tor_fw_options.private_dir_port;
+ }
+ }
+
+ if (tor_fw_options.verbose) {
+ fprintf(stdout, "V: pub or port = %u, priv or port = %u\n"
+ "V: pub dir port = %u, priv dir port = %u\n",
+ tor_fw_options.private_or_port, tor_fw_options.public_or_port,
+ tor_fw_options.private_dir_port,
+ tor_fw_options.public_dir_port);
+ }
+
+ // Initialize networking
+ if (network_init())
+ exit(1);
+
+ // Initalize the various fw-helper backend helpers
+ r = init_backends(&tor_fw_options, &backend_state);
+ if (r)
+ printf("tor-fw-helper: %i NAT traversal helper(s) loaded\n", r);
+
+ if (tor_fw_options.fetch_public_ip) {
+ tor_fw_fetch_public_ip(&tor_fw_options, &backend_state);
+ }
+
+ if (tor_fw_options.private_or_port) {
+ tor_fw_options.internal_port = tor_fw_options.private_or_port;
+ tor_fw_options.external_port = tor_fw_options.private_or_port;
+ tor_fw_add_or_port(&tor_fw_options, &backend_state);
+ }
+
+ if (tor_fw_options.private_dir_port) {
+ tor_fw_options.internal_port = tor_fw_options.private_dir_port;
+ tor_fw_options.external_port = tor_fw_options.private_dir_port;
+ tor_fw_add_dir_port(&tor_fw_options, &backend_state);
+ }
+
+ r = (((tor_fw_options.nat_pmp_status | tor_fw_options.upnp_status)
+ |tor_fw_options.public_ip_status));
+ if (r > 0) {
+ fprintf(stdout, "tor-fw-helper: SUCCESS\n");
+ } else {
+ fprintf(stderr, "tor-fw-helper: FAILURE\n");
+ }
+
+ exit(r);
+}
+
diff --git a/src/tools/tor-fw-helper/tor-fw-helper.h b/src/tools/tor-fw-helper/tor-fw-helper.h
new file mode 100644
index 000000000..39d852d21
--- /dev/null
+++ b/src/tools/tor-fw-helper/tor-fw-helper.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch.
+ * Copyright (c) 2010-2011, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file tor-fw-helper.h
+ * \brief The main header for our firewall helper.
+ **/
+
+#ifndef _TOR_FW_HELPER_H
+#define _TOR_FW_HELPER_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <time.h>
+
+/** The current version of tor-fw-helper. */
+#define tor_fw_version "0.1"
+
+/** This is an arbitrary hard limit - We currently have two (NAT-PMP and UPnP).
+ We're likely going to add the Intel UPnP library but nothing else comes to
+ mind at the moment. */
+#define MAX_BACKENDS 23
+
+/** This is where we store parsed commandline options. */
+typedef struct {
+ int verbose;
+ int help;
+ int test_commandline;
+ uint16_t private_dir_port;
+ uint16_t private_or_port;
+ uint16_t public_dir_port;
+ uint16_t public_or_port;
+ uint16_t internal_port;
+ uint16_t external_port;
+ int fetch_public_ip;
+ int nat_pmp_status;
+ int upnp_status;
+ int public_ip_status;
+} tor_fw_options_t;
+
+/** This is our main structure that defines our backend helper API; each helper
+ * must conform to these public methods if it expects to be handled in a
+ * non-special way. */
+typedef struct tor_fw_backend_t {
+ const char *name;
+ size_t state_len;
+ int (*init)(tor_fw_options_t *options, void *backend_state);
+ int (*cleanup)(tor_fw_options_t *options, void *backend_state);
+ int (*fetch_public_ip)(tor_fw_options_t *options, void *backend_state);
+ int (*add_tcp_mapping)(tor_fw_options_t *options, void *backend_state);
+} tor_fw_backend_t;
+
+#endif
+
diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h
index b3cd1db50..48bd2f232 100644
--- a/src/win32/orconfig.h
+++ b/src/win32/orconfig.h
@@ -122,6 +122,7 @@
/* Define to 1 if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
+
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H
@@ -233,5 +234,13 @@
#define USING_TWOS_COMPLEMENT
/* Version number of package */
-#define VERSION "0.2.2.19-alpha"
+#define VERSION "0.2.3.5-alpha"
+
+
+#define HAVE_STRUCT_SOCKADDR_IN6
+#define HAVE_STRUCT_IN6_ADDR
+#define RSHIFT_DOES_SIGN_EXTEND
+#define FLEXIBLE_ARRAY_MEMBER 0
+#define HAVE_EVENT2_EVENT_H
+#define SHARE_DATADIR ""