diff options
165 files changed, 16414 insertions, 4832 deletions
diff --git a/.gitignore b/.gitignore index 673bb7871..867a97d2f 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,7 @@ /src/test/Makefile /src/test/Makefile.in /src/test/test +/src/test/test-child # /src/tools/ @@ -151,6 +158,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 @@ -1,3 +1,1229 @@ +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. 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 optionss 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.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. @@ -4195,7 +5421,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 +6585,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 +6595,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.) @@ -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..0daca63e9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,15 +3,22 @@ # 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 \ + README \ + ReleaseNotes \ + tor.spec \ + tor.spec.in #install-data-local: # $(INSTALL) -m 755 -d $(LOCALSTATEDIR)/lib/tor @@ -47,9 +54,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/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 new file mode 100644 index 000000000..67cb2dce2 --- /dev/null +++ b/changes/abandon-rend-circs-on-newnym @@ -0,0 +1,8 @@ + 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 new file mode 100644 index 000000000..140b94e3b --- /dev/null +++ b/changes/bug1297a @@ -0,0 +1,16 @@ + 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/bug2355 b/changes/bug2355 new file mode 100644 index 000000000..ee0ae4b96 --- /dev/null +++ b/changes/bug2355 @@ -0,0 +1,8 @@ + 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 new file mode 100644 index 000000000..2ded40ad8 --- /dev/null +++ b/changes/bug2355_revert @@ -0,0 +1,7 @@ + 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/bug2574 b/changes/bug2574 new file mode 100644 index 000000000..5cf2daebf --- /dev/null +++ b/changes/bug2574 @@ -0,0 +1,3 @@ + o Minor features: + - Allow nameservers with IPv6 address. Fixes bug 2574. + diff --git a/changes/bug2748 b/changes/bug2748 new file mode 100644 index 000000000..b522560a9 --- /dev/null +++ b/changes/bug2748 @@ -0,0 +1,10 @@ + 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/bug3045 b/changes/bug3045 new file mode 100644 index 000000000..1cbcabaff --- /dev/null +++ b/changes/bug3045 @@ -0,0 +1,6 @@ + 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/bug3118 b/changes/bug3118 new file mode 100644 index 000000000..c70298173 --- /dev/null +++ b/changes/bug3118 @@ -0,0 +1,4 @@ + o Minor bugfixes: + - Correctly link libevent_openssl when --enable-static-libevent + is passed to configure. Fixes bug 3118; bugfix on 0.2.3.1-alpha. + diff --git a/changes/bug3183 b/changes/bug3183 new file mode 100644 index 000000000..b1e594b8d --- /dev/null +++ b/changes/bug3183 @@ -0,0 +1,5 @@ + o Minor bugfixes: + - Bridges should not complain that they are unlisted in the consensus: + that's more or less the point of being a bridge. Bugfix on + 0.2.3.1-alpha; fixes bug 3183. + diff --git a/changes/bug3208 b/changes/bug3208 new file mode 100644 index 000000000..fd737ba69 --- /dev/null +++ b/changes/bug3208 @@ -0,0 +1,6 @@ + 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/bug3216 b/changes/bug3216 new file mode 100644 index 000000000..599b5e162 --- /dev/null +++ b/changes/bug3216 @@ -0,0 +1,4 @@ + 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 new file mode 100644 index 000000000..4aca810d3 --- /dev/null +++ b/changes/bug3228 @@ -0,0 +1,3 @@ + 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/bug3264 b/changes/bug3264 new file mode 100644 index 000000000..dcd0a842f --- /dev/null +++ b/changes/bug3264 @@ -0,0 +1,4 @@ + o Minor features: + - Log SSL state transitions at log level DEBUG, log domain + HANDSHAKE. This can be useful for debugging censorship events. + Implements ticket 3264. diff --git a/changes/bug3270 b/changes/bug3270 new file mode 100644 index 000000000..b37bb983c --- /dev/null +++ b/changes/bug3270 @@ -0,0 +1,4 @@ + 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 new file mode 100644 index 000000000..c469796d6 --- /dev/null +++ b/changes/bug3289 @@ -0,0 +1,5 @@ + 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 new file mode 100644 index 000000000..f868a24af --- /dev/null +++ b/changes/bug3306 @@ -0,0 +1,9 @@ + 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 new file mode 100644 index 000000000..104056d8e --- /dev/null +++ b/changes/bug3309 @@ -0,0 +1,13 @@ + 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 new file mode 100644 index 000000000..8a3c27825 --- /dev/null +++ b/changes/bug3318 @@ -0,0 +1,7 @@ + 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 new file mode 100644 index 000000000..3605efce2 --- /dev/null +++ b/changes/bug3321 @@ -0,0 +1,7 @@ + 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/bug3332 b/changes/bug3332 new file mode 100644 index 000000000..28ccbf41d --- /dev/null +++ b/changes/bug3332 @@ -0,0 +1,9 @@ + o Minor bugfixes: + - 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. + + diff --git a/changes/bug3349 b/changes/bug3349 new file mode 100644 index 000000000..fe5836ae1 --- /dev/null +++ b/changes/bug3349 @@ -0,0 +1,9 @@ + o Minor bugfixes: + - 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. Bugfix on 0.2.3.1-alpha; fixes bug 3349. + + + diff --git a/changes/bug3361 b/changes/bug3361 new file mode 100644 index 000000000..06bd954a0 --- /dev/null +++ b/changes/bug3361 @@ -0,0 +1,4 @@ + o Major bugfixes: + - Fix a crash bug that could occur when setting a consensus in a + non-used flavor without having a current consensus set. Fixes bug + 3361; bugfix on 0.2.3.1-alpha. diff --git a/changes/bug3367 b/changes/bug3367 new file mode 100644 index 000000000..8a697782b --- /dev/null +++ b/changes/bug3367 @@ -0,0 +1,4 @@ + o Minor bugfixes + - 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; bugfix on 0.2.3.1-alpha. diff --git a/changes/bug3369 b/changes/bug3369 new file mode 100644 index 000000000..9c0d0e699 --- /dev/null +++ b/changes/bug3369 @@ -0,0 +1,4 @@ + 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/bug3389 b/changes/bug3389 new file mode 100644 index 000000000..2442f4f97 --- /dev/null +++ b/changes/bug3389 @@ -0,0 +1,4 @@ + o Major bugfixes: + - Always ship the tor-fw-helper manpage in our release tarballs. Bugfix + on 0.2.3.1-alpha; fixes bug 3389. Reported by Stephen Walker. + diff --git a/changes/bug3393 b/changes/bug3393 new file mode 100644 index 000000000..677bcb7be --- /dev/null +++ b/changes/bug3393 @@ -0,0 +1,5 @@ + 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/bug3403 b/changes/bug3403 new file mode 100644 index 000000000..7d051d9f4 --- /dev/null +++ b/changes/bug3403 @@ -0,0 +1,3 @@ + o Minor bugfixes: + - Fix a class of double-mark-for-close bugs when bufferevents + are enabled. Fixes bug 3403; bugfix on 0.2.3.1-alpha. diff --git a/changes/bug3434 b/changes/bug3434 new file mode 100644 index 000000000..24ee51872 --- /dev/null +++ b/changes/bug3434 @@ -0,0 +1,2 @@ + o Minor bugfixes: + - Update tor-fw-helper to support libnatpmp-20110618; fixes 3434. diff --git a/changes/bug3465-022 b/changes/bug3465-022 new file mode 100644 index 000000000..2d226162a --- /dev/null +++ b/changes/bug3465-022 @@ -0,0 +1,6 @@ + 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/bug3465-023 b/changes/bug3465-023 new file mode 100644 index 000000000..9fa089bda --- /dev/null +++ b/changes/bug3465-023 @@ -0,0 +1,6 @@ + o Minor bugfixes: + + - Add SIGNAL to the list returned by the 'GETINFO events/names' + control-port command. Bugfix on 0.2.3.1-alpha; fixes part of + bug 3465. + diff --git a/changes/bug3536 b/changes/bug3536 new file mode 100644 index 000000000..d3cec131b --- /dev/null +++ b/changes/bug3536 @@ -0,0 +1,5 @@ + 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/cid_428 b/changes/cid_428 new file mode 100644 index 000000000..cb0fc8c2b --- /dev/null +++ b/changes/cid_428 @@ -0,0 +1,5 @@ + 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 new file mode 100644 index 000000000..2045fca23 --- /dev/null +++ b/changes/cid_450 @@ -0,0 +1,5 @@ + 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/cov217_scanf b/changes/cov217_scanf new file mode 100644 index 000000000..368bca825 --- /dev/null +++ b/changes/cov217_scanf @@ -0,0 +1,5 @@ + 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. diff --git a/changes/coverity_maint b/changes/coverity_maint new file mode 100644 index 000000000..e7be90a48 --- /dev/null +++ b/changes/coverity_maint @@ -0,0 +1,9 @@ + 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/coverity_master b/changes/coverity_master new file mode 100644 index 000000000..eca003d20 --- /dev/null +++ b/changes/coverity_master @@ -0,0 +1,8 @@ + o Minor bugfixes: + - Prevent using negative indices during unit test runs when read_all() + fails. Spotted by coverity. Bugfix on 0.2.3.1-alpha. + - Fix a rare memory leak when checking the nodelist without it being + present. Found by coverity. Bugfix on 0.2.3.1-alpha. + o Code simplifications and refactoring: + - Remove a dead variable in the heartbeat log code. Spotted by coverity. + diff --git a/changes/exit-policy-default-is-not-a-prefix b/changes/exit-policy-default-is-not-a-prefix new file mode 100644 index 000000000..6eb1e8df9 --- /dev/null +++ b/changes/exit-policy-default-is-not-a-prefix @@ -0,0 +1,5 @@ + 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 new file mode 100644 index 000000000..7960a1f47 --- /dev/null +++ b/changes/feature3049 @@ -0,0 +1,6 @@ + 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/feature3439 b/changes/feature3439 new file mode 100644 index 000000000..ee8c6f2ce --- /dev/null +++ b/changes/feature3439 @@ -0,0 +1,3 @@ + o Minor features: + - Add port 6523 (Gobby) to LongLivedPorts. Patch by intrigeri; + implements ticket 3439. diff --git a/changes/fix-connection_printf_to_buf b/changes/fix-connection_printf_to_buf new file mode 100644 index 000000000..e191eac8a --- /dev/null +++ b/changes/fix-connection_printf_to_buf @@ -0,0 +1,15 @@ + * 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/geoip-june2011 b/changes/geoip-june2011 new file mode 100644 index 000000000..8cf011b72 --- /dev/null +++ b/changes/geoip-june2011 @@ -0,0 +1,3 @@ + o Minor features: + - Update to the June 1 2011 Maxmind GeoLite Country database. + diff --git a/changes/memleak_rendcache b/changes/memleak_rendcache new file mode 100644 index 000000000..93b1f6141 --- /dev/null +++ b/changes/memleak_rendcache @@ -0,0 +1,4 @@ + 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/microdesc_use b/changes/microdesc_use new file mode 100644 index 000000000..89faf7c5f --- /dev/null +++ b/changes/microdesc_use @@ -0,0 +1,10 @@ + o Major features + - Clients can now use microdescriptors instead of regular descriptors + to build circuits. Microdescriptors are authority-generated and + -authenticated summaries of regular descriptors' contents, designed + to change very rarely. 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. + diff --git a/changes/prefer_tt_assert b/changes/prefer_tt_assert new file mode 100644 index 000000000..4fdb6367f --- /dev/null +++ b/changes/prefer_tt_assert @@ -0,0 +1,4 @@ + o Code simplifications and refactoring (tests): + - 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. diff --git a/configure.in b/configure.in index aa2233d4e..12922ae2e 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.1-alpha-dev) 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,9 @@ 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.)) + AC_PROG_CC AC_PROG_CPP AC_PROG_MAKE_SET @@ -132,6 +162,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], []) + else + AC_DEFINE([FLEXIBLE_ARRAY_MEMBER], [1]) + fi +]) + AC_PATH_PROG([SHA1SUM], [sha1sum], none) AC_PATH_PROG([OPENSSL], [openssl], none) @@ -223,7 +280,28 @@ 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 \ + memmem \ + prctl \ + socketpair \ + strlcat \ + strlcpy \ + strptime \ + strtok_r \ + strtoull \ + sysconf \ + uname \ + vasprintf \ +) using_custom_malloc=no if test x$enable_openbsd_malloc = xyes ; then @@ -314,7 +392,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 +410,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 < 0x02000800 +#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.8-rc 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 +532,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], + [#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 +1076,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 @@ -945,7 +1162,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 @@ -957,7 +1179,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" @@ -990,7 +1212,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..460424f30 --- /dev/null +++ b/contrib/findMergedChanges.pl @@ -0,0 +1,66 @@ +#!/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 +} + +while (@ARGV and $ARGV[0] =~ /^--/) { + my $flag = shift @ARGV; + if ($flag =~ /^--(weird|merged|unmerged|list)/) { + $look_for_type = $1; + } else { + die "Unrecognized flag $flag"; + } +} + +for my $changefile (@ARGV) { + my $n_merged = nChanges("origin/release-0.2.2", $changefile); + my $n_postmerged = nChanges("origin/release-0.2.2..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..b559bdb89 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.1-alpha-dev" !define INSTALLER "tor-${VERSION}-win32.exe" !define WEBSITE "https://www.torproject.org/" !define LICENSE "LICENSE" diff --git a/doc/HACKING b/doc/HACKING index 7ff9c5f3c..feeb05d02 100644 --- a/doc/HACKING +++ b/doc/HACKING @@ -456,7 +456,6 @@ interesting and understandable. 2.7) Run it through fmt to make it pretty. - 3) Compose a short release blurb to highlight the user-facing changes. Insert said release blurb into the ChangeLog stanza. If it's a stable release, add it to the ReleaseNotes file too. If we're adding @@ -472,15 +471,19 @@ or somebody to try building it on Windows. 6) Get at least two of weasel/arma/karsten to put the new version number in their approved versions list. -7) Sign and push the tarball to the website in the dist/ directory. Sign -and push the git tag. - (That's either "git tag -u <keyid> tor-0.2.x.y-status", then - "git push origin tag tor-0.2.x.y-status". To sign the - tarball, "gpg -ba <the_tarball>". Put the files in - /srv/www-master.torproject.org/htdocs/dist/ on vescum.) +7) Sign the tarball, then sign and push the git tag: + gpg -ba <the_tarball> + git tag -u <keyid> tor-0.2.x.y-status + git push origin tag tor-0.2.x.y-status + +8) scp the tarball and its sig to the website in the dist/ directory +(i.e. /srv/www-master.torproject.org/htdocs/dist/ on vescum). Edit +include/versions.wmi to note the new version. From your website checkout, +run ./publish to build and publish the website. -8) Edit include/versions.wmi to note the new version. From your website -checkout, run ./publish to build and publish the website. +Try not to delay too much between scp'ing the tarball and running +./publish -- the website has multiple A records and your scp only sent +it to one of them. 9) Email Erinn and weasel (cc'ing tor-assistants) that a new tarball is up. This step should probably change to mailing more packagers. @@ -498,3 +501,4 @@ changelog to tor-talk or tor-announce. (We might be moving to faster announcements, but don't announce until the website is at least updated.) + 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 1815a8d96..9607632e1 100644 --- a/doc/tor.1.txt +++ b/doc/tor.1.txt @@ -388,6 +388,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,6 +449,17 @@ 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 -------------- @@ -509,14 +527,14 @@ The following options are useful only for clients (that is, if patterns of nodes to avoid when building a circuit. (Example: ExcludeNodes SlowServer, $ EFFFFFFFFFFFFFFF, \{cc}, 255.254.0.0/8) + -+ + + By default, this option is treated as a preference that Tor is allowed to override in order to keep working. For example, if you try to connect to a hidden service, but you have excluded all of the hidden service's introduction points, Tor will connect to one of them anyway. If you do not want this behavior, set the StrictNodes option (documented below). + -+ + + Note also that if you are a relay, this (and the other node selection options below) only affects your own circuits that Tor builds for you. Clients can still build circuits through you to any node. Controllers @@ -530,38 +548,37 @@ 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 node that delivers traffic for you outside the Tor network. + -+ + + Note that if you list too few nodes here, or if you exclude too many exit nodes with ExcludeExitNodes, you can degrade functionality. For example, if none of the exits you list allows traffic on port 80 or 443, you won't be able to browse the web. + -+ + + Note also that not every circuit is used to deliver traffic outside of the Tor network. It is normal to see non-exit circuits (such as those used to connect to hidden services, those that do directory fetches, those used for relay reachability self-tests, and so on) that end at a non-exit node. To keep a node from being used entirely, see ExcludeNodes and StrictNodes. + -+ + + The ExcludeNodes option overrides this option: any node listed in both ExitNodes and ExcludeNodes is treated as excluded. + -+ + + The .exit address notation, if enabled via AllowDotExit, overrides 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. + -+ + + The ExcludeNodes option overrides this option: any node listed in both EntryNodes and ExcludeNodes is treated as excluded. @@ -634,7 +651,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,7 +674,8 @@ 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 @@ -964,7 +982,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 +997,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 +1028,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 +1141,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. @@ -1396,6 +1437,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 2d009bd4f..48218491b 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -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 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 +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/address.c b/src/common/address.c index 1c725393d..d0c2d5e15 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); @@ -962,6 +962,19 @@ fmt_addr(const tor_addr_t *addr) return buf; } +/** 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 fc066da68..330c43228 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; @@ -415,7 +444,7 @@ tor_vasprintf(char **strp, const char *fmt, va_list args) * * This function is <em>not</em> timing-safe. * - * Requires that nlen be greater than zero. + * Requires that <b>nlen</b> be greater than zero. */ const void * tor_memmem(const void *_haystack, size_t hlen, @@ -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)); @@ -841,7 +870,7 @@ socket_accounting_unlock(void) * Windows, where close()ing a socket doesn't work. Returns 0 on success, -1 * on failure. */ int -tor_close_socket(int s) +tor_close_socket(tor_socket_t s) { int r = 0; @@ -894,8 +923,10 @@ tor_close_socket(int s) /** Helper: if DEBUG_SOCKET_COUNTING is enabled, remember that <b>s</b> is * now an open socket. */ static INLINE void -mark_socket_open(int s) +mark_socket_open(tor_socket_t s) { + /* XXXX This bitarray business will NOT work on windows: sockets aren't + small ints there. */ if (s > max_socket) { if (max_socket == -1) { open_sockets = bitarray_init_zero(s+128); @@ -917,11 +948,19 @@ mark_socket_open(int s) /** @} */ /** As socket(), but counts the number of open sockets. */ -int +tor_socket_t tor_open_socket(int domain, int type, int protocol) { - int s = socket(domain, type, protocol); - if (s >= 0) { + 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); @@ -931,11 +970,20 @@ tor_open_socket(int domain, int type, int protocol) } /** As socket(), but counts the number of open sockets. */ -int +tor_socket_t tor_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *len) { - int s = accept(sockfd, addr, len); - if (s >= 0) { + 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); @@ -958,7 +1006,7 @@ get_n_open_sockets(void) /** Turn <b>socket</b> into a nonblocking socket. */ void -set_socket_nonblocking(int socket) +set_socket_nonblocking(tor_socket_t socket) { #if defined(MS_WINDOWS) unsigned long nonblocking = 1; @@ -986,13 +1034,22 @@ set_socket_nonblocking(int socket) **/ /* It would be nicer just to set errno, but that won't work for windows. */ int -tor_socketpair(int family, int type, int protocol, int fd[2]) +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; @@ -1011,9 +1068,9 @@ tor_socketpair(int family, int type, int protocol, int fd[2]) * for now, and really, when localhost is down sometimes, we * have other problems too. */ - int listener = -1; - int connector = -1; - int acceptor = -1; + tor_socket_t listener = -1; + tor_socket_t connector = -1; + tor_socket_t acceptor = -1; struct sockaddr_in listen_addr; struct sockaddr_in connect_addr; int size; @@ -1223,7 +1280,8 @@ log_credential_status(void) /* Read, effective and saved GIDs */ gid_t rgid, egid, sgid; /* Supplementary groups */ - gid_t sup_gids[NGROUPS_MAX + 1]; + gid_t *sup_gids = NULL; + int sup_gids_size; /* Number of supplementary groups */ int ngids; @@ -1269,9 +1327,19 @@ log_credential_status(void) #endif /* log supplementary groups */ - if ((ngids = getgroups(NGROUPS_MAX + 1, sup_gids)) < 0) { + sup_gids_size = 64; + sup_gids = tor_malloc(sizeof(gid_t) * 64); + while ((ngids = getgroups(sup_gids_size, sup_gids)) < 0 && + errno == EINVAL && + sup_gids_size < NGROUPS_MAX) { + sup_gids_size *= 2; + sup_gids = tor_realloc(sup_gids, sizeof(gid_t) * sup_gids_size); + } + + if (ngids < 0) { log_warn(LD_GENERAL, "Error getting supplementary GIDs: %s", strerror(errno)); + tor_free(sup_gids); return -1; } else { int i, retval = 0; @@ -1301,6 +1369,7 @@ log_credential_status(void) tor_free(cp); }); smartlist_free(elts); + tor_free(sup_gids); return retval; } @@ -1980,6 +2049,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.) */ @@ -2577,11 +2692,11 @@ in_main_thread(void) */ #if defined(MS_WINDOWS) int -tor_socket_errno(int sock) +tor_socket_errno(tor_socket_t sock) { int optval, optvallen=sizeof(optval); int err = WSAGetLastError(); - if (err == WSAEWOULDBLOCK && sock >= 0) { + if (err == WSAEWOULDBLOCK && SOCKET_OK(sock)) { if (getsockopt(sock, SOL_SOCKET, SO_ERROR, (void*)&optval, &optvallen)) return err; if (optval) diff --git a/src/common/compat.h b/src/common/compat.h index eff51ab30..094036dff 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -51,6 +51,8 @@ #include <netinet6/in6.h> #endif +#include <stdio.h> + #if defined (WINCE) #include <fcntl.h> #include <io.h> @@ -367,6 +369,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); @@ -390,15 +395,24 @@ int tor_fd_seekend(int fd); typedef int socklen_t; #endif -int tor_close_socket(int s); -int tor_open_socket(int domain, int type, int protocol); -int tor_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *len); +#ifdef MS_WINDOWS +#define tor_socket_t intptr_t +#define SOCKET_OK(s) ((s) != INVALID_SOCKET) +#else +#define tor_socket_t int +#define SOCKET_OK(s) ((s) >= 0) +#endif + +int tor_close_socket(tor_socket_t s); +tor_socket_t tor_open_socket(int domain, int type, int protocol); +tor_socket_t tor_accept_socket(int sockfd, struct sockaddr *addr, + socklen_t *len); int get_n_open_sockets(void); #define tor_socket_send(s, buf, len, flags) send(s, buf, len, flags) #define tor_socket_recv(s, buf, len, flags) recv(s, buf, len, flags) -/** Implementatino of struct in6_addr for platforms that do not have it. +/** Implementation of struct in6_addr for platforms that do not have it. * Generally, these platforms are ones without IPv6 support, but we want to * have a working in6_addr there anyway, so we can use it to parse IPv6 * addresses. */ @@ -464,8 +478,8 @@ int tor_inet_aton(const char *cp, struct in_addr *addr) ATTR_NONNULL((1,2)); const char *tor_inet_ntop(int af, const void *src, char *dst, size_t len); int tor_inet_pton(int af, const char *src, void *dst); int tor_lookup_hostname(const char *name, uint32_t *addr) ATTR_NONNULL((1,2)); -void set_socket_nonblocking(int socket); -int tor_socketpair(int family, int type, int protocol, int fd[2]); +void set_socket_nonblocking(tor_socket_t socket); +int tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]); int network_init(void); /* For stupid historical reasons, windows sockets have an independent @@ -492,7 +506,7 @@ int network_init(void); ((e) == WSAEMFILE || (e) == WSAENOBUFS) /** Return true if e is EADDRINUSE or the local equivalent. */ #define ERRNO_IS_EADDRINUSE(e) ((e) == WSAEADDRINUSE) -int tor_socket_errno(int sock); +int tor_socket_errno(tor_socket_t sock); const char *tor_socket_strerror(int e); #else #define ERRNO_IS_EAGAIN(e) ((e) == EAGAIN) @@ -568,6 +582,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 3ad9be145..c338dd6c0 100644 --- a/src/common/compat_libevent.c +++ b/src/common/compat_libevent.c @@ -48,7 +48,7 @@ typedef uint32_t le_version_t; * it is. */ #define LE_OLD V(0,0,0) /** Represents a version of libevent so weird we can't figure out what version - * it it. */ + * it is. */ #define LE_OTHER V(0,0,99) static le_version_t tor_get_libevent_version(const char **v_out); @@ -165,9 +165,11 @@ struct event_base *the_event_base = NULL; /** 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 +179,29 @@ 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) + event_config_set_flag(cfg, EVENT_BASE_FLAG_STARTUP_IOCP); +#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 @@ -240,7 +264,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 +272,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 +576,29 @@ 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 1 / TOR_LIBEVENT_TICKS_PER_SECOND seconds have passed. +*/ +const struct timeval * +tor_libevent_get_one_tick_timeout(void) +{ + if (PREDICT_UNLIKELY(one_tick == NULL)) { + struct event_base *base = tor_libevent_get_base(); + struct timeval tv; + if (TOR_LIBEVENT_TICKS_PER_SECOND == 1) { + tv.tv_sec = 1; + tv.tv_usec = 0; + } else { + tv.tv_sec = 0; + tv.tv_usec = 1000000 / TOR_LIBEVENT_TICKS_PER_SECOND; + } + one_tick = event_base_init_common_timeout(base, &tv); + } + return one_tick; +} +#endif + diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h index fdf5e0a18..8669fd4e0 100644 --- a/src/common/compat_libevent.h +++ b/src/common/compat_libevent.h @@ -8,10 +8,14 @@ struct event; struct event_base; +#ifdef USE_BUFFEREVENTS +struct bufferevent; +#endif #ifdef HAVE_EVENT2_EVENT_H #include <event2/util.h> -#else +#elif !defined(EVUTIL_SOCKET_DEFINED) +#define EVUTIL_SOCKET_DEFINED #define evutil_socket_t int #endif @@ -53,7 +57,12 @@ 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; +} 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, @@ -61,5 +70,10 @@ 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 +#define TOR_LIBEVENT_TICKS_PER_SECOND 3 +const struct timeval *tor_libevent_get_one_tick_timeout(void); +#endif + #endif diff --git a/src/common/container.c b/src/common/container.c index da44b7fe6..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) @@ -338,7 +337,8 @@ smartlist_insert(smartlist_t *sl, int idx, void *val) /** * Split a string <b>str</b> along all occurrences of <b>sep</b>, - * adding the split strings, in order, to <b>sl</b>. + * appending the (newly allocated) split strings, in order, to + * <b>sl</b>. Return the number of strings added to <b>sl</b>. * * If <b>flags</b>&SPLIT_SKIP_SPACE is true, remove initial and * trailing space from each entry. @@ -347,7 +347,7 @@ smartlist_insert(smartlist_t *sl, int idx, void *val) * If <b>flags</b>&SPLIT_STRIP_SPACE is true, strip spaces from each * split string. * - * If max>0, divide the string into no more than <b>max</b> pieces. If + * If <b>max</b>\>0, divide the string into no more than <b>max</b> pieces. If * <b>sep</b> is NULL, split on any sequence of horizontal space. */ int diff --git a/src/common/crypto.c b/src/common/crypto.c index 1ecc24ce2..05c1ce9ea 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -777,6 +777,17 @@ crypto_pk_keysize(crypto_pk_env_t *env) return (size_t) RSA_size(env->key); } +/** Return the size of the public key modulus of <b>env</b>, in bits. */ +int +crypto_pk_num_bits(crypto_pk_env_t *env) +{ + tor_assert(env); + tor_assert(env->key); + tor_assert(env->key->n); + + return BN_num_bits(env->key->n); +} + /** Increase the reference count of <b>env</b>, and return it. */ crypto_pk_env_t * @@ -937,7 +948,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) { @@ -1122,8 +1133,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, @@ -2134,13 +2145,14 @@ crypto_rand(char *to, size_t n) } /** Return a pseudorandom integer, chosen uniformly from the values - * between 0 and <b>max</b>-1. */ + * between 0 and <b>max</b>-1 inclusive. <b>max</b> must be between 1 and + * INT_MAX+1, inclusive. */ int crypto_rand_int(unsigned int max) { unsigned int val; unsigned int cutoff; - tor_assert(max < UINT_MAX); + tor_assert(max <= ((unsigned int)INT_MAX)+1); tor_assert(max > 0); /* don't div by 0 */ /* We ignore any values that are >= 'cutoff,' to avoid biasing the diff --git a/src/common/crypto.h b/src/common/crypto.h index 54c7a67a3..9b4eee622 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -119,6 +119,7 @@ int crypto_pk_write_private_key_to_filename(crypto_pk_env_t *env, int crypto_pk_check_key(crypto_pk_env_t *env); int crypto_pk_cmp_keys(crypto_pk_env_t *a, crypto_pk_env_t *b); size_t crypto_pk_keysize(crypto_pk_env_t *env); +int crypto_pk_num_bits(crypto_pk_env_t *env); crypto_pk_env_t *crypto_pk_dup_key(crypto_pk_env_t *orig); crypto_pk_env_t *crypto_pk_copy_full(crypto_pk_env_t *orig); int crypto_pk_key_is_private(const crypto_pk_env_t *key); @@ -244,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 d14563c88..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 @@ -390,7 +409,7 @@ logv(int severity, log_domain_mask_t domain, const char *funcname, /** Output a message to the log. It gets logged to all logfiles that * care about messages with <b>severity</b> in <b>domain</b>. The content - * is formatted printf style basedc on <b>format</b> and extra arguments. + * is formatted printf-style based on <b>format</b> and extra arguments. * */ void tor_log(int severity, log_domain_mask_t domain, const char *format, ...) @@ -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/procmon.c b/src/common/procmon.c new file mode 100644 index 000000000..5c10e9a22 --- /dev/null +++ b/src/common/procmon.c @@ -0,0 +1,336 @@ + +/** + * \file procmon.c + * \brief Process-termination monitor functions + **/ + +#include "procmon.h" + +#include "util.h" + +#ifdef HAVE_EVENT2_EVENT_H +#include <event2/event.h> +#else +#include <event.h> +#endif + +#ifdef HAVE_SIGNAL_H +#include <signal.h> +#endif +#ifdef HAVE_ERRNO_H +#include <errno.h> +#endif + +#ifdef MS_WINDOWS +#include <windows.h> + +/* Windows does not define pid_t, but _getpid() returns an int. */ +typedef int pid_t; +#endif + +/* Define to 1 if process-termination monitors on this OS and Libevent + version must poll for process termination themselves. */ +#define PROCMON_POLLS 1 +/* Currently we need to poll in some way on all systems. */ + +#ifdef PROCMON_POLLS +static void tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2, + void *procmon_); +#endif + +/* This struct may contain pointers into the original process + * specifier string, but it should *never* contain anything which + * needs to be freed. */ +struct parsed_process_specifier_t { + pid_t pid; +}; + +/** Parse the process specifier given in <b>process_spec</b> into + * *<b>ppspec</b>. Return 0 on success; return -1 and store an error + * message into *<b>msg</b> on failure. The caller must not free the + * returned error message. */ +static int +parse_process_specifier(const char *process_spec, + struct parsed_process_specifier_t *ppspec, + const char **msg) +{ + long pid_l; + int pid_ok = 0; + char *pspec_next; + + /* If we're lucky, long will turn out to be large enough to hold a + * PID everywhere that Tor runs. */ + pid_l = tor_parse_long(process_spec, 0, 1, LONG_MAX, &pid_ok, &pspec_next); + + /* Reserve room in the ‘process specifier’ for additional + * (platform-specific) identifying information beyond the PID, to + * make our process-existence checks a bit less racy in a future + * version. */ + if ((*pspec_next != 0) && (*pspec_next != ' ') && (*pspec_next != ':')) { + pid_ok = 0; + } + + ppspec->pid = (pid_t)(pid_l); + if (!pid_ok || (pid_l != (long)(ppspec->pid))) { + *msg = "invalid PID"; + goto err; + } + + return 0; + err: + return -1; +} + +struct tor_process_monitor_t { + /** Log domain for warning messages. */ + log_domain_mask_t log_domain; + + /** All systems: The best we can do in general is poll for the + * process's existence by PID periodically, and hope that the kernel + * doesn't reassign the same PID to another process between our + * polls. */ + pid_t pid; + +#ifdef MS_WINDOWS + /** Windows-only: Should we poll hproc? If false, poll pid + * instead. */ + int poll_hproc; + + /** Windows-only: Get a handle to the process (if possible) and + * periodically check whether the process we have a handle to has + * ended. */ + HANDLE hproc; + /* XXX023 We can and should have Libevent watch hproc for us, + * if/when some version of Libevent 2.x can be told to do so. */ +#endif + + /* XXX023 On Linux, we can and should receive the 22nd + * (space-delimited) field (‘starttime’) of /proc/$PID/stat from the + * owning controller and store it, and poll once in a while to see + * whether it has changed -- if so, the kernel has *definitely* + * reassigned the owning controller's PID and we should exit. On + * FreeBSD, we can do the same trick using either the 8th + * space-delimited field of /proc/$PID/status on the seven FBSD + * systems whose admins have mounted procfs, or the start-time field + * of the process-information structure returned by kvmgetprocs() on + * any system. The latter is ickier. */ + /* XXX023 On FreeBSD (and possibly other kqueue systems), we can and + * should arrange to receive EVFILT_PROC NOTE_EXIT notifications for + * pid, so we don't have to do such a heavyweight poll operation in + * order to avoid the PID-reassignment race condition. (We would + * still need to poll our own kqueue periodically until some version + * of Libevent 2.x learns to receive these events for us.) */ + + /** A Libevent event structure, to either poll for the process's + * existence or receive a notification when the process ends. */ + struct event *e; + + /** A callback to be called when the process ends. */ + tor_procmon_callback_t cb; + void *cb_arg; /**< A user-specified pointer to be passed to cb. */ +}; + +/** Verify that the process specifier given in <b>process_spec</b> is + * syntactically valid. Return 0 on success; return -1 and store an + * error message into *<b>msg</b> on failure. The caller must not + * free the returned error message. */ +int +tor_validate_process_specifier(const char *process_spec, + const char **msg) +{ + struct parsed_process_specifier_t ppspec; + + tor_assert(msg != NULL); + *msg = NULL; + + return parse_process_specifier(process_spec, &ppspec, msg); +} + +#ifdef HAVE_EVENT2_EVENT_H +#define PERIODIC_TIMER_FLAGS EV_PERSIST +#else +#define PERIODIC_TIMER_FLAGS (0) +#endif + +static struct timeval poll_interval_tv = {15, 0}; +/* Note: If you port this file to plain Libevent 2, you can make + * poll_interval_tv const. It has to be non-const here because in + * libevent 1.x, event_add expects a pointer to a non-const struct + * timeval. */ + +/** Create a process-termination monitor for the process specifier + * given in <b>process_spec</b>. Return a newly allocated + * tor_process_monitor_t on success; return NULL and store an error + * message into *<b>msg</b> on failure. The caller must not free + * the returned error message. + * + * When the monitored process terminates, call + * <b>cb</b>(<b>cb_arg</b>). + */ +tor_process_monitor_t * +tor_process_monitor_new(struct event_base *base, + const char *process_spec, + log_domain_mask_t log_domain, + tor_procmon_callback_t cb, void *cb_arg, + const char **msg) +{ + tor_process_monitor_t *procmon = tor_malloc(sizeof(tor_process_monitor_t)); + struct parsed_process_specifier_t ppspec; + + tor_assert(msg != NULL); + *msg = NULL; + + if (procmon == NULL) { + *msg = "out of memory"; + goto err; + } + + procmon->log_domain = log_domain; + + if (parse_process_specifier(process_spec, &ppspec, msg)) + goto err; + + procmon->pid = ppspec.pid; + +#ifdef MS_WINDOWS + procmon->hproc = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, + FALSE, + procmon->pid); + + if (procmon->hproc != NULL) { + procmon->poll_hproc = 1; + log_info(procmon->log_domain, "Successfully opened handle to process %d; " + "monitoring it.", + (int)(procmon->pid)); + } else { + /* If we couldn't get a handle to the process, we'll try again the + * first time we poll. */ + log_info(procmon->log_domain, "Failed to open handle to process %d; will " + "try again later.", + (int)(procmon->pid)); + } +#endif + + procmon->cb = cb; + procmon->cb_arg = cb_arg; + +#ifdef PROCMON_POLLS + procmon->e = tor_event_new(base, -1 /* no FD */, PERIODIC_TIMER_FLAGS, + tor_process_monitor_poll_cb, procmon); + /* Note: If you port this file to plain Libevent 2, check that + * procmon->e is non-NULL. We don't need to here because + * tor_evtimer_new never returns NULL. */ + + evtimer_add(procmon->e, &poll_interval_tv); +#else +#error OOPS? +#endif + + return procmon; + err: + tor_process_monitor_free(procmon); + return NULL; +} + +#ifdef PROCMON_POLLS +/** Libevent callback to poll for the existence of the process + * monitored by <b>procmon_</b>. */ +static void +tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2, + void *procmon_) +{ + tor_process_monitor_t *procmon = (tor_process_monitor_t *)(procmon_); + int its_dead_jim; + + (void)unused1; (void)unused2; + + tor_assert(procmon != NULL); + +#ifdef MS_WINDOWS + if (procmon->poll_hproc) { + DWORD exit_code; + if (!GetExitCodeProcess(procmon->hproc, &exit_code)) { + char *errmsg = format_win32_error(GetLastError()); + log_warn(procmon->log_domain, "Error \"%s\" occurred while polling " + "handle for monitored process %d; assuming it's dead.", + errmsg, procmon->pid); + tor_free(errmsg); + its_dead_jim = 1; + } else { + its_dead_jim = (exit_code != STILL_ACTIVE); + } + } else { + /* All we can do is try to open the process, and look at the error + * code if it fails again. */ + procmon->hproc = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, + FALSE, + procmon->pid); + + if (procmon->hproc != NULL) { + log_info(procmon->log_domain, "Successfully opened handle to monitored " + "process %d.", + procmon->pid); + its_dead_jim = 0; + procmon->poll_hproc = 1; + } else { + DWORD err_code = GetLastError(); + char *errmsg = format_win32_error(err_code); + + /* When I tested OpenProcess's error codes on Windows 7, I + * received error code 5 (ERROR_ACCESS_DENIED) for PIDs of + * existing processes that I could not open and error code 87 + * (ERROR_INVALID_PARAMETER) for PIDs that were not in use. + * Since the nonexistent-process error code is sane, I'm going + * to assume that all errors other than ERROR_INVALID_PARAMETER + * mean that the process we are monitoring is still alive. */ + its_dead_jim = (err_code == ERROR_INVALID_PARAMETER); + + if (!its_dead_jim) + log_info(procmon->log_domain, "Failed to open handle to monitored " + "process %d, and error code %lu (%s) is not 'invalid " + "parameter' -- assuming the process is still alive.", + procmon->pid, + err_code, errmsg); + + tor_free(errmsg); + } + } +#else + /* Unix makes this part easy, if a bit racy. */ + its_dead_jim = kill(procmon->pid, 0); + its_dead_jim = its_dead_jim && (errno == ESRCH); +#endif + + log(its_dead_jim ? LOG_NOTICE : LOG_INFO, + procmon->log_domain, "Monitored process %d is %s.", + (int)procmon->pid, + its_dead_jim ? "dead" : "still alive"); + + if (its_dead_jim) { + procmon->cb(procmon->cb_arg); +#ifndef HAVE_EVENT2_EVENT_H + } else { + evtimer_add(procmon->e, &poll_interval_tv); +#endif + } +} +#endif + +/** Free the process-termination monitor <b>procmon</b>. */ +void +tor_process_monitor_free(tor_process_monitor_t *procmon) +{ + if (procmon == NULL) + return; + +#ifdef MS_WINDOWS + if (procmon->hproc != NULL) + CloseHandle(procmon->hproc); +#endif + + if (procmon->e != NULL) + tor_event_free(procmon->e); + + tor_free(procmon); +} + diff --git a/src/common/procmon.h b/src/common/procmon.h new file mode 100644 index 000000000..02eb2da61 --- /dev/null +++ b/src/common/procmon.h @@ -0,0 +1,30 @@ + +/** + * \file procmon.h + * \brief Headers for procmon.c + **/ + +#ifndef TOR_PROCMON_H +#define TOR_PROCMON_H + +#include "compat.h" +#include "compat_libevent.h" + +#include "torlog.h" + +typedef struct tor_process_monitor_t tor_process_monitor_t; + +typedef void (*tor_procmon_callback_t)(void *); + +int tor_validate_process_specifier(const char *process_spec, + const char **msg); +tor_process_monitor_t *tor_process_monitor_new(struct event_base *base, + const char *process_spec, + log_domain_mask_t log_domain, + tor_procmon_callback_t cb, + void *cb_arg, + const char **msg); +void tor_process_monitor_free(tor_process_monitor_t *procmon); + +#endif + diff --git a/src/common/torlog.h b/src/common/torlog.h index 000e32dda..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,8 +147,8 @@ 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); -/* Outputs a message to stdout */ void tor_log(int severity, log_domain_mask_t domain, const char *format, ...) CHECK_PRINTF(3,4); #define log tor_log /* hack it so we don't conflict with log() as much */ diff --git a/src/common/tortls.c b/src/common/tortls.c index 10f4440cb..94ca81ba4 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -44,14 +44,20 @@ #error "We require OpenSSL >= 0.9.7" #endif +#ifdef USE_BUFFEREVENTS +#include <event2/bufferevent_ssl.h> +#include <event2/buffer.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 +103,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 +117,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 +126,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 +154,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 +187,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 +198,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 +222,46 @@ ssl_state_to_string(int ssl_state) return buf; } +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; + + 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 +436,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 +456,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 +899,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 +917,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 +930,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 +951,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 +1042,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 +1083,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 +1106,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 +1144,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 +1152,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 +1176,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 +1204,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 +1216,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 +1329,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 +1625,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 +1776,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 +1814,71 @@ 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) { + /* 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); + } 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..ecb5bd2fb 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -67,8 +67,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 +84,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 7ffe0a98c..b95ee3a61 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -14,6 +14,7 @@ #define _GNU_SOURCE #include "orconfig.h" +#define UTIL_PRIVATE #include "util.h" #include "torlog.h" #undef log @@ -775,13 +776,17 @@ tor_digest256_is_zero(const char *digest) if (next) *next = endptr; \ return 0 -/** Extract a long from the start of s, in the given numeric base. If - * there is unconverted data and next is provided, set *next to the - * first unconverted character. An error has occurred if no characters - * are converted; or if there are unconverted characters and next is NULL; or - * if the parsed value is not between min and max. When no error occurs, - * return the parsed value and set *ok (if provided) to 1. When an error - * occurs, return 0 and set *ok (if provided) to 0. +/** Extract a long from the start of <b>s</b>, in the given numeric + * <b>base</b>. If <b>base</b> is 0, <b>s</b> is parsed as a decimal, + * octal, or hex number in the syntax of a C integer literal. If + * there is unconverted data and <b>next</b> is provided, set + * *<b>next</b> to the first unconverted character. An error has + * occurred if no characters are converted; or if there are + * unconverted characters and <b>next</b> is NULL; or if the parsed + * value is not between <b>min</b> and <b>max</b>. When no error + * occurs, return the parsed value and set *<b>ok</b> (if provided) to + * 1. When an error occurs, return 0 and set *<b>ok</b> (if provided) + * to 0. */ long tor_parse_long(const char *s, int base, long min, long max, @@ -948,7 +953,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) { @@ -1568,7 +1573,7 @@ rate_limit_log(ratelim_t *lim, time_t now) * was returned by open(). Return the number of bytes written, or -1 * on error. Only use if fd is a blocking fd. */ ssize_t -write_all(int fd, const char *buf, size_t count, int isSocket) +write_all(tor_socket_t fd, const char *buf, size_t count, int isSocket) { size_t written = 0; ssize_t result; @@ -1578,7 +1583,7 @@ write_all(int fd, const char *buf, size_t count, int isSocket) if (isSocket) result = tor_socket_send(fd, buf+written, count-written, 0); else - result = write(fd, buf+written, count-written); + result = write((int)fd, buf+written, count-written); if (result<0) return -1; written += result; @@ -1592,7 +1597,7 @@ write_all(int fd, const char *buf, size_t count, int isSocket) * open(). Return the number of bytes read, or -1 on error. Only use * if fd is a blocking fd. */ ssize_t -read_all(int fd, char *buf, size_t count, int isSocket) +read_all(tor_socket_t fd, char *buf, size_t count, int isSocket) { size_t numread = 0; ssize_t result; @@ -1604,7 +1609,7 @@ read_all(int fd, char *buf, size_t count, int isSocket) if (isSocket) result = tor_socket_recv(fd, buf+numread, count-numread, 0); else - result = read(fd, buf+numread, count-numread); + result = read((int)fd, buf+numread, count-numread); if (result<0) return -1; else if (result == 0) @@ -1673,15 +1678,21 @@ file_status(const char *fname) * is group-readable, but in all cases we create the directory mode 0700. * If CPD_CHECK_MODE_ONLY is set, then we don't alter the directory permissions * if they are too permissive: we just return -1. + * When effective_user is not NULL, check permissions against the given user + * and its primary group. */ int -check_private_dir(const char *dirname, cpd_check_t check) +check_private_dir(const char *dirname, cpd_check_t check, + const char *effective_user) { int r; struct stat st; char *f; #ifndef MS_WINDOWS int mask; + struct passwd *pw = NULL; + uid_t running_uid; + gid_t running_gid; #endif tor_assert(dirname); @@ -1720,33 +1731,49 @@ check_private_dir(const char *dirname, cpd_check_t check) return -1; } #ifndef MS_WINDOWS - if (st.st_uid != getuid()) { + if (effective_user) { + /* Look up the user and group information. + * If we have a problem, bail out. */ + pw = getpwnam(effective_user); + if (pw == NULL) { + log_warn(LD_CONFIG, "Error setting configured user: %s not found", + effective_user); + return -1; + } + running_uid = pw->pw_uid; + running_gid = pw->pw_gid; + } else { + running_uid = getuid(); + running_gid = getgid(); + } + + if (st.st_uid != running_uid) { struct passwd *pw = NULL; char *process_ownername = NULL; - pw = getpwuid(getuid()); + pw = getpwuid(running_uid); process_ownername = pw ? tor_strdup(pw->pw_name) : tor_strdup("<unknown>"); pw = getpwuid(st.st_uid); log_warn(LD_FS, "%s is not owned by this user (%s, %d) but by " "%s (%d). Perhaps you are running Tor as the wrong user?", - dirname, process_ownername, (int)getuid(), + dirname, process_ownername, (int)running_uid, pw ? pw->pw_name : "<unknown>", (int)st.st_uid); tor_free(process_ownername); return -1; } - if ((check & CPD_GROUP_OK) && st.st_gid != getgid()) { + if ((check & CPD_GROUP_OK) && st.st_gid != running_gid) { struct group *gr; char *process_groupname = NULL; - gr = getgrgid(getgid()); + gr = getgrgid(running_gid); process_groupname = gr ? tor_strdup(gr->gr_name) : tor_strdup("<unknown>"); gr = getgrgid(st.st_gid); log_warn(LD_FS, "%s is not owned by this group (%s, %d) but by group " "%s (%d). Are you running Tor as the wrong user?", - dirname, process_groupname, (int)getgid(), + dirname, process_groupname, (int)running_gid, gr ? gr->gr_name : "<unknown>", (int)st.st_gid); tor_free(process_groupname); @@ -1865,7 +1892,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)); @@ -2086,7 +2113,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; @@ -2472,18 +2499,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; @@ -2545,11 +2575,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; @@ -2586,9 +2617,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 @@ -2782,7 +2813,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); @@ -2853,3 +2884,451 @@ load_windows_system_library(const TCHAR *library_name) } #endif +/** 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 + +#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 + +#define SPAWN_ERROR_MESSAGE "ERR: Failed to spawn background process - code " + +/** Start a program in the background. If <b>filename</b> contains a '/', + * then it will be treated as an absolute or relative path. Otherwise the + * system path will be searched for <b>filename</b>. 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). The last element of argv must be NULL. If the child + * program is launched, the PID will be returned and <b>stdout_read</b> and + * <b>stdout_err</b> will be set to file descriptors from which the stdout + * and stderr, respectively, output of the child program can be read, and the + * stdin of the child process shall be set to /dev/null. Otherwise returns + * -1. Some parts of this code are based on the POSIX subprocess module from + * Python. + */ +int +tor_spawn_background(const char *const filename, int *stdout_read, + int *stderr_read, const char **argv) +{ +#ifdef MS_WINDOWS + (void) filename; (void) stdout_read; (void) stderr_read; (void) argv; + log_warn(LD_BUG, "not yet implemented on Windows."); + return -1; +#else + 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; + + /* 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 -1; + } + + 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 -1; + } + + 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 */ + 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 */ + nbytes = write(STDOUT_FILENO, error_message, error_message_length); + nbytes = write(STDOUT_FILENO, hex_errno, sizeof(hex_errno)); + + (void) nbytes; + + _exit(255); + return -1; /* Never reached, but avoids compiler warning */ + } + + /* 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 -1; + } + + /* Return read end of the pipes to caller, and close write end */ + *stdout_read = 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)); + /* Do not return -1, because the child is running, so the parent + needs to know about the pid in order to reap it later */ + } + + *stderr_read = 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)); + /* Do not return -1, because the child is running, so the parent + needs to know about the pid in order to reap it later */ + } + + return pid; +#endif +} + +/** 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]; + + for (;;) { + char *retval; + retval = fgets(buf, sizeof(buf), stream); + + if (NULL == retval) { + if (feof(stream)) { + /* Program has closed stream (probably it exited) */ + /* TODO: check error */ + fclose(stream); + return 1; + } else { + if (EAGAIN == errno) { + /* Nothing more to read, try again next time */ + return 0; + } else { + /* There was a problem, abandon this child process */ + fclose(stream); + return -1; + } + } + } else { + /* We have some data, log it and keep asking for more */ + size_t len; + + len = strlen(buf); + if (buf[len - 1] == '\n') { + /* Remove the trailing newline */ + buf[len - 1] = '\0'; + } else { + /* No newline; check whether we overflowed the buffer */ + if (!feof(stream)) + log_warn(LD_GENERAL, + "Line from port forwarding helper was truncated: %s", buf); + /* TODO: What to do with this error? */ + } + + /* 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; +} + +void +tor_check_port_forwarding(const char *filename, int dir_port, int or_port, + time_t now) +{ +#ifdef MS_WINDOWS + (void) filename; (void) dir_port; (void) or_port; (void) now; + (void) tor_spawn_background; + (void) log_from_pipe; + log_warn(LD_GENERAL, "Sorry, port forwarding is not yet supported " + "on windows."); +#else +/* When fw-helper succeeds, how long do we wait until running it again */ +#define TIME_TO_EXEC_FWHELPER_SUCCESS 300 +/* When fw-helper fails, how long do we wait until running it again */ +#define TIME_TO_EXEC_FWHELPER_FAIL 60 + + static int child_pid = -1; + static FILE *stdout_read = NULL; + static FILE *stderr_read = NULL; + 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 (-1 == child_pid && + time_to_run_helper < now) { + int fd_out=-1, fd_err=-1; + + /* Assume tor-fw-helper will succeed, start it later*/ + time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_SUCCESS; + + child_pid = tor_spawn_background(filename, &fd_out, &fd_err, argv); + if (child_pid < 0) { + log_warn(LD_GENERAL, "Failed to start port forwarding helper %s", + filename); + child_pid = -1; + return; + } + /* Set stdout/stderr pipes to be non-blocking */ + fcntl(fd_out, F_SETFL, O_NONBLOCK); + fcntl(fd_err, F_SETFL, O_NONBLOCK); + /* Open the buffered IO streams */ + stdout_read = fdopen(fd_out, "r"); + stderr_read = fdopen(fd_err, "r"); + + log_info(LD_GENERAL, + "Started port forwarding helper (%s) with pid %d", filename, child_pid); + } + + /* If child is running, read from its stdout and stderr) */ + if (child_pid > 0) { + /* Read from stdout/stderr and log result */ + retval = 0; + stdout_status = log_from_pipe(stdout_read, LOG_INFO, filename, &retval); + stderr_status = log_from_pipe(stderr_read, LOG_WARN, filename, &retval); + 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; + else if (1 == stdout_status || 1 == stderr_status) + /* stdout or stderr was closed */ + retval = 1; + 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"); + } else { + log_warn(LD_GENERAL, "Failed to read from port forwarding helper"); + } + + /* TODO: The child might not actually be finished (maybe it failed or + closed stdout/stderr), so maybe we shouldn't start another? */ + child_pid = -1; + } + } +#endif +} + diff --git a/src/common/util.h b/src/common/util.h index f32709acc..6496c42db 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -276,8 +276,8 @@ typedef struct ratelim_t { char *rate_limit_log(ratelim_t *lim, time_t now); /* File helpers */ -ssize_t write_all(int fd, const char *buf, size_t count, int isSocket); -ssize_t read_all(int fd, char *buf, size_t count, int isSocket); +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); /** Return values from file_status(); see that function's documentation * for details. */ @@ -292,7 +292,8 @@ typedef unsigned int cpd_check_t; #define CPD_CHECK 2 #define CPD_GROUP_OK 4 #define CPD_CHECK_MODE_ONLY 8 -int check_private_dir(const char *dirname, cpd_check_t check); +int check_private_dir(const char *dirname, cpd_check_t check, + const char *effective_user); #define OPEN_FLAGS_REPLACE (O_WRONLY|O_CREAT|O_TRUNC) #define OPEN_FLAGS_APPEND (O_WRONLY|O_CREAT|O_APPEND) typedef struct open_file_t open_file_t; @@ -336,10 +337,27 @@ 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); + #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) */ +int tor_spawn_background(const char *const filename, int *stdout_read, + int *stderr_read, 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 465c13be7..8d64d312d 100644 --- a/src/config/geoip +++ b/src/config/geoip @@ -1,4 +1,4 @@ -# Last updated based on May 1 2011 Maxmind GeoLite Country +# Last updated based on June 1 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 @@ -104,17 +104,26 @@ 34928384,34928639,DE 34928640,34930687,EU 34930688,34938879,DE -34938880,34952703,EU -34952704,34953215,ES +34938880,34947071,FR +34947072,34952703,EU +34952704,34953215,SE 34953216,34954751,AT 34954752,34955263,NL 34955264,34959359,AT 34959360,34963455,NL 34963456,34992127,EU 34992128,34993151,NL -34993152,34993663,EU +34993152,34993663,FR 34993664,34993919,AT -34993920,35127295,EU +34993920,34994175,DE +34994176,34995711,FR +34995712,34995967,EU +34995968,34996223,NL +34996224,35000319,EU +35000320,35002367,SE +35002368,35069951,EU +35069952,35078143,SE +35078144,35127295,EU 35127296,35651583,GB 35651584,36700159,IT 36700160,36962303,AE @@ -371,8 +380,12 @@ 210439560,210439567,PR 210439568,210784255,US 210784256,210784383,BO -210784384,210784767,US -210784768,210786303,BO +210784384,210785023,US +210785024,210785575,BO +210785576,210785583,US +210785584,210785599,BO +210785600,210785663,US +210785664,210786303,BO 210786304,210970847,US 210970848,210970855,PR 210970856,211051199,US @@ -928,7 +941,6 @@ 452997120,453001215,IN 453001216,453009407,AU 453009408,453017599,BD -453017600,453050367,JP 453050368,453115903,KR 453115904,453246975,VN 453246976,453509119,IN @@ -1378,7 +1390,9 @@ 522715136,522717183,IR 522717184,522719231,RU 522719232,522721279,UA -522721280,522739711,RU +522721280,522741759,RU +522741760,522743807,UA +522743808,522747903,RU 522747904,522780671,UA 522780672,522782719,RU 522782720,522784767,UA @@ -1468,7 +1482,20 @@ 528605184,528613375,UA 528613376,528637951,RU 528637952,528642047,PL -528642048,528646143,RU +528642048,528654335,RU +528654336,528656383,SK +528656384,528658431,CZ +528658432,528662527,IR +528662528,528664575,RU +528664576,528666623,BY +528666624,528668671,RU +528668672,528670719,PL +528670720,528674815,CH +528674816,528676863,RO +528676864,528678911,RU +528678912,528680959,MD +528680960,528683007,RO +528683008,528689151,UA 528809984,528812031,PL 528812032,528814079,CZ 528814080,528816127,PL @@ -1478,11 +1505,18 @@ 528836608,528838655,RU 528838656,528840703,UA 528840704,528842751,RU -528875520,528887807,RU +528842752,528859135,CH +528863232,528867327,KZ +528867328,528887807,RU 528887808,528891903,PL 528891904,528900095,UA 528900096,528902143,SK 528902144,528908287,UA +528908288,528926719,RU +528926720,528928767,NL +528928768,528930815,UA +528930816,528932863,CZ +528932864,528941055,RU 529006592,529268735,NL 529268736,529530879,TR 529530880,529596415,UA @@ -1528,7 +1562,8 @@ 530972672,531103743,SA 531103744,531169279,IL 531169280,531177471,KZ -531177472,531183615,GB +531177472,531179519,GB +531181568,531183615,GB 531183616,531185663,NL 531185664,531193855,TR 531193856,531195903,IE @@ -1549,15 +1584,18 @@ 531263488,531265535,RU 531265536,531267583,GB 531267584,531275775,UA -531275776,531277823,LT +531275776,531277823,US 531277824,531279871,RU 531281920,531283967,RU 531283968,531292159,DE 531292160,531333119,AZ 531333120,531333599,NL 531333600,531333631,RU -531333632,531334399,NL -531334400,531334655,SE +531333632,531334143,NL +531334144,531334207,US +531334208,531334399,NL +531334400,531334463,US +531334464,531334655,NL 531334656,531335167,US 531335168,531337215,IT 531337216,531339263,CH @@ -1573,7 +1611,8 @@ 531369984,531371007,CH 531371008,531371519,US 531371520,531372031,JP -531372032,531398655,CH +531372032,531380223,CH +531380224,531398655,DE 531398656,531400703,RU 531400704,531402751,UA 531402752,531404799,LU @@ -1642,7 +1681,9 @@ 532414464,532676607,IT 532676608,532692991,GE 532692992,532701183,CZ -532703232,532705279,RU +532703232,532704511,RU +532704512,532704767,IN +532704768,532705279,RU 532705280,532709375,NL 532709376,532725759,RU 532725760,532729855,SE @@ -1652,7 +1693,15 @@ 532736000,532738047,RU 532738048,532740095,GB 532740096,532742143,KG -532742144,532746239,GB +532742144,532742655,GB +532742656,532742783,CN +532742784,532743167,GB +532743168,532743423,CN +532743424,532743679,GB +532743680,532743807,DE +532743808,532744095,GB +532744096,532744127,CN +532744128,532746239,GB 532746240,532750335,IT 532750336,532752383,SM 532752384,532754431,BE @@ -1684,18 +1733,330 @@ 533250048,533262335,RU 533262336,533264383,ES 533264384,533266431,RU -533266432,533331967,FR +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 +533270784,533271039,DK +533271040,533271295,EE +533271296,533271551,FO +533271552,533271807,GE +533271808,533272063,FR +533272064,533272319,DE +533272320,533272575,GI +533272576,533272831,GR +533272832,533273087,GL +533273088,533273343,GG +533273344,533273599,VA +533273600,533273855,HU +533273856,533274111,IS +533274112,533274367,IR +533274368,533274623,IQ +533274624,533274879,IE +533274880,533275135,IM +533275136,533275391,IL +533275392,533275647,IT +533275648,533275903,JE +533275904,533276159,JO +533276160,533276415,KZ +533276416,533276671,KW +533276672,533276927,KG +533276928,533277183,LV +533277184,533277439,LB +533277440,533277695,LI +533277696,533277951,LT +533277952,533278207,LU +533278208,533278463,MT +533278464,533278719,MC +533278720,533278975,ME +533278976,533279231,NL +533279232,533279487,NO +533279488,533279743,OM +533279744,533279999,PS +533280000,533280255,PL +533280256,533280511,PT +533280512,533280767,RO +533280768,533281023,RU +533281024,533281279,SM +533281280,533281535,SA +533281536,533281791,RS +533281792,533282047,SK +533282048,533282303,SI +533282304,533282559,ES +533282560,533282815,SE +533282816,533283071,CH +533283072,533283327,SY +533283328,533283583,TJ +533283584,533283839,TR +533283840,533284095,TM +533284096,533284351,UA +533284352,533284607,AE +533284608,533284863,GB +533284864,533285119,UZ +533285120,533285375,YE +533285376,533285631,AX +533285632,533285887,AL +533285888,533286143,AD +533286144,533286399,AM +533286400,533286655,AT +533286656,533286911,AZ +533286912,533287167,BH +533287168,533287423,BY +533287424,533287679,BE +533287680,533287935,BA +533287936,533288191,BG +533288192,533288447,HR +533288448,533288703,CY +533288704,533288959,CZ +533288960,533289215,DK +533289216,533289471,EE +533289472,533289727,FO +533289728,533289983,GE +533289984,533290239,FR +533290240,533290495,DE +533290496,533290751,GI +533290752,533291007,GR +533291008,533291263,GL +533291264,533291519,GG +533291520,533291775,VA +533291776,533292031,HU +533292032,533292287,IS +533292288,533292543,IR +533292544,533292799,IQ +533292800,533293055,IE +533293056,533293311,IM +533293312,533293567,IL +533293568,533293823,IT +533293824,533294079,JE +533294080,533294335,JO +533294336,533294591,KZ +533294592,533294847,KW +533294848,533295103,KG +533295104,533295359,LV +533295360,533295615,LB +533295616,533295871,LI +533295872,533296127,LT +533296128,533296383,LU +533296384,533296639,MT +533296640,533296895,MC +533296896,533297151,ME +533297152,533297407,NL +533297408,533297663,NO +533297664,533297919,OM +533297920,533298175,PT +533298176,533298431,RO +533298432,533298687,RU +533298688,533298943,SM +533298944,533299199,SA +533299200,533299455,RS +533299456,533299711,SK +533299712,533299967,SI +533299968,533300223,ES +533300224,533300479,SE +533300480,533300735,CH +533300736,533300991,SY +533300992,533301247,TJ +533301248,533301503,TM +533301504,533301759,UA +533301760,533302015,AE +533302016,533302271,GB +533302272,533302527,UZ +533302528,533302783,AX +533302784,533303039,AL +533303040,533303295,AD +533303296,533303551,AM +533303552,533303807,AT +533303808,533304063,AZ +533304064,533304319,BH +533304320,533304575,BY +533304576,533304831,BE +533304832,533305087,BA +533305088,533305343,BG +533305344,533305599,HR +533305600,533305855,FR +533305856,533306111,CZ +533306112,533306367,FR +533306368,533306623,EE +533306624,533306879,FO +533306880,533307135,GE +533307136,533307391,FR +533307392,533307647,DE +533307648,533307903,GI +533307904,533308159,GR +533308160,533308415,GL +533308416,533308671,GG +533308672,533308927,VA +533308928,533309183,HU +533309184,533309439,IS +533309440,533309695,IR +533309696,533309951,IQ +533309952,533310207,IE +533310208,533310463,IM +533310464,533310719,IL +533310720,533310975,IT +533310976,533311231,JE +533311232,533311487,JO +533311488,533311743,KZ +533311744,533311999,KW +533312000,533312255,KG +533312256,533312511,LV +533312512,533312767,LB +533312768,533313023,LI +533313024,533313279,LT +533313280,533313535,LU +533313536,533313791,MT +533313792,533314047,MC +533314048,533314303,ME +533314304,533314559,NL +533314560,533314815,NO +533314816,533315071,OM +533315072,533315327,PT +533315328,533315583,RO +533315584,533315839,RU +533315840,533316095,SM +533316096,533316351,SA +533316352,533316607,RS +533316608,533316863,SK +533316864,533317119,SI +533317120,533317375,ES +533317376,533317631,SE +533317632,533317887,CH +533317888,533318143,SY +533318144,533318399,TJ +533318400,533318655,TR +533318656,533318911,TM +533318912,533319167,UA +533319168,533319423,AE +533319424,533319679,GB +533319680,533319935,UZ +533319936,533320191,YE +533320192,533320447,AX +533320448,533320703,AL +533320704,533320959,AD +533320960,533321215,AM +533321216,533321471,AT +533321472,533321727,AZ +533321728,533321983,BH +533321984,533322495,BE +533322496,533331967,FR 533331968,533397503,UA 533397504,533463039,KW 533463040,533479423,RU 533481472,533483519,NO 533483520,533485567,FR +533485568,533487615,LU 533487616,533491711,RU 533491712,533495807,DE 533495808,533503999,NL +533504000,533512191,RU 533512192,533528575,ME 533528576,533594111,GB 533594112,533659647,TR +533659648,533676031,CZ +533676032,533680127,RU +533680128,533682175,TR +533682176,533684223,ES +533684224,533692415,IT +533692416,533725183,RU +533725184,533807103,SE +533807104,533811199,LT +533811200,533815295,DE +533815296,533819391,TR +533819392,533823487,DE +533823488,533825535,BE +533827584,533831679,IS +533831680,533835775,DE +533835776,533837823,SE +533837824,533839871,DE +533839872,533856255,IS +533856256,533858303,FR +533858304,533860351,HU +533860352,533860607,DE +533860608,533862399,NL +533862400,533864447,GB +533864448,533889023,TR +533889024,533891071,GB +533891072,533893119,RU +533893120,533895167,ES +533895168,533897215,TR +533897216,533899263,DE +533899264,533901311,RU +533901312,533905407,IL +533905408,533913599,RU +533913600,533915647,ES +533915648,533919743,GB +533919744,533921791,SE +533921792,533954559,RU +533954560,533962751,BG +533962752,533964799,GB +533964800,533966847,NO +533966848,533968895,DE +533968896,533970943,ES +533970944,533987327,SE +533987328,534118399,DE +534118400,534151167,KW +534151168,534183935,DE +534183936,534249471,RO +534249472,534253567,GB +534253568,534257663,FR +534257664,534259711,SE +534259712,534261759,CH +534261760,534263807,GB +534263808,534265855,PL +534265856,534282239,CY +534282240,534284287,IT +534284288,534286335,SE +534286336,534288383,LU +534288384,534290431,IT +534290432,534296575,RU +534296576,534298623,BA +534298624,534306815,HR +534306816,534308863,SE +534308864,534310911,IE +534310912,534315007,IT +534315008,534347775,HR +534380544,534511615,AE +534511616,534544383,DE +534544384,534546431,RO +534546432,534548479,DE +534548480,534550527,PL +534550528,534560767,RU +534560768,534609919,GB +534609920,534642687,ES +534642688,534646783,CZ +534646784,534648831,PL +534648832,534650879,CH +534650880,534652927,RU +534652928,534654975,AL +534654976,534663167,GB +534663168,534675455,ES +534675456,534691839,GB +534691840,534693887,FR +534693888,534695935,GB +534700032,534708223,JO +534708224,534740991,TR +534740992,534749183,BA +534749184,534753279,NL +534753280,534757375,PS +534757376,534761471,KZ +534761472,534765567,BA +534765568,534767615,UA +534767616,534769663,HU +534769664,534773759,IT +534773760,536870911,DE 536870912,539624567,US 539624568,539624575,IE 539624576,539624703,US @@ -1986,6 +2347,8 @@ 692922368,692924415,NG 692924416,692928511,ZA 692928512,692930559,GH +692930560,692932607,UG +692932608,692934655,CM 692969472,692971519,TZ 692973568,692975615,MZ 692975616,692977663,EG @@ -2050,6 +2413,13 @@ 693045248,693046271,KE 693046272,693047295,ZW 693047296,693049343,ZA +693049344,693050367,SD +693050368,693051391,ZW +693051392,693052415,BW +693052416,693054463,ZA +693054464,693055487,BI +693055488,693056511,GQ +693056512,693057535,NA 693101568,693102591,KE 693102592,693103615,CD 693103616,693104639,GN @@ -2533,7 +2903,9 @@ 772057728,772057735,IT 772057736,772076095,DE 772076096,772076103,IT -772076104,772145151,DE +772076104,772076127,DE +772076128,772076159,EG +772076160,772145151,DE 772145152,772210687,ES 772210688,772276223,IE 772276224,772341759,RU @@ -2680,9 +3052,11 @@ 773048320,773050367,LV 773050368,773052415,IE 773052416,773054463,NL -773054464,773055487,AL -773055488,773055743,RS -773055744,773056511,AL +773054464,773054655,AL +773054656,773054719,RS +773054720,773055487,AL +773055488,773055999,RS +773056000,773056511,AL 773056512,773058559,IT 773058560,773060607,BE 773060608,773062655,DK @@ -2723,16 +3097,14 @@ 773152768,773153791,SE 773153792,773154815,US 773154816,773156863,SE -773156864,773160447,FR -773160448,773160703,ES -773160704,773165055,FR -773165056,773168127,NL -773168128,773168639,US -773168640,773168895,NL -773168896,773169151,US -773169152,773169375,NL -773169376,773169407,BE -773169408,773171343,NL +773156864,773157887,FR +773157888,773158911,DE +773158912,773160447,FR +773160448,773160959,ES +773160960,773165055,FR +773165056,773167615,NL +773167616,773169151,US +773169152,773171343,NL 773171344,773171359,BE 773171360,773172223,NL 773172224,773172287,BE @@ -2755,8 +3127,9 @@ 773234688,773238783,PL 773238784,773242879,NL 773242880,773246975,FR -773246976,773247999,EE -773248000,773251071,US +773246976,773247871,EE +773247872,773247999,US +773248000,773251071,EE 773251072,773255167,AZ 773255168,773259263,RU 773259264,773263359,SI @@ -2796,7 +3169,6 @@ 773621760,773623807,PS 773623808,773625855,SE 773625856,773627903,IS -773627904,773629951,TR 773629952,773631999,FR 773632000,773634047,CY 773634048,773636095,DE @@ -2807,7 +3179,9 @@ 773646336,773648383,TR 773648384,773650431,PL 773650432,773652479,GB -773652480,773654527,SK +773652480,773653759,SK +773653760,773653791,CZ +773653792,773654527,SK 773654528,773656575,RU 773656576,773658623,PL 773658624,773660671,DE @@ -2849,8 +3223,7 @@ 773709824,773711871,CZ 773711872,773713919,RU 773713920,773715967,NL -773715968,773716479,EE -773716480,773716991,SE +773715968,773716991,SE 773716992,773718015,US 773718016,773720063,DE 773720064,773722111,GB @@ -2875,12 +3248,10 @@ 773763072,773765119,TR 773765120,773767167,NL 773767168,773769215,GB -773769216,773771263,SE 773771264,773773311,DK 773773312,773775359,IT 773775360,773777407,IQ 773777408,773779455,CZ -773779456,773781503,ME 773781504,773783551,IT 773783552,773785599,RU 773785600,773787647,NL @@ -2925,7 +3296,8 @@ 773898240,773906431,PS 773906432,773922815,GB 773922816,773931007,UA -773931008,773939199,FR +773931008,773934847,DE +773934848,773939199,FR 773939200,773947391,CZ 773947392,773955583,GB 773955584,773963775,FR @@ -2945,11 +3317,16 @@ 774029312,774037503,RO 774037504,774045695,SK 774045696,774053887,FR -774053888,774055935,DE +774053888,774054015,HR +774054016,774055935,DE 774055936,774057983,US 774057984,774058359,DE 774058360,774058367,HR -774058368,774059215,DE +774058368,774058599,DE +774058600,774058603,HR +774058604,774059207,DE +774059208,774059211,HR +774059212,774059215,DE 774059216,774059223,ZA 774059224,774060031,DE 774060032,774060047,ES @@ -3154,7 +3531,26 @@ 774162174,774162176,VA 774162177,774162181,LK 774162182,774162186,IE -774162187,774168575,VA +774162187,774162196,EH +774162197,774162206,NA +774162207,774162216,CX +774162217,774162226,LA +774162227,774162236,GB +774162237,774162246,CH +774162247,774162266,US +774162267,774162276,PT +774162277,774162286,AE +774162287,774162296,IO +774162297,774162306,GU +774162307,774162316,RE +774162317,774162326,TK +774162327,774162336,CV +774162337,774162432,VA +774162433,774162442,GB +774162443,774162452,BA +774162453,774162462,WS +774162463,774162472,SR +774162473,774168575,VA 774168576,774176767,PL 774176768,774184959,IT 774184960,774193151,GB @@ -3243,8 +3639,10 @@ 774219776,774219839,CN 774219840,774219847,UA 774219848,774219855,CN -774219856,774219871,GB -774219872,774219887,CN +774219856,774219863,GB +774219864,774219871,IT +774219872,774219879,RU +774219880,774219887,CN 774219888,774219895,RU 774219896,774219903,LK 774219904,774219967,US @@ -3261,8 +3659,7 @@ 774221568,774221823,US 774221824,774222079,GB 774222080,774222335,US -774222336,774222463,GB -774222464,774222495,CN +774222336,774222495,GB 774222496,774222511,FI 774222512,774222527,CN 774222528,774222591,GB @@ -3271,20 +3668,22 @@ 774222720,774222783,CN 774222784,774222847,GB 774222848,774222863,UA -774222864,774222879,TR +774222864,774222879,IT 774222880,774222895,US 774222896,774222911,GB 774222912,774222943,MA 774222944,774222951,GB 774222952,774222967,CN -774222968,774222975,GB +774222968,774222975,GR 774222976,774223039,CN 774223040,774223071,IT 774223072,774223103,CN 774223104,774223119,UA 774223120,774223151,CN -774223152,774223167,TR -774223168,774223215,GB +774223152,774223167,PK +774223168,774223183,GB +774223184,774223199,PK +774223200,774223215,GB 774223216,774223231,BE 774223232,774223239,CN 774223240,774223247,ME @@ -3303,8 +3702,8 @@ 774223352,774223359,GB 774223360,774223375,UA 774223376,774223391,RU -774223392,774223423,TR -774223424,774223743,GB +774223392,774223407,PK +774223408,774223743,GB 774223744,774223807,US 774223808,774223839,CN 774223840,774223871,US @@ -3346,7 +3745,7 @@ 774224832,774224847,UA 774224848,774224967,GB 774224968,774224975,UA -774224976,774224983,TR +774224976,774224983,RU 774224984,774224991,CN 774224992,774224999,LK 774225000,774225007,CN @@ -3381,10 +3780,10 @@ 774225616,774225647,TR 774225648,774225663,UA 774225664,774225671,LK -774225672,774225679,RU -774225680,774225687,GB -774225688,774225695,CA -774225696,774225727,GB +774225672,774225687,RU +774225688,774225695,PK +774225696,774225703,CN +774225704,774225727,GB 774225728,774225743,LT 774225744,774225791,GB 774225792,774225807,UA @@ -3560,7 +3959,7 @@ 778666392,778666399,PL 778666400,778666479,FR 778666480,778666495,DE -778666496,778666751,FR +778666496,778666751,BE 778666752,778666783,CZ 778666784,778666815,FR 778666816,778666847,GB @@ -3645,15 +4044,16 @@ 778668736,778668799,IT 778668800,778669103,FR 778669104,778669107,PL -778669108,778669119,GB +778669108,778669111,GB +778669112,778669119,NL 778669120,778669151,FI -778669152,778669183,FR -778669184,778669191,DE -778669192,778669199,FR +778669152,778669199,FR 778669200,778669207,PL 778669208,778669211,CH 778669212,778669215,ES -778669216,778669247,GB +778669216,778669223,IE +778669224,778669231,NL +778669232,778669247,PL 778669248,778669295,FR 778669296,778669303,PL 778669304,778669439,FR @@ -3719,10 +4119,9 @@ 778670356,778670359,FR 778670360,778670383,DE 778670384,778670387,PL -778670388,778670395,GB -778670396,778670399,CZ +778670388,778670399,GB 778670400,778670407,PL -778670408,778670411,GB +778670408,778670411,DE 778670412,778670415,NL 778670416,778670431,FR 778670432,778670435,NL @@ -3817,7 +4216,29 @@ 778672920,778672923,FR 778672924,778672927,ES 778672928,778672959,DE -778672960,778698751,FR +778672960,778673071,FR +778673072,778673079,DE +778673080,778673087,GB +778673088,778673119,FR +778673120,778673151,ES +778673152,778673215,FR +778673216,778673247,FI +778673248,778673263,FR +778673264,778673279,IT +778673280,778673343,FR +778673344,778673359,PL +778673360,778673391,GB +778673392,778673407,FR +778673408,778673663,PL +778673664,778673711,FR +778673712,778673715,CH +778673716,778673719,NL +778673720,778673723,PT +778673724,778673727,PL +778673728,778673791,FR +778673792,778673919,GB +778673920,778674175,NL +778674176,778698751,FR 778698752,778764287,TR 778764288,778829823,HU 778829824,778895359,RO @@ -4094,7 +4515,13 @@ 780729600,780729855,JM 780729856,780730111,JO 780730112,780730367,JP -780730368,780795903,IE +780730368,780779519,IE +780779520,780783615,NL +780783616,780785663,GB +780785664,780787711,DE +780787712,780791807,FR +780791808,780793855,SE +780793856,780795903,DE 780795904,780861439,RU 780861440,780926975,HU 780926976,780992511,CH @@ -4195,9 +4622,14 @@ 782664448,782664703,LU 782664704,782664704,GB 782664705,782665471,NL -782665472,782667519,GB +782665472,782666495,US +782666496,782667007,GB +782667008,782667519,RU 782667520,782667775,LU -782667776,782680063,GB +782667776,782668287,FR +782668288,782668799,RU +782668800,782669567,NL +782669568,782680063,GB 782680064,782696447,RU 782696448,782712831,DE 782712832,782729215,RU @@ -4600,7 +5032,13 @@ 787709952,787724287,RU 787724288,787726335,UA 787726336,787742719,RU -787742720,787775487,NL +787742720,787758847,NL +787758848,787759871,GB +787759872,787760895,NL +787760896,787761919,DE +787761920,787762943,NL +787762944,787763967,ES +787763968,787775487,NL 787775488,787808255,DE 787808256,787841023,IR 787841024,787843071,RU @@ -4891,11 +5329,7 @@ 839095808,839096063,CA 839096064,839101695,US 839101696,839102207,CA -839102208,839103999,US -839104000,839104255,CA -839104256,839110143,US -839110144,839110399,CA -839110400,839112447,US +839102208,839112447,US 839112448,839112703,CA 839112704,839113215,US 839113216,839113471,CA @@ -4910,8 +5344,8 @@ 843644928,844890111,US 844890112,844988415,CA 844988416,845283327,US -845283328,845414399,CA -845545472,846200831,US +845283328,845545471,CA +845545472,846331903,US 847249408,855638015,US 855638016,872415231,GB 872415232,889192447,US @@ -5450,7 +5884,9 @@ 1040470400,1040470431,DE 1040470432,1040471487,EU 1040471488,1040471519,NL -1040471520,1040474111,EU +1040471520,1040472575,EU +1040472576,1040472831,DE +1040472832,1040474111,EU 1040474112,1040482303,CZ 1040482304,1040515071,BE 1040515072,1040547839,GB @@ -5499,7 +5935,6 @@ 1041253376,1041268735,RU 1041268736,1041301503,NO 1041301504,1041367039,IE -1041367040,1041498111,GB 1041498112,1041563647,SE 1041563648,1041596415,PL 1041596416,1041629183,NL @@ -5549,8 +5984,8 @@ 1041699768,1041699807,GB 1041699808,1041700423,FR 1041700424,1041700535,GB -1041700536,1041700551,FR -1041700552,1041700607,GB +1041700536,1041700559,FR +1041700560,1041700607,GB 1041700608,1041700983,FR 1041700984,1041700991,GB 1041700992,1041701175,FR @@ -5567,7 +6002,9 @@ 1041701720,1041701727,GB 1041701728,1041701863,FR 1041701864,1041701871,GB -1041701872,1041701967,FR +1041701872,1041701887,FR +1041701888,1041701919,GB +1041701920,1041701967,FR 1041701968,1041701975,GB 1041701976,1041702167,FR 1041702168,1041702175,GB @@ -5579,9 +6016,7 @@ 1041702352,1041702399,GB 1041702400,1041703575,FR 1041703576,1041703583,GB -1041703584,1041703783,FR -1041703784,1041703791,GB -1041703792,1041704119,FR +1041703584,1041704119,FR 1041704120,1041704127,GB 1041704128,1041704159,FR 1041704160,1041704175,GB @@ -5619,8 +6054,8 @@ 1041705392,1041705439,GB 1041705440,1041705447,FR 1041705448,1041705455,GB -1041705456,1041705471,FR -1041705472,1041705479,GB +1041705456,1041705463,FR +1041705464,1041705479,GB 1041705480,1041705487,FR 1041705488,1041705519,GB 1041705520,1041705631,FR @@ -5647,9 +6082,7 @@ 1041706112,1041706143,GB 1041706144,1041706191,FR 1041706192,1041706239,GB -1041706240,1041706359,FR -1041706360,1041706367,GB -1041706368,1041706447,FR +1041706240,1041706447,FR 1041706448,1041706463,GB 1041706464,1041706479,FR 1041706480,1041706487,GB @@ -5785,9 +6218,7 @@ 1041714096,1041714103,GB 1041714104,1041714111,FR 1041714112,1041714175,GB -1041714176,1041714631,FR -1041714632,1041714639,GB -1041714640,1041714655,FR +1041714176,1041714655,FR 1041714656,1041714687,GB 1041714688,1041714775,FR 1041714776,1041714783,GB @@ -5797,8 +6228,8 @@ 1041714856,1041714879,GB 1041714880,1041714911,FR 1041714912,1041714919,GB -1041714920,1041714999,FR -1041715000,1041715015,GB +1041714920,1041715007,FR +1041715008,1041715015,GB 1041715016,1041715079,FR 1041715080,1041715087,GB 1041715088,1041715095,FR @@ -5831,9 +6262,7 @@ 1041716048,1041716095,GB 1041716096,1041716111,FR 1041716112,1041716223,GB -1041716224,1041716231,FR -1041716232,1041716239,GB -1041716240,1041716311,FR +1041716224,1041716311,FR 1041716312,1041716319,GB 1041716320,1041716439,FR 1041716440,1041716447,GB @@ -5917,7 +6346,9 @@ 1041719920,1041719935,GB 1041719936,1041720015,FR 1041720016,1041720031,GB -1041720032,1041720551,FR +1041720032,1041720479,FR +1041720480,1041720511,GB +1041720512,1041720551,FR 1041720552,1041720559,GB 1041720560,1041720567,FR 1041720568,1041720607,GB @@ -5925,7 +6356,9 @@ 1041720632,1041720639,GB 1041720640,1041720687,FR 1041720688,1041720703,GB -1041720704,1041720903,FR +1041720704,1041720831,FR +1041720832,1041720839,GB +1041720840,1041720903,FR 1041720904,1041720927,GB 1041720928,1041721039,FR 1041721040,1041721055,GB @@ -6163,7 +6596,11 @@ 1041737456,1041737463,GB 1041737464,1041737487,FR 1041737488,1041737495,GB -1041737496,1041737583,FR +1041737496,1041737503,FR +1041737504,1041737511,GB +1041737512,1041737527,FR +1041737528,1041737535,GB +1041737536,1041737583,FR 1041737584,1041737599,GB 1041737600,1041737607,FR 1041737608,1041737615,GB @@ -6208,9 +6645,7 @@ 1041738752,1041739079,FR 1041739080,1041739087,GB 1041739088,1041739167,FR -1041739168,1041739207,GB -1041739208,1041739215,FR -1041739216,1041739231,GB +1041739168,1041739231,GB 1041739232,1041739295,FR 1041739296,1041739299,BE 1041739300,1041739303,GB @@ -6228,7 +6663,9 @@ 1041739744,1041739751,GB 1041739752,1041740031,FR 1041740032,1041740039,GB -1041740040,1041740135,FR +1041740040,1041740103,FR +1041740104,1041740119,GB +1041740120,1041740135,FR 1041740136,1041740143,GB 1041740144,1041740263,FR 1041740264,1041740271,GB @@ -6242,7 +6679,9 @@ 1041740672,1041740687,GB 1041740688,1041740703,FR 1041740704,1041740719,GB -1041740720,1041741063,FR +1041740720,1041740807,FR +1041740808,1041740831,GB +1041740832,1041741063,FR 1041741064,1041741087,GB 1041741088,1041741135,FR 1041741136,1041741151,GB @@ -6298,8 +6737,8 @@ 1041743744,1041743759,GB 1041743760,1041743767,FR 1041743768,1041743775,GB -1041743776,1041743791,FR -1041743792,1041743799,GB +1041743776,1041743783,FR +1041743784,1041743799,GB 1041743800,1041743807,FR 1041743808,1041743823,GB 1041743824,1041743831,FR @@ -6732,9 +7171,7 @@ 1043466576,1043466583,NL 1043466584,1043466607,GB 1043466608,1043466887,NL -1043466888,1043466895,GB -1043466896,1043466911,NL -1043466912,1043466927,GB +1043466888,1043466927,GB 1043466928,1043466943,NL 1043466944,1043466991,GB 1043466992,1043467007,NL @@ -6869,7 +7306,104 @@ 1043480352,1043480359,GB 1043480360,1043480363,DE 1043480364,1043480575,GB -1043480576,1043488767,CH +1043480576,1043480687,CH +1043480688,1043480695,GB +1043480696,1043480831,CH +1043480832,1043481855,GB +1043481856,1043482007,CH +1043482008,1043482015,GB +1043482016,1043482079,CH +1043482080,1043482623,GB +1043482624,1043482647,CH +1043482648,1043482667,GB +1043482668,1043482671,CH +1043482672,1043482687,GB +1043482688,1043482719,CH +1043482720,1043482735,GB +1043482736,1043482759,CH +1043482760,1043482783,GB +1043482784,1043482791,CH +1043482792,1043482807,GB +1043482808,1043482895,CH +1043482896,1043482911,GB +1043482912,1043482951,CH +1043482952,1043482959,GB +1043482960,1043482975,CH +1043482976,1043482995,GB +1043482996,1043483039,CH +1043483040,1043483047,GB +1043483048,1043483059,CH +1043483060,1043483063,GB +1043483064,1043483103,CH +1043483104,1043483111,GB +1043483112,1043483231,CH +1043483232,1043483235,GB +1043483236,1043483279,CH +1043483280,1043483295,GB +1043483296,1043483311,CH +1043483312,1043483319,GB +1043483320,1043483327,CH +1043483328,1043483335,GB +1043483336,1043483391,CH +1043483392,1043483655,GB +1043483656,1043483679,CH +1043483680,1043483687,GB +1043483688,1043483759,CH +1043483760,1043483775,GB +1043483776,1043483839,CH +1043483840,1043483871,GB +1043483872,1043483911,CH +1043483912,1043484159,GB +1043484160,1043484191,CH +1043484192,1043484199,GB +1043484200,1043484215,CH +1043484216,1043484223,GB +1043484224,1043484351,CH +1043484352,1043484383,GB +1043484384,1043484431,CH +1043484432,1043484463,GB +1043484464,1043484551,CH +1043484552,1043484559,GB +1043484560,1043484575,CH +1043484576,1043484583,GB +1043484584,1043484623,CH +1043484624,1043484631,GB +1043484632,1043484671,CH +1043484672,1043484679,GB +1043484680,1043484751,CH +1043484752,1043484767,GB +1043484768,1043484799,CH +1043484800,1043484927,GB +1043484928,1043484935,CH +1043484936,1043484943,GB +1043484944,1043484959,CH +1043484960,1043484991,GB +1043484992,1043485055,CH +1043485056,1043485191,GB +1043485192,1043485195,CH +1043485196,1043485439,GB +1043485440,1043485567,CH +1043485568,1043485695,GB +1043485696,1043486239,CH +1043486240,1043486463,GB +1043486464,1043486487,CH +1043486488,1043486719,GB +1043486720,1043486723,CH +1043486724,1043486975,GB +1043486976,1043487039,CH +1043487040,1043487055,GB +1043487056,1043487103,CH +1043487104,1043487231,GB +1043487232,1043487443,CH +1043487444,1043487447,GB +1043487448,1043487455,CH +1043487456,1043487487,GB +1043487488,1043487623,CH +1043487624,1043487631,GB +1043487632,1043487679,CH +1043487680,1043487743,GB +1043487744,1043487751,CH +1043487752,1043488767,GB 1043488768,1043496959,DE 1043496960,1043497055,FR 1043497056,1043497079,GB @@ -7311,7 +7845,9 @@ 1044578304,1044580607,DE 1044580608,1044580735,GB 1044580736,1044580767,DE -1044580768,1044586495,GB +1044580768,1044580863,GB +1044580864,1044581119,DE +1044581120,1044586495,GB 1044586496,1044587007,DE 1044587008,1044587519,GB 1044587520,1044587775,DE @@ -7337,7 +7873,9 @@ 1044592192,1044592255,DE 1044592256,1044592639,GB 1044592640,1044592655,DE -1044592656,1044592831,GB +1044592656,1044592671,GB +1044592672,1044592703,DE +1044592704,1044592831,GB 1044592832,1044594431,DE 1044594432,1044625407,GB 1044625408,1044625463,DE @@ -7350,8 +7888,8 @@ 1044628480,1044629503,GB 1044629504,1044629759,DE 1044629760,1044631551,GB -1044631552,1044631871,DE -1044631872,1044631951,GB +1044631552,1044631903,DE +1044631904,1044631951,GB 1044631952,1044631967,DE 1044631968,1044632063,GB 1044632064,1044633855,DE @@ -7798,9 +8336,7 @@ 1045742116,1045742175,GB 1045742176,1045742191,SE 1045742192,1045742335,GB -1045742336,1045742339,SE -1045742340,1045742343,GB -1045742344,1045742351,SE +1045742336,1045742351,SE 1045742352,1045742367,GB 1045742368,1045742383,SE 1045742384,1045742395,GB @@ -7814,8 +8350,8 @@ 1045742760,1045742831,GB 1045742832,1045742839,SE 1045742840,1045742847,GB -1045742848,1045742975,SE -1045742976,1045743031,GB +1045742848,1045742983,SE +1045742984,1045743031,GB 1045743032,1045743039,SE 1045743040,1045743063,GB 1045743064,1045743071,SE @@ -8427,8 +8963,8 @@ 1046896384,1046897663,GB 1046897664,1046898431,BE 1046898432,1046898687,EU -1046898688,1046898943,BE -1046898944,1046899167,EU +1046898688,1046898975,BE +1046898976,1046899167,EU 1046899168,1046904831,BE 1046904832,1046908927,SK 1046908928,1046910975,SE @@ -8490,19 +9026,11 @@ 1047527424,1047535615,BE 1047535616,1047551999,DE 1047552000,1047560191,RU -1047560192,1047560875,DE -1047560876,1047560879,AU -1047560880,1047561159,DE -1047561160,1047561167,AU -1047561168,1047561367,DE -1047561368,1047561371,CN -1047561372,1047561747,DE +1047560192,1047561747,DE 1047561748,1047561751,ES 1047561752,1047561887,DE 1047561888,1047561891,US -1047561892,1047563227,DE -1047563228,1047563231,CH -1047563232,1047563287,DE +1047561892,1047563287,DE 1047563288,1047563295,CH 1047563296,1047563303,DE 1047563304,1047563311,CH @@ -8527,9 +9055,9 @@ 1047563468,1047563471,CH 1047563472,1047565131,DE 1047565132,1047565135,GB -1047565136,1047565311,DE -1047565312,1047565315,CH -1047565316,1047566363,DE +1047565136,1047565343,DE +1047565344,1047565359,CH +1047565360,1047566363,DE 1047566364,1047566367,CH 1047566368,1047566403,DE 1047566404,1047566415,CH @@ -9498,7 +10026,9 @@ 1049017984,1049018047,GE 1049018048,1049020127,DE 1049020128,1049020135,FR -1049020136,1049026559,DE +1049020136,1049021343,DE +1049021344,1049021375,US +1049021376,1049026559,DE 1049026560,1049026815,EU 1049026816,1049031871,DE 1049031872,1049031903,EU @@ -9625,8 +10155,7 @@ 1049757600,1049757631,LU 1049757632,1049757647,DE 1049757648,1049757663,CA -1049757664,1049757671,BA -1049757672,1049758063,DE +1049757664,1049758063,DE 1049758064,1049758071,PL 1049758072,1049758095,DE 1049758096,1049758103,ES @@ -10027,7 +10556,9 @@ 1052004000,1052004671,EU 1052004672,1052004687,DE 1052004688,1052004703,EU -1052004704,1052004759,DE +1052004704,1052004735,DE +1052004736,1052004751,EU +1052004752,1052004759,DE 1052004760,1052004767,EU 1052004768,1052004783,DE 1052004784,1052004815,EU @@ -10105,7 +10636,9 @@ 1052013964,1052014015,EU 1052014016,1052014079,DE 1052014080,1052014111,EU -1052014112,1052014303,DE +1052014112,1052014239,DE +1052014240,1052014271,EU +1052014272,1052014303,DE 1052014304,1052015367,EU 1052015368,1052015375,DE 1052015376,1052015423,EU @@ -11788,8 +12321,7 @@ 1055253056,1055253087,ES 1055253088,1055256447,EU 1055256448,1055256463,ES -1055256464,1055260671,EU -1055260672,1055326207,SE +1055256464,1055326207,EU 1055326208,1055334399,RU 1055334400,1055342591,IE 1055342592,1055358975,RO @@ -12103,7 +12635,9 @@ 1066584064,1066586111,PE 1066586112,1066604927,US 1066604928,1066604959,CA -1066604960,1067473471,US +1066604960,1066606295,US +1066606296,1066606303,GB +1066606304,1067473471,US 1067473472,1067473535,CA 1067473536,1067474751,US 1067474752,1067474767,NL @@ -12268,7 +12802,9 @@ 1071309696,1071309727,HK 1071309728,1071318783,US 1071318784,1071319039,IN -1071319040,1071362079,US +1071319040,1071321487,US +1071321488,1071321503,HK +1071321504,1071362079,US 1071362080,1071362111,HK 1071362112,1071362207,US 1071362208,1071362239,HK @@ -12359,7 +12895,8 @@ 1072931584,1072931839,SY 1072931840,1072932607,CA 1072932608,1072932863,NG -1072932864,1072934399,CA +1072932864,1072933887,US +1072933888,1072934399,CA 1072934400,1072934655,US 1072934656,1072934783,CA 1072934784,1072934847,AU @@ -12827,10 +13364,8 @@ 1075972352,1075973887,US 1075973888,1075974143,CA 1075974144,1075975167,US -1075975168,1075976031,CA -1075976032,1075976063,US -1075976064,1075976127,CA -1075976128,1075976191,US +1075975168,1075976175,CA +1075976176,1075976191,US 1075976192,1075976511,CA 1075976512,1075976543,US 1075976544,1075976647,CA @@ -12993,9 +13528,7 @@ 1076007248,1076007263,US 1076007264,1076007947,CA 1076007948,1076007951,US -1076007952,1076007967,CA -1076007968,1076007983,US -1076007984,1076008063,CA +1076007952,1076008063,CA 1076008064,1076008191,US 1076008192,1076009631,CA 1076009632,1076009639,US @@ -14163,7 +14696,9 @@ 1077936598,1077936601,CA 1077936602,1077936605,TH 1077936606,1077936609,JO -1077936610,1077936621,US +1077936610,1077936613,US +1077936614,1077936617,UY +1077936618,1077936621,US 1077936622,1077936622,AU 1077936623,1077936630,US 1077936631,1077936634,PE @@ -14472,7 +15007,8 @@ 1077938802,1077938805,US 1077938806,1077938809,DK 1077938810,1077938813,HK -1077938814,1077938831,US +1077938814,1077938829,US +1077938830,1077938831,ES 1077938832,1077938835,CA 1077938836,1077938848,US 1077938849,1077938852,IT @@ -14527,12 +15063,15 @@ 1077939211,1077939218,US 1077939219,1077939219,NL 1077939220,1077939223,CA -1077939224,1077939240,US +1077939224,1077939228,BR +1077939229,1077939240,US 1077939241,1077939244,NL 1077939245,1077939251,US 1077939252,1077939255,BR 1077939256,1077939259,FR -1077939260,1077939304,US +1077939260,1077939263,US +1077939264,1077939267,MY +1077939268,1077939304,US 1077939305,1077939308,GB 1077939309,1077939321,US 1077939322,1077939329,CA @@ -14549,9 +15088,15 @@ 1077939388,1077939391,PK 1077939392,1077939395,US 1077939396,1077939399,SE -1077939400,1077939415,US +1077939400,1077939410,US +1077939411,1077939414,CN +1077939415,1077939415,US 1077939416,1077939423,BE -1077939424,1077939491,US +1077939424,1077939439,US +1077939440,1077939443,IS +1077939444,1077939447,US +1077939448,1077939451,IN +1077939452,1077939491,US 1077939492,1077939495,GB 1077939496,1077939523,US 1077939524,1077939533,CA @@ -15327,7 +15872,9 @@ 1079411456,1079411711,PK 1079411712,1079413311,CA 1079413312,1079413343,US -1079413344,1079414783,CA +1079413344,1079413535,CA +1079413536,1079413567,US +1079413568,1079414783,CA 1079414784,1079415039,US 1079415040,1079415295,HN 1079415296,1079415807,CA @@ -15881,9 +16428,7 @@ 1081912576,1081912639,DE 1081912640,1081927135,US 1081927136,1081927143,GB -1081927144,1081955839,US -1081955840,1081956095,CA -1081956096,1081966871,US +1081927144,1081966871,US 1081966872,1081966879,AS 1081966880,1082091263,US 1082091264,1082091271,CN @@ -15905,7 +16450,19 @@ 1082344785,1082344786,HN 1082344787,1082345733,US 1082345734,1082345737,CA -1082345738,1082348319,US +1082345738,1082346510,US +1082346511,1082346514,IN +1082346515,1082347740,US +1082347741,1082347744,IN +1082347745,1082347760,US +1082347761,1082347763,MX +1082347764,1082347882,US +1082347883,1082347886,IN +1082347887,1082347892,US +1082347893,1082347896,IN +1082347897,1082348005,US +1082348006,1082348009,IN +1082348010,1082348319,US 1082348320,1082348327,GB 1082348328,1082348335,US 1082348336,1082348351,GB @@ -16102,9 +16659,7 @@ 1085685670,1085685685,CA 1085685686,1085698199,US 1085698200,1085698207,AS -1085698208,1085823775,US -1085823776,1085823807,DE -1085823808,1085849599,US +1085698208,1085849599,US 1085849600,1085857791,CA 1085857792,1085915135,US 1085915136,1085923327,PR @@ -16668,16 +17223,14 @@ 1093056144,1093056159,SY 1093056160,1093056167,US 1093056168,1093056175,RO -1093056176,1093056319,US -1093056320,1093056335,CA -1093056336,1093056447,US +1093056176,1093056447,US 1093056448,1093056463,FR 1093056464,1093056479,CA 1093056480,1093056511,US 1093056512,1093056519,GB 1093056520,1093056591,US -1093056592,1093056607,CA -1093056608,1093056959,US +1093056592,1093056599,CA +1093056600,1093056959,US 1093056960,1093056975,SA 1093056976,1093057103,US 1093057104,1093057119,JP @@ -17948,7 +18501,9 @@ 1106349600,1106349607,UM 1106349608,1106428959,US 1106428960,1106428975,UM -1106428976,1106443623,US +1106428976,1106441615,US +1106441616,1106441623,A2 +1106441624,1106443623,US 1106443624,1106443631,CA 1106443632,1106469695,US 1106469696,1106469759,CO @@ -18937,9 +19492,7 @@ 1117829376,1117829631,GR 1117829632,1117831359,US 1117831360,1117831423,A2 -1117831424,1117832191,US -1117832192,1117832447,IT -1117832448,1117978623,US +1117831424,1117978623,US 1117978624,1117979503,CA 1117979504,1117979519,US 1117979520,1117982639,CA @@ -19200,7 +19753,9 @@ 1118793824,1118793839,CA 1118793840,1118793935,US 1118793936,1118793951,ES -1118793952,1118794287,US +1118793952,1118793967,US +1118793968,1118793983,HT +1118793984,1118794287,US 1118794288,1118794303,BR 1118794304,1118794799,US 1118794800,1118794815,PR @@ -21004,7 +21559,8 @@ 1125455616,1125455871,A2 1125455872,1125456131,US 1125456132,1125456135,NO -1125456136,1125456151,US +1125456136,1125456139,A2 +1125456140,1125456151,US 1125456152,1125456155,NL 1125456156,1125456163,US 1125456164,1125456167,NO @@ -22397,12 +22953,16 @@ 1138271088,1138271103,TN 1138271104,1138337167,US 1138337168,1138337183,GB -1138337184,1138417663,US +1138337184,1138337199,US +1138337200,1138337207,SG +1138337208,1138417663,US 1138417664,1138417695,CA 1138417696,1138417727,DE 1138417728,1138421759,US 1138421760,1138421791,DE -1138421792,1138425855,US +1138421792,1138422783,US +1138422784,1138423039,PA +1138423040,1138425855,US 1138425856,1138427519,KN 1138427520,1138427647,US 1138427648,1138429951,KN @@ -22821,8 +23381,8 @@ 1145333864,1145333871,EG 1145333872,1145333879,US 1145333880,1145333903,CN -1145333904,1145334143,US -1145334144,1145334167,CN +1145333904,1145334151,US +1145334152,1145334167,CN 1145334168,1145334175,US 1145334176,1145334223,CN 1145334224,1145334231,US @@ -22933,7 +23493,9 @@ 1157670432,1157670463,CA 1157670464,1157713663,US 1157713664,1157713791,CA -1157713792,1157755247,US +1157713792,1157753087,US +1157753088,1157753343,GB +1157753344,1157755247,US 1157755248,1157755263,GR 1157755264,1157758207,US 1157758208,1157758463,RU @@ -24165,8 +24727,7 @@ 1161628648,1161628663,US 1161628664,1161628671,AR 1161628672,1161629199,US -1161629200,1161629207,SI -1161629208,1161629215,HR +1161629200,1161629215,SI 1161629216,1161629223,US 1161629224,1161629231,GB 1161629232,1161629239,US @@ -24180,8 +24741,9 @@ 1161629392,1161629399,IE 1161629400,1161629407,IL 1161629408,1161629415,GB -1161629416,1161629423,HR -1161629424,1161629439,MY +1161629416,1161629423,SI +1161629424,1161629431,US +1161629432,1161629439,MY 1161629440,1161629519,US 1161629520,1161629527,GB 1161629528,1161629535,MY @@ -24194,14 +24756,17 @@ 1161629952,1161630263,US 1161630264,1161630271,AR 1161630272,1161630335,US -1161630336,1161630343,PL -1161630344,1161630367,US +1161630336,1161630343,AR +1161630344,1161630351,IL +1161630352,1161630367,US 1161630368,1161630375,GB 1161630376,1161630383,US 1161630384,1161630391,AR 1161630392,1161630399,US 1161630400,1161630431,GB -1161630432,1161630727,US +1161630432,1161630455,US +1161630456,1161630463,NL +1161630464,1161630727,US 1161630728,1161630735,EG 1161630736,1161630743,AU 1161630744,1161630751,GB @@ -24507,7 +25072,7 @@ 1161653760,1161653791,US 1161653792,1161653799,SI 1161653800,1161653831,US -1161653832,1161653839,HR +1161653832,1161653839,SI 1161653840,1161653847,US 1161653848,1161653855,SI 1161653856,1161653887,US @@ -24851,10 +25416,14 @@ 1163403264,1163407359,US 1163407360,1163411455,CA 1163411456,1163468799,US -1163468800,1163472895,PR +1163468800,1163469055,PR +1163469056,1163469311,US +1163469312,1163472895,PR 1163472896,1163477695,US 1163477696,1163477727,JP -1163477728,1163526143,US +1163477728,1163478047,US +1163478048,1163478063,JP +1163478064,1163526143,US 1163526144,1163526463,CA 1163526464,1163526655,US 1163526656,1163527023,CA @@ -24869,8 +25438,8 @@ 1163527776,1163527791,US 1163527792,1163529215,CA 1163529216,1163530239,US -1163530240,1163530399,CA -1163530400,1163530431,US +1163530240,1163530415,CA +1163530416,1163530431,US 1163530432,1163530639,CA 1163530640,1163530655,US 1163530656,1163530839,CA @@ -25147,7 +25716,9 @@ 1163876472,1163876479,PA 1163876480,1163878399,US 1163878400,1163878407,CN -1163878408,1167321959,US +1163878408,1167319111,US +1167319112,1167319119,ZA +1167319120,1167321959,US 1167321960,1167321967,GB 1167321968,1167322695,US 1167322696,1167322703,IN @@ -25242,7 +25813,9 @@ 1168954016,1168954047,IN 1168954048,1168954075,US 1168954076,1168954079,CA -1168954080,1168955647,US +1168954080,1168954623,US +1168954624,1168954687,IN +1168954688,1168955647,US 1168955648,1168956159,CA 1168956160,1168957439,US 1168957440,1168958047,CA @@ -25260,7 +25833,9 @@ 1168958232,1168958423,CA 1168958424,1168958463,US 1168958464,1168958479,CA -1168958480,1168960543,US +1168958480,1168958495,US +1168958496,1168958559,IN +1168958560,1168960543,US 1168960544,1168960591,CA 1168960592,1168960607,US 1168960608,1168960623,CA @@ -25379,14 +25954,12 @@ 1170539911,1170539911,KH 1170539912,1170539969,US 1170539970,1170539970,KH -1170539971,1170539971,TR -1170539972,1170540036,US +1170539971,1170540036,US 1170540037,1170540037,TR 1170540038,1170540038,US 1170540039,1170540039,PH 1170540040,1170540096,US -1170540097,1170540097,CN -1170540098,1170540098,TR +1170540097,1170540098,TR 1170540099,1170540105,US 1170540106,1170540106,CN 1170540107,1170540163,US @@ -25499,7 +26072,9 @@ 1170554496,1170554683,US 1170554684,1170554687,TR 1170554688,1170573375,US -1170573376,1170573439,RU +1170573376,1170573391,RU +1170573392,1170573392,US +1170573393,1170573439,RU 1170573440,1175977983,US 1175977984,1176068167,CA 1176068168,1176068175,US @@ -25516,7 +26091,9 @@ 1176108560,1176502271,CA 1176502272,1176512151,US 1176512152,1176512159,GB -1176512160,1176513879,US +1176512160,1176512703,US +1176512704,1176512711,ZA +1176512712,1176513879,US 1176513880,1176513887,GB 1176513888,1176514271,US 1176514272,1176514303,IN @@ -25549,12 +26126,16 @@ 1176620992,1176620999,US 1176621000,1176621599,CA 1176621600,1176621631,US -1176621632,1176621679,CA -1176621680,1176621823,US +1176621632,1176621695,CA +1176621696,1176621727,US +1176621728,1176621759,CA +1176621760,1176621823,US 1176621824,1176621855,CA -1176621856,1176621887,US -1176621888,1176621951,CA -1176621952,1176622079,US +1176621856,1176621863,US +1176621864,1176621871,CA +1176621872,1176621887,US +1176621888,1176622047,CA +1176622048,1176622079,US 1176622080,1176622335,GB 1176622336,1176622591,US 1176622592,1176623359,CA @@ -25595,7 +26176,9 @@ 1176686592,1176686599,PK 1176686600,1176686623,US 1176686624,1176686631,IL -1176686632,1176686719,US +1176686632,1176686639,US +1176686640,1176686647,DE +1176686648,1176686719,US 1176686720,1176686751,CA 1176686752,1176686847,US 1176686848,1176687103,AN @@ -25852,10 +26435,8 @@ 1177053696,1177053951,GB 1177053952,1177059327,US 1177059328,1177061375,CA -1177061376,1177062399,US -1177062400,1177074943,CA -1177074944,1177075199,US -1177075200,1177075455,CA +1177061376,1177062143,US +1177062144,1177075455,CA 1177075456,1177164255,US 1177164256,1177164263,CA 1177164264,1177164415,US @@ -26690,9 +27271,7 @@ 1209270584,1209270607,US 1209270608,1209270611,KR 1209270612,1209270615,CN -1209270616,1209270783,US -1209270784,1209270787,TR -1209270788,1209271067,US +1209270616,1209271067,US 1209271068,1209271071,VN 1209271072,1209271083,US 1209271084,1209271087,BR @@ -28161,14 +28740,76 @@ 1247070816,1247070831,CA 1247070832,1247072719,US 1247072720,1247072735,NL -1247072736,1248864255,US +1247072736,1247481855,US +1247481856,1247481863,CN +1247481864,1247481871,CO +1247481872,1247481879,TR +1247481880,1247481887,US +1247481888,1247481903,CN +1247481904,1247481911,BO +1247481912,1247481927,CN +1247481928,1247481951,US +1247481952,1247481967,CN +1247481968,1247481983,US +1247481984,1247482015,GB +1247482016,1247482047,CN +1247482048,1247482063,CA +1247482064,1247482071,BO +1247482072,1247482079,US +1247482080,1247482175,CN +1247482176,1247482239,US +1247482240,1247482255,GB +1247482256,1247482319,CN +1247482320,1247482335,US +1247482336,1247482351,CN +1247482352,1247482367,US +1247482368,1247482383,GB +1247482384,1247482543,CN +1247482544,1247482551,US +1247482552,1247482559,CN +1247482560,1247482567,US +1247482568,1247482583,CN +1247482584,1247482607,US +1247482608,1247482623,CN +1247482624,1247482687,US +1247482688,1247482751,CA +1247482752,1247482815,US +1247482816,1247482879,CN +1247482880,1247482927,US +1247482928,1247482951,BO +1247482952,1247482967,US +1247482968,1247482975,CN +1247482976,1247483015,US +1247483016,1247483039,CN +1247483040,1247483047,CA +1247483048,1247483079,US +1247483080,1247483095,CN +1247483096,1247483111,US +1247483112,1247483119,CN +1247483120,1247483647,US +1247483648,1247484671,CN +1247484672,1247484927,US +1247484928,1247485191,CN +1247485192,1247485231,US +1247485232,1247485263,CN +1247485264,1247485439,US +1247485440,1247485543,CN +1247485544,1247485615,US +1247485616,1247485639,CN +1247485640,1247485647,US +1247485648,1247485951,CN +1247485952,1248864255,US 1248864256,1248866303,CA 1248866304,1248885759,US 1248885760,1248886783,CA 1248886784,1248899071,US 1248899072,1248900095,CA -1248900096,1248913407,US -1248913408,1248915455,GP +1248900096,1248903695,US +1248903696,1248903711,ZA +1248903712,1248903775,US +1248903776,1248903791,FR +1248903792,1248913407,US +1248913408,1248915455,MF 1248915456,1248919551,US 1248919552,1248920575,CA 1248920576,1248921599,US @@ -28189,7 +28830,9 @@ 1249019904,1249020927,CA 1249020928,1249026423,US 1249026424,1249026431,CA -1249026432,1249026703,US +1249026432,1249026455,US +1249026456,1249026463,ES +1249026464,1249026703,US 1249026704,1249026711,ZA 1249026712,1249026719,CA 1249026720,1249026767,US @@ -28234,7 +28877,8 @@ 1249092608,1249099775,US 1249099776,1249101823,CA 1249101824,1249102847,PR -1249102848,1249103871,CA +1249102848,1249103103,US +1249103104,1249103871,CA 1249103872,1249103887,TW 1249103888,1249103951,US 1249103952,1249103967,TW @@ -28292,12 +28936,50 @@ 1249217536,1249218559,CA 1249218560,1249221887,US 1249221888,1249222655,RO -1249222656,1249236991,US +1249222656,1249227007,US +1249227008,1249227071,CY +1249227072,1249227135,VG +1249227136,1249227167,US +1249227168,1249227199,VG +1249227200,1249227263,HK +1249227264,1249227519,VG +1249227520,1249228031,US +1249228032,1249228063,CZ +1249228064,1249228095,US +1249228096,1249228223,UA +1249228224,1249228239,CZ +1249228240,1249228287,US +1249228288,1249228351,SC +1249228352,1249229007,US +1249229008,1249229008,CA +1249229009,1249229087,US +1249229088,1249229095,CA +1249229096,1249229216,US +1249229217,1249229217,CA +1249229218,1249229289,US +1249229290,1249229291,CA +1249229292,1249236991,US 1249236992,1249239039,KY 1249239040,1249245183,US 1249245184,1249247231,CA 1249247232,1249256447,US -1249256448,1249257471,CA +1249256448,1249256500,CA +1249256501,1249256542,GB +1249256543,1249256713,CA +1249256714,1249256773,US +1249256774,1249256988,CA +1249256989,1249256998,US +1249256999,1249256999,CA +1249257000,1249257009,LB +1249257010,1249257017,CA +1249257018,1249257042,US +1249257043,1249257052,CA +1249257053,1249257062,US +1249257063,1249257121,CA +1249257122,1249257131,LB +1249257132,1249257348,CA +1249257349,1249257412,US +1249257413,1249257471,CA 1249257472,1249260543,US 1249260544,1249261567,CA 1249261568,1249272831,US @@ -28310,7 +28992,13 @@ 1249335296,1249337343,CA 1249337344,1249359871,US 1249359872,1249361919,CA -1249361920,1249384447,US +1249361920,1249381503,US +1249381504,1249381519,DE +1249381520,1249381759,US +1249381760,1249381775,DE +1249381776,1249382287,US +1249382288,1249382303,DE +1249382304,1249384447,US 1249384448,1249386495,PR 1249386496,1249391615,US 1249391616,1249392639,CA @@ -28332,7 +29020,9 @@ 1249474560,1249475583,CA 1249475584,1249484799,US 1249484800,1249486847,CA -1249486848,1249506303,US +1249486848,1249492735,US +1249492736,1249492991,CA +1249492992,1249506303,US 1249506304,1249507327,CA 1249507328,1249522687,US 1249522688,1249523711,CA @@ -28340,15 +29030,17 @@ 1249531904,1249533951,GD 1249533952,1249542143,US 1249542144,1249544191,CA -1249544192,1249562623,US +1249544192,1249550367,US +1249550368,1249550375,HK +1249550376,1249562623,US 1249562624,1249564671,CA 1249564672,1249568319,US 1249568320,1249568327,NL 1249568328,1249571839,US 1249571840,1249572863,CA 1249572864,1249577087,US -1249577088,1249577279,CA -1249577280,1249577343,US +1249577088,1249577232,CA +1249577233,1249577343,US 1249577344,1249577480,CA 1249577481,1249577545,US 1249577546,1249577730,CA @@ -28429,15 +29121,15 @@ 1254604192,1254604199,IE 1254604200,1254621183,US 1254621184,1254629375,CA -1254629376,1254704383,US +1254629376,1254688511,US +1254688512,1254688543,CA +1254688544,1254704383,US 1254704384,1254704639,PH 1254704640,1254704903,US 1254704904,1254704911,PH 1254704912,1254713359,US 1254713360,1254713407,CA -1254713408,1254725119,US -1254725120,1254725151,GB -1254725152,1254924687,US +1254713408,1254924687,US 1254924688,1254924703,RO 1254924704,1254948927,US 1254948928,1254948935,SG @@ -28450,9 +29142,7 @@ 1254950208,1254950671,US 1254950672,1254950679,RU 1254950680,1254950687,CA -1254950688,1254950719,US -1254950720,1254950727,SG -1254950728,1254950751,US +1254950688,1254950751,US 1254950752,1254950759,IL 1254950760,1254950767,US 1254950768,1254950775,GR @@ -28545,7 +29235,9 @@ 1254954664,1254954671,GB 1254954672,1254954887,US 1254954888,1254954895,IL -1254954896,1254955599,US +1254954896,1254955103,US +1254955104,1254955111,GB +1254955112,1254955599,US 1254955600,1254955607,GB 1254955608,1254955735,US 1254955736,1254955743,GB @@ -28676,7 +29368,9 @@ 1254964344,1254964351,PR 1254964352,1254964391,US 1254964392,1254964399,AU -1254964400,1254964799,US +1254964400,1254964639,US +1254964640,1254964671,AU +1254964672,1254964799,US 1254964800,1254964815,CA 1254964816,1254964927,US 1254964928,1254964943,CA @@ -28986,7 +29680,8 @@ 1255059168,1255059327,US 1255059328,1255059343,NL 1255059344,1255059359,US -1255059360,1255059407,CA +1255059360,1255059391,CA +1255059392,1255059407,US 1255059408,1255059423,AR 1255059424,1255060159,US 1255060160,1255060191,NL @@ -29004,9 +29699,7 @@ 1255061984,1255062015,CA 1255062016,1255062463,US 1255062464,1255062527,PA -1255062528,1255062591,US -1255062592,1255062607,CA -1255062608,1255062847,US +1255062528,1255062847,US 1255062848,1255062863,CA 1255062864,1255063551,US 1255063552,1255071743,PR @@ -29036,13 +29729,19 @@ 1255750240,1255750271,AU 1255750272,1255753215,US 1255753216,1255753471,GB -1255753472,1255768063,US +1255753472,1255756799,US +1255756800,1255756815,CA +1255756816,1255768063,US 1255768064,1255768575,CA 1255768576,1255770367,US 1255770368,1255770623,CA -1255770624,1255780351,US +1255770624,1255776431,US +1255776432,1255776439,LB +1255776440,1255780351,US 1255780352,1255782399,CA -1255782400,1255796743,US +1255782400,1255792127,US +1255792128,1255792383,IL +1255792384,1255796743,US 1255796744,1255796751,GB 1255796752,1255972863,US 1255972864,1255981055,CA @@ -29062,7 +29761,9 @@ 1263264000,1263264127,CA 1263264128,1263264305,US 1263264306,1263264321,PK -1263264322,1263266623,US +1263264322,1263264511,US +1263264512,1263264767,CA +1263264768,1263266623,US 1263266624,1263266655,CA 1263266656,1263267327,US 1263267328,1263267583,CA @@ -29587,7 +30288,9 @@ 1279962912,1279962927,CN 1279962928,1279962943,US 1279962944,1279962975,CN -1279962976,1279963935,US +1279962976,1279963135,US +1279963136,1279963391,IN +1279963392,1279963935,US 1279963936,1279963967,CA 1279963968,1279965183,US 1279965184,1279966207,CA @@ -29881,7 +30584,8 @@ 1296238592,1296239103,NL 1296239104,1296239231,FR 1296239232,1296239359,NL -1296239360,1296240127,FR +1296239360,1296239615,DE +1296239616,1296240127,FR 1296240128,1296241151,BE 1296241152,1296241407,IT 1296241408,1296242175,NL @@ -29912,7 +30616,9 @@ 1296248384,1296248447,IT 1296248448,1296248575,US 1296248576,1296248703,IE -1296248704,1296249855,FR +1296248704,1296248959,FR +1296248960,1296249024,DE +1296249025,1296249855,FR 1296249856,1296249887,US 1296249888,1296249951,FR 1296249952,1296250015,DE @@ -29936,7 +30642,9 @@ 1296251328,1296251359,IE 1296251360,1296251391,DE 1296251392,1296251775,NL -1296251776,1296252039,FR +1296251776,1296252015,FR +1296252016,1296252031,US +1296252032,1296252039,FR 1296252040,1296252055,DE 1296252056,1296252063,BE 1296252064,1296252079,IT @@ -29992,7 +30700,7 @@ 1296258048,1296258303,TW 1296258304,1296259071,NL 1296259072,1296259583,US -1296259584,1296259839,FR +1296259584,1296259839,DE 1296259840,1296260351,NL 1296260352,1296260607,US 1296260608,1296262143,DE @@ -30048,9 +30756,7 @@ 1296465920,1296466239,NG 1296466240,1296466303,NO 1296466304,1296466335,BF -1296466336,1296466367,NO -1296466368,1296466383,AO -1296466384,1296466399,NO +1296466336,1296466399,NO 1296466400,1296466415,AO 1296466416,1296466431,NG 1296466432,1296466447,TZ @@ -30078,8 +30784,8 @@ 1296472416,1296473087,NO 1296473088,1296474623,LT 1296474624,1296476159,US -1296476160,1296480255,LT -1296480256,1296482303,NO +1296476160,1296479743,LT +1296479744,1296482303,NO 1296482304,1296498687,LT 1296498688,1296531455,BG 1296531456,1296564223,MT @@ -30172,9 +30878,7 @@ 1296678152,1296678159,A2 1296678160,1296678215,NG 1296678216,1296678223,A2 -1296678224,1296678319,NG -1296678320,1296678327,A2 -1296678328,1296678351,NG +1296678224,1296678351,NG 1296678352,1296678367,A2 1296678368,1296678415,NG 1296678416,1296678431,A2 @@ -30187,7 +30891,10 @@ 1296678792,1296678831,NG 1296678832,1296678839,A2 1296678840,1296678911,NG -1296678912,1296680959,SA +1296678912,1296680191,SA +1296680192,1296680447,AE +1296680448,1296680703,KW +1296680704,1296680959,SA 1296680960,1296683007,ES 1296683008,1296685055,IE 1296685056,1296687103,TR @@ -30232,7 +30939,6 @@ 1296754688,1296756735,DE 1296756736,1296758783,FR 1296758784,1296760831,RS -1296760832,1296762879,GB 1296762880,1296764927,RU 1296764928,1296769023,AT 1296769024,1296771071,TR @@ -30712,8 +31418,16 @@ 1307803648,1307807743,DK 1307807744,1307811839,SE 1307811840,1307815935,NL -1307815936,1307819791,BE -1307819792,1307820031,EU +1307815936,1307816191,EU +1307816192,1307816447,GB +1307816448,1307818239,EU +1307818240,1307818495,GB +1307818496,1307818751,DE +1307818752,1307819007,ES +1307819008,1307819263,DE +1307819264,1307819519,NL +1307819520,1307819775,BE +1307819776,1307820031,IT 1307820032,1307824127,ES 1307824128,1307828223,HU 1307828224,1307830128,NL @@ -30826,9 +31540,7 @@ 1308073984,1308078079,RU 1308078080,1308078879,NL 1308078880,1308078911,FR -1308078912,1308079519,NL -1308079520,1308079535,DE -1308079536,1308080127,NL +1308078912,1308080127,NL 1308080128,1308082175,RU 1308082176,1308084223,GB 1308084224,1308086271,RS @@ -30836,7 +31548,6 @@ 1308088320,1308090367,UA 1308090368,1308092415,SK 1308092416,1308094463,RU -1308094464,1308096511,KW 1308096512,1308098559,RS 1308098560,1308360703,NL 1308360704,1308622847,PL @@ -31113,7 +31824,9 @@ 1311263424,1311263615,CH 1311263616,1311263743,FR 1311263744,1311263871,CH -1311263872,1311264767,FR +1311263872,1311263999,FR +1311264000,1311264015,CH +1311264016,1311264767,FR 1311264768,1311266815,RU 1311266816,1311268863,FR 1311268864,1311270911,BE @@ -31508,7 +32221,7 @@ 1317650432,1317666815,RU 1317666816,1317666823,IQ 1317666824,1317666831,CD -1317666832,1317666839,NG +1317666832,1317666839,A2 1317666840,1317666855,GH 1317666856,1317666863,A2 1317666864,1317666871,GH @@ -31567,7 +32280,8 @@ 1317667760,1317667767,FR 1317667768,1317667775,ZA 1317667776,1317667783,US -1317667784,1317667799,NG +1317667784,1317667791,AO +1317667792,1317667799,NG 1317667800,1317667807,A2 1317667808,1317667815,NG 1317667816,1317668095,A2 @@ -31656,9 +32370,7 @@ 1317669960,1317669983,A2 1317669984,1317669991,LR 1317669992,1317669999,NG -1317670000,1317670007,A2 -1317670008,1317670015,NG -1317670016,1317670063,A2 +1317670000,1317670063,A2 1317670064,1317670103,NG 1317670104,1317670135,A2 1317670136,1317670143,NG @@ -31692,8 +32404,8 @@ 1317670648,1317670655,NG 1317670656,1317670663,AO 1317670664,1317670679,A2 -1317670680,1317670695,NG -1317670696,1317670711,A2 +1317670680,1317670703,NG +1317670704,1317670711,A2 1317670712,1317670719,GH 1317670720,1317670727,A2 1317670728,1317670735,GH @@ -31765,7 +32477,8 @@ 1317671920,1317671927,NG 1317671928,1317671935,A2 1317671936,1317672447,GA -1317672448,1317672463,A2 +1317672448,1317672455,A2 +1317672456,1317672463,GA 1317672464,1317672471,NG 1317672472,1317672479,A2 1317672480,1317672487,ZM @@ -31952,8 +32665,7 @@ 1317675544,1317675551,IQ 1317675552,1317675559,NG 1317675560,1317675567,NA -1317675568,1317675583,A2 -1317675584,1317675591,LR +1317675568,1317675591,A2 1317675592,1317675607,NG 1317675608,1317675623,A2 1317675624,1317675639,NG @@ -31973,7 +32685,8 @@ 1317675776,1317675783,NG 1317675784,1317675799,A2 1317675800,1317675807,GB -1317675808,1317675823,A2 +1317675808,1317675815,NG +1317675816,1317675823,A2 1317675824,1317675847,NG 1317675848,1317675855,A2 1317675856,1317675863,NG @@ -31992,9 +32705,8 @@ 1317676008,1317676015,GH 1317676016,1317676023,SD 1317676024,1317676031,GQ -1317676032,1317676039,A2 -1317676040,1317676047,CD -1317676048,1317676055,A2 +1317676032,1317676039,NG +1317676040,1317676055,A2 1317676056,1317676063,NG 1317676064,1317676079,A2 1317676080,1317676087,AO @@ -32013,7 +32725,7 @@ 1317676192,1317676207,SD 1317676208,1317676215,A2 1317676216,1317676223,NG -1317676224,1317676231,A2 +1317676224,1317676231,GH 1317676232,1317676239,NG 1317676240,1317676247,SD 1317676248,1317676255,NG @@ -32059,7 +32771,7 @@ 1317676944,1317676951,CM 1317676952,1317676983,A2 1317676984,1317676991,NG -1317676992,1317676999,LR +1317676992,1317676999,A2 1317677000,1317677007,IQ 1317677008,1317677015,CD 1317677016,1317677023,A2 @@ -32076,7 +32788,8 @@ 1317677128,1317677135,NG 1317677136,1317677191,A2 1317677192,1317677199,SD -1317677200,1317677215,NG +1317677200,1317677207,A2 +1317677208,1317677215,NG 1317677216,1317677231,A2 1317677232,1317677239,UG 1317677240,1317677247,A2 @@ -32140,15 +32853,14 @@ 1317678224,1317678231,NG 1317678232,1317678239,BF 1317678240,1317678247,CD -1317678248,1317678271,A2 +1317678248,1317678255,TD +1317678256,1317678271,A2 1317678272,1317678287,NG 1317678288,1317678295,GR 1317678296,1317678311,A2 1317678312,1317678319,SD 1317678320,1317678327,NG -1317678328,1317678335,A2 -1317678336,1317678343,NG -1317678344,1317678351,A2 +1317678328,1317678351,A2 1317678352,1317678359,CD 1317678360,1317678367,NG 1317678368,1317678375,CD @@ -32179,7 +32891,7 @@ 1317679632,1317679639,NG 1317679640,1317679647,ZW 1317679648,1317679655,CD -1317679656,1317679663,A2 +1317679656,1317679663,NG 1317679664,1317679671,AO 1317679672,1317679687,NG 1317679688,1317679695,A2 @@ -32192,7 +32904,9 @@ 1317679768,1317679775,A2 1317679776,1317679799,NG 1317679800,1317679807,A2 -1317679808,1317679847,NG +1317679808,1317679831,NG +1317679832,1317679839,A2 +1317679840,1317679847,NG 1317679848,1317679855,A2 1317679856,1317679871,NG 1317679872,1317681183,A2 @@ -32208,9 +32922,7 @@ 1317686304,1317686319,NL 1317686320,1317686335,DE 1317686336,1317686399,NL -1317686400,1317695743,DE -1317695744,1317695999,CH -1317696000,1317698559,DE +1317686400,1317698559,DE 1317698560,1317698687,NL 1317698688,1317699583,DE 1317699584,1317715967,RU @@ -32243,7 +32955,9 @@ 1317836864,1317836927,CY 1317836928,1317836991,NL 1317836992,1317837007,GB -1317837008,1317838943,NL +1317837008,1317837567,NL +1317837568,1317837823,US +1317837824,1317838943,NL 1317838944,1317838959,GB 1317838960,1317838975,NL 1317838976,1317839103,GI @@ -32285,8 +32999,8 @@ 1317994496,1317995519,NL 1317995520,1317996095,DE 1317996096,1317996287,NL -1317996288,1317998079,DE -1317998080,1317998591,NL +1317996288,1317998207,DE +1317998208,1317998591,NL 1317998592,1318000383,DE 1318000384,1318000447,NL 1318000448,1318002175,DE @@ -32382,8 +33096,9 @@ 1318936576,1318944767,DK 1318944768,1318956287,CZ 1318956288,1318957055,PL -1318957056,1318958847,CZ -1318958848,1318961151,PL +1318957056,1318958079,CZ +1318958080,1318960895,PL +1318960896,1318961151,CZ 1318961152,1318969343,NL 1318969344,1318977535,RU 1318977536,1318985727,LT @@ -32567,7 +33282,10 @@ 1332412416,1332477951,GR 1332477952,1332609023,ES 1332609024,1332613119,PL -1332613120,1332629503,UA +1332613120,1332617215,UA +1332617216,1332621311,CZ +1332621312,1332625407,UA +1332625408,1332629503,RU 1332629504,1332633599,DE 1332633600,1332637695,UA 1332637696,1332641791,BG @@ -32691,8 +33409,8 @@ 1334647808,1334648063,LB 1334648064,1334648319,IQ 1334648320,1334648831,A2 -1334648832,1334651391,GB -1334651392,1334651647,NL +1334648832,1334651455,GB +1334651456,1334651647,NL 1334651648,1334651903,FR 1334651904,1334652159,DE 1334652160,1334652543,GB @@ -32730,8 +33448,8 @@ 1334725632,1334726143,SE 1334726144,1334726655,NL 1334726656,1334729983,RU -1334729984,1334730015,KZ -1334730016,1334730239,RU +1334729984,1334730027,KZ +1334730028,1334730239,RU 1334730240,1334730431,KZ 1334730432,1334730439,RU 1334730440,1334730443,KZ @@ -32745,8 +33463,8 @@ 1334730544,1334730579,KZ 1334730580,1334730583,RU 1334730584,1334730667,KZ -1334730668,1334730679,RU -1334730680,1334730751,KZ +1334730668,1334730671,RU +1334730672,1334730751,KZ 1334730752,1334734847,RU 1334734848,1334738943,LT 1334738944,1334743039,CH @@ -32816,7 +33534,6 @@ 1336614912,1336616959,GB 1336616960,1336619007,ES 1336619008,1336621055,AL -1336621056,1336623103,IT 1336623104,1336625151,BE 1336625152,1336625823,IE 1336625824,1336625839,GB @@ -33070,7 +33787,12 @@ 1346699756,1346699756,LI 1346699757,1346699767,GB 1346699768,1346699775,US -1346699776,1346700575,GB +1346699776,1346699839,GB +1346699840,1346699871,HK +1346699872,1346699875,GB +1346699876,1346699879,IL +1346699880,1346699887,US +1346699888,1346700575,GB 1346700576,1346700591,VG 1346700592,1346700607,GB 1346700608,1346700623,US @@ -33095,7 +33817,9 @@ 1346704640,1346704767,LI 1346704768,1346705247,GB 1346705248,1346705279,US -1346705280,1346707455,GB +1346705280,1346705407,GB +1346705408,1346705535,US +1346705536,1346707455,GB 1346707456,1346711551,DE 1346711552,1346715647,AZ 1346715648,1346723839,NL @@ -33402,9 +34126,7 @@ 1347384704,1347384831,US 1347384832,1347385063,EE 1347385064,1347385071,RU -1347385072,1347385215,EE -1347385216,1347385343,US -1347385344,1347385599,EE +1347385072,1347385599,EE 1347385600,1347385855,US 1347385856,1347386559,EE 1347386560,1347386567,RU @@ -33415,7 +34137,7 @@ 1347386816,1347387011,EE 1347387012,1347387015,DE 1347387016,1347387215,EE -1347387216,1347387219,DE +1347387216,1347387219,NZ 1347387220,1347387224,EE 1347387225,1347387228,DE 1347387229,1347387391,EE @@ -33607,8 +34329,8 @@ 1347854880,1347854887,DE 1347854888,1347854911,EU 1347854912,1347855071,DE -1347855072,1347855079,EU -1347855080,1347855103,DE +1347855072,1347855087,EU +1347855088,1347855103,DE 1347855104,1347855359,CH 1347855360,1347855935,DE 1347855936,1347855943,EU @@ -33655,7 +34377,9 @@ 1347861800,1347861823,DE 1347861824,1347861943,EU 1347861944,1347861951,DE -1347861952,1347862111,EU +1347861952,1347862007,EU +1347862008,1347862015,CH +1347862016,1347862111,EU 1347862112,1347862143,DE 1347862144,1347862303,EU 1347862304,1347862431,DE @@ -33676,7 +34400,9 @@ 1347915776,1347919871,RU 1347919872,1347923967,DE 1347923968,1347928063,CZ -1347928064,1347932159,RU +1347928064,1347930623,RU +1347930624,1347930879,GB +1347930880,1347932159,RU 1347932160,1347936255,SK 1347936256,1347940351,FR 1347940352,1347944447,BA @@ -34038,9 +34764,7 @@ 1352149856,1352149871,SE 1352149872,1352277535,DE 1352277536,1352277567,IT -1352277568,1352287399,DE -1352287400,1352287407,NL -1352287408,1352402791,DE +1352277568,1352402791,DE 1352402792,1352402799,BE 1352402800,1352404599,DE 1352404600,1352404607,NL @@ -34075,8 +34799,8 @@ 1353258416,1353258423,DK 1353258424,1353258495,SE 1353258496,1353258503,GB -1353258504,1353258527,SE -1353258528,1353258559,GB +1353258504,1353258519,SE +1353258520,1353258559,GB 1353258560,1353258639,SE 1353258640,1353258783,GB 1353258784,1353258807,SE @@ -34095,7 +34819,9 @@ 1353268224,1353268479,GB 1353268480,1353268575,BE 1353268576,1353268583,GB -1353268584,1353269247,BE +1353268584,1353268599,BE +1353268600,1353268607,GB +1353268608,1353269247,BE 1353269248,1353270527,GB 1353270528,1353270783,IE 1353270784,1353271295,GB @@ -34143,7 +34869,11 @@ 1353280120,1353280127,GB 1353280128,1353280143,IT 1353280144,1353280151,GB -1353280152,1353280671,IT +1353280152,1353280159,IT +1353280160,1353280167,GB +1353280168,1353280287,IT +1353280288,1353280295,GB +1353280296,1353280671,IT 1353280672,1353280679,GB 1353280680,1353281023,IT 1353281024,1353281535,BE @@ -34216,10 +34946,13 @@ 1353298752,1353298815,SE 1353298816,1353298831,PT 1353298832,1353298839,SE -1353298840,1353298879,GB +1353298840,1353298847,IE +1353298848,1353298879,GB 1353298880,1353298881,SE 1353298882,1353298887,GB -1353298888,1353299647,SE +1353298888,1353299503,SE +1353299504,1353299511,GB +1353299512,1353299647,SE 1353299648,1353299839,GB 1353299840,1353299847,SE 1353299848,1353299863,GB @@ -34249,9 +34982,7 @@ 1353310336,1353310463,GB 1353310464,1353310479,ES 1353310480,1353310487,GB -1353310488,1353310559,ES -1353310560,1353310575,GB -1353310576,1353310599,ES +1353310488,1353310599,ES 1353310600,1353310607,DE 1353310608,1353310719,ES 1353310720,1353311175,IT @@ -34454,7 +35185,7 @@ 1357321016,1357321023,DK 1357321024,1357321087,KE 1357321088,1357321215,HK -1357321216,1357321471,GB +1357321216,1357321471,EU 1357321472,1357321503,ES 1357321504,1357321727,EU 1357321728,1357321983,CY @@ -34523,10 +35254,10 @@ 1357358592,1357358847,DE 1357358848,1357359103,PL 1357359104,1357359999,ES -1357360000,1357360031,GB -1357360032,1357360127,EU -1357360128,1357360279,GB -1357360280,1357360383,EU +1357360000,1357360279,GB +1357360280,1357360319,EU +1357360320,1357360335,GB +1357360336,1357360383,EU 1357360384,1357360639,ES 1357360640,1357360895,GB 1357360896,1357361151,DE @@ -34551,7 +35282,9 @@ 1357366864,1357366879,ES 1357366880,1357366911,EU 1357366912,1357366927,GB -1357366928,1357366975,EU +1357366928,1357366943,EU +1357366944,1357366959,GB +1357366960,1357366975,EU 1357366976,1357367295,GB 1357367296,1357367551,FR 1357367552,1357367807,EU @@ -34662,7 +35395,8 @@ 1357883536,1357883551,FR 1357883552,1357883583,EU 1357883584,1357883727,FR -1357883728,1357883759,EU +1357883728,1357883743,DE +1357883744,1357883759,EU 1357883760,1357883775,FR 1357883776,1357883807,RU 1357883808,1357883839,EU @@ -34708,7 +35442,7 @@ 1357891584,1357891647,EU 1357891648,1357891679,NL 1357891680,1357891711,GB -1357891712,1357891839,FI +1357891712,1357891839,EU 1357891840,1357892095,GB 1357892096,1357892111,DE 1357892112,1357892127,ES @@ -34721,7 +35455,7 @@ 1357892200,1357892207,NL 1357892208,1357892215,SE 1357892216,1357892223,US -1357892224,1357892351,FI +1357892224,1357892351,EU 1357892352,1357893119,NL 1357893120,1357893375,SE 1357893376,1357893407,EU @@ -34733,13 +35467,16 @@ 1357897856,1357898495,DE 1357898496,1357898751,EU 1357898752,1357899019,DE -1357899020,1357899023,EU +1357899020,1357899023,NL 1357899024,1357899039,DE 1357899040,1357899047,EU 1357899048,1357899063,DE 1357899064,1357899071,EU 1357899072,1357899199,DE -1357899200,1357899279,EU +1357899200,1357899263,EU +1357899264,1357899267,DE +1357899268,1357899275,FR +1357899276,1357899279,NL 1357899280,1357899287,RU 1357899288,1357899327,EU 1357899328,1357899391,PL @@ -34761,7 +35498,7 @@ 1357903872,1357904383,EU 1357904384,1357904895,DE 1357904896,1357905407,GB -1357905408,1357905663,FR +1357905408,1357905663,SE 1357905664,1357905919,NL 1357905920,1357910015,LT 1357910016,1357914111,GR @@ -34807,7 +35544,8 @@ 1357989784,1357989791,GB 1357989792,1357989807,FR 1357989808,1357989823,GB -1357989824,1357989839,FR +1357989824,1357989831,NL +1357989832,1357989839,FR 1357989840,1357989847,GB 1357989848,1357989887,FR 1357989888,1357991679,GB @@ -34890,10 +35628,8 @@ 1358223672,1358223687,DE 1358223688,1358223695,GB 1358223696,1358223719,DE -1358223720,1358223783,GB -1358223784,1358223791,DE -1358223792,1358223807,GB -1358223808,1358223843,DE +1358223720,1358223815,GB +1358223816,1358223843,DE 1358223844,1358223871,GB 1358223872,1358223887,NL 1358223888,1358223895,DE @@ -34905,8 +35641,8 @@ 1358223940,1358223975,DE 1358223976,1358223991,NL 1358223992,1358223999,DE -1358224000,1358224079,NL -1358224080,1358224511,DE +1358224000,1358224087,NL +1358224088,1358224511,DE 1358224512,1358224519,BE 1358224520,1358224611,DE 1358224612,1358224651,BE @@ -34915,9 +35651,7 @@ 1358224728,1358224959,DE 1358224960,1358225127,IT 1358225128,1358225135,DE -1358225136,1358225143,IT -1358225144,1358225151,DE -1358225152,1358225183,IT +1358225136,1358225183,IT 1358225184,1358225191,DE 1358225192,1358225199,IT 1358225200,1358225407,DE @@ -35086,10 +35820,12 @@ 1358487552,1358487711,SE 1358487712,1358487727,US 1358487728,1358487999,FR -1358488000,1358488223,SE +1358488000,1358488191,SE +1358488192,1358488223,GB 1358488224,1358488239,US 1358488240,1358488255,FR -1358488256,1358488479,SE +1358488256,1358488447,SE +1358488448,1358488479,GB 1358488480,1358488495,US 1358488496,1358488511,FR 1358488512,1358491647,SE @@ -35150,9 +35886,7 @@ 1358669352,1358669359,GB 1358669360,1358669463,PT 1358669464,1358669471,GB -1358669472,1358669503,PT -1358669504,1358669519,GB -1358669520,1358669543,PT +1358669472,1358669543,PT 1358669544,1358669551,GB 1358669552,1358669975,PT 1358669976,1358669983,GB @@ -35161,8 +35895,10 @@ 1358670024,1358670183,PT 1358670184,1358670191,GB 1358670192,1358670943,PT -1358670944,1358670959,GB -1358670960,1358671415,PT +1358670944,1358670951,FR +1358670952,1358671039,PT +1358671040,1358671103,GB +1358671104,1358671415,PT 1358671416,1358671423,GB 1358671424,1358671431,PT 1358671432,1358671439,GB @@ -35305,7 +36041,9 @@ 1358876672,1358880767,LV 1358880768,1358884863,GB 1358884864,1358888959,SE -1358888960,1358893055,DE +1358888960,1358889599,DE +1358889600,1358889631,IN +1358889632,1358893055,DE 1358893056,1358897151,RU 1358897152,1358898175,A2 1358898176,1358898239,CA @@ -35519,8 +36257,8 @@ 1359467488,1359467495,DE 1359467496,1359467647,US 1359467648,1359467775,DE -1359467776,1359467823,US -1359467824,1359467903,DE +1359467776,1359467831,US +1359467832,1359467903,DE 1359467904,1359468063,US 1359468064,1359468575,DE 1359468576,1359468583,SG @@ -35765,7 +36503,9 @@ 1360625664,1360626687,DE 1360626688,1360627199,LB 1360627200,1360627455,DE -1360627456,1360627743,LB +1360627456,1360627520,IQ +1360627521,1360627711,DE +1360627712,1360627743,LB 1360627744,1360627967,DE 1360627968,1360628095,IQ 1360628096,1360628223,LU @@ -36081,7 +36821,7 @@ 1361036596,1361036599,GI 1361036600,1361036607,IQ 1361036608,1361036611,GI -1361036612,1361036615,IQ +1361036612,1361036615,NL 1361036616,1361036623,GB 1361036624,1361036631,IQ 1361036632,1361036635,GR @@ -36978,7 +37718,9 @@ 1372147712,1372151807,BE 1372151808,1372152823,DE 1372152824,1372152831,GB -1372152832,1372159999,DE +1372152832,1372156063,DE +1372156064,1372156095,GB +1372156096,1372159999,DE 1372160000,1372164095,GB 1372164096,1372166863,DE 1372166864,1372166879,US @@ -37066,8 +37808,8 @@ 1372702992,1372703271,EU 1372703272,1372703323,DE 1372703324,1372703327,EU -1372703328,1372703407,DE -1372703408,1372703423,EU +1372703328,1372703391,DE +1372703392,1372703423,EU 1372703424,1372703487,DE 1372703488,1372703743,EU 1372703744,1372713327,DE @@ -37190,7 +37932,9 @@ 1382182832,1382182895,DE 1382182896,1382182911,GB 1382182912,1382183167,LI -1382183168,1382187007,DE +1382183168,1382183423,CH +1382183424,1382183935,LI +1382183936,1382187007,DE 1382187008,1382191871,ES 1382191872,1382192127,VE 1382192128,1382203391,ES @@ -37301,7 +38045,6 @@ 1383104024,1383104255,GB 1383104256,1383104511,FR 1383104512,1383112703,JE -1383112704,1383120895,GE 1383120896,1383129031,IT 1383129032,1383129039,ES 1383129040,1383129087,IT @@ -37386,7 +38129,6 @@ 1383440384,1383448575,RU 1383448576,1383456767,RS 1383456768,1383464959,UA -1383464960,1383473151,US 1383473152,1383481343,DE 1383481344,1383481599,GB 1383481600,1383481615,US @@ -37434,9 +38176,7 @@ 1384190464,1384190719,NL 1384190720,1384190975,DE 1384190976,1384191231,DK -1384191232,1384191359,DE -1384191360,1384191423,AT -1384191424,1384191999,DE +1384191232,1384191999,DE 1384192000,1384192191,NL 1384192192,1384192255,DE 1384192256,1384192511,NL @@ -37624,8 +38364,7 @@ 1385275392,1385283583,IT 1385283584,1385285631,DE 1385285632,1385287679,GB -1385287680,1385289727,IS -1385289728,1385291775,NO +1385287680,1385291775,IS 1385291776,1385299967,TR 1385299968,1385308159,BG 1385308160,1385309439,BE @@ -37808,7 +38547,9 @@ 1388389928,1388390015,NG 1388390016,1388390143,IT 1388390144,1388394495,NG -1388394496,1388396543,IT +1388394496,1388396031,IT +1388396032,1388396287,NG +1388396288,1388396543,IT 1388396544,1388404735,LV 1388404736,1388412927,UA 1388412928,1388421119,RU @@ -38000,7 +38741,9 @@ 1388743088,1388743099,GB 1388743100,1388743343,IE 1388743344,1388743351,GB -1388743352,1388743443,IE +1388743352,1388743359,IE +1388743360,1388743375,GB +1388743376,1388743443,IE 1388743444,1388743451,GB 1388743452,1388743555,IE 1388743556,1388743559,GB @@ -38074,9 +38817,7 @@ 1388765184,1388773375,GB 1388773376,1388781567,NO 1388781568,1388789759,ES -1388789760,1388791519,NL -1388791520,1388791527,GB -1388791528,1388794943,NL +1388789760,1388794943,NL 1388794944,1388794959,GB 1388794960,1388795343,NL 1388795344,1388795359,GB @@ -38670,11 +39411,11 @@ 1399848960,1400111103,FR 1400111104,1400373247,NL 1400373248,1400705279,DE -1400705280,1400706047,EU -1400706048,1400708095,DE -1400708096,1400709119,EU -1400709120,1400710143,DE -1400710144,1400710399,EU +1400705280,1400705791,EU +1400705792,1400708607,DE +1400708608,1400709120,EU +1400709121,1400710142,DE +1400710143,1400710399,EU 1400710400,1400712191,DE 1400712192,1400712447,EU 1400712448,1400712703,DE @@ -38705,7 +39446,9 @@ 1401264128,1401264903,DE 1401264904,1401265151,EU 1401265152,1401265919,DE -1401265920,1401266175,EU +1401265920,1401265951,EU +1401265952,1401265983,DE +1401265984,1401266175,EU 1401266176,1401273599,DE 1401273600,1401273727,EU 1401273728,1401274367,DE @@ -38807,45 +39550,97 @@ 1401667584,1401683967,IT 1401683968,1401684067,SE 1401684068,1401684071,NO -1401684072,1401684479,SE +1401684072,1401684075,DE +1401684076,1401684479,SE 1401684480,1401684511,DK -1401684512,1401684543,SE +1401684512,1401684515,DE +1401684516,1401684543,SE 1401684544,1401684607,DK 1401684608,1401684671,SE 1401684672,1401684703,DK 1401684704,1401684731,SE 1401684732,1401684735,DK 1401684736,1401684755,NO -1401684756,1401684767,SE +1401684756,1401684759,SE +1401684760,1401684763,DE +1401684764,1401684767,SE 1401684768,1401684895,NO -1401684896,1401686015,SE +1401684896,1401684995,SE +1401684996,1401684999,DE +1401685000,1401686015,SE 1401686016,1401686059,GB -1401686060,1401686063,SE +1401686060,1401686063,DE 1401686064,1401686143,GB 1401686144,1401686223,SE 1401686224,1401686271,GB 1401686272,1401686287,NL -1401686288,1401686335,SE +1401686288,1401686291,DE +1401686292,1401686335,SE 1401686336,1401686399,NL 1401686400,1401686911,SE 1401686912,1401686927,DE -1401686928,1401691519,SE +1401686928,1401686943,SE +1401686944,1401686947,DE +1401686948,1401691519,SE 1401691520,1401691535,DE 1401691536,1401695263,SE 1401695264,1401695267,GB 1401695268,1401695271,SE 1401695272,1401695275,GB -1401695276,1401697815,SE +1401695276,1401695279,DE +1401695280,1401697815,SE 1401697816,1401697823,DE 1401697824,1401698223,SE 1401698224,1401698227,GB -1401698228,1401708543,SE +1401698228,1401698231,DE +1401698232,1401703951,SE +1401703952,1401703955,DE +1401703956,1401704511,SE +1401704512,1401704515,DE +1401704516,1401705983,SE +1401705984,1401705987,DE +1401705988,1401708543,SE 1401708544,1401709055,FR 1401709056,1401709311,SE 1401709312,1401709567,GB -1401709568,1401714047,SE +1401709568,1401711615,SE +1401711616,1401711647,GB +1401711648,1401711679,DE +1401711680,1401711711,NL +1401711712,1401711743,ES +1401711744,1401711775,DK +1401711776,1401711807,IT +1401711808,1401711839,US +1401711840,1401711871,NL +1401711872,1401711903,GB +1401711904,1401711935,DE +1401711936,1401711967,NL +1401711968,1401711999,ES +1401712000,1401712031,DK +1401712032,1401712063,CH +1401712064,1401712095,FR +1401712096,1401712127,NL +1401712128,1401712159,GB +1401712160,1401712191,DE +1401712192,1401712223,SE +1401712224,1401712255,ES +1401712256,1401712287,DK +1401712288,1401712319,SE +1401712320,1401712351,IT +1401712352,1401712383,DE +1401712384,1401712415,GB +1401712416,1401712447,DE +1401712448,1401712479,NL +1401712480,1401712511,ES +1401712512,1401712543,SE +1401712544,1401712575,US +1401712576,1401712607,GB +1401712608,1401712639,NL +1401712640,1401714047,SE 1401714048,1401714063,FR -1401714064,1401715455,SE +1401714064,1401715403,SE +1401715404,1401715407,DE +1401715408,1401715455,SE 1401715456,1401715459,US 1401715460,1401717759,SE 1401717760,1401718015,NL @@ -38854,7 +39649,10 @@ 1401719952,1401719955,GB 1401719956,1401719959,SE 1401719960,1401719963,GB -1401719964,1401727743,SE +1401719964,1401719967,DE +1401719968,1401726783,SE +1401726784,1401726787,DE +1401726788,1401727743,SE 1401727744,1401727999,GB 1401728000,1401728335,SE 1401728336,1401728351,NL @@ -38891,7 +39689,9 @@ 1401745984,1401745999,NL 1401746000,1401746015,ES 1401746016,1401746019,GB -1401746020,1401746175,SE +1401746020,1401746023,SE +1401746024,1401746027,DE +1401746028,1401746175,SE 1401746176,1401746191,DK 1401746192,1401746215,SE 1401746216,1401746223,BG @@ -38901,7 +39701,8 @@ 1401746272,1401746279,GB 1401746280,1401746283,SE 1401746284,1401746287,US -1401746288,1401746431,SE +1401746288,1401746291,DE +1401746292,1401746431,SE 1401746432,1401746447,NL 1401746448,1401746467,SE 1401746468,1401746471,NL @@ -38910,12 +39711,15 @@ 1401746488,1401746495,SE 1401746496,1401746511,NL 1401746512,1401746527,ES -1401746528,1401746623,SE +1401746528,1401746531,DE +1401746532,1401746623,SE 1401746624,1401746639,DE 1401746640,1401746655,SE 1401746656,1401746687,IE 1401746688,1401746703,NO -1401746704,1401746751,SE +1401746704,1401746719,SE +1401746720,1401746723,DE +1401746724,1401746751,SE 1401746752,1401746767,NL 1401746768,1401746783,ES 1401746784,1401746879,SE @@ -38925,13 +39729,15 @@ 1401746960,1401747007,SE 1401747008,1401747023,NL 1401747024,1401747039,ES -1401747040,1401747135,SE +1401747040,1401747043,DE +1401747044,1401747135,SE 1401747136,1401747151,DE 1401747152,1401747199,SE 1401747200,1401747215,IT 1401747216,1401747235,SE 1401747236,1401747239,US -1401747240,1401747279,SE +1401747240,1401747243,DE +1401747244,1401747279,SE 1401747280,1401747295,ES 1401747296,1401747391,SE 1401747392,1401747407,DE @@ -38940,7 +39746,9 @@ 1401747488,1401747495,DK 1401747496,1401747499,SE 1401747500,1401747503,GB -1401747504,1401747647,SE +1401747504,1401747583,SE +1401747584,1401747587,DE +1401747588,1401747647,SE 1401747648,1401747663,DE 1401747664,1401747711,SE 1401747712,1401747967,FR @@ -39116,9 +39924,13 @@ 1403574784,1403575039,IT 1403575040,1403576063,SE 1403576064,1403576319,DE -1403576320,1403580159,SE +1403576320,1403578879,SE +1403578880,1403579135,DK +1403579136,1403580159,SE 1403580160,1403580415,GB -1403580416,1403584511,SE +1403580416,1403581951,SE +1403581952,1403582207,US +1403582208,1403584511,SE 1403584512,1403600895,DE 1403600896,1403601519,FR 1403601520,1403601535,MC @@ -39418,7 +40230,8 @@ 1406964928,1406967295,DE 1406967296,1406967327,GB 1406967328,1406967343,NL -1406967344,1406967807,DE +1406967344,1406967359,GB +1406967360,1406967807,DE 1406967808,1406975999,RU 1406976000,1406984191,IE 1406984192,1407000575,RU @@ -39443,7 +40256,14 @@ 1407123456,1407131647,SE 1407131648,1407139839,NL 1407139840,1407148031,DE -1407148032,1407152263,GB +1407148032,1407148295,GB +1407148296,1407148303,SE +1407148304,1407149695,GB +1407149696,1407149759,CY +1407149760,1407151615,GB +1407151616,1407151871,SE +1407151872,1407152259,GB +1407152260,1407152263,IE 1407152264,1407152287,US 1407152288,1407152903,GB 1407152904,1407152927,NL @@ -39466,8 +40286,7 @@ 1407516728,1407516735,NG 1407516736,1407516743,UG 1407516744,1407516751,LR -1407516752,1407516759,SL -1407516760,1407516767,A2 +1407516752,1407516767,A2 1407516768,1407516775,AO 1407516776,1407516783,A2 1407516784,1407516791,NG @@ -39483,7 +40302,8 @@ 1407516912,1407516951,NG 1407516952,1407516959,A2 1407516960,1407516967,NG -1407516968,1407516983,A2 +1407516968,1407516975,A2 +1407516976,1407516983,GN 1407516984,1407516991,KE 1407516992,1407516999,CD 1407517000,1407517023,A2 @@ -39535,7 +40355,7 @@ 1407518352,1407518359,A2 1407518360,1407518367,NG 1407518368,1407518375,ZA -1407518376,1407518383,CD +1407518376,1407518383,AO 1407518384,1407518391,A2 1407518392,1407518399,CD 1407518400,1407518831,A2 @@ -39593,7 +40413,9 @@ 1407519896,1407519903,GN 1407519904,1407519911,NG 1407519912,1407519919,GN -1407519920,1407519959,A2 +1407519920,1407519943,A2 +1407519944,1407519951,CD +1407519952,1407519959,A2 1407519960,1407519967,GB 1407519968,1407519983,NG 1407519984,1407519991,SD @@ -39665,7 +40487,7 @@ 1407520792,1407520799,ZA 1407520800,1407520807,A2 1407520808,1407520815,MU -1407520816,1407520823,A2 +1407520816,1407520823,ZW 1407520824,1407520831,CI 1407520832,1407520839,SO 1407520840,1407520847,A2 @@ -39728,7 +40550,9 @@ 1407522384,1407522391,A2 1407522392,1407522407,NG 1407522408,1407522415,ZW -1407522416,1407522439,A2 +1407522416,1407522423,SD +1407522424,1407522431,A2 +1407522432,1407522439,ZM 1407522440,1407522455,UG 1407522456,1407522463,ML 1407522464,1407522471,A2 @@ -39757,7 +40581,7 @@ 1407522656,1407522663,CI 1407522664,1407522671,A2 1407522672,1407522679,ZM -1407522680,1407522687,IQ +1407522680,1407522687,SD 1407522688,1407522695,NG 1407522696,1407522703,GL 1407522704,1407522711,NG @@ -39767,8 +40591,8 @@ 1407522736,1407522743,LR 1407522744,1407522751,NG 1407522752,1407522767,ZM -1407522768,1407522775,A2 -1407522776,1407522791,NG +1407522768,1407522783,A2 +1407522784,1407522791,NG 1407522792,1407522799,A2 1407522800,1407522807,NG 1407522808,1407522815,A2 @@ -39780,7 +40604,8 @@ 1407522856,1407522863,ZW 1407522864,1407522871,TZ 1407522872,1407522879,IQ -1407522880,1407522895,A2 +1407522880,1407522887,MU +1407522888,1407522895,A2 1407522896,1407522903,UG 1407522904,1407522911,KE 1407522912,1407522919,CG @@ -39790,12 +40615,14 @@ 1407522944,1407522951,CD 1407522952,1407522967,ZW 1407522968,1407522975,MU -1407522976,1407522991,A2 +1407522976,1407522983,CD +1407522984,1407522991,A2 1407522992,1407522999,CD 1407523000,1407523007,A2 1407523008,1407523015,NG 1407523016,1407523023,KE -1407523024,1407523079,A2 +1407523024,1407523071,A2 +1407523072,1407523079,CD 1407523080,1407523088,NG 1407523089,1407523103,A2 1407523104,1407523111,UG @@ -39834,23 +40661,35 @@ 1407523560,1407523567,KE 1407523568,1407523583,A2 1407523584,1407523591,IQ -1407523592,1407523839,A2 +1407523592,1407523607,A2 +1407523608,1407523615,IQ +1407523616,1407523623,A2 +1407523624,1407523631,IQ +1407523632,1407523639,A2 +1407523640,1407523647,IQ +1407523648,1407523679,A2 +1407523680,1407523687,IQ +1407523688,1407523839,A2 1407523840,1407524351,MW 1407524352,1407524607,GB 1407524608,1407524615,ZW -1407524616,1407524623,CM +1407524616,1407524623,CD 1407524624,1407524631,ZA 1407524632,1407524639,NG 1407524640,1407524647,KE 1407524648,1407524655,CD -1407524656,1407524663,NG +1407524656,1407524663,ZW 1407524664,1407524671,CD 1407524672,1407524679,A2 1407524680,1407524687,LR 1407524688,1407524703,MZ -1407524704,1407524727,A2 +1407524704,1407524711,A2 +1407524712,1407524719,ZW +1407524720,1407524727,A2 1407524728,1407524735,NG -1407524736,1407524759,A2 +1407524736,1407524743,A2 +1407524744,1407524751,ZW +1407524752,1407524759,A2 1407524760,1407524767,CM 1407524768,1407524775,BW 1407524776,1407524783,A2 @@ -39860,12 +40699,15 @@ 1407524840,1407524847,LR 1407524848,1407524855,A2 1407524856,1407524863,CD -1407524864,1407524887,A2 +1407524864,1407524879,A2 +1407524880,1407524887,ZW 1407524888,1407524895,TZ 1407524896,1407524903,LR -1407524904,1407524935,A2 +1407524904,1407524911,A2 +1407524912,1407524919,ZW +1407524920,1407524935,A2 1407524936,1407524943,GR -1407524944,1407524951,A2 +1407524944,1407524951,ZW 1407524952,1407524959,CM 1407524960,1407524967,TZ 1407524968,1407524975,NG @@ -39880,11 +40722,11 @@ 1407525040,1407525047,ZA 1407525048,1407525055,NG 1407525056,1407525063,ZA -1407525064,1407525071,A2 +1407525064,1407525071,SO 1407525072,1407525079,NG 1407525080,1407525087,A2 1407525088,1407525095,MW -1407525096,1407525103,A2 +1407525096,1407525103,ZW 1407525104,1407525111,NG 1407525112,1407525119,ZA 1407525120,1407525127,A2 @@ -39973,8 +40815,7 @@ 1407533056,1407533311,NG 1407533312,1407533327,AO 1407533328,1407533343,A2 -1407533344,1407533359,NG -1407533360,1407533375,A2 +1407533344,1407533375,NG 1407533376,1407533407,CD 1407533408,1407533423,A2 1407533424,1407533567,GH @@ -40025,8 +40866,7 @@ 1407535632,1407535639,SD 1407535640,1407535647,CD 1407535648,1407535655,NG -1407535656,1407535663,GB -1407535664,1407535671,A2 +1407535656,1407535671,A2 1407535672,1407535679,SD 1407535680,1407535687,GN 1407535688,1407535695,A2 @@ -40041,8 +40881,7 @@ 1407535776,1407535783,GN 1407535784,1407535815,A2 1407535816,1407535823,NG -1407535824,1407535831,GB -1407535832,1407535847,A2 +1407535824,1407535847,A2 1407535848,1407535855,CD 1407535856,1407535863,SD 1407535864,1407536127,A2 @@ -40087,9 +40926,7 @@ 1407537368,1407537383,NG 1407537384,1407537399,A2 1407537400,1407537407,BF -1407537408,1407537415,A2 -1407537416,1407537423,GH -1407537424,1407537431,A2 +1407537408,1407537431,A2 1407537432,1407537447,NG 1407537448,1407537455,UG 1407537456,1407537463,AO @@ -40100,9 +40937,7 @@ 1407537512,1407537519,LR 1407537520,1407537543,A2 1407537544,1407537551,AO -1407537552,1407537559,A2 -1407537560,1407537567,NG -1407537568,1407537575,A2 +1407537552,1407537575,A2 1407537576,1407537599,NG 1407537600,1407537607,A2 1407537608,1407537615,CM @@ -40140,8 +40975,7 @@ 1407538072,1407538079,A2 1407538080,1407538087,LR 1407538088,1407538095,AO -1407538096,1407538103,CD -1407538104,1407538111,A2 +1407538096,1407538111,A2 1407538112,1407538119,LR 1407538120,1407538127,NG 1407538128,1407538143,A2 @@ -40204,8 +41038,7 @@ 1407539720,1407539727,A2 1407539728,1407539735,GR 1407539736,1407539743,NG -1407539744,1407539751,A2 -1407539752,1407539759,NG +1407539744,1407539759,A2 1407539760,1407539767,GH 1407539768,1407539775,GR 1407539776,1407539783,A2 @@ -40224,7 +41057,8 @@ 1407539928,1407539935,GN 1407539936,1407539943,A2 1407539944,1407539951,CD -1407539952,1407539967,A2 +1407539952,1407539959,LR +1407539960,1407539967,A2 1407539968,1407539975,CD 1407539976,1407540055,A2 1407540056,1407540063,NG @@ -40238,7 +41072,12 @@ 1407540160,1407540167,CD 1407540168,1407540199,A2 1407540200,1407540215,CD -1407540216,1407541471,A2 +1407540216,1407540223,A2 +1407540224,1407540231,AO +1407540232,1407540239,NG +1407540240,1407540279,A2 +1407540280,1407540287,NG +1407540288,1407541471,A2 1407541472,1407541495,NG 1407541496,1407541535,A2 1407541536,1407541543,CM @@ -40292,13 +41131,18 @@ 1407545856,1407545863,CI 1407545864,1407545895,A2 1407545896,1407545903,CD -1407545904,1407545951,A2 +1407545904,1407545919,A2 +1407545920,1407545927,NG +1407545928,1407545951,A2 1407545952,1407545959,NG 1407545960,1407545967,A2 1407545968,1407545975,GQ 1407545976,1407545983,A2 1407545984,1407545991,MU -1407545992,1407546367,A2 +1407545992,1407545999,GN +1407546000,1407546031,A2 +1407546032,1407546039,NG +1407546040,1407546367,A2 1407546368,1407546495,AE 1407546496,1407546799,A2 1407546800,1407546815,GH @@ -40318,8 +41162,7 @@ 1407547240,1407547255,SL 1407547256,1407547263,A2 1407547264,1407547271,SL -1407547272,1407547279,NG -1407547280,1407547303,A2 +1407547272,1407547303,A2 1407547304,1407547311,SL 1407547312,1407547327,NG 1407547328,1407547335,A2 @@ -40355,19 +41198,18 @@ 1407549040,1407549047,NG 1407549048,1407549055,A2 1407549056,1407549063,NG -1407549064,1407549071,A2 +1407549064,1407549071,GA 1407549072,1407549079,NG 1407549080,1407549127,A2 1407549128,1407549135,NG -1407549136,1407549183,A2 +1407549136,1407549175,A2 +1407549176,1407549183,NG 1407549184,1407549439,GE 1407549440,1407582207,RU 1407582208,1407614975,PL 1407614976,1407680511,ES -1407680512,1407680591,FR -1407680592,1407680607,GB -1407680608,1407680639,FR -1407680640,1407681023,GB +1407680512,1407680671,FR +1407680672,1407681023,GB 1407681024,1407681087,ES 1407681088,1407681279,GB 1407681280,1407681291,ES @@ -40705,13 +41547,9 @@ 1410036992,1410037247,LB 1410037248,1410037759,A2 1410037760,1410038015,US -1410038016,1410039807,A2 -1410039808,1410041855,AE -1410041856,1410042815,A2 +1410038016,1410042815,A2 1410042816,1410042831,US -1410042832,1410043903,A2 -1410043904,1410044415,JO -1410044416,1410044927,A2 +1410042832,1410044927,A2 1410044928,1410045183,VG 1410045184,1410045439,IQ 1410045440,1410045695,LB @@ -40728,9 +41566,7 @@ 1410212864,1410213119,GB 1410213120,1410234839,FR 1410234840,1410234847,A2 -1410234848,1410250551,FR -1410250552,1410250559,GB -1410250560,1410258527,FR +1410234848,1410258527,FR 1410258528,1410258535,ES 1410258536,1410261007,FR 1410261008,1410261015,GB @@ -41031,17 +41867,19 @@ 1411919872,1411923967,DE 1411923968,1411940351,BG 1411940352,1411973119,PL -1411973120,1411999743,SI -1411999744,1411999783,BA -1411999784,1411999791,SI -1411999792,1411999799,BA -1411999800,1411999807,SI +1411973120,1411999751,SI +1411999752,1411999783,BA +1411999784,1411999807,SI 1411999808,1411999847,BA 1411999848,1411999871,SI 1411999872,1411999887,BA 1411999888,1411999903,SI -1411999904,1411999943,BA -1411999944,1411999999,SI +1411999904,1411999911,BA +1411999912,1411999919,SI +1411999920,1411999927,BA +1411999928,1411999951,SI +1411999952,1411999959,BA +1411999960,1411999999,SI 1412000000,1412000767,BA 1412000768,1412000783,SI 1412000784,1412000791,BA @@ -41086,9 +41924,7 @@ 1412003352,1412003375,SI 1412003376,1412003383,BA 1412003384,1412003391,SI -1412003392,1412003407,BA -1412003408,1412003423,SI -1412003424,1412003527,BA +1412003392,1412003527,BA 1412003528,1412003535,SI 1412003536,1412003551,BA 1412003552,1412003583,SI @@ -41141,7 +41977,9 @@ 1412686240,1412686335,BB 1412686336,1412686591,IE 1412686592,1412686847,GB -1412686848,1412690191,IE +1412686848,1412689315,IE +1412689316,1412689343,GB +1412689344,1412690191,IE 1412690192,1412690199,GB 1412690200,1412694015,IE 1412694016,1412710399,EE @@ -41200,7 +42038,9 @@ 1422468208,1422468223,IT 1422468224,1422468671,DE 1422468672,1422468735,IT -1422468736,1422479615,DE +1422468736,1422476863,DE +1422476864,1422476895,GB +1422476896,1422479615,DE 1422479616,1422479871,BE 1422479872,1422491647,DE 1422491648,1422508031,RU @@ -41219,12 +42059,7 @@ 1422761984,1422770175,PL 1422770176,1422786559,GR 1422786560,1422852095,HU -1422852096,1422853119,FR -1422853120,1422853631,EU -1422853632,1422853919,FR -1422853920,1422854143,EU -1422854144,1422854151,FR -1422854152,1422856383,EU +1422852096,1422856383,EU 1422856384,1422856447,FR 1422856448,1422856703,EU 1422856704,1422857151,FR @@ -41250,7 +42085,8 @@ 1424556032,1424588799,EG 1424588800,1424588839,DE 1424588840,1424588847,GB -1424588848,1424588959,DE +1424588848,1424588951,DE +1424588952,1424588959,GB 1424588960,1424588963,IT 1424588964,1424589311,DE 1424589312,1424589567,FR @@ -41305,16 +42141,16 @@ 1424597344,1424597351,CH 1424597352,1424597375,GB 1424597376,1424597391,CZ -1424597392,1424597503,GB +1424597392,1424597407,GB +1424597408,1424597423,CZ +1424597424,1424597503,GB 1424597504,1424597759,FR 1424597760,1424598015,IT 1424598016,1424599039,GB 1424599040,1424599279,DK 1424599280,1424599295,GB 1424599296,1424599551,DK -1424599552,1424599839,HU -1424599840,1424599847,GB -1424599848,1424599855,HU +1424599552,1424599855,HU 1424599856,1424599871,GB 1424599872,1424599875,HU 1424599876,1424599879,GB @@ -41369,7 +42205,10 @@ 1424605696,1424605951,NL 1424605952,1424605959,CH 1424605960,1424606023,AT -1424606024,1424607167,GB +1424606024,1424606207,GB +1424606208,1424606719,IT +1424606720,1424606975,NL +1424606976,1424607167,GB 1424607168,1424607199,SK 1424607200,1424607215,GB 1424607216,1424607223,SK @@ -41384,8 +42223,8 @@ 1424608384,1424608399,ES 1424608400,1424608511,FR 1424608512,1424608687,ES -1424608688,1424608695,GB -1424608696,1424609023,ES +1424608688,1424608691,GB +1424608692,1424609023,ES 1424609024,1424609259,DE 1424609260,1424609271,GB 1424609272,1424609279,DE @@ -41447,12 +42286,12 @@ 1424617408,1424617423,ES 1424617424,1424617431,GB 1424617432,1424617439,ES -1424617440,1424617463,IT +1424617440,1424617447,IT +1424617448,1424617455,GB +1424617456,1424617463,IT 1424617464,1424617471,GB 1424617472,1424617727,US -1424617728,1424617983,IT -1424617984,1424618015,GB -1424618016,1424618039,IT +1424617728,1424618039,IT 1424618040,1424618047,GB 1424618048,1424618239,IT 1424618240,1424618495,NL @@ -41462,9 +42301,7 @@ 1424618944,1424619007,FR 1424619008,1424619775,IT 1424619776,1424619807,BE -1424619808,1424619815,GB -1424619816,1424619823,BE -1424619824,1424619839,GB +1424619808,1424619839,GB 1424619840,1424619915,BE 1424619916,1424619919,GB 1424619920,1424620031,BE @@ -42025,12 +42862,15 @@ 1427723520,1427728479,DE 1427728480,1427728511,CY 1427728512,1427728543,BR -1427728544,1427728671,DE +1427728544,1427728575,DE +1427728576,1427728607,BR +1427728608,1427728639,TW +1427728640,1427728671,DE 1427728672,1427728703,TR 1427728704,1427728799,DE 1427728800,1427728831,RU 1427728832,1427728895,CY -1427728896,1427728927,DE +1427728896,1427728927,RU 1427728928,1427728959,IL 1427728960,1427728991,RU 1427728992,1427729055,DE @@ -42058,34 +42898,37 @@ 1427743616,1427743647,DK 1427743648,1427743775,DE 1427743776,1427743807,ZA -1427743808,1427743839,US +1427743808,1427743839,DE 1427743840,1427743871,RU 1427743872,1427743935,DE 1427743936,1427743967,RU 1427743968,1427744127,DE 1427744128,1427744159,PL 1427744160,1427744191,RU -1427744192,1427744223,TR -1427744224,1427744255,DE +1427744192,1427744255,DE 1427744256,1427744287,US 1427744288,1427744319,TR 1427744320,1427744351,DE 1427744352,1427744383,UA 1427744384,1427744415,PL 1427744416,1427744447,UA -1427744448,1427744639,DE +1427744448,1427744479,US +1427744480,1427744639,DE 1427744640,1427744671,TR 1427744672,1427744735,DE 1427744736,1427744767,DK 1427744768,1427744863,DE 1427744864,1427744927,TR -1427744928,1427744991,DE +1427744928,1427744959,HU +1427744960,1427744991,DE 1427744992,1427745023,DK 1427745024,1427745055,BM 1427745056,1427745151,DE 1427745152,1427745183,RO 1427745184,1427745215,CH -1427745216,1427745439,DE +1427745216,1427745375,DE +1427745376,1427745407,TW +1427745408,1427745439,DE 1427745440,1427745471,US 1427745472,1427745503,DE 1427745504,1427745535,RU @@ -42099,7 +42942,8 @@ 1427745760,1427745791,LT 1427745792,1427745823,GB 1427745824,1427745855,US -1427745856,1427746079,DE +1427745856,1427746047,DE +1427746048,1427746079,SE 1427746080,1427746111,GB 1427746112,1427746143,DE 1427746144,1427746175,GR @@ -42120,33 +42964,42 @@ 1427748480,1427748511,TR 1427748512,1427748543,DE 1427748544,1427748575,MX -1427748576,1427748799,DE +1427748576,1427748703,DE +1427748704,1427748735,US +1427748736,1427748799,DE 1427748800,1427748831,US 1427748832,1427749567,DE 1427749568,1427749599,CY -1427749600,1427749631,NL +1427749600,1427749631,DE 1427749632,1427749663,US -1427749664,1427749887,DE +1427749664,1427749855,DE +1427749856,1427749887,RU 1427749888,1427749919,BR 1427749920,1427749951,DE 1427749952,1427749983,RU 1427749984,1427750079,DE 1427750080,1427750111,BG -1427750112,1427750239,DE +1427750112,1427750175,DE +1427750176,1427750207,TR +1427750208,1427750239,DE 1427750240,1427750271,US -1427750272,1427750303,DE +1427750272,1427750303,GR 1427750304,1427750335,GB -1427750336,1427751167,DE +1427750336,1427750367,US +1427750368,1427751167,DE 1427751168,1427751423,NL 1427751424,1427759935,DE 1427759936,1427759967,HR -1427759968,1427760191,DE +1427759968,1427760031,DE +1427760032,1427760063,US +1427760064,1427760191,DE 1427760192,1427760255,US 1427760256,1427760319,BR 1427760320,1427760351,TR 1427760352,1427760383,RU 1427760384,1427760415,TR -1427760416,1427760575,DE +1427760416,1427760447,US +1427760448,1427760575,DE 1427760576,1427760607,CH 1427760608,1427760799,DE 1427760800,1427760831,US @@ -42187,9 +43040,7 @@ 1428045824,1428062207,MK 1428062208,1428078591,SE 1428078592,1428094975,RU -1428094976,1428096031,AT -1428096032,1428096039,CH -1428096040,1428103167,AT +1428094976,1428103167,AT 1428103168,1428111359,GB 1428111360,1428119551,A2 1428119552,1428121599,LV @@ -42507,7 +43358,8 @@ 1434615808,1434648575,IL 1434648576,1434681343,FI 1434681344,1434681983,DE -1434681984,1434682111,NL +1434681984,1434682015,CY +1434682016,1434682111,NL 1434682112,1434682303,DE 1434682304,1434682367,NL 1434682368,1434683119,DE @@ -42734,12 +43586,9 @@ 1438890240,1438890495,RU 1438890496,1438890751,IQ 1438890752,1438892031,RU -1438892032,1438892287,US -1438892288,1438900223,IS -1438900224,1438900479,AQ -1438900480,1438904319,IS -1438904320,1438904575,CH -1438904576,1438908415,IS +1438892032,1438895359,CH +1438895360,1438900223,IS +1438900224,1438908415,AQ 1438908416,1438924799,GR 1438924800,1438941183,NO 1438941184,1438957567,BG @@ -42917,7 +43766,9 @@ 1441389224,1441389231,LU 1441389232,1441389567,FR 1441389568,1441389599,LU -1441389600,1441390591,FR +1441389600,1441389967,FR +1441389968,1441389983,CA +1441389984,1441390591,FR 1441390592,1441398783,DK 1441398784,1441415167,RU 1441415168,1441423359,GB @@ -43231,7 +44082,8 @@ 1446905124,1446905127,AF 1446905128,1446905131,IQ 1446905132,1446905135,A2 -1446905136,1446905143,IQ +1446905136,1446905139,LY +1446905140,1446905143,IQ 1446905144,1446905147,A2 1446905148,1446905151,LY 1446905152,1446905155,AF @@ -43427,7 +44279,7 @@ 1446907112,1446907115,IQ 1446907116,1446907123,A2 1446907124,1446907131,IQ -1446907132,1446907135,A2 +1446907132,1446907135,AF 1446907136,1446907139,IQ 1446907140,1446907143,A2 1446907144,1446907147,AF @@ -43982,7 +44834,8 @@ 1446911568,1446911571,IQ 1446911572,1446911575,LY 1446911576,1446911579,IQ -1446911580,1446911595,A2 +1446911580,1446911583,CG +1446911584,1446911595,A2 1446911596,1446911597,LY 1446911598,1446911619,A2 1446911620,1446911623,GH @@ -44016,7 +44869,7 @@ 1446911788,1446911791,AF 1446911792,1446911795,LY 1446911796,1446911799,IQ -1446911800,1446911803,A2 +1446911800,1446911803,NG 1446911804,1446911811,LY 1446911812,1446911815,IQ 1446911816,1446911819,LY @@ -44131,11 +44984,7 @@ 1449656320,1449657087,GB 1449657088,1449658623,RO 1449658624,1449659135,GB -1449659136,1449660415,RO -1449660416,1449662463,GB -1449662464,1449676799,RO -1449676800,1449678847,GB -1449678848,1449685759,RO +1449659136,1449685759,RO 1449685760,1449686271,GB 1449686272,1449686527,RO 1449686528,1449687039,GB @@ -44147,9 +44996,7 @@ 1449705472,1449705727,GB 1449705728,1449706239,RO 1449706240,1449706495,GB -1449706496,1449707519,RO -1449707520,1449709567,GB -1449709568,1449710591,RO +1449706496,1449710591,RO 1449710592,1449711103,GB 1449711104,1449711359,RO 1449711360,1449711615,GB @@ -44208,8 +45055,8 @@ 1449899008,1449899263,GB 1449899264,1449899519,RO 1449899520,1449899775,GB -1449899776,1449904127,RO -1449904128,1449910271,GB +1449899776,1449908223,RO +1449908224,1449910271,GB 1449910272,1449918463,RO 1449918464,1449951231,JO 1449951232,1449983999,TR @@ -44392,9 +45239,7 @@ 1467466272,1467466495,NL 1467466496,1467467071,DE 1467467072,1467467103,CH -1467467104,1467467903,DE -1467467904,1467468031,CH -1467468032,1467468111,DE +1467467104,1467468111,DE 1467468112,1467468119,BR 1467468120,1467473919,DE 1467473920,1467482111,RU @@ -44486,7 +45331,6 @@ 1475131392,1475133439,RU 1475133440,1475135487,CZ 1475135488,1475137535,CH -1475137536,1475139583,SE 1475139584,1475141631,ES 1475141632,1475143679,FI 1475143680,1475145727,JO @@ -44571,9 +45415,9 @@ 1475223552,1475229695,NO 1475229696,1475229759,SE 1475229760,1475229951,NO -1475229952,1475230111,SE -1475230112,1475230199,NO -1475230200,1475230207,SE +1475229952,1475230175,SE +1475230176,1475230191,NO +1475230192,1475230207,SE 1475230208,1475233791,NO 1475233792,1475234303,GB 1475234304,1475234559,IE @@ -45044,7 +45888,6 @@ 1486323448,1486323455,GB 1486323456,1486323711,EU 1486323712,1486325759,GB -1486325760,1486327807,SA 1486327808,1486329855,CH 1486329856,1486331903,FR 1486331904,1486333951,NO @@ -45340,7 +46183,9 @@ 1495146496,1495150591,FR 1495150592,1495151103,GB 1495151104,1495151359,NL -1495151360,1495154687,FR +1495151360,1495153919,FR +1495153920,1495154175,TR +1495154176,1495154687,FR 1495154688,1495161599,EU 1495161600,1495161855,FR 1495161856,1495162367,EU @@ -45458,9 +46303,7 @@ 1495927296,1495927551,AE 1495927552,1495937023,RO 1495937024,1495937535,ES -1495937536,1495986175,RO -1495986176,1495988223,GB -1495988224,1495990271,RO +1495937536,1495990271,RO 1495990272,1495994367,GB 1495994368,1496078335,RO 1496078336,1496079359,MD @@ -45504,11 +46347,13 @@ 1500107944,1500107951,DE 1500107952,1500107999,NL 1500108000,1500108007,BE -1500108008,1500108159,NL -1500108160,1500108287,DE +1500108008,1500108095,NL +1500108096,1500108287,DE 1500108288,1500108319,NL 1500108320,1500108351,DE -1500108352,1500110847,NL +1500108352,1500108367,NL +1500108368,1500108375,DE +1500108376,1500110847,NL 1500110848,1500119039,UA 1500119040,1500127231,TR 1500127232,1500135423,FI @@ -45643,13 +46488,11 @@ 1502674944,1502691327,DE 1502691328,1502691679,GB 1502691680,1502691711,SE -1502691712,1502692415,GB -1502692416,1502692479,ES -1502692480,1502706623,GB +1502691712,1502702835,GB +1502702836,1502702839,IE +1502702840,1502706623,GB 1502706624,1502706687,CY -1502706688,1502707631,GB -1502707632,1502707639,IE -1502707640,1502707711,GB +1502706688,1502707711,GB 1502707712,1502724095,RU 1502724096,1502740479,GB 1502740480,1502756863,NL @@ -45758,7 +46601,8 @@ 1503895608,1503895631,DE 1503895632,1503895639,AT 1503895640,1503895647,GR -1503895648,1503895671,DE +1503895648,1503895663,DE +1503895664,1503895671,FR 1503895672,1503895679,PL 1503895680,1503895687,IT 1503895688,1503895695,DE @@ -45822,8 +46666,7 @@ 1503898576,1503898599,DE 1503898600,1503898607,IT 1503898608,1503898615,GR -1503898616,1503898623,SE -1503898624,1503898631,DE +1503898616,1503898631,DE 1503898632,1503898647,GR 1503898648,1503898679,DE 1503898680,1503898687,IT @@ -45837,7 +46680,9 @@ 1503898888,1503898895,IT 1503898896,1503898935,DE 1503898936,1503898943,IT -1503898944,1503898991,DE +1503898944,1503898959,DE +1503898960,1503898967,IT +1503898968,1503898991,DE 1503898992,1503898999,GB 1503899000,1503899007,AT 1503899008,1503899063,DE @@ -45848,7 +46693,13 @@ 1503899144,1503899151,IT 1503899152,1503899159,DE 1503899160,1503899167,GB -1503899168,1503908351,DE +1503899168,1503899183,DE +1503899184,1503899191,GR +1503899192,1503899199,CH +1503899200,1503899263,DE +1503899264,1503899271,AT +1503899272,1503899287,BE +1503899288,1503908351,DE 1503908352,1503909375,IT 1503909376,1503920127,DE 1503920128,1503985663,HR @@ -45927,10 +46778,10 @@ 1505312768,1505320959,RU 1505320960,1505321103,AT 1505321104,1505321135,DE -1505321136,1505321407,AT -1505321408,1505321439,DE -1505321440,1505321631,AT -1505321632,1505321823,DE +1505321136,1505321423,AT +1505321424,1505321439,DE +1505321440,1505321663,AT +1505321664,1505321823,DE 1505321824,1505321831,AT 1505321832,1505321983,DE 1505321984,1505322287,AT @@ -45955,8 +46806,8 @@ 1505336064,1505336071,GB 1505336072,1505336576,IE 1505336577,1505336639,GB -1505336640,1505336831,IE -1505336832,1505336863,GB +1505336640,1505336823,IE +1505336824,1505336863,GB 1505336864,1505336864,IE 1505336865,1505336879,GB 1505336880,1505336959,IE @@ -46023,8 +46874,8 @@ 1505455768,1505455791,GB 1505455792,1505455799,US 1505455800,1505455999,GB -1505456000,1505456063,US -1505456064,1505456127,GB +1505456000,1505456079,US +1505456080,1505456127,GB 1505456128,1505456255,US 1505456256,1505456639,GB 1505456640,1505456895,US @@ -46082,7 +46933,9 @@ 1505709056,1505714175,DE 1505714176,1505722367,LV 1505722368,1505738751,PL -1505738752,1505745839,GB +1505738752,1505745135,GB +1505745136,1505745151,ES +1505745152,1505745839,GB 1505745840,1505745855,IL 1505745856,1505746943,GB 1505746944,1505755135,RU @@ -46107,7 +46960,9 @@ 1506418688,1506418695,CY 1506418696,1506418703,GB 1506418704,1506418719,CA -1506418720,1506422655,DE +1506418720,1506418975,DE +1506418976,1506418983,CA +1506418984,1506422655,DE 1506422656,1506422687,CY 1506422688,1506422703,CA 1506422704,1506422711,GB @@ -46218,9 +47073,9 @@ 1506444288,1506445311,DE 1506445312,1506445337,FR 1506445338,1506445343,GB -1506445344,1506445407,FR -1506445408,1506445439,GB -1506445440,1506445519,FR +1506445344,1506445415,FR +1506445416,1506445423,GB +1506445424,1506445519,FR 1506445520,1506445527,GB 1506445528,1506445703,FR 1506445704,1506445711,NL @@ -46246,9 +47101,7 @@ 1506448704,1506448895,GB 1506448896,1506449159,BE 1506449160,1506449171,GB -1506449172,1506449255,BE -1506449256,1506449263,GB -1506449264,1506449407,BE +1506449172,1506449407,BE 1506449408,1506449663,NL 1506449664,1506449919,SK 1506449920,1506449927,CH @@ -46261,7 +47114,8 @@ 1506450848,1506450863,CZ 1506450864,1506450879,GB 1506450880,1506450943,CZ -1506450944,1506451007,GB +1506450944,1506450958,DK +1506450959,1506451007,GB 1506451008,1506451023,DK 1506451024,1506451031,FI 1506451032,1506451039,DK @@ -46318,7 +47172,9 @@ 1506460064,1506460079,GB 1506460080,1506460126,FR 1506460127,1506460127,GB -1506460128,1506460335,FR +1506460128,1506460315,FR +1506460316,1506460319,GB +1506460320,1506460335,FR 1506460336,1506460343,GB 1506460344,1506460671,FR 1506460672,1506460927,AT @@ -46336,7 +47192,8 @@ 1506462208,1506462463,ES 1506462464,1506462527,FR 1506462528,1506462583,GB -1506462584,1506462607,FR +1506462584,1506462599,FR +1506462600,1506462607,GB 1506462608,1506462623,A2 1506462624,1506462719,FR 1506462720,1506463231,IT @@ -46373,8 +47230,8 @@ 1506472704,1506473215,IT 1506473216,1506473471,GB 1506473472,1506474247,IT -1506474248,1506474271,GB -1506474272,1506474495,IT +1506474248,1506474255,GB +1506474256,1506474495,IT 1506474496,1506474751,FR 1506474752,1506475519,IT 1506475520,1506475559,AT @@ -46410,7 +47267,13 @@ 1506767616,1506767679,NO 1506767680,1506768895,GE 1506768896,1506770943,AT -1506770944,1506772991,NL +1506770944,1506771971,NL +1506771972,1506771973,IR +1506771974,1506772014,NL +1506772015,1506772036,IR +1506772037,1506772938,NL +1506772939,1506772939,IR +1506772940,1506772991,NL 1506772992,1506775039,GB 1506775040,1506777087,AT 1506777088,1506781695,GB @@ -46698,7 +47561,9 @@ 1518510080,1518516479,LV 1518516480,1518517247,SE 1518517248,1518518271,LV -1518518272,1518665727,SE +1518518272,1518551039,SE +1518551040,1518565375,NL +1518565376,1518665727,SE 1518665728,1518727167,RU 1518727168,1518731263,SE 1518731264,1518927871,DE @@ -46942,7 +47807,6 @@ 1533421568,1533423615,NL 1533423616,1533425663,IT 1533425664,1533429759,GB -1533429760,1533431807,IT 1533431808,1533433855,IE 1533433856,1533435903,DK 1533435904,1533437951,CZ @@ -47066,7 +47930,8 @@ 1534714384,1534714399,FR 1534714400,1534714403,GB 1534714404,1534714407,PL -1534714408,1534714431,GB +1534714408,1534714415,DE +1534714416,1534714431,GB 1534714432,1534714463,FR 1534714464,1534714495,GB 1534714496,1534714511,FR @@ -47085,7 +47950,9 @@ 1534714752,1534714767,DE 1534714768,1534714783,FR 1534714784,1534714799,PL -1534714800,1534714831,FR +1534714800,1534714815,FR +1534714816,1534714819,BE +1534714820,1534714831,FR 1534714832,1534714847,BE 1534714848,1534714855,GB 1534714856,1534714863,CH @@ -47110,7 +47977,9 @@ 1534715208,1534715215,BE 1534715216,1534715263,FR 1534715264,1534715279,ES -1534715280,1534715295,FR +1534715280,1534715283,PL +1534715284,1534715287,FR +1534715288,1534715295,PL 1534715296,1534715299,ES 1534715300,1534715303,FR 1534715304,1534715307,ES @@ -47121,7 +47990,7 @@ 1534715328,1534715359,FR 1534715360,1534715367,PL 1534715368,1534715371,FR -1534715372,1534715375,GB +1534715372,1534715375,CH 1534715376,1534715391,ES 1534715392,1534715407,PL 1534715408,1534715419,DE @@ -47217,7 +48086,10 @@ 1534717140,1534717143,BE 1534717144,1534717147,FR 1534717148,1534717151,IT -1534717152,1534717263,FR +1534717152,1534717247,FR +1534717248,1534717251,CZ +1534717252,1534717255,NL +1534717256,1534717263,FR 1534717264,1534717267,PL 1534717268,1534717315,FR 1534717316,1534717319,IE @@ -47367,10 +48239,11 @@ 1534720112,1534720127,ES 1534720128,1534720211,FR 1534720212,1534720215,PL -1534720216,1534720223,FR +1534720216,1534720219,FR +1534720220,1534720223,GB 1534720224,1534720239,DE 1534720240,1534720255,BE -1534720256,1534720271,NL +1534720256,1534720271,FR 1534720272,1534720287,PL 1534720288,1534720291,IT 1534720292,1534720295,PL @@ -47415,7 +48288,7 @@ 1534720864,1534720879,ES 1534720880,1534720895,FR 1534720896,1534720899,ES -1534720900,1534720903,GB +1534720900,1534720903,LT 1534720904,1534720943,FR 1534720944,1534720951,ES 1534720952,1534720959,PL @@ -47466,8 +48339,8 @@ 1534721496,1534721519,PL 1534721520,1534721527,FR 1534721528,1534721531,ES -1534721532,1534721535,FR -1534721536,1534721583,GB +1534721532,1534721567,FR +1534721568,1534721583,GB 1534721584,1534721599,FR 1534721600,1534721619,ES 1534721620,1534721627,PL @@ -47481,7 +48354,7 @@ 1534721756,1534721823,FR 1534721824,1534721827,PL 1534721828,1534721831,FR -1534721832,1534721835,PL +1534721832,1534721835,DE 1534721836,1534721839,BE 1534721840,1534721855,PL 1534721856,1534721887,ES @@ -47496,8 +48369,7 @@ 1534721968,1534721971,DE 1534721972,1534721975,PL 1534721976,1534721979,ES -1534721980,1534721983,FR -1534721984,1534722007,PL +1534721980,1534722007,PL 1534722008,1534722011,PT 1534722012,1534722015,ES 1534722016,1534722039,FR @@ -47690,8 +48562,7 @@ 1536660016,1536660019,CG 1536660020,1536660023,DE 1536660024,1536660031,CG -1536660032,1536660039,DJ -1536660040,1536660735,DE +1536660032,1536660735,DE 1536660736,1536660991,SA 1536660992,1536661247,DE 1536661248,1536661759,GQ @@ -47700,7 +48571,8 @@ 1536662304,1536662335,LB 1536662336,1536662367,DE 1536662368,1536662399,SO -1536662400,1536662415,DE +1536662400,1536662407,DE +1536662408,1536662415,SO 1536662416,1536662431,GN 1536662432,1536662463,IQ 1536662464,1536662527,SO @@ -47711,11 +48583,11 @@ 1536663312,1536663319,DE 1536663320,1536663327,LB 1536663328,1536663343,DE -1536663344,1536663391,IQ -1536663392,1536663423,DE +1536663344,1536663359,IQ +1536663360,1536663423,DE 1536663424,1536663551,KW 1536663552,1536667647,SA -1536667648,1536675839,RU +1536671744,1536675839,RU 1536675840,1536679935,GB 1536679936,1536684031,LB 1536684032,1536688127,GB @@ -47797,9 +48669,7 @@ 1539049216,1539049223,LY 1539049224,1539049255,IT 1539049256,1539049263,LY -1539049264,1539049279,IT -1539049280,1539049287,LY -1539049288,1539049311,IT +1539049264,1539049311,IT 1539049312,1539049327,LY 1539049328,1539049335,IT 1539049336,1539049343,LY @@ -47868,13 +48738,13 @@ 1539219712,1539221503,GG 1539221504,1539222527,FR 1539222528,1539222783,HK -1539222784,1539223551,FR +1539222784,1539223039,CN +1539223040,1539223551,FR 1539223552,1539225599,DE 1539225600,1539227647,HU 1539227648,1539229695,FI 1539229696,1539231743,DE 1539231744,1539233791,BE -1539233792,1539235839,GR 1539235840,1539237887,DE 1539237888,1539239935,RU 1539239936,1539244031,DE @@ -47952,7 +48822,6 @@ 1539379200,1539380223,EU 1539380224,1539381247,CH 1539381248,1539382271,RS -1539382272,1539383295,PL 1539383296,1539384319,UA 1539384320,1539385343,RU 1539385344,1539385855,PL @@ -48080,7 +48949,6 @@ 1539482112,1539482623,UA 1539482624,1539483135,RU 1539483136,1539483647,ES -1539483648,1539484159,NL 1539484160,1539484671,GB 1539484672,1539485695,RU 1539485696,1539486207,RO @@ -48402,8 +49270,7 @@ 1539718912,1539719167,KZ 1539719168,1539719423,IE 1539719424,1539719679,PL -1539719680,1539719935,IE -1539719936,1539720191,DE +1539719680,1539720191,DE 1539720192,1539720703,RU 1539720704,1539720959,IL 1539720960,1539721215,RU @@ -48630,7 +49497,6 @@ 1539780608,1539780863,PL 1539780864,1539781119,RO 1539781120,1539781375,NL -1539781376,1539781631,DE 1539781632,1539781887,HU 1539781888,1539782143,IL 1539782144,1539782399,UA @@ -48653,7 +49519,6 @@ 1539786752,1539787007,HU 1539787008,1539787263,TR 1539787264,1539787519,IE -1539787520,1539787775,UA 1539787776,1539788031,CH 1539788032,1539788287,HR 1539788288,1539788543,GB @@ -48975,7 +49840,6 @@ 1540026368,1540028415,UA 1540028416,1540029439,ES 1540029440,1540030463,RU -1540030464,1540031487,DE 1540031488,1540032511,UA 1540032512,1540033535,RU 1540033536,1540034559,UA @@ -49121,7 +49985,6 @@ 1540206592,1540208639,RU 1540208640,1540209663,NO 1540209664,1540211711,RU -1540211712,1540212735,DE 1540212736,1540213759,RU 1540213760,1540214783,UA 1540214784,1540215807,RU @@ -49818,7 +50681,7 @@ 1540488704,1540488959,DE 1540488960,1540489215,RO 1540489216,1540491263,RU -1540491264,1540493311,UA +1540491264,1540492287,UA 1540493312,1540494335,CZ 1540494336,1540495359,UA 1540495360,1540496383,RU @@ -49829,14 +50692,13 @@ 1540502528,1540503551,RU 1540503552,1540504575,NL 1540504576,1540505599,SE -1540505600,1540506623,RU 1540506624,1540507647,GB 1540507648,1540508671,RU 1540508672,1540509695,UA 1540509696,1540510719,RO 1540510720,1540511743,RU 1540511744,1540512767,BG -1540512768,1540514815,UA +1540513792,1540514815,UA 1540514816,1540515839,GB 1540515840,1540516863,RU 1540516864,1540517887,UA @@ -50432,7 +51294,6 @@ 1540818944,1540819967,UA 1540819968,1540820991,CZ 1540820992,1540822015,RU -1540822016,1540823039,FR 1540823040,1540824063,UA 1540824064,1540825087,RU 1540825088,1540826111,PL @@ -51284,7 +52145,6 @@ 1541236736,1541237247,DE 1541237248,1541237759,RU 1541237760,1541238271,CZ -1541238272,1541238783,ES 1541238784,1541239295,SK 1541239296,1541239807,PL 1541239808,1541240319,RU @@ -51355,7 +52215,6 @@ 1541275136,1541275647,FR 1541275648,1541276671,UA 1541276672,1541277695,RS -1541277696,1541278719,ES 1541278720,1541280767,UA 1541280768,1541281791,BG 1541281792,1541282815,PL @@ -51688,8 +52547,7 @@ 1541426176,1541426687,RU 1541426688,1541427199,UA 1541427200,1541428223,RU -1541428224,1541428735,UA -1541428736,1541429247,RU +1541428224,1541429247,UA 1541429248,1541429759,FI 1541429760,1541430271,CZ 1541430272,1541430783,LT @@ -51819,7 +52677,7 @@ 1541543936,1541544447,GB 1541544448,1541544959,PL 1541544960,1541545471,FR -1541545472,1541545983,RU +1541545472,1541545983,NL 1541545984,1541546495,LV 1541546496,1541547007,UA 1541547008,1541547519,SE @@ -51885,7 +52743,6 @@ 1541589248,1541589503,UA 1541589504,1541590015,CH 1541590016,1541590527,RU -1541590528,1541590783,DK 1541590784,1541591039,UA 1541591040,1541592063,RU 1541592064,1541592575,UA @@ -51908,6 +52765,167 @@ 1541602048,1541602303,PL 1541602304,1541603327,UA 1541603328,1541604351,PL +1541604352,1541605119,TR +1541605120,1541605375,CZ +1541605376,1541606911,RU +1541606912,1541607423,UZ +1541607424,1541608447,RU +1541608448,1541608703,DE +1541608704,1541608959,PL +1541608960,1541609215,SA +1541609216,1541609471,RU +1541609472,1541609983,SA +1541609984,1541610239,GB +1541610240,1541610495,NL +1541610496,1541611775,RU +1541611776,1541612031,RO +1541612032,1541612543,RU +1541612544,1541614079,PL +1541614080,1541614335,UA +1541614336,1541614591,SI +1541614592,1541615615,RU +1541615616,1541615871,CH +1541615872,1541616127,SE +1541616128,1541617663,RU +1541617664,1541619199,PL +1541619200,1541619455,GB +1541619456,1541620735,PL +1541620736,1541620991,RU +1541620992,1541621247,UA +1541621248,1541621759,IL +1541621760,1541622271,RO +1541622272,1541622527,RU +1541622528,1541622783,NL +1541622784,1541623295,PL +1541623296,1541623551,GB +1541623552,1541623679,RU +1541623808,1541624831,PL +1541624832,1541625855,RU +1541625856,1541626367,PL +1541626368,1541626623,RO +1541626624,1541627903,RU +1541627904,1541628415,CZ +1541628416,1541628927,DE +1541628928,1541629183,PT +1541629184,1541629439,LV +1541629440,1541630975,PL +1541630976,1541631231,GR +1541631232,1541631487,IT +1541631488,1541631999,SI +1541632000,1541632511,RU +1541632512,1541632767,NL +1541632768,1541633023,SK +1541633024,1541634303,PL +1541634304,1541634559,MD +1541634560,1541635071,PL +1541635072,1541636095,UA +1541636096,1541636863,AT +1541636864,1541637119,RO +1541637120,1541637631,PL +1541637632,1541638143,CZ +1541638144,1541638399,RU +1541638400,1541638655,FR +1541638656,1541639167,HU +1541639168,1541640191,RU +1541640192,1541641215,KZ +1541641216,1541641727,RU +1541641728,1541642239,UA +1541642240,1541643263,RU +1541643264,1541644287,PL +1541644288,1541645311,RU +1541645312,1541645823,IL +1541646080,1541646335,PL +1541646336,1541646847,RU +1541646848,1541647359,NO +1541647360,1541648383,RU +1541648384,1541648639,PL +1541648640,1541648895,DK +1541648896,1541649151,GB +1541649152,1541649407,NL +1541649408,1541650431,UA +1541650432,1541650687,RU +1541650688,1541650943,MD +1541650944,1541651199,SE +1541651200,1541651455,FI +1541651456,1541652479,RU +1541652480,1541652991,FI +1541652992,1541653247,FR +1541653248,1541653503,CZ +1541653504,1541654015,PL +1541654016,1541654271,RU +1541654272,1541655551,PL +1541655552,1541656063,AT +1541656064,1541656575,UA +1541656576,1541656831,SE +1541656832,1541657087,BE +1541657088,1541657599,RU +1541657600,1541659647,PL +1541659648,1541660671,GB +1541660672,1541661695,SK +1541661696,1541661951,RU +1541661952,1541662207,NL +1541662208,1541662719,RO +1541662720,1541663743,CZ +1541663744,1541664767,RO +1541664768,1541666047,RU +1541666048,1541666815,GB +1541666816,1541667839,NO +1541667840,1541668095,CH +1541668096,1541668351,GB +1541668352,1541668607,UA +1541668608,1541668863,GE +1541668864,1541669887,GB +1541669888,1541670911,LV +1541670912,1541671423,PL +1541671424,1541671679,RU +1541671680,1541671935,PL +1541671936,1541672959,UA +1541672960,1541674495,RS +1541674496,1541675007,KG +1541675008,1541675519,IE +1541675520,1541676031,RU +1541676288,1541676543,RO +1541676544,1541677055,RU +1541677056,1541678079,PL +1541678080,1541678591,RO +1541678592,1541678847,BG +1541678848,1541679615,RU +1541679616,1541680127,PL +1541680128,1541681151,CZ +1541681152,1541682175,RU +1541682176,1541682687,DE +1541682688,1541683199,RU +1541683200,1541683455,PL +1541683456,1541683711,RU +1541683712,1541684223,UA +1541684224,1541684735,CH +1541684736,1541686271,RU +1541686272,1541687295,UA +1541687296,1541688319,GB +1541688320,1541688831,RU +1541688832,1541689343,GB +1541689344,1541690367,PL +1541690368,1541691391,LT +1541691392,1541691903,PL +1541691904,1541692159,SE +1541692160,1541692415,ES +1541692416,1541693439,PL +1541693440,1541694463,RU +1541694464,1541694719,CZ +1541694720,1541694975,CH +1541694976,1541695487,RU +1541695488,1541696511,DE +1541696512,1541697535,MD +1541697536,1541698047,PL +1541698048,1541698303,DK +1541698304,1541698559,GB +1541698560,1541699327,RU +1541699328,1541699583,RO +1541699584,1541700095,RU +1541700096,1541700607,UA +1541700608,1541700863,RU +1541700864,1541701119,PL +1541701632,1541702655,RO 1543503872,1545601023,GB 1545601024,1545673167,SE 1545673168,1545673175,FI @@ -52032,7 +53050,9 @@ 1546379264,1546381311,ES 1546381312,1546383359,DK 1546383360,1546385407,IT -1546385408,1546387455,FR +1546385408,1546385535,FR +1546385536,1546385599,US +1546385600,1546387455,FR 1546387456,1546460960,TR 1546460961,1546460967,NL 1546460968,1546518527,TR @@ -52138,8 +53158,8 @@ 1547620352,1547620359,A2 1547620360,1547620367,NG 1547620368,1547620375,A2 -1547620376,1547620383,NG -1547620384,1547620399,A2 +1547620376,1547620391,NG +1547620392,1547620399,A2 1547620400,1547620407,NG 1547620408,1547620415,A2 1547620416,1547620423,NG @@ -52160,17 +53180,15 @@ 1547620936,1547620951,A2 1547620952,1547620959,NG 1547620960,1547620967,A2 -1547620968,1547620983,NG -1547620984,1547620999,A2 +1547620968,1547620991,NG +1547620992,1547620999,A2 1547621000,1547621031,NG 1547621032,1547621039,A2 1547621040,1547621063,NG 1547621064,1547621071,A2 1547621072,1547621087,NG 1547621088,1547621095,A2 -1547621096,1547621119,NG -1547621120,1547621127,A2 -1547621128,1547621135,NG +1547621096,1547621135,NG 1547621136,1547621143,A2 1547621144,1547621151,NG 1547621152,1547621167,A2 @@ -52187,9 +53205,77 @@ 1547621304,1547621335,NG 1547621336,1547621351,A2 1547621352,1547621375,NG -1547621376,1547622463,A2 -1547622464,1547622471,NG -1547622472,1547624447,A2 +1547621376,1547621447,A2 +1547621448,1547621455,NG +1547621456,1547621463,A2 +1547621464,1547621471,NG +1547621472,1547621575,A2 +1547621576,1547621583,NG +1547621584,1547621615,A2 +1547621616,1547621623,NG +1547621624,1547621687,A2 +1547621688,1547621711,NG +1547621712,1547622407,A2 +1547622408,1547622415,NG +1547622416,1547622455,A2 +1547622456,1547622471,NG +1547622472,1547622511,A2 +1547622512,1547622527,NG +1547622528,1547622559,A2 +1547622560,1547622575,NG +1547622576,1547622583,A2 +1547622584,1547622615,NG +1547622616,1547622623,A2 +1547622624,1547622631,NG +1547622632,1547622911,A2 +1547622912,1547622935,NG +1547622936,1547622951,A2 +1547622952,1547622959,NG +1547622960,1547622967,A2 +1547622968,1547622983,NG +1547622984,1547622991,A2 +1547622992,1547623015,NG +1547623016,1547623031,A2 +1547623032,1547623039,NG +1547623040,1547623047,A2 +1547623048,1547623071,NG +1547623072,1547623103,A2 +1547623104,1547623159,NG +1547623160,1547623167,A2 +1547623168,1547623175,NG +1547623176,1547623183,A2 +1547623184,1547623191,NG +1547623192,1547623199,A2 +1547623200,1547623207,NG +1547623208,1547623215,A2 +1547623216,1547623247,NG +1547623248,1547623255,A2 +1547623256,1547623263,NG +1547623264,1547623287,A2 +1547623288,1547623295,NG +1547623296,1547623319,A2 +1547623320,1547623327,NG +1547623328,1547623335,A2 +1547623336,1547623343,NG +1547623344,1547623359,A2 +1547623360,1547623367,NG +1547623368,1547623383,A2 +1547623384,1547623391,NG +1547623392,1547623399,A2 +1547623400,1547623415,NG +1547623416,1547623455,A2 +1547623456,1547623463,NG +1547623464,1547623479,A2 +1547623480,1547623487,NG +1547623488,1547623495,A2 +1547623496,1547623519,NG +1547623520,1547623527,A2 +1547623528,1547623559,NG +1547623560,1547623567,A2 +1547623568,1547623615,NG +1547623616,1547623727,A2 +1547623728,1547623735,NG +1547623736,1547624447,A2 1547624448,1547628543,CZ 1547628544,1547632639,BG 1547632640,1547636735,TR @@ -52277,7 +53363,8 @@ 1551556608,1551558655,FR 1551558656,1551560703,EU 1551560704,1551561727,DE -1551561728,1551564799,EU +1551561728,1551562751,FR +1551562752,1551564799,EU 1551564800,1551572991,FR 1551572992,1551576063,NL 1551576064,1551577087,EU @@ -52517,7 +53604,6 @@ 1566401920,1566401983,NO 1566401984,1566402047,AU 1566402048,1566402559,NO -1566402560,1566404607,IT 1566404608,1566406655,ES 1566406656,1566408703,NL 1566408704,1566410751,GB @@ -52737,7 +53823,8 @@ 1570652160,1570652287,SE 1570652288,1570652291,MY 1570652292,1570652295,GB -1570652296,1570652543,SE +1570652296,1570652299,DE +1570652300,1570652543,SE 1570652544,1570652551,FR 1570652552,1570652891,SE 1570652892,1570652895,DE @@ -52752,7 +53839,9 @@ 1570660360,1570660367,SE 1570660368,1570660383,FR 1570660384,1570660387,RU -1570660388,1570660543,SE +1570660388,1570660407,SE +1570660408,1570660411,DE +1570660412,1570660543,SE 1570660544,1570660575,FI 1570660576,1570660591,GB 1570660592,1570660595,RU @@ -52762,7 +53851,8 @@ 1570660616,1570660619,RU 1570660620,1570660623,SE 1570660624,1570660639,FR -1570660640,1570660863,SE +1570660640,1570660675,DE +1570660676,1570660863,SE 1570660864,1570661375,NO 1570661376,1570661631,GB 1570661632,1570662143,SE @@ -52780,7 +53870,9 @@ 1570665920,1570665935,GB 1570665936,1570665951,IT 1570665952,1570665967,FR -1570665968,1570666175,SE +1570665968,1570666143,SE +1570666144,1570666147,DE +1570666148,1570666175,SE 1570666176,1570666191,GB 1570666192,1570666223,FR 1570666224,1570666227,SE @@ -52789,7 +53881,9 @@ 1570666368,1570666383,FR 1570666384,1570666387,SE 1570666388,1570666391,NL -1570666392,1570666431,SE +1570666392,1570666395,SE +1570666396,1570666399,DE +1570666400,1570666431,SE 1570666432,1570666447,GB 1570666448,1570666463,DE 1570666464,1570666495,SE @@ -52804,7 +53898,9 @@ 1570666752,1570666755,ES 1570666756,1570666759,SE 1570666760,1570666767,GB -1570666768,1570666943,SE +1570666768,1570666887,SE +1570666888,1570666891,DE +1570666892,1570666943,SE 1570666944,1570666959,FR 1570666960,1570666975,SE 1570666976,1570666991,FR @@ -52813,7 +53909,9 @@ 1570667012,1570667015,SE 1570667016,1570667023,GB 1570667024,1570667039,ES -1570667040,1570667199,SE +1570667040,1570667167,SE +1570667168,1570667171,DE +1570667172,1570667199,SE 1570667200,1570667215,FR 1570667216,1570667231,SE 1570667232,1570667247,FR @@ -52825,7 +53923,8 @@ 1570667328,1570667335,SE 1570667336,1570667339,GB 1570667340,1570667343,NL -1570667344,1570667455,SE +1570667344,1570667347,DE +1570667348,1570667455,SE 1570667456,1570667471,FR 1570667472,1570667487,SE 1570667488,1570667503,FR @@ -52837,7 +53936,9 @@ 1570667532,1570667535,GB 1570667536,1570667587,SE 1570667588,1570667591,US -1570667592,1570667711,SE +1570667592,1570667599,SE +1570667600,1570667603,DE +1570667604,1570667711,SE 1570667712,1570667727,FR 1570667728,1570667743,NL 1570667744,1570667775,SE @@ -52849,7 +53950,9 @@ 1570667904,1570667907,SE 1570667908,1570667911,RU 1570667912,1570667915,US -1570667916,1570667967,SE +1570667916,1570667919,SE +1570667920,1570667923,DE +1570667924,1570667967,SE 1570667968,1570667983,FR 1570667984,1570668031,SE 1570668032,1570668035,NL @@ -52878,8 +53981,8 @@ 1571429376,1571432447,UA 1571432448,1571434495,CZ 1571434496,1571435519,UA -1571435520,1571435775,NL -1571435776,1571438591,CZ +1571435520,1571436031,NL +1571436032,1571438591,CZ 1571438592,1571441663,UA 1571441664,1571442175,KZ 1571442176,1571442687,NL @@ -53101,7 +54204,6 @@ 1572612096,1572614143,RU 1572614144,1572616191,ES 1572616192,1572618239,CH -1572618240,1572620287,RS 1572620288,1572620415,CH 1572620416,1572620431,CZ 1572620432,1572620559,CH @@ -53312,7 +54414,8 @@ 1578590536,1578590543,FR 1578590544,1578590559,GB 1578590560,1578590575,ES -1578590576,1578590603,FR +1578590576,1578590599,FR +1578590600,1578590603,LT 1578590604,1578590607,PL 1578590608,1578590615,FR 1578590616,1578590619,DE @@ -53325,9 +54428,11 @@ 1578590664,1578590667,FR 1578590668,1578590671,NL 1578590672,1578590687,PL -1578590688,1578590699,FR -1578590700,1578590731,PL -1578590732,1578590799,FR +1578590688,1578590691,GB +1578590692,1578590695,DE +1578590696,1578590699,FR +1578590700,1578590735,PL +1578590736,1578590799,FR 1578590800,1578590831,GB 1578590832,1578590839,FR 1578590840,1578590847,PL @@ -53362,7 +54467,8 @@ 1578591296,1578591327,FR 1578591328,1578591343,PL 1578591344,1578591391,FR -1578591392,1578591407,CH +1578591392,1578591395,IT +1578591396,1578591407,PL 1578591408,1578591411,ES 1578591412,1578591415,FR 1578591416,1578591423,ES @@ -53395,7 +54501,7 @@ 1578591808,1578591887,FR 1578591888,1578591891,DE 1578591892,1578591899,FR -1578591900,1578591903,GB +1578591900,1578591903,NL 1578591904,1578591919,PL 1578591920,1578591939,ES 1578591940,1578591951,FR @@ -53420,8 +54526,7 @@ 1578592208,1578592223,FR 1578592224,1578592239,ES 1578592240,1578592271,FR -1578592272,1578592275,PL -1578592276,1578592279,FI +1578592272,1578592279,PL 1578592280,1578592283,BE 1578592284,1578592287,NL 1578592288,1578592295,PL @@ -53442,7 +54547,8 @@ 1578592516,1578592519,PL 1578592520,1578592531,FR 1578592532,1578592535,GB -1578592536,1578592543,NL +1578592536,1578592539,PL +1578592540,1578592543,ES 1578592544,1578592559,FR 1578592560,1578592575,NL 1578592576,1578592591,GB @@ -53452,8 +54558,14 @@ 1578592720,1578592735,CH 1578592736,1578592743,PL 1578592744,1578592747,PT -1578592748,1578592783,DE -1578592784,1578592831,FR +1578592748,1578592751,DE +1578592752,1578592767,IE +1578592768,1578592783,DE +1578592784,1578592799,FR +1578592800,1578592807,GB +1578592808,1578592811,FR +1578592812,1578592815,PL +1578592816,1578592831,FR 1578592832,1578592847,PL 1578592848,1578592851,BE 1578592852,1578592855,DE @@ -53479,7 +54591,10 @@ 1578593416,1578593423,PL 1578593424,1578593439,FR 1578593440,1578593455,PL -1578593456,1578593487,FR +1578593456,1578593471,FR +1578593472,1578593479,GB +1578593480,1578593483,PL +1578593484,1578593487,FR 1578593488,1578593495,ES 1578593496,1578593503,FR 1578593504,1578593519,PL @@ -53532,7 +54647,10 @@ 1578594088,1578594095,CZ 1578594096,1578594111,FR 1578594112,1578594127,PL -1578594128,1578594159,FR +1578594128,1578594143,FR +1578594144,1578594147,PL +1578594148,1578594151,ES +1578594152,1578594159,IT 1578594160,1578594163,PT 1578594164,1578594167,ES 1578594168,1578594171,DE @@ -53587,8 +54705,8 @@ 1578594784,1578594799,FR 1578594800,1578594815,DE 1578594816,1578594847,FR -1578594848,1578594863,IT -1578594864,1578594871,GB +1578594848,1578594867,IT +1578594868,1578594871,BE 1578594872,1578595039,FR 1578595040,1578595055,GB 1578595056,1578595103,FR @@ -53613,9 +54731,7 @@ 1578595328,1578595343,IT 1578595344,1578595363,FR 1578595364,1578595367,DE -1578595368,1578595371,FR -1578595372,1578595375,BE -1578595376,1578595379,FR +1578595368,1578595379,FR 1578595380,1578595383,CH 1578595384,1578595387,ES 1578595388,1578595407,PL @@ -53688,7 +54804,8 @@ 1578610768,1578610771,CH 1578610772,1578610775,GB 1578610776,1578610779,DE -1578610780,1578610799,FR +1578610780,1578610783,FR +1578610784,1578610799,DE 1578610800,1578610803,PL 1578610804,1578610807,GB 1578610808,1578610943,FR @@ -53734,7 +54851,7 @@ 1578611776,1578611783,DE 1578611784,1578611807,FR 1578611808,1578611839,CH -1578611840,1578611855,ES +1578611840,1578611855,BE 1578611856,1578611919,FR 1578611920,1578611935,BE 1578611936,1578611943,PL @@ -53753,7 +54870,7 @@ 1578612120,1578612123,IE 1578612124,1578612127,DE 1578612128,1578612135,ES -1578612136,1578612139,NL +1578612136,1578612139,IE 1578612140,1578612143,ES 1578612144,1578612223,PL 1578612224,1578612239,IT @@ -53776,7 +54893,7 @@ 1578612904,1578612907,DE 1578612908,1578612911,FR 1578612912,1578612959,ES -1578612960,1578612975,FR +1578612960,1578612975,DE 1578612976,1578612983,IT 1578612984,1578612991,FR 1578612992,1578613247,DE @@ -53815,7 +54932,14 @@ 1578614196,1578614207,GB 1578614208,1578614271,PL 1578614272,1578614527,ES -1578614528,1578631167,FR +1578614528,1578614543,GB +1578614544,1578614559,PL +1578614560,1578614575,FR +1578614576,1578614583,DE +1578614584,1578614591,GB +1578614592,1578614623,CZ +1578614624,1578614655,BE +1578614656,1578631167,FR 1578631168,1578663935,RO 1578663936,1578762239,RU 1578762240,1578795007,BG @@ -53881,7 +55005,9 @@ 1581826048,1581842431,GB 1581842432,1581858815,BG 1581858816,1581875199,IT -1581875200,1581891583,TR +1581875200,1581881343,TR +1581881344,1581881599,GB +1581881600,1581891583,TR 1581891584,1581907967,RU 1581907968,1581924351,IT 1581924352,1581940735,UA @@ -53958,7 +55084,9 @@ 1583742976,1583747071,TR 1583747072,1583751167,RU 1583751168,1583755263,NO -1583755264,1583759359,NL +1583755264,1583755414,NL +1583755415,1583755424,RU +1583755425,1583759359,NL 1583759360,1583763455,TR 1583763456,1583767551,RU 1583767552,1583771647,AT @@ -53993,7 +55121,9 @@ 1583815216,1583815343,NL 1583815344,1583815351,US 1583815352,1583816703,NL -1583816704,1583820799,TR +1583816704,1583819007,TR +1583819008,1583819136,GB +1583819137,1583820799,TR 1583820800,1583824895,LV 1583824896,1583828991,SI 1583828992,1583833087,RU @@ -54049,7 +55179,6 @@ 1585231360,1585231615,NL 1585231616,1585231871,RU 1585231872,1585233919,CZ -1585233920,1585235967,LB 1585235968,1585238015,RU 1585238016,1585240063,DE 1585240064,1585241087,FR @@ -54292,6 +55421,15 @@ 1586495488,1587019775,DK 1587019776,1587085311,PL 1587085312,1587150847,UA +1587150848,1587154943,RU +1587154944,1587159039,PL +1587159040,1587163135,UA +1587163136,1587165183,DE +1587165184,1587167231,PL +1587167232,1587175423,RU +1587175424,1587177471,PL +1587177472,1587179519,RS +1587179520,1587183615,UA 1587183616,1587199999,RU 1587200000,1587216383,UA 1587216384,1587347455,BG @@ -54434,20 +55572,26 @@ 1592061952,1592066047,RU 1592066048,1592067583,US 1592067584,1592067711,NO -1592067712,1592069119,CY +1592067712,1592067839,CY +1592067840,1592068095,NL +1592068096,1592069119,CY 1592069120,1592069135,RU 1592069136,1592069247,CY 1592069248,1592069375,RU 1592069376,1592069407,US 1592069408,1592069631,CY -1592069632,1592069759,NL -1592069760,1592069855,CY -1592069856,1592069887,NL +1592069632,1592069711,NL +1592069712,1592069727,CY +1592069728,1592069759,NL +1592069760,1592069839,CY +1592069840,1592069887,NL 1592069888,1592074239,RU 1592074240,1592078335,SK 1592078336,1592082431,NL 1592082432,1592086527,GB -1592086528,1592087295,CZ +1592086528,1592087079,CZ +1592087080,1592087087,PL +1592087088,1592087295,CZ 1592087296,1592088191,PL 1592088192,1592090623,CZ 1592090624,1592094719,RU @@ -54510,7 +55654,6 @@ 1592326144,1592328191,UA 1592328192,1592393727,RU 1592393728,1592459263,SE -1592459264,1592524799,GE 1592524800,1592540415,GB 1592540416,1592540423,A2 1592540424,1592557567,GB @@ -54878,8 +56021,16 @@ 1602449408,1602451455,LV 1602451456,1602453503,DE 1602453504,1602455551,SK -1602455552,1602456015,FR -1602456016,1602456031,ES +1602455552,1602455690,FR +1602455691,1602455691,BE +1602455692,1602456015,FR +1602456016,1602456025,ES +1602456026,1602456026,DE +1602456027,1602456027,NL +1602456028,1602456028,IT +1602456029,1602456029,ES +1602456030,1602456030,PT +1602456031,1602456031,ES 1602456032,1602456175,FR 1602456176,1602456183,ES 1602456184,1602457599,FR @@ -54960,7 +56111,8 @@ 1603161008,1603161023,GB 1603161024,1603161103,DE 1603161104,1603161119,GB -1603161120,1603161567,DE +1603161120,1603161135,AT +1603161136,1603161567,DE 1603161568,1603161599,FR 1603161600,1603162111,DE 1603162112,1603166207,TJ @@ -55026,8 +56178,8 @@ 1603225632,1603225639,US 1603225640,1603225647,CN 1603225648,1603225855,FR -1603225856,1603226111,GB -1603226112,1603227647,FR +1603225856,1603226623,GB +1603226624,1603227647,FR 1603227648,1603231743,AT 1603231744,1603235839,IT 1603235840,1603239935,RU @@ -55064,7 +56216,9 @@ 1603982784,1603982847,AN 1603982848,1603984895,GB 1603984896,1603985151,PT -1603985152,1603990271,GB +1603985152,1603985279,GB +1603985280,1603985407,BR +1603985408,1603990271,GB 1603990272,1603990527,SA 1603990528,1603993599,GB 1603993600,1604009983,ME @@ -55170,8 +56324,8 @@ 1605125280,1605125335,GB 1605125336,1605125343,US 1605125344,1605125375,GB -1605125376,1605125919,US -1605125920,1605126143,GB +1605125376,1605125903,US +1605125904,1605126143,GB 1605126144,1605127679,US 1605127680,1605127935,GB 1605127936,1605128703,US @@ -55203,7 +56357,6 @@ 1605230592,1605238783,TR 1605238784,1605246975,IT 1605246976,1605255167,PL -1605255168,1605263359,HU 1605263360,1605271551,RU 1605271552,1605279743,DE 1605279744,1605287935,FR @@ -55290,9 +56443,7 @@ 1607966720,1607967743,RU 1607967744,1607968767,UA 1607968768,1607969791,SE -1607969792,1607970815,RU 1607972864,1607974911,NL -1607974912,1607975935,LV 1607976960,1607977983,KZ 1607979008,1607980031,RU 1607980032,1607981055,DE @@ -55419,8 +56570,13 @@ 1614741504,1614757887,CA 1614757888,1614774271,US 1614774272,1614786559,CA -1614786560,1618886655,US -1618968576,1618984959,US +1614786560,1618837503,US +1618837504,1618841599,CA +1618841600,1618849791,US +1618849792,1618862079,CA +1618862080,1618866175,US +1618866176,1618870271,CA +1618870272,1618984959,US 1618984960,1619001343,CA 1619001344,1632305151,US 1632305152,1632321535,CA @@ -56294,7 +57450,10 @@ 1710949376,1710950399,NP 1710950400,1711210495,CN 1711210496,1711276031,ID -1728053248,1728120831,AU +1728053248,1728120063,AU +1728120064,1728120319,SG +1728120320,1728120575,IN +1728120576,1728120831,AU 1728120832,1728121855,CN 1728121856,1728123903,HK 1728123904,1728125951,CN @@ -56389,6 +57548,89 @@ 1728291840,1728292863,SG 1728292864,1728293887,PG 1728293888,1728294911,MY +1728294912,1728295935,TH +1728295936,1728299007,JP +1728299008,1728300031,TW +1728300032,1728301055,AU +1728301056,1728302079,SG +1728302080,1728303103,IN +1728303104,1728305151,ID +1728305152,1728306175,AU +1728306176,1728307199,ID +1728307200,1728308223,BD +1728308224,1728309247,IN +1728309248,1728310271,NZ +1728310272,1728311295,AU +1728311296,1728312319,GU +1728312320,1728315391,VN +1728315392,1728316415,ID +1728316416,1728317439,MY +1728317440,1728318463,JP +1728318464,1728319487,SG +1728319488,1728320511,AU +1728320512,1728321535,PH +1728321536,1728322559,JP +1728322560,1728323583,MY +1728323584,1728324607,JP +1728324608,1728325631,SG +1728325632,1728326655,JP +1728326656,1728327679,MY +1728327680,1728328703,KR +1728328704,1728329727,ID +1728329728,1728330751,CN +1728330752,1728331775,AU +1728708608,1728709631,CN +1728709632,1728710655,TW +1728710656,1728710911,AU +1728710912,1728711167,IN +1728711424,1728711679,AU +1728711680,1728712703,HK +1728712704,1728713727,CN +1728713728,1728714751,MN +1728714752,1728715775,IN +1728715776,1728716799,NP +1728716800,1728717823,AU +1728717824,1728718847,JP +1728718848,1728719871,MY +1728719872,1728720895,NZ +1728720896,1728721919,AU +1728721920,1728722943,BD +1728722944,1728723199,ID +1728723200,1728723455,AU +1728723456,1728724991,ID +1729544192,1729545215,IN +1729545216,1729546239,AU +1729546240,1729547263,HK +1729547264,1729548287,IN +1729548288,1729549311,AU +1729549312,1729550335,JP +1729550336,1729551359,MY +1729551360,1729552383,KR +1729552384,1729553407,AU +1729553408,1729554431,CN +1729554432,1729554943,ID +1729555456,1729556479,IN +1729556480,1729557503,ID +1729557504,1729558527,HK +1729558528,1729559551,ID +1729559552,1729560575,CN +1729953792,1729954815,MY +1729954816,1729955839,ID +1729961984,1729964031,IN +1729964032,1729965055,AU +1729965056,1729966079,IN +1729966080,1729967103,JP +1729967104,1729968127,AU +1729968128,1729969151,MY +1729969152,1729970175,LK +1744199680,1744201727,AU +1744201728,1744201983,VN +1744202240,1744202495,IN +1744202496,1744202751,ID +1744202752,1744203775,PK +1744203776,1744204799,MY +1744204800,1744205823,ID +1744205824,1744207871,CN 1778384896,1778385151,CN 1778385152,1778385407,AU 1778385408,1778393087,CN @@ -56424,7 +57666,9 @@ 1815912448,1815920639,CA 1815920640,1815928831,US 1815928832,1815937023,BS -1815937024,1816068095,US +1815937024,1816024319,US +1816024320,1816024575,CA +1816024576,1816068095,US 1816068096,1816133631,CA 1816133632,1828716543,US 1828716544,1830813695,FR @@ -56480,7 +57724,7 @@ 1833248768,1833250815,MK 1833250816,1833254911,GB 1833254912,1833256959,DE -1833256960,1833261055,GB +1833259008,1833261055,GB 1833261056,1833263103,PL 1833263104,1833265151,DE 1833265152,1833267199,GB @@ -56488,7 +57732,6 @@ 1833269248,1833271295,FI 1833271296,1833273343,IT 1833273344,1833275391,EU -1833275392,1833277439,GB 1833277440,1833279487,CH 1833279488,1833281535,AL 1833281536,1833283583,AT @@ -56609,7 +57852,8 @@ 1833468592,1833471999,CH 1833472000,1833474047,EU 1833474048,1833474559,UA -1833474560,1833476095,EU +1833474560,1833474815,RU +1833474816,1833476095,EU 1833476096,1833477375,NL 1833477376,1833477503,GB 1833477504,1833477631,DE @@ -56669,17 +57913,15 @@ 1833648128,1833652223,LB 1833652224,1833659903,DE 1833659904,1833659919,NA -1833659920,1833660159,DE -1833660160,1833660175,CH -1833660176,1833660179,DE -1833660180,1833660223,CH -1833660224,1833660351,DE +1833659920,1833660351,DE 1833660352,1833660415,US 1833660416,1833664511,IT 1833664512,1833668607,RU 1833668608,1833672703,CZ 1833672704,1833676799,GB -1833676800,1833680895,DE +1833676800,1833677567,DE +1833677568,1833677599,CH +1833677600,1833680895,DE 1833680896,1833684991,UA 1833684992,1833689087,DE 1833689088,1833693183,FI @@ -56786,12 +58028,10 @@ 1835909120,1835913215,RS 1835913216,1835917311,RU 1835917312,1835920127,GB -1835920128,1835920143,PT -1835920144,1835920151,GB -1835920152,1835920159,PT -1835920160,1835920263,GB -1835920264,1835920279,PT -1835920280,1835925503,GB +1835920128,1835920159,PT +1835920160,1835920255,GB +1835920256,1835920303,PT +1835920304,1835925503,GB 1835925504,1835933695,LV 1835933696,1835941887,RU 1835941888,1835950079,UA @@ -56874,7 +58114,9 @@ 1839796608,1839796671,US 1839796672,1839797759,GB 1839797760,1839798015,GR -1839798016,1839798527,GB +1839798016,1839798271,GB +1839798272,1839798399,DE +1839798400,1839798527,GB 1839798528,1839798559,US 1839798560,1839800447,GB 1839800448,1839800479,SG @@ -56887,13 +58129,13 @@ 1839801344,1839801471,CN 1839801472,1839801551,GB 1839801552,1839801567,US -1839801568,1839801599,GB -1839801600,1839801855,US -1839801856,1839802111,GB +1839801568,1839802111,GB 1839802112,1839802239,RO 1839802240,1839806463,GB 1839806464,1839811071,US -1839811072,1839816703,GB +1839811072,1839811455,GB +1839811456,1839811583,IE +1839811584,1839816703,GB 1839816704,1839824895,NO 1839824896,1839890431,RU 1839890432,1839923199,GB @@ -57199,7 +58441,10 @@ 1844127744,1844129791,DE 1844129792,1844131583,NL 1844131584,1844131711,SC -1844131712,1844131839,NL +1844131712,1844131743,NL +1844131744,1844131775,RU +1844131776,1844131807,AE +1844131808,1844131839,US 1844131840,1844133887,DE 1844133888,1844135935,LT 1844135936,1844137983,NL @@ -57227,7 +58472,8 @@ 1844169656,1844169663,SE 1844169664,1844169679,US 1844169680,1844169687,ZM -1844169688,1844169727,SE +1844169688,1844169695,IQ +1844169696,1844169727,SE 1844169728,1844169767,DE 1844169768,1844169951,US 1844169952,1844169983,DE @@ -57235,9 +58481,10 @@ 1844169988,1844169991,DE 1844169992,1844169995,AF 1844169996,1844169999,TM -1844170000,1844170007,DE -1844170008,1844170015,AF -1844170016,1844170751,DE +1844170000,1844170015,AF +1844170016,1844170239,DE +1844170240,1844170247,AF +1844170248,1844170751,DE 1844170752,1844174847,RU 1844174848,1844178943,DE 1844178944,1844180991,EE @@ -57249,7 +58496,23 @@ 1844181953,1844181958,GB 1844181959,1844181984,TR 1844181985,1844181990,GB -1844181991,1844183039,TR +1844181991,1844182272,TR +1844182273,1844182302,US +1844182303,1844182309,TR +1844182310,1844182329,US +1844182330,1844182343,TR +1844182344,1844182403,US +1844182404,1844182416,TR +1844182417,1844182417,US +1844182418,1844182424,TR +1844182425,1844182426,US +1844182427,1844182432,TR +1844182433,1844182480,US +1844182481,1844182485,TR +1844182486,1844182489,US +1844182490,1844182501,TR +1844182502,1844182511,US +1844182512,1844183039,TR 1844183040,1844191231,IT 1844191232,1844195327,AL 1844195328,1844203519,RU @@ -57257,7 +58520,9 @@ 1844207616,1844211711,RU 1844211712,1844215807,SK 1844215808,1844219903,BE -1844219904,1844220159,A2 +1844219904,1844219919,A2 +1844219920,1844219959,LB +1844219960,1844220159,A2 1844220160,1844220191,IQ 1844220192,1844220415,DE 1844220416,1844220431,A2 @@ -57290,7 +58555,8 @@ 1844310016,1844318207,FR 1844318208,1844322303,IT 1844322304,1844326399,CZ -1844326400,1844330495,DK +1844326400,1844329983,DK +1844329984,1844330495,LU 1844330496,1844334591,GB 1844334592,1844342783,RU 1844342784,1844346879,IT @@ -57715,7 +58981,6 @@ 1888266240,1888268287,JP 1888268288,1888270335,AU 1888270336,1888271359,SG -1888271360,1888272383,TH 1888272384,1888288767,KR 1888288768,1888354303,AU 1888354304,1888485375,TH @@ -57850,7 +59115,9 @@ 1908539392,1908670463,CN 1908670464,1908735999,TW 1908736000,1908740095,AU -1908740096,1908748287,JP +1908740096,1908744191,JP +1908744192,1908746239,SG +1908746240,1908748287,JP 1908748288,1908750335,PK 1908750336,1908752383,JP 1908752384,1908753407,NZ @@ -58319,7 +59586,7 @@ 1958830080,1958838271,JP 1958838272,1958842367,IN 1958842368,1958844415,NZ -1958844416,1958846463,HK +1958845440,1958846463,HK 1958846464,1958848511,IN 1958848512,1958850559,BD 1958850560,1958853631,AU @@ -60879,7 +62146,9 @@ 2332098560,2332622847,DE 2332622848,2332688383,CN 2332688384,2332753919,NL -2332753920,2333868031,DE +2332753920,2333736959,DE +2333736960,2333802495,EU +2333802496,2333868031,DE 2333933568,2334064639,DE 2334064640,2334916607,US 2334916608,2334982143,AU @@ -61535,7 +62804,7 @@ 2453864448,2453929983,CH 2453929984,2454061055,US 2454061056,2454126591,GB -2454126592,2454192127,US +2454159360,2454192127,US 2454192128,2454257663,NO 2454257664,2454388735,US 2454388736,2454454271,SE @@ -61962,7 +63231,7 @@ 2532114432,2532179967,GB 2532179968,2532376575,US 2532376576,2532442111,ES -2532442112,2532507647,FR +2532442112,2532507647,EU 2532507648,2532573183,US 2532573184,2532638719,ES 2532638720,2533031935,US @@ -63672,20 +64941,46 @@ 2899443712,2899574783,FR 2899574784,2899902463,GB 2902458368,2902462463,A1 -2902462464,2902470936,US +2902462464,2902470775,US +2902470776,2902470777,BD +2902470778,2902470936,US 2902470937,2902470938,LK -2902470939,2902471468,US +2902470939,2902470986,US +2902470987,2902470989,BD +2902470990,2902471468,US 2902471469,2902471470,AU 2902471471,2902471895,US 2902471896,2902471897,AU 2902471898,2902471960,US 2902471961,2902471962,AU -2902471963,2902472037,US +2902471963,2902472018,US +2902472019,2902472021,AL +2902472022,2902472037,US 2902472038,2902472039,AU -2902472040,2902472834,US +2902472040,2902472725,US +2902472726,2902472728,BD +2902472729,2902472788,US +2902472789,2902472790,LK +2902472791,2902472813,US +2902472814,2902472814,LK +2902472815,2902472834,US 2902472835,2902472836,BD -2902472837,2902492927,US -2902492928,2902493183,IN +2902472837,2902473028,US +2902473029,2902473031,IN +2902473032,2902473107,US +2902473108,2902473109,BD +2902473110,2902473649,US +2902473650,2902473650,BD +2902473651,2902473652,US +2902473653,2902473653,BD +2902473654,2902474023,US +2902474024,2902474032,RU +2902474033,2902474062,US +2902474063,2902474073,RU +2902474074,2902475263,US +2902475264,2902475327,CY +2902475328,2902492671,US +2902492672,2902493183,IN 2902493184,2902507519,US 2902507520,2902515711,CA 2902515712,2904555519,US @@ -63745,7 +65040,7 @@ 2915765288,2915765343,US 2915765344,2915765351,NZ 2915765352,2915765367,US -2915765368,2915765375,PE +2915765368,2915765375,ZA 2915765376,2915765431,US 2915765432,2915765439,MX 2915765440,2915765471,US @@ -64060,37 +65355,38 @@ 2916434560,2916434591,CA 2916434592,2916434623,US 2916434624,2916434655,CA -2916434656,2916436543,US +2916434656,2916436487,US +2916436488,2916436495,CA +2916436496,2916436543,US 2916436544,2916436607,CA -2916436608,2916436735,US -2916436736,2916436743,CA -2916436744,2916437039,US +2916436608,2916437039,US 2916437040,2916437047,DE 2916437048,2916437055,CN 2916437056,2916437063,GB -2916437064,2916437503,US +2916437064,2916437199,US +2916437200,2916437207,GB +2916437208,2916437215,TH +2916437216,2916437231,US +2916437232,2916437239,SG +2916437240,2916437503,US 2916437504,2916437567,CA 2916437568,2916440143,US 2916440144,2916440159,CA 2916440160,2916440175,US 2916440176,2916440191,CA -2916440192,2916440223,US -2916440224,2916440239,CA -2916440240,2916440287,US +2916440192,2916440287,US 2916440288,2916440295,CA 2916440296,2916441119,US 2916441120,2916441151,CA -2916441152,2916441191,US -2916441192,2916441199,CA -2916441200,2916441343,US +2916441152,2916441199,US +2916441200,2916441207,MY +2916441208,2916441343,US 2916441344,2916442111,CA 2916442112,2916442623,US 2916442624,2916442879,CA 2916442880,2916443614,US 2916443615,2916443647,CA -2916443648,2916444351,US -2916444352,2916444359,CA -2916444360,2916444927,US +2916443648,2916444927,US 2916444928,2916445951,CA 2916445952,2916449279,US 2916449280,2916450303,CA @@ -64110,9 +65406,7 @@ 2917168000,2917168031,UA 2917168032,2917168095,US 2917168096,2917168127,NZ -2917168128,2917168159,US -2917168160,2917168191,NL -2917168192,2917168223,US +2917168128,2917168223,US 2917168224,2917168255,BR 2917168256,2917168319,US 2917168320,2917168351,AR @@ -64124,15 +65418,12 @@ 2917168608,2917168639,BR 2917168640,2917169663,US 2917169664,2917169695,DE -2917169696,2917169727,NL -2917169728,2917170015,US +2917169696,2917170015,US 2917170016,2917170047,UA 2917170048,2917170079,BR -2917170080,2917170111,NL +2917170080,2917170111,US 2917170112,2917170143,RU -2917170144,2917170175,US -2917170176,2917170207,NL -2917170208,2917170239,US +2917170144,2917170239,US 2917170240,2917170271,RU 2917170272,2917170303,BR 2917170304,2917193025,US @@ -64221,7 +65512,9 @@ 2918199680,2918199743,CA 2918199744,2918200287,US 2918200288,2918200303,CA -2918200304,2918232063,US +2918200304,2918201551,US +2918201552,2918201567,CA +2918201568,2918232063,US 2918232064,2918236159,CA 2918236160,2918260735,US 2918260736,2918264831,CA @@ -64257,8 +65550,8 @@ 2918481920,2918514943,US 2918514944,2918515079,CA 2918515080,2918532111,US -2918532112,2918532127,CN -2918532128,2918532143,US +2918532112,2918532119,CN +2918532120,2918532143,US 2918532144,2918532151,PK 2918532152,2918533119,US 2918533120,2918533127,CN @@ -64275,29 +65568,24 @@ 2918534704,2918534735,CN 2918534736,2918534751,US 2918534752,2918534767,CN -2918534768,2918534783,US -2918534784,2918534807,CN +2918534768,2918534799,US +2918534800,2918534807,CN 2918534808,2918534815,US -2918534816,2918534887,CN -2918534888,2918534911,US +2918534816,2918534879,CN +2918534880,2918534911,US 2918534912,2918534943,KR -2918534944,2918534983,CN +2918534944,2918534975,CN +2918534976,2918534983,US 2918534984,2918534991,ID 2918534992,2918535199,US 2918535200,2918535231,CN 2918535232,2918535423,US 2918535424,2918535679,CN 2918535680,2918535807,US -2918535808,2918536191,CN -2918536192,2918536703,US -2918536704,2918536711,CN -2918536712,2918536767,US -2918536768,2918536791,CN -2918536792,2918536799,US -2918536800,2918536815,CN -2918536816,2918536823,US -2918536824,2918536959,CN -2918536960,2918537215,US +2918535808,2918535967,CN +2918535968,2918535983,US +2918535984,2918536191,CN +2918536192,2918537215,US 2918537216,2918537615,CN 2918537616,2918537623,US 2918537624,2918537727,CN @@ -64572,8 +65860,7 @@ 2919170552,2919170559,FR 2919170560,2919170575,US 2919170576,2919170583,FR -2919170584,2919170591,US -2919170592,2919170599,CN +2919170584,2919170599,US 2919170600,2919170607,JP 2919170608,2919170615,US 2919170616,2919170623,CN @@ -64618,11 +65905,24 @@ 2919171144,2919171151,TR 2919171152,2919171159,US 2919171160,2919171167,AU -2919171168,2919174143,US +2919171168,2919171311,US +2919171312,2919171319,IL +2919171320,2919171327,TW +2919171328,2919171343,US +2919171344,2919171351,BR +2919171352,2919171399,US +2919171400,2919171407,IT +2919171408,2919171455,US +2919171456,2919171463,BR +2919171464,2919171479,US +2919171480,2919171487,BR +2919171488,2919174143,US 2919174144,2919178239,CA 2919178240,2919186431,US 2919186432,2919190527,CA -2919190528,2919202815,US +2919190528,2919202079,US +2919202080,2919202111,BE +2919202112,2919202815,US 2919206912,2919211007,CA 2919219200,2919235583,US 2919235584,2919759871,CA @@ -64696,7 +65996,9 @@ 2928175056,2928175063,MX 2928175064,2928175143,US 2928175144,2928175151,PH -2928175152,2928175271,US +2928175152,2928175207,US +2928175208,2928175215,CA +2928175216,2928175271,US 2928175272,2928175279,NZ 2928175280,2928175303,US 2928175304,2928175311,CN @@ -65667,7 +66969,94 @@ 2948135936,2948136959,IN 2948136960,2948595711,CN 2948595712,2952790015,KR -2969567232,2973761535,BR +2952790016,2953314303,DE +2953314304,2953379839,UA +2953379840,2953445375,DE +2953445376,2953453567,IT +2953453568,2953455615,IS +2953455616,2953457663,SK +2953457664,2953459711,DE +2953459712,2953461759,IT +2953461760,2953465855,ES +2953465856,2953467903,EU +2953467904,2953469951,BE +2953469952,2953478143,CH +2953478144,2953510911,SE +2953510912,2953576447,NO +2953576448,2953592831,BG +2953592832,2953596927,IR +2953596928,2953598975,ES +2953598976,2953601023,IT +2953601024,2953603071,RU +2953603072,2953609215,GB +2953609216,2953707519,IL +2953707520,2953838591,RU +2953838592,2954100735,SA +2954100736,2954362879,DK +2954362880,2954625023,GB +2954625024,2954641407,DE +2954641408,2954643455,RU +2954643456,2954645503,IQ +2954645504,2954647551,AZ +2954647552,2954657791,ES +2954657792,2954756095,JO +2954756096,2954821631,TR +2954821632,2954887167,FR +2954887168,2954891263,UA +2954891264,2954895359,IT +2954895360,2954897407,RU +2954897408,2954899455,DE +2954899456,2954901503,ES +2954901504,2954903551,IT +2954903552,2954919935,IE +2954919936,2954928127,RU +2954928128,2954932223,PL +2954932224,2954936319,RU +2954936320,2954938367,AM +2954938368,2954940415,HU +2954940416,2954944511,DE +2954944512,2954946559,GB +2954946560,2954948607,DE +2954948608,2954950655,RU +2954950656,2954952703,ES +2954952704,2955018239,TR +2955018240,2955083775,IE +2955083776,2955149311,GB +2955149312,2955411455,UA +2955411456,2955673599,TR +2955673600,2955804671,SA +2955804672,2955837439,EE +2955837440,2955845631,IR +2955845632,2955853823,GB +2955853824,2955870207,CH +2955870208,2955935743,UA +2955935744,2956230655,RU +2956230656,2956238847,SI +2956238848,2956242943,ES +2956242944,2956244991,SE +2956244992,2956247039,FR +2956247040,2956249087,DE +2956249088,2956251135,RU +2956251136,2956253183,GB +2956253184,2956255231,IE +2956255232,2956259327,FR +2956259328,2956261375,DE +2956261376,2956263423,ES +2956263424,2956296191,TR +2956296192,2956328959,RU +2956328960,2956460031,TR +2956460032,2956468223,RU +2956468224,2956470271,LV +2956470272,2956472319,NL +2956472320,2956474367,RU +2956474368,2956476415,GB +2956476416,2956492799,ES +2956492800,2956496895,CH +2956496896,2956500991,IR +2956500992,2956509183,RU +2956509184,2956517375,GB +2956517376,2956521471,NL +2969567232,2977955839,BR 2986344448,2987393023,DE 2987393024,2987397119,IM 2987397120,2987401215,LV @@ -65810,7 +67199,6 @@ 2987755520,2987757567,PL 2987757568,2987759615,DE 2987759616,2987761663,PL -2987761664,2987763711,DK 2987763712,2987765759,GR 2987765760,2987767807,FR 2987767808,2987769855,CZ @@ -65902,7 +67290,7 @@ 2988441696,2988441791,FR 2988441792,2988441807,PL 2988441808,2988441815,FR -2988441816,2988441819,GB +2988441816,2988441819,FI 2988441820,2988441839,FR 2988441840,2988441843,PL 2988441844,2988441847,BE @@ -65924,7 +67312,8 @@ 2988441980,2988441983,IT 2988441984,2988441991,FR 2988441992,2988441995,ES -2988441996,2988442003,FR +2988441996,2988441999,PT +2988442000,2988442003,FR 2988442004,2988442007,ES 2988442008,2988442047,FR 2988442048,2988442063,GB @@ -65937,8 +67326,8 @@ 2988442432,2988442439,CZ 2988442440,2988442447,ES 2988442448,2988442463,GB -2988442464,2988442639,FR -2988442640,2988442647,PL +2988442464,2988442623,FR +2988442624,2988442647,PL 2988442648,2988442651,DE 2988442652,2988442655,GB 2988442656,2988442671,PL @@ -65990,7 +67379,7 @@ 2988443928,2988444167,FR 2988444168,2988444171,CZ 2988444172,2988444199,FR -2988444200,2988444203,DE +2988444200,2988444203,FI 2988444204,2988444207,NL 2988444208,2988444415,FR 2988444416,2988444679,ES @@ -66058,7 +67447,8 @@ 2988448512,2988448515,GB 2988448516,2988448519,FR 2988448520,2988448543,PL -2988448544,2988448551,FR +2988448544,2988448547,GB +2988448548,2988448551,FR 2988448552,2988448559,PL 2988448560,2988448563,DE 2988448564,2988448575,ES @@ -66094,7 +67484,9 @@ 2988449536,2988449579,FR 2988449580,2988449583,PL 2988449584,2988449631,FR -2988449632,2988449647,ES +2988449632,2988449639,ES +2988449640,2988449643,CH +2988449644,2988449647,CZ 2988449648,2988449663,FR 2988449664,2988449695,DE 2988449696,2988449727,IT @@ -66107,7 +67499,9 @@ 2988457984,2988457987,FR 2988457988,2988457991,PL 2988457992,2988457995,CH -2988457996,2988458031,FR +2988457996,2988457999,FR +2988458000,2988458015,DE +2988458016,2988458031,FR 2988458032,2988458047,IT 2988458048,2988458055,PL 2988458056,2988458063,CH @@ -66170,7 +67564,7 @@ 2988459260,2988459263,NL 2988459264,2988459519,ES 2988459520,2988459583,DE -2988459584,2988459599,FR +2988459584,2988459599,ES 2988459600,2988459603,GB 2988459604,2988459615,FR 2988459616,2988459631,CZ @@ -66200,8 +67594,7 @@ 2988459856,2988459863,FR 2988459864,2988459867,ES 2988459868,2988459871,GB -2988459872,2988459887,FR -2988459888,2988459895,PL +2988459872,2988459895,PL 2988459896,2988459967,FR 2988459968,2988459999,ES 2988460000,2988460015,NL @@ -66258,8 +67651,8 @@ 2988460932,2988460943,PL 2988460944,2988460959,DE 2988460960,2988460991,GB -2988460992,2988461087,FR -2988461088,2988461103,PL +2988460992,2988461055,FR +2988461056,2988461103,PL 2988461104,2988461151,FR 2988461152,2988461183,GB 2988461184,2988461255,FR @@ -66301,7 +67694,7 @@ 2988461624,2988461695,FR 2988461696,2988461699,DE 2988461700,2988461703,PL -2988461704,2988461707,NL +2988461704,2988461707,FR 2988461708,2988461711,BE 2988461712,2988461719,FR 2988461720,2988461723,DE @@ -66380,7 +67773,8 @@ 2988463104,2988463107,IT 2988463108,2988463111,FR 2988463112,2988463119,ES -2988463120,2988463127,GB +2988463120,2988463123,GB +2988463124,2988463127,ES 2988463128,2988463131,FR 2988463132,2988463135,PL 2988463136,2988463143,NL @@ -66393,7 +67787,7 @@ 2988463204,2988463207,DE 2988463208,2988463211,FR 2988463212,2988463223,GB -2988463224,2988463227,FR +2988463224,2988463227,ES 2988463228,2988463231,CH 2988463232,2988463263,NL 2988463264,2988463279,PL @@ -66451,8 +67845,7 @@ 2988464284,2988464287,PL 2988464288,2988464303,FR 2988464304,2988464307,IT -2988464308,2988464319,FR -2988464320,2988464351,GB +2988464308,2988464351,FR 2988464352,2988464355,DE 2988464356,2988464359,FR 2988464360,2988464363,PL @@ -66466,22 +67859,23 @@ 2988464576,2988464591,GB 2988464592,2988464607,FR 2988464608,2988464611,DE -2988464612,2988464615,PL -2988464616,2988464619,FR +2988464612,2988464619,PL 2988464620,2988464623,ES 2988464624,2988464627,FR 2988464628,2988464631,IT 2988464632,2988464783,FR 2988464784,2988464787,IT 2988464788,2988464791,ES -2988464792,2988464799,FR +2988464792,2988464795,FR +2988464796,2988464799,GB 2988464800,2988464815,DE 2988464816,2988464819,FR 2988464820,2988464823,NL 2988464824,2988464831,PL 2988464832,2988464895,ES 2988464896,2988464927,NL -2988464928,2988464947,FR +2988464928,2988464943,ES +2988464944,2988464947,FR 2988464948,2988464951,CH 2988464952,2988464955,FR 2988464956,2988464959,GB @@ -66543,16 +67937,38 @@ 2988466144,2988466159,NL 2988466160,2988476415,FR 2988476416,2988478463,IT -2988478464,2988482799,FR +2988478464,2988482559,FR +2988482560,2988482567,ES +2988482568,2988482579,FR +2988482580,2988482591,ES +2988482592,2988482607,PL +2988482608,2988482631,FR +2988482632,2988482639,PL +2988482640,2988482647,FR +2988482648,2988482651,CZ +2988482652,2988482655,GB +2988482656,2988482763,FR +2988482764,2988482767,GB +2988482768,2988482775,PL +2988482776,2988482779,NL +2988482780,2988482783,PL +2988482784,2988482799,FR 2988482800,2988482807,ES 2988482808,2988482811,GB 2988482812,2988482815,FR 2988482816,2988482819,NL 2988482820,2988482823,DE -2988482824,2988482827,PL -2988482828,2988482895,FR -2988482896,2988482911,GB -2988482912,2988482935,FR +2988482824,2988482831,PL +2988482832,2988482839,FI +2988482840,2988482843,ES +2988482844,2988482847,NL +2988482848,2988482863,FR +2988482864,2988482871,ES +2988482872,2988482875,PT +2988482876,2988482879,CZ +2988482880,2988482895,FR +2988482896,2988482927,GB +2988482928,2988482935,FR 2988482936,2988482939,PL 2988482940,2988482943,LT 2988482944,2988482959,PL @@ -66560,17 +67976,17 @@ 2988482976,2988482979,DE 2988482980,2988482983,GB 2988482984,2988482987,DE -2988482988,2988483079,FR -2988483080,2988483087,IT -2988483088,2988483091,FR +2988482988,2988483091,FR 2988483092,2988483095,BE -2988483096,2988483103,FR +2988483096,2988483099,FR +2988483100,2988483103,PL 2988483104,2988483107,IE 2988483108,2988483111,PL 2988483112,2988483115,ES 2988483116,2988483119,PL 2988483120,2988483127,ES -2988483128,2988483151,FR +2988483128,2988483135,PL +2988483136,2988483151,FR 2988483152,2988483155,CH 2988483156,2988483159,FR 2988483160,2988483167,ES @@ -66659,19 +68075,55 @@ 2988484512,2988484543,IT 2988484544,2988484591,FR 2988484592,2988484607,ES -2988484608,2988484863,FR +2988484608,2988484775,FR +2988484776,2988484783,PL +2988484784,2988484831,FR +2988484832,2988484847,PL +2988484848,2988484863,FR 2988484864,2988484879,ES -2988484880,2988484991,FR +2988484880,2988484883,GB +2988484884,2988484887,PL +2988484888,2988484891,FR +2988484892,2988484895,GB +2988484896,2988484927,FR +2988484928,2988484959,PT +2988484960,2988484991,FR 2988484992,2988485007,LT 2988485008,2988485023,PL -2988485024,2988485071,FR +2988485024,2988485039,IE +2988485040,2988485055,PL +2988485056,2988485071,FR 2988485072,2988485087,IE -2988485088,2988485327,FR +2988485088,2988485119,PL +2988485120,2988485135,FR +2988485136,2988485151,PL +2988485152,2988485167,IT +2988485168,2988485183,FR +2988485184,2988485247,BE +2988485248,2988485255,IT +2988485256,2988485263,NL +2988485264,2988485267,DE +2988485268,2988485271,CH +2988485272,2988485279,FR +2988485280,2988485311,PL +2988485312,2988485327,IT 2988485328,2988485335,FI 2988485336,2988485343,PT -2988485344,2988485487,FR -2988485488,2988485503,DE -2988485504,2988485599,FR +2988485344,2988485347,ES +2988485348,2988485351,IT +2988485352,2988485355,GB +2988485356,2988485359,PL +2988485360,2988485439,FR +2988485440,2988485455,PL +2988485456,2988485479,FR +2988485480,2988485487,IT +2988485488,2988485503,FR +2988485504,2988485519,GB +2988485520,2988485559,FR +2988485560,2988485567,NL +2988485568,2988485583,GB +2988485584,2988485591,ES +2988485592,2988485599,FR 2988485600,2988485607,PL 2988485608,2988485611,GB 2988485612,2988485615,PL @@ -66702,7 +68154,7 @@ 2988486072,2988486075,FR 2988486076,2988486079,ES 2988486080,2988486083,BE -2988486084,2988486087,NL +2988486084,2988486087,IT 2988486088,2988486111,FR 2988486112,2988486127,PL 2988486128,2988486159,NL @@ -66822,7 +68274,8 @@ 2988489348,2988489351,PL 2988489352,2988489355,FR 2988489356,2988489359,PT -2988489360,2988489379,ES +2988489360,2988489375,FR +2988489376,2988489379,ES 2988489380,2988489383,GB 2988489384,2988489391,FR 2988489392,2988489399,NL @@ -66836,8 +68289,9 @@ 2988489484,2988489487,GB 2988489488,2988489503,FR 2988489504,2988489519,GB -2988489520,2988489535,ES -2988489536,2988489543,PT +2988489520,2988489527,ES +2988489528,2988489539,NL +2988489540,2988489543,CH 2988489544,2988489663,FR 2988489664,2988489667,DE 2988489668,2988489671,GB @@ -66901,7 +68355,278 @@ 2988490424,2988490463,FR 2988490464,2988490623,PL 2988490624,2988490751,ES -2988490752,2988507143,FR +2988490752,2988492799,FR +2988492800,2988494847,PL +2988494848,2988498991,FR +2988498992,2988499007,PL +2988499008,2988499039,FR +2988499040,2988499051,DE +2988499052,2988499055,IT +2988499056,2988499063,FR +2988499064,2988499067,DE +2988499068,2988499071,FR +2988499072,2988499103,PL +2988499104,2988499119,IE +2988499120,2988499135,FR +2988499136,2988499139,DE +2988499140,2988499143,FR +2988499144,2988499151,DE +2988499152,2988499167,FR +2988499168,2988499199,ES +2988499200,2988499327,FR +2988499328,2988499343,NL +2988499344,2988499347,PL +2988499348,2988499351,FR +2988499352,2988499359,IT +2988499360,2988499367,PL +2988499368,2988499375,IT +2988499376,2988499379,PT +2988499380,2988499387,PL +2988499388,2988499407,FR +2988499408,2988499415,PL +2988499416,2988499423,FR +2988499424,2988499455,PL +2988499456,2988499463,NL +2988499464,2988499471,DE +2988499472,2988499487,FR +2988499488,2988499519,PL +2988499520,2988499551,FR +2988499552,2988499559,PL +2988499560,2988499567,NL +2988499568,2988499575,IE +2988499576,2988499579,FR +2988499580,2988499583,CH +2988499584,2988499599,IT +2988499600,2988499615,PL +2988499616,2988499623,DE +2988499624,2988499631,ES +2988499632,2988499635,CH +2988499636,2988499639,DE +2988499640,2988499663,GB +2988499664,2988499671,DE +2988499672,2988499679,NL +2988499680,2988499683,FR +2988499684,2988499687,CZ +2988499688,2988499691,FI +2988499692,2988499695,IT +2988499696,2988499699,PT +2988499700,2988499703,GB +2988499704,2988499711,DE +2988499712,2988499731,GB +2988499732,2988499735,FR +2988499736,2988499743,NL +2988499744,2988499747,IE +2988499748,2988499751,LT +2988499752,2988499755,PL +2988499756,2988499759,ES +2988499760,2988499763,CH +2988499764,2988499775,PL +2988499776,2988499791,IT +2988499792,2988499795,GB +2988499796,2988499803,IT +2988499804,2988499807,DE +2988499808,2988499823,FR +2988499824,2988499839,DE +2988499840,2988499847,BE +2988499848,2988499851,DE +2988499852,2988499855,PL +2988499856,2988499871,ES +2988499872,2988499903,CH +2988499904,2988499907,FR +2988499908,2988499911,BE +2988499912,2988499919,FR +2988499920,2988499923,DE +2988499924,2988499927,BE +2988499928,2988499935,FR +2988499936,2988499967,IE +2988499968,2988500223,FR +2988500224,2988500255,NL +2988500256,2988500271,IT +2988500272,2988500287,BE +2988500288,2988500303,PL +2988500304,2988500307,FR +2988500308,2988500311,IT +2988500312,2988500315,FR +2988500316,2988500319,DE +2988500320,2988500335,IT +2988500336,2988500347,FR +2988500348,2988500351,PL +2988500352,2988500367,IE +2988500368,2988500383,DE +2988500384,2988500399,BE +2988500400,2988500415,DE +2988500416,2988500447,PL +2988500448,2988500479,ES +2988500480,2988500495,DE +2988500496,2988500499,PL +2988500500,2988500503,DE +2988500504,2988500511,PL +2988500512,2988500519,NL +2988500520,2988500523,ES +2988500524,2988500527,GB +2988500528,2988500543,BE +2988500544,2988500607,PL +2988500608,2988500639,FR +2988500640,2988500671,GB +2988500672,2988500679,IT +2988500680,2988500687,PL +2988500688,2988500703,NL +2988500704,2988500711,PL +2988500712,2988500719,FR +2988500720,2988500735,FI +2988500736,2988500751,PT +2988500752,2988500767,FR +2988500768,2988500771,PT +2988500772,2988500775,ES +2988500776,2988500779,GB +2988500780,2988500783,PL +2988500784,2988500791,FR +2988500792,2988500799,PL +2988500800,2988500815,ES +2988500816,2988500863,FR +2988500864,2988500867,GB +2988500868,2988500871,DE +2988500872,2988500879,NL +2988500880,2988500883,IE +2988500884,2988500887,PL +2988500888,2988500895,DE +2988500896,2988500919,FR +2988500920,2988500927,PL +2988500928,2988500935,FR +2988500936,2988500939,DE +2988500940,2988500943,FI +2988500944,2988500959,IT +2988500960,2988500975,IE +2988500976,2988500979,CZ +2988500980,2988500983,NL +2988500984,2988500987,DE +2988500988,2988500991,PL +2988500992,2988501055,FR +2988501056,2988501119,PT +2988501120,2988501199,FR +2988501200,2988501215,GB +2988501216,2988501219,DE +2988501220,2988501223,ES +2988501224,2988501227,PL +2988501228,2988501231,CZ +2988501232,2988501247,PL +2988501248,2988501327,FR +2988501328,2988501331,FI +2988501332,2988501335,GB +2988501336,2988501339,FR +2988501340,2988501359,PL +2988501360,2988501367,FR +2988501368,2988501375,ES +2988501376,2988501407,FR +2988501408,2988501411,LT +2988501412,2988501415,NL +2988501416,2988501423,BE +2988501424,2988501439,NL +2988501440,2988501471,BE +2988501472,2988501475,PT +2988501476,2988501479,BE +2988501480,2988501483,DE +2988501484,2988501487,PL +2988501488,2988501503,FR +2988501504,2988501567,PT +2988501568,2988501631,PL +2988501632,2988501663,DE +2988501664,2988501679,CH +2988501680,2988501683,PL +2988501684,2988501687,GB +2988501688,2988501691,FR +2988501692,2988501695,PL +2988501696,2988501727,FI +2988501728,2988501759,PL +2988501760,2988502031,FR +2988502032,2988502047,DE +2988502048,2988502063,NL +2988502064,2988502067,FR +2988502068,2988502071,GB +2988502072,2988502075,PL +2988502076,2988502079,ES +2988502080,2988502095,IE +2988502096,2988502099,FI +2988502100,2988502103,CZ +2988502104,2988502111,PT +2988502112,2988502143,PL +2988502144,2988502207,FR +2988502208,2988502223,GB +2988502224,2988502255,FR +2988502256,2988502263,GB +2988502264,2988502267,ES +2988502268,2988502271,DE +2988502272,2988502399,FR +2988502400,2988502407,NL +2988502408,2988502411,FR +2988502412,2988502415,CH +2988502416,2988502431,DE +2988502432,2988502447,FR +2988502448,2988502451,IE +2988502452,2988502455,IT +2988502456,2988502459,ES +2988502460,2988502463,PT +2988502464,2988502527,FR +2988502528,2988502591,PL +2988502592,2988502599,FR +2988502600,2988502603,DE +2988502604,2988502607,PL +2988502608,2988502631,FR +2988502632,2988502639,NL +2988502640,2988502655,FR +2988502656,2988502719,DE +2988502720,2988502723,ES +2988502724,2988502731,FR +2988502732,2988502735,PL +2988502736,2988502751,FR +2988502752,2988502783,ES +2988502784,2988502795,FR +2988502796,2988502799,DE +2988502800,2988502831,GB +2988502832,2988502839,DE +2988502840,2988502847,NL +2988502848,2988502851,FR +2988502852,2988502855,CH +2988502856,2988502859,FI +2988502860,2988502863,BE +2988502864,2988502867,IE +2988502868,2988502871,LT +2988502872,2988502875,PL +2988502876,2988502879,ES +2988502880,2988502883,IT +2988502884,2988502887,CZ +2988502888,2988502891,NL +2988502892,2988502895,PL +2988502896,2988502911,FR +2988502912,2988502915,PL +2988502916,2988502919,CH +2988502920,2988502959,FR +2988502960,2988502975,IE +2988502976,2988502983,PL +2988502984,2988502991,BE +2988502992,2988503015,DE +2988503016,2988503019,PL +2988503020,2988503023,ES +2988503024,2988503031,GB +2988503032,2988503035,ES +2988503036,2988503039,GB +2988503040,2988503079,FR +2988503080,2988503103,GB +2988503104,2988503107,ES +2988503108,2988503111,NL +2988503112,2988503119,PL +2988503120,2988503127,DE +2988503128,2988503131,IT +2988503132,2988503151,PL +2988503152,2988503155,DE +2988503156,2988503159,LT +2988503160,2988503167,ES +2988503168,2988503171,PL +2988503172,2988503183,ES +2988503184,2988503199,NL +2988503200,2988503215,FR +2988503216,2988503231,PL +2988503232,2988507143,FR 2988507144,2988507147,BE 2988507148,2988507151,IT 2988507152,2988507159,DE @@ -66922,7 +68647,9 @@ 2988507280,2988507287,GB 2988507288,2988507327,FR 2988507328,2988507335,DE -2988507336,2988507423,FR +2988507336,2988507339,FR +2988507340,2988507343,NL +2988507344,2988507423,FR 2988507424,2988507431,PL 2988507432,2988507439,DE 2988507440,2988507443,IT @@ -67005,7 +68732,9 @@ 2988508208,2988508215,PL 2988508216,2988508219,FR 2988508220,2988508223,DE -2988508224,2988508263,FR +2988508224,2988508255,FR +2988508256,2988508259,BE +2988508260,2988508263,FR 2988508264,2988508271,ES 2988508272,2988508287,FR 2988508288,2988508303,PL @@ -67033,7 +68762,9 @@ 2988508712,2988508719,DE 2988508720,2988508723,IT 2988508724,2988508735,GB -2988508736,2988508847,FR +2988508736,2988508767,FR +2988508768,2988508799,PT +2988508800,2988508847,FR 2988508848,2988508855,GB 2988508856,2988508871,FR 2988508872,2988508875,PL @@ -67045,8 +68776,7 @@ 2988508944,2988508947,DE 2988508948,2988508951,FR 2988508952,2988508959,ES -2988508960,2988508975,IT -2988508976,2988508991,FR +2988508960,2988508991,FR 2988508992,2988509055,NL 2988509056,2988509119,FR 2988509120,2988509151,IT @@ -67155,7 +68885,20 @@ 2988510408,2988510415,PL 2988510416,2988510431,FR 2988510432,2988510435,IT -2988510436,2988510751,FR +2988510436,2988510463,FR +2988510464,2988510495,PL +2988510496,2988510511,FR +2988510512,2988510515,GB +2988510516,2988510519,DE +2988510520,2988510527,IE +2988510528,2988510559,FR +2988510560,2988510591,IT +2988510592,2988510623,BE +2988510624,2988510655,IE +2988510656,2988510687,PL +2988510688,2988510703,FR +2988510704,2988510719,PL +2988510720,2988510751,FR 2988510752,2988510759,PL 2988510760,2988510767,FR 2988510768,2988510775,ES @@ -67292,8 +69035,7 @@ 2988512840,2988512847,DE 2988512848,2988512851,ES 2988512852,2988512855,DE -2988512856,2988512883,FR -2988512884,2988512895,DE +2988512856,2988512895,FR 2988512896,2988512899,PL 2988512900,2988512903,GB 2988512904,2988512907,ES @@ -67341,8 +69083,7 @@ 2988513360,2988513375,GB 2988513376,2988513379,FR 2988513380,2988513383,PT -2988513384,2988513391,GB -2988513392,2988513407,FR +2988513384,2988513407,FR 2988513408,2988513471,PL 2988513472,2988513503,FR 2988513504,2988513507,CH @@ -67366,9 +69107,7 @@ 2988513704,2988513707,DE 2988513708,2988513723,FR 2988513724,2988513727,DE -2988513728,2988513731,FR -2988513732,2988513735,BE -2988513736,2988513739,FR +2988513728,2988513739,FR 2988513740,2988513743,ES 2988513744,2988513759,GB 2988513760,2988513879,FR @@ -67422,8 +69161,7 @@ 2988514304,2988514335,FR 2988514336,2988514339,IE 2988514340,2988514343,FR -2988514344,2988514351,GB -2988514352,2988514359,PL +2988514344,2988514359,PL 2988514360,2988514367,ES 2988514368,2988514399,FR 2988514400,2988514431,GB @@ -67457,7 +69195,9 @@ 2988514984,2988514991,IT 2988514992,2988514995,FR 2988514996,2988515007,PL -2988515008,2988515039,FR +2988515008,2988515027,FR +2988515028,2988515031,DE +2988515032,2988515039,FR 2988515040,2988515071,GB 2988515072,2988515327,FR 2988515328,2988517375,DE @@ -67510,7 +69250,7 @@ 2988524308,2988524319,GB 2988524320,2988524351,FR 2988524352,2988524359,CH -2988524360,2988524363,GB +2988524360,2988524363,ES 2988524364,2988524367,DE 2988524368,2988524383,GB 2988524384,2988524415,IE @@ -67543,22 +69283,26 @@ 2988525852,2988525887,DE 2988525888,2988525951,FI 2988525952,2988526079,ES -2988526080,2988526423,PL +2988526080,2988526143,PT +2988526144,2988526175,BE +2988526176,2988526239,ES +2988526240,2988526423,PL 2988526424,2988526427,NL 2988526428,2988526431,ES 2988526432,2988526447,FR 2988526448,2988526451,ES 2988526452,2988526455,FR 2988526456,2988526463,ES -2988526464,2988526527,FR -2988526528,2988526543,GB +2988526464,2988526543,FR 2988526544,2988526559,IT 2988526560,2988526579,FR 2988526580,2988526583,ES 2988526584,2988526591,DE 2988526592,2988526607,FR 2988526608,2988526615,DE -2988526616,2988526687,FR +2988526616,2988526655,FR +2988526656,2988526663,PL +2988526664,2988526687,FR 2988526688,2988526703,ES 2988526704,2988526711,FR 2988526712,2988526715,ES @@ -67690,7 +69434,8 @@ 2988529248,2988529251,GB 2988529252,2988529255,PL 2988529256,2988529263,NL -2988529264,2988529311,FR +2988529264,2988529279,ES +2988529280,2988529311,FR 2988529312,2988529315,PL 2988529316,2988529319,FR 2988529320,2988529323,FI @@ -67724,7 +69469,10 @@ 2988529768,2988529771,FR 2988529772,2988529775,DE 2988529776,2988529783,ES -2988529784,2988529823,FR +2988529784,2988529791,FR +2988529792,2988529799,ES +2988529800,2988529807,DE +2988529808,2988529823,FR 2988529824,2988529855,ES 2988529856,2988529887,FR 2988529888,2988529891,DE @@ -67737,7 +69485,7 @@ 2988529940,2988529943,GB 2988529944,2988529951,ES 2988529952,2988529955,GB -2988529956,2988529959,DE +2988529956,2988529959,PL 2988529960,2988529967,GB 2988529968,2988529983,NL 2988529984,2988529999,GB @@ -67754,15 +69502,14 @@ 2988530104,2988530111,GB 2988530112,2988530191,FR 2988530192,2988530207,NL -2988530208,2988530239,IE +2988530208,2988530239,PL 2988530240,2988530271,FR 2988530272,2988530303,IE 2988530304,2988530367,FR 2988530368,2988530371,ES 2988530372,2988530379,FR 2988530380,2988530383,CH -2988530384,2988530391,FR -2988530392,2988530399,IE +2988530384,2988530399,FR 2988530400,2988530403,ES 2988530404,2988530415,FR 2988530416,2988530419,PT @@ -67784,9 +69531,9 @@ 2988530872,2988530879,IT 2988530880,2988530887,PL 2988530888,2988530895,DE -2988530896,2988530943,FR -2988530944,2988530959,BE -2988530960,2988530975,FR +2988530896,2988530927,FR +2988530928,2988530943,FI +2988530944,2988530975,FR 2988530976,2988531007,PL 2988531008,2988531015,DE 2988531016,2988531019,NL @@ -67855,8 +69602,9 @@ 2988540364,2988540367,PL 2988540368,2988540375,FR 2988540376,2988540379,GB -2988540380,2988540423,FR -2988540424,2988540427,GB +2988540380,2988540415,FR +2988540416,2988540419,CZ +2988540420,2988540427,GB 2988540428,2988540431,NL 2988540432,2988540435,FR 2988540436,2988540439,DE @@ -67866,7 +69614,7 @@ 2988540456,2988540459,DE 2988540460,2988540463,ES 2988540464,2988540471,PL -2988540472,2988540479,DE +2988540472,2988540479,ES 2988540480,2988540483,FR 2988540484,2988540487,DE 2988540488,2988540491,ES @@ -68038,17 +69786,16 @@ 2988542784,2988542847,CZ 2988542848,2988542919,DE 2988542920,2988542923,PL -2988542924,2988542927,CH -2988542928,2988542935,FR +2988542924,2988542935,FR 2988542936,2988542939,IT 2988542940,2988542943,PL 2988542944,2988542959,DE 2988542960,2988542963,FR -2988542964,2988542967,PL +2988542964,2988542967,CH 2988542968,2988542975,DE 2988542976,2988543007,FR 2988543008,2988543011,PL -2988543012,2988543015,IT +2988543012,2988543015,LT 2988543016,2988543023,CH 2988543024,2988543039,DE 2988543040,2988543047,GB @@ -68133,7 +69880,7 @@ 2988544272,2988544275,DE 2988544276,2988544279,FR 2988544280,2988544283,GB -2988544284,2988544287,DE +2988544284,2988544287,CZ 2988544288,2988544291,PL 2988544292,2988544295,GB 2988544296,2988544303,FR @@ -68182,12 +69929,11 @@ 2988544928,2988544931,DE 2988544932,2988544935,FR 2988544936,2988544943,IT -2988544944,2988544951,PL +2988544944,2988544951,PT 2988544952,2988544959,GB 2988544960,2988544979,ES 2988544980,2988544983,FR -2988544984,2988544991,IE -2988544992,2988544995,PL +2988544984,2988544995,PL 2988544996,2988544999,FR 2988545000,2988545003,DE 2988545004,2988545007,ES @@ -68255,7 +70001,7 @@ 2988545860,2988545867,FR 2988545868,2988545871,PL 2988545872,2988545919,FR -2988545920,2988545923,GB +2988545920,2988545923,ES 2988545924,2988545927,PL 2988545928,2988545931,BE 2988545932,2988545935,DE @@ -68285,7 +70031,7 @@ 2988546176,2988546239,GB 2988546240,2988546271,LT 2988546272,2988546279,IT -2988546280,2988546283,GB +2988546280,2988546283,DE 2988546284,2988546287,BE 2988546288,2988546291,GB 2988546292,2988546295,ES @@ -68331,11 +70077,13 @@ 2988546832,2988546835,DE 2988546836,2988546839,ES 2988546840,2988546847,IE -2988546848,2988546879,FR +2988546848,2988546851,PT +2988546852,2988546855,IT +2988546856,2988546879,FR 2988546880,2988546947,ES 2988546948,2988546951,DE 2988546952,2988546955,FR -2988546956,2988546959,GB +2988546956,2988546959,DE 2988546960,2988546963,CH 2988546964,2988546967,IT 2988546968,2988546971,FR @@ -68345,8 +70093,7 @@ 2988546996,2988546999,ES 2988547000,2988547003,IT 2988547004,2988547007,ES -2988547008,2988547011,GB -2988547012,2988547015,FR +2988547008,2988547015,FR 2988547016,2988547019,NL 2988547020,2988547023,ES 2988547024,2988547039,FR @@ -68460,7 +70207,8 @@ 2988556964,2988556967,FR 2988556968,2988556975,BE 2988556976,2988556979,FI -2988556980,2988557003,FR +2988556980,2988556999,FR +2988557000,2988557003,BE 2988557004,2988557007,ES 2988557008,2988557023,FR 2988557024,2988557039,IE @@ -68492,7 +70240,7 @@ 2988557344,2988557379,FR 2988557380,2988557383,ES 2988557384,2988557387,GB -2988557388,2988557391,ES +2988557388,2988557391,CZ 2988557392,2988557399,PL 2988557400,2988557407,DE 2988557408,2988557427,ES @@ -68544,7 +70292,8 @@ 2988558464,2988558527,NL 2988558528,2988558591,PL 2988558592,2988558655,GB -2988558656,2988558727,FR +2988558656,2988558719,FR +2988558720,2988558727,PL 2988558728,2988558731,IT 2988558732,2988558735,PT 2988558736,2988558751,GB @@ -68630,8 +70379,8 @@ 2988560992,2988560995,FR 2988560996,2988561007,DE 2988561008,2988561023,FR -2988561024,2988561031,ES -2988561032,2988561039,FR +2988561024,2988561027,BE +2988561028,2988561039,FR 2988561040,2988561043,GB 2988561044,2988561047,FR 2988561048,2988561051,PL @@ -68657,7 +70406,12 @@ 2988561200,2988561203,PL 2988561204,2988561207,GB 2988561208,2988561215,PL -2988561216,2988561283,FR +2988561216,2988561231,FR +2988561232,2988561235,PT +2988561236,2988561239,GB +2988561240,2988561243,BE +2988561244,2988561263,PL +2988561264,2988561283,FR 2988561284,2988561287,NL 2988561288,2988561291,ES 2988561292,2988561295,PT @@ -68671,7 +70425,10 @@ 2988561668,2988561671,PL 2988561672,2988561675,NL 2988561676,2988561679,FI -2988561680,2988561695,ES +2988561680,2988561683,FR +2988561684,2988561687,CZ +2988561688,2988561691,DE +2988561692,2988561695,LT 2988561696,2988561727,FR 2988561728,2988561743,PL 2988561744,2988561747,FR @@ -68689,8 +70446,7 @@ 2988561888,2988561903,PL 2988561904,2988561983,FR 2988561984,2988562015,DE -2988562016,2988562023,PT -2988562024,2988562027,ES +2988562016,2988562027,ES 2988562028,2988562031,LT 2988562032,2988562047,PL 2988562048,2988562079,DE @@ -68723,7 +70479,7 @@ 2988562864,2988562911,FR 2988562912,2988562943,PL 2988562944,2988563011,FR -2988563012,2988563015,PL +2988563012,2988563015,PT 2988563016,2988563023,GB 2988563024,2988563043,FR 2988563044,2988563047,ES @@ -68762,19 +70518,39 @@ 2988563676,2988563679,PL 2988563680,2988563967,FR 2988563968,2988563999,BE -2988564000,2988564019,FR +2988564000,2988564015,IE +2988564016,2988564019,FR 2988564020,2988564023,PL 2988564024,2988564031,FR 2988564032,2988564063,BE -2988564064,2988564191,FR +2988564064,2988564175,FR +2988564176,2988564179,PL +2988564180,2988564183,GB +2988564184,2988564191,IT 2988564192,2988564195,ES 2988564196,2988564203,DE -2988564204,2988564383,FR +2988564204,2988564215,FR +2988564216,2988564219,GB +2988564220,2988564223,IT +2988564224,2988564279,FR +2988564280,2988564287,ES +2988564288,2988564303,FR +2988564304,2988564307,IT +2988564308,2988564311,PL +2988564312,2988564319,ES +2988564320,2988564351,FR +2988564352,2988564359,DE +2988564360,2988564367,GB +2988564368,2988564383,FR 2988564384,2988564387,IE 2988564388,2988564391,GB 2988564392,2988564395,NL 2988564396,2988564399,CH -2988564400,2988572671,FR +2988564400,2988564403,DE +2988564404,2988564407,ES +2988564408,2988564471,FR +2988564472,2988564479,GB +2988564480,2988572671,FR 2988572672,2988703743,RU 2988703744,2988834815,PL 2988834816,2988965887,CH @@ -68799,7 +70575,9 @@ 2990518016,2990518079,IT 2990518080,2990525247,DE 2990525248,2990525311,ES -2990525312,2990535935,DE +2990525312,2990534655,DE +2990534656,2990534687,EG +2990534688,2990535935,DE 2990535936,2990535967,PL 2990535968,2990538751,DE 2990538752,2991063039,RU @@ -69014,11 +70792,7 @@ 2991981064,2991981071,DE 2991981072,2991981495,UA 2991981496,2991981503,NA -2991981504,2991981647,UA -2991981648,2991981655,NA -2991981656,2991981687,UA -2991981688,2991981695,NA -2991981696,2991981839,UA +2991981504,2991981839,UA 2991981840,2991981847,RU 2991981848,2991982535,UA 2991982536,2991982543,GL @@ -69085,8 +70859,8 @@ 2996862976,2996895743,AM 2996895744,2996928511,KW 2996928512,2996994047,RU -2996994048,2996994879,DE -2996994880,2996994943,UA +2996994048,2996994911,DE +2996994912,2996994943,BR 2996994944,2996995071,US 2996995072,2996995327,BZ 2996995328,2996995647,DE @@ -69131,7 +70905,8 @@ 2997001120,2997001471,DE 2997001472,2997001727,BZ 2997001728,2997001983,TR -2997001984,2997003071,DE +2997001984,2997003039,DE +2997003040,2997003071,BR 2997003072,2997003135,RU 2997003136,2997003199,DE 2997003200,2997003263,RU @@ -69139,11 +70914,10 @@ 2997003288,2997003295,NL 2997003296,2997003327,CA 2997003328,2997003391,RU -2997003392,2997003583,DE -2997003584,2997003647,UA -2997003648,2997004031,DE +2997003392,2997004031,DE 2997004032,2997004287,BZ -2997004288,2997004607,DE +2997004288,2997004543,CA +2997004544,2997004607,DE 2997004608,2997004671,RU 2997004672,2997004799,DE 2997004800,2997005055,BZ @@ -69181,7 +70955,7 @@ 2997020672,2997020719,DE 2997020720,2997020735,SE 2997020736,2997020799,DE -2997020800,2997020863,US +2997020800,2997020863,CA 2997020864,2997021183,DE 2997021184,2997021695,GB 2997021696,2997022079,DE @@ -69239,11 +71013,13 @@ 2999985712,2999985727,BE 2999985728,2999985743,CZ 2999985744,2999985759,NL -2999985760,2999988991,BE -2999988992,2999989007,FR -2999989008,2999989247,NL -2999989248,2999990527,BE -2999990528,2999992319,NL +2999985760,2999985918,BE +2999985919,2999985919,NL +2999985920,2999988991,BE +2999988992,2999988999,FR +2999989000,2999989247,NL +2999989248,2999991039,BE +2999991040,2999992319,NL 2999992320,3000000511,RU 3000000512,3000008703,DE 3000008704,3000016895,RU @@ -69421,31 +71197,46 @@ 3001823232,3001827327,GE 3001827328,3001827647,SE 3001827648,3001827743,GB -3001827744,3001828864,SE +3001827744,3001827775,US +3001827776,3001828864,SE 3001828865,3001828896,US -3001828897,3001829120,SE +3001828897,3001828927,SE +3001828928,3001828991,DE +3001828992,3001829055,GB +3001829056,3001829120,SE 3001829121,3001829152,US -3001829153,3001830400,SE +3001829153,3001829183,SE +3001829184,3001829247,DE +3001829248,3001829311,GB +3001829312,3001830400,SE 3001830401,3001830432,GB -3001830433,3001830527,SE +3001830433,3001830495,SE +3001830496,3001830527,GB 3001830528,3001830559,IT 3001830560,3001830591,FR 3001830592,3001830623,US -3001830624,3001830656,SE +3001830624,3001830631,SE +3001830632,3001830639,IT +3001830640,3001830656,SE 3001830657,3001830688,GB -3001830689,3001830783,SE +3001830689,3001830751,SE +3001830752,3001830783,GB 3001830784,3001830815,IT 3001830816,3001830847,FR 3001830848,3001830879,US -3001830880,3001830912,SE +3001830880,3001830887,SE +3001830888,3001830895,IT +3001830896,3001830912,SE 3001830913,3001830944,GB -3001830945,3001831039,SE +3001830945,3001831007,SE +3001831008,3001831039,GB 3001831040,3001831071,IT 3001831072,3001831103,FR 3001831104,3001831135,US 3001831136,3001831167,IT 3001831168,3001831199,GB -3001831200,3001831295,SE +3001831200,3001831263,SE +3001831264,3001831295,GB 3001831296,3001831327,IT 3001831328,3001831359,FR 3001831360,3001831391,US @@ -69552,8 +71343,7 @@ 3001975896,3001975919,GB 3001975920,3001975927,CN 3001975928,3001975935,AU -3001975936,3001976623,GB -3001976624,3001976639,CN +3001975936,3001976639,GB 3001976640,3001976655,RU 3001976656,3001976671,GB 3001976672,3001976679,IN @@ -69614,8 +71404,7 @@ 3002003456,3002011647,PL 3002011648,3002015743,BA 3002015744,3002019839,IT -3002019840,3002020223,NL -3002020224,3002020287,IL +3002019840,3002020287,NL 3002020288,3002020303,US 3002020304,3002023935,NL 3002023936,3002028031,DE @@ -69788,7 +71577,8 @@ 3003058432,3003058687,FI 3003058688,3003058751,EE 3003058752,3003058943,PH -3003058944,3003060223,EE +3003058944,3003059199,IL +3003059200,3003060223,EE 3003060224,3003062271,DE 3003062272,3003064319,NL 3003064320,3003066367,RO @@ -69808,7 +71598,11 @@ 3003088896,3003090943,FR 3003090944,3003092991,DE 3003092992,3003095039,NO -3003095040,3003097087,AT +3003095040,3003095567,AT +3003095568,3003095583,CZ +3003095584,3003096063,AT +3003096064,3003096079,CZ +3003096080,3003097087,AT 3003097088,3003099135,FR 3003099136,3003101183,CZ 3003101184,3003103231,UA @@ -70055,6 +71849,7 @@ 3038511104,3038773247,AR 3039035392,3039166463,DO 3039297536,3039363071,PY +3039821824,3040346111,CO 3053453312,3054501887,ID 3054501888,3054534655,HK 3054534656,3054537727,PH @@ -70288,6 +72083,9 @@ 3091976192,3091980287,CA 3091980288,3093168127,US 3093168128,3093200895,CA +3093200896,3093213183,US +3093213184,3093217279,CA +3093217280,3093233663,US 3093233664,3093237759,PR 3093237760,3093266431,US 3093299200,3093940991,US @@ -70433,6 +72231,8 @@ 3098099712,3098116095,US 3098148864,3098165247,JM 3098165248,3098181631,US +3098181632,3098185727,CA +3098185728,3098202111,US 3098214400,3098263551,US 3098263552,3098271743,CA 3098271744,3098275839,US @@ -70480,7 +72280,7 @@ 3122331648,3122348031,BO 3122397184,3122659327,CO 3122659328,3122724863,GT -3122790400,3122987007,CL +3122790400,3123052543,CL 3123052544,3123183615,AR 3123183616,3123314687,CL 3123314688,3123380223,EC @@ -70493,7 +72293,8 @@ 3124822016,3124838399,EC 3124854784,3124887551,CL 3124887552,3124953087,EC -3125018624,3125149695,EC +3124953088,3125018623,CL +3125018624,3125280767,EC 3125280768,3125542911,PA 3125673984,3125805055,CL 3125805056,3126329343,CO @@ -70512,6 +72313,7 @@ 3129016320,3129999359,AR 3129999360,3130261503,CO 3130523648,3130654719,AR +3130654720,3130720255,CO 3131047936,3131310079,PE 3131572224,3131703295,CO 3132096512,3132162047,CR @@ -70530,7 +72332,9 @@ 3133079552,3133145087,AR 3133145088,3145727999,BR 3145728000,3154116607,MX -3154116608,3154149375,NO +3154149376,3154157567,UA +3154157568,3154173951,RU +3154173952,3154182143,MD 3154182144,3154247679,DE 3154247680,3154313215,RS 3154313216,3154378751,TR @@ -70572,7 +72376,6 @@ 3157786624,3158048767,TR 3158048768,3158310911,CH 3158310912,3158312959,FI -3158312960,3158315007,NL 3158315008,3158317055,DE 3158317056,3158319103,SI 3158319104,3158321151,GB @@ -70618,13 +72421,23 @@ 3158395008,3158395135,GB 3158395136,3158395151,AT 3158395152,3158395159,DE -3158395160,3158395263,AT +3158395160,3158395167,AT +3158395168,3158395175,DE +3158395176,3158395191,AT +3158395192,3158395199,DE +3158395200,3158395263,AT 3158395264,3158395295,DE -3158395296,3158395431,AT +3158395296,3158395359,AT +3158395360,3158395367,DE +3158395368,3158395431,AT 3158395432,3158395439,DE 3158395440,3158395647,AT 3158395648,3158395663,DE -3158395664,3158396287,AT +3158395664,3158395687,AT +3158395688,3158395695,DE +3158395696,3158395711,AT +3158395712,3158395743,DE +3158395744,3158396287,AT 3158396288,3158396319,DE 3158396320,3158396927,AT 3158396928,3158398975,IT @@ -70842,7 +72655,10 @@ 3160324096,3160328191,IT 3160328192,3160330239,FR 3160330240,3160332287,RU -3160332288,3160333055,NO +3160332288,3160332751,NO +3160332752,3160332759,SE +3160332760,3160332767,AU +3160332768,3160333055,NO 3160333056,3160333087,CO 3160333088,3160334335,NO 3160334336,3160336383,RU @@ -70899,10 +72715,14 @@ 3161784320,3161800703,FI 3161800704,3161817087,SA 3161817088,3161833471,PL -3161833472,3161833983,MK -3161833984,3161834495,AT -3161834496,3161835263,MK -3161835264,3161849855,AT +3161833472,3161835519,MK +3161835520,3161835775,AT +3161835776,3161837567,MK +3161837568,3161837695,AT +3161837696,3161840639,MK +3161840640,3161840895,AT +3161840896,3161844735,MK +3161844736,3161849855,AT 3161849856,3161866239,BE 3161866240,3161882623,IR 3161882624,3161899007,DE @@ -71030,11 +72850,10 @@ 3163161760,3163161791,BR 3163161792,3163161887,DE 3163161888,3163161951,US -3163161952,3163162111,DE +3163161952,3163162079,DE +3163162080,3163162111,RU 3163162112,3163162143,TR -3163162144,3163162207,DE -3163162208,3163162239,TR -3163162240,3163162271,DE +3163162144,3163162271,DE 3163162272,3163162303,NL 3163162304,3163162431,DE 3163162432,3163162463,CY @@ -71052,16 +72871,17 @@ 3163164192,3163164223,RU 3163164224,3163164287,DE 3163164288,3163164319,CL -3163164320,3163164447,DE +3163164320,3163164351,RU +3163164352,3163164447,DE 3163164448,3163164479,RU -3163164480,3163164511,US +3163164480,3163164511,DE 3163164512,3163164543,HU 3163164544,3163164575,RU 3163164576,3163165759,DE 3163165760,3163165791,PL 3163165792,3163165823,RU 3163165824,3163166175,DE -3163166176,3163166207,US +3163166176,3163166207,RU 3163166208,3163166367,DE 3163166368,3163166399,US 3163166400,3163166495,DE @@ -71103,7 +72923,8 @@ 3163170144,3163170175,ZA 3163170176,3163170207,DE 3163170208,3163170239,RU -3163170240,3163170303,DE +3163170240,3163170271,DE +3163170272,3163170303,TW 3163170304,3163170335,IT 3163170336,3163170367,RO 3163170368,3163170495,DE @@ -71117,22 +72938,22 @@ 3163170816,3163171871,DE 3163171872,3163171903,RO 3163171904,3163171935,BZ -3163171936,3163171967,BR -3163171968,3163172127,DE +3163171936,3163172095,DE +3163172096,3163172127,BR 3163172128,3163172159,US 3163172160,3163172191,TR 3163172192,3163172319,DE 3163172320,3163172351,NL 3163172352,3163172383,GB -3163172384,3163172447,DE -3163172448,3163172479,TR +3163172384,3163172479,DE 3163172480,3163172511,US 3163172512,3163172543,RU 3163172544,3163172607,DE 3163172608,3163172639,DK 3163172640,3163172735,DE 3163172736,3163172767,GR -3163172768,3163174047,DE +3163172768,3163174015,DE +3163174016,3163174047,RU 3163174048,3163174079,DK 3163174080,3163174111,DE 3163174112,3163174143,BE @@ -71141,7 +72962,7 @@ 3163174336,3163174367,RU 3163174368,3163174495,DE 3163174496,3163174527,US -3163174528,3163174559,DE +3163174528,3163174559,BD 3163174560,3163174591,PL 3163174592,3163174623,SE 3163174624,3163174655,GB @@ -71151,14 +72972,17 @@ 3163174784,3163174815,DE 3163174816,3163174847,CA 3163174848,3163174879,TR -3163174880,3163176127,DE +3163174880,3163176095,DE +3163176096,3163176127,CY 3163176128,3163176159,US 3163176160,3163176255,DE 3163176256,3163176287,UG 3163176288,3163176319,PT -3163176320,3163176479,DE +3163176320,3163176447,DE +3163176448,3163176479,US 3163176480,3163176511,GB -3163176512,3163176575,DE +3163176512,3163176543,TR +3163176544,3163176575,DE 3163176576,3163176607,GR 3163176608,3163176767,DE 3163176768,3163176799,PL @@ -71246,7 +73070,7 @@ 3164949124,3164949131,DE 3164949132,3164949151,FR 3164949152,3164949155,NL -3164949156,3164949159,FR +3164949156,3164949159,DE 3164949160,3164949163,PL 3164949164,3164949183,FR 3164949184,3164949199,GB @@ -71360,7 +73184,8 @@ 3164952192,3164952207,ES 3164952208,3164952215,FR 3164952216,3164952219,NL -3164952220,3164952239,FR +3164952220,3164952223,FR +3164952224,3164952239,GB 3164952240,3164952243,DE 3164952244,3164952247,BE 3164952248,3164952255,FR @@ -71426,7 +73251,9 @@ 3164954544,3164954559,LT 3164954560,3164954591,FR 3164954592,3164954623,PL -3164954624,3164956479,FR +3164954624,3164956383,FR +3164956384,3164956399,DE +3164956400,3164956479,FR 3164956480,3164956543,GB 3164956544,3164958847,FR 3164958848,3164958911,IT @@ -71451,8 +73278,9 @@ 3164959384,3164959387,PL 3164959388,3164959487,FR 3164959488,3164959743,ES -3164959744,3164959871,FR -3164959872,3164959903,GB +3164959744,3164959887,FR +3164959888,3164959895,ES +3164959896,3164959903,PL 3164959904,3164959919,DE 3164959920,3164959927,FR 3164959928,3164959931,GB @@ -71547,7 +73375,10 @@ 3164961656,3164961663,ES 3164961664,3164961695,DE 3164961696,3164961727,GB -3164961728,3164961743,ES +3164961728,3164961731,ES +3164961732,3164961735,IT +3164961736,3164961739,FR +3164961740,3164961743,GB 3164961744,3164961763,PL 3164961764,3164961767,IT 3164961768,3164961775,BE @@ -71693,7 +73524,9 @@ 3164970368,3164970371,PL 3164970372,3164970375,ES 3164970376,3164970399,IT -3164970400,3164970415,GB +3164970400,3164970407,CH +3164970408,3164970411,IT +3164970412,3164970415,GB 3164970416,3164970423,FR 3164970424,3164970427,IE 3164970428,3164970431,PT @@ -71812,7 +73645,7 @@ 3164975352,3164975355,NL 3164975356,3164975359,FR 3164975360,3164975615,ES -3164975616,3164976127,GB +3164975616,3164976127,FR 3164976128,3164976131,NL 3164976132,3164976135,GB 3164976136,3164976139,FR @@ -71843,7 +73676,9 @@ 3164976348,3164976351,ES 3164976352,3164976367,DE 3164976368,3164976383,PL -3164976384,3164976407,FR +3164976384,3164976399,FR +3164976400,3164976403,ES +3164976404,3164976407,FR 3164976408,3164976415,DE 3164976416,3164976431,IT 3164976432,3164976459,FR @@ -71881,7 +73716,9 @@ 3164977888,3164977903,IT 3164977904,3164977919,NL 3164977920,3164978047,DE -3164978048,3164978067,FR +3164978048,3164978055,FR +3164978056,3164978063,NL +3164978064,3164978067,FR 3164978068,3164978079,ES 3164978080,3164978111,IT 3164978112,3164978127,GB @@ -71896,8 +73733,10 @@ 3164978496,3164978511,IT 3164978512,3164978527,ES 3164978528,3164978543,FR -3164978544,3164978559,PT -3164978560,3164978575,FR +3164978544,3164978563,PT +3164978564,3164978567,PL +3164978568,3164978571,GB +3164978572,3164978575,FR 3164978576,3164978591,ES 3164978592,3164978607,FR 3164978608,3164978623,CZ @@ -71979,13 +73818,11 @@ 3168120832,3168124927,GB 3168124928,3168161791,RO 3168161792,3168165887,GB -3168165888,3168169983,RO -3168169984,3168178175,GB -3168178176,3168182271,RO -3168182272,3168186367,GB -3168186368,3168190463,RO +3168165888,3168190463,RO 3168190464,3168194559,GB -3168194560,3168207103,RO +3168194560,3168195583,RO +3168195584,3168196095,DE +3168196096,3168207103,RO 3168207104,3168207359,CY 3168207360,3168214527,RO 3168214528,3168214783,CY @@ -72163,6 +74000,8 @@ 3188513536,3188523007,AR 3188523008,3188539391,CO 3188539392,3188543487,CL +3188543488,3188545535,PA +3188545536,3188547583,AR 3188547584,3188551679,CO 3188555776,3188572159,CL 3188572160,3188576255,CO @@ -72314,6 +74153,7 @@ 3194585088,3194589183,HN 3194589184,3194591231,AR 3194591232,3194592255,PA +3194592256,3194593279,GY 3194593280,3194595327,AR 3194595328,3194596351,PA 3194596352,3194597375,HT @@ -72336,7 +74176,6 @@ 3194707968,3194716159,AR 3194716160,3194724351,HN 3194724352,3194728447,PA -3194732544,3194736639,AR 3194740736,3194742783,CL 3194742784,3194744831,EC 3194744832,3194746879,AR @@ -72410,7 +74249,8 @@ 3195740160,3195744255,PA 3195744256,3195748351,EC 3195748352,3195752447,CL -3195756544,3195764735,AR +3195756544,3195763711,AR +3195763712,3195764735,BO 3195764736,3195768831,CR 3195772928,3195777023,VE 3195781120,3195797503,PA @@ -72449,6 +74289,11 @@ 3197370368,3197501439,GT 3197501440,3197534207,SV 3197566976,3197599743,CL +3197599744,3197600767,GT +3197600768,3197601791,CR +3197603840,3197607935,AR +3197612032,3197616127,SV +3197616128,3197632511,CO 3197632512,3197698047,EC 3197698048,3197730815,VE 3197730816,3197763583,CL @@ -72772,14 +74617,42 @@ 3223582464,3223582719,NL 3223582720,3223582975,AU 3223583488,3223584767,US -3223584768,3223650303,SE +3223584768,3223589119,SE +3223589120,3223589375,US +3223589376,3223606527,SE +3223606528,3223606783,GB +3223606784,3223607551,SE +3223607552,3223607807,GB +3223607808,3223610367,SE +3223610368,3223610623,IT +3223610624,3223610879,SE +3223610880,3223611135,NO +3223611136,3223611647,SE +3223611648,3223611903,GB +3223611904,3223617535,SE +3223617536,3223617791,NO +3223617792,3223620863,SE +3223620864,3223621119,DK +3223621120,3223627775,SE +3223627776,3223628031,DE +3223628032,3223628287,SE +3223628288,3223628543,ES +3223628544,3223630591,SE +3223630592,3223630847,GB +3223630848,3223634431,SE +3223634432,3223634687,US +3223634688,3223646207,SE +3223646208,3223646463,IT +3223646464,3223646975,SE +3223646976,3223647231,IT +3223647232,3223650303,SE 3223650304,3223715839,CH 3223715840,3223781375,DK 3223781376,3223823871,US 3223823872,3223824127,AT 3223824128,3223863295,US 3223863552,3223863807,US -3223864320,3223867647,FI +3223865344,3223867391,FI 3223871488,3223887871,US 3223898368,3223898623,US 3223902464,3223902719,CA @@ -73311,7 +75184,35 @@ 3225876480,3225878527,US 3225878528,3225880319,SE 3225880320,3225880575,US -3225880576,3225944063,SE +3225880576,3225881343,SE +3225881344,3225881599,IT +3225881600,3225887999,SE +3225888000,3225888255,GB +3225888256,3225905407,SE +3225905408,3225905663,IT +3225905664,3225913855,SE +3225913856,3225914111,DE +3225914112,3225915135,SE +3225915136,3225915391,DK +3225915392,3225918463,SE +3225918464,3225918719,GB +3225918720,3225920767,SE +3225920768,3225921023,GB +3225921024,3225921791,SE +3225921792,3225922047,GB +3225922048,3225923839,SE +3225923840,3225924095,GB +3225924096,3225930239,SE +3225930240,3225930495,FR +3225930496,3225932799,SE +3225932800,3225933055,IT +3225933056,3225935359,SE +3225935360,3225935615,US +3225935616,3225937407,SE +3225937408,3225937663,US +3225937664,3225938431,SE +3225938432,3225938687,US +3225938688,3225944063,SE 3225944064,3225977855,TW 3225977856,3225978111,CH 3225978112,3226008831,TW @@ -73898,7 +75799,7 @@ 3227909632,3227909887,AU 3227910400,3227910655,AT 3227910656,3227911679,US -3227911680,3227912191,HU +3227911680,3227912191,EU 3227912192,3227912447,GB 3227912448,3227912703,ZA 3227912704,3227912959,US @@ -74232,9 +76133,15 @@ 3229120768,3229151487,US 3229151488,3229151743,SE 3229151744,3229155327,US -3229155328,3229171455,SE +3229155328,3229155839,SE +3229155840,3229156095,ES +3229156096,3229171455,SE 3229171456,3229171711,MT -3229171712,3229219583,SE +3229171712,3229200895,SE +3229200896,3229201151,DE +3229201152,3229201663,SE +3229201664,3229201919,DK +3229201920,3229219583,SE 3229219584,3229219839,EE 3229219840,3229220863,SE 3229220864,3229245439,GB @@ -74296,11 +76203,13 @@ 3229473792,3229474047,GB 3229474048,3229474303,DE 3229474304,3229475839,GB -3229475840,3229478911,DE +3229475840,3229478399,DE +3229478400,3229478655,IE +3229478656,3229478911,DE 3229478912,3229480959,IE 3229480960,3229481471,DE 3229481472,3229482239,GB -3229482240,3229483007,DE +3229482240,3229483007,IE 3229483008,3229499647,FI 3229499648,3229500671,US 3229548544,3229679615,US @@ -74320,7 +76229,9 @@ 3229749760,3229750015,BE 3229750016,3229764063,FI 3229764064,3229764095,AX -3229764096,3229810687,FI +3229764096,3229808639,FI +3229808640,3229808647,AX +3229808648,3229810687,FI 3229810688,3229814015,US 3229814016,3229814271,AU 3229814272,3229815807,US @@ -75281,14 +77192,34 @@ 3231896576,3231897599,RU 3231897600,3231898623,IE 3231898624,3231899647,SE -3231899648,3231903743,UA -3231903744,3231907839,RU +3231899648,3231900671,UA +3231900672,3231901439,DE +3231901440,3231901695,BG +3231901696,3231903743,UA +3231903744,3231905791,RU +3231905792,3231906047,PL +3231906048,3231907839,RU 3231907840,3231916031,US 3231916032,3231948799,FI 3231973376,3232038911,AT -3232038912,3232079871,SE +3232038912,3232039167,SE +3232039168,3232039423,DK +3232039424,3232039679,IT +3232039680,3232049151,SE +3232049152,3232049407,GB +3232049408,3232060415,SE +3232060416,3232060671,IE +3232060672,3232066559,SE +3232066560,3232066815,NO +3232066816,3232079871,SE 3232079872,3232080895,GB -3232080896,3232092671,SE +3232080896,3232083455,SE +3232083456,3232083711,DE +3232083712,3232089087,SE +3232089088,3232089343,ES +3232089344,3232090367,SE +3232090368,3232090623,IT +3232090624,3232092671,SE 3232092672,3232093183,GB 3232093184,3232093439,US 3232093440,3232094207,GB @@ -75297,7 +77228,11 @@ 3232095232,3232096255,GB 3232096256,3232097279,SE 3232097280,3232097535,IT -3232097536,3232104447,SE +3232097536,3232098047,SE +3232098048,3232098303,FR +3232098304,3232100095,SE +3232100096,3232100351,IE +3232100352,3232104447,SE 3232104448,3232107519,DE 3232107520,3232108543,RU 3232108544,3232129023,DE @@ -75352,7 +77287,21 @@ 3232706560,3232706815,US 3232710656,3232718847,US 3232727040,3232759807,US -3232759808,3232825343,SE +3232759808,3232774911,SE +3232774912,3232775167,IE +3232775168,3232794879,SE +3232794880,3232795135,DE +3232795136,3232802559,SE +3232802560,3232802815,DK +3232802816,3232803071,SE +3232803072,3232803327,IE +3232803328,3232804607,SE +3232804608,3232804863,IT +3232804864,3232812799,SE +3232812800,3232813055,ES +3232813056,3232820223,SE +3232820224,3232820479,IE +3232820480,3232825343,SE 3233285120,3233285375,US 3233480704,3233484799,US 3233484800,3233488895,ES @@ -76160,7 +78109,6 @@ 3238007040,3238010879,NL 3238010880,3238017023,CH 3238017024,3238018303,DK -3238018304,3238018559,TR 3238018560,3238018815,FR 3238018816,3238019071,DE 3238019072,3238035455,PL @@ -76790,7 +78738,6 @@ 3239783424,3239783679,DK 3239783680,3239783935,CH 3239783936,3239784191,DE -3239784192,3239784447,UA 3239784448,3239788543,DE 3239788544,3239789055,EU 3239789568,3239790079,FR @@ -77204,7 +79151,7 @@ 3240282112,3240282239,DE 3240282240,3240282367,UA 3240282368,3240282495,RO -3240282496,3240282879,SE +3240282624,3240282879,SE 3240282880,3240283007,UA 3240283008,3240283391,PL 3240283392,3240283647,TR @@ -77299,7 +79246,6 @@ 3240577280,3240577535,RO 3240577536,3240577791,DE 3240577792,3240578559,UA -3240578560,3240578815,CH 3240578816,3240579071,IL 3240579072,3240587263,GB 3240587264,3240587519,NL @@ -77474,7 +79420,6 @@ 3240813568,3240814591,PL 3240814592,3240818687,IT 3240818688,3240820735,NL -3240820736,3240820799,EU 3240820800,3240820831,RU 3240820832,3240827135,IT 3240827136,3240827391,FR @@ -77535,8 +79480,7 @@ 3240884224,3240886271,UA 3240886272,3240952071,SE 3240952072,3240952079,IE -3240952080,3240952087,GB -3240952088,3240952095,SE +3240952080,3240952095,SE 3240952096,3240952127,US 3240952128,3240954495,SE 3240954496,3240954623,DE @@ -77765,7 +79709,9 @@ 3241869312,3241934847,PL 3241934848,3242196991,GB 3242196992,3242393599,FI -3242393600,3242459135,NL +3242393600,3242394471,NL +3242394472,3242394479,DE +3242394480,3242459135,NL 3242459136,3242467327,BG 3242467328,3242475519,HU 3242475520,3242483711,LV @@ -78298,7 +80244,6 @@ 3244906752,3244907007,SA 3244907008,3244907263,FR 3244907264,3244907519,RO -3244907520,3244907775,GB 3244907776,3244908287,RU 3244908288,3244908543,NL 3244908544,3244908799,RU @@ -78491,7 +80436,6 @@ 3245001728,3245002751,IL 3245002752,3245003263,PL 3245003264,3245003519,SE -3245003520,3245003775,CH 3245003776,3245004799,RU 3245004800,3245005823,PL 3245005824,3245006847,UA @@ -78506,7 +80450,7 @@ 3245017088,3245018111,PL 3245018112,3245019135,RU 3245019136,3245020159,SC -3245020160,3245021183,CZ +3245020160,3245021183,RU 3245021184,3245022207,UA 3245022208,3245023231,NO 3245023232,3245024255,PL @@ -78649,7 +80593,6 @@ 3245136384,3245136639,GB 3245136640,3245136895,EU 3245136896,3245137151,PL -3245137152,3245137407,IT 3245137408,3245137663,DE 3245137664,3245137919,SE 3245137920,3245138431,DK @@ -79010,7 +80953,9 @@ 3245903032,3245903039,GB 3245903040,3245903959,IE 3245903960,3245903967,FR -3245903968,3245904199,IE +3245903968,3245904087,IE +3245904088,3245904095,GB +3245904096,3245904199,IE 3245904200,3245904207,GB 3245904208,3245906367,IE 3245906368,3245906431,GB @@ -79508,7 +81453,9 @@ 3247714304,3247716351,CH 3247716352,3247717887,ES 3247717888,3247718399,CH -3247718400,3247769599,ES +3247718400,3247742975,ES +3247742976,3247751167,DE +3247751168,3247769599,ES 3247769600,3247771647,DE 3247771648,3247775743,ES 3247775744,3247779647,DE @@ -79531,7 +81478,6 @@ 3247833088,3247865855,RU 3247865856,3247871999,GB 3247872000,3247875327,NL -3247875328,3247875583,TR 3247875584,3247876095,DE 3247876096,3247876351,PL 3247876352,3247876607,FR @@ -79660,8 +81606,8 @@ 3248790784,3248791039,PL 3248791040,3248791295,BE 3248791296,3248791551,DE -3248791552,3248792511,GB -3248792512,3248796607,EU +3248791552,3248792527,GB +3248792528,3248796607,EU 3248796608,3248796863,GB 3248796864,3248798975,EU 3248798976,3248799231,GB @@ -79928,17 +81874,57 @@ 3249731584,3249732607,UA 3249732608,3249733631,IT 3249733632,3249799167,CZ -3249799168,3249865727,SE -3249865728,3249866751,GB -3249866752,3249910783,SE +3249799168,3249829887,SE +3249829888,3249830143,GB +3249830144,3249830399,SE +3249830400,3249830655,IT +3249830656,3249850623,SE +3249850624,3249850879,GB +3249850880,3249863679,SE +3249863680,3249863935,ES +3249863936,3249865471,SE +3249865472,3249866751,GB +3249866752,3249868543,SE +3249868544,3249868799,DE +3249868800,3249871103,SE +3249871104,3249871359,NO +3249871360,3249871615,SE +3249871616,3249871871,NO +3249871872,3249872383,SE +3249872384,3249872639,GB +3249872640,3249910783,SE 3249910784,3249912319,GB 3249912320,3249931007,SE 3249931008,3249931263,GB 3249931264,3249932031,SE 3249932032,3249934335,GB -3249934336,3249968127,SE +3249934336,3249967615,SE +3249967616,3249967871,GB +3249967872,3249968127,SE 3249968128,3249969151,FR -3249969152,3250061311,SE +3249969152,3249971199,SE +3249971200,3249971455,IT +3249971456,3249974527,SE +3249974528,3249974783,ES +3249974784,3249976063,SE +3249976064,3249976319,FR +3249976320,3249976831,SE +3249976832,3249977087,GB +3249977088,3249991679,SE +3249991680,3249991935,US +3249991936,3249995263,SE +3249995264,3249995519,GB +3249995520,3249997055,SE +3249997056,3249997311,US +3249997312,3250000127,SE +3250000128,3250000383,GB +3250000384,3250007295,SE +3250007296,3250007551,GB +3250007552,3250031359,SE +3250031360,3250031615,US +3250031616,3250035455,SE +3250035456,3250035711,US +3250035712,3250061311,SE 3250061312,3250061635,FI 3250061636,3250061639,AX 3250061640,3250083643,FI @@ -80137,7 +82123,6 @@ 3250692096,3250692351,NO 3250692352,3250692607,NL 3250692608,3250693375,BG -3250693376,3250693631,IE 3250694400,3250694655,GB 3250694656,3250694911,SK 3250694912,3250695167,NL @@ -80147,7 +82132,7 @@ 3250697728,3250697983,BG 3250697984,3250698239,IT 3250698240,3250698751,GR -3250698752,3250699775,GB +3250699264,3250699775,GB 3250699776,3250700287,DE 3250700288,3250708479,UA 3250708480,3250716671,KZ @@ -80517,8 +82502,7 @@ 3251237888,3251238911,DK 3251238912,3251239935,FR 3251239936,3251240959,US -3251240960,3251241215,DE -3251241216,3251243007,GB +3251240960,3251243007,GB 3251243008,3251245055,BE 3251245056,3251245311,DE 3251245312,3251245567,BE @@ -80536,12 +82520,7 @@ 3251248640,3251248895,DE 3251248896,3251249151,GB 3251249152,3251251199,NL -3251251200,3251251455,PT -3251251456,3251251711,GB -3251251712,3251251967,CH -3251251968,3251252223,BG -3251252224,3251252479,AT -3251252480,3251252735,NL +3251251200,3251252735,EU 3251252736,3251256831,CH 3251256832,3251257343,GB 3251257344,3251259903,BE @@ -80661,7 +82640,9 @@ 3251734528,3251734783,NL 3251734784,3251765247,FI 3251765248,3251765503,NL -3251765504,3251774207,FI +3251765504,3251766663,FI +3251766664,3251766671,AX +3251766672,3251774207,FI 3251774208,3251774463,DE 3251774464,3251783423,FI 3251783424,3251783679,GB @@ -80783,7 +82764,9 @@ 3252407776,3252407791,GH 3252407792,3252407807,NO 3252407808,3252407999,GN -3252408000,3252408159,NO +3252408000,3252408063,NO +3252408064,3252408079,ML +3252408080,3252408159,NO 3252408160,3252408191,GQ 3252408192,3252408319,NO 3252408320,3252408327,MW @@ -80815,7 +82798,9 @@ 3252408856,3252408863,CM 3252408864,3252408871,LR 3252408872,3252408879,CI -3252408880,3252409103,LT +3252408880,3252409023,LT +3252409024,3252409039,TZ +3252409040,3252409103,LT 3252409104,3252409111,SD 3252409112,3252409119,LT 3252409120,3252409127,NG @@ -80891,20 +82876,21 @@ 3252414656,3252414991,LT 3252414992,3252414999,IQ 3252415000,3252415015,LT -3252415016,3252415095,IQ +3252415016,3252415031,IQ +3252415032,3252415039,LT +3252415040,3252415095,IQ 3252415096,3252415103,LT 3252415104,3252415127,IQ 3252415128,3252415135,LT 3252415136,3252415159,IQ 3252415160,3252415167,BE 3252415168,3252415231,IQ -3252415232,3252415487,LT -3252415488,3252415743,IQ +3252415232,3252415743,LT 3252415744,3252415775,GB 3252415776,3252415967,LT 3252415968,3252415999,CM -3252416000,3252416831,LT -3252416832,3252416927,GN +3252416000,3252416895,LT +3252416896,3252416927,GN 3252416928,3252416959,LT 3252416960,3252417023,GN 3252417024,3252417279,LT @@ -80941,9 +82927,7 @@ 3252419360,3252419423,GH 3252419424,3252419839,LT 3252419840,3252419879,IQ -3252419880,3252419903,LT -3252419904,3252419911,IQ -3252419912,3252419919,LT +3252419880,3252419919,LT 3252419920,3252419927,IQ 3252419928,3252419935,LT 3252419936,3252419943,IQ @@ -80956,9 +82940,7 @@ 3252420120,3252420143,IQ 3252420144,3252420191,LT 3252420192,3252420223,IQ -3252420224,3252420263,LT -3252420264,3252420271,IQ -3252420272,3252420351,LT +3252420224,3252420351,LT 3252420352,3252420415,IQ 3252420416,3252420431,GB 3252420432,3252420447,LT @@ -81001,7 +82983,7 @@ 3252430520,3252430527,LT 3252430528,3252430543,BF 3252430544,3252430559,BJ -3252430560,3252430591,BF +3252430560,3252430591,LT 3252430592,3252430847,GN 3252430848,3252431359,MW 3252431360,3252431871,LT @@ -81032,13 +83014,14 @@ 3252435344,3252435359,BF 3252435360,3252435375,LT 3252435376,3252435415,GN -3252435416,3252435423,CD -3252435424,3252435455,LT +3252435416,3252435447,CD +3252435448,3252435455,LT 3252435456,3252435711,TZ 3252435712,3252435855,GH 3252435856,3252435871,MR 3252435872,3252435887,GH -3252435888,3252435919,BW +3252435888,3252435903,LT +3252435904,3252435919,BW 3252435920,3252435935,BF 3252435936,3252435951,CF 3252435952,3252435967,LT @@ -81054,8 +83037,8 @@ 3252436352,3252436383,GN 3252436384,3252436399,LR 3252436400,3252436407,SL -3252436408,3252436431,ML -3252436432,3252436447,LT +3252436408,3252436415,ML +3252436416,3252436447,LT 3252436448,3252436479,ER 3252436480,3252436991,LT 3252436992,3252437503,NG @@ -81065,9 +83048,7 @@ 3252438528,3252438783,CM 3252438784,3252439039,LT 3252439040,3252439055,BJ -3252439056,3252439071,LT -3252439072,3252439079,BJ -3252439080,3252439263,LT +3252439056,3252439263,LT 3252439264,3252439271,SN 3252439272,3252439287,LT 3252439288,3252439295,SN @@ -81185,7 +83166,6 @@ 3252510720,3252514815,FR 3252514816,3252515071,SI 3252515072,3252515327,GB -3252515328,3252515583,DE 3252515584,3252515839,SI 3252515840,3252516095,CH 3252516096,3252516351,FR @@ -81362,7 +83342,36 @@ 3253265920,3253270527,RU 3253270528,3253271551,BY 3253271552,3253338111,RU -3253338112,3253469183,SE +3253338112,3253380863,SE +3253380864,3253381119,IT +3253381120,3253383935,SE +3253383936,3253384191,NO +3253384192,3253409791,SE +3253409792,3253410047,GB +3253410048,3253412351,SE +3253412352,3253412607,US +3253412608,3253416447,SE +3253416448,3253416703,GB +3253416704,3253428223,SE +3253428224,3253428479,DE +3253428480,3253429759,SE +3253429760,3253430015,ES +3253430016,3253433087,SE +3253433088,3253433343,DE +3253433344,3253434111,SE +3253434112,3253434367,GB +3253434368,3253434623,IT +3253434624,3253434879,SE +3253434880,3253435135,IT +3253435136,3253440511,SE +3253440512,3253440767,FR +3253440768,3253453311,SE +3253453312,3253453567,NO +3253453568,3253454079,SE +3253454080,3253454335,GB +3253454336,3253460735,SE +3253460736,3253460991,IT +3253460992,3253469183,SE 3253469184,3253471231,AO 3253471232,3253534719,PT 3253534720,3253600255,GB @@ -81793,6 +83802,8 @@ 3254785280,3254785535,KZ 3254785536,3254785791,DK 3254785792,3254786047,LU +3254786304,3254786815,AT +3254786816,3254787071,SM 3254796288,3254797311,SE 3254797312,3254798335,RU 3254798336,3254799359,AT @@ -82379,7 +84390,7 @@ 3255401472,3255412479,DE 3255412480,3255412735,RO 3255412736,3255413247,DE -3255413248,3255413759,LV +3255413248,3255413503,LV 3255413760,3255414271,GB 3255414272,3255414527,TR 3255414528,3255414783,LV @@ -82503,11 +84514,17 @@ 3255660544,3255666431,NL 3255666432,3255666687,DE 3255666688,3255697407,NL -3255697408,3255739647,SE +3255697408,3255710719,SE +3255710720,3255710975,ES +3255710976,3255724543,SE +3255724544,3255725055,US +3255725056,3255725311,ES +3255725312,3255739647,SE 3255739648,3255739903,GB 3255739904,3255743231,SE 3255743232,3255743487,IT -3255743488,3255745535,SE +3255743488,3255743743,DE +3255743744,3255745535,SE 3255745536,3255746047,DK 3255746048,3255762943,SE 3255762944,3255791615,DE @@ -82581,7 +84598,6 @@ 3256413184,3256413695,UA 3256413696,3256414207,PL 3256414208,3256414719,RU -3256414720,3256415231,DE 3256415232,3256415743,PL 3256415744,3256416255,UA 3256416256,3256416767,RS @@ -82684,7 +84700,8 @@ 3256699136,3256699391,NL 3256699392,3256700415,GB 3256700416,3256700671,NL -3256700672,3256701183,EU +3256700672,3256700927,FR +3256700928,3256701183,EU 3256701184,3256701439,BE 3256701440,3256701695,GB 3256701696,3256705279,EU @@ -82816,7 +84833,6 @@ 3257401344,3257466879,CH 3257466880,3257467135,DE 3257467136,3257467391,GB -3257467392,3257467903,NL 3257467904,3257468927,IT 3257468928,3257469183,EU 3257469184,3257469439,IT @@ -84093,11 +86109,27 @@ 3259228160,3259236351,RU 3259236352,3259236863,SE 3259236864,3259237119,CH -3259237120,3259269375,SE +3259237120,3259237887,SE +3259237888,3259238143,FR +3259238144,3259248127,SE +3259248128,3259248383,GB +3259248384,3259258623,SE +3259258624,3259258879,ES +3259258880,3259262719,SE +3259262720,3259262975,DK +3259262976,3259269375,SE 3259269376,3259269631,FR -3259269632,3259292415,SE +3259269632,3259276287,SE +3259276288,3259276543,ES +3259276544,3259285759,SE +3259285760,3259286015,GB +3259286016,3259290879,SE +3259290880,3259291135,US +3259291136,3259292415,SE 3259292416,3259292671,IT -3259292672,3259301887,SE +3259292672,3259297535,SE +3259297536,3259297791,GB +3259297792,3259301887,SE 3259301888,3259302143,DE 3259302144,3259302399,AE 3259302400,3259303423,CH @@ -84201,13 +86233,19 @@ 3259367424,3259432959,GB 3259432960,3259435263,SE 3259435264,3259435519,IT -3259435520,3259457279,SE +3259435520,3259438079,SE +3259438080,3259438335,ES +3259438336,3259457279,SE 3259457280,3259457535,IT 3259457536,3259460351,SE 3259460352,3259460607,DE 3259460608,3259465215,SE 3259465216,3259465471,KH -3259465472,3259492351,SE +3259465472,3259479807,SE +3259479808,3259480063,DK +3259480064,3259480831,SE +3259480832,3259481087,ES +3259481088,3259492351,SE 3259492352,3259493375,GB 3259493376,3259498495,SE 3259498496,3259506943,GB @@ -84439,15 +86477,7 @@ 3260809216,3260874751,PL 3260874752,3260875775,DK 3260875776,3260876031,GB -3260876032,3260891391,DK -3260891392,3260891647,IT -3260891648,3260891903,NL -3260891904,3260892159,ES -3260892160,3260892415,GB -3260892416,3260892671,FI -3260892672,3260892927,PT -3260892928,3260893183,SE -3260893184,3260893439,AT +3260876032,3260893439,DK 3260893440,3260894207,SE 3260894208,3260895231,AT 3260895232,3260898303,SE @@ -87681,14 +89711,21 @@ 3263138560,3263138815,AT 3263138816,3263168511,DE 3263168512,3263430655,GB -3263430656,3263436799,SE +3263430656,3263436543,SE +3263436544,3263436799,ES 3263436800,3263437311,GB -3263437312,3263461631,SE +3263437312,3263458047,SE +3263458048,3263458303,DE +3263458304,3263459583,SE +3263459584,3263459839,FR +3263459840,3263461631,SE 3263461632,3263461887,AE 3263461888,3263477759,SE 3263477760,3263478015,JP 3263478016,3263478271,AU -3263478272,3263496191,SE +3263478272,3263478527,SE +3263478528,3263478783,ES +3263478784,3263496191,SE 3263496192,3263497983,EU 3263497984,3263498239,GB 3263498240,3263498751,EU @@ -87919,7 +89956,7 @@ 3264320000,3264320255,DE 3264320256,3264321023,GB 3264321024,3264321535,DE -3264321536,3264321791,SE +3264321536,3264321791,GB 3264321792,3264322047,RS 3264322048,3264322303,FR 3264322304,3264322559,RO @@ -88017,7 +90054,9 @@ 3264431104,3264431615,LI 3264431616,3264446207,CH 3264446208,3264446463,FR -3264446464,3264463871,CH +3264446464,3264447743,CH +3264447744,3264447999,DE +3264448000,3264463871,CH 3264463872,3264466943,LI 3264466944,3264483071,CH 3264483072,3264483327,LI @@ -88408,7 +90447,6 @@ 3265605376,3265605631,CZ 3265605632,3265605887,PL 3265605888,3265606143,FR -3265606144,3265606399,RU 3265606400,3265606655,DE 3265606656,3265606911,AT 3265606912,3265607167,FR @@ -88913,8 +90951,8 @@ 3267648512,3267648767,DE 3267648768,3267649023,NL 3267649024,3267649279,RU -3267649280,3267649295,DE -3267649296,3267649311,EU +3267649280,3267649303,DE +3267649304,3267649311,EU 3267649312,3267649471,DE 3267649472,3267649791,EU 3267649792,3267650303,NL @@ -88967,8 +91005,8 @@ 3267661848,3267661855,EU 3267661856,3267661887,ES 3267661888,3267662023,EU -3267662024,3267662031,ES -3267662032,3267662047,EU +3267662024,3267662039,ES +3267662040,3267662047,EU 3267662048,3267662079,ES 3267662080,3267662847,EU 3267662848,3267662879,IE @@ -89012,9 +91050,7 @@ 3267667456,3267667967,GB 3267667968,3267670015,EU 3267670016,3267671551,ZA -3267671552,3267671679,DE -3267671680,3267671711,EU -3267671712,3267671807,DE +3267671552,3267671807,DE 3267671808,3267672063,NO 3267672064,3267672223,DE 3267672224,3267672255,EU @@ -89030,9 +91066,7 @@ 3267673024,3267673087,FR 3267673088,3267673439,DE 3267673440,3267673471,EU -3267673472,3267673479,DE -3267673480,3267673487,EU -3267673488,3267673503,DE +3267673472,3267673503,DE 3267673504,3267673599,EU 3267673600,3267673759,DE 3267673760,3267673807,EU @@ -89215,9 +91249,7 @@ 3268223232,3268224767,EU 3268224768,3268225023,US 3268225024,3268226367,EU -3268226368,3268226663,GB -3268226664,3268226671,EU -3268226672,3268226815,GB +3268226368,3268226815,GB 3268226816,3268227327,EU 3268227328,3268227391,GB 3268227392,3268227519,EU @@ -89554,7 +91586,11 @@ 3268935680,3269057535,GB 3269057536,3269058047,NL 3269058048,3269066751,GB -3269066752,3269131555,SE +3269066752,3269118087,SE +3269118088,3269118091,GB +3269118092,3269122343,SE +3269122344,3269122351,GB +3269122352,3269131555,SE 3269131556,3269131559,NO 3269131560,3269132287,SE 3269132288,3269197823,GR @@ -90288,9 +92324,7 @@ 3271821247,3271821247,AT 3271821248,3271847487,DE 3271847488,3271847495,US -3271847496,3271851879,DE -3271851880,3271851887,NL -3271851888,3271884799,DE +3271847496,3271884799,DE 3271884800,3271901183,UA 3271901184,3271909375,ES 3271909376,3271909887,RO @@ -90731,7 +92765,9 @@ 3272358912,3272359935,NL 3272359936,3272368127,RU 3272368128,3272376319,KZ -3272376320,3272384511,SK +3272376320,3272376447,SK +3272376448,3272376463,SR +3272376464,3272384511,SK 3272384512,3272392703,LT 3272392704,3272400895,AT 3272400896,3272400903,EU @@ -92349,7 +94385,6 @@ 3275108352,3275108863,FR 3275108864,3275109375,PL 3275109376,3275109887,UA -3275109888,3275110399,DE 3275110400,3275110911,NL 3275110912,3275111423,GB 3275111424,3275111935,IT @@ -92392,8 +94427,10 @@ 3275423752,3275423775,EU 3275423776,3275423807,GB 3275423808,3275423871,EU -3275423872,3275424719,GB -3275424720,3275425791,EU +3275423872,3275424751,GB +3275424752,3275424767,EU +3275424768,3275424895,GB +3275424896,3275425791,EU 3275425792,3275427271,GB 3275427272,3275427279,EU 3275427280,3275427615,GB @@ -92432,9 +94469,7 @@ 3275450880,3275451231,EU 3275451232,3275451263,GB 3275451264,3275452415,EU -3275452416,3275453423,GB -3275453424,3275453439,EU -3275453440,3275454127,GB +3275452416,3275454127,GB 3275454128,3275454143,EU 3275454144,3275457023,GB 3275457024,3275457791,FK @@ -92444,8 +94479,8 @@ 3275460608,3275460863,HK 3275460864,3275463523,GB 3275463524,3275463527,EU -3275463528,3275463583,GB -3275463584,3275463679,EU +3275463528,3275463631,GB +3275463632,3275463679,EU 3275463680,3275464031,GB 3275464032,3275464047,IE 3275464048,3275468655,GB @@ -92456,8 +94491,8 @@ 3275468768,3275468799,IE 3275468800,3275469071,GB 3275469072,3275469087,IE -3275469088,3275471871,GB -3275471872,3275489279,EU +3275469088,3275472895,GB +3275472896,3275489279,EU 3275489280,3275497471,GB 3275497472,3275505663,DE 3275505664,3275506175,PL @@ -92474,7 +94509,6 @@ 3275510016,3275510079,SE 3275510080,3275510143,ES 3275510144,3275510207,FI -3275510208,3275510271,SE 3275510336,3275510399,IE 3275510400,3275510463,NL 3275510464,3275510527,GB @@ -92790,9 +94824,7 @@ 3275808768,3275816959,UA 3275816960,3275818207,CH 3275818208,3275818215,DE -3275818216,3275881335,CH -3275881336,3275881343,DE -3275881344,3275882495,CH +3275818216,3275882495,CH 3275882496,3275884543,DE 3275884544,3275886591,IT 3275886592,3275888639,PL @@ -92812,7 +94844,7 @@ 3275902720,3275902975,UA 3275902976,3275903231,FR 3275903232,3275903487,GB -3275903488,3275903999,DE +3275903744,3275903999,DE 3275904000,3275904255,RU 3275904256,3275904511,CH 3275904512,3275904767,PL @@ -93002,7 +95034,9 @@ 3276019136,3276019151,GB 3276019152,3276019463,FR 3276019464,3276019471,GB -3276019472,3276019503,FR +3276019472,3276019479,FR +3276019480,3276019487,GB +3276019488,3276019503,FR 3276019504,3276019511,GB 3276019512,3276019535,FR 3276019536,3276019543,GB @@ -93050,7 +95084,9 @@ 3276022456,3276022463,GB 3276022464,3276022479,FR 3276022480,3276022495,GB -3276022496,3276022519,FR +3276022496,3276022503,FR +3276022504,3276022511,GB +3276022512,3276022519,FR 3276022520,3276022527,GB 3276022528,3276022567,FR 3276022568,3276022639,GB @@ -93107,9 +95143,7 @@ 3276026224,3276026319,FR 3276026320,3276026351,GB 3276026352,3276026423,FR -3276026424,3276026431,GB -3276026432,3276026439,FR -3276026440,3276026447,GB +3276026424,3276026447,GB 3276026448,3276026527,FR 3276026528,3276026535,GB 3276026536,3276026543,FR @@ -93219,8 +95253,8 @@ 3276031744,3276032007,FR 3276032008,3276032015,GB 3276032016,3276032023,FR -3276032024,3276032031,GB -3276032032,3276032055,FR +3276032024,3276032047,GB +3276032048,3276032055,FR 3276032056,3276032063,GB 3276032064,3276032103,FR 3276032104,3276032111,GB @@ -93284,7 +95318,9 @@ 3276038048,3276038111,GB 3276038112,3276038143,FR 3276038144,3276038399,GB -3276038400,3276038703,FR +3276038400,3276038663,FR +3276038664,3276038671,GB +3276038672,3276038703,FR 3276038704,3276038719,GB 3276038720,3276038735,FR 3276038736,3276038767,GB @@ -93302,9 +95338,9 @@ 3276039328,3276039343,GB 3276039344,3276039391,FR 3276039392,3276039423,GB -3276039424,3276039551,FR -3276039552,3276039567,GB -3276039568,3276039647,FR +3276039424,3276039615,FR +3276039616,3276039631,GB +3276039632,3276039647,FR 3276039648,3276039663,GB 3276039664,3276039967,FR 3276039968,3276040031,GB @@ -93342,8 +95378,8 @@ 3276041280,3276041311,GB 3276041312,3276041391,FR 3276041392,3276041407,GB -3276041408,3276041487,FR -3276041488,3276041503,GB +3276041408,3276041495,FR +3276041496,3276041503,GB 3276041504,3276041519,FR 3276041520,3276041535,GB 3276041536,3276041551,FR @@ -93356,18 +95392,18 @@ 3276041920,3276041951,GB 3276041952,3276041967,FR 3276041968,3276041983,GB -3276041984,3276042031,FR -3276042032,3276042143,GB +3276041984,3276042039,FR +3276042040,3276042143,GB 3276042144,3276042175,FR 3276042176,3276042191,GB 3276042192,3276042207,FR 3276042208,3276042239,GB -3276042240,3276042767,FR -3276042768,3276042815,GB +3276042240,3276042775,FR +3276042776,3276042815,GB 3276042816,3276042831,FR 3276042832,3276042847,GB -3276042848,3276044303,FR -3276044304,3276044319,GB +3276042848,3276044311,FR +3276044312,3276044319,GB 3276044320,3276044351,FR 3276044352,3276044359,GB 3276044360,3276044367,FR @@ -95665,7 +97701,8 @@ 3276479224,3276479279,FR 3276479280,3276479295,EU 3276479296,3276479343,FR -3276479344,3276479359,EU +3276479344,3276479351,GB +3276479352,3276479359,EU 3276479360,3276479615,FR 3276479616,3276479647,EU 3276479648,3276479743,FR @@ -95724,9 +97761,9 @@ 3276494384,3276494415,EU 3276494416,3276495503,GB 3276495504,3276495519,EU -3276495520,3276495679,GB -3276495680,3276495775,EU -3276495776,3276496639,GB +3276495520,3276495763,GB +3276495764,3276495767,EU +3276495768,3276496639,GB 3276496640,3276496895,EU 3276496896,3276497151,DE 3276497152,3276497215,EU @@ -96028,8 +98065,8 @@ 3276536736,3276536743,HU 3276536744,3276536831,EU 3276536832,3276536895,ES -3276536896,3276536967,EU -3276536968,3276536991,ES +3276536896,3276536959,EU +3276536960,3276536991,ES 3276536992,3276537151,EU 3276537152,3276537215,AT 3276537216,3276537343,EU @@ -96520,7 +98557,11 @@ 3276877536,3276877551,AT 3276877552,3276878079,GB 3276878080,3276878335,BG -3276878336,3276878591,GB +3276878336,3276878399,GB +3276878400,3276878421,FR +3276878422,3276878431,GB +3276878432,3276878495,FR +3276878496,3276878591,GB 3276878592,3276878847,FR 3276878848,3276879359,ES 3276879360,3276879423,TR @@ -96537,11 +98578,12 @@ 3276884736,3276884991,PL 3276884992,3276886015,GB 3276886016,3276886271,RO -3276886272,3276886527,GB -3276886528,3276886943,DE +3276886272,3276886943,DE 3276886944,3276886959,GB -3276886960,3276886975,DE -3276886976,3276887071,GB +3276886960,3276886991,DE +3276886992,3276887047,GB +3276887048,3276887057,DE +3276887058,3276887071,GB 3276887072,3276888063,DE 3276888064,3276888575,GB 3276888576,3276888831,AT @@ -96574,15 +98616,16 @@ 3276900040,3276900047,GB 3276900048,3276900351,CH 3276900352,3276900607,GB -3276900608,3276901471,CH -3276901472,3276901631,GB +3276900608,3276901503,CH +3276901504,3276901519,ES +3276901520,3276901631,GB 3276901632,3276902151,CH 3276902152,3276902159,GB 3276902160,3276902191,CH -3276902192,3276902207,GB -3276902208,3276902271,CH -3276902272,3276902399,GB -3276902400,3276902583,SE +3276902192,3276902399,GB +3276902400,3276902407,SE +3276902408,3276902431,GB +3276902432,3276902583,SE 3276902584,3276902615,GB 3276902616,3276902639,SE 3276902640,3276902655,GB @@ -96608,7 +98651,12 @@ 3276906832,3276907551,NL 3276907552,3276907567,BE 3276907568,3276907643,NL -3276907644,3276907775,GB +3276907644,3276907647,GB +3276907648,3276907663,NL +3276907664,3276907679,BE +3276907680,3276907695,GB +3276907696,3276907743,NL +3276907744,3276907775,GB 3276907776,3276908159,NL 3276908160,3276908175,CH 3276908176,3276908287,GB @@ -96617,7 +98665,9 @@ 3276909568,3276910591,NL 3276910592,3276910967,IT 3276910968,3276910975,GB -3276910976,3276912615,IT +3276910976,3276912319,IT +3276912320,3276912383,GB +3276912384,3276912615,IT 3276912616,3276912623,GB 3276912624,3276913183,IT 3276913184,3276913215,GB @@ -96666,9 +98716,7 @@ 3276923448,3276923455,DE 3276923456,3276924071,FR 3276924072,3276924079,GB -3276924080,3276926751,FR -3276926752,3276926783,GB -3276926784,3276926847,FR +3276924080,3276926847,FR 3276926848,3276931071,GB 3276931072,3276939263,KZ 3276939264,3276955647,DE @@ -96701,7 +98749,6 @@ 3277179392,3277179647,DE 3277179648,3277180159,BE 3277180160,3277180415,NL -3277180416,3277180671,GB 3277180672,3277180927,FR 3277180928,3277181183,DE 3277181184,3277181439,PL @@ -96873,7 +98920,9 @@ 3277395968,3277452647,GB 3277452648,3277452655,DK 3277452656,3277455359,GB -3277455360,3277463551,DE +3277455360,3277456895,DE +3277456896,3277457151,CH +3277457152,3277463551,DE 3277463552,3277463807,GB 3277463808,3277464063,US 3277464064,3277464575,FR @@ -97068,16 +99117,18 @@ 3277881344,3277884175,IT 3277884176,3277884191,IR 3277884192,3277885439,IT -3277885440,3277885727,LB +3277885440,3277885695,IQ +3277885696,3277885727,LB 3277885728,3277885951,IT -3277885952,3277886207,LB -3277886208,3277886463,IT +3277885952,3277886463,LB 3277886464,3277886719,IQ 3277886720,3277886975,IR 3277886976,3277887487,IQ 3277887488,3277888255,IT 3277888256,3277888319,LB -3277888320,3277889535,IT +3277888320,3277889023,IT +3277889024,3277889279,IQ +3277889280,3277889535,IT 3277889536,3277897727,RU 3277897728,3277905919,IT 3277905920,3277914111,BG @@ -99017,7 +101068,7 @@ 3278944036,3278944036,US 3278944037,3278944037,FR 3278944038,3278944038,GB -3278944039,3278944039,ES +3278944039,3278944039,DE 3278944040,3278944040,FR 3278944041,3278944041,DE 3278944042,3278944042,FR @@ -101761,7 +103812,6 @@ 3281341440,3281341695,DE 3281341696,3281341951,PL 3281341952,3281342207,DK -3281342208,3281342463,GB 3281342464,3281343231,DE 3281343232,3281343487,FI 3281343488,3281343743,GB @@ -102204,7 +104254,6 @@ 3283495680,3283495935,NL 3283495936,3283496191,BG 3283496192,3283496447,DE -3283496448,3283496703,FR 3283496704,3283496959,LV 3283496960,3283497215,DE 3283497216,3283497471,GB @@ -102271,12 +104320,10 @@ 3283550624,3283550655,FR 3283550656,3283550719,GB 3283550720,3283552255,AT -3283552256,3283552279,IT -3283552280,3283552287,EU -3283552288,3283552319,IT +3283552256,3283552319,IT 3283552320,3283552351,EU -3283552352,3283552415,IT -3283552416,3283552447,EU +3283552352,3283552431,IT +3283552432,3283552447,EU 3283552448,3283552575,IT 3283552576,3283552639,DE 3283552640,3283552671,IT @@ -103291,9 +105338,7 @@ 3285457664,3285457759,IT 3285457760,3285457791,EU 3285457792,3285457919,IT -3285457920,3285457967,GB -3285457968,3285457983,EU -3285457984,3285458111,GB +3285457920,3285458111,GB 3285458112,3285458175,EU 3285458176,3285458943,GB 3285458944,3285458975,DK @@ -103360,7 +105405,8 @@ 3285463312,3285463319,BE 3285463320,3285463359,EU 3285463360,3285463455,BE -3285463456,3285463519,EU +3285463456,3285463487,EU +3285463488,3285463519,GB 3285463520,3285463615,BE 3285463616,3285463647,FR 3285463648,3285463743,BE @@ -103546,7 +105592,9 @@ 3285485640,3285485647,SK 3285485648,3285485727,EU 3285485728,3285485743,SK -3285485744,3285485799,EU +3285485744,3285485751,EU +3285485752,3285485759,SK +3285485760,3285485799,EU 3285485800,3285485815,SK 3285485816,3285486591,EU 3285486592,3285487103,IT @@ -103584,8 +105632,8 @@ 3285493760,3285493775,ES 3285493776,3285493783,EU 3285493784,3285493887,ES -3285493888,3285493967,EU -3285493968,3285493983,ES +3285493888,3285493951,EU +3285493952,3285493983,ES 3285493984,3285493991,GB 3285493992,3285493999,EU 3285494000,3285494015,ES @@ -103594,9 +105642,7 @@ 3285494112,3285494783,IT 3285494784,3285495807,EU 3285495808,3285496319,DE -3285496320,3285496335,ES -3285496336,3285496351,EU -3285496352,3285496383,ES +3285496320,3285496383,ES 3285496384,3285496463,EU 3285496464,3285496471,ES 3285496472,3285496479,EU @@ -103607,9 +105653,7 @@ 3285496576,3285496607,EU 3285496608,3285497855,DE 3285497856,3285497887,EU -3285497888,3285498031,DE -3285498032,3285498047,EU -3285498048,3285498079,DE +3285497888,3285498079,DE 3285498080,3285498095,EU 3285498096,3285498111,DE 3285498112,3285498367,IT @@ -103628,9 +105672,7 @@ 3285500288,3285500415,CZ 3285500416,3285500927,GB 3285500928,3285501183,DK -3285501184,3285501311,CZ -3285501312,3285501319,EU -3285501320,3285501327,CZ +3285501184,3285501327,CZ 3285501328,3285501335,EU 3285501336,3285501343,CZ 3285501344,3285501375,GB @@ -104570,7 +106612,8 @@ 3285911552,3285912575,EU 3285912576,3285913087,GB 3285913088,3285913215,ES -3285913216,3285913343,EU +3285913216,3285913231,GB +3285913232,3285913343,EU 3285913344,3285913599,GB 3285913600,3285915647,EU 3285915648,3285915903,GB @@ -104614,10 +106657,12 @@ 3285926408,3285926415,ES 3285926416,3285926431,GB 3285926432,3285926463,CH -3285926464,3285926479,GB -3285926480,3285926783,EU -3285926784,3285926799,GB -3285926800,3285926847,EU +3285926464,3285926511,GB +3285926512,3285926639,EU +3285926640,3285926671,GB +3285926672,3285926783,EU +3285926784,3285926815,GB +3285926816,3285926847,EU 3285926848,3285926911,GB 3285926912,3285927423,DE 3285927424,3285927679,GB @@ -104633,8 +106678,8 @@ 3285928320,3285928447,EU 3285928448,3285928959,ES 3285928960,3285929983,EU -3285929984,3285930495,GB -3285930496,3285930559,EU +3285929984,3285930511,GB +3285930512,3285930559,EU 3285930560,3285930575,ES 3285930576,3285930623,GB 3285930624,3285930631,BE @@ -104643,8 +106688,8 @@ 3285930656,3285930671,NL 3285930672,3285930679,BE 3285930680,3285930687,DE -3285930688,3285930703,GB -3285930704,3285930751,EU +3285930688,3285930719,GB +3285930720,3285930751,EU 3285930752,3285931007,GB 3285931008,3285932031,EU 3285932032,3285932287,NL @@ -104673,8 +106718,8 @@ 3285939072,3285939199,EU 3285939200,3285939711,ES 3285939712,3285940223,EU -3285940224,3285940735,ES -3285940736,3285941247,GB +3285940224,3285940479,ES +3285940480,3285941247,GB 3285941248,3285942655,EU 3285942656,3285942783,IR 3285942784,3285943039,ES @@ -104692,8 +106737,8 @@ 3285945344,3285945599,ES 3285945600,3285945663,EU 3285945664,3285945695,FR -3285945696,3285945727,GB -3285945728,3285945855,EU +3285945696,3285945743,GB +3285945744,3285945855,EU 3285945856,3285946111,GB 3285946112,3285946367,ES 3285946368,3285946879,GB @@ -104714,13 +106759,17 @@ 3285949952,3285950463,ES 3285950464,3285950719,GB 3285950720,3285950783,US -3285950784,3285950975,EU +3285950784,3285950799,GB +3285950800,3285950959,EU +3285950960,3285950975,GB 3285950976,3285951231,NL 3285951232,3285951487,IT -3285951488,3285951615,EU +3285951488,3285951503,GB +3285951504,3285951615,EU 3285951616,3285951647,GB 3285951648,3285951679,ES -3285951680,3285951743,EU +3285951680,3285951695,GB +3285951696,3285951743,EU 3285951744,3285951999,GB 3285952000,3285952255,IT 3285952256,3285952511,SA @@ -104734,7 +106783,11 @@ 3285956864,3285957631,PT 3285957632,3285957887,PL 3285957888,3285958143,GB -3285958144,3285958847,EU +3285958144,3285958655,EU +3285958656,3285958671,GB +3285958672,3285958783,EU +3285958784,3285958799,GB +3285958800,3285958847,EU 3285958848,3285958895,NL 3285958896,3285959039,GB 3285959040,3285959167,DE @@ -104755,7 +106808,10 @@ 3285967616,3285968383,BE 3285968384,3285968639,ES 3285968640,3285968895,PL -3285968896,3285971199,EU +3285968896,3285971007,EU +3285971008,3285971023,GB +3285971024,3285971183,EU +3285971184,3285971199,GB 3285971200,3285971455,FR 3285971456,3285971711,DE 3285971712,3285971967,GB @@ -104763,7 +106819,13 @@ 3285972224,3285972479,EU 3285972480,3285972735,PL 3285972736,3285972991,FR -3285972992,3285975039,GB +3285972992,3285973095,GB +3285973096,3285973247,EU +3285973248,3285973767,GB +3285973768,3285973791,EU +3285973792,3285973823,GB +3285973824,3285974015,EU +3285974016,3285975039,GB 3285975040,3286106111,FR 3286106112,3286106687,EE 3286106688,3286106691,FI @@ -104805,7 +106867,6 @@ 3286313984,3286314495,CH 3286314496,3286315007,IL 3286315008,3286315519,UA -3286315520,3286316031,DE 3286316032,3286316543,UA 3286316544,3286317055,NL 3286317056,3286317567,RU @@ -104889,7 +106950,7 @@ 3286423808,3286424063,CZ 3286424064,3286424319,LV 3286424320,3286424575,FR -3286424576,3286424831,UA +3286424576,3286424831,RU 3286424832,3286425087,TR 3286425088,3286425343,RU 3286425344,3286425599,IT @@ -105358,8 +107419,7 @@ 3287481344,3287482367,PL 3287482368,3287499279,DE 3287499280,3287499287,FR -3287499288,3287499295,US -3287499296,3287499439,DE +3287499288,3287499439,DE 3287499440,3287499471,GB 3287499472,3287499487,DE 3287499488,3287499503,GB @@ -105980,6 +108040,11 @@ 3291205632,3291206143,ZA 3291206144,3291206399,AO 3291206400,3291206911,KE +3291207168,3291207423,MG +3291207424,3291207679,NG +3291207680,3291207935,BW +3291207936,3291208447,KE +3291208448,3291208703,EG 3291217920,3291230207,ZA 3291230208,3291234303,GH 3291234304,3291242495,ZA @@ -106053,7 +108118,6 @@ 3291437568,3291437823,NA 3291437824,3291439103,ZA 3291447296,3291463679,CI -3291480064,3291480319,MU 3291742208,3292004351,ZA 3300917248,3300921343,MU 3300925440,3300929535,MG @@ -106182,9 +108246,12 @@ 3302954240,3302954495,KE 3302954496,3302955007,ZA 3302955008,3302955263,LS +3302955264,3302955519,UG 3305111552,3307208703,TN +3307208704,3309305855,EG 3309305856,3310354431,ZA 3311403008,3312451583,ZA +3312451584,3312975871,DZ 3312975872,3313500159,EG 3313500160,3313762303,MA 3313762304,3314024447,EG @@ -106197,23 +108264,30 @@ 3318218752,3318743039,DZ 3319529472,3319537663,ZM 3319537664,3319545855,UG +3319545856,3319554047,SO +3319554048,3319562239,KE +3319562240,3319570431,LS 3319652352,3319660543,ZW 3319660544,3319791615,EG 3319791616,3320053759,MU 3320578048,3320643583,ZA 3320643584,3320709119,KE 3320709120,3320840191,ZA +3321364480,3321430015,KE +3321430016,3321495551,MZ +3321692160,3321708543,NG 3321708544,3321724927,GH 3321724928,3321757695,MA 3321757696,3321790463,KE 3321790464,3321806847,LS 3321806848,3321823231,SD 3321823232,3321839615,NG -3321839616,3321855999,MU +3321839616,3321855999,GH 3321856000,3321860095,CV 3321860096,3321864191,ZA 3321864192,3321868287,NG 3321868288,3321872383,CG +3321872384,3321876479,GM 3321954304,3321970687,US 3322019840,3322023935,US 3322023936,3322028031,CL @@ -106318,7 +108392,9 @@ 3324379136,3324380159,CA 3324380160,3324391423,US 3324395520,3324399615,US -3324411904,3324579839,US +3324411904,3324470271,US +3324470272,3324471295,GB +3324471296,3324579839,US 3324579840,3324583935,NZ 3324583936,3324588031,CL 3324592128,3324596223,US @@ -107137,7 +109213,9 @@ 3341778944,3341807615,US 3341807616,3341808639,CA 3341808640,3341828095,US -3341844480,3341854551,US +3341844480,3341854079,US +3341854080,3341854207,SG +3341854208,3341854551,US 3341854552,3341854559,SG 3341854560,3341863935,US 3341863936,3341864959,AG @@ -107172,7 +109250,63 @@ 3342605312,3342605567,US 3342605568,3342663679,CA 3342663680,3343007743,US -3343024128,3343055871,US +3343024128,3343046915,US +3343046916,3343046919,GB +3343046920,3343046927,IT +3343046928,3343046939,US +3343046940,3343046943,RU +3343046944,3343046947,KW +3343046948,3343046951,PT +3343046952,3343046955,US +3343046956,3343046959,IT +3343046960,3343046963,BE +3343046964,3343046967,US +3343046968,3343046971,NL +3343046972,3343046979,US +3343046980,3343046983,GB +3343046984,3343046987,US +3343046988,3343046991,CA +3343046992,3343046999,US +3343047000,3343047003,RU +3343047004,3343047011,US +3343047012,3343047015,AU +3343047016,3343047039,US +3343047040,3343047047,CA +3343047048,3343047079,US +3343047080,3343047087,GR +3343047088,3343047111,US +3343047112,3343047127,SG +3343047128,3343047143,US +3343047144,3343047159,IT +3343047160,3343047327,US +3343047328,3343047343,IT +3343047344,3343047423,US +3343047424,3343047439,RU +3343047440,3343047455,UA +3343047456,3343047471,IE +3343047472,3343047519,US +3343047520,3343047535,IN +3343047536,3343047599,US +3343047600,3343047615,GB +3343047616,3343047687,US +3343047688,3343047695,CA +3343047696,3343047727,US +3343047728,3343047735,CA +3343047736,3343047743,US +3343047744,3343047751,AU +3343047752,3343047759,BR +3343047760,3343047791,US +3343047792,3343047799,PL +3343047800,3343047847,US +3343047848,3343047855,IT +3343047856,3343047863,US +3343047864,3343047871,RU +3343047872,3343047879,AU +3343047880,3343047903,US +3343047904,3343047911,AR +3343047912,3343047935,US +3343047936,3343047967,CA +3343047968,3343055871,US 3343055872,3343056895,CA 3343056896,3343167487,US 3343167488,3343169535,CA @@ -107226,9 +109360,7 @@ 3344637952,3344642047,US 3344662528,3344670719,US 3344670720,3344671743,GP -3344671744,3344673919,US -3344673920,3344673983,GB -3344673984,3344676863,US +3344671744,3344676863,US 3344676864,3344678911,CA 3344678912,3344681983,US 3344681984,3344685055,CA @@ -107309,9 +109441,30 @@ 3346241536,3346243583,CA 3346243584,3346282495,US 3346282496,3346284543,PR -3346333696,3346923519,US +3346300928,3346323455,US +3346323456,3346325503,CA +3346325504,3346327551,US +3346327552,3346328575,CA +3346328576,3346481151,US +3346497536,3346498559,CA +3346498560,3346499583,US +3346499584,3346501631,VI +3346501632,3346520063,US +3346520064,3346521087,CA +3346521088,3346524159,US +3346524160,3346525183,CA +3346525184,3346528255,US +3346528256,3346529279,PR +3346529280,3346530303,CA +3346530304,3346923519,US 3346923520,3346989055,CA 3346989056,3347005439,US +3347021824,3347022847,CA +3347022848,3347033087,US +3347033088,3347034111,CA +3347034112,3347039231,US +3347039232,3347040255,DM +3347040256,3347044351,US 3347054592,3349268479,US 3349268480,3349268991,CA 3349268992,3349273087,US @@ -107487,7 +109640,9 @@ 3352066048,3352067071,CA 3352067072,3352068095,US 3352068096,3352069119,CA -3352069120,3352082431,US +3352069120,3352069919,US +3352069920,3352069935,CO +3352069936,3352082431,US 3352082432,3352083455,JM 3352083456,3352088575,US 3352088576,3352090623,CA @@ -108749,7 +110904,7 @@ 3362529280,3362533375,PA 3362537472,3362545663,AR 3362545664,3362549759,PE -3362549760,3362551807,AR +3362549760,3362553855,AR 3362553856,3362557951,PY 3362562048,3362563071,BZ 3362563072,3362563199,PA @@ -113799,7 +115954,7 @@ 3419878144,3419878399,IN 3419878400,3419879423,GU 3419879424,3419880447,JP -3419880448,3419881471,MY +3419880448,3419881471,MM 3419881472,3419897855,PH 3419897856,3419899903,JP 3419899904,3419900159,FR @@ -114031,7 +116186,9 @@ 3423161480,3423161487,HK 3423161488,3423161613,US 3423161614,3423161621,CA -3423161622,3423162303,US +3423161622,3423162159,US +3423162160,3423162167,MX +3423162168,3423162303,US 3423162304,3423162311,GB 3423162312,3423162367,US 3423162368,3423163391,CA @@ -114512,17 +116669,29 @@ 3423652000,3423653887,CA 3423653888,3423705599,US 3423705600,3423705855,CA -3423705856,3423797247,US -3423797248,3423823359,CA +3423705856,3423797503,US +3423797504,3423823359,CA 3423823360,3423823871,US 3423823872,3423827711,CA 3423827712,3423827967,US -3423827968,3423848447,CA +3423827968,3423830271,CA +3423830272,3423830527,US +3423830528,3423838719,CA +3423838720,3423838975,US +3423838976,3423848447,CA 3423848448,3423849471,KN -3423849984,3423858175,CA +3423849984,3423850495,CA +3423850496,3423850751,US +3423850752,3423854335,CA +3423854336,3423854591,US +3423854592,3423858175,CA 3423858176,3423858687,US -3423858688,3423862783,CA -3423862784,3424334847,US +3423858688,3423858943,CA +3423858944,3423859455,US +3423859456,3423859711,CA +3423859712,3423859967,US +3423859968,3423862527,CA +3423862528,3424334847,US 3424334848,3424335871,CA 3424335872,3424378879,US 3424378880,3424379135,PR @@ -114538,7 +116707,9 @@ 3425830816,3425830831,US 3425830832,3425855231,CA 3425855232,3425855487,US -3425855488,3425869167,CA +3425855488,3425864711,CA +3425864712,3425864719,US +3425864720,3425869167,CA 3425869168,3425869183,US 3425869184,3425875391,CA 3425875392,3425875407,US @@ -114560,9 +116731,11 @@ 3426388992,3426617855,US 3426618368,3426618687,US 3426618688,3426618703,NZ -3426618704,3426618911,US -3426618912,3426618943,NZ -3426618944,3426646015,US +3426618704,3426618735,US +3426618736,3426618751,NZ +3426618752,3426618911,US +3426618912,3426619071,NZ +3426619072,3426646015,US 3426646016,3426647039,CA 3426647040,3426744319,US 3426744320,3426746367,CA @@ -114674,8 +116847,7 @@ 3427773696,3427773951,FR 3427773952,3427774719,US 3427774720,3427775231,DE -3427775232,3427775999,US -3427776000,3427776511,HK +3427775232,3427776511,US 3427776512,3427776767,CZ 3427776768,3427777023,US 3427777024,3427777279,NL @@ -114960,7 +117132,7 @@ 3428646016,3428646079,CA 3428646080,3428646143,US 3428646144,3428646911,CA -3428646912,3428739327,US +3428679680,3428739327,US 3428739328,3428739343,GB 3428739344,3428743167,US 3428743168,3428744191,CA @@ -115013,7 +117185,9 @@ 3430703872,3430704127,PR 3430704128,3430705151,US 3430705152,3430706175,MX -3430706176,3430747903,US +3430706176,3430722303,US +3430722304,3430722559,CA +3430722560,3430747903,US 3430747904,3430748159,CA 3430748160,3430749951,US 3430749952,3430750207,CA @@ -115387,7 +117561,9 @@ 3437792280,3437792287,SE 3437792288,3437792415,US 3437792416,3437792423,AU -3437792424,3437792735,US +3437792424,3437792527,US +3437792528,3437792535,MX +3437792536,3437792735,US 3437792736,3437792743,CA 3437792744,3437792775,US 3437792776,3437792783,CA @@ -115758,7 +117934,9 @@ 3448563016,3448563031,GB 3448563032,3448569055,US 3448569056,3448569087,MX -3448569088,3449001245,US +3448569088,3448569735,US +3448569736,3448569743,GB +3448569744,3449001245,US 3449001246,3449001246,MC 3449001247,3449159679,US 3449159680,3449160703,CA @@ -117289,10 +119467,7 @@ 3461332736,3461332991,SG 3461332992,3461408767,US 3461410816,3461414911,CA -3461414912,3461435647,US -3461435648,3461435903,CA -3461435904,3461436159,US -3461436416,3461513215,US +3461414912,3461513215,US 3461513216,3461513727,CA 3461513728,3461513983,BF 3461513984,3461514495,CA @@ -117466,8 +119641,8 @@ 3464128000,3464128255,DE 3464128256,3464129535,US 3464129536,3464130047,DE -3464130048,3464167423,US -3464167424,3464171775,CA +3464130048,3464167679,US +3464167680,3464171775,CA 3464171776,3464172031,US 3464172032,3464180735,CA 3464180736,3464184487,US @@ -117484,8 +119659,11 @@ 3464191808,3464191815,US 3464191816,3464191823,CA 3464191824,3464191831,US -3464191832,3464191847,CA -3464191848,3464195543,US +3464191832,3464191839,CA +3464191840,3464191911,US +3464191912,3464191919,ES +3464191920,3464191927,SG +3464191928,3464195543,US 3464195544,3464195551,IT 3464195552,3464195887,US 3464195888,3464195895,PR @@ -117634,7 +119812,9 @@ 3466283328,3466283391,CA 3466283392,3466286103,US 3466286104,3466286111,DE -3466286112,3466313727,US +3466286112,3466290687,US +3466290688,3466290943,CH +3466290944,3466313727,US 3466313728,3466317823,CA 3466317824,3466489855,US 3466489856,3466490111,CA @@ -118095,13 +120275,11 @@ 3470150656,3470150911,CA 3470150912,3470151295,US 3470151296,3470151359,CA -3470151360,3470151935,US -3470151936,3470152703,CA +3470151360,3470151679,US +3470151680,3470152703,CA 3470152704,3470152959,US 3470152960,3470152975,CA -3470152976,3470153983,US -3470153984,3470154239,CA -3470154240,3470184454,US +3470152976,3470184454,US 3470184455,3470184458,LK 3470184459,3470184460,RU 3470184461,3470184476,US @@ -118610,8 +120788,7 @@ 3470362560,3470362623,CA 3470362624,3470362719,US 3470362720,3470362727,CA -3470362728,3470362783,US -3470362784,3470362791,AF +3470362728,3470362791,US 3470362792,3470362799,SG 3470362800,3470362847,US 3470362848,3470362855,AR @@ -118657,7 +120834,8 @@ 3470645632,3470645655,US 3470645656,3470645663,RU 3470645664,3470645687,US -3470645688,3470645703,ES +3470645688,3470645695,ES +3470645696,3470645703,NL 3470645704,3470645731,US 3470645732,3470645735,AU 3470645736,3470645739,CN @@ -118713,8 +120891,7 @@ 3470646608,3470646623,ZA 3470646624,3470646631,DE 3470646632,3470646639,BR -3470646640,3470646663,US -3470646664,3470646671,PL +3470646640,3470646671,US 3470646672,3470646679,BR 3470646680,3470646687,CA 3470646688,3470646703,US @@ -119080,7 +121257,9 @@ 3476722528,3476722543,AU 3476722544,3476722591,US 3476722592,3476722607,GB -3476722608,3476722759,US +3476722608,3476722719,US +3476722720,3476722727,CO +3476722728,3476722759,US 3476722760,3476722767,IN 3476722768,3476722775,US 3476722776,3476722783,GB @@ -119102,7 +121281,17 @@ 3476725400,3476725415,CA 3476725416,3476725423,US 3476725424,3476725431,GB -3476725432,3476732373,US +3476725432,3476731909,US +3476731910,3476731913,IN +3476731914,3476732049,US +3476732050,3476732053,IN +3476732054,3476732073,US +3476732074,3476732077,IN +3476732078,3476732113,US +3476732114,3476732117,IN +3476732118,3476732341,US +3476732342,3476732345,MX +3476732346,3476732373,US 3476732374,3476732377,MX 3476732378,3476733603,US 3476733604,3476733604,MX @@ -119128,7 +121317,9 @@ 3478114304,3478118399,PE 3478118400,3478192127,US 3478192128,3478257663,CA -3478257664,3478294527,US +3478257664,3478261855,US +3478261856,3478261887,SG +3478261888,3478294527,US 3478294528,3478294543,GB 3478294544,3478323391,US 3478323392,3478323399,CA @@ -120199,7 +122390,9 @@ 3491780608,3491781631,EC 3491781632,3491826687,US 3491826688,3491826943,AN -3491826944,3491921663,US +3491826944,3491832575,US +3491832576,3491832583,PR +3491832584,3491921663,US 3491921664,3491921919,PR 3491921920,3491955711,US 3491955712,3491956735,CO @@ -120299,7 +122492,9 @@ 3493901952,3493901983,CA 3493901984,3493902215,US 3493902216,3493902223,CA -3493902224,3493903551,US +3493902224,3493902295,US +3493902296,3493902303,NG +3493902304,3493903551,US 3493903552,3493903567,KW 3493903568,3493914239,US 3493914240,3493914367,CA @@ -120346,7 +122541,9 @@ 3494101408,3494101415,CO 3494101416,3494101429,US 3494101430,3494101437,GB -3494101438,3494102623,US +3494101438,3494102481,US +3494102482,3494102489,CA +3494102490,3494102623,US 3494102624,3494102639,SB 3494102640,3494102687,US 3494102688,3494102701,PE @@ -120472,9 +122669,7 @@ 3494299728,3494299735,SC 3494299736,3494300367,US 3494300368,3494300383,TW -3494300384,3494300927,US -3494300928,3494301055,TW -3494301056,3494301247,US +3494300384,3494301247,US 3494301248,3494301311,SG 3494301312,3494301439,US 3494301440,3494301695,TW @@ -120702,7 +122897,7 @@ 3494744064,3494744399,US 3494744400,3494744407,AU 3494744408,3494744703,US -3494744704,3494744711,DK +3494744704,3494744711,DE 3494744712,3494745151,US 3494745152,3494745159,AU 3494745160,3494745303,US @@ -120823,9 +123018,7 @@ 3495098368,3495100415,CA 3495100416,3495120895,US 3495120896,3495122943,AG -3495122944,3495136455,US -3495136456,3495136463,IN -3495136464,3495136471,US +3495122944,3495136471,US 3495136472,3495136479,AR 3495136480,3495136495,US 3495136496,3495136503,IN @@ -120884,13 +123077,19 @@ 3495235824,3495235831,GB 3495235832,3495235903,US 3495235904,3495235911,CA -3495235912,3495235991,US -3495235992,3495235999,CA -3495236000,3495236015,US -3495236016,3495236023,GB -3495236024,3495236367,US +3495235912,3495235975,US +3495235976,3495235983,VN +3495235984,3495235999,US +3495236000,3495236007,HK +3495236008,3495236015,US +3495236016,3495236031,GB +3495236032,3495236247,US +3495236248,3495236255,AZ +3495236256,3495236367,US 3495236368,3495236375,CA -3495236376,3495251967,US +3495236376,3495236431,US +3495236432,3495236439,IN +3495236440,3495251967,US 3495251968,3495254015,CA 3495254016,3495260159,US 3495260160,3495261183,CA @@ -121032,13 +123231,22 @@ 3495547472,3495547479,GB 3495547480,3495547605,US 3495547606,3495547606,BD -3495547607,3495548205,US +3495547607,3495547633,US +3495547634,3495547635,CO +3495547636,3495548126,US +3495548127,3495548129,NO +3495548130,3495548205,US 3495548206,3495548207,ID -3495548208,3495548544,US +3495548208,3495548437,US +3495548438,3495548438,ES +3495548439,3495548544,US 3495548545,3495548545,BD -3495548546,3495548549,US +3495548546,3495548548,US +3495548549,3495548549,ES 3495548550,3495548550,BD -3495548551,3495548586,US +3495548551,3495548558,US +3495548559,3495548559,ES +3495548560,3495548586,US 3495548587,3495548588,LK 3495548589,3495548635,US 3495548636,3495548637,BD @@ -121072,11 +123280,9 @@ 3495653376,3495654399,CA 3495654400,3495657551,US 3495657552,3495657567,GB -3495657568,3495658015,US -3495658016,3495658023,IN -3495658024,3495658319,US -3495658320,3495658327,IN -3495658328,3495673855,US +3495657568,3495658527,US +3495658528,3495658559,FR +3495658560,3495673855,US 3495673856,3495674623,GP 3495674624,3495674879,MF 3495674880,3495675903,VG @@ -121198,9 +123404,7 @@ 3496886448,3496886463,TR 3496886464,3496886495,US 3496886496,3496886503,CA -3496886504,3496886511,US -3496886512,3496886527,GB -3496886528,3496886607,US +3496886504,3496886607,US 3496886608,3496886623,CA 3496886624,3496886655,US 3496886656,3496886671,IN @@ -121208,9 +123412,7 @@ 3496886712,3496886727,AU 3496886728,3496886823,US 3496886824,3496886831,IN -3496886832,3496886919,US -3496886920,3496886927,PK -3496886928,3496886935,US +3496886832,3496886935,US 3496886936,3496886943,PK 3496886944,3496887135,US 3496887136,3496887167,AU @@ -121367,7 +123569,9 @@ 3497156864,3497156879,NL 3497156880,3497156983,US 3497156984,3497157006,DZ -3497157007,3497160191,US +3497157007,3497157375,US +3497157376,3497158655,A2 +3497158656,3497160191,US 3497160192,3497160351,NL 3497160352,3497161215,US 3497161216,3497161343,HK @@ -121573,17 +123777,21 @@ 3500809992,3500809999,CA 3500810000,3500810247,US 3500810248,3500810255,CA -3500810256,3500921279,US +3500810256,3500812175,US +3500812176,3500812183,GB +3500812184,3500921279,US 3500921280,3500921311,AU 3500921312,3501146951,US 3501146952,3501146959,CA 3501146960,3501146975,GB -3501146976,3501181703,US +3501146976,3501147039,US +3501147040,3501147071,CA +3501147072,3501181703,US 3501181704,3501181711,AU 3501181712,3501181727,KR 3501181728,3501181743,US -3501181744,3501181759,JP -3501181760,3501182975,US +3501181744,3501181791,JP +3501181792,3501182975,US 3501182976,3501183007,SG 3501183008,3501183023,US 3501183024,3501183047,SG @@ -121774,29 +123982,9 @@ 3507101920,3507101935,IL 3507101936,3507290111,US 3507290112,3507355647,AR -3507355648,3507479075,US -3507479076,3507479076,CA -3507479077,3507479079,US -3507479080,3507479080,CA -3507479081,3507479108,US -3507479109,3507479109,CA -3507479110,3507479154,US -3507479155,3507479155,CA -3507479156,3507479184,US -3507479185,3507479185,CA -3507479186,3507481766,US -3507481767,3507481767,CA -3507481768,3507482153,US -3507482154,3507482155,CA -3507482156,3507482197,US -3507482198,3507482198,CA -3507482199,3507482303,US -3507482304,3507482304,CA -3507482305,3507484047,US -3507484048,3507484063,CA -3507484064,3507485103,US -3507485104,3507485119,CA -3507485120,3507540015,US +3507355648,3507470335,US +3507470336,3507486719,CA +3507486720,3507540015,US 3507540016,3507540031,IN 3507540032,3507585023,US 3507585024,3507598911,CA @@ -122586,8 +124774,8 @@ 3509779008,3509779039,IN 3509779040,3509822335,US 3509822336,3509822351,DE -3509822352,3509825791,US -3509825792,3509826303,CN +3509822352,3509826047,US +3509826048,3509826303,CN 3509826304,3509829503,US 3509829504,3509829535,GB 3509829536,3509830287,US @@ -123316,7 +125504,9 @@ 3512269824,3512270847,US 3512270848,3512336383,CA 3512336384,3512369151,US -3512369152,3512385535,CA +3512369152,3512378435,CA +3512378436,3512378436,US +3512378437,3512385535,CA 3512385536,3512397823,US 3512397824,3512399375,CA 3512399376,3512399383,US @@ -123788,11 +125978,11 @@ 3514007552,3514040319,CA 3514040320,3514367999,US 3514368000,3514433535,CA -3514433536,3514583479,US -3514583480,3514583487,PA -3514583488,3514583535,US +3514433536,3514583535,US 3514583536,3514583543,JE -3514583544,3514587511,US +3514583544,3514585359,US +3514585360,3514585375,GB +3514585376,3514587511,US 3514587512,3514587519,PA 3514587520,3514589439,US 3514589440,3514589695,GT @@ -123932,7 +126122,9 @@ 3517100620,3517100635,CA 3517100636,3517100648,US 3517100649,3517100668,CA -3517100669,3517100811,US +3517100669,3517100720,US +3517100721,3517100730,CA +3517100731,3517100811,US 3517100812,3517100829,GB 3517100830,3517101597,US 3517101598,3517101613,GB @@ -124055,8 +126247,8 @@ 3517416712,3517416727,US 3517416728,3517416735,CA 3517416736,3517416743,US -3517416744,3517416775,CA -3517416776,3517416783,US +3517416744,3517416767,CA +3517416768,3517416783,US 3517416784,3517416791,CA 3517416792,3517416799,US 3517416800,3517416823,CA @@ -124377,9 +126569,7 @@ 3518911744,3518911999,GB 3518912000,3518912511,US 3518912512,3518912767,IN -3518912768,3518921447,US -3518921448,3518921455,CN -3518921456,3518929535,US +3518912768,3518929535,US 3518929536,3518929599,CA 3518929600,3518995695,US 3518995696,3518995703,GB @@ -124465,7 +126655,9 @@ 3519412736,3519412751,RU 3519412752,3519412799,US 3519412800,3519412815,RU -3519412816,3519413759,US +3519412816,3519412999,US +3519413000,3519413007,CY +3519413008,3519413759,US 3519413760,3519414271,CA 3519414272,3519417071,US 3519417072,3519417075,PT @@ -124532,9 +126724,7 @@ 3519879768,3519879775,US 3519879776,3519879807,CA 3519879808,3519879815,US -3519879816,3519879863,CA -3519879864,3519879871,US -3519879872,3519880767,CA +3519879816,3519880767,CA 3519880768,3519880831,DE 3519880832,3519881375,CA 3519881376,3519881407,US @@ -125050,7 +127240,9 @@ 3521937261,3521937406,EG 3521937407,3521965055,US 3521965056,3521966079,DE -3521966080,3522029439,US +3521966080,3521989631,US +3521989632,3521989887,A2 +3521989888,3522029439,US 3522029440,3522029503,FI 3522029504,3522029567,CA 3522029568,3522029823,US @@ -125555,10 +127747,12 @@ 3556984640,3556984647,DE 3556984648,3556984651,FR 3556984652,3556984655,DE -3556984656,3556984663,FR -3556984664,3556984671,DE -3556984672,3556984719,FR -3556984720,3556985663,DE +3556984656,3556984719,FR +3556984720,3556985127,DE +3556985128,3556985135,ES +3556985136,3556985207,DE +3556985208,3556985215,ES +3556985216,3556985663,DE 3556985664,3556985671,HU 3556985672,3556990975,DE 3556990976,3556999167,UA @@ -125672,8 +127866,8 @@ 3557336192,3557336255,EU 3557336256,3557336319,BE 3557336320,3557336575,EU -3557336576,3557336663,BE -3557336664,3557336703,EU +3557336576,3557336671,BE +3557336672,3557336703,EU 3557336704,3557336831,BE 3557336832,3557338111,EU 3557338112,3557338367,BE @@ -125693,8 +127887,8 @@ 3557340192,3557340927,BE 3557340928,3557341183,EU 3557341184,3557341439,BE -3557341440,3557341471,EU -3557341472,3557341527,BE +3557341440,3557341455,EU +3557341456,3557341527,BE 3557341528,3557341535,EU 3557341536,3557341551,BE 3557341552,3557341559,EU @@ -125735,8 +127929,8 @@ 3557360560,3557360575,JE 3557360576,3557360680,GB 3557360681,3557360687,JE -3557360688,3557360863,GB -3557360864,3557360895,JE +3557360688,3557360871,GB +3557360872,3557360895,JE 3557360896,3557360927,GB 3557360928,3557360943,JE 3557360944,3557360959,GB @@ -125769,8 +127963,8 @@ 3557363672,3557363679,JE 3557363680,3557364103,GB 3557364104,3557364107,JE -3557364108,3557364135,GB -3557364136,3557364223,JE +3557364108,3557364143,GB +3557364144,3557364223,JE 3557364224,3557364479,GB 3557364480,3557364495,JE 3557364496,3557364527,GB @@ -125901,7 +128095,9 @@ 3557860832,3557860847,FI 3557860848,3557860863,SE 3557860864,3557861119,NO -3557861120,3557867519,SE +3557861120,3557864799,SE +3557864800,3557864831,FI +3557864832,3557867519,SE 3557867520,3557875711,RU 3557875712,3557883903,DE 3557883904,3557892095,RU @@ -125960,7 +128156,9 @@ 3558155048,3558155055,A2 3558155056,3558155059,AF 3558155060,3558155063,DE -3558155064,3558155135,A2 +3558155064,3558155103,A2 +3558155104,3558155119,DE +3558155120,3558155135,A2 3558155136,3558155263,SD 3558155264,3558155391,ET 3558155392,3558155399,A2 @@ -126010,7 +128208,9 @@ 3558158336,3558158847,SE 3558158848,3558159359,DE 3558159360,3558159519,AF -3558159520,3558159871,A2 +3558159520,3558159807,A2 +3558159808,3558159839,DE +3558159840,3558159871,A2 3558159872,3558160127,SL 3558160128,3558160383,DE 3558160384,3558161151,A2 @@ -126043,9 +128243,7 @@ 3558196368,3558196415,IT 3558196416,3558196543,ES 3558196544,3558196607,IT -3558196608,3558196719,ES -3558196720,3558196727,IT -3558196728,3558196735,ES +3558196608,3558196735,ES 3558196736,3558203391,US 3558203392,3558211583,ES 3558211584,3558219775,GB @@ -126084,17 +128282,13 @@ 3558288320,3558288383,CH 3558288384,3558288423,US 3558288424,3558288447,GB -3558288448,3558288471,US -3558288472,3558288479,GB -3558288480,3558288483,US +3558288448,3558288483,US 3558288484,3558288487,GB 3558288488,3558288639,US -3558288640,3558288671,GB +3558288640,3558288671,BE 3558288672,3558288687,DE 3558288688,3558288895,BE -3558288896,3558289087,FR -3558289088,3558289103,GB -3558289104,3558289111,FR +3558288896,3558289111,FR 3558289112,3558289119,GB 3558289120,3558289151,FR 3558289152,3558289407,GB @@ -126493,7 +128687,9 @@ 3559088376,3559088379,GB 3559088380,3559089023,BE 3559089024,3559089027,GB -3559089028,3559089351,BE +3559089028,3559089079,BE +3559089080,3559089087,GB +3559089088,3559089351,BE 3559089352,3559089359,GB 3559089360,3559089407,BE 3559089408,3559089411,GB @@ -126569,7 +128765,9 @@ 3559092160,3559092160,GB 3559092161,3559092222,BE 3559092223,3559092223,GB -3559092224,3559092287,BE +3559092224,3559092271,BE +3559092272,3559092279,GB +3559092280,3559092287,BE 3559092288,3559092303,GB 3559092304,3559092311,BE 3559092312,3559092319,GB @@ -126614,7 +128812,8 @@ 3559093220,3559093239,BE 3559093240,3559093243,GB 3559093244,3559093511,BE -3559093512,3559093567,GB +3559093512,3559093535,GB +3559093536,3559093567,BE 3559093568,3559093599,IT 3559093600,3559093663,BE 3559093664,3559093671,GB @@ -126790,9 +128989,7 @@ 3559490816,3559491071,ES 3559491072,3559491135,NL 3559491136,3559491167,ES -3559491168,3559491327,NL -3559491328,3559491359,ES -3559491360,3559491439,NL +3559491168,3559491439,NL 3559491440,3559491455,ES 3559491456,3559491647,NL 3559491648,3559491711,ES @@ -126883,9 +129080,7 @@ 3559877968,3559882751,LT 3559882752,3559890943,AZ 3559890944,3559899135,CH -3559899136,3559899391,UA -3559899392,3559899395,EE -3559899396,3559899487,UA +3559899136,3559899487,UA 3559899488,3559899519,EE 3559899520,3559899903,UA 3559899904,3559899907,EE @@ -126938,8 +129133,8 @@ 3559902240,3559902431,UA 3559902432,3559902463,EE 3559902464,3559902975,UA -3559902976,3559903295,EE -3559903296,3559903487,UA +3559902976,3559903359,EE +3559903360,3559903487,UA 3559903488,3559903999,EE 3559904000,3559904015,UA 3559904016,3559904023,EE @@ -126966,8 +129161,8 @@ 3559905300,3559905317,EE 3559905318,3559905319,LT 3559905320,3559905323,UA -3559905324,3559905327,EE -3559905328,3559905535,UA +3559905324,3559905331,EE +3559905332,3559905535,UA 3559905536,3559905623,EE 3559905624,3559905631,UA 3559905632,3559905695,EE @@ -127428,8 +129623,7 @@ 3560941124,3560941127,FR 3560941128,3560941131,DE 3560941132,3560941135,GB -3560941136,3560941139,ES -3560941140,3560941147,DE +3560941136,3560941147,DE 3560941148,3560941151,IT 3560941152,3560941155,DK 3560941156,3560941159,ES @@ -129721,8 +131915,9 @@ 3562242048,3562258431,FR 3562258432,3562263975,NL 3562263976,3562263983,BE -3562263984,3562283007,NL -3562283008,3562291199,IT +3562263984,3562274767,NL +3562274768,3562274775,DE +3562274776,3562283007,NL 3562291200,3562307583,GB 3562307584,3562315775,NL 3562315776,3562321231,GB @@ -129915,9 +132110,7 @@ 3563372544,3563380735,SA 3563380736,3563381951,GB 3563381952,3563381959,IT -3563381960,3563382383,GB -3563382384,3563382391,AU -3563382392,3563382495,GB +3563381960,3563382495,GB 3563382496,3563382503,AT 3563382504,3563382583,GB 3563382584,3563382587,AT @@ -130159,10 +132352,14 @@ 3564024104,3564024135,GB 3564024136,3564024143,IT 3564024144,3564027903,GB -3564027904,3564041215,DE +3564027904,3564036351,DE +3564036352,3564039423,A2 +3564039424,3564039679,DE +3564039680,3564041215,A2 3564041216,3564041727,RU -3564041728,3564044031,DE -3564044032,3564044287,GB +3564041728,3564043263,A2 +3564043264,3564043519,DE +3564043520,3564044287,A2 3564044288,3564052479,CZ 3564052480,3564060671,GB 3564060672,3564068863,RU @@ -130191,7 +132388,9 @@ 3564153200,3564153207,NL 3564153208,3564156415,SE 3564156416,3564156419,NO -3564156420,3564156919,SE +3564156420,3564156815,SE +3564156816,3564156819,FI +3564156820,3564156919,SE 3564156920,3564156927,FI 3564156928,3564157207,SE 3564157208,3564157215,NO @@ -130637,8 +132836,8 @@ 3564881232,3564881247,NL 3564881248,3564881343,GB 3564881344,3564881359,NL -3564881360,3564881375,GB -3564881376,3564881439,NL +3564881360,3564881391,GB +3564881392,3564881439,NL 3564881440,3564881455,GB 3564881456,3564881463,NL 3564881464,3564881471,GB @@ -130837,8 +133036,8 @@ 3564896256,3564904447,RU 3564904448,3564912639,DE 3564912640,3564920831,BG -3564920832,3564922879,ES -3564922880,3564929023,US +3564920832,3564921855,ES +3564921856,3564929023,US 3564929024,3564937215,AT 3564937216,3564945407,RS 3564945408,3564947175,GB @@ -131057,7 +133256,9 @@ 3565037568,3565037823,IE 3565037824,3565038591,GB 3565038592,3565038663,IE -3565038664,3565039615,GB +3565038664,3565038687,GB +3565038688,3565038719,IE +3565038720,3565039615,GB 3565039616,3565042175,IE 3565042176,3565043711,GB 3565043712,3565047807,AT @@ -132839,15 +135040,7 @@ 3572826112,3572891647,IT 3572891648,3572957175,FI 3572957176,3572957183,AX -3572957184,3572975359,SE -3572975360,3572975615,A2 -3572975616,3572980991,SE -3572980992,3572981247,A2 -3572981248,3572984319,SE -3572984320,3572984575,A2 -3572984576,3572986367,SE -3572986368,3572986623,A2 -3572986624,3573022719,SE +3572957184,3573022719,SE 3573022720,3573055487,RU 3573055488,3573088255,GB 3573088256,3573088263,CH @@ -133914,14 +136107,14 @@ 3576131584,3576135679,CH 3576135680,3576168447,DE 3576168448,3576233983,GB -3576233984,3576236671,FR -3576236672,3576236719,GB +3576233984,3576236687,FR +3576236688,3576236719,GB 3576236720,3576236743,FR 3576236744,3576236751,GB 3576236752,3576236775,FR 3576236776,3576236783,GB -3576236784,3576236879,FR -3576236880,3576236927,GB +3576236784,3576236887,FR +3576236888,3576236927,GB 3576236928,3576237063,FR 3576237064,3576237071,GB 3576237072,3576237087,FR @@ -133948,9 +136141,7 @@ 3576238512,3576238527,GB 3576238528,3576238559,FR 3576238560,3576238575,GB -3576238576,3576238615,FR -3576238616,3576238623,GB -3576238624,3576238639,FR +3576238576,3576238639,FR 3576238640,3576238655,GB 3576238656,3576238863,FR 3576238864,3576238879,GB @@ -134003,9 +136194,7 @@ 3576242320,3576242327,GB 3576242328,3576242335,FR 3576242336,3576242343,GB -3576242344,3576243967,FR -3576243968,3576243983,GB -3576243984,3576244103,FR +3576242344,3576244103,FR 3576244104,3576244111,GB 3576244112,3576244127,FR 3576244128,3576244143,GB @@ -134065,7 +136254,9 @@ 3576255408,3576255423,GB 3576255424,3576255431,FR 3576255432,3576255439,GB -3576255440,3576255519,FR +3576255440,3576255471,FR +3576255472,3576255479,GB +3576255480,3576255519,FR 3576255520,3576255527,GB 3576255528,3576255543,FR 3576255544,3576255551,GB @@ -134105,9 +136296,7 @@ 3576256896,3576256959,GB 3576256960,3576256991,FR 3576256992,3576257007,GB -3576257008,3576257103,FR -3576257104,3576257111,GB -3576257112,3576257135,FR +3576257008,3576257135,FR 3576257136,3576257151,GB 3576257152,3576257159,FR 3576257160,3576257167,GB @@ -134120,9 +136309,7 @@ 3576257376,3576257455,FR 3576257456,3576257471,GB 3576257472,3576257487,FR -3576257488,3576257495,GB -3576257496,3576257503,FR -3576257504,3576257535,GB +3576257488,3576257535,GB 3576257536,3576257551,FR 3576257552,3576257583,GB 3576257584,3576257631,FR @@ -134137,10 +136324,8 @@ 3576257888,3576257903,GB 3576257904,3576257975,FR 3576257976,3576258015,GB -3576258016,3576258055,FR -3576258056,3576258063,GB -3576258064,3576258079,FR -3576258080,3576258095,GB +3576258016,3576258087,FR +3576258088,3576258095,GB 3576258096,3576258167,FR 3576258168,3576258175,GB 3576258176,3576258351,FR @@ -134248,8 +136433,8 @@ 3576263744,3576263751,FR 3576263752,3576263759,GB 3576263760,3576263791,FR -3576263792,3576263887,GB -3576263888,3576263911,FR +3576263792,3576263903,GB +3576263904,3576263911,FR 3576263912,3576263919,GB 3576263920,3576264295,FR 3576264296,3576264319,GB @@ -134445,8 +136630,8 @@ 3577625208,3577625215,GB 3577625216,3577625231,EU 3577625232,3577625599,GB -3577625600,3577625823,EU -3577625824,3577626623,GB +3577625600,3577625791,EU +3577625792,3577626623,GB 3577626624,3577627135,FR 3577627136,3577627391,EU 3577627392,3577627647,GB @@ -134487,17 +136672,11 @@ 3577640720,3577640735,EU 3577640736,3577641151,FR 3577641152,3577641159,EU -3577641160,3577641199,FR -3577641200,3577641215,EU -3577641216,3577641391,FR +3577641160,3577641391,FR 3577641392,3577641399,EU -3577641400,3577641423,FR -3577641424,3577641983,EU -3577641984,3577642023,GB -3577642024,3577642031,EU -3577642032,3577642111,GB -3577642112,3577642175,EU -3577642176,3577642239,GB +3577641400,3577641439,FR +3577641440,3577641983,EU +3577641984,3577642239,GB 3577642240,3577642495,EU 3577642496,3577642623,FR 3577642624,3577642751,EU @@ -134903,11 +137082,11 @@ 3580200960,3580201983,LT 3580201984,3580203519,SE 3580203520,3580204543,RU -3580204544,3580205055,SE +3580204544,3580205055,NL 3580205056,3580207103,HR 3580207104,3580208127,SE -3580208128,3580208639,EE -3580208640,3580213247,SE +3580208128,3580209151,EE +3580209152,3580213247,SE 3580213248,3580214271,CH 3580214272,3580214783,LV 3580214784,3580223487,SE @@ -135076,7 +137255,11 @@ 3582050304,3582058495,NL 3582058496,3582066687,AT 3582066688,3582074879,UA -3582074880,3582078631,GB +3582074880,3582076863,GB +3582076864,3582076895,DE +3582076896,3582077439,GB +3582077440,3582077471,DE +3582077472,3582078631,GB 3582078632,3582078639,DE 3582078640,3582081023,GB 3582081024,3582081535,ES @@ -135103,23 +137286,15 @@ 3582156800,3582164991,GB 3582164992,3582173183,SE 3582173184,3582181375,GB -3582181376,3582190847,DE -3582190848,3582190879,CH -3582190880,3582190927,DE +3582181376,3582190927,DE 3582190928,3582190931,FR 3582190932,3582191023,DE 3582191024,3582191031,BE 3582191032,3582192127,DE 3582192128,3582192143,NL -3582192144,3582192287,DE -3582192288,3582192303,CH -3582192304,3582194775,DE +3582192144,3582194775,DE 3582194776,3582194783,CY -3582194784,3582194863,DE -3582194864,3582194879,CH -3582194880,3582195135,DE -3582195136,3582195143,CH -3582195144,3582196183,DE +3582194784,3582196183,DE 3582196184,3582196191,BE 3582196192,3582197127,DE 3582197128,3582197135,BZ @@ -135137,7 +137312,9 @@ 3582223968,3582223975,NO 3582223976,3582224375,SE 3582224376,3582224379,FI -3582224380,3582226599,SE +3582224380,3582225719,SE +3582225720,3582225727,FI +3582225728,3582226599,SE 3582226600,3582226607,FI 3582226608,3582230527,SE 3582230528,3582238719,BE @@ -135380,9 +137557,7 @@ 3582566752,3582566767,BE 3582566768,3582566783,EU 3582566784,3582566847,BE -3582566848,3582566863,EU -3582566864,3582566879,BE -3582566880,3582566911,EU +3582566848,3582566911,EU 3582566912,3582567019,BE 3582567020,3582567023,EU 3582567024,3582567039,BE @@ -135426,8 +137601,7 @@ 3582569472,3582569535,FR 3582569536,3582569983,EU 3582569984,3582570239,FR -3582570240,3582570367,DE -3582570368,3582570399,EU +3582570240,3582570399,GB 3582570400,3582570431,FR 3582570432,3582570463,EU 3582570464,3582570471,FR @@ -135748,8 +137922,7 @@ 3583705848,3583705855,NA 3583705856,3583705859,UA 3583705860,3583705863,NA -3583705864,3583705903,UA -3583705904,3583705911,NA +3583705864,3583705911,UA 3583705912,3583705919,RU 3583705920,3583706023,UA 3583706024,3583706031,NA @@ -135853,9 +138026,7 @@ 3583709728,3583709743,NA 3583709744,3583709759,UA 3583709760,3583709767,NA -3583709768,3583709791,UA -3583709792,3583709799,NA -3583709800,3583709839,UA +3583709768,3583709839,UA 3583709840,3583709863,NA 3583709864,3583709871,RU 3583709872,3583709879,NA @@ -135892,9 +138063,7 @@ 3583710856,3583710863,NA 3583710864,3583710887,UA 3583710888,3583710895,NA -3583710896,3583710991,UA -3583710992,3583710999,NA -3583711000,3583711007,UA +3583710896,3583711007,UA 3583711008,3583711015,RU 3583711016,3583711023,NA 3583711024,3583711247,UA @@ -136267,9 +138436,7 @@ 3584958464,3584966655,DE 3584966656,3584974847,DK 3584974848,3584983039,FR -3584983040,3584988255,US -3584988256,3584988287,UA -3584988288,3584988575,US +3584983040,3584988575,US 3584988576,3584988591,UA 3584988592,3584988623,US 3584988624,3584988639,UA @@ -136685,7 +138852,8 @@ 3586478592,3586478847,HU 3586478848,3586479103,SK 3586479104,3586479359,TR -3586479360,3586490367,HU +3586479360,3586479615,SK +3586479616,3586490367,HU 3586490368,3586506751,LT 3586506752,3586523135,NL 3586523136,3586542559,DE @@ -136734,7 +138902,9 @@ 3586678688,3586678783,GB 3586678784,3586679039,IT 3586679040,3586679103,FR -3586679104,3586679167,DE +3586679104,3586679143,DE +3586679144,3586679151,FR +3586679152,3586679167,DE 3586679168,3586679327,FR 3586679328,3586679343,DK 3586679344,3586679359,FR @@ -136758,9 +138928,7 @@ 3586680768,3586680831,ES 3586680832,3586681087,FR 3586681088,3586681343,IT -3586681344,3586682111,FR -3586682112,3586682175,US -3586682176,3586682239,FR +3586681344,3586682239,FR 3586682240,3586682367,US 3586682368,3586682399,AT 3586682400,3586682879,FR @@ -136783,40 +138951,13 @@ 3586883584,3586899967,IT 3586899968,3586900287,DE 3586900288,3586900351,NL -3586900352,3586902271,DE -3586902272,3586902335,CH -3586902336,3586902411,DE -3586902412,3586902415,CH -3586902416,3586903263,DE -3586903264,3586903295,CH -3586903296,3586904223,DE -3586904224,3586904255,CH -3586904256,3586904319,DE -3586904320,3586904415,CH -3586904416,3586904831,DE +3586900352,3586904831,DE 3586904832,3586904839,VG -3586904840,3586905039,DE -3586905040,3586905055,CH -3586905056,3586905071,DE -3586905072,3586905079,CH -3586905080,3586905087,DE -3586905088,3586905119,CH -3586905120,3586905167,DE -3586905168,3586905199,CH +3586904840,3586905199,DE 3586905200,3586905215,GB -3586905216,3586905247,DE -3586905248,3586905279,CH -3586905280,3586905287,DE +3586905216,3586905287,DE 3586905288,3586905295,CY -3586905296,3586906391,DE -3586906392,3586906399,CH -3586906400,3586906423,DE -3586906424,3586906427,CH -3586906428,3586906719,DE -3586906720,3586906735,CH -3586906736,3586907903,DE -3586907904,3586908031,CH -3586908032,3586909695,DE +3586905296,3586909695,DE 3586909696,3586909823,CH 3586909824,3586910559,DE 3586910560,3586910567,NL @@ -136930,11 +139071,14 @@ 3587179456,3587179463,AT 3587179464,3587179471,CH 3587179472,3587186687,AT -3587186688,3587190783,DE -3587190784,3587191039,GB -3587191040,3587194495,DE +3587186688,3587186815,DE +3587186816,3587187199,A2 +3587187200,3587187455,DE +3587187456,3587188479,A2 +3587188480,3587188735,DE +3587188736,3587194495,A2 3587194496,3587194511,RU -3587194512,3587194879,DE +3587194512,3587194879,A2 3587194880,3587211263,GB 3587211264,3587211531,AT 3587211532,3587211535,DE @@ -136942,7 +139086,9 @@ 3587213912,3587213919,UY 3587213920,3587219455,AT 3587219456,3587227647,RU -3587227648,3587227759,NL +3587227648,3587227663,NL +3587227664,3587227679,GB +3587227680,3587227759,NL 3587227760,3587227775,GB 3587227776,3587227903,NL 3587227904,3587227967,GB @@ -137055,11 +139201,13 @@ 3587238608,3587238911,GB 3587238912,3587239303,NL 3587239304,3587239311,GB -3587239312,3587239903,NL -3587239904,3587239935,GB -3587239936,3587239975,NL +3587239312,3587239911,NL +3587239912,3587239919,GB +3587239920,3587239975,NL 3587239976,3587239983,GB -3587239984,3587240087,NL +3587239984,3587240063,NL +3587240064,3587240071,GB +3587240072,3587240087,NL 3587240088,3587240095,GB 3587240096,3587240103,NL 3587240104,3587240107,GB @@ -137073,7 +139221,9 @@ 3587240512,3587240575,GB 3587240576,3587240615,NL 3587240616,3587240623,GB -3587240624,3587241143,NL +3587240624,3587241071,NL +3587241072,3587241087,GB +3587241088,3587241143,NL 3587241144,3587241151,GB 3587241152,3587241223,NL 3587241224,3587241247,GB @@ -137347,7 +139497,9 @@ 3588588568,3588588575,IT 3588588576,3588590175,ES 3588590176,3588590207,BE -3588590208,3588598607,ES +3588590208,3588590591,ES +3588590592,3588590847,FR +3588590848,3588598607,ES 3588598608,3588598615,IT 3588598616,3588603903,ES 3588603904,3588620287,SI @@ -137370,7 +139522,9 @@ 3588782272,3588782279,A2 3588782280,3588784127,GB 3588784128,3588800511,CH -3588800512,3588816895,RU +3588800512,3588802687,RU +3588802688,3588802815,CH +3588802816,3588816895,RU 3588816896,3588833279,IT 3588833280,3588848767,RO 3588848768,3588848775,FR @@ -137870,7 +140024,9 @@ 3590157856,3590157951,RS 3590157952,3590158079,SI 3590158080,3590158343,RS -3590158344,3590158407,SI +3590158344,3590158359,SI +3590158360,3590158367,RS +3590158368,3590158407,SI 3590158408,3590158415,RS 3590158416,3590158431,SI 3590158432,3590158439,RS @@ -137899,10 +140055,7 @@ 3590245312,3590245439,US 3590245440,3590245503,FR 3590245504,3590245567,GB -3590245568,3590245631,US -3590245632,3590245887,FR -3590245888,3590245983,US -3590245984,3590246175,FR +3590245568,3590246175,FR 3590246176,3590246207,AU 3590246208,3590246271,FR 3590246272,3590246287,DE @@ -138016,16 +140169,18 @@ 3590308392,3590308399,A2 3590308400,3590308407,IQ 3590308408,3590308415,A2 -3590308416,3590308455,IQ +3590308416,3590308431,IQ +3590308432,3590308439,A2 +3590308440,3590308455,IQ 3590308456,3590308463,A2 3590308464,3590308471,IQ 3590308472,3590308479,A2 3590308480,3590308487,IQ -3590308488,3590308503,A2 -3590308504,3590308511,IQ -3590308512,3590308519,A2 +3590308488,3590308519,A2 3590308520,3590308527,IQ -3590308528,3590308551,A2 +3590308528,3590308535,A2 +3590308536,3590308543,IQ +3590308544,3590308551,A2 3590308552,3590308559,IQ 3590308560,3590308567,A2 3590308568,3590308583,IQ @@ -138071,8 +140226,8 @@ 3590309712,3590309719,IQ 3590309720,3590309727,A2 3590309728,3590309759,IQ -3590309760,3590309767,A2 -3590309768,3590309791,IQ +3590309760,3590309775,A2 +3590309776,3590309791,IQ 3590309792,3590309799,A2 3590309800,3590309807,IQ 3590309808,3590309815,A2 @@ -138087,8 +140242,7 @@ 3590310184,3590310215,IQ 3590310216,3590310223,A2 3590310224,3590310255,IQ -3590310256,3590310263,A2 -3590310264,3590310271,SD +3590310256,3590310271,A2 3590310272,3590310279,IQ 3590310280,3590310287,A2 3590310288,3590310303,IQ @@ -138099,8 +140253,8 @@ 3590310336,3590310343,IQ 3590310344,3590310351,A2 3590310352,3590310367,IQ -3590310368,3590310383,A2 -3590310384,3590310391,IQ +3590310368,3590310375,A2 +3590310376,3590310391,IQ 3590310392,3590310655,A2 3590310656,3590310911,GB 3590310912,3590310919,IQ @@ -138379,7 +140533,9 @@ 3624376656,3624376679,GB 3624376680,3624377319,US 3624377320,3624377323,GB -3624377324,3624377863,US +3624377324,3624377599,US +3624377600,3624377855,A2 +3624377856,3624377863,US 3624377864,3624377871,GB 3624377872,3624377879,US 3624377880,3624377887,GB @@ -138421,9 +140577,7 @@ 3624380936,3624380943,SA 3624380944,3624380967,GB 3624380968,3624380983,TW -3624380984,3624381471,US -3624381472,3624381487,AU -3624381488,3624381567,US +3624380984,3624381567,US 3624381568,3624381583,MY 3624381584,3624381631,US 3624381632,3624381647,GB @@ -138516,8 +140670,8 @@ 3624549080,3624549087,A2 3624549088,3624549103,US 3624549104,3624549111,A2 -3624549112,3624549375,US -3624549376,3624550143,A2 +3624549112,3624549383,US +3624549384,3624550143,A2 3624550144,3624587263,US 3624587264,3624591359,JM 3624595456,3624730623,US @@ -138528,7 +140682,9 @@ 3624820736,3624820799,CY 3624820800,3624821695,US 3624821696,3624821703,GB -3624821704,3624825097,US +3624821704,3624822783,US +3624822784,3624823039,SG +3624823040,3624825097,US 3624825098,3624825102,BR 3624825103,3624827296,US 3624827297,3624827299,RS @@ -139362,7 +141518,8 @@ 3626385098,3626385101,IN 3626385102,3626385113,US 3626385114,3626385117,JP -3626385118,3626385125,US +3626385118,3626385121,US +3626385122,3626385125,IN 3626385126,3626385129,ID 3626385130,3626385133,GR 3626385134,3626385137,CA @@ -139605,7 +141762,9 @@ 3627524988,3627532287,US 3627532288,3627544575,CA 3627544576,3627659263,US -3627659264,3627663359,CA +3627659264,3627661951,CA +3627661952,3627662015,US +3627662016,3627663359,CA 3627663360,3627665407,US 3627665408,3627665439,CA 3627665440,3627666255,US @@ -139623,13 +141782,13 @@ 3627745376,3627745439,US 3627745440,3627745471,IN 3627745472,3627745503,CA -3627745504,3627745919,US -3627745920,3627745983,IL -3627745984,3627746399,US +3627745504,3627746399,US 3627746400,3627746431,CA 3627746432,3627747159,US 3627747160,3627747167,IN -3627747168,3627753471,US +3627747168,3627747583,US +3627747584,3627747615,FR +3627747616,3627753471,US 3627753472,3627753727,AR 3627753728,3627755007,US 3627755008,3627755135,IE @@ -139732,8 +141891,7 @@ 3628179456,3628187647,CA 3628187648,3628208127,US 3628208128,3628208383,IT -3628208384,3628208639,CN -3628208640,3628223983,US +3628208384,3628223983,US 3628223984,3628223999,CA 3628224000,3628224735,US 3628224736,3628224743,IT @@ -140490,7 +142648,9 @@ 3631333376,3631333679,CA 3631333680,3631333695,US 3631333696,3631341567,CA -3631341568,3631435007,US +3631341568,3631415295,US +3631415296,3631419391,A2 +3631419392,3631435007,US 3631435008,3631435263,GB 3631435264,3631480831,US 3631482880,3631484927,CA @@ -140720,7 +142880,7 @@ 3632484384,3632484391,GB 3632484392,3632484623,US 3632484624,3632484639,GB -3632484640,3632484647,CA +3632484640,3632484647,SG 3632484648,3632484655,JP 3632484656,3632484687,US 3632484688,3632484695,GI @@ -141367,7 +143527,9 @@ 3635533536,3635533551,IN 3635533552,3635658751,US 3635658752,3635660799,CN -3635660800,3635847791,US +3635660800,3635661823,HK +3635661824,3635662847,JP +3635662848,3635847791,US 3635847792,3635847807,CA 3635847808,3635856511,US 3635856512,3635856543,CA @@ -141513,11 +143675,7 @@ 3636266880,3636266911,HK 3636266912,3636284415,US 3636284416,3636284671,FR -3636284672,3636290815,US -3636290816,3636291327,FR -3636291328,3636296959,US -3636296960,3636297727,FR -3636297728,3636396031,US +3636284672,3636396031,US 3636396032,3636461567,CA 3636461568,3636577647,US 3636577648,3636577663,CA @@ -142121,7 +144279,9 @@ 3640028336,3640028343,CA 3640028344,3640028447,US 3640028448,3640028455,GB -3640028456,3640028591,US +3640028456,3640028519,US +3640028520,3640028527,BR +3640028528,3640028591,US 3640028592,3640028599,CA 3640028600,3640057855,US 3640057856,3640066047,CA @@ -142216,7 +144376,9 @@ 3640450048,3640451071,US 3640451072,3640459263,A2 3640459264,3640557567,US -3640557568,3640560511,CA +3640557568,3640559567,CA +3640559568,3640559575,US +3640559576,3640560511,CA 3640560512,3640560527,US 3640560528,3640564455,CA 3640564456,3640564463,US @@ -142325,9 +144487,7 @@ 3641354328,3641354335,GB 3641354336,3641354339,A2 3641354340,3641354367,GB -3641354368,3641354383,A2 -3641354384,3641354479,IT -3641354480,3641354495,A2 +3641354368,3641354495,A2 3641354496,3641354751,GB 3641354752,3641355263,NG 3641355264,3641355519,AO @@ -142539,8 +144699,10 @@ 3641956864,3641957631,GB 3641957632,3641957887,MD 3641957888,3641958399,GB -3641958400,3641960699,BE -3641960700,3641960703,NL +3641958400,3641960447,BE +3641960448,3641960519,NL +3641960520,3641960527,BE +3641960528,3641960703,NL 3641960704,3641961727,BE 3641961728,3641961743,NL 3641961744,3641961791,BE @@ -142590,10 +144752,11 @@ 3642064896,3642068991,SE 3642068992,3642073087,AL 3642073088,3642077183,LV -3642077184,3642081271,BE +3642077184,3642078999,BE +3642079000,3642079007,NL +3642079008,3642081271,BE 3642081272,3642081278,US -3642081279,3642081279,BE -3642081280,3642085375,NL +3642081279,3642085375,NL 3642085376,3642089471,RU 3642089472,3642093567,SE 3642093568,3642097663,NL @@ -142704,10 +144867,8 @@ 3642253312,3642257407,FI 3642257408,3642261503,RU 3642261504,3642265599,BA -3642265600,3642266111,AE -3642266112,3642266367,IR -3642266368,3642266623,AE -3642266624,3642269695,IR +3642265600,3642265855,AE +3642265856,3642269695,IR 3642269696,3642273791,UA 3642273792,3642277887,RU 3642277888,3642290175,DE @@ -142750,7 +144911,6 @@ 3642415636,3642415651,GB 3642415652,3642415655,MT 3642415656,3642417151,GB -3642417152,3642421247,IT 3642421248,3642423091,A2 3642423092,3642423099,NG 3642423100,3642424151,A2 @@ -142820,9 +144980,7 @@ 3642552848,3642553095,UA 3642553096,3642553099,LV 3642553100,3642553103,UA -3642553104,3642553139,LV -3642553140,3642553143,UA -3642553144,3642553161,LV +3642553104,3642553161,LV 3642553162,3642553163,UA 3642553164,3642553175,LV 3642553176,3642553183,UA @@ -142928,7 +145086,8 @@ 3642555496,3642555503,PL 3642555504,3642555647,UA 3642555648,3642555683,SE -3642555684,3642555691,UA +3642555684,3642555685,GB +3642555686,3642555691,UA 3642555692,3642555695,SE 3642555696,3642555703,UA 3642555704,3642555707,FI @@ -143219,7 +145378,7 @@ 3645435904,3645439999,GB 3645440000,3645444095,SE 3645444096,3645448191,SK -3645448192,3645456383,DE +3645448192,3645452287,DE 3645456384,3645460479,GB 3645460480,3645464575,UA 3645464576,3645468671,SE @@ -143270,7 +145429,9 @@ 3645594712,3645594719,SR 3645594720,3645594743,SK 3645594744,3645594751,SR -3645594752,3645595647,SK +3645594752,3645594863,SK +3645594864,3645594871,SR +3645594872,3645595647,SK 3645595648,3645597751,SE 3645597752,3645597759,GB 3645597760,3645601471,SE @@ -143849,8 +146010,8 @@ 3645764262,3645764262,BE 3645764263,3645764264,IT 3645764265,3645764265,TR -3645764266,3645764268,DE -3645764269,3645764270,ES +3645764266,3645764269,DE +3645764270,3645764270,ES 3645764271,3645764271,IT 3645764272,3645764272,DE 3645764273,3645764273,IT @@ -144331,9 +146492,7 @@ 3647965296,3647965303,DE 3647965304,3647965311,ES 3647965312,3647965319,DE -3647965320,3647965359,ES -3647965360,3647965375,DE -3647965376,3647965407,ES +3647965320,3647965407,ES 3647965408,3647965439,DE 3647965440,3647965695,ES 3647965696,3647966207,CH @@ -144352,15 +146511,17 @@ 3647972200,3647972259,GB 3647972260,3647972263,DE 3647972264,3647972351,GB -3647972352,3647973623,IT -3647973624,3647973631,DE -3647973632,3647973679,IT -3647973680,3647973711,DE +3647972352,3647973679,IT +3647973680,3647973695,DE +3647973696,3647973703,IT +3647973704,3647973711,DE 3647973712,3647973735,IT 3647973736,3647973743,DE 3647973744,3647973783,IT 3647973784,3647973791,DE -3647973792,3647973967,IT +3647973792,3647973815,IT +3647973816,3647973823,DE +3647973824,3647973967,IT 3647973968,3647973975,DE 3647973976,3647974047,IT 3647974048,3647974055,DE @@ -144394,8 +146555,8 @@ 3647978776,3647978783,DE 3647978784,3647978895,NL 3647978896,3647978911,DE -3647978912,3647978951,NL -3647978952,3647979007,DE +3647978912,3647978943,NL +3647978944,3647979007,DE 3647979008,3647979136,IT 3647979137,3647979519,DE 3647979520,3647980215,FR @@ -144415,7 +146576,9 @@ 3647982592,3647983615,IT 3647983616,3647984639,NL 3647984640,3647985151,DK -3647985152,3647985663,BE +3647985152,3647985415,BE +3647985416,3647985423,AT +3647985424,3647985663,BE 3647985664,3647985919,ES 3647985920,3647985935,BE 3647985936,3647986431,ES @@ -144423,14 +146586,19 @@ 3647986688,3647986943,DE 3647986944,3647986951,ES 3647986952,3647986975,DE -3647986976,3647986999,ES -3647987000,3647987455,DE +3647986976,3647987031,ES +3647987032,3647987039,DE +3647987040,3647987055,ES +3647987056,3647987455,DE 3647987456,3647987527,ES 3647987528,3647987543,DE 3647987544,3647987711,ES 3647987712,3647988735,IT -3647988736,3647989759,BE -3647989760,3647995903,DE +3647988736,3647988991,DE +3647988992,3647989063,BE +3647989064,3647989071,DE +3647989072,3647989087,BE +3647989088,3647995903,DE 3647995904,3648004223,RU 3648004224,3648004607,GB 3648004608,3648006271,RU @@ -144503,9 +146671,7 @@ 3648086016,3648090111,AT 3648090112,3648094207,RU 3648094208,3648102399,PL -3648102400,3648104767,GB -3648104768,3648104783,IE -3648104784,3648104791,GB +3648102400,3648104791,GB 3648104792,3648104799,IE 3648104800,3648106495,GB 3648106496,3648110591,DE @@ -144575,8 +146741,7 @@ 3648182824,3648182831,RU 3648182832,3648182847,DE 3648182848,3648182879,AT -3648182880,3648182911,SG -3648182912,3648183551,DE +3648182880,3648183551,DE 3648183552,3648183679,BR 3648183680,3648183871,DE 3648183872,3648183935,GB @@ -144635,7 +146800,9 @@ 3648356352,3648360447,PL 3648360448,3648362251,FR 3648362252,3648362255,GB -3648362256,3648364543,FR +3648362256,3648362263,FR +3648362264,3648362271,GB +3648362272,3648364543,FR 3648364544,3648368639,CH 3648368640,3648372735,RU 3648372736,3648376831,LU @@ -144760,7 +146927,6 @@ 3650093056,3650097151,JO 3650097152,3650101247,SK 3650101248,3650105343,DE -3650105344,3650109439,CH 3650109440,3650113535,NO 3650113536,3650117631,GB 3650117632,3650121727,RU @@ -144793,7 +146959,9 @@ 3650228224,3650228735,US 3650228736,3650228991,A2 3650228992,3650232319,US -3650232320,3650236415,RU +3650232320,3650233343,RU +3650233344,3650233599,CY +3650233600,3650236415,RU 3650236416,3650240511,GB 3650240512,3650244607,EE 3650244608,3650256895,GB @@ -145061,7 +147229,8 @@ 3651204224,3651204351,DE 3651204352,3651204607,PL 3651204608,3651205119,ES -3651205120,3651207167,DE +3651205120,3651205375,GB +3651205376,3651207167,DE 3651207168,3651207199,GB 3651207200,3651207223,EU 3651207224,3651207295,GB @@ -145378,7 +147547,9 @@ 3652050536,3652050567,IE 3652050568,3652050615,GB 3652050616,3652050619,IE -3652050620,3652050671,GB +3652050620,3652050627,GB +3652050628,3652050631,IE +3652050632,3652050671,GB 3652050672,3652050943,IE 3652050944,3652055039,LI 3652055040,3652059135,NO @@ -145712,7 +147883,9 @@ 3653664768,3653664895,DE 3653664896,3653665023,NL 3653665024,3653665071,DE -3653665072,3653668863,NL +3653665072,3653666815,NL +3653666816,3653667327,DE +3653667328,3653668863,NL 3653668864,3653672959,SE 3653672960,3653681151,RU 3653681152,3653685247,ES @@ -145773,7 +147946,9 @@ 3654608128,3654608383,SE 3654608384,3654608895,PL 3654608896,3654609919,NO -3654609920,3654613007,SE +3654609920,3654610431,SE +3654610432,3654610943,FR +3654610944,3654613007,SE 3654613008,3654613015,RU 3654613016,3654613055,SE 3654613056,3654613071,RU @@ -145798,8 +147973,7 @@ 3656234000,3656234007,NL 3656234008,3656236527,DE 3656236528,3656236535,GB -3656236536,3656236543,US -3656236544,3656633487,DE +3656236536,3656633487,DE 3656633488,3656633495,GB 3656633496,3656633503,US 3656633504,3656650583,DE diff --git a/src/or/Makefile.am b/src/or/Makefile.am index a9ac3cdee..a12d56b73 100644 --- a/src/or/Makefile.am +++ b/src/or/Makefile.am @@ -15,16 +15,45 @@ 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 \ + 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 +69,54 @@ 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 \ + 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 diff --git a/src/or/buffers.c b/src/or/buffers.c index db926955b..73127490c 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,6 +551,7 @@ buf_free(buf_t *buf) { if (!buf) return; + buf_clear(buf); buf->magic = 0xdeadbeef; tor_free(buf); @@ -578,38 +583,18 @@ 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, * and the number of bytes read otherwise. */ static INLINE int -read_to_chunk(buf_t *buf, chunk_t *chunk, int fd, size_t at_most, +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 +613,6 @@ read_to_chunk(buf_t *buf, chunk_t *chunk, int 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); @@ -668,7 +645,7 @@ read_to_chunk_tls(buf_t *buf, chunk_t *chunk, tor_tls_t *tls, */ /* XXXX023 indicate "read blocked" somehow? */ int -read_to_buf(int s, size_t at_most, buf_t *buf, int *reached_eof, +read_to_buf(tor_socket_t s, size_t at_most, buf_t *buf, int *reached_eof, int *socket_error) { /* XXXX023 It's stupid to overload the return values for these functions: @@ -767,29 +744,14 @@ read_to_buf_tls(tor_tls_t *tls, size_t at_most, buf_t *buf) * written on success, 0 on blocking, -1 on failure. */ static INLINE int -flush_chunk(int s, buf_t *buf, chunk_t *chunk, size_t sz, +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); @@ -854,7 +816,7 @@ flush_chunk_tls(tor_tls_t *tls, buf_t *buf, chunk_t *chunk, * -1 on failure. Return 0 if write() would block. */ int -flush_buf(int s, buf_t *buf, size_t sz, size_t *buf_flushlen) +flush_buf(tor_socket_t s, buf_t *buf, size_t sz, size_t *buf_flushlen) { /* XXXX023 It's stupid to overload the return values for these functions: * "error status" and "number of bytes flushed" are not mutually exclusive. @@ -1056,6 +1018,103 @@ 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</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</b>. + */ +static ssize_t +inspect_evbuffer(struct evbuffer *buf, char **data, 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 = v.iov_base; + *free_out = 0; + return v.iov_len; + } else { + struct evbuffer_iovec *vecs = + tor_malloc(sizeof(struct evbuffer_iovec)*n_vecs); + size_t copied = 0; + i = evbuffer_peek(buf, n, NULL, vecs, n_vecs); + tor_assert(i == n_vecs); + *data = tor_malloc(n); + for (i=0; i < n_vecs; ++i) { + size_t copy = n - copied; + if (copy > vecs[i].iov_len) + copy = vecs[i].iov_len; + tor_assert(copied+copy <= n); + memcpy(data+copied, vecs[i].iov_base, copy); + copied += copy; + } + *free_out = 1; + 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 +1122,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 +1357,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 +1459,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; @@ -1369,6 +1515,128 @@ 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 && + buf->datalen > buf->head->datalen && + want_length < buf->head->datalen); + + 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; + want_length = evbuffer_get_contiguous_space(buf); + n_drain = 0; + i = evbuffer_peek(buf, want_length, NULL, &v, 1); + tor_assert(i == 1); + data = v.iov_base; + datalen = v.iov_len; + + 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. */ + while (evbuffer_get_length(buf) > datalen) { + int free_data = 0; + n_drain = 0; + data = NULL; + datalen = inspect_evbuffer(buf, &data, want_length, &free_data, NULL); + + 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) /* If res is nonzero, parse_socks() made up its mind. */ + return res; + + /* If parse_socks says that we want less data than we actually tried to + give it, we've got some kind of weird situation; just exit the loop for + now. + */ + if (want_length <= datalen) + break; + /* Otherwise, it wants more data than we gave it. If we can provide more + * data than we gave it, we'll try to do so in the next iteration of the + * loop. If we can't, the while loop will exit. It's okay if it asked for + * more than we have total; maybe it doesn't really need so much. */ + } + + 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; @@ -1378,25 +1646,20 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, char *next, *startaddr; struct in_addr in; - if (buf->datalen < 2) /* version and another byte */ - return 0; - - buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN, 0); - tor_assert(buf->head && buf->head->datalen >= 2); - - 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); 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 || !memchr(data+2, 0, nummethods)) { log_warn(LD_APP, "socks5: offered methods don't include 'no auth'. " "Rejecting."); @@ -1407,7 +1670,7 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, } /* remove packet from buf. also remove any other extraneous * bytes, to support broken socks clients. */ - buf_clear(buf); + *drain_out = -1; req->replylen = 2; /* 2 bytes of response */ req->reply[0] = 5; /* socks5 reply */ @@ -1418,10 +1681,11 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, } /* 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 < 8) {/* basic info plus >=2 for addr plus 2 for port */ + *want_length_out = 8; 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 +1694,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 +1720,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 +1737,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 " @@ -1501,7 +1767,7 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, 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); @@ -1510,10 +1776,12 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, /* http://archive.socks.permeo.com/protocol/socks4a.protocol */ 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 +1791,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 +1812,18 @@ 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); + next = memchr(data+SOCKS4_NETWORK_LEN, 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; /* ???? */ return 0; } - tor_assert(next < CHUNK_WRITE_PTR(buf->head)); + tor_assert(next < data+datalen); startaddr = NULL; if (socks4_prot != socks4a && @@ -1565,18 +1834,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; return 0; } if (MAX_SOCKS_ADDR_LEN <= next-startaddr) { @@ -1602,7 +1873,7 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, return -1; } /* 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 */ @@ -1640,9 +1911,10 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, 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 +1936,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 +2005,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 +2017,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 +2027,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 +2048,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 +2057,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 +2068,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 +2078,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 +2086,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 +2112,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 +2150,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 +2229,59 @@ 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 + /** 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 e50b9ff6f..613001066 100644 --- a/src/or/buffers.h +++ b/src/or/buffers.h @@ -24,11 +24,11 @@ size_t buf_datalen(const buf_t *buf); size_t buf_allocation(const buf_t *buf); size_t buf_slack(const buf_t *buf); -int read_to_buf(int s, size_t at_most, buf_t *buf, int *reached_eof, +int read_to_buf(tor_socket_t s, size_t at_most, buf_t *buf, int *reached_eof, int *socket_error); int read_to_buf_tls(tor_tls_t *tls, size_t at_most, buf_t *buf); -int flush_buf(int s, buf_t *buf, size_t sz, size_t *buf_flushlen); +int flush_buf(tor_socket_t s, buf_t *buf, size_t sz, size_t *buf_flushlen); int flush_buf_tls(tor_tls_t *tls, buf_t *buf, size_t sz, size_t *buf_flushlen); int write_to_buf(const char *string, size_t string_len, buf_t *buf); @@ -48,6 +48,23 @@ 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 + void assert_buf_ok(buf_t *buf); #ifdef BUFFERS_PRIVATE diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 08bfb9881..4ec45bc08 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -23,6 +23,7 @@ #include "directory.h" #include "main.h" #include "networkstatus.h" +#include "nodelist.h" #include "onion.h" #include "policies.h" #include "relay.h" @@ -55,8 +56,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]; @@ -95,7 +96,7 @@ 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); @@ -262,7 +263,7 @@ circuit_build_times_test_frequency(void) } /** - * Retrieve and bounds-check the cbtmintimeout consensus paramter. + * Retrieve and bounds-check the cbtmintimeout consensus parameter. * * Effect: This is the minimum allowed timeout value in milliseconds. * The minimum is to prevent rounding to 0 (we only check once @@ -678,7 +679,15 @@ circuit_build_times_shuffle_and_store_array(circuit_build_times_t *cbt, log_notice(LD_CIRC, "The number of circuit times that this Tor version " "uses to calculate build times is less than the number stored " "in your state file. Decreasing the circuit time history from " - "%d to %d.", num_times, CBT_NCIRCUITS_TO_OBSERVE); + "%lu to %d.", (unsigned long)num_times, + CBT_NCIRCUITS_TO_OBSERVE); + } + + if (n > INT_MAX-1) { + log_warn(LD_CIRC, "For some insane reasons, you had %lu circuit build " + "observations in your state file. That's far too many; probably " + "there's a bug here.", (unsigned long)n); + n = INT_MAX-1; } /* This code can only be run on a compact array */ @@ -1493,7 +1502,7 @@ get_unique_circ_id_by_conn(or_connection_t *conn) } /** If <b>verbose</b> is false, allocate and return a comma-separated list of - * the currently built elements of circuit_t. If <b>verbose</b> is true, also + * the currently built elements of <b>circ</b>. If <b>verbose</b> is true, also * list information about link status in a more verbose format using spaces. * If <b>verbose_names</b> is false, give nicknames for Named routers and hex * digests for others; if <b>verbose_names</b> is true, use $DIGEST=Name style @@ -1524,10 +1533,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) @@ -1537,10 +1545,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); @@ -1552,9 +1558,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] = '$'; @@ -1582,7 +1588,7 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names) } /** If <b>verbose</b> is false, allocate and return a comma-separated - * list of the currently built elements of circuit_t. If + * list of the currently built elements of <b>circ</b>. If * <b>verbose</b> is true, also list information about link status in * a more verbose format using spaces. */ @@ -1593,7 +1599,7 @@ circuit_list_path(origin_circuit_t *circ, int verbose) } /** Allocate and return a comma-separated list of the currently built elements - * of circuit_t, giving each as a verbose nickname. + * of <b>circ</b>, giving each as a verbose nickname. */ char * circuit_list_path_for_controller(origin_circuit_t *circ) @@ -1602,7 +1608,7 @@ circuit_list_path_for_controller(origin_circuit_t *circ) } /** Log, at severity <b>severity</b>, the nicknames of each router in - * circ's cpath. Also log the length of the cpath, and the intended + * <b>circ</b>'s cpath. Also log the length of the cpath, and the intended * exit point. */ void @@ -1614,7 +1620,7 @@ circuit_log_path(int severity, unsigned int domain, origin_circuit_t *circ) } /** Tell the rep(utation)hist(ory) module about the status of the links - * in circ. Hops that have become OPEN are marked as successfully + * in <b>circ</b>. Hops that have become OPEN are marked as successfully * extended; the _first_ hop that isn't open (if any) is marked as * unable to extend. */ @@ -1623,31 +1629,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; } @@ -1753,10 +1756,9 @@ circuit_handle_first_hop(origin_circuit_t *circ) if (!n_conn) { /* not currently connected in a useful way. */ - const char *name = strlen(firsthop->extend_info->nickname) ? - firsthop->extend_info->nickname : fmt_addr(&firsthop->extend_info->addr); log_info(LD_CIRC, "Next router is %s: %s", - safe_str_client(name), msg?msg:"???"); + safe_str_client(extend_info_describe(firsthop->extend_info)), + msg?msg:"???"); circ->_base.n_hop = extend_info_dup(firsthop->extend_info); if (should_launch) { @@ -1917,7 +1919,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, @@ -1946,7 +1948,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); @@ -1989,7 +1991,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; @@ -2005,7 +2007,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 @@ -2039,7 +2041,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->nickname : "<unnamed>"); + node ? node_describe(node) : "<unnamed>"); } else { tor_assert(circ->cpath->state == CPATH_STATE_OPEN); tor_assert(circ->_base.state == CIRCUIT_STATE_BUILDING); @@ -2081,7 +2083,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, @@ -2516,12 +2518,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 && @@ -2529,10 +2531,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, @@ -2550,24 +2552,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; } @@ -2601,12 +2591,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; @@ -2616,7 +2606,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_addr_to_node_policy(0, port, node); + else + continue; if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED) return 1; } @@ -2649,18 +2642,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(); @@ -2681,10 +2673,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 @@ -2692,41 +2685,45 @@ 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)) { + 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); @@ -2734,11 +2731,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_EDGE_CONN(conn), node)) { ++n_supported[i]; // log_fn(LOG_DEBUG,"%s is supported. n_supported[%d] now %d.", // router->nickname, i, n_supported[i]); @@ -2746,7 +2742,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. */ @@ -2763,7 +2759,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, @@ -2774,11 +2770,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 @@ -2796,7 +2793,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.", @@ -2807,18 +2804,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); } @@ -2828,9 +2824,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->nickname); - return router; + if (node) { + log_info(LD_CIRC, "Chose exit server '%s'", node_describe(node)); + return node; } if (options->ExitNodes) { log_warn(LD_CIRC, @@ -2851,12 +2847,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) @@ -2869,7 +2865,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; @@ -2885,7 +2881,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; @@ -2936,7 +2932,7 @@ warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit) log_warn(LD_BUG, "Using %s '%s' which is listed in ExcludeNodes%s, " "even though StrictNodes is set. Please report. " "(Circuit purpose: %s)", - description, exit->nickname, + description, extend_info_describe(exit), rs==options->ExcludeNodes?"":" or ExcludeExitNodes", circuit_purpose_to_string(purpose)); } else { @@ -2945,7 +2941,7 @@ warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit) "prevent this (and possibly break your Tor functionality), " "set the StrictNodes configuration option. " "(Circuit purpose: %s)", - description, exit->nickname, + description, extend_info_describe(exit), rs==options->ExcludeNodes?"":" or ExcludeExitNodes", circuit_purpose_to_string(purpose)); } @@ -2962,13 +2958,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; @@ -2976,17 +2971,19 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit) if (exit) { /* the circuit-builder pre-requested one */ warn_if_last_router_excluded(circ, exit); - log_info(LD_CIRC,"Using requested exit node '%s'", exit->nickname); + log_info(LD_CIRC,"Using requested exit node '%s'", + 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; @@ -3025,8 +3022,8 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit) circuit_append_new_exit(circ, exit); circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING); if ((err_reason = circuit_send_next_onion_skin(circ))<0) { - log_warn(LD_CIRC, "Couldn't extend circuit to new point '%s'.", - exit->nickname); + log_warn(LD_CIRC, "Couldn't extend circuit to new point %s.", + extend_info_describe(exit)); circuit_mark_for_close(TO_CIRCUIT(circ), -err_reason); return -1; } @@ -3037,35 +3034,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; } @@ -3093,31 +3085,31 @@ 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))) { + smartlist_add(excluded, (void*) r); + nodelist_add_node_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))) { + smartlist_add(excluded, (void*)r); + nodelist_add_node_family(excluded, r); } } @@ -3140,44 +3132,45 @@ 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. */ + smartlist_add(excluded, (void*)node); + nodelist_add_node_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))) { + smartlist_add(excluded, (void*)node); + nodelist_add_node_family(excluded, node); } }); } @@ -3233,14 +3226,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) { @@ -3250,7 +3247,8 @@ onion_extend_cpath(origin_circuit_t *circ) } log_debug(LD_CIRC,"Chose router %s for hop %d (exit is %s)", - info->nickname, cur_len+1, build_state_get_exit_nickname(state)); + extend_info_describe(info), + cur_len+1, build_state_get_exit_nickname(state)); onion_append_hop(&circ->cpath, info); extend_info_free(info); @@ -3299,7 +3297,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); @@ -3308,6 +3306,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) @@ -3338,12 +3359,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 @@ -3365,10 +3386,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; @@ -3376,16 +3397,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 && !ri->is_possible_guard && - !routerset_contains_router(options->EntryNodes,ri)) + else if (options->UseBridges && !node_is_a_configured_bridge(node)) + *reason = "not a configured bridge"; + 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) { @@ -3429,7 +3453,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; @@ -3443,12 +3467,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) { @@ -3461,33 +3485,40 @@ 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 (get_options()->UseBridges && r->purpose != ROUTER_PURPOSE_BRIDGE) { - *msg = "not a bridge"; - return NULL; - } - if (!get_options()->UseBridges && r->purpose != ROUTER_PURPOSE_GENERAL) { - *msg = "not general-purpose"; - return NULL; + if (get_options()->UseBridges) { + if (node_get_purpose(node) != ROUTER_PURPOSE_BRIDGE) { + *msg = "not a bridge"; + return NULL; + } + if (!node_is_a_configured_bridge(node)) { + *msg = "not a configured bridge"; + 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)) { + 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. */ @@ -3526,20 +3557,24 @@ log_entry_guards(int severity) smartlist_t *elements = smartlist_create(); char *s; - SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, e) { const char *msg = NULL; char *cp; if (entry_is_live(e, 0, 1, 0, &msg)) - tor_asprintf(&cp, "%s (up %s)", + tor_asprintf(&cp, "%s [%s] (up %s)", e->nickname, + hex_str(e->identity, DIGEST_LEN), e->made_contact ? "made-contact" : "never-contacted"); else - tor_asprintf(&cp, "%s (%s, %s)", - e->nickname, msg, + tor_asprintf(&cp, "%s [%s] (%s, %s)", + e->nickname, + hex_str(e->identity, DIGEST_LEN), + msg, e->made_contact ? "made-contact" : "never-contacted"); smartlist_add(elements, cp); - }); + } + SMARTLIST_FOREACH_END(e); s = smartlist_join_strings(elements, ",", 0, NULL); SMARTLIST_FOREACH(elements, char*, cp, tor_free(cp)); @@ -3563,7 +3598,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, @@ -3585,15 +3620,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) { - 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; @@ -3602,14 +3637,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->nickname); - 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 @@ -3624,13 +3660,13 @@ add_an_entry_guard(routerinfo_t *chosen, int reset_status) 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; @@ -3763,10 +3799,9 @@ 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; - int severity = LOG_DEBUG; digestmap_t *reasons; if (! entry_guards) @@ -3778,7 +3813,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; @@ -3793,15 +3828,14 @@ entry_guards_compute_status(or_options_t *options, time_t now) if (remove_dead_entry_guards(now)) changed = 1; - severity = changed ? LOG_DEBUG : LOG_INFO; - if (changed) { 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); - log_info(LD_CIRC, "Summary: Entry '%s' is %s, %s%s%s, and %s%s.", + 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), entry->unreachable_since ? "unreachable" : "reachable", entry->bad_since ? "unusable" : "usable", reason ? ", ": "", @@ -3916,7 +3950,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; @@ -3955,9 +3989,9 @@ entry_nodes_should_be_added(void) /** Add all nodes in EntryNodes that aren't currently guard nodes to the list * of guard nodes, at the front. */ static void -entry_guards_prepend_from_config(or_options_t *options) +entry_guards_prepend_from_config(const or_options_t *options) { - smartlist_t *entry_routers, *entry_fps; + smartlist_t *entry_nodes, *entry_fps; smartlist_t *old_entry_guards_on_list, *old_entry_guards_not_on_list; tor_assert(entry_guards); @@ -3977,7 +4011,7 @@ entry_guards_prepend_from_config(or_options_t *options) tor_free(string); } - entry_routers = smartlist_create(); + entry_nodes = smartlist_create(); entry_fps = smartlist_create(); old_entry_guards_on_list = smartlist_create(); old_entry_guards_not_on_list = smartlist_create(); @@ -3990,10 +4024,11 @@ entry_guards_prepend_from_config(or_options_t *options) * 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); @@ -4002,9 +4037,9 @@ entry_guards_prepend_from_config(or_options_t *options) }); /* 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); + SMARTLIST_FOREACH(entry_nodes, const node_t *, node, { + if (is_an_entry_guard(node->identity)) { + SMARTLIST_DEL_CURRENT(entry_nodes, node); } }); @@ -4013,15 +4048,15 @@ entry_guards_prepend_from_config(or_options_t *options) /* First, the previously configured guards that are in EntryNodes. */ smartlist_add_all(entry_guards, old_entry_guards_on_list); /* Next, the rest of EntryNodes */ - SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri, { - add_an_entry_guard(ri, 0); + SMARTLIST_FOREACH(entry_nodes, const node_t *, node, { + add_an_entry_guard(node, 0); }); /* 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(entry_fps); smartlist_free(old_entry_guards_on_list); smartlist_free(old_entry_guards_not_on_list); @@ -4033,7 +4068,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; @@ -4047,20 +4082,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_family(exit_family, chosen_exit); consider_exit_family = 1; } @@ -4076,19 +4112,18 @@ 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 */ @@ -4102,7 +4137,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 @@ -4112,7 +4147,7 @@ choose_random_entry(cpath_build_state_t *state) } if (smartlist_len(live_entry_guards) >= options->NumEntryGuards) break; /* 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 @@ -4132,8 +4167,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); + 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 @@ -4143,11 +4178,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; @@ -4156,10 +4191,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; } @@ -4171,16 +4206,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. @@ -4427,7 +4462,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"; @@ -4438,9 +4473,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); @@ -4549,7 +4584,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); @@ -4559,11 +4594,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. @@ -4642,7 +4695,7 @@ 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, @@ -4683,9 +4736,9 @@ 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; @@ -4750,26 +4803,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); - 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 == 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); + + 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 @@ -4783,16 +4865,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); - 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 @@ -4845,21 +4930,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 @@ -4868,15 +4952,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; @@ -4885,7 +4969,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); @@ -4893,7 +4977,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); diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h index 0e673e1c0..caa8a6738 100644 --- a/src/or/circuitbuild.h +++ b/src/or/circuitbuild.h @@ -44,18 +44,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 +65,19 @@ 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); +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); 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); diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index 8ec46186d..93f5fd349 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, @@ -274,8 +272,10 @@ circuit_count_pending_on_or_conn(or_connection_t *or_conn) circuit_get_all_pending_on_or_conn(sl, or_conn); cnt = smartlist_len(sl); smartlist_free(sl); - log_debug(LD_CIRC,"or_conn to %s, %d pending circs", - or_conn->nickname ? or_conn->nickname : "NULL", cnt); + log_debug(LD_CIRC,"or_conn to %s at %s, %d pending circs", + or_conn->nickname ? or_conn->nickname : "NULL", + or_conn->_base.address, + cnt); return cnt; } @@ -773,8 +773,8 @@ circuit_get_by_circid_orconn_impl(circid_t circ_id, or_connection_t *conn) return found->circuit; return NULL; - /* The rest of this checks for bugs. Disabled by default. */ + /* We comment it out because coverity complains otherwise. { circuit_t *circ; for (circ=global_circuitlist;circ;circ = circ->next) { @@ -793,7 +793,7 @@ circuit_get_by_circid_orconn_impl(circid_t circ_id, or_connection_t *conn) } } return NULL; - } + } */ } /** Return a circ such that: @@ -864,7 +864,7 @@ circuit_unlink_all_from_or_conn(or_connection_t *conn, int reason) } /** Return a circ such that: - * - circ-\>rend_data-\>query is equal to <b>rend_query</b>, and + * - circ-\>rend_data-\>onion_address is equal to <b>rend_query</b>, and * - circ-\>purpose is equal to <b>purpose</b>. * * Return NULL if no such circuit exists. @@ -979,7 +979,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. */ @@ -1005,15 +1005,15 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, 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); @@ -1098,7 +1098,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) && diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 7289aa5c1..67677ef05 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -17,6 +17,7 @@ #include "connection.h" #include "connection_edge.h" #include "control.h" +#include "nodelist.h" #include "policies.h" #include "rendclient.h" #include "rendcommon.h" @@ -43,7 +44,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn, int need_uptime, int need_internal, time_t now) { - routerinfo_t *exitrouter; + const node_t *exitnode; cpath_build_state_t *build_state; tor_assert(circ); tor_assert(conn); @@ -73,7 +74,8 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn, return 0; } - if (purpose == CIRCUIT_PURPOSE_C_GENERAL) + if (purpose == CIRCUIT_PURPOSE_C_GENERAL || + purpose == CIRCUIT_PURPOSE_C_REND_JOINED) if (circ->timestamp_dirty && circ->timestamp_dirty+get_options()->MaxCircuitDirtiness <= now) return 0; @@ -85,7 +87,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn, * of the one we meant to finish at. */ build_state = TO_ORIGIN_CIRCUIT(circ)->build_state; - exitrouter = build_state_get_exit_router(build_state); + exitnode = build_state_get_exit_node(build_state); if (need_uptime && !build_state->need_uptime) return 0; @@ -93,7 +95,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. */ @@ -127,7 +129,7 @@ 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; } @@ -288,7 +290,6 @@ circuit_expire_building(void) struct timeval general_cutoff, begindir_cutoff, fourhop_cutoff, cannibalize_cutoff, close_cutoff, extremely_old_cutoff; struct timeval now; - struct timeval introcirc_cutoff; cpath_build_state_t *build_state; tor_gettimeofday(&now); @@ -307,8 +308,6 @@ circuit_expire_building(void) SET_CUTOFF(close_cutoff, circ_times.close_ms); SET_CUTOFF(extremely_old_cutoff, circ_times.close_ms*2 + 1000); - introcirc_cutoff = begindir_cutoff; - while (next_circ) { struct timeval cutoff; victim = next_circ; @@ -325,8 +324,6 @@ circuit_expire_building(void) cutoff = fourhop_cutoff; else if (TO_ORIGIN_CIRCUIT(victim)->has_opened) cutoff = cannibalize_cutoff; - else if (victim->purpose == CIRCUIT_PURPOSE_C_INTRODUCING) - cutoff = introcirc_cutoff; else if (victim->purpose == CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT) cutoff = close_cutoff; else @@ -337,12 +334,6 @@ circuit_expire_building(void) #if 0 /* some debug logs, to help track bugs */ - if (victim->purpose == CIRCUIT_PURPOSE_C_INTRODUCING && - victim->timestamp_created <= introcirc_cutoff && - victim->timestamp_created > general_cutoff) - log_info(LD_REND|LD_CIRC, "Timing out introduction circuit which we " - "would not have done if it had been a general circuit."); - if (victim->purpose >= CIRCUIT_PURPOSE_C_INTRODUCING && victim->purpose <= CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) { if (!victim->timestamp_dirty) @@ -495,7 +486,7 @@ circuit_stream_is_being_handled(edge_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, @@ -511,14 +502,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_addr_to_node_policy(0, port, exitnode); ok = r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED; } if (ok) { @@ -585,7 +576,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; } @@ -597,7 +588,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; } @@ -615,7 +606,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; } @@ -628,7 +619,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; } } @@ -645,7 +636,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(); @@ -664,9 +655,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 } @@ -1101,17 +1092,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 @@ -1225,7 +1208,7 @@ 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); @@ -1282,9 +1265,9 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, 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)) { + if (router_exit_policy_all_nodes_reject(addr, + 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), @@ -1294,9 +1277,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.", @@ -1335,8 +1318,8 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT; return 0; } - log_info(LD_REND,"Chose '%s' as intro point for '%s'.", - extend_info->nickname, + log_info(LD_REND,"Chose %s as intro point for '%s'.", + extend_info_describe(extend_info), safe_str_client(conn->rend_data->onion_address)); } @@ -1345,11 +1328,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); @@ -1488,7 +1471,7 @@ link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ, /** 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; @@ -1512,7 +1495,7 @@ hostname_in_track_host_exits(or_options_t *options, const char *address) static void consider_recording_trackhost(edge_connection_t *conn, 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]; @@ -1615,9 +1598,9 @@ connection_ap_handshake_attach_circuit(edge_connection_t *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 @@ -1633,7 +1616,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.", diff --git a/src/or/circuituse.h b/src/or/circuituse.h index bfeaea20d..ab7f6a2fe 100644 --- a/src/or/circuituse.h +++ b/src/or/circuituse.h @@ -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, origin_circuit_t *circ, crypt_path_t *cpath); int connection_ap_handshake_attach_circuit(edge_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 00d9af33f..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: nickname \"%s\", platform %s.", - router->nickname, escaped(router->platform)); + "Details: router %s, platform %s.", + 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. */ @@ -645,6 +649,7 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn) /* XXX maybe act on my_apparent_addr, if the source is sufficiently * trustworthy. */ + (void)my_apparent_addr; if (connection_or_set_state_open(conn)<0) connection_mark_for_close(TO_CONN(conn)); diff --git a/src/or/config.c b/src/or/config.c index 4bdb0384d..4aabe6b95 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -38,6 +38,8 @@ #include <shlobj.h> #endif +#include "procmon.h" + /** Enumeration of types which option values can take */ typedef enum config_type_t { CONFIG_TYPE_STRING = 0, /**< An arbitrary string. */ @@ -46,9 +48,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. */ @@ -201,6 +207,7 @@ static config_var_t _option_vars[] = { V(ClientOnly, BOOL, "0"), V(ConsensusParams, STRING, NULL), V(ConnLimit, UINT, "1000"), + V(ConnDirectionStatistics, BOOL, "0"), V(ConstrainedSockets, BOOL, "0"), V(ConstrainedSockSize, MEMUNIT, "8192"), V(ContactInfo, STRING, NULL), @@ -209,10 +216,11 @@ static config_var_t _option_vars[] = { V(ControlPortFileGroupReadable,BOOL, "0"), V(ControlPortWriteToFile, FILENAME, NULL), V(ControlSocket, LINELIST, NULL), - V(ControlSocketsGroupWritable, BOOL, "0"), + V(ControlSocketsGroupWritable, BOOL, "0"), 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), @@ -227,9 +235,10 @@ 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(DisableIOCP, BOOL, "1"), V(DNSPort, PORT, "0"), V(DNSListenAddress, LINELIST, NULL), V(DownloadExtraInfo, BOOL, "0"), @@ -244,7 +253,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"), @@ -269,6 +278,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), @@ -298,8 +308,9 @@ 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"), @@ -314,7 +325,7 @@ static config_var_t _option_vars[] = { 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"), @@ -324,6 +335,8 @@ static config_var_t _option_vars[] = { V(PerConnBWRate, MEMUNIT, "0"), V(PidFile, STRING, NULL), V(TestingTorNetwork, BOOL, "0"), + V(PortForwarding, BOOL, "0"), + V(PortForwardingHelper, FILENAME, "tor-fw-helper"), V(PreferTunneledDirConns, BOOL, "1"), V(ProtocolWarnings, BOOL, "0"), V(PublishServerDescriptor, CSV, "1"), @@ -335,7 +348,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"), @@ -376,6 +389,7 @@ static config_var_t _option_vars[] = { V(UpdateBridgesFromAuthority, BOOL, "0"), V(UseBridges, BOOL, "0"), V(UseEntryGuards, BOOL, "1"), + V(UseMicrodescriptors, AUTOBOOL, "0"), V(User, STRING, NULL), VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"), VAR("V2AuthoritativeDirectory",BOOL, V2AuthoritativeDir, "0"), @@ -392,12 +406,14 @@ 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"), VAR("__LeaveStreamsUnattached",BOOL, LeaveStreamsUnattached, "0"), VAR("__HashedControlSessionPassword", LINELIST, HashedControlSessionPassword, NULL), + VAR("__OwningControllerProcess",STRING,OwningControllerProcess, NULL), V(MinUptimeHidServDirectoryV2, INTERVAL, "24 hours"), V(_UsingTestNetworkDefaults, BOOL, "0"), @@ -406,7 +422,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"), @@ -415,6 +431,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"), @@ -426,6 +443,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 @@ -528,39 +546,43 @@ 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 void config_register_addressmaps(const or_options_t *options); static int parse_bridge_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 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); @@ -570,8 +592,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. */ @@ -598,7 +621,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), @@ -632,7 +655,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; @@ -642,12 +665,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. @@ -705,6 +735,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); } @@ -787,7 +822,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[] = { @@ -861,16 +896,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; } @@ -879,8 +914,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 = @@ -901,27 +936,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; } @@ -933,12 +969,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; @@ -978,7 +1014,7 @@ 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; } @@ -1022,7 +1058,8 @@ options_act_reversible(or_options_t *old_options, char **msg) /* Ensure data directory is private; create if possible. */ if (check_private_dir(options->DataDirectory, - running_tor ? CPD_CREATE : CPD_CHECK)<0) { + running_tor ? CPD_CREATE : CPD_CHECK, + options->User)<0) { tor_asprintf(msg, "Couldn't access/create private data directory \"%s\"", options->DataDirectory); @@ -1030,12 +1067,13 @@ options_act_reversible(or_options_t *old_options, char **msg) /* No need to roll back, since you can't change the value. */ } - 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", options->DataDirectory); - if (check_private_dir(fn, running_tor ? CPD_CREATE : CPD_CHECK) < 0) { + if (check_private_dir(fn, running_tor ? CPD_CREATE : CPD_CHECK, + options->User) < 0) { tor_asprintf(msg, "Couldn't access/create private data directory \"%s\"", fn); tor_free(fn); @@ -1105,7 +1143,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; @@ -1130,7 +1168,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) @@ -1144,7 +1182,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) @@ -1163,12 +1201,14 @@ 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 = + old_options && options_transition_affects_workers(old_options, options); if (running_tor && !have_lockfile()) { if (try_locking(options, 1) < 0) @@ -1220,6 +1260,17 @@ options_act(or_options_t *old_options) finish_daemon(options->DataDirectory); } + /* We want to reinit keys as needed before we do much of anything else: + keys are important, and other things can depend on them. */ + if (transition_affects_workers || + (options->V3AuthoritativeDir && (!old_options || + !old_options->V3AuthoritativeDir))) { + if (init_keys() < 0) { + log_warn(LD_BUG,"Error initializing keys; exiting"); + return -1; + } + } + /* Write our PID to the PID file. If we do not have write permissions we * will log a warning */ if (options->PidFile) @@ -1241,6 +1292,8 @@ options_act(or_options_t *old_options) return -1; } + monitor_owning_controller_process(options->OwningControllerProcess); + /* reload keys as needed for rendezvous services. */ if (rend_service_load_keys()<0) { log_warn(LD_GENERAL,"Error loading rendezvous service keys"); @@ -1255,17 +1308,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()); @@ -1341,14 +1393,10 @@ options_act(or_options_t *old_options) } } - if (options_transition_affects_workers(old_options, options)) { + if (transition_affects_workers) { log_info(LD_GENERAL, "Worker-related options changed. Rotating workers."); - if (init_keys() < 0) { - log_warn(LD_BUG,"Error initializing keys; exiting"); - return -1; - } if (server_mode(options) && !server_mode(old_options)) { ip_address_changed(0); if (can_complete_circuit || !any_predicted_circuits(time(NULL))) @@ -1362,9 +1410,6 @@ options_act(or_options_t *old_options) return -1; } - if (options->V3AuthoritativeDir && !old_options->V3AuthoritativeDir) - init_keys(); - if (options->PerConnBWRate != old_options->PerConnBWRate || options->PerConnBWBurst != old_options->PerConnBWBurst) connection_or_update_token_buckets(get_connection_array(), options); @@ -1391,44 +1436,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."); @@ -1446,6 +1501,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 && @@ -1503,7 +1561,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; @@ -1663,12 +1721,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); @@ -1693,9 +1748,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) @@ -1713,11 +1779,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); @@ -1760,6 +1826,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) { @@ -1783,6 +1861,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); @@ -1853,11 +1945,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); @@ -1918,10 +2010,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); @@ -1936,7 +2028,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); } @@ -1945,14 +2037,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); } @@ -2005,10 +2097,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); @@ -2052,7 +2144,9 @@ get_assigned_option(config_format_t *fmt, void *options, escape_val = 0; break; } + /* 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. */ @@ -2068,6 +2162,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. */ @@ -2180,7 +2282,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; @@ -2242,7 +2344,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. */ } @@ -2264,7 +2366,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 */ @@ -2280,11 +2383,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; @@ -2318,8 +2425,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; @@ -2359,7 +2466,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; @@ -2378,7 +2485,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; @@ -2387,7 +2494,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; @@ -2429,48 +2536,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 @@ -2478,7 +2580,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) { @@ -2486,19 +2589,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) { @@ -2517,11 +2621,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; } @@ -2556,7 +2661,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; @@ -2595,8 +2700,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; @@ -2613,7 +2719,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; @@ -2689,10 +2795,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) { @@ -2708,7 +2814,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; @@ -2776,7 +2882,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); } @@ -2835,24 +2941,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 " @@ -2880,6 +2986,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 @@ -3009,12 +3119,6 @@ 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."); @@ -3052,17 +3156,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"); @@ -3272,9 +3383,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."); @@ -3317,6 +3428,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."); @@ -3480,6 +3598,16 @@ options_validate(or_options_t *old_options, or_options_t *options, } } + if (options->OwningControllerProcess) { + const char *validate_pspec_msg = NULL; + if (tor_validate_process_specifier(options->OwningControllerProcess, + &validate_pspec_msg)) { + tor_asprintf(msg, "Bad OwningControllerProcess: %s", + validate_pspec_msg); + return -1; + } + } + if (options->ControlListenAddress) { int all_are_local = 1; config_line_t *ln; @@ -3534,8 +3662,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) @@ -3745,7 +3877,8 @@ opt_streq(const char *s1, const char *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) @@ -3801,8 +3934,8 @@ options_transition_allowed(or_options_t *old, or_options_t *new_val, /** 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 || @@ -3825,8 +3958,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. */ @@ -4031,6 +4164,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; @@ -4191,9 +4326,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; @@ -4270,7 +4405,7 @@ get_torrc_fname(void) * configuration <b>options</b> */ static void -config_register_addressmaps(or_options_t *options) +config_register_addressmaps(const or_options_t *options) { smartlist_t *elts; config_line_t *opt; @@ -4319,6 +4454,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(); @@ -4472,7 +4636,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; @@ -4481,7 +4645,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(); @@ -4502,13 +4666,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=")) { @@ -4525,7 +4689,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", @@ -4535,9 +4699,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."); @@ -4671,7 +4835,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; @@ -4812,6 +4976,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. @@ -4875,6 +5059,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. @@ -4894,13 +5097,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 @@ -4910,7 +5129,11 @@ 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); + + tor_libevent_initialize(&cfg); suppress_libevent_log_msg(NULL); @@ -4949,7 +5172,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) { @@ -5266,7 +5489,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) { @@ -5275,9 +5498,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..bc7119143 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,18 +58,21 @@ 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); +int options_need_geoip_info(const or_options_t *options, + const char **reason_out); 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 */ diff --git a/src/or/connection.c b/src/or/connection.c index 72414589c..c84ee04d5 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -36,6 +36,10 @@ #include "router.h" #include "routerparse.h" +#ifdef USE_BUFFEREVENTS +#include <event2/event.h> +#endif + static connection_t *connection_create_listener( const struct sockaddr *listensockaddr, socklen_t listensocklen, int type, @@ -45,8 +49,10 @@ static void connection_init(time_t now, connection_t *conn, int type, static int connection_init_accepted_conn(connection_t *conn, uint8_t listener_type); 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); @@ -54,8 +60,8 @@ static int connection_reached_eof(connection_t *conn); static int connection_read_to_buf(connection_t *conn, ssize_t *max_to_read, int *socket_error); static int connection_process_inbuf(connection_t *conn, int package_partial); -static void client_check_address_changed(int sock); -static void set_constrained_socket_buffers(int sock, int size); +static void client_check_address_changed(tor_socket_t sock); +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); @@ -183,6 +189,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 * @@ -308,10 +334,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; @@ -377,7 +406,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)) { @@ -424,6 +454,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); @@ -439,8 +478,8 @@ _connection_free(connection_t *conn) rend_data_free(dir_conn->rend_data); } - if (conn->s >= 0) { - log_debug(LD_NET,"closing fd %d.",conn->s); + if (SOCKET_OK(conn->s)) { + log_debug(LD_NET,"closing fd %d.",(int)conn->s); tor_close_socket(conn->s); conn->s = -1; } @@ -450,6 +489,11 @@ _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); + } +#endif memset(mem, 0xCC, memlen); /* poison memory */ tor_free(mem); @@ -479,8 +523,7 @@ connection_free(connection_t *conn) } } if (conn->type == CONN_TYPE_CONTROL) { - TO_CONTROL_CONN(conn)->event_mask = 0; - control_update_global_event_mask(); + connection_control_closed(TO_CONTROL_CONN(conn)); } connection_unregister_events(conn); _connection_free(conn); @@ -576,7 +619,7 @@ connection_about_to_close_connection(connection_t *conn) 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(); + const 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); @@ -663,22 +706,21 @@ connection_close_immediate(connection_t *conn) } if (conn->outbuf_flushlen) { log_info(LD_NET,"fd %d, type %s, state %s, %d bytes on outbuf.", - conn->s, conn_type_to_string(conn->type), + (int)conn->s, conn_type_to_string(conn->type), conn_state_to_string(conn->type, conn->state), (int)conn->outbuf_flushlen); } connection_unregister_events(conn); - if (conn->s >= 0) + if (SOCKET_OK(conn->s)) tor_close_socket(conn->s); 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 @@ -740,7 +782,7 @@ connection_expire_held_open(void) log_fn(severity, LD_NET, "Giving up on marked_for_close conn that's been flushing " "for 15s (fd %d, type %s, state %s).", - conn->s, conn_type_to_string(conn->type), + (int)conn->s, conn_type_to_string(conn->type), conn_state_to_string(conn->type, conn->state)); conn->hold_open_until_flushed = 0; } @@ -812,7 +854,13 @@ create_unix_sockaddr(const char *listenaddress, char **readable_address, sockaddr = tor_malloc_zero(sizeof(struct sockaddr_un)); sockaddr->sun_family = AF_UNIX; - strncpy(sockaddr->sun_path, listenaddress, sizeof(sockaddr->sun_path)); + if (strlcpy(sockaddr->sun_path, listenaddress, sizeof(sockaddr->sun_path)) + >= sizeof(sockaddr->sun_path)) { + log_warn(LD_CONFIG, "Unix socket path '%s' is too long to fit.", + escaped(listenaddress)); + tor_free(sockaddr); + return NULL; + } if (readable_address) *readable_address = tor_strdup(listenaddress); @@ -857,7 +905,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); @@ -868,7 +916,7 @@ check_location_for_unix_socket(or_options_t *options, const char *path) if (options->ControlSocketsGroupWritable) flags |= CPD_GROUP_OK; - if (check_private_dir(p, flags) < 0) { + if (check_private_dir(p, flags, options->User) < 0) { char *escpath, *escdir; escpath = esc_for_log(path); escdir = esc_for_log(p); @@ -893,7 +941,7 @@ check_location_for_unix_socket(or_options_t *options, const char *path) /** Tell the TCP stack that it shouldn't wait for a long time after * <b>sock</b> has closed before reusing its port. */ static void -make_socket_reuseable(int sock) +make_socket_reuseable(tor_socket_t sock) { #ifdef MS_WINDOWS (void) sock; @@ -921,7 +969,7 @@ connection_create_listener(const struct sockaddr *listensockaddr, int type, char* address) { connection_t *conn; - int s; /* the socket we're going to make */ + tor_socket_t s; /* the socket we're going to make */ uint16_t usePort = 0, gotPort = 0; int start_reading = 0; @@ -944,7 +992,7 @@ connection_create_listener(const struct sockaddr *listensockaddr, s = tor_open_socket(PF_INET, is_tcp ? SOCK_STREAM : SOCK_DGRAM, is_tcp ? IPPROTO_TCP: IPPROTO_UDP); - if (s < 0) { + if (!SOCKET_OK(s)) { log_warn(LD_NET,"Socket creation failed."); goto err; } @@ -1137,20 +1185,20 @@ check_sockaddr_family_match(sa_family_t got, connection_t *listener) static int connection_handle_listener_read(connection_t *conn, int new_type) { - int news; /* the new socket */ + tor_socket_t news; /* the new socket */ connection_t *newconn; /* information about the remote peer when connecting to other routers */ char addrbuf[256]; 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)); news = tor_accept_socket(conn->s,remote,&remotelen); - if (news < 0) { /* accept() error */ + if (!SOCKET_OK(news)) { /* accept() error */ int e = tor_socket_errno(conn->s); if (ERRNO_IS_ACCEPT_EAGAIN(e)) { return 0; /* he hung up before we could accept(). that's fine. */ @@ -1166,7 +1214,7 @@ connection_handle_listener_read(connection_t *conn, int new_type) } log_debug(LD_NET, "Connection accepted on socket %d (child of fd %d).", - news,conn->s); + (int)news,(int)conn->s); make_socket_reuseable(news); set_socket_nonblocking(news); @@ -1319,11 +1367,12 @@ int connection_connect(connection_t *conn, const char *address, const tor_addr_t *addr, uint16_t port, int *socket_error) { - int s, inprogress = 0; + tor_socket_t s; + 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) { @@ -1380,7 +1429,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. */ @@ -1405,7 +1454,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; } @@ -1446,7 +1495,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); @@ -1638,6 +1687,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. * @@ -1665,17 +1727,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); @@ -1684,9 +1746,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) { @@ -1721,9 +1783,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); @@ -1732,9 +1794,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; @@ -1949,38 +2011,41 @@ int retry_all_listeners(smartlist_t *replaced_conns, smartlist_t *new_conns) { - or_options_t *options = get_options(); + 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) - return -1; + 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) - return -1; + 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) - return -1; + 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) - return -1; + 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) - return -1; + 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) - return -1; + retval = -1; if (retry_listeners(CONN_TYPE_CONTROL_LISTENER, options->ControlListenAddress, options->ControlPort, "127.0.0.1", @@ -1994,7 +2059,16 @@ retry_all_listeners(smartlist_t *replaced_conns, AF_UNIX)<0) return -1; - return 0; + 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 + * descriptor we had (if any) should be regenerated. (We won't + * automatically notice this because of changes in the option, + * since the value could be "auto".) */ + mark_my_descriptor_dirty("Chosen Or/DirPort changed"); + } + + return retval; } /** Return 1 if we should apply rate limiting to <b>conn</b>, @@ -2003,14 +2077,20 @@ retry_all_listeners(smartlist_t *replaced_conns, 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; @@ -2018,11 +2098,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. @@ -2133,6 +2215,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 @@ -2157,8 +2253,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 */ @@ -2168,12 +2268,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); @@ -2185,6 +2287,7 @@ global_write_bucket_low(connection_t *conn, size_t attempt, int priority) return 0; } +#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 @@ -2212,6 +2315,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); } @@ -2285,7 +2393,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; @@ -2330,7 +2438,7 @@ connection_bucket_refill_helper(int *bucket, int rate, int burst, void connection_bucket_refill(int seconds_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; @@ -2393,7 +2501,7 @@ connection_bucket_refill(int seconds_elapsed, time_t now) TO_OR_CONN(conn)->read_bucket > 0)) { /* and either a non-cell conn or a cell conn with non-empty bucket */ LOG_FN_CONN(conn, (LOG_DEBUG,LD_NET, - "waking up conn (fd %d) for read", conn->s)); + "waking up conn (fd %d) for read", (int)conn->s)); conn->read_blocked_on_bw = 0; connection_start_reading(conn); } @@ -2406,7 +2514,7 @@ connection_bucket_refill(int seconds_elapsed, time_t now) conn->state != OR_CONN_STATE_OPEN || TO_OR_CONN(conn)->write_bucket > 0)) { LOG_FN_CONN(conn, (LOG_DEBUG,LD_NET, - "waking up conn (fd %d) for write", conn->s)); + "waking up conn (fd %d) for write", (int)conn->s)); conn->write_blocked_on_bw = 0; connection_start_writing(conn); } @@ -2428,6 +2536,88 @@ 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; + } + + rate /= TOR_LIBEVENT_TICKS_PER_SECOND; + 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(); + bufferevent_add_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. * @@ -2598,7 +2788,7 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read, log_debug(LD_NET, "%d: starting, inbuf_datalen %ld (%d pending in tls object)." " at_most %ld.", - conn->s,(long)buf_datalen(conn->inbuf), + (int)conn->s,(long)buf_datalen(conn->inbuf), tor_tls_get_pending_bytes(or_conn->tls), (long)at_most); initial_size = buf_datalen(conn->inbuf); @@ -2682,7 +2872,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 */ @@ -2714,11 +2904,205 @@ 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; + connection_buckets_decrement(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; + connection_buckets_decrement(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 (edge_conn->socks_request) /* broken, don't send a socks reply back */ + edge_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); + + 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 @@ -2739,15 +3123,15 @@ connection_outbuf_too_full(connection_t *conn) return (conn->outbuf_flushlen > 10*CELL_PAYLOAD_SIZE); } -/** Try to flush more bytes onto conn-\>s. +/** Try to flush more bytes onto <b>conn</b>-\>s. * * This function gets called either from conn_write() in main.c * when poll() has declared that conn wants to write, or below * from connection_write_to_buf() when an entire TLS record is ready. * - * Update conn-\>timestamp_lastwritten to now, and call flush_buf + * Update <b>conn</b>-\>timestamp_lastwritten to now, and call flush_buf * or flush_buf_tls appropriately. If it succeeds and there are no more - * more bytes on conn->outbuf, then call connection_finished_flushing + * more bytes on <b>conn</b>-\>outbuf, then call connection_finished_flushing * on it too. * * If <b>force</b>, then write as many bytes as possible, ignoring bandwidth @@ -2769,7 +3153,7 @@ connection_handle_write_impl(connection_t *conn, int force) tor_assert(!connection_is_listener(conn)); - if (conn->marked_for_close || conn->s < 0) + if (conn->marked_for_close || !SOCKET_OK(conn->s)) return 0; /* do nothing */ if (conn->in_flushed_some) { @@ -2839,6 +3223,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); @@ -2894,6 +3279,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; @@ -2937,6 +3323,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 @@ -2970,6 +3375,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); @@ -2985,18 +3406,25 @@ _connection_write_to_buf_impl(const char *string, size_t len, /* if it failed, it means we have our package/delivery windows set wrong compared to our max outbuf size. close the whole circuit. */ log_warn(LD_NET, - "write_to_buf failed. Closing circuit (fd %d).", conn->s); + "write_to_buf failed. Closing circuit (fd %d).", (int)conn->s); circuit_mark_for_close(circuit_get_by_edge_conn(TO_EDGE_CONN(conn)), END_CIRC_REASON_INTERNAL); } else { log_warn(LD_NET, - "write_to_buf failed. Closing connection (fd %d).", conn->s); + "write_to_buf failed. Closing connection (fd %d).", + (int)conn->s); connection_mark_for_close(conn); } 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 { @@ -3030,7 +3458,7 @@ _connection_write_to_buf_impl(const char *string, size_t len, /* this connection is broken. remove it. */ log_warn(LD_BUG, "unhandled error on write for " "conn (type %d, fd %d); removing", - conn->type, conn->s); + conn->type, (int)conn->s); tor_fragile_assert(); /* do a close-immediate here, so we don't try to flush */ connection_close_immediate(conn); @@ -3142,6 +3570,32 @@ connection_get_by_type_state_rendquery(int type, int state, 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; +} + /** Return an open, non-marked connection of a given type and purpose, or NULL * if no such connection exists. */ connection_t * @@ -3253,7 +3707,7 @@ alloc_http_authenticator(const char *authenticator) * call init_keys(). */ static void -client_check_address_changed(int sock) +client_check_address_changed(tor_socket_t sock) { uint32_t iface_ip, ip_out; /* host order */ struct sockaddr_in out_addr; @@ -3309,7 +3763,7 @@ client_check_address_changed(int sock) * to the desired size to stay below system TCP buffer limits. */ static void -set_constrained_socket_buffers(int sock, int size) +set_constrained_socket_buffers(tor_socket_t sock, int size) { void *sz = (void*)&size; socklen_t sz_sz = (socklen_t) sizeof(size); @@ -3392,6 +3846,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)); @@ -3517,6 +3974,16 @@ 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); @@ -3541,11 +4008,18 @@ assert_connection_ok(connection_t *conn, time_t now) tor_assert(conn->linked); } if (conn->linked) - tor_assert(conn->s < 0); + 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) @@ -3555,10 +4029,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); diff --git a/src/or/connection.h b/src/or/connection.h index 576d3a63e..8dc011209 100644 --- a/src/or/connection.h +++ b/src/or/connection.h @@ -12,6 +12,9 @@ #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); @@ -31,6 +34,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, @@ -51,10 +69,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 +99,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 +132,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 +147,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 7828f1638..c49014848 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" @@ -90,8 +91,8 @@ _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; + _connection_mark_and_flush(TO_CONN(conn), line, file); + conn->end_reason = endreason; } @@ -100,7 +101,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; @@ -191,8 +192,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 +336,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 +344,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 +374,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. */ @@ -439,7 +439,7 @@ connection_ap_expire_beginning(void) edge_connection_t *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; @@ -503,12 +503,12 @@ connection_ap_expire_beginning(void) } tor_assert(circ->purpose == CIRCUIT_PURPOSE_C_GENERAL); log_fn(cutoff < 15 ? LOG_INFO : severity, LD_APP, - "We tried for %d seconds to connect to '%s' using exit '%s'." + "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), conn->cpath_layer ? - conn->cpath_layer->extend_info->nickname : "*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 */ @@ -605,7 +605,7 @@ void circuit_discard_optional_exit_enclaves(extend_info_t *info) { edge_connection_t *edge_conn; - routerinfo_t *r1, *r2; + const node_t *r1, *r2; smartlist_t *conns = get_connection_array(); SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { @@ -617,8 +617,8 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info) if (!edge_conn->chosen_exit_optional && !edge_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(edge_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); @@ -813,7 +813,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 +829,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 */ @@ -848,11 +848,11 @@ addressmap_clear_excluded_trackexithosts(or_options_t *options) } else { nodename = tor_strndup(dot+1, strlen(dot+1)-5); } - ri = router_get_by_nickname(nodename, 0); + 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 +866,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 +1313,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 +1326,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. */ @@ -1520,7 +1520,7 @@ addressmap_get_mappings(smartlist_t *sl, time_t min_expires, static int consider_plaintext_ports(edge_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)) { @@ -1557,7 +1557,7 @@ connection_ap_rewrite_and_attach_if_allowed(edge_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; @@ -1588,7 +1588,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, { 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 */ @@ -1711,15 +1711,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 +1733,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 +1750,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,16 +1825,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), r->nickname); + 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; } } @@ -1949,10 +1949,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) { @@ -2079,7 +2079,7 @@ connection_ap_handshake_process_socks(edge_connection_t *conn) { socks_request_t *socks; int sockshere; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); tor_assert(conn); tor_assert(conn->_base.type == CONN_TYPE_AP); @@ -2089,8 +2089,14 @@ connection_ap_handshake_process_socks(edge_connection_t *conn) log_debug(LD_APP,"entered."); - sockshere = fetch_from_buf_socks(conn->_base.inbuf, socks, - options->TestSocks, options->SafeSocks); + IF_HAS_BUFFEREVENT(TO_CONN(conn), { + struct evbuffer *input = bufferevent_get_input(conn->_base.bufev); + sockshere = fetch_from_evbuffer_socks(input, socks, + options->TestSocks, options->SafeSocks); + }) ELSE_IF_NO_BUFFEREVENT { + sockshere = fetch_from_buf_socks(conn->_base.inbuf, socks, + options->TestSocks, options->SafeSocks); + }; if (sockshere == 0) { if (socks->replylen) { connection_write_to_buf(socks->reply, socks->replylen, TO_CONN(conn)); @@ -2191,7 +2197,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(TO_CONN(conn), tmp_buf, &tlen); if (err == 0) return 0; if (err < 0) { @@ -2304,8 +2310,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, + ap_conn->stream_id); begin_type = ap_conn->use_begindir ? RELAY_COMMAND_BEGIN_DIR : RELAY_COMMAND_BEGIN; @@ -2418,9 +2426,11 @@ 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, +connection_ap_make_link(connection_t *partner, + char *address, uint16_t port, const char *digest, int use_begindir, int want_onehop) { edge_connection_t *conn; @@ -2455,6 +2465,8 @@ connection_ap_make_link(char *address, uint16_t port, tor_addr_make_unspec(&conn->_base.addr); conn->_base.port = 0; + connection_link_connections(partner, TO_CONN(conn)); + if (connection_add(TO_CONN(conn)) < 0) { /* no space, forget it */ connection_free(TO_CONN(conn)); return NULL; @@ -2491,13 +2503,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); @@ -2610,7 +2620,8 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn, } connection_ap_handshake_socks_reply(conn, buf, replylen, (answer_type == RESOLVED_TYPE_IPV4 || - answer_type == RESOLVED_TYPE_IPV6) ? + answer_type == RESOLVED_TYPE_IPV6 || + answer_type == RESOLVED_TYPE_HOSTNAME) ? 0 : END_STREAM_REASON_RESOLVEFAILED); } @@ -2693,7 +2704,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)) @@ -2976,12 +2987,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)) { @@ -3091,9 +3103,9 @@ 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(edge_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); @@ -3104,10 +3116,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); @@ -3122,8 +3134,7 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit) 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); + r = compare_addr_to_node_policy(addr, 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) @@ -3131,17 +3142,12 @@ 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)) { + routerset_contains_node(options->_ExcludeExitNodesUnion, exit)) { /* Not a suitable exit. Refuse it. */ return 0; } diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h index 8ba2fafd0..a7fc12e23 100644 --- a/src/or/connection_edge.h +++ b/src/or/connection_edge.h @@ -30,7 +30,8 @@ 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); -edge_connection_t *connection_ap_make_link(char *address, uint16_t port, +edge_connection_t *connection_ap_make_link(connection_t *partner, + char *address, uint16_t port, const char *digest, int use_begindir, int want_onehop); void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply, @@ -47,7 +48,8 @@ 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(edge_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, @@ -61,8 +63,8 @@ int connection_ap_process_transparent(edge_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); diff --git a/src/or/connection_or.c b/src/or/connection_or.c index ed174c922..679500dee 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -22,12 +22,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 +42,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 @@ -178,7 +191,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 +241,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 +270,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 +303,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); @@ -342,7 +363,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 +380,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 +403,22 @@ 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; + int rate_per_tick = rate / TOR_LIBEVENT_TICKS_PER_SECOND; + cfg = ev_token_bucket_cfg_new(rate_per_tick, burst, rate_per_tick, + burst, tick); + old_cfg = conn->bucket_cfg; + if (conn->_base.bufev) + bufferevent_set_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 +429,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 +455,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 +463,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 +479,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,7 +828,7 @@ 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; @@ -863,6 +904,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 +912,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) + bufferevent_set_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; } @@ -929,13 +997,16 @@ connection_tls_continue_handshake(or_connection_t *conn) if (! tor_tls_used_v1_handshake(conn->tls)) { if (!tor_tls_is_server(conn->tls)) { if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) { - // log_notice(LD_OR,"Done. state was TLS_HANDSHAKING."); + log_debug(LD_OR, "Done with initial SSL handshake (client-side). " + "Requesting renegotiation."); conn->_base.state = OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING; goto again; } // log_notice(LD_OR,"Done. state was %d.", conn->_base.state); } else { /* improved handshake, but not a client. */ + log_debug(LD_OR, "Done with initial SSL handshake (server-side). " + "Expecting renegotiation."); tor_tls_set_renegotiate_callback(conn->tls, connection_or_tls_renegotiated_cb, conn); @@ -960,6 +1031,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. */ @@ -1005,7 +1148,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 : @@ -1128,7 +1271,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(); @@ -1209,7 +1354,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); @@ -1220,8 +1365,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; @@ -1266,12 +1415,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. @@ -1289,7 +1444,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) @@ -1300,8 +1455,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); @@ -1388,7 +1543,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..4a374cac0 100644 --- a/src/or/connection_or.h +++ b/src/or/connection_or.h @@ -27,7 +27,7 @@ int connection_or_finished_flushing(or_connection_t *conn); int connection_or_finished_connecting(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); diff --git a/src/or/control.c b/src/or/control.c index 384e579f9..6ea9dbe47 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -26,12 +26,20 @@ #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 * finished authentication and is accepting commands. */ #define STATE_IS_OPEN(s) ((s) == CONTROL_CONN_STATE_OPEN) @@ -64,7 +72,8 @@ #define EVENT_CLIENTS_SEEN 0x0015 #define EVENT_NEWCONSENSUS 0x0016 #define EVENT_BUILDTIMEOUT_SET 0x0017 -#define _EVENT_MAX 0x0017 +#define EVENT_SIGNAL 0x0018 +#define _EVENT_MAX 0x0018 /* If _EVENT_MAX ever hits 0x0020, we need to make the mask wider. */ /** Bitfield: The bit 1<<e is set if <b>any</b> open control @@ -96,7 +105,7 @@ static int disable_log_messages = 0; static int authentication_cookie_is_set = 0; /** If authentication_cookie_is_set, a secret cookie that we've stored to disk * and which we're using to authenticate controllers. (If the controller can - * read it off disk, it has permission to connect. */ + * read it off disk, it has permission to connect.) */ static char authentication_cookie[AUTHENTICATION_COOKIE_LEN]; /** A sufficiently large size to record the last bootstrap phase string. */ @@ -479,33 +488,26 @@ decode_escaped_string(const char *start, size_t in_len_max, } /** Acts like sprintf, but writes its formatted string to the end of - * <b>conn</b>-\>outbuf. The message may be truncated if it is too long, - * but it will always end with a CRLF sequence. - * - * Currently the length of the message is limited to 1024 (including the - * ending CR LF NUL ("\\r\\n\\0"). */ + * <b>conn</b>-\>outbuf. */ static void connection_printf_to_buf(control_connection_t *conn, const char *format, ...) { -#define CONNECTION_PRINTF_TO_BUF_BUFFERSIZE 1024 va_list ap; - char buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE]; - int r; - size_t len; + char *buf = NULL; + int len; + va_start(ap,format); - r = tor_vsnprintf(buf, sizeof(buf), format, ap); + len = tor_vasprintf(&buf, format, ap); va_end(ap); - if (r<0) { + + if (len < 0) { log_warn(LD_BUG, "Unable to format string for controller."); return; } - len = strlen(buf); - if (fast_memcmp("\r\n\0", buf+len-2, 3)) { - buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-1] = '\0'; - buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-2] = '\n'; - buf[CONNECTION_PRINTF_TO_BUF_BUFFERSIZE-3] = '\r'; - } - connection_write_to_buf(buf, len, TO_CONN(conn)); + + connection_write_to_buf(buf, (size_t)len, TO_CONN(conn)); + + tor_free(buf); } /** Write all of the open control ports to ControlPortWriteToFile */ @@ -514,7 +516,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; @@ -598,52 +600,37 @@ 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); } -/** Helper for send_control1_event and send_control1_event_extended: +/** Helper for send_control_event and control_event_status: * Send an event to all v1 controllers that are listening for code * <b>event</b>. The event's body is created by the printf-style format in - * <b>format</b>, and other arguments as provided. - * - * Currently the length of the message is limited to 1024 (including the - * ending \\r\\n\\0). */ + * <b>format</b>, and other arguments as provided. */ static void send_control_event_impl(uint16_t event, event_format_t which, const char *format, va_list ap) { - /* This is just a little longer than the longest allowed log message */ -#define SEND_CONTROL1_EVENT_BUFFERSIZE 10064 - int r; - char buf[SEND_CONTROL1_EVENT_BUFFERSIZE]; - size_t len; + char *buf = NULL; + int len; - r = tor_vsnprintf(buf, sizeof(buf), format, ap); - if (r<0) { + len = tor_vasprintf(&buf, format, ap); + if (len < 0) { log_warn(LD_BUG, "Unable to format event for controller."); return; } - len = strlen(buf); - if (fast_memcmp("\r\n\0", buf+len-2, 3)) { - /* if it is not properly terminated, do it now */ - buf[SEND_CONTROL1_EVENT_BUFFERSIZE-1] = '\0'; - buf[SEND_CONTROL1_EVENT_BUFFERSIZE-2] = '\n'; - buf[SEND_CONTROL1_EVENT_BUFFERSIZE-3] = '\r'; - } - send_control_event_string(event, which|ALL_FORMATS, buf); + + tor_free(buf); } /** Send an event to all v1 controllers that are listening for code * <b>event</b>. The event's body is created by the printf-style format in - * <b>format</b>, and other arguments as provided. - * - * Currently the length of the message is limited to 1024 (including the - * ending \\n\\r\\0. */ + * <b>format</b>, and other arguments as provided. */ static void send_control_event(uint16_t event, event_format_t which, const char *format, ...) @@ -818,7 +805,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. */ @@ -930,13 +917,44 @@ 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" }, + { 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(); @@ -948,56 +966,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); } @@ -1059,7 +1043,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; @@ -1268,13 +1252,33 @@ 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); return 0; } +/** Called when we get a TAKEOWNERSHIP command. Mark this connection + * as an owning connection, so that we will exit if the connection + * closes. */ +static int +handle_control_takeownership(control_connection_t *conn, uint32_t len, + const char *body) +{ + (void)len; + (void)body; + + conn->is_owning_control_connection = 1; + + log_info(LD_CONTROL, "Control connection %d has taken ownership of this " + "Tor instance.", + (int)(conn->_base.s)); + + send_control_done(conn); + return 0; +} + /** Called when we get a MAPADDRESS command; try to bind all listed addresses, * and report success or failure. */ static int @@ -1377,10 +1381,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"); + 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")) { @@ -1390,10 +1400,65 @@ 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")) { - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); if (!me) { *errmsg = "No routerdesc known; am I really a server?"; return -1; @@ -1415,8 +1480,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; @@ -1490,7 +1556,7 @@ getinfo_helper_listeners(control_connection_t *control_conn, struct sockaddr_storage ss; socklen_t ss_len = sizeof(ss); - if (conn->type != type || conn->marked_for_close || conn->s < 0) + if (conn->type != type || conn->marked_for_close || !SOCKET_OK(conn->s)) continue; if (getsockname(conn->s, (struct sockaddr *)&ss, &ss_len) < 0) { @@ -1518,16 +1584,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) @@ -1537,7 +1604,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) @@ -1553,7 +1620,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( @@ -1571,8 +1638,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); @@ -1885,7 +1952,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); @@ -2003,6 +2070,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."), @@ -2010,8 +2085,8 @@ static const getinfo_item_t getinfo_items[] = { "v2 networkstatus docs as retrieved from a DirPort."), ITEM("dir/status-vote/current/consensus", dir, "v3 Networkstatus consensus as retrieved from a DirPort."), - PREFIX("exit-policy/default", policies, - "The default value appended to the configured exit policy."), + ITEM("exit-policy/default", policies, + "The default value appended to the configured exit policy."), PREFIX("ip-to-country/", geoip, "Perform a GEOIP lookup"), { NULL, NULL, NULL, 0 } }; @@ -2212,7 +2287,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; @@ -2243,8 +2318,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 { @@ -2272,17 +2346,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; } @@ -2293,9 +2371,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); }); @@ -2329,7 +2408,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; } @@ -2445,16 +2524,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); @@ -2748,7 +2828,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); @@ -2826,8 +2906,6 @@ int connection_control_finished_flushing(control_connection_t *conn) { tor_assert(conn); - - connection_stop_writing(TO_CONN(conn)); return 0; } @@ -2842,6 +2920,43 @@ connection_control_reached_eof(control_connection_t *conn) return 0; } +/** Shut down this Tor instance in the same way that SIGINT would, but + * with a log message appropriate for the loss of an owning controller. */ +static void +lost_owning_controller(const char *owner_type, const char *loss_manner) +{ + int shutdown_slowly = server_mode(get_options()); + + log_notice(LD_CONTROL, "Owning controller %s has %s -- %s.", + owner_type, loss_manner, + shutdown_slowly ? "shutting down" : "exiting now"); + + /* XXXX Perhaps this chunk of code should be a separate function, + * called here and by process_signal(SIGINT). */ + + if (!shutdown_slowly) { + tor_cleanup(); + exit(0); + } + /* XXXX This will close all listening sockets except control-port + * listeners. Perhaps we should close those too. */ + hibernate_begin_shutdown(); +} + +/** Called when <b>conn</b> is being freed. */ +void +connection_control_closed(control_connection_t *conn) +{ + tor_assert(conn); + + conn->event_mask = 0; + control_update_global_event_mask(); + + if (conn->is_owning_control_connection) { + lost_owning_controller("connection", "closed"); + } +} + /** Return true iff <b>cmd</b> is allowable (or at least forgivable) at this * stage of the protocol. */ static int @@ -2862,6 +2977,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. */ @@ -2884,7 +3010,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]; @@ -2896,8 +3022,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; } @@ -2908,7 +3034,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) @@ -2918,8 +3044,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; @@ -2979,8 +3104,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; } @@ -2997,6 +3121,9 @@ connection_control_process_inbuf(control_connection_t *conn) return 0; } + /* XXXX Why is this not implemented as a table like the GETINFO + * items are? Even handling the plus signs at the beginnings of + * commands wouldn't be very hard with proper macros. */ cmd_data_len = (uint32_t)data_len; if (!strcasecmp(conn->incoming_cmd, "SETCONF")) { if (handle_control_setconf(conn, cmd_data_len, args)) @@ -3022,6 +3149,9 @@ connection_control_process_inbuf(control_connection_t *conn) } else if (!strcasecmp(conn->incoming_cmd, "SIGNAL")) { if (handle_control_signal(conn, cmd_data_len, args)) return -1; + } else if (!strcasecmp(conn->incoming_cmd, "TAKEOWNERSHIP")) { + if (handle_control_takeownership(conn, cmd_data_len, args)) + return -1; } else if (!strcasecmp(conn->incoming_cmd, "MAPADDRESS")) { if (handle_control_mapaddress(conn, cmd_data_len, args)) return -1; @@ -3077,7 +3207,6 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp, { const char *status; char extended_buf[96]; - int providing_reason=0; if (!EVENT_IS_INTERESTING(EVENT_CIRCUIT_STATUS)) return 0; tor_assert(circ); @@ -3101,7 +3230,6 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp, const char *reason_str = circuit_end_reason_to_control_string(reason_code); char *reason = NULL; size_t n=strlen(extended_buf); - providing_reason=1; if (!reason_str) { reason = tor_malloc(16); tor_snprintf(reason, 16, "UNKNOWN_%d", reason_code); @@ -3274,10 +3402,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, @@ -3594,7 +3722,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; @@ -3682,10 +3810,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; @@ -3694,7 +3858,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; @@ -3819,9 +3983,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); } @@ -3836,7 +4000,7 @@ control_event_guard(const char *nickname, const char *digest, 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 { @@ -3884,6 +4048,75 @@ init_cookie_authentication(int enabled) return 0; } +/** A copy of the process specifier of Tor's owning controller, or + * NULL if this Tor instance is not currently owned by a process. */ +static char *owning_controller_process_spec = NULL; + +/** A process-termination monitor for Tor's owning controller, or NULL + * if this Tor instance is not currently owned by a process. */ +static tor_process_monitor_t *owning_controller_process_monitor = NULL; + +/** Process-termination monitor callback for Tor's owning controller + * process. */ +static void +owning_controller_procmon_cb(void *unused) +{ + (void)unused; + + lost_owning_controller("process", "vanished"); +} + +/** Set <b>process_spec</b> as Tor's owning controller process. + * Exit on failure. */ +void +monitor_owning_controller_process(const char *process_spec) +{ + const char *msg; + + tor_assert((owning_controller_process_spec == NULL) == + (owning_controller_process_monitor == NULL)); + + if (owning_controller_process_spec != NULL) { + if ((process_spec != NULL) && !strcmp(process_spec, + owning_controller_process_spec)) { + /* Same process -- return now, instead of disposing of and + * recreating the process-termination monitor. */ + return; + } + + /* We are currently owned by a process, and we should no longer be + * owned by it. Free the process-termination monitor. */ + tor_process_monitor_free(owning_controller_process_monitor); + owning_controller_process_monitor = NULL; + + tor_free(owning_controller_process_spec); + owning_controller_process_spec = NULL; + } + + tor_assert((owning_controller_process_spec == NULL) && + (owning_controller_process_monitor == NULL)); + + if (process_spec == NULL) + return; + + owning_controller_process_spec = tor_strdup(process_spec); + owning_controller_process_monitor = + tor_process_monitor_new(tor_libevent_get_base(), + owning_controller_process_spec, + LD_CONTROL, + owning_controller_procmon_cb, NULL, + &msg); + + if (owning_controller_process_monitor == NULL) { + log_err(LD_BUG, "Couldn't create process-termination monitor for " + "owning controller: %s. Exiting.", + msg); + owning_controller_process_spec = NULL; + tor_cleanup(); + exit(0); + } +} + /** Convert the name of a bootstrapping phase <b>s</b> into strings * <b>tag</b> and <b>summary</b> suitable for display by the controller. */ static int diff --git a/src/or/control.h b/src/or/control.h index a73ed5d3c..147a5af0b 100644 --- a/src/or/control.h +++ b/src/or/control.h @@ -27,6 +27,8 @@ void control_ports_write_to_file(void); int connection_control_finished_flushing(control_connection_t *conn); int connection_control_reached_eof(control_connection_t *conn); +void connection_control_closed(control_connection_t *conn); + int connection_control_process_inbuf(control_connection_t *conn); #define EVENT_AUTHDIR_NEWDESCS 0x000D @@ -55,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,12 +68,15 @@ int control_event_guard(const char *nickname, const char *digest, const char *status); 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); void disable_control_logging(void); void enable_control_logging(void); +void monitor_owning_controller_process(const char *process_spec); + void control_event_bootstrap(bootstrap_status_t status, int progress); void control_event_bootstrap_problem(const char *warn, int reason); diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index 7cbc19133..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); @@ -226,8 +225,8 @@ cpuworker_main(void *data) { char question[ONIONSKIN_CHALLENGE_LEN]; uint8_t question_type; - int *fdarray = data; - int fd; + tor_socket_t *fdarray = data; + tor_socket_t fd; /* variables for onion processing */ char keys[CPATH_KEY_MATERIAL_LEN]; @@ -317,12 +316,12 @@ cpuworker_main(void *data) static int spawn_cpuworker(void) { - int *fdarray; - int fd; + tor_socket_t *fdarray; + tor_socket_t fd; connection_t *conn; int err; - fdarray = tor_malloc(sizeof(int)*2); + fdarray = tor_malloc(sizeof(tor_socket_t)*2); if ((err = tor_socketpair(AF_UNIX, SOCK_STREAM, 0, fdarray)) < 0) { log_warn(LD_NET, "Couldn't construct socketpair for cpuworker: %s", tor_socket_strerror(-err)); @@ -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 eb99e9d08..9e1373d46 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; @@ -297,7 +307,7 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, continue; if (options->ExcludeNodes && options->StrictNodes && - routerset_contains_routerstatus(options->ExcludeNodes, rs)) { + 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,42 @@ 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; + type = V3_DIRINFO; break; case DIR_PURPOSE_FETCH_CONSENSUS: case DIR_PURPOSE_FETCH_CERTIFICATE: - type = V3_AUTHORITY; + type = V3_DIRINFO; + break; + case DIR_PURPOSE_FETCH_MICRODESC: + type = MICRODESC_DIRINFO; break; default: log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose); @@ -381,25 +394,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 +442,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 +454,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 +464,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 +481,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 +527,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 +538,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,20 +548,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) { + if (!node && anonymized_connection) { log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we " - "don't have its router descriptor.", status->nickname); + "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)); @@ -538,11 +572,11 @@ 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)) { - log_warn(LD_DIR, "Wanted to contact directory mirror '%s' for %s, but " + 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.", - status->nickname, + routerstatus_describe(status), dir_conn_purpose_to_string(dir_purpose)); return; } @@ -573,7 +607,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, @@ -597,7 +631,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*/ @@ -625,15 +659,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) { @@ -642,6 +679,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); } } @@ -712,7 +753,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; } @@ -775,7 +817,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) @@ -816,6 +858,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 @@ -831,7 +887,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, @@ -850,6 +906,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 && @@ -925,14 +984,14 @@ 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, + connection_ap_make_link(TO_CONN(conn), + conn->_base.address, conn->_base.port, digest, 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."); @@ -945,8 +1004,12 @@ 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(TO_CONN(linked_conn), { + connection_watch_events(TO_CONN(linked_conn), READ_EVENT|WRITE_EVENT); + }) ELSE_IF_NO_BUFFEREVENT + connection_start_reading(TO_CONN(linked_conn)); } } @@ -984,12 +1047,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; @@ -999,7 +1072,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); @@ -1011,16 +1084,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; } @@ -1101,10 +1173,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; @@ -1144,6 +1217,11 @@ directory_send_command(dir_connection_t *conn, url = tor_malloc(len); tor_snprintf(url, len, "/tor/extra/%s", resource); break; + case DIR_PURPOSE_FETCH_MICRODESC: + tor_assert(resource); + httpcommand = "GET"; + tor_asprintf(&url, "/tor/micro/%s", resource); + break; case DIR_PURPOSE_UPLOAD_DIR: tor_assert(!resource); tor_assert(payload); @@ -1419,6 +1497,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") || @@ -1495,11 +1576,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)) { @@ -1574,13 +1656,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); @@ -1719,6 +1802,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, @@ -1727,22 +1811,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."); } @@ -1892,6 +1978,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) { @@ -1900,7 +2023,6 @@ connection_dir_client_reached_eof(dir_connection_t *conn) router_get_trusteddirserver_by_digest(conn->identity_digest); char *rejected_hdr = http_get_header(headers, "X-Descriptor-Not-New: "); - int rejected = 0; if (rejected_hdr) { if (!strcmp(rejected_hdr, "Yes")) { log_info(LD_GENERAL, @@ -1913,7 +2035,6 @@ connection_dir_client_reached_eof(dir_connection_t *conn) * last descriptor, not on the published time of the last * descriptor. If those are different, that's a bad thing to * do. -NM */ - rejected = 1; } tor_free(rejected_hdr); } @@ -2168,7 +2289,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)); @@ -2471,18 +2592,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."); @@ -3191,7 +3312,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."); @@ -3335,7 +3456,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 */ @@ -3388,10 +3509,10 @@ 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."); @@ -3621,6 +3742,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..caff938e5 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, diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 79b68cdac..0ea1ef648 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) @@ -518,14 +518,15 @@ dirserv_router_has_valid_address(routerinfo_t *ri) if (get_options()->DirAllowPrivateAddresses) return 0; /* whatever it is, we're fine with it */ if (!tor_inet_aton(ri->address, &iaddr)) { - log_info(LD_DIRSERV,"Router '%s' published non-IP address '%s'. Refusing.", - ri->nickname, ri->address); + log_info(LD_DIRSERV,"Router %s published non-IP address '%s'. Refusing.", + router_describe(ri), + ri->address); return -1; } if (is_internal_IP(ntohl(iaddr.s_addr), 0)) { log_info(LD_DIRSERV, - "Router '%s' published internal IP address '%s'. Refusing.", - ri->nickname, ri->address); + "Router %s published internal IP address '%s'. Refusing.", + router_describe(ri), ri->address); return -1; /* it's a private IP, we should reject it */ } return 0; @@ -541,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); @@ -554,10 +555,11 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, /* Is there too much clock skew? */ now = time(NULL); if (ri->cache_info.published_on > now+ROUTER_ALLOW_SKEW) { - log_fn(severity, LD_DIRSERV, "Publication time for nickname '%s' is too " + log_fn(severity, LD_DIRSERV, "Publication time for %s is too " "far (%d minutes) in the future; possible clock skew. Not adding " "(%s)", - ri->nickname, (int)((ri->cache_info.published_on-now)/60), + router_describe(ri), + (int)((ri->cache_info.published_on-now)/60), esc_router_info(ri)); *msg = "Rejected: Your clock is set too far in the future, or your " "timezone is not correct."; @@ -565,9 +567,10 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, } if (ri->cache_info.published_on < now-ROUTER_MAX_AGE_TO_PUBLISH) { log_fn(severity, LD_DIRSERV, - "Publication time for router with nickname '%s' is too far " + "Publication time for %s is too far " "(%d minutes) in the past. Not adding (%s)", - ri->nickname, (int)((now-ri->cache_info.published_on)/60), + router_describe(ri), + (int)((now-ri->cache_info.published_on)/60), esc_router_info(ri)); *msg = "Rejected: Server is expired, or your clock is too far in the past," " or your timezone is not correct."; @@ -575,22 +578,32 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, } if (dirserv_router_has_valid_address(ri) < 0) { log_fn(severity, LD_DIRSERV, - "Router with nickname '%s' has invalid address '%s'. " + "Router %s has invalid address '%s'. " "Not adding (%s).", - ri->nickname, ri->address, + router_describe(ri), + ri->address, esc_router_info(ri)); *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) @@ -715,14 +728,14 @@ 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)) { log_info(LD_DIRSERV, - "Not replacing descriptor from '%s' (source: %s); " + "Not replacing descriptor from %s (source: %s); " "differences are cosmetic.", - ri->nickname, source); + router_describe(ri), source); *msg = "Not replacing router descriptor; no information has changed since " "the last one with this identity."; control_event_or_authdir_new_descriptor("DROPPED", @@ -759,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.", @@ -775,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); @@ -815,54 +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); - uint32_t r = dirserv_router_get_status(ent, &msg); + routerinfo_t *ent = node->ri; + char description[NODE_DESC_BUF_LEN]; + 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", - ent->nickname, msg?msg:""); + 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.", ent->nickname, + "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)) { - log_info(LD_DIRSERV, "Router '%s' is now %svalid.", ent->nickname, + 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)) { - log_info(LD_DIRSERV, "Router '%s' is now a %s directory", ent->nickname, + 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)) { - log_info(LD_DIRSERV, "Router '%s' is now a %s exit", ent->nickname, + 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 @@ -901,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); @@ -912,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++ = '='; @@ -951,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. */ @@ -985,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 @@ -1003,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(). */ @@ -1013,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); @@ -1020,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); @@ -1063,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; } @@ -1167,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) @@ -1194,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); } @@ -1206,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; } @@ -1214,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; } @@ -1223,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; @@ -1239,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; } @@ -1248,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; } @@ -1258,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 && @@ -1281,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 @@ -1525,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; @@ -1558,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. @@ -1651,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, @@ -1734,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; @@ -1788,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; @@ -1816,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 @@ -1864,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; @@ -1884,7 +1922,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl) } ++n_active; } - }); + } SMARTLIST_FOREACH_END(node); /* Now, compute thresholds. */ if (n_active) { @@ -1910,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) @@ -1989,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", @@ -2015,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) { @@ -2043,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":"", @@ -2065,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) { @@ -2161,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. */ @@ -2183,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); @@ -2209,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; @@ -2254,7 +2297,9 @@ 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) { @@ -2266,48 +2311,46 @@ 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 = 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; @@ -2324,7 +2367,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 @@ -2332,18 +2375,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 @@ -2409,7 +2440,7 @@ measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line) tor_free(line); return -1; } - strncpy(out->node_hex, cp, sizeof(out->node_hex)); + strlcpy(out->node_hex, cp, sizeof(out->node_hex)); got_node_id=1; } } while ((cp = tor_strtok_r(NULL, " \t", &strtok_state))); @@ -2461,7 +2492,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; @@ -2521,7 +2552,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; @@ -2591,17 +2622,20 @@ 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, + set_routerstatus_from_routerinfo(rs, node, ri, now, naming, listbadexits, listbaddirs); 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); @@ -2699,7 +2733,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, voter->sigs = smartlist_create(); voter->address = hostname; voter->addr = addr; - voter->dir_port = router_get_advertised_dir_port(options); + voter->dir_port = router_get_advertised_dir_port(options, 0); voter->or_port = router_get_advertised_or_port(options); voter->contact = tor_strdup(contact); if (options->V3AuthUseLegacyKey) { @@ -2733,12 +2767,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(); @@ -2759,8 +2791,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); @@ -2806,7 +2836,8 @@ 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, (int)router_get_advertised_dir_port(options), + hostname, fmt_addr32(addr), + (int)router_get_advertised_dir_port(options, 0), fingerprint, contact, published, @@ -2837,8 +2868,12 @@ 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, + 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); if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest)) @@ -2921,7 +2956,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)); @@ -2940,7 +2975,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); @@ -3009,7 +3044,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)); @@ -3029,8 +3064,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) @@ -3041,7 +3076,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)) { @@ -3080,9 +3115,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/"); @@ -3106,17 +3141,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)); @@ -3163,7 +3198,8 @@ dirserv_orconn_tls_done(const char *address, if (!bridge_auth || ri->purpose == ROUTER_PURPOSE_BRIDGE) { tor_addr_t addr, *addrp=NULL; log_info(LD_DIRSERV, "Found router %s to be reachable at %s:%d. Yay.", - ri->nickname, address, ri->or_port ); + router_describe(ri), + address, ri->or_port); if (tor_addr_from_str(&addr, ri->address) != -1) addrp = &addr; else @@ -3182,7 +3218,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; @@ -3306,7 +3343,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) { @@ -3316,7 +3353,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) @@ -3384,7 +3421,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%. */ @@ -3448,10 +3485,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 { @@ -3509,7 +3546,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); @@ -3548,7 +3585,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) @@ -3587,7 +3624,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); @@ -3633,7 +3670,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 96e3df5ce..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); @@ -1592,7 +1585,7 @@ networkstatus_compute_consensus(smartlist_t *votes, * is the same flag as votes[j]->known_flags[b]. */ int *named_flag; /* Index of the flag "Named" for votes[j] */ int *unnamed_flag; /* Index of the flag "Unnamed" for votes[j] */ - int chosen_named_idx, chosen_unnamed_idx; + int chosen_named_idx; strmap_t *name_to_id_map = strmap_new(); char conflict[DIGEST_LEN]; @@ -1610,7 +1603,6 @@ networkstatus_compute_consensus(smartlist_t *votes, for (i = 0; i < smartlist_len(votes); ++i) unnamed_flag[i] = named_flag[i] = -1; chosen_named_idx = smartlist_string_pos(flags, "Named"); - chosen_unnamed_idx = smartlist_string_pos(flags, "Unnamed"); /* Build the flag index. */ SMARTLIST_FOREACH(votes, networkstatus_t *, v, @@ -2512,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); @@ -2586,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; @@ -2637,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; @@ -2752,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."); @@ -2771,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)) { @@ -2884,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)))); @@ -3079,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: " @@ -3218,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..b6746c655 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,6 +60,7 @@ 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); 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 243b730cb..f2c473dfc 100644 --- a/src/or/dnsserv.c +++ b/src/or/dnsserv.c @@ -95,8 +95,8 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) } if (!q) { log_info(LD_APP, "None of the questions we got were ones we're willing " - "to support. Sending NODATA."); - evdns_server_request_respond(req, DNS_ERR_NONE); + "to support. Sending NOTIMPL."); + evdns_server_request_respond(req, DNS_ERR_NOTIMPL); return; } if (q->type != EVDNS_TYPE_A) { @@ -306,7 +306,7 @@ void dnsserv_configure_listener(connection_t *conn) { tor_assert(conn); - tor_assert(conn->s >= 0); + tor_assert(SOCKET_OK(conn->s)); tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER); conn->dns_server_port = diff --git a/src/or/eventdns.c b/src/or/eventdns.c index fc005df2d..7fe376baf 100644 --- a/src/or/eventdns.c +++ b/src/or/eventdns.c @@ -1028,6 +1028,9 @@ request_parse(u8 *packet, ssize_t length, struct evdns_server_port *port, struct GET16(answers); GET16(authority); GET16(additional); + (void)additional; + (void)authority; + (void)answers; if (flags & 0x8000) return -1; /* Must not be an answer. */ flags &= 0x0110; /* Only RD and CD get preserved. */ @@ -1560,7 +1563,7 @@ evdns_request_data_build(const char *const name, const size_t name_len, /* exported function */ struct evdns_server_port * -evdns_add_server_port(int socket, int is_tcp, evdns_request_callback_fn_type cb, void *user_data) +evdns_add_server_port(tor_socket_t socket, int is_tcp, evdns_request_callback_fn_type cb, void *user_data) { struct evdns_server_port *port; if (!(port = mm_malloc(sizeof(struct evdns_server_port)))) @@ -1828,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) { @@ -2288,7 +2291,7 @@ _evdns_nameserver_add_impl(const struct sockaddr *address, evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns); - ns->socket = socket(PF_INET, SOCK_DGRAM, 0); + ns->socket = tor_open_socket(address->sa_family, SOCK_DGRAM, 0); if (ns->socket < 0) { err = 1; goto out1; } #ifdef WIN32 { @@ -3037,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; @@ -3457,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/eventdns.h b/src/or/eventdns.h index 2fe4ac937..3ff8bba4b 100644 --- a/src/or/eventdns.h +++ b/src/or/eventdns.h @@ -319,7 +319,7 @@ typedef void (*evdns_request_callback_fn_type)(struct evdns_server_request *, vo #define EVDNS_CLASS_INET 1 -struct evdns_server_port *evdns_add_server_port(int socket, int is_tcp, evdns_request_callback_fn_type callback, void *user_data); +struct evdns_server_port *evdns_add_server_port(tor_socket_t socket, int is_tcp, evdns_request_callback_fn_type callback, void *user_data); void evdns_close_server_port(struct evdns_server_port *port); int evdns_server_request_add_reply(struct evdns_server_request *req, int section, const char *name, int type, int class, int ttl, int datalen, int is_name, const char *data); diff --git a/src/or/geoip.c b/src/or/geoip.c index 5bb2410a7..62c7a5c39 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. */ @@ -970,7 +990,7 @@ geoip_dirreq_stats_write(time_t now) geoip_remove_old_clients(start_of_dirreq_stats_interval); statsdir = get_datadir_fname("stats"); - if (check_private_dir(statsdir, CPD_CREATE) < 0) + 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); @@ -1209,7 +1229,7 @@ geoip_bridge_stats_write(time_t now) /* Write it to disk. */ statsdir = get_datadir_fname("stats"); - if (check_private_dir(statsdir, CPD_CREATE) < 0) + if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) goto done; filename = get_datadir_fname2("stats", "bridge-stats"); @@ -1304,7 +1324,7 @@ geoip_entry_stats_write(time_t now) geoip_remove_old_clients(start_of_entry_stats_interval); statsdir = get_datadir_fname("stats"); - if (check_private_dir(statsdir, CPD_CREATE) < 0) + if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) goto done; filename = get_datadir_fname2("stats", "entry-stats"); data = geoip_get_client_history(GEOIP_CLIENT_CONNECT); diff --git a/src/or/geoip.h b/src/or/geoip.h index 24f7c5b93..b50da74dc 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, diff --git a/src/or/hibernate.c b/src/or/hibernate.c index aebce4cc8..f03433a27 100644 --- a/src/or/hibernate.c +++ b/src/or/hibernate.c @@ -134,7 +134,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; @@ -249,7 +249,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; @@ -411,7 +411,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; @@ -750,7 +750,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) { diff --git a/src/or/hibernate.h b/src/or/hibernate.h index 2aea0fab0..b5826bced 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 d1ceeec34..9536ae449 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -33,6 +33,7 @@ #include "main.h" #include "microdesc.h" #include "networkstatus.h" +#include "nodelist.h" #include "ntmain.h" #include "onion.h" #include "policies.h" @@ -44,6 +45,7 @@ #include "router.h" #include "routerlist.h" #include "routerparse.h" +#include "status.h" #ifdef USE_DMALLOC #include <dmalloc.h> #include <openssl/crypto.h> @@ -56,14 +58,18 @@ #include <event.h> #endif +#ifdef USE_BUFFEREVENTS +#include <event2/bufferevent.h> +#endif + void evdns_shutdown(int); /********* PROTOTYPES **********/ static void dumpmemusage(int severity); static void dumpstats(int severity); /* log stats */ -static void conn_read_callback(int fd, short event, void *_conn); -static void conn_write_callback(int fd, short event, void *_conn); +static void conn_read_callback(evutil_socket_t fd, short event, void *_conn); +static void conn_write_callback(evutil_socket_t fd, short event, void *_conn); static void second_elapsed_callback(periodic_timer_t *timer, void *args); static int conn_close_if_marked(int i); static void connection_start_reading_from_linked_conn(connection_t *conn); @@ -71,6 +77,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 +85,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; +#else +static uint64_t stats_prev_n_read = 0; +static uint64_t stats_prev_n_written = 0; +#endif + /* 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; @@ -150,15 +161,41 @@ 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(conn->s >= 0 || + tor_assert(SOCKET_OK(conn->s) || conn->linked || (conn->type == CONN_TYPE_AP && TO_EDGE_CONN(conn)->is_dns_request)); @@ -167,15 +204,67 @@ connection_add(connection_t *conn) conn->conn_array_index = smartlist_len(connection_array); smartlist_add(connection_array, conn); - if (conn->s >= 0 || 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.", - conn_type_to_string(conn->type), conn->s, conn->address, + conn_type_to_string(conn->type), (int)conn->s, conn->address, smartlist_len(connection_array)); return 0; @@ -187,14 +276,20 @@ connection_unregister_events(connection_t *conn) { if (conn->read_event) { if (event_del(conn->read_event)) - log_warn(LD_BUG, "Error removing read event for %d", conn->s); + log_warn(LD_BUG, "Error removing read event for %d", (int)conn->s); tor_free(conn->read_event); } if (conn->write_event) { if (event_del(conn->write_event)) - log_warn(LD_BUG, "Error removing write event for %d", conn->s); + log_warn(LD_BUG, "Error removing write event for %d", (int)conn->s); tor_free(conn->write_event); } +#ifdef USE_BUFFEREVENTS + if (conn->bufev) { + bufferevent_free(conn->bufev); + conn->bufev = NULL; + } +#endif if (conn->dns_server_port) { dnsserv_close_listener(conn); } @@ -213,7 +308,7 @@ connection_remove(connection_t *conn) tor_assert(conn); log_debug(LD_NET,"removing socket %d (type %s), n_conns now %d", - conn->s, conn_type_to_string(conn->type), + (int)conn->s, conn_type_to_string(conn->type), smartlist_len(connection_array)); tor_assert(conn->conn_array_index >= 0); @@ -303,12 +398,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 +446,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 +458,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) { @@ -344,7 +473,7 @@ connection_stop_reading(connection_t *conn) if (event_del(conn->read_event)) log_warn(LD_NET, "Error from libevent setting read event state for %d " "to unwatched: %s", - conn->s, + (int)conn->s, tor_socket_strerror(tor_socket_errno(conn->s))); } } @@ -354,6 +483,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) { @@ -364,7 +499,7 @@ connection_start_reading(connection_t *conn) if (event_add(conn->read_event, NULL)) log_warn(LD_NET, "Error from libevent setting read event state for %d " "to watched: %s", - conn->s, + (int)conn->s, tor_socket_strerror(tor_socket_errno(conn->s))); } } @@ -375,6 +510,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 +523,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) { @@ -394,7 +539,7 @@ connection_stop_writing(connection_t *conn) if (event_del(conn->write_event)) log_warn(LD_NET, "Error from libevent setting write event state for %d " "to unwatched: %s", - conn->s, + (int)conn->s, tor_socket_strerror(tor_socket_errno(conn->s))); } } @@ -404,6 +549,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) { @@ -415,7 +566,7 @@ connection_start_writing(connection_t *conn) if (event_add(conn->write_event, NULL)) log_warn(LD_NET, "Error from libevent setting write event state for %d " "to watched: %s", - conn->s, + (int)conn->s, tor_socket_strerror(tor_socket_errno(conn->s))); } } @@ -501,13 +652,13 @@ close_closeable_connections(void) /** Libevent callback: this gets invoked when (connection_t*)<b>conn</b> has * some data to read. */ static void -conn_read_callback(int fd, short event, void *_conn) +conn_read_callback(evutil_socket_t fd, short event, void *_conn) { connection_t *conn = _conn; (void)fd; (void)event; - log_debug(LD_NET,"socket %d wants to read.",conn->s); + log_debug(LD_NET,"socket %d wants to read.",(int)conn->s); /* assert_connection_ok(conn, time(NULL)); */ @@ -516,7 +667,7 @@ conn_read_callback(int fd, short event, void *_conn) #ifndef MS_WINDOWS log_warn(LD_BUG,"Unhandled error on read for %s connection " "(fd %d); removing", - conn_type_to_string(conn->type), conn->s); + conn_type_to_string(conn->type), (int)conn->s); tor_fragile_assert(); #endif if (CONN_IS_EDGE(conn)) @@ -533,13 +684,14 @@ conn_read_callback(int fd, short event, void *_conn) /** Libevent callback: this gets invoked when (connection_t*)<b>conn</b> has * some data to write. */ static void -conn_write_callback(int fd, short events, void *_conn) +conn_write_callback(evutil_socket_t fd, short events, void *_conn) { connection_t *conn = _conn; (void)fd; (void)events; - LOG_FN_CONN(conn, (LOG_DEBUG, LD_NET, "socket %d wants to write.",conn->s)); + LOG_FN_CONN(conn, (LOG_DEBUG, LD_NET, "socket %d wants to write.", + (int)conn->s)); /* assert_connection_ok(conn, time(NULL)); */ @@ -548,7 +700,7 @@ conn_write_callback(int fd, short events, void *_conn) /* this connection is broken. remove it. */ log_fn(LOG_WARN,LD_BUG, "unhandled error on write for %s connection (fd %d); removing", - conn_type_to_string(conn->type), conn->s); + conn_type_to_string(conn->type), (int)conn->s); tor_fragile_assert(); if (CONN_IS_EDGE(conn)) { /* otherwise we cry wolf about duplicate close */ @@ -589,8 +741,25 @@ conn_close_if_marked(int i) assert_connection_ok(conn, now); /* assert_all_pending_dns_resolves_ok(); */ +#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 ((conn->s >= 0 || conn->linked_conn) && connection_wants_to_flush(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); @@ -599,7 +768,7 @@ conn_close_if_marked(int i) "Conn (addr %s, fd %d, type %s, state %d) marked, but wants " "to flush %d bytes. (Marked at %s:%d)", escaped_safe_str_client(conn->address), - conn->s, conn_type_to_string(conn->type), conn->state, + (int)conn->s, conn_type_to_string(conn->type), conn->state, (int)conn->outbuf_flushlen, conn->marked_for_close_file, conn->marked_for_close); if (conn->linked_conn) { @@ -612,8 +781,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) { @@ -630,7 +799,7 @@ conn_close_if_marked(int i) if (retval > 0) { LOG_FN_CONN(conn, (LOG_INFO,LD_NET, "Holding conn (fd %d) open for more flushing.", - conn->s)); + (int)conn->s)); conn->timestamp_lastwritten = now; /* reset so we can flush more */ } return 0; @@ -650,13 +819,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), - conn->s, conn_type_to_string(conn->type), conn->state, + (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; } @@ -694,18 +867,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. */ @@ -738,12 +912,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) { @@ -759,11 +934,11 @@ run_connection_housekeeping(int i, time_t now) (!DIR_CONN_IS_SERVER(conn) && conn->timestamp_lastread + DIR_CONN_MAX_STALL < now))) { log_info(LD_DIR,"Expiring wedged directory conn (fd %d, purpose %d)", - conn->s, conn->purpose); + (int)conn->s, conn->purpose); /* 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)); @@ -780,54 +955,55 @@ 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: * mark it now. */ log_info(LD_OR, "Expiring non-used OR connection to fd %d (%s:%d) [Too old].", - conn->s, conn->address, conn->port); + (int)conn->s, conn->address, conn->port); if (conn->state == OR_CONN_STATE_CONNECTING) 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. */ log_info(LD_OR,"Expiring non-open OR connection to fd %d (%s:%d).", - conn->s,conn->address, conn->port); + (int)conn->s,conn->address, conn->port); 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].", - conn->s,conn->address, conn->port); - connection_mark_for_close(conn); - conn->hold_open_until_flushed = 1; + (int)conn->s,conn->address, conn->port); + connection_mark_and_flush(conn); } else if (!or_conn->n_circuits && now >= or_conn->timestamp_last_added_nonpadding + IDLE_OR_CONN_TIMEOUT) { log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) " - "[idle %d].", conn->s,conn->address, conn->port, + "[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) { log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL, "Expiring stuck OR connection to fd %d (%s:%d). (%d bytes to " "flush; %d seconds since last write)", - conn->s, conn->address, conn->port, - (int)buf_datalen(conn->outbuf), + (int)conn->s, conn->address, conn->port, + (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); @@ -842,7 +1018,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."); @@ -851,10 +1027,11 @@ signewnym_impl(time_t now) circuit_expire_all_dirty_circs(); addressmap_clear_transient(); - rend_cache_purge(); - rend_client_cancel_descriptor_fetches(); + rend_client_purge_state(); time_of_last_signewnym = now; signewnym_is_pending = 0; + + control_event_signal(SIGNEWNYM); } /** Perform regular maintenance tasks. This function gets run once per @@ -880,10 +1057,12 @@ 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; + const or_options_t *options = get_options(); int is_server = server_mode(options); int i; int have_dir_info; @@ -894,6 +1073,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 && @@ -922,7 +1111,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; @@ -1046,6 +1235,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; } @@ -1074,10 +1268,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; } @@ -1086,7 +1279,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(); } @@ -1117,7 +1310,7 @@ run_scheduled_events(time_t 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) { @@ -1128,7 +1321,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) { @@ -1162,7 +1355,10 @@ run_scheduled_events(time_t now) * it's not comfortable with the number of available circuits. */ /* XXXX022 If our circuit build timeout is much lower than a second, maybe - we should do this more often? */ + * we should do this more often? -NM + * It can't be lower than 1.5 seconds currently; see + * circuit_build_times_min_timeout(). -RD + */ circuit_expire_building(); /** 3b. Also look at pending streams and prune the ones that 'began' @@ -1253,6 +1449,24 @@ run_scheduled_events(time_t now) #define BRIDGE_STATUSFILE_INTERVAL (30*60) time_to_write_bridge_status_file = now+BRIDGE_STATUSFILE_INTERVAL; } + + 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; + } + + /** 11. 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. */ @@ -1272,7 +1486,10 @@ 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(); +#ifdef USE_BUFFEREVENTS + uint64_t cur_read,cur_written; +#endif + const or_options_t *options = get_options(); (void)timer; (void)arg; @@ -1283,9 +1500,15 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg) update_approx_time(now); /* the second has rolled over. check more stuff. */ + seconds_elapsed = current_second ? (int)(now - current_second) : 0; +#ifdef USE_BUFFEREVENTS + 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); +#else 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; +#endif stats_n_bytes_read += bytes_read; stats_n_bytes_written += bytes_written; if (accounting_is_enabled(options) && seconds_elapsed >= 0) @@ -1295,8 +1518,13 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg) if (seconds_elapsed > 0) connection_bucket_refill(seconds_elapsed, now); +#ifdef USE_BUFFEREVENTS + stats_prev_n_written = cur_written; + stats_prev_n_read = cur_read; +#else stats_prev_global_read_bucket = global_read_bucket; stats_prev_global_write_bucket = global_write_bucket; +#endif if (server_mode(options) && !we_are_hibernating() && @@ -1306,7 +1534,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, " @@ -1404,7 +1632,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(); @@ -1496,8 +1724,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); @@ -1628,11 +1858,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) { @@ -1640,6 +1872,7 @@ process_signal(uintptr_t sig) tor_cleanup(); exit(1); } + control_event_signal(sig); break; #ifdef SIGCHLD case SIGCHLD: @@ -1661,10 +1894,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; @@ -1700,7 +1941,7 @@ dumpstats(int severity) int i = conn_sl_idx; log(severity, LD_GENERAL, "Conn %d (socket %d) type %d (%s), state %d (%s), created %d secs ago", - i, conn->s, conn->type, conn_type_to_string(conn->type), + i, (int)conn->s, conn->type, conn_type_to_string(conn->type), conn->state, conn_state_to_string(conn->type, conn->state), (int)(now - conn->timestamp_created)); if (!connection_is_listener(conn)) { @@ -1711,13 +1952,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) { @@ -1932,7 +2173,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; @@ -2014,6 +2255,7 @@ tor_free_all(int postfork) connection_free_all(); buf_shrink_freelists(1); memarea_clear_freelist(); + nodelist_free_all(); microdesc_free_all(); if (!postfork) { config_free_all(); @@ -2045,7 +2287,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..db251356f 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,12 @@ 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); + 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..cae31fe4c 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, @@ -208,6 +246,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; } @@ -247,7 +294,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 +307,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 +340,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; @@ -390,6 +439,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 +465,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); @@ -449,7 +513,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 +555,148 @@ 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: */ +#if 0 + /* So we decide that we'll use microdescriptors iff we are not a server */ + ret = ! server_mode(options); +#else + /* We don't use microdescs for now: not enough caches are running + * 0.2.3.1-alpha */ + ret = 0; +#endif + } + 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; + 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; + 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..72e4572f9 100644 --- a/src/or/microdesc.h +++ b/src/or/microdesc.h @@ -16,7 +16,8 @@ microdesc_cache_t *get_microdesc_cache(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 +32,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..2586ce6eb 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,25 @@ 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; + } + /* 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 +1204,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 +1274,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 +1348,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 +1362,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 +1383,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 +1394,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 +1418,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 +1449,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 +1478,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 +1519,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 +1550,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 +1585,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 +1623,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 +1642,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 = ¤t_consensus->digests; - current_valid_after = current_consensus->valid_after; + if (current_ns_consensus) { + current_digests = ¤t_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 = ¤t_md_consensus->digests; + current_valid_after = current_md_consensus->valid_after; } } else { cached_dir_t *cur; @@ -1695,24 +1728,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 +1782,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 +1814,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 +1869,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 +1942,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 +1970,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 +1991,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 +2006,19 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, tor_memcmp(rs->identity_digest, router->cache_info.identity_digest, DIGEST_LEN), { +#if 0 /* 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); } +#endif }) { /* 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 +2026,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 +2045,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 +2068,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 +2076,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 +2093,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 +2126,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 +2136,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); smartlist_add(statuses, networkstatus_getinfo_helper_single(&rs)); }); @@ -2120,7 +2151,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 +2205,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 +2284,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 +2295,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 +2339,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..96b65a132 --- /dev/null +++ b/src/or/nodelist.c @@ -0,0 +1,735 @@ +/* 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) + node->md = md; + 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(); + + 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)) { + node->md = microdesc_cache_lookup_by_digest256(NULL, + rs->descriptor_digest); + } + } + + 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; +} + +/** 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; + 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_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); + } + } 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..08f11da59 --- /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_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 b9d8319ba..c9fe4ff8d 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -83,6 +83,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" @@ -384,7 +391,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 +814,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 +867,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. */ @@ -970,8 +982,9 @@ typedef struct connection_t { unsigned int proxy_state:4; /** Our socket; -1 if this connection is closed, or has no socket. */ - evutil_socket_t s; + 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 +995,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 */ @@ -1009,7 +1027,7 @@ typedef struct connection_t { /* XXXX023 move this field, and all the listener-only fields (just socket_family, I think), into a new listener_connection_t subtype. */ /** If the connection is a CONN_TYPE_AP_DNS_LISTENER, this field points - * to the evdns_server_port is uses to listen to and answer connections. */ + * 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. */ @@ -1081,10 +1099,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 ? */ @@ -1199,8 +1223,13 @@ typedef struct edge_connection_t { 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 @@ -1242,6 +1271,9 @@ typedef struct control_connection_t { /** True if we have sent a protocolinfo reply on this connection. */ unsigned int have_sent_protocolinfo:1; + /** True if we have received a takeownership command on this + * connection. */ + unsigned int is_owning_control_connection:1; /** Amount of space allocated in incoming_cmd. */ uint32_t incoming_cmd_len; @@ -1291,6 +1323,51 @@ static INLINE control_connection_t *TO_CONTROL_CONN(connection_t *c) return DOWNCAST(control_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 { ADDR_POLICY_ACCEPT=1, @@ -1454,59 +1531,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. */ @@ -1532,8 +1599,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. */ @@ -1541,7 +1609,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. */ @@ -1572,6 +1644,9 @@ 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; unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */ unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */ @@ -1593,15 +1668,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 @@ -1643,15 +1734,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? */ @@ -1765,9 +1924,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) @@ -1937,24 +2093,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 @@ -2027,15 +2192,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? */ @@ -2133,13 +2298,21 @@ 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 * in time in order to indicate that a circuit shouldn't be used for new * streams, but that it can stay alive as long as it has streams on it. * That's a kludge we should fix. + * + * XXX023 The CBT code uses this field to record when HS-related + * circuits entered certain states. This usage probably won't + * interfere with this field's primary purpose, but we should + * document it more thoroughly to make sure of that. */ time_t timestamp_dirty; @@ -2310,14 +2483,14 @@ typedef struct or_circuit_t { cell_ewma_t p_cell_ewma; } or_circuit_t; -/** Convert a circuit subtype to a circuit_t.*/ +/** Convert a circuit subtype to a circuit_t. */ #define TO_CIRCUIT(x) (&((x)->_base)) -/** Convert a circuit_t* to a pointer to the enclosing or_circuit_t. Asserts +/** Convert a circuit_t* to a pointer to the enclosing or_circuit_t. Assert * if the cast is impossible. */ static or_circuit_t *TO_OR_CIRCUIT(circuit_t *); /** Convert a circuit_t* to a pointer to the enclosing origin_circuit_t. - * Asserts if the cast is impossible. */ + * Assert if the cast is impossible. */ static origin_circuit_t *TO_ORIGIN_CIRCUIT(circuit_t *); static INLINE or_circuit_t *TO_OR_CIRCUIT(circuit_t *x) @@ -2370,6 +2543,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? */ @@ -2489,8 +2663,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? */ @@ -2519,12 +2693,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. */ @@ -2595,6 +2767,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. */ @@ -2632,7 +2807,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 @@ -2674,6 +2850,11 @@ typedef struct { int DisablePredictedCircuits; /**< Boolean: does Tor preemptively * make circuits in the background (0), * or not (1)? */ + + /** Process specifier for a controller that ‘owns’ this Tor + * instance. Tor will terminate if its owning controller does. */ + char *OwningControllerProcess; + int ShutdownWaitLength; /**< When we get a SIGINT and we're a server, how * long do we wait before exiting? */ char *SafeLogging; /**< Contains "relay", "1", "0" (meaning no scrubbing). */ @@ -2727,7 +2908,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. */ @@ -2737,6 +2920,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. */ @@ -2774,6 +2961,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; @@ -2870,11 +3060,21 @@ 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? */ @@ -2994,8 +3194,6 @@ struct socks_request_t { * every connection. */ }; -/* all the function prototypes go here */ - /********************************* circuitbuild.c **********************/ /** How many hops does a general-purpose circuit have by default? */ @@ -3408,7 +3606,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 ***************************/ @@ -3493,7 +3691,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. */ @@ -3539,6 +3737,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 @@ -3556,7 +3756,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 e48f42058..1b5408c77 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" @@ -45,7 +46,7 @@ typedef struct policy_summary_item_t { uint16_t prt_max; /**< Highest port number to accept/reject. */ uint64_t reject_count; /**< Number of IP-Addresses that are rejected to this port range. */ - int accepted:1; /** Has this port already been accepted */ + unsigned int accepted:1; /** Has this port already been accepted */ } policy_summary_item_t; /** Private networks. This list is used in two places, once to expand the @@ -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) @@ -866,15 +883,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 +1098,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 +1311,195 @@ 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_internal(addr, 0) || + tor_addr_is_null(addr) || + 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_addr_to_node_policy(uint32_t addr, uint16_t port, const node_t *node) +{ + tor_addr_t a; + tor_addr_from_ipv4h(&a, addr); + return compare_tor_addr_to_node_policy(&a, port, node); +} + +/** 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 && 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..6f3624aba 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,9 +29,9 @@ 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); @@ -38,11 +39,17 @@ 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_addr_to_node_policy(uint32_t addr, + uint16_t port, const node_t *node); +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 +64,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 9effae303..df6d0a8a5 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -24,10 +24,12 @@ #include "main.h" #include "mempool.h" #include "networkstatus.h" +#include "nodelist.h" #include "policies.h" #include "reasons.h" #include "relay.h" #include "rendcommon.h" +#include "router.h" #include "routerlist.h" #include "routerparse.h" @@ -704,7 +706,7 @@ connection_ap_process_end_not_open( edge_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; (void) layer_hint; /* unused */ @@ -712,11 +714,12 @@ connection_ap_process_end_not_open( if (rh->length > 0 && edge_reason_is_retriable(reason) && !connection_edge_is_rendezvous_stream(conn) /* avoid retry if rend */ ) { + 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) { @@ -749,10 +752,10 @@ connection_ap_process_end_not_open( (tor_inet_aton(conn->socks_request->address, &in) && !conn->chosen_exit_name))) { log_info(LD_APP, - "Exitrouter '%s' seems to be more restrictive than its exit " + "Exitrouter %s seems to be more restrictive than its exit " "policy. Not using this router as exit for now.", - exitrouter->nickname); - 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, @@ -817,7 +820,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 */ @@ -900,12 +903,8 @@ 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); return 0; @@ -982,11 +981,8 @@ 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); + log_info(LD_APP,"Got a resolve with answer %s. Rejecting.", + fmt_addr32(addr)); connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_ERROR_TRANSIENT, 0, NULL, 0, TIME_MAX); @@ -1038,6 +1034,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); @@ -1057,9 +1056,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: @@ -1126,7 +1136,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 ? @@ -1151,8 +1168,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: @@ -1359,7 +1375,7 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial, return 0; } - amount_to_process = buf_datalen(conn->_base.inbuf); + amount_to_process = connection_get_inbuf_len(TO_CONN(conn)); if (!amount_to_process) return 0; @@ -1378,7 +1394,7 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial, 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 (connection_edge_send_command(conn, RELAY_COMMAND_DATA, payload, length) < 0 ) @@ -1531,7 +1547,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; } } @@ -1542,7 +1558,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; } } @@ -1581,7 +1597,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 @@ -1994,7 +2010,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; @@ -2245,7 +2262,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; @@ -2320,13 +2337,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 " @@ -2446,7 +2463,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 77e11c2a0..b618d0fe4 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -16,16 +16,28 @@ #include "connection_edge.h" #include "directory.h" #include "main.h" +#include "nodelist.h" #include "relay.h" #include "rendclient.h" #include "rendcommon.h" #include "rephist.h" +#include "router.h" #include "routerlist.h" static extend_info_t *rend_client_get_random_intro_impl( const rend_cache_entry_t *rend_query, const int strict, const int warnings); +/** Purge all potentially remotely-detectable state held in the hidden + * service client code. Called on SIGNAL NEWNYM. */ +void +rend_client_purge_state(void) +{ + rend_cache_purge(); + rend_client_cancel_descriptor_fetches(); + rend_client_purge_last_hid_serv_requests(); +} + /** Called when we've established a circuit to an introduction point: * send the introduction request. */ void @@ -90,12 +102,13 @@ rend_client_reextend_intro_circuit(origin_circuit_t *circ) if (circ->remaining_relay_early_cells) { log_info(LD_REND, "Re-extending circ %d, this time to %s.", - circ->_base.n_circ_id, extend_info->nickname); + circ->_base.n_circ_id, + safe_str_client(extend_info_describe(extend_info))); result = circuit_extend_to_new_exit(circ, extend_info); } else { log_info(LD_REND, "Building a new introduction circuit, this time to %s.", - extend_info->nickname); + safe_str_client(extend_info_describe(extend_info))); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED); if (!circuit_launch_by_extend_info(CIRCUIT_PURPOSE_C_INTRODUCING, extend_info, @@ -132,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) { @@ -168,7 +183,8 @@ rend_client_send_introduction(origin_circuit_t *introcirc, "have a v2 rend desc with %d intro points. " "Trying a different intro point...", safe_str_client(introcirc->rend_data->onion_address), - introcirc->build_state->chosen_exit->nickname, + safe_str_client(extend_info_describe( + introcirc->build_state->chosen_exit)), smartlist_len(entry->parsed->intro_nodes)); if (rend_client_reextend_intro_circuit(introcirc)) { @@ -275,6 +291,10 @@ rend_client_send_introduction(origin_circuit_t *introcirc, /* Now, we wait for an ACK or NAK on this circuit. */ introcirc->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT; + /* Set timestamp_dirty, because circuit_expire_building expects it + * to specify when a circuit entered the _C_INTRODUCE_ACK_WAIT + * state. */ + introcirc->_base.timestamp_dirty = time(NULL); return 0; perm_err: @@ -317,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) { @@ -328,7 +349,12 @@ 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 + * _C_REND_READY_INTRO_ACKED state. */ + rendcirc->_base.timestamp_dirty = time(NULL); } else { log_info(LD_REND,"...Found no rend circ. Dropping on the floor."); } @@ -343,8 +369,8 @@ rend_client_introduction_acked(origin_circuit_t *circ, * If none remain, refetch the service descriptor. */ log_info(LD_REND, "Got nack for %s from %s...", - safe_str_client(circ->rend_data->onion_address), - circ->build_state->chosen_exit->nickname); + 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) { /* There are introduction points left. Re-extend the circuit to @@ -366,7 +392,17 @@ rend_client_introduction_acked(origin_circuit_t *circ, * 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. */ -static strmap_t *last_hid_serv_requests = NULL; +static strmap_t *last_hid_serv_requests_ = NULL; + +/** Returns last_hid_serv_requests_, initializing it to a new strmap if + * necessary. */ +static strmap_t * +get_last_hid_serv_requests(void) +{ + if (!last_hid_serv_requests_) + last_hid_serv_requests_ = strmap_new(); + return last_hid_serv_requests_; +} /** 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, @@ -380,6 +416,7 @@ lookup_last_hid_serv_request(routerstatus_t *hs_dir, char hsdir_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; char hsdir_desc_comb_id[2 * REND_DESC_ID_V2_LEN_BASE32 + 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", @@ -401,12 +438,11 @@ 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; - if (!last_hid_serv_requests) - last_hid_serv_requests = strmap_new(); + 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); ) { const char *key; @@ -423,6 +459,26 @@ directory_clean_last_hid_serv_requests(void) } } +/** 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 + * recently. */ +void +rend_client_purge_last_hid_serv_requests(void) +{ + /* Don't create the table if it doesn't exist yet (and it may very + * well not exist if the user hasn't accessed any HSes)... */ + strmap_t *old_last_hid_serv_requests = last_hid_serv_requests_; + /* ... and let get_last_hid_serv_requests re-create it for us if + * necessary. */ + last_hid_serv_requests_ = NULL; + + if (old_last_hid_serv_requests != NULL) { + log_info(LD_REND, "Purging client last-HS-desc-request-time table"); + strmap_free(old_last_hid_serv_requests, _tor_free); + } +} + /** 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 @@ -449,12 +505,14 @@ 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)) + !router_get_by_id_digest(dir->identity_digest)) SMARTLIST_DEL_CURRENT(responsible_dirs, dir); }); @@ -497,12 +555,12 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query) log_info(LD_REND, "Sending fetch request for v2 descriptor for " "service '%s' with descriptor ID '%s', auth type %d, " "and descriptor cookie '%s' to hidden service " - "directory '%s' on port %d.", + "directory %s", rend_query->onion_address, desc_id_base32, rend_query->auth_type, (rend_query->auth_type == REND_NO_AUTH ? "[none]" : - escaped_safe_str_client(descriptor_cookie_base64)), - hs_dir->nickname, hs_dir->dir_port); + escaped_safe_str_client(descriptor_cookie_base64)), + routerstatus_describe(hs_dir)); return 1; } @@ -674,6 +732,9 @@ rend_client_rendezvous_acked(origin_circuit_t *circ, const uint8_t *request, log_info(LD_REND,"Got rendezvous ack. This circuit is now ready for " "rendezvous."); circ->_base.purpose = CIRCUIT_PURPOSE_C_REND_READY; + /* Set timestamp_dirty, because circuit_expire_building expects it + * to specify when a circuit entered the _C_REND_READY state. */ + circ->_base.timestamp_dirty = time(NULL); /* XXXX023 This is a pretty brute-force approach. It'd be better to * attach only the connections that are waiting on this circuit, rather * than trying to attach them all. See comments bug 743. */ @@ -846,8 +907,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; @@ -873,18 +933,19 @@ 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 && @@ -953,7 +1014,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 6910c1a97..1893fd952 100644 --- a/src/or/rendclient.h +++ b/src/or/rendclient.h @@ -12,6 +12,8 @@ #ifndef _TOR_RENDCLIENT_H #define _TOR_RENDCLIENT_H +void rend_client_purge_state(void); + void rend_client_introcirc_has_opened(origin_circuit_t *circ); void rend_client_rendcirc_has_opened(origin_circuit_t *circ); int rend_client_introduction_acked(origin_circuit_t *circ, @@ -19,6 +21,7 @@ int rend_client_introduction_acked(origin_circuit_t *circ, size_t request_len); 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); int rend_client_rendezvous_acked(origin_circuit_t *circ, @@ -34,7 +37,7 @@ 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 4d4a90f61..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; @@ -839,18 +838,20 @@ rend_cache_clean(void) void rend_cache_purge(void) { - if (rend_cache) + if (rend_cache) { + log_info(LD_REND, "Purging client/v0-HS-authority HS descriptor cache"); strmap_free(rend_cache, _rend_cache_entry_free); + } rend_cache = strmap_new(); } /** 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; @@ -982,15 +983,10 @@ rend_cache_lookup_v2_desc_as_dir(const char *desc_id, const char **desc) tor_assert(rend_cache_v2_dir); if (base32_decode(desc_id_digest, DIGEST_LEN, desc_id, REND_DESC_ID_V2_LEN_BASE32) < 0) { - log_warn(LD_REND, "Descriptor ID contains illegal characters: %s", - safe_str(desc_id)); - return -1; - } - /* Determine if we are responsible. */ - if (hid_serv_responsible_for_desc_id(desc_id_digest) < 0) { - log_info(LD_REND, "Could not answer fetch request for v2 descriptor; " - "either we are no hidden service directory, or we are " - "not responsible for the requested ID."); + log_fn(LOG_PROTOCOL_WARN, LD_REND, + "Rejecting v2 rendezvous descriptor request -- descriptor ID " + "contains illegal characters: %s", + safe_str(desc_id)); return -1; } /* Lookup descriptor and return. */ @@ -1044,6 +1040,7 @@ rend_cache_store(const char *desc, size_t desc_len, int published, log_warn(LD_REND, "Received service descriptor for service ID %s; " "expected descriptor for service ID %s.", query, safe_str(service_id)); + rend_service_descriptor_free(parsed); return -2; } now = time(NULL); 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 35e8b9057..4413ae9d8 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" @@ -181,6 +182,31 @@ rend_add_service(rend_service_t *service) log_warn(LD_CONFIG, "Hidden service with no ports configured; ignoring."); rend_service_free(service); } else { + int dupe = 0; + /* XXX This duplicate check has two problems: + * + * a) It's O(n^2), but the same comment from the bottom of + * rend_config_services() should apply. + * + * b) We only compare directory paths as strings, so we can't + * detect two distinct paths that specify the same directory + * (which can arise from symlinks, case-insensitivity, bind + * mounts, etc.). + * + * It also can't detect that two separate Tor instances are trying + * to use the same HiddenServiceDir; for that, we would need a + * lock file. But this is enough to detect a simple mistake that + * at least one person has actually made. + */ + SMARTLIST_FOREACH(rend_service_list, rend_service_t*, ptr, + dupe = dupe || + !strcmp(ptr->directory, service->directory)); + if (dupe) { + log_warn(LD_REND, "Another hidden service is already configured for " + "directory %s, ignoring.", service->directory); + rend_service_free(service); + return; + } smartlist_add(rend_service_list, service); log_debug(LD_REND,"Configuring service with directory \"%s\"", service->directory); @@ -266,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; @@ -474,7 +500,8 @@ rend_config_services(or_options_t *options, int validate_only) if (keep_it) continue; log_info(LD_REND, "Closing intro point %s for service %s.", - safe_str_client(oc->build_state->chosen_exit->nickname), + safe_str_client(extend_info_describe( + oc->build_state->chosen_exit)), oc->rend_data->onion_address); circuit_mark_for_close(circ, END_CIRC_REASON_FINISHED); /* XXXX Is there another reason we should use here? */ @@ -543,7 +570,7 @@ rend_service_load_keys(void) s->directory); /* Check/create directory */ - if (check_private_dir(s->directory, CPD_CREATE) < 0) + if (check_private_dir(s->directory, CPD_CREATE, get_options()->User) < 0) return -1; /* Load key */ @@ -876,8 +903,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, @@ -1005,7 +1033,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; @@ -1032,8 +1060,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? */ @@ -1041,7 +1069,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) { @@ -1146,7 +1174,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, if (!launched) { /* give up */ log_warn(LD_REND, "Giving up launching first hop of circuit to rendezvous " "point %s for service %s.", - escaped_safe_str_client(extend_info->nickname), + safe_str_client(extend_info_describe(extend_info)), serviceid); reason = END_CIRC_REASON_CONNECTFAILED; goto err; @@ -1154,7 +1182,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, log_info(LD_REND, "Accepted intro; launching circuit to %s " "(cookie %s) for service %s.", - escaped_safe_str_client(extend_info->nickname), + safe_str_client(extend_info_describe(extend_info)), hexcookie, serviceid); tor_assert(launched->build_state); /* Fill in the circuit's state. */ @@ -1206,7 +1234,8 @@ rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc) "Attempt to build circuit to %s for rendezvous has failed " "too many times or expired; giving up.", oldcirc->build_state ? - oldcirc->build_state->chosen_exit->nickname : "*unknown*"); + safe_str(extend_info_describe(oldcirc->build_state->chosen_exit)) + : "*unknown*"); return; } @@ -1220,7 +1249,7 @@ rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc) } log_info(LD_REND,"Reattempting rendezvous circuit to '%s'", - oldstate->chosen_exit->nickname); + safe_str(extend_info_describe(oldstate->chosen_exit))); newcirc = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_CONNECT_REND, oldstate->chosen_exit, @@ -1228,7 +1257,7 @@ rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc) if (!newcirc) { log_warn(LD_REND,"Couldn't relaunch rendezvous circuit to '%s'.", - oldstate->chosen_exit->nickname); + safe_str(extend_info_describe(oldstate->chosen_exit))); return; } newstate = newcirc->build_state; @@ -1252,7 +1281,7 @@ rend_service_launch_establish_intro(rend_service_t *service, log_info(LD_REND, "Launching circuit to introduction point %s for service %s", - escaped_safe_str_client(intro->extend_info->nickname), + safe_str_client(extend_info_describe(intro->extend_info)), service->service_id); rep_hist_note_used_internal(time(NULL), 1, 0); @@ -1265,7 +1294,7 @@ rend_service_launch_establish_intro(rend_service_t *service, if (!launched) { log_info(LD_REND, "Can't launch circuit to establish introduction at %s.", - escaped_safe_str_client(intro->extend_info->nickname)); + safe_str_client(extend_info_describe(intro->extend_info))); return -1; } @@ -1331,6 +1360,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); @@ -1349,7 +1379,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, @@ -1473,6 +1503,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); @@ -1606,11 +1637,11 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc, 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)) { + if (!router_get_by_id_digest(hs_dir->identity_digest)) { log_info(LD_REND, "Not sending publish request for v2 descriptor to " - "hidden service directory '%s'; we don't have its " + "hidden service directory %s; we don't have its " "router descriptor. Queuing for later upload.", - hs_dir->nickname); + safe_str_client(routerstatus_describe(hs_dir))); failed_upload = -1; continue; } @@ -1783,19 +1814,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); @@ -1815,10 +1846,11 @@ 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.", - intro->extend_info->nickname, service->service_id); + safe_str_client(extend_info_describe(intro->extend_info)), + safe_str_client(service->service_id)); if (service->desc) { SMARTLIST_FOREACH(service->desc->intro_nodes, rend_intro_point_t *, dintro, { @@ -1835,8 +1867,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 @@ -1865,26 +1897,27 @@ 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.", - router->nickname, service->service_id); + safe_str_client(node_describe(node)), + safe_str_client(service->service_id)); } /* If there's no need to launch new circuits, stop here. */ @@ -1897,11 +1930,12 @@ rend_services_introduce(void) r = rend_service_launch_establish_intro(service, intro); if (r<0) { log_warn(LD_REND, "Error launching circuit to node %s for service %s.", - intro->extend_info->nickname, service->service_id); + safe_str_client(extend_info_describe(intro->extend_info)), + safe_str_client(service->service_id)); } } } - 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 8cddd2b5e..cd74f1b72 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" @@ -634,6 +635,7 @@ rep_hist_dump_stats(time_t now, int severity) digestmap_iter_t *orhist_it; const char *name1, *name2, *digest1, *digest2; char hexdigest1[HEX_DIGEST_LEN+1]; + char hexdigest2[HEX_DIGEST_LEN+1]; or_history_t *or_history; link_history_t *link_history; void *or_history_p, *link_history_p; @@ -642,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); @@ -656,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); @@ -687,14 +689,17 @@ 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)"; link_history = (link_history_t*) link_history_p; - ret = tor_snprintf(buffer+len, 2048-len, "%s(%ld/%ld); ", name2, + base16_encode(hexdigest2, sizeof(hexdigest2), digest2, DIGEST_LEN); + ret = tor_snprintf(buffer+len, 2048-len, "%s [%s](%ld/%ld); ", + name2, + hexdigest2, link_history->n_extend_ok, link_history->n_extend_ok+link_history->n_extend_fail); if (ret<0) @@ -819,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. */ @@ -934,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); @@ -1470,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) { @@ -1766,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 @@ -1778,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 @@ -1796,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 */ } @@ -1806,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>. @@ -1821,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); } @@ -1847,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 @@ -2112,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) { @@ -2303,7 +2297,7 @@ rep_hist_exit_stats_write(time_t now) /* Try to write to disk. */ statsdir = get_datadir_fname("stats"); - if (check_private_dir(statsdir, CPD_CREATE) < 0) { + if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) { log_warn(LD_HIST, "Unable to create stats/ directory!"); goto done; } @@ -2387,8 +2381,8 @@ rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval) 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); @@ -2397,8 +2391,7 @@ rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval) stat = tor_malloc_zero(sizeof(circ_buffer_stats_t)); stat->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 = interval_length == 0 ? 0.0 : - (double) orcirc->total_cell_waiting_time / + stat->mean_num_cells_in_queue = (double) orcirc->total_cell_waiting_time / (double) interval_length / 1000.0 / 2.0; stat->mean_time_cells_in_queue = (double) orcirc->total_cell_waiting_time / @@ -2448,8 +2441,8 @@ rep_hist_buffer_stats_write(time_t now) int processed_cells[SHARES], circs_in_share[SHARES], number_of_circuits, i; double queued_cells[SHARES], time_in_queue[SHARES]; - smartlist_t *str_build = smartlist_create(); - char *str = NULL, *buf=NULL; + smartlist_t *str_build = NULL; + char *str = NULL, *buf = NULL; circuit_t *circ; if (!start_of_buffer_stats_interval) @@ -2457,6 +2450,8 @@ rep_hist_buffer_stats_write(time_t now) if (start_of_buffer_stats_interval + WRITE_STATS_INTERVAL > now) goto done; /* Not ready to write */ + str_build = smartlist_create(); + /* add current circuits to stats */ for (circ = _circuit_get_global_list(); circ; circ = circ->next) rep_hist_buffer_stats_add_circ(circ, now); @@ -2492,7 +2487,7 @@ rep_hist_buffer_stats_write(time_t now) smartlist_clear(circuits_for_buffer_stats); /* write to file */ statsdir = get_datadir_fname("stats"); - if (check_private_dir(statsdir, CPD_CREATE) < 0) + 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, @@ -2557,6 +2552,227 @@ rep_hist_buffer_stats_write(time_t now) 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); + 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 * bandwidth history arrays, by the port history, or by statistics . */ void @@ -2571,6 +2787,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..5748748a8 100644 --- a/src/or/rephist.h +++ b/src/or/rephist.h @@ -78,5 +78,13 @@ void rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t rep_hist_buffer_stats_write(time_t now); void rep_hist_buffer_stats_term(void); +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 f6728aac9..eaad57bb9 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" @@ -154,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)); } } @@ -498,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; @@ -538,12 +540,12 @@ init_keys(void) return 0; } /* Make sure DataDirectory exists, and is private. */ - if (check_private_dir(options->DataDirectory, CPD_CREATE)) { + if (check_private_dir(options->DataDirectory, CPD_CREATE, options->User)) { return -1; } /* Check the key directory. */ keydir = get_datadir_fname("keys"); - if (check_private_dir(keydir, CPD_CREATE)) { + if (check_private_dir(keydir, CPD_CREATE, options->User)) { tor_free(keydir); return -1; } @@ -700,16 +702,17 @@ 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) { ds = add_trusted_dir_server(options->Nickname, NULL, - router_get_advertised_dir_port(options), + router_get_advertised_dir_port(options, 0), router_get_advertised_or_port(options), digest, v3_digest, @@ -726,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."); @@ -765,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; } @@ -774,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() || @@ -789,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; @@ -807,6 +810,8 @@ decide_to_advertise_dirport(or_options_t *options, uint16_t dir_port) return 0; if (!check_whether_dirport_reachable()) return 0; + if (!router_get_advertised_dir_port(options, dir_port)) + return 0; /* Section two: reasons to publish or not publish that the user * might find surprising. These are generally config options that @@ -852,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. */ @@ -879,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); @@ -906,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"); @@ -924,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."); @@ -970,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; } @@ -978,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; } @@ -986,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; } @@ -994,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 || @@ -1009,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); @@ -1018,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); @@ -1033,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; @@ -1043,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); } @@ -1051,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; } @@ -1059,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); @@ -1068,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); @@ -1078,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); } @@ -1110,7 +1118,7 @@ set_server_advertised(int s) /** Return true iff we are trying to be a socks proxy. */ int -proxy_mode(or_options_t *options) +proxy_mode(const or_options_t *options) { return (options->SocksPort != 0 || options->TransPort != 0 || @@ -1131,16 +1139,18 @@ 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; if (authdir_mode(options)) return 1; + if (!router_get_advertised_or_port(options)) + return 0; return check_whether_orport_reachable(); } @@ -1174,7 +1184,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); @@ -1185,12 +1195,16 @@ router_get_advertised_or_port(or_options_t *options) return options->ORPort; } -/** Return the port that we should advertise as our DirPort; this is either - * the one configured in the DirPort option, or the one we actually bound to - * if DirPort is "auto". */ +/** Return the port that we should advertise as our DirPort; + * this is one of three possibilities: + * The one that is passed as <b>dirport</b> if the DirPort option is 0, or + * the one configured in the DirPort option, + * or the one we actually bound to if DirPort is "auto". */ uint16_t -router_get_advertised_dir_port(or_options_t *options) +router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport) { + if (!options->DirPort) + return dirport; if (options->DirPort == CFG_AUTO_PORT) { connection_t *c = connection_get_by_type(CONN_TYPE_DIR_LISTENER); if (c) @@ -1221,11 +1235,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) { @@ -1233,7 +1247,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; @@ -1254,7 +1268,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); @@ -1319,7 +1333,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); } @@ -1338,7 +1352,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())) @@ -1388,10 +1402,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."); @@ -1401,9 +1413,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; } @@ -1419,12 +1429,13 @@ 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; - if (router_pick_published_address(options, &addr) < 0) { + if (router_pick_published_address(options, &addr) < 0 || + router_get_advertised_or_port(options) == 0) { /* Stop trying to rebuild our descriptor every second. We'll * learn that it's time to try again when ip_address_changed() * marks it dirty. */ @@ -1440,7 +1451,7 @@ router_rebuild_descriptor(int force) ri->nickname = tor_strdup(options->Nickname); ri->addr = addr; ri->or_port = router_get_advertised_or_port(options); - ri->dir_port = router_get_advertised_dir_port(options); + ri->dir_port = router_get_advertised_dir_port(options, 0); ri->cache_info.published_on = time(NULL); ri->onion_pkey = crypto_pk_dup_key(get_onion_key()); /* must invoke from * main thread */ @@ -1472,13 +1483,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) @@ -1487,13 +1497,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) && @@ -1513,19 +1522,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); @@ -1586,8 +1597,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)); } @@ -1682,7 +1691,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) @@ -1714,7 +1723,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)) { @@ -1813,7 +1822,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)) { @@ -2055,7 +2064,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]; @@ -2079,6 +2088,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 && @@ -2101,6 +2116,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) { @@ -2229,6 +2249,186 @@ is_legal_hexdigest(const char *s) strspn(s,HEX_CHARACTERS)==HEX_DIGEST_LEN); } +/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to + * hold a human-readable description of a node with identity digest + * <b>id_digest</b>, named-status <b>is_named</b>, nickname <b>nickname</b>, + * and address <b>addr</b> or <b>addr32h</b>. + * + * The <b>nickname</b> and <b>addr</b> fields are optional and may be set to + * NULL. The <b>addr32h</b> field is optional and may be set to 0. + * + * Return a pointer to the front of <b>buf</b>. + */ +const char * +format_node_description(char *buf, + const char *id_digest, + int is_named, + const char *nickname, + const tor_addr_t *addr, + uint32_t addr32h) +{ + char *cp; + + if (!buf) + return "<NULL BUFFER>"; + + buf[0] = '$'; + base16_encode(buf+1, HEX_DIGEST_LEN+1, id_digest, DIGEST_LEN); + cp = buf+1+HEX_DIGEST_LEN; + if (nickname) { + buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~'; + strlcpy(buf+1+HEX_DIGEST_LEN+1, nickname, MAX_NICKNAME_LEN+1); + cp += strlen(cp); + } + if (addr32h || addr) { + memcpy(cp, " at ", 4); + cp += 4; + if (addr) { + tor_addr_to_str(cp, addr, TOR_ADDR_BUF_LEN, 0); + } else { + struct in_addr in; + in.s_addr = htonl(addr32h); + tor_inet_ntoa(&in, cp, INET_NTOA_BUF_LEN); + } + } + return buf; +} + +/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to + * hold a human-readable description of <b>ri</b>. + * + * + * Return a pointer to the front of <b>buf</b>. + */ +const char * +router_get_description(char *buf, const routerinfo_t *ri) +{ + if (!ri) + return "<null>"; + return format_node_description(buf, + ri->cache_info.identity_digest, + 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>. + */ +const char * +routerstatus_get_description(char *buf, const routerstatus_t *rs) +{ + if (!rs) + return "<null>"; + return format_node_description(buf, + rs->identity_digest, + rs->is_named, + rs->nickname, + NULL, + rs->addr); +} + +/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to + * hold a human-readable description of <b>ei</b>. + * + * Return a pointer to the front of <b>buf</b>. + */ +const char * +extend_info_get_description(char *buf, const extend_info_t *ei) +{ + if (!ei) + return "<null>"; + return format_node_description(buf, + ei->identity_digest, + 0, + ei->nickname, + &ei->addr, + 0); +} + +/** Return a human-readable description of the routerinfo_t <b>ri</b>. + * + * This function is not thread-safe. Each call to this function invalidates + * previous values returned by this function. + */ +const char * +router_describe(const routerinfo_t *ri) +{ + static char buf[NODE_DESC_BUF_LEN]; + 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 + * previous values returned by this function. + */ +const char * +routerstatus_describe(const routerstatus_t *rs) +{ + static char buf[NODE_DESC_BUF_LEN]; + return routerstatus_get_description(buf, rs); +} + +/** Return a human-readable description of the extend_info_t <b>ri</b>. + * + * This function is not thread-safe. Each call to this function invalidates + * previous values returned by this function. + */ +const char * +extend_info_describe(const extend_info_t *ei) +{ + static char buf[NODE_DESC_BUF_LEN]; + return extend_info_get_description(buf, ei); +} + /** Set <b>buf</b> (which must have MAX_VERBOSE_NICKNAME_LEN+1 bytes) to the * verbose representation of the identity of <b>router</b>. The format is: * A dollar sign. @@ -2239,10 +2439,15 @@ is_legal_hexdigest(const char *s) 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 95c0a34e2..f6d3c1233 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -39,26 +39,27 @@ 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); @@ -69,14 +70,14 @@ 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); 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); @@ -85,6 +86,30 @@ int extrainfo_dump_to_string(char **s, extrainfo_t *extrainfo, int is_legal_nickname(const char *s); int is_legal_nickname_or_hexdigest(const char *s); int is_legal_hexdigest(const char *s); + +/** + * Longest allowed output of format_node_description, plus 1 character for + * NUL. This allows space for: + * "$FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF~xxxxxxxxxxxxxxxxxxx at" + * " [ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255]" + * plus a terminating NUL. + */ +#define NODE_DESC_BUF_LEN (MAX_VERBOSE_NICKNAME_LEN+4+TOR_ADDR_BUF_LEN) +const char *format_node_description(char *buf, + const char *id_digest, + int is_named, + const char *nickname, + const tor_addr_t *addr, + uint32_t addr32h); +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); + void router_get_verbose_nickname(char *buf, const routerinfo_t *router); void routerstatus_get_verbose_nickname(char *buf, const routerstatus_t *router); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index a3d9b78ee..15f643cf7 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)) { + 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 && 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,25 +1347,14 @@ 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); -} - -/** 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>. - */ -static void -routerlist_add_network_family(smartlist_t *sl, routerinfo_t *router) -{ - SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, r, - { - if (router != r && routers_in_same_network_family(router, r)) - smartlist_add(sl, r); - }); + /* XXXX MOVE ? */ + return 0 == tor_addr_compare_masked(a1, a2, 16, CMP_SEMANTIC); } /** Add all the family of <b>router</b> to the smartlist <b>sl</b>. @@ -1352,122 +1362,132 @@ routerlist_add_network_family(smartlist_t *sl, routerinfo_t *router) * or pick more than one relay from a family for our entry guard list. */ void -routerlist_add_family(smartlist_t *sl, routerinfo_t *router) +nodelist_add_node_family(smartlist_t *sl, const node_t *node) { - routerinfo_t *r; - config_line_t *cl; - or_options_t *options = get_options(); + /* XXXX MOVE */ + const smartlist_t *all_nodes = nodelist_get_list(); + const smartlist_t *declared_family; + const or_options_t *options = get_options(); - /* First, add any routers with similar network addresses. */ - if (options->EnforceDistinctSubnets) - routerlist_add_network_family(sl, router); + tor_assert(node); - if (router->declared_family) { - /* Add every r such that router declares familyness with r, and r + declared_family = node_get_declared_family(node); + + /* First, add any nodes with similar network addresses. */ + if (options->EnforceDistinctSubnets) { + tor_addr_t node_addr; + node_get_addr(node, &node_addr); + + 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); + } + + /* 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); + } + }); + } +} + +/** Given a <b>router</b>, add every node_t in its family to <b>sl</b>. + * + * Note the type mismatch: This function takes a routerinfo, but adds nodes + * to the smartlist! + */ +static void +routerlist_add_nodes_in_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_family(sl, node); } -/** Return true iff r is named by some nickname in <b>lst</b>. */ +/** 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 +1495,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 +1514,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 +1559,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 +1573,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 +1591,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 +1606,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 +1620,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 +1662,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 +1675,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 +1771,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 +1787,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,11 +1808,11 @@ 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; @@ -1857,12 +1860,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 +1872,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 +1917,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 +1964,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) { @@ -2125,40 +2108,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 +2136,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 +2165,30 @@ 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); + const node_t *me = node_get_by_id(r->cache_info.identity_digest); + if (me) + smartlist_add(excludednodes, (void *)me); + routerlist_add_nodes_in_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 +2211,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 +2302,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 +2315,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 +2397,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 +2417,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 +2430,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 +2446,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 +2498,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 +2522,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 +2580,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 +2629,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 +2637,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 +2690,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 +2704,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 +2717,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 +2822,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 +2844,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 +2865,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 +2910,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 +2950,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 +3063,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 +3073,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 +3222,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) { - log_debug(LD_DIR,"Marking router '%s/%s' as %s.", - router->nickname, router->address, up ? "up" : "down"); - if (!up && router_is_me(router) && !we_are_hibernating()) + node = node_get_mutable_by_id(digest); + if (node) { +#if 0 + log_debug(LD_DIR,"Marking router %s as %s.", + 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,7 +3269,7 @@ 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; @@ -3265,7 +3284,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, @@ -3283,11 +3302,12 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, router->purpose == ROUTER_PURPOSE_BRIDGE && !was_bridge) { log_info(LD_DIR, "Replacing non-bridge descriptor with bridge " - "descriptor for router '%s'", router->nickname); + "descriptor for router %s", + router_describe(router)); } else { log_info(LD_DIR, - "Dropping descriptor that we already have for router '%s'", - router->nickname); + "Dropping descriptor that we already have for router %s", + router_describe(router)); *msg = "Router descriptor was not new."; routerinfo_free(router); return ROUTER_WAS_NOT_NEW; @@ -3296,12 +3316,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. */ @@ -3311,8 +3331,8 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, /* We asked for it, so some networkstatus must have listed it when we * did. Save it if we're a cache in case somebody else asks for it. */ log_info(LD_DIR, - "Received a no-longer-recognized descriptor for router '%s'", - router->nickname); + "Received a no-longer-recognized descriptor for router %s", + router_describe(router)); *msg = "Router descriptor is not referenced by any network-status."; /* Only journal this desc if we'll be serving it. */ @@ -3328,14 +3348,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)) { @@ -3363,8 +3384,9 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, if (router->purpose == ROUTER_PURPOSE_BRIDGE && from_cache && !authdir_mode_bridge(options) && !routerinfo_is_a_configured_bridge(router)) { - log_info(LD_DIR, "Dropping bridge descriptor for '%s' because we have " - "no bridge configured at that address.", router->nickname); + log_info(LD_DIR, "Dropping bridge descriptor for %s because we have " + "no bridge configured at that address.", + safe_str_client(router_describe(router))); *msg = "Router descriptor was not a configured bridge."; routerinfo_free(router); return ROUTER_WAS_NOT_WANTED; @@ -3375,8 +3397,8 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, if (!in_consensus && (router->cache_info.published_on <= old_router->cache_info.published_on)) { /* Same key, but old. This one is not listed in the consensus. */ - log_debug(LD_DIR, "Not-new descriptor for router '%s'", - router->nickname); + log_debug(LD_DIR, "Not-new descriptor for router %s", + router_describe(router)); /* Only journal this desc if we'll be serving it. */ if (!from_cache && should_cache_old_descriptors()) signed_desc_append_to_journal(&router->cache_info, @@ -3386,9 +3408,8 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, return ROUTER_WAS_NOT_NEW; } else { /* Same key, and either new, or listed in the consensus. */ - log_debug(LD_DIR, "Replacing entry for router '%s/%s' [%s]", - router->nickname, old_router->nickname, - hex_str(id_digest,DIGEST_LEN)); + log_debug(LD_DIR, "Replacing entry for router %s", + router_describe(router)); if (routers_have_same_or_addr(router, old_router)) { /* these carry over when the address and orport are unchanged. */ router->last_reachable = old_router->last_reachable; @@ -3664,8 +3685,8 @@ routerlist_remove_old_routers(void) /* Too old: remove it. (If we're a cache, just move it into * old_routers.) */ log_info(LD_DIR, - "Forgetting obsolete (too old) routerinfo for router '%s'", - router->nickname); + "Forgetting obsolete (too old) routerinfo for router %s", + router_describe(router)); routerlist_remove(routerlist, router, 1, now); i--; } @@ -3949,7 +3970,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(); @@ -3973,6 +3994,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 @@ -3981,34 +4012,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(uint32_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_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; } @@ -4021,7 +4052,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; @@ -4056,7 +4087,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); @@ -4135,7 +4166,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; } @@ -4143,7 +4174,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) @@ -4151,20 +4184,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); @@ -4184,13 +4220,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) @@ -4198,6 +4242,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) @@ -4205,15 +4263,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); @@ -4234,9 +4296,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; @@ -4260,6 +4323,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 @@ -4274,35 +4338,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); } } } @@ -4329,12 +4407,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; @@ -4349,11 +4434,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; } } @@ -4369,7 +4454,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)) { @@ -4511,7 +4596,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(); @@ -4539,15 +4624,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 @@ -4580,17 +4664,19 @@ 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); log_info(LD_DIR, "Learned about %s (%s vs %s) from %s's vote (%s)", - rs->nickname, time_bufnew, + routerstatus_describe(rs), + time_bufnew, oldrouter ? time_bufold : "none", 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)) { @@ -4622,7 +4708,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: @@ -4636,27 +4723,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, @@ -4665,11 +4745,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; @@ -4697,7 +4794,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; @@ -4791,23 +4888,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); } @@ -4821,7 +4926,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) @@ -4849,16 +4954,16 @@ 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()); 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; @@ -4937,7 +5042,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, @@ -4961,7 +5066,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; @@ -4969,7 +5074,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; } @@ -4988,7 +5093,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)) @@ -5043,7 +5147,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) { @@ -5051,7 +5156,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."; @@ -5116,7 +5221,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; @@ -5206,7 +5311,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; @@ -5308,38 +5413,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. */ @@ -5428,7 +5501,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); @@ -5441,7 +5514,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>. */ @@ -5491,11 +5564,10 @@ 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 (nickname && strmap_get_lc(set->names, nickname)) return 4; if (id_digest && digestmap_get(set->digests, id_digest)) @@ -5523,13 +5595,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); @@ -5538,13 +5611,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); @@ -5553,50 +5628,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 @@ -5605,40 +5689,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); } }); } @@ -5704,18 +5788,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 @@ -5758,7 +5847,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) { @@ -5774,7 +5863,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..3a8af6fd9 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,51 @@ 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); +void routerlist_add_family(smartlist_t *sl, const routerinfo_t *router); 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 +130,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(uint32_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 +202,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 ce98a47b6..d1b2cd0fb 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 ), @@ -1210,7 +1208,8 @@ router_parse_list_from_string(const char **s, const char *eos, prepend_annotations); if (router) { log_debug(LD_DIR, "Read router '%s', purpose '%s'", - router->nickname, router_purpose_to_string(router->purpose)); + router_describe(router), + router_purpose_to_string(router->purpose)); signed_desc = &router->cache_info; elt = router; } @@ -1357,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; @@ -1503,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 " @@ -1543,10 +1534,10 @@ router_parse_entry_from_string(const char *s, const char *end, } } - if ((tok = find_opt_by_keyword(tokens, K_CACHES_EXTRA_INFO))) + if (find_opt_by_keyword(tokens, K_CACHES_EXTRA_INFO)) router->caches_extra_info = 1; - if ((tok = find_opt_by_keyword(tokens, K_ALLOW_SINGLE_HOP_EXITS))) + if (find_opt_by_keyword(tokens, K_ALLOW_SINGLE_HOP_EXITS)) router->allow_single_hop_exits = 1; if ((tok = find_opt_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) { @@ -1559,7 +1550,7 @@ router_parse_entry_from_string(const char *s, const char *end, } } - if ((tok = find_opt_by_keyword(tokens, K_HIDDEN_SERVICE_DIR))) { + if (find_opt_by_keyword(tokens, K_HIDDEN_SERVICE_DIR)) { router->wants_to_be_hs_dir = 1; } @@ -1574,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; @@ -1975,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); @@ -1987,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 { @@ -2069,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")) @@ -2100,6 +2091,7 @@ 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; } else { rs->version_supports_begindir = tor_version_as_new_as(tok->args[0], "0.2.0.1-alpha"); @@ -2109,6 +2101,14 @@ 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"); } if (vote_rs) { vote_rs->version = tor_strdup(tok->args[0]); @@ -2171,6 +2171,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)) @@ -2493,7 +2503,7 @@ networkstatus_verify_bw_weights(networkstatus_t *ns) } } else { log_warn(LD_BUG, "Missing consensus bandwidth for router %s", - rs->nickname); + routerstatus_describe(rs)); } } SMARTLIST_FOREACH_END(rs); @@ -3502,10 +3512,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; } }); @@ -3764,9 +3774,9 @@ token_check_object(memarea_t *area, const char *kwd, break; case NEED_KEY_1024: /* There must be a 1024-bit public key. */ case NEED_SKEY_1024: /* There must be a 1024-bit private key. */ - if (tok->key && crypto_pk_keysize(tok->key) != PK_BYTES) { + if (tok->key && crypto_pk_num_bits(tok->key) != PK_BYTES*8) { tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits", - kwd, (int)crypto_pk_keysize(tok->key)); + kwd, crypto_pk_num_bits(tok->key)); RET_ERR(ebuf); } /* fall through */ @@ -4358,7 +4368,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..acb8ba414 --- /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 pushed %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/test/Makefile.am b/src/test/Makefile.am index 546fa2f4b..852715079 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)\"" \ @@ -8,16 +8,17 @@ AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ -I"$(top_srcdir)/src/or" # -L flags need to go in LDFLAGS. -l flags need to go in LDADD. -# This seems to matter nowhere but on windows, but I assure you that it +# 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. 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_util.c \ tinytest.c @@ -25,6 +26,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..ca52750c2 --- /dev/null +++ b/src/test/test-child.c @@ -0,0 +1,18 @@ +#include <stdio.h> + +/** 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, "DONE\n"); + + return 0; +} + diff --git a/src/test/test.c b/src/test/test.c index 9b24a99b5..02d238e26 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*/ @@ -566,6 +582,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 +595,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 */ @@ -1053,8 +1074,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); @@ -1089,7 +1110,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 +1156,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 +1166,41 @@ 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); done: tor_free(s); @@ -1203,6 +1260,7 @@ 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[]; static struct testgroup_t testgroups[] = { { "", test_array }, @@ -1211,6 +1269,7 @@ static struct testgroup_t testgroups[] = { { "container/", container_tests }, { "util/", util_tests }, { "dir/", dir_tests }, + { "dir/md/", microdesc_tests }, END_OF_GROUPS }; @@ -1259,7 +1318,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 6db4ee248..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 @@ -436,13 +438,16 @@ test_addr_ip6_helpers(void) /* test tor_addr_parse_mask_ports */ test_addr_mask_ports_parse("[::f]/17:47-95", AF_INET6, 0, 0, 0, 0x0000000f, 17, 47, 95); + test_streq(p1, "::f"); //test_addr_parse("[::fefe:4.1.1.7/120]:999-1000"); //test_addr_parse_check("::fefe:401:107", 120, 999, 1000); test_addr_mask_ports_parse("[::ffff:4.1.1.7]/120:443", AF_INET6, 0, 0, 0x0000ffff, 0x04010107, 120, 443, 443); + test_streq(p1, "::ffff:4.1.1.7"); test_addr_mask_ports_parse("[abcd:2::44a:0]:2-65000", AF_INET6, 0xabcd0002, 0, 0, 0x044a0000, 128, 2, 65000); + test_streq(p1, "abcd:2::44a:0"); r=tor_addr_parse_mask_ports("[fefef::]/112", &t1, NULL, NULL, NULL); test_assert(r == -1); r=tor_addr_parse_mask_ports("efef::/112", &t1, NULL, NULL, NULL); diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 781081a4a..dca0d3a28 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -69,7 +69,7 @@ test_crypto_rng(void) uint64_t big; char *host; j = crypto_rand_int(100); - if (i < 0 || i >= 100) + if (j < 0 || j >= 100) allok = 0; big = crypto_rand_uint64(U64_LITERAL(1)<<40); if (big >= (U64_LITERAL(1)<<40)) @@ -240,11 +240,13 @@ test_crypto_sha(void) /* Test SHA-1 with a test vector from the specification. */ i = crypto_digest(data, "abc", 3); test_memeq_hex(data, "A9993E364706816ABA3E25717850C26C9CD0D89D"); + tt_int_op(i, ==, 0); /* Test SHA-256 with a test vector from the specification. */ i = crypto_digest256(data, "abc", 3, DIGEST_SHA256); test_memeq_hex(data, "BA7816BF8F01CFEA414140DE5DAE2223B00361A3" "96177A9CB410FF61F20015AD"); + tt_int_op(i, ==, 0); /* Test HMAC-SHA-1 with test cases from RFC2202. */ @@ -341,7 +343,9 @@ test_crypto_pk(void) test_eq(0, crypto_pk_cmp_keys(pk1, pk2)); test_eq(128, crypto_pk_keysize(pk1)); + test_eq(1024, crypto_pk_num_bits(pk1)); test_eq(128, crypto_pk_keysize(pk2)); + test_eq(1024, crypto_pk_num_bits(pk2)); test_eq(128, crypto_pk_public_encrypt(pk2, data1, sizeof(data1), "Hello whirled.", 15, @@ -626,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); @@ -635,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); @@ -644,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. */ @@ -676,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); @@ -692,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); @@ -708,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); @@ -724,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 8fd94289a..04ca29a9f 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -298,7 +298,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)) @@ -803,7 +803,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); @@ -818,7 +818,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); @@ -835,7 +835,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); @@ -1075,7 +1076,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); @@ -1097,7 +1099,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); @@ -1167,10 +1169,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_util.c b/src/test/test_util.c index 23cd059cf..c4769e640 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,204 @@ 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 + +#ifndef MS_WINDOWS +/** 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 stdout_pipe=-1, stderr_pipe=-1; + int retval, stat_loc; + pid_t pid; + ssize_t pos; + char stdout_buf[100], stderr_buf[100]; + + /* Start the program */ + retval = tor_spawn_background(argv[0], &stdout_pipe, &stderr_pipe, argv); + tt_int_op(retval, >, 0); + tt_int_op(stdout_pipe, >, 0); + tt_int_op(stderr_pipe, >, 0); + pid = retval; + + /* Check stdout */ + pos = read_all(stdout_pipe, stdout_buf, sizeof(stdout_buf) - 1, 0); + tt_assert(pos >= 0); + stdout_buf[pos] = '\0'; + tt_int_op(pos, ==, strlen(expected_out)); + tt_str_op(stdout_buf, ==, expected_out); + + /* Check it terminated correctly */ + retval = waitpid(pid, &stat_loc, 0); + tt_int_op(retval, ==, pid); + tt_assert(WIFEXITED(stat_loc)); + tt_int_op(WEXITSTATUS(stat_loc), ==, expected_exit); + tt_assert(!WIFSIGNALED(stat_loc)); + tt_assert(!WIFSTOPPED(stat_loc)); + + /* Check stderr */ + pos = read_all(stderr_pipe, stderr_buf, sizeof(stderr_buf) - 1, 0); + tt_assert(pos >= 0); + stderr_buf[pos] = '\0'; + tt_int_op(pos, ==, strlen(expected_err)); + tt_str_op(stderr_buf, ==, expected_err); + + done: + ; +} + +/** Check that we can launch a process and read the output */ +static void +test_util_spawn_background_ok(void *ptr) +{ + const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL}; + const char *expected_out = "OUT\n--test\nDONE\n"; + const char *expected_err = "ERR\n"; + + (void)ptr; + + run_util_spawn_background(argv, expected_out, expected_err, 0); +} + +/** Check that failing to find the executable works as expected */ +static void +test_util_spawn_background_fail(void *ptr) +{ + 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 = ""; + + (void)ptr; + + run_util_spawn_background(argv, expected_out, expected_err, 255); +} +#endif + +static void test_util_di_ops(void) { #define LT -1 @@ -1319,6 +1530,12 @@ 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), + UTIL_TEST(spawn_background_ok, 0), + UTIL_TEST(spawn_background_fail, 0), +#endif 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 bd33cc37f..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 @@ -39,7 +39,7 @@ /* ============================================================ */ /* First, let's see if strcmp is working. (All your test cases should be - * functions declared to take a single void * as) an argument. */ + * functions declared to take a single void * as an argument.) */ void test_strcmp(void *data) { @@ -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..75878f259 --- /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 +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 = $(nat_pmp_ldadd) $(miniupnpc_ldadd) ../../common/libor.a @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..18ca56394 --- /dev/null +++ b/src/tools/tor-fw-helper/tor-fw-helper-upnp.c @@ -0,0 +1,186 @@ +/* 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 +#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..20d60d7ba --- /dev/null +++ b/src/tools/tor-fw-helper/tor-fw-helper.c @@ -0,0 +1,363 @@ +/* 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 <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <getopt.h> +#include <time.h> +#include <string.h> + +#include "orconfig.h" +#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); + } +} + +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)); + + 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); + } + + // 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/tools/tor-resolve.c b/src/tools/tor-resolve.c index 12349d9d1..8c4d3f648 100644 --- a/src/tools/tor-resolve.c +++ b/src/tools/tor-resolve.c @@ -319,7 +319,7 @@ main(int argc, char **argv) { uint32_t sockshost; uint16_t socksport = 0, port_option = 0; - int isSocks4 = 0, isVerbose = 0, isReverse = 0, force = 0; + int isSocks4 = 0, isVerbose = 0, isReverse = 0; char **arg; int n_args; struct in_addr a; @@ -349,8 +349,6 @@ main(int argc, char **argv) isSocks4 = 0; else if (!strcmp("-x", arg[0])) isReverse = 1; - else if (!strcmp("-F", arg[0])) - force = 1; else if (!strcmp("-p", arg[0])) { int p; if (n_args < 2) { diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h index b3cd1db50..5483b6d06 100644 --- a/src/win32/orconfig.h +++ b/src/win32/orconfig.h @@ -233,5 +233,4 @@ #define USING_TWOS_COMPLEMENT /* Version number of package */ -#define VERSION "0.2.2.19-alpha" - +#define VERSION "0.2.3.1-alpha-dev" |