diff options
Diffstat (limited to 'src')
117 files changed, 28325 insertions, 9467 deletions
diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 6952591d67..2920e73d2e 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -1,7 +1,7 @@ noinst_LIBRARIES = libor.a libor-crypto.a libor-event.a -EXTRA_DIST = common_sha1.i sha256.c +EXTRA_DIST = common_sha1.i sha256.c Makefile.nmake #CFLAGS = -Wall -Wpointer-arith -O2 @@ -11,18 +11,54 @@ else libor_extra_source= endif -libor_a_SOURCES = address.c log.c util.c compat.c container.c mempool.c \ - memarea.c di_ops.c procmon.c util_codedigest.c $(libor_extra_source) -libor_crypto_a_SOURCES = crypto.c aes.c tortls.c torgzip.c +libor_a_SOURCES = \ + address.c \ + compat.c \ + container.c \ + di_ops.c \ + log.c \ + memarea.c \ + mempool.c \ + procmon.c \ + util.c \ + util_codedigest.c \ + $(libor_extra_source) + +libor_crypto_a_SOURCES = \ + aes.c \ + crypto.c \ + torgzip.c \ + tortls.c + libor_event_a_SOURCES = compat_libevent.c -noinst_HEADERS = address.h torlog.h crypto.h util.h compat.h aes.h torint.h tortls.h strlcpy.c strlcat.c torgzip.h container.h ht.h mempool.h memarea.h ciphers.inc compat_libevent.h tortls_states.h di_ops.h procmon.h +noinst_HEADERS = \ + address.h \ + aes.h \ + ciphers.inc \ + compat.h \ + compat_libevent.h \ + container.h \ + crypto.h \ + di_ops.h \ + ht.h \ + memarea.h \ + mempool.h \ + procmon.h \ + strlcat.c \ + strlcpy.c \ + torgzip.h \ + torint.h \ + torlog.h \ + tortls.h \ + tortls_states.h \ + util.h common_sha1.i: $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS) if test "@SHA1SUM@" != none; then \ - @SHA1SUM@ $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS) | @SED@ -n 's/^\(.*\)$$/"\1\\n"/p' > common_sha1.i; \ + (cd "$(srcdir)" && @SHA1SUM@ $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS)) | @SED@ -n 's/^\(.*\)$$/"\1\\n"/p' > common_sha1.i; \ elif test "@OPENSSL@" != none; then \ - @OPENSSL@ sha1 $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS) | @SED@ -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > common_sha1.i; \ + (cd "$(srcdir)" && @OPENSSL@ sha1 $(libor_SOURCES) $(libor_crypto_a_SOURCES) $(noinst_HEADERS)) | @SED@ -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > common_sha1.i; \ else \ rm common_sha1.i; \ touch common_sha1.i; \ diff --git a/src/common/Makefile.nmake b/src/common/Makefile.nmake new file mode 100644 index 0000000000..c8b5988666 --- /dev/null +++ b/src/common/Makefile.nmake @@ -0,0 +1,20 @@ +all: libor.lib libor-crypto.lib libor-event.lib
+
+CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include
+
+LIBOR_OBJECTS = address.obj compat.obj container.obj di_ops.obj \
+ log.obj memarea.obj mempool.obj procmon.obj util.obj \
+ util_codedigest.obj
+
+LIBOR_CRYPTO_OBJECTS = aes.obj crypto.obj torgzip.obj tortls.obj
+
+LIBOR_EVENT_OBJECTS = compat_libevent.obj
+
+libor.lib: $(LIBOR_OBJECTS)
+ lib $(LIBOR_OBJECTS) /out:libor.lib
+
+libor-crypto.lib: $(LIBOR_CRYPTO_OBJECTS)
+ lib $(LIBOR_CRYPTO_OBJECTS) /out:libor-crypto.lib
+
+libor-event.lib: $(LIBOR_EVENT_OBJECTS)
+ lib $(LIBOR_EVENT_OBJECTS) /out:libor-event.lib
diff --git a/src/common/OpenBSD_malloc_Linux.c b/src/common/OpenBSD_malloc_Linux.c index 19dac77657..445135c6bb 100644 --- a/src/common/OpenBSD_malloc_Linux.c +++ b/src/common/OpenBSD_malloc_Linux.c @@ -1236,7 +1236,7 @@ imalloc(size_t size) ptralloc = 1; size = malloc_pagesize; } - if ((size + malloc_pagesize) < size) { /* Check for overflow */ + if (size > SIZE_MAX - malloc_pagesize) { /* Check for overflow */ result = NULL; errno = ENOMEM; } else if (size <= malloc_maxsize) diff --git a/src/common/address.c b/src/common/address.c index 7fc7301051..f40e428cce 100644 --- a/src/common/address.c +++ b/src/common/address.c @@ -52,6 +52,13 @@ #include <string.h> #include <assert.h> +/* tor_addr_is_null() and maybe other functions rely on AF_UNSPEC being 0 to + * work correctly. Bail out here if we've found a platform where AF_UNSPEC + * isn't 0. */ +#if AF_UNSPEC != 0 +#error We rely on AF_UNSPEC being 0. Let us know about your platform, please! +#endif + /** Convert the tor_addr_t in <b>a</b>, with port in <b>port</b>, into a * sockaddr object in *<b>sa_out</b> of object size <b>len</b>. If not enough * room is available in sa_out, or on error, return 0. On success, return @@ -343,22 +350,28 @@ 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); switch (tor_addr_family(addr)) { case AF_INET: - if (len<3) + /* Shortest addr x.x.x.x + \0 */ + if (len < 8) return NULL; - ptr = tor_inet_ntop(AF_INET, &addr->addr.in_addr, dest, len); + ptr = tor_inet_ntop(AF_INET, &addr->addr.in_addr, dest, len); break; case AF_INET6: + /* Shortest addr [ :: ] + \0 */ + if (len < (3 + (decorate ? 2 : 0))) + return NULL; + if (decorate) ptr = tor_inet_ntop(AF_INET6, &addr->addr.in6_addr, dest+1, len-2); else ptr = tor_inet_ntop(AF_INET6, &addr->addr.in6_addr, dest, len); + if (ptr && decorate) { *dest = '['; memcpy(dest+strlen(dest), "]", 2); @@ -384,7 +397,7 @@ tor_addr_to_str(char *dest, const tor_addr_t *addr, int len, int decorate) * IPv4 or IPv6 address too. */ int -tor_addr_parse_reverse_lookup_name(tor_addr_t *result, const char *address, +tor_addr_parse_PTR_name(tor_addr_t *result, const char *address, int family, int accept_regular) { if (!strcasecmpend(address, ".in-addr.arpa")) { @@ -455,7 +468,7 @@ tor_addr_parse_reverse_lookup_name(tor_addr_t *result, const char *address, if (accept_regular) { tor_addr_t tmp; - int r = tor_addr_from_str(&tmp, address); + int r = tor_addr_parse(&tmp, address); if (r < 0) return 0; if (r != family && family != AF_UNSPEC) @@ -470,13 +483,17 @@ tor_addr_parse_reverse_lookup_name(tor_addr_t *result, const char *address, return 0; } -/** Convert <b>addr</b> to an in-addr.arpa name or a .ip6.arpa name, and store - * the result in the <b>outlen</b>-byte buffer at <b>out</b>. Return 0 on - * success, -1 on failure. */ +/** Convert <b>addr</b> to an in-addr.arpa name or a .ip6.arpa name, + * and store the result in the <b>outlen</b>-byte buffer at + * <b>out</b>. Return the number of chars written to <b>out</b>, not + * including the trailing \0, on success. Returns -1 on failure. */ int -tor_addr_to_reverse_lookup_name(char *out, size_t outlen, - const tor_addr_t *addr) +tor_addr_to_PTR_name(char *out, size_t outlen, + const tor_addr_t *addr) { + tor_assert(out); + tor_assert(addr); + if (addr->family == AF_INET) { uint32_t a = tor_addr_to_ipv4h(addr); @@ -499,7 +516,7 @@ tor_addr_to_reverse_lookup_name(char *out, size_t outlen, *cp++ = '.'; } memcpy(cp, "ip6.arpa", 9); /* 8 characters plus NUL */ - return 0; + return 32 * 2 + 8; } return -1; } @@ -964,6 +981,19 @@ fmt_addr(const tor_addr_t *addr) return "???"; } +/** Like fmt_addr(), but takes <b>addr</b> as a host-order IPv4 + * addresses. Also not thread-safe, also clobbers its return buffer on + * repeated calls. */ +const char * +fmt_addr32(uint32_t addr) +{ + static char buf[INET_NTOA_BUF_LEN]; + struct in_addr in; + in.s_addr = htonl(addr); + tor_inet_ntoa(&in, buf, sizeof(buf)); + return buf; +} + /** Convert the string in <b>src</b> to a tor_addr_t <b>addr</b>. The string * may be an IPv4 address, an IPv6 address, or an IPv6 address surrounded by * square brackets. @@ -971,7 +1001,7 @@ fmt_addr(const tor_addr_t *addr) * Return an address family on success, or -1 if an invalid address string is * provided. */ int -tor_addr_from_str(tor_addr_t *addr, const char *src) +tor_addr_parse(tor_addr_t *addr, const char *src) { char *tmp = NULL; /* Holds substring if we got a dotted quad. */ int result; @@ -999,7 +1029,7 @@ tor_addr_from_str(tor_addr_t *addr, const char *src) * address as needed, and put the result in <b>addr_out</b> and (optionally) * <b>port_out</b>. Return 0 on success, negative on failure. */ int -tor_addr_port_parse(const char *s, tor_addr_t *addr_out, uint16_t *port_out) +tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_out) { const char *port; tor_addr_t addr; @@ -1135,6 +1165,20 @@ is_internal_IP(uint32_t ip, int for_listening) return tor_addr_is_internal(&myaddr, for_listening); } +/** Given an address of the form "host:port", try to divide it into its host + * ane port portions, setting *<b>address_out</b> to a newly allocated string + * holding the address portion and *<b>port_out</b> to the port (or 0 if no + * port is given). Return 0 on success, -1 on failure. */ +int +tor_addr_port_split(int severity, const char *addrport, + char **address_out, uint16_t *port_out) +{ + tor_assert(addrport); + tor_assert(address_out); + tor_assert(port_out); + return addr_port_lookup(severity, addrport, address_out, NULL, port_out); +} + /** Parse a string of the form "host[:port]" from <b>addrport</b>. If * <b>address</b> is provided, set *<b>address</b> to a copy of the * host portion of the string. If <b>addr</b> is provided, try to @@ -1146,7 +1190,7 @@ is_internal_IP(uint32_t ip, int for_listening) * Return 0 on success, -1 on failure. */ int -parse_addr_port(int severity, const char *addrport, char **address, +addr_port_lookup(int severity, const char *addrport, char **address, uint32_t *addr, uint16_t *port_out) { const char *colon; @@ -1156,7 +1200,7 @@ parse_addr_port(int severity, const char *addrport, char **address, tor_assert(addrport); - colon = strchr(addrport, ':'); + colon = strrchr(addrport, ':'); if (colon) { _address = tor_strndup(addrport, colon-addrport); _port = (int) tor_parse_long(colon+1,10,1,65535,NULL,NULL); diff --git a/src/common/address.h b/src/common/address.h index 9a7656f69b..bc225a65ea 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" @@ -148,24 +149,24 @@ int tor_addr_compare_masked(const tor_addr_t *addr1, const tor_addr_t *addr2, unsigned int tor_addr_hash(const tor_addr_t *addr); int tor_addr_is_v4(const tor_addr_t *addr); -int tor_addr_is_internal(const tor_addr_t *ip, int for_listening) ATTR_PURE; +int tor_addr_is_internal(const tor_addr_t *ip, int for_listening); /** Longest length that can be required for a reverse lookup name. */ /* 32 nybbles, 32 dots, 8 characters of "ip6.arpa", 1 NUL: 73 characters. */ #define REVERSE_LOOKUP_NAME_BUF_LEN 73 -int tor_addr_to_reverse_lookup_name(char *out, size_t outlen, +int tor_addr_to_PTR_name(char *out, size_t outlen, const tor_addr_t *addr); -int tor_addr_parse_reverse_lookup_name(tor_addr_t *result, const char *address, +int tor_addr_parse_PTR_name(tor_addr_t *result, const char *address, int family, int accept_regular); -int tor_addr_port_parse(const char *s, tor_addr_t *addr_out, +int tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_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); +int tor_addr_parse(tor_addr_t *addr, const char *src); void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src); void tor_addr_from_ipv4n(tor_addr_t *dest, uint32_t v4addr); /** Set <b>dest</b> to the IPv4 address encoded in <b>v4addr</b> in host @@ -180,9 +181,12 @@ void tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6); int tor_addr_is_null(const tor_addr_t *addr); int tor_addr_is_loopback(const tor_addr_t *addr); +int tor_addr_port_split(int severity, const char *addrport, + char **address_out, uint16_t *port_out); + /* IPv4 helpers */ -int is_internal_IP(uint32_t ip, int for_listening) ATTR_PURE; -int parse_addr_port(int severity, const char *addrport, char **address, +int is_internal_IP(uint32_t ip, int for_listening); +int addr_port_lookup(int severity, const char *addrport, char **address, uint32_t *addr, uint16_t *port_out); int parse_port_range(const char *port, uint16_t *port_min_out, uint16_t *port_max_out); diff --git a/src/common/aes.c b/src/common/aes.c index c2fdeb594a..cec6899817 100644 --- a/src/common/aes.c +++ b/src/common/aes.c @@ -6,11 +6,7 @@ /** * \file aes.c - * \brief Implements the AES cipher (with 128-bit keys and blocks), - * and a counter-mode stream cipher on top of AES. This code is - * taken from the main Rijndael distribution. (We include this - * because many people are running older versions of OpenSSL without - * AES support.) + * \brief Implements a counter-mode stream cipher on top of AES. **/ #include "orconfig.h" @@ -18,120 +14,39 @@ #include <assert.h> #include <stdlib.h> #include <string.h> +#include <openssl/aes.h> +#include <openssl/evp.h> +#include <openssl/engine.h> +#if OPENSSL_VERSION_NUMBER >= 0x10000000L +/* See comments about which counter mode implementation to use below. */ +#include <openssl/modes.h> +#define USE_OPENSSL_CTR +#endif #include "compat.h" #include "aes.h" #include "util.h" #include "torlog.h" -/* We have 3 strategies for getting AES: Via OpenSSL's AES_encrypt function, - * via OpenSSL's EVP_EncryptUpdate function, or via the built-in AES - * implementation below. */ - -/** Defined iff we're using OpenSSL's AES functions for AES. */ -#undef USE_OPENSSL_AES -/** Defined iff we're using OpenSSL's EVP code for AES. */ -#undef USE_OPENSSL_EVP -/** Defined iff we're using Tor's internal AES implementation, defined - * below. */ -#undef USE_BUILTIN_AES - -/* Figure out our CPU type. We use this to pick an AES implementation. - * Macros are as listed at http://predef.sourceforge.net/prearch.html - */ -#if (defined(i386) || defined(__i386__) || defined(__i386) || defined(_X86_) \ - || defined(_M_IX86) || defined(__THW_INTEL__) || defined(__I86__)) -# define CPU_IS_X86 -#elif (defined(__amd64__) || defined(__amd64) || \ - defined(__x86_64__) || defined(__x86_64) || \ - defined(_M_X64)) -# define CPU_IS_X86_64 -#elif (defined(__ia64__) || defined(__ia64) || defined(_IA64) || \ - defined(_M_IA64)) -# define CPU_IS_IA64 -#elif (defined(__sparc__) || defined(__sparc)) -# define CPU_IS_SPARC -#elif (defined(__arm__) || defined (__TARGET_ARCH_ARM)) -# define CPU_IS_ARM +#ifdef ANDROID +/* Android's OpenSSL seems to have removed all of its Engine support. */ +#define DISABLE_ENGINES #endif -/* Here we pick which to use, if none is force-defined. See - * http://archives.seul.org/or/dev/Feb-2007/msg00045.html - * for a summary of the most recent benchmarking results that led to this - * nutty decision tree. -*/ -#if (!defined(USE_BUILTIN_AES) && \ - !defined(USE_OPENSSL_AES) && \ - !defined(USE_OPENSSL_EVP)) - -/* OpenSSL 0.9.7 was the first to support AES. It was slower than our - * built-in implementation. - * OpenSSL 0.9.8 added assembly implementations for i386 and ia64. - * Either the i386 stuff isn't used for x86-64, or it isn't faster. - * OpenSSL 0.9.9 (not yet out) has added assembly implementations for - * x86_64 (aka amd64), sparc9, and arm +/* We have 2 strategies for getting AES: Via OpenSSL's AES_encrypt function, + * via OpenSSL's EVP_EncryptUpdate function. * - * Note: the "f" at the end of OpenSSL version numbers below means - * "release". */ -# if defined(CPU_IS_X86) || defined(CPU_IS_IA64) -# if OPENSSL_VERSION_NUMBER >= 0x0090800fL -# define USE_OPENSSL_AES -# endif -# endif - -# if defined(CPU_IS_X86_64) || defined(CPU_IS_ARM) || defined(CPU_IS_SPARC) -# if OPENSSL_VERSION_NUMBER >= 0x0090900fL -# define USE_OPENSSL_AES -# endif -# endif - -/* Otherwise, use the built-in implementation below. */ -# ifndef USE_OPENSSL_AES -# define USE_BUILTIN_AES -# endif -#endif /* endif need to pick a method */ - -/* Include OpenSSL headers as needed. */ -#ifdef USE_OPENSSL_AES -# include <openssl/aes.h> -#endif -#ifdef USE_OPENSSL_EVP -# include <openssl/evp.h> -#endif - -/* Figure out which AES optimizations to use. */ -#ifdef USE_BUILTIN_AES -/** If this is defined, we take advantage of the fact that AES treats its - * input as a set of 4 32-bit words, so that there is no need to encode and - * decode the 128-bit counter before every block encryption */ -# define USE_RIJNDAEL_COUNTER_OPTIMIZATION -# if 0 && (defined(__powerpc__) || defined(__powerpc64__)) -/* XXXX do more experimentation before concluding this is actually - * a good idea. */ -# define FULL_UNROLL -# endif -#endif - -/*======================================================================*/ -/* From rijndael-alg-fst.h */ - -typedef uint64_t u64; -typedef uint32_t u32; -typedef uint8_t u8; - -#ifdef USE_BUILTIN_AES -#define MAXNR 14 + * If there's any hardware acceleration in play, we want to be using EVP_* so + * we can get it. Otherwise, we'll want AES_*, which seems to be about 5% + * faster than indirecting through the EVP layer. + */ -static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], - const u8 cipherKey[], int keyBits); -#ifdef USE_RIJNDAEL_COUNTER_OPTIMIZATION -static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, - u32 ctr3, u32 ctr2, - u32 ctr1, u32 ctr0, u8 ct[16]); -#else -static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, - const u8 pt[16], u8 ct[16]); -#endif -#endif +/* We have 2 strategies for counter mode: use our own, or use OpenSSL's. + * + * Here we have a counter mode that's faster than the one shipping with + * OpenSSL pre-1.0 (by about 10%!). But OpenSSL 1.0.0 added a counter mode + * implementation faster than the one here (by about 7%). So we pick which + * one to used based on the Openssl version above. + */ /*======================================================================*/ /* Interface to AES code, and counter implementation */ @@ -139,42 +54,78 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, /** Implements an AES counter-mode cipher. */ struct aes_cnt_cipher { /** This next element (however it's defined) is the AES key. */ -#if defined(USE_OPENSSL_EVP) - EVP_CIPHER_CTX key; -#elif defined(USE_OPENSSL_AES) - AES_KEY key; -#else - u32 rk[4*(MAXNR+1)]; - int nr; -#endif + union { + EVP_CIPHER_CTX evp; + AES_KEY aes; + } key; -#if !defined(WORDS_BIGENDIAN) || defined(USE_RIJNDAEL_COUNTER_OPTIMIZATION) +#if !defined(WORDS_BIGENDIAN) && !defined(USE_OPENSSL_CTR) #define USING_COUNTER_VARS /** These four values, together, implement a 128-bit counter, with * counter0 as the low-order word and counter3 as the high-order word. */ - u32 counter3; - u32 counter2; - u32 counter1; - u32 counter0; + uint32_t counter3; + uint32_t counter2; + uint32_t counter1; + uint32_t counter0; #endif -#ifndef USE_RIJNDAEL_COUNTER_OPTIMIZATION -#define USING_COUNTER_BUFS union { /** The counter, in big-endian order, as bytes. */ - u8 buf[16]; + uint8_t buf[16]; /** The counter, in big-endian order, as big-endian words. Note that * on big-endian platforms, this is redundant with counter3...0, * so we just use these values instead. */ - u32 buf32[4]; + uint32_t buf32[4]; } ctr_buf; -#endif + /** The encrypted value of ctr_buf. */ - u8 buf[16]; + uint8_t buf[16]; /** Our current stream position within buf. */ - u8 pos; +#ifdef USE_OPENSSL_CTR + unsigned int pos; +#else + uint8_t pos; +#endif + + /** True iff we're using the evp implementation of this cipher. */ + uint8_t using_evp; }; +/** True if we should prefer the EVP implementation for AES, either because + * we're testing it or because we have hardware acceleration configured */ +static int should_use_EVP = 0; + +/** Check whether we should use the EVP interface for AES. If <b>force_val</b> + * is nonnegative, we use use EVP iff it is true. Otherwise, we use EVP + * if there is an engine enabled for aes-ecb. */ +int +evaluate_evp_for_aes(int force_val) +{ + ENGINE *e; + + if (force_val >= 0) { + should_use_EVP = force_val; + return 0; + } +#ifdef DISABLE_ENGINES + should_use_EVP = 0; +#else + e = ENGINE_get_cipher_engine(NID_aes_128_ecb); + + if (e) { + log_notice(LD_CRYPTO, "AES engine \"%s\" found; using EVP_* functions.", + ENGINE_get_name(e)); + should_use_EVP = 1; + } else { + log_notice(LD_CRYPTO, "No AES engine found; using AES_* functions."); + should_use_EVP = 0; + } +#endif + + return 0; +} + +#ifndef USE_OPENSSL_CTR #if !defined(USING_COUNTER_VARS) #define COUNTER(c, n) ((c)->ctr_buf.buf32[3-(n)]) #else @@ -194,25 +145,16 @@ _aes_fill_buf(aes_cnt_cipher_t *cipher) * 3) changing the counter position was not trivial, last time I looked. * None of these issues are insurmountable in principle. */ -#if defined(USE_BUILTIN_AES) && defined(USE_RIJNDAEL_COUNTER_OPTIMIZATION) - rijndaelEncrypt(cipher->rk, cipher->nr, - cipher->counter3, cipher->counter2, - cipher->counter1, cipher->counter0, cipher->buf); -#else -#if defined(USE_OPENSSL_EVP) - { + if (cipher->using_evp) { int outl=16, inl=16; - EVP_EncryptUpdate(&cipher->key, cipher->buf, &outl, + EVP_EncryptUpdate(&cipher->key.evp, cipher->buf, &outl, cipher->ctr_buf.buf, inl); + } else { + AES_encrypt(cipher->ctr_buf.buf, cipher->buf, &cipher->key.aes); } -#elif defined(USE_OPENSSL_AES) - AES_encrypt(cipher->ctr_buf.buf, cipher->buf, &cipher->key); -#else - rijndaelEncrypt(cipher->rk, cipher->nr, cipher->ctr_buf.buf, cipher->buf); -#endif -#endif } +#endif /** * Return a newly allocated counter-mode AES128 cipher implementation. @@ -232,33 +174,37 @@ aes_new_cipher(void) void aes_set_key(aes_cnt_cipher_t *cipher, const char *key, int key_bits) { -#if defined(USE_OPENSSL_EVP) - const EVP_CIPHER *c; - switch (key_bits) { - case 128: c = EVP_aes_128_ecb(); break; - case 192: c = EVP_aes_192_ecb(); break; - case 256: c = EVP_aes_256_ecb(); break; - default: tor_assert(0); + if (should_use_EVP) { + const EVP_CIPHER *c; + switch (key_bits) { + case 128: c = EVP_aes_128_ecb(); break; + case 192: c = EVP_aes_192_ecb(); break; + case 256: c = EVP_aes_256_ecb(); break; + default: tor_assert(0); + } + EVP_EncryptInit(&cipher->key.evp, c, (const unsigned char*)key, NULL); + cipher->using_evp = 1; + } else { + AES_set_encrypt_key((const unsigned char *)key, key_bits, &cipher->key.aes); + cipher->using_evp = 0; } - EVP_EncryptInit(&cipher->key, c, (const unsigned char*)key, NULL); -#elif defined(USE_OPENSSL_AES) - AES_set_encrypt_key((const unsigned char *)key, key_bits, &(cipher->key)); -#else - cipher->nr = rijndaelKeySetupEnc(cipher->rk, (const unsigned char*)key, - key_bits); -#endif + #ifdef USING_COUNTER_VARS cipher->counter0 = 0; cipher->counter1 = 0; cipher->counter2 = 0; cipher->counter3 = 0; #endif -#ifdef USING_COUNTER_BUFS + memset(cipher->ctr_buf.buf, 0, sizeof(cipher->ctr_buf.buf)); -#endif cipher->pos = 0; + +#ifdef USE_OPENSSL_CTR + memset(cipher->buf, 0, sizeof(cipher->buf)); +#else _aes_fill_buf(cipher); +#endif } /** Release storage held by <b>cipher</b> @@ -268,14 +214,14 @@ aes_free_cipher(aes_cnt_cipher_t *cipher) { if (!cipher) return; -#ifdef USE_OPENSSL_EVP - EVP_CIPHER_CTX_cleanup(&cipher->key); -#endif + if (cipher->using_evp) { + EVP_CIPHER_CTX_cleanup(&cipher->key.evp); + } memset(cipher, 0, sizeof(aes_cnt_cipher_t)); tor_free(cipher); } -#if defined(USING_COUNTER_VARS) && defined(USING_COUNTER_BUFS) +#if defined(USING_COUNTER_VARS) #define UPDATE_CTR_BUF(c, n) STMT_BEGIN \ (c)->ctr_buf.buf32[3-(n)] = htonl((c)->counter ## n); \ STMT_END @@ -283,6 +229,18 @@ aes_free_cipher(aes_cnt_cipher_t *cipher) #define UPDATE_CTR_BUF(c, n) #endif +#ifdef USE_OPENSSL_CTR +/* Helper function to use EVP with openssl's counter-mode wrapper. */ +static void evp_block128_fn(const uint8_t in[16], + uint8_t out[16], + const void *key) +{ + EVP_CIPHER_CTX *ctx = (void*)key; + int inl=16, outl=16; + EVP_EncryptUpdate(ctx, out, &outl, in, inl); +} +#endif + /** Encrypt <b>len</b> bytes from <b>input</b>, storing the result in * <b>output</b>. Uses the key in <b>cipher</b>, and advances the counter * by <b>len</b> bytes as it encrypts. @@ -291,11 +249,29 @@ 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. */ +#ifdef USE_OPENSSL_CTR + if (cipher->using_evp) { + /* In openssl 1.0.0, there's an if'd out EVP_aes_128_ctr in evp.h. If + * it weren't disabled, it might be better just to use that. + */ + CRYPTO_ctr128_encrypt((const unsigned char *)input, + (unsigned char *)output, + len, + &cipher->key.evp, + cipher->ctr_buf.buf, + cipher->buf, + &cipher->pos, + evp_block128_fn); + } else { + AES_ctr128_encrypt((const unsigned char *)input, + (unsigned char *)output, + len, + &cipher->key.aes, + cipher->ctr_buf.buf, + cipher->buf, + &cipher->pos); + } +#else int c = cipher->pos; if (PREDICT_UNLIKELY(!len)) return; @@ -318,6 +294,7 @@ aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len, UPDATE_CTR_BUF(cipher, 0); _aes_fill_buf(cipher); } +#endif } /** Encrypt <b>len</b> bytes from <b>input</b>, storing the results in place. @@ -327,11 +304,9 @@ aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len, void aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len) { - - /* 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. */ +#ifdef USE_OPENSSL_CTR + aes_crypt(cipher, data, len, data); +#else int c = cipher->pos; if (PREDICT_UNLIKELY(!len)) return; @@ -354,6 +329,7 @@ aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len) UPDATE_CTR_BUF(cipher, 0); _aes_fill_buf(cipher); } +#endif } /** Reset the 128-bit counter of <b>cipher</b> to the 16-bit big-endian value @@ -368,705 +344,10 @@ aes_set_iv(aes_cnt_cipher_t *cipher, const char *iv) cipher->counter0 = ntohl(get_uint32(iv+12)); #endif cipher->pos = 0; -#ifndef USE_RIJNDAEL_COUNTER_OPTIMIZATION memcpy(cipher->ctr_buf.buf, iv, 16); -#endif +#ifndef USE_OPENSSL_CTR _aes_fill_buf(cipher); -} - -#ifdef USE_BUILTIN_AES -/*======================================================================*/ -/* From rijndael-alg-fst.c */ - -/** - * rijndael-alg-fst.c - * - * @version 3.0 (December 2000) - * - * Optimized ANSI C code for the Rijndael cipher (now AES) - * - * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be> - * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be> - * @author Paulo Barreto <paulo.barreto@terra.com.br> - * - * This code is hereby placed in the public domain. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS - * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* -Te0[x] = S [x].[02, 01, 01, 03]; -Te1[x] = S [x].[03, 02, 01, 01]; -Te2[x] = S [x].[01, 03, 02, 01]; -Te3[x] = S [x].[01, 01, 03, 02]; -Te4[x] = S [x].[01, 01, 01, 01]; - -Td0[x] = Si[x].[0e, 09, 0d, 0b]; -Td1[x] = Si[x].[0b, 0e, 09, 0d]; -Td2[x] = Si[x].[0d, 0b, 0e, 09]; -Td3[x] = Si[x].[09, 0d, 0b, 0e]; -Td4[x] = Si[x].[01, 01, 01, 01]; -*/ - -static const u32 Te0[256] = { - 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, - 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, - 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, - 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, - 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, - 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, - 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, - 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, - 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, - 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, - 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, - 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, - 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, - 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, - 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, - 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, - 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, - 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, - 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, - 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, - 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, - 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, - 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, - 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, - 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, - 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, - 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, - 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, - 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, - 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, - 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, - 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, - 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, - 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, - 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, - 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, - 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, - 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, - 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, - 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, - 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, - 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, - 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, - 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, - 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, - 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, - 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, - 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, - 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, - 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, - 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, - 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, - 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, - 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, - 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, - 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, - 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, - 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, - 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, - 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, - 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, - 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, - 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, - 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, -}; -static const u32 Te1[256] = { - 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, - 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, - 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, - 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, - 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, - 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, - 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, - 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, - 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, - 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, - 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, - 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, - 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, - 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, - 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, - 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, - 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, - 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, - 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, - 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, - 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, - 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, - 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, - 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, - 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, - 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, - 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, - 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, - 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, - 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, - 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, - 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, - 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, - 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, - 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, - 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, - 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, - 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, - 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, - 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, - 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, - 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, - 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, - 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, - 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, - 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, - 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, - 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, - 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, - 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, - 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, - 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, - 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, - 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, - 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, - 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, - 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, - 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, - 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, - 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, - 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, - 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, - 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, - 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, -}; -static const u32 Te2[256] = { - 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, - 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, - 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, - 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, - 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, - 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, - 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, - 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, - 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, - 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, - 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, - 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, - 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, - 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, - 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, - 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, - 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, - 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, - 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, - 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, - 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, - 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, - 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, - 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, - 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, - 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, - 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, - 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, - 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, - 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, - 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, - 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, - 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, - 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, - 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, - 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, - 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, - 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, - 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, - 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, - 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, - 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, - 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, - 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, - 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, - 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, - 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, - 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, - 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, - 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, - 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, - 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, - 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, - 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, - 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, - 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, - 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, - 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, - 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, - 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, - 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, - 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, - 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, - 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, -}; -static const u32 Te3[256] = { - - 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, - 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, - 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, - 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, - 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, - 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, - 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, - 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, - 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, - 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, - 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, - 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, - 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, - 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, - 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, - 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, - 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, - 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, - 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, - 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, - 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, - 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, - 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, - 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, - 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, - 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, - 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, - 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, - 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, - 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, - 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, - 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, - 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, - 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, - 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, - 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, - 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, - 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, - 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, - 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, - 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, - 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, - 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, - 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, - 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, - 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, - 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, - 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, - 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, - 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, - 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, - 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, - 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, - 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, - 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, - 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, - 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, - 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, - 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, - 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, - 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, - 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, - 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, - 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, -}; -static const u32 Te4[256] = { - 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, - 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, - 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, - 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, - 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, - 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, - 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, - 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, - 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, - 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, - 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, - 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, - 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, - 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, - 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, - 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, - 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, - 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, - 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, - 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, - 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, - 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, - 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, - 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, - 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, - 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, - 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, - 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, - 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, - 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, - 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, - 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, - 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, - 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, - 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, - 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, - 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, - 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, - 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, - 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, - 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, - 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, - 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, - 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, - 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, - 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, - 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, - 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, - 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, - 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, - 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, - 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, - 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, - 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, - 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, - 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, - 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, - 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, - 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, - 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, - 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, - 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, - 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, - 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, -}; - -static const u32 rcon[] = { - 0x01000000, 0x02000000, 0x04000000, 0x08000000, - 0x10000000, 0x20000000, 0x40000000, 0x80000000, - 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ -}; - -#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) - -#ifdef _MSC_VER -#define GETU32(p) SWAP(*((u32 *)(p))) -#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } -#else -#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) -#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } #endif - -/** - * Expand the cipher key into the encryption key schedule. - * - * @return the number of rounds for the given cipher key size. - */ -static int -rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) -{ - int i = 0; - u32 temp; - - rk[0] = GETU32(cipherKey ); - rk[1] = GETU32(cipherKey + 4); - rk[2] = GETU32(cipherKey + 8); - rk[3] = GETU32(cipherKey + 12); - if (keyBits == 128) { - for (;;) { - temp = rk[3]; - rk[4] = rk[0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]; - rk[5] = rk[1] ^ rk[4]; - rk[6] = rk[2] ^ rk[5]; - rk[7] = rk[3] ^ rk[6]; - if (++i == 10) { - return 10; - } - rk += 4; - } - } - rk[4] = GETU32(cipherKey + 16); - rk[5] = GETU32(cipherKey + 20); - if (keyBits == 192) { - for (;;) { - temp = rk[ 5]; - rk[ 6] = rk[ 0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]; - rk[ 7] = rk[ 1] ^ rk[ 6]; - rk[ 8] = rk[ 2] ^ rk[ 7]; - rk[ 9] = rk[ 3] ^ rk[ 8]; - if (++i == 8) { - return 12; - } - rk[10] = rk[ 4] ^ rk[ 9]; - rk[11] = rk[ 5] ^ rk[10]; - rk += 6; - } - } - rk[6] = GETU32(cipherKey + 24); - rk[7] = GETU32(cipherKey + 28); - if (keyBits == 256) { - for (;;) { - temp = rk[ 7]; - rk[ 8] = rk[ 0] ^ - (Te4[(temp >> 16) & 0xff] & 0xff000000) ^ - (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ - (Te4[(temp ) & 0xff] & 0x0000ff00) ^ - (Te4[(temp >> 24) ] & 0x000000ff) ^ - rcon[i]; - rk[ 9] = rk[ 1] ^ rk[ 8]; - rk[10] = rk[ 2] ^ rk[ 9]; - rk[11] = rk[ 3] ^ rk[10]; - if (++i == 7) { - return 14; - } - temp = rk[11]; - rk[12] = rk[ 4] ^ - (Te4[(temp >> 24) ] & 0xff000000) ^ - (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(temp ) & 0xff] & 0x000000ff); - rk[13] = rk[ 5] ^ rk[12]; - rk[14] = rk[ 6] ^ rk[13]; - rk[15] = rk[ 7] ^ rk[14]; - - rk += 8; - } - } - return 0; -} - -#ifdef USE_RIJNDAEL_COUNTER_OPTIMIZATION -static void -rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, u32 ctr3, u32 ctr2, u32 ctr1, u32 ctr0, u8 ct[16]) -#else -static void -rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) -#endif -{ - u32 s0, s1, s2, s3, t0, t1, t2, t3; -#ifndef FULL_UNROLL - int r; -#endif /* ?FULL_UNROLL */ - - /* - * map byte array block to cipher state - * and add initial round key: - */ -#ifdef USE_RIJNDAEL_COUNTER_OPTIMIZATION - s0 = ctr3 ^ rk[0]; - s1 = ctr2 ^ rk[1]; - s2 = ctr1 ^ rk[2]; - s3 = ctr0 ^ rk[3]; -#else - s0 = GETU32(pt ) ^ rk[0]; - s1 = GETU32(pt + 4) ^ rk[1]; - s2 = GETU32(pt + 8) ^ rk[2]; - s3 = GETU32(pt + 12) ^ rk[3]; -#endif - -#ifdef FULL_UNROLL - /* round 1: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; - /* round 2: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; - /* round 3: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; - /* round 4: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; - /* round 5: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; - /* round 6: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; - /* round 7: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; - /* round 8: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; - /* round 9: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; - if (Nr > 10) { - /* round 10: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43]; - /* round 11: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47]; - if (Nr > 12) { - /* round 12: */ - s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48]; - s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49]; - s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50]; - s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51]; - /* round 13: */ - t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52]; - t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53]; - t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54]; - t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55]; - } - } - rk += Nr << 2; -#else /* !FULL_UNROLL */ - /* - * Nr - 1 full rounds: - */ - r = Nr >> 1; - for (;;) { - t0 = - Te0[(s0 >> 24) ] ^ - Te1[(s1 >> 16) & 0xff] ^ - Te2[(s2 >> 8) & 0xff] ^ - Te3[(s3 ) & 0xff] ^ - rk[4]; - t1 = - Te0[(s1 >> 24) ] ^ - Te1[(s2 >> 16) & 0xff] ^ - Te2[(s3 >> 8) & 0xff] ^ - Te3[(s0 ) & 0xff] ^ - rk[5]; - t2 = - Te0[(s2 >> 24) ] ^ - Te1[(s3 >> 16) & 0xff] ^ - Te2[(s0 >> 8) & 0xff] ^ - Te3[(s1 ) & 0xff] ^ - rk[6]; - t3 = - Te0[(s3 >> 24) ] ^ - Te1[(s0 >> 16) & 0xff] ^ - Te2[(s1 >> 8) & 0xff] ^ - Te3[(s2 ) & 0xff] ^ - rk[7]; - - rk += 8; - if (--r == 0) { - break; - } - - s0 = - Te0[(t0 >> 24) ] ^ - Te1[(t1 >> 16) & 0xff] ^ - Te2[(t2 >> 8) & 0xff] ^ - Te3[(t3 ) & 0xff] ^ - rk[0]; - s1 = - Te0[(t1 >> 24) ] ^ - Te1[(t2 >> 16) & 0xff] ^ - Te2[(t3 >> 8) & 0xff] ^ - Te3[(t0 ) & 0xff] ^ - rk[1]; - s2 = - Te0[(t2 >> 24) ] ^ - Te1[(t3 >> 16) & 0xff] ^ - Te2[(t0 >> 8) & 0xff] ^ - Te3[(t1 ) & 0xff] ^ - rk[2]; - s3 = - Te0[(t3 >> 24) ] ^ - Te1[(t0 >> 16) & 0xff] ^ - Te2[(t1 >> 8) & 0xff] ^ - Te3[(t2 ) & 0xff] ^ - rk[3]; - } -#endif /* ?FULL_UNROLL */ - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = - (Te4[(t0 >> 24) ] & 0xff000000) ^ - (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t3 ) & 0xff] & 0x000000ff) ^ - rk[0]; - PUTU32(ct , s0); - s1 = - (Te4[(t1 >> 24) ] & 0xff000000) ^ - (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t0 ) & 0xff] & 0x000000ff) ^ - rk[1]; - PUTU32(ct + 4, s1); - s2 = - (Te4[(t2 >> 24) ] & 0xff000000) ^ - (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t1 ) & 0xff] & 0x000000ff) ^ - rk[2]; - PUTU32(ct + 8, s2); - s3 = - (Te4[(t3 >> 24) ] & 0xff000000) ^ - (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ - (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ - (Te4[(t2 ) & 0xff] & 0x000000ff) ^ - rk[3]; - PUTU32(ct + 12, s3); -} -#endif - -#ifdef AES_BENCHMARK -int -main(int c, char **v) -{ - int i; - char blob[509]; /* the size of a cell payload. */ - char blob_out[509]; - aes_cnt_cipher_t *cipher = aes_new_cipher(); - aes_set_key(cipher, "aesbenchmarkkey!", 128); - memset(blob, 'z', sizeof(blob)); - - for (i=0;i<1000000; ++i) { - aes_crypt(cipher, blob, sizeof(blob), blob_out); - } - return 0; } -#endif diff --git a/src/common/aes.h b/src/common/aes.h index eb633dbcce..221e846155 100644 --- a/src/common/aes.h +++ b/src/common/aes.h @@ -13,8 +13,6 @@ * \brief Headers for aes.c */ -#include "torint.h" - struct aes_cnt_cipher; typedef struct aes_cnt_cipher aes_cnt_cipher_t; @@ -26,5 +24,7 @@ void aes_crypt(aes_cnt_cipher_t *cipher, const char *input, size_t len, void aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len); void aes_set_iv(aes_cnt_cipher_t *cipher, const char *iv); +int evaluate_evp_for_aes(int force_value); + #endif diff --git a/src/common/compat.c b/src/common/compat.c index 80b4907b81..ea95f9f085 100644 --- a/src/common/compat.c +++ b/src/common/compat.c @@ -58,6 +58,14 @@ #endif #endif +/* Includes for the process attaching prevention */ +#if defined(HAVE_SYS_PRCTL_H) && defined(__linux__) +#include <sys/prctl.h> +#elif defined(__APPLE__) +#include <sys/types.h> +#include <sys/ptrace.h> +#endif + #ifdef HAVE_NETDB_H #include <netdb.h> #endif @@ -103,6 +111,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 +155,7 @@ tor_mmap_file(const char *filename) tor_assert(filename); - fd = open(filename, O_RDONLY, 0); + fd = tor_open_cloexec(filename, O_RDONLY, 0); if (fd<0) { int save_errno = errno; int severity = (errno == ENOENT) ? LOG_INFO : LOG_WARN; @@ -695,7 +732,7 @@ tor_lockfile_lock(const char *filename, int blocking, int *locked_out) *locked_out = 0; log_info(LD_FS, "Locking \"%s\"", filename); - fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0600); + fd = tor_open_cloexec(filename, O_RDWR|O_CREAT|O_TRUNC, 0600); if (fd < 0) { log_warn(LD_FS,"Couldn't open \"%s\" for locking: %s", filename, strerror(errno)); @@ -922,8 +959,16 @@ mark_socket_open(tor_socket_t s) tor_socket_t tor_open_socket(int domain, int type, int protocol) { - tor_socket_t s = socket(domain, type, protocol); + tor_socket_t s; +#ifdef SOCK_CLOEXEC +#define LINUX_CLOEXEC_OPEN_SOCKET + type |= SOCK_CLOEXEC; +#endif + s = socket(domain, type, protocol); if (SOCKET_OK(s)) { +#if !defined(LINUX_CLOEXEC_OPEN_SOCKET) && defined(FD_CLOEXEC) + fcntl(s, F_SETFD, FD_CLOEXEC); +#endif socket_accounting_lock(); ++n_sockets_open; mark_socket_open(s); @@ -936,8 +981,17 @@ tor_open_socket(int domain, int type, int protocol) tor_socket_t tor_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *len) { - tor_socket_t s = accept(sockfd, addr, len); + tor_socket_t s; +#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) +#define LINUX_CLOEXEC_ACCEPT + s = accept4(sockfd, addr, len, SOCK_CLOEXEC); +#else + s = accept(sockfd, addr, len); +#endif if (SOCKET_OK(s)) { +#if !defined(LINUX_CLOEXEC_ACCEPT) && defined(FD_CLOEXEC) + fcntl(s, F_SETFD, FD_CLOEXEC); +#endif socket_accounting_lock(); ++n_sockets_open; mark_socket_open(s); @@ -993,8 +1047,17 @@ tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2]) //don't use win32 socketpairs (they are always bad) #if defined(HAVE_SOCKETPAIR) && !defined(MS_WINDOWS) int r; +#ifdef SOCK_CLOEXEC + type |= SOCK_CLOEXEC; +#endif r = socketpair(family, type, protocol, fd); if (r == 0) { +#if !defined(SOCK_CLOEXEC) && defined(FD_CLOEXEC) + if (fd[0] >= 0) + fcntl(fd[0], F_SETFD, FD_CLOEXEC); + if (fd[1] >= 0) + fcntl(fd[1], F_SETFD, FD_CLOEXEC); +#endif socket_accounting_lock(); if (fd[0] >= 0) { ++n_sockets_open; @@ -1464,6 +1527,57 @@ switch_id(const char *user) #endif } +/* We only use the linux prctl for now. There is no Win32 support; this may + * also work on various BSD systems and Mac OS X - send testing feedback! + * + * On recent Gnu/Linux kernels it is possible to create a system-wide policy + * that will prevent non-root processes from attaching to other processes + * unless they are the parent process; thus gdb can attach to programs that + * they execute but they cannot attach to other processes running as the same + * user. The system wide policy may be set with the sysctl + * kernel.yama.ptrace_scope or by inspecting + * /proc/sys/kernel/yama/ptrace_scope and it is 1 by default on Ubuntu 11.04. + * + * This ptrace scope will be ignored on Gnu/Linux for users with + * CAP_SYS_PTRACE and so it is very likely that root will still be able to + * attach to the Tor process. + */ +/** Attempt to disable debugger attachment: return 0 on success, -1 on + * failure. */ +int +tor_disable_debugger_attach(void) +{ + int r, attempted; + r = -1; + attempted = 0; + log_debug(LD_CONFIG, + "Attemping to disable debugger attachment to Tor for " + "unprivileged users."); +#if defined(__linux__) && defined(HAVE_SYS_PRCTL_H) && defined(HAVE_PRCTL) +#ifdef PR_SET_DUMPABLE + attempted = 1; + r = prctl(PR_SET_DUMPABLE, 0); +#endif +#endif +#if defined(__APPLE__) && defined(PT_DENY_ATTACH) + if (r < 0) { + attempted = 1; + r = ptrace(PT_DENY_ATTACH, 0, 0, 0); + } +#endif + + // XXX: TODO - Mac OS X has dtrace and this may be disabled. + // XXX: TODO - Windows probably has something similar + if (r == 0) { + log_debug(LD_CONFIG,"Debugger attachment disabled for " + "unprivileged users."); + } else if (attempted) { + log_warn(LD_CONFIG, "Unable to disable ptrace attach: %s", + strerror(errno)); + } + return r; +} + #ifdef HAVE_PWD_H /** Allocate and return a string containing the home directory for the * user <b>username</b>. Only works on posix-like systems. */ @@ -1577,7 +1691,7 @@ tor_inet_ntop(int af, const void *src, char *dst, size_t len) addr->s6_addr[12], addr->s6_addr[13], addr->s6_addr[14], addr->s6_addr[15]); } - if (strlen(buf) > len) + if ((strlen(buf) + 1) > len) /* +1 for \0 */ return NULL; strlcpy(dst, buf, len); return dst; @@ -1618,7 +1732,7 @@ tor_inet_ntop(int af, const void *src, char *dst, size_t len) } } *cp = '\0'; - if (strlen(buf) > len) + if ((strlen(buf) + 1) > len) /* +1 for \0 */ return NULL; strlcpy(dst, buf, len); return dst; @@ -1678,24 +1792,30 @@ tor_inet_pton(int af, const char *src, void *dst) return 0; if (TOR_ISXDIGIT(*src)) { char *next; + ssize_t len; long r = strtol(src, &next, 16); - if (next > 4+src) - return 0; - if (next == src) - return 0; - if (r<0 || r>65536) + tor_assert(next != NULL); + tor_assert(next != src); + + len = *next == '\0' ? eow - src : next - src; + if (len > 4) return 0; + if (len > 1 && !TOR_ISXDIGIT(src[1])) + return 0; /* 0x is not valid */ + tor_assert(r >= 0); + tor_assert(r < 65536); words[i++] = (uint16_t)r; setWords++; src = next; if (*src != ':' && src != eow) return 0; ++src; - } else if (*src == ':' && i > 0 && gapPos==-1) { + } else if (*src == ':' && i > 0 && gapPos == -1) { gapPos = i; ++src; - } else if (*src == ':' && i == 0 && src[1] == ':' && gapPos==-1) { + } else if (*src == ':' && i == 0 && src+1 < eow && src[1] == ':' && + gapPos == -1) { gapPos = i; src += 2; } else { @@ -1806,6 +1926,7 @@ get_uname(void) static struct { unsigned major; unsigned minor; const char *version; } win_version_table[] = { + { 6, 2, "Windows 8" }, { 6, 1, "Windows 7" }, { 6, 0, "Windows Vista" }, { 5, 2, "Windows Server 2003" }, @@ -1862,7 +1983,7 @@ get_uname(void) plat, extra); } else { if (info.dwMajorVersion > 6 || - (info.dwMajorVersion==6 && info.dwMinorVersion>1)) + (info.dwMajorVersion==6 && info.dwMinorVersion>2)) tor_snprintf(uname_result, sizeof(uname_result), "Very recent version of Windows [major=%d,minor=%d] %s", (int)info.dwMajorVersion,(int)info.dwMinorVersion, @@ -1994,6 +2115,52 @@ spawn_exit(void) #endif } +/** Implementation logic for compute_num_cpus(). */ +static int +compute_num_cpus_impl(void) +{ +#ifdef MS_WINDOWS + SYSTEM_INFO info; + memset(&info, 0, sizeof(info)); + GetSystemInfo(&info); + if (info.dwNumberOfProcessors >= 1 && info.dwNumberOfProcessors < INT_MAX) + return (int)info.dwNumberOfProcessors; + else + return -1; +#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF) + long cpus = sysconf(_SC_NPROCESSORS_CONF); + if (cpus >= 1 && cpus < INT_MAX) + return (int)cpus; + else + return -1; +#else + return -1; +#endif +} + +#define MAX_DETECTABLE_CPUS 16 + +/** Return how many CPUs we are running with. We assume that nobody is + * using hot-swappable CPUs, so we don't recompute this after the first + * time. Return -1 if we don't know how to tell the number of CPUs on this + * system. + */ +int +compute_num_cpus(void) +{ + static int num_cpus = -2; + if (num_cpus == -2) { + num_cpus = compute_num_cpus_impl(); + tor_assert(num_cpus != -2); + if (num_cpus > MAX_DETECTABLE_CPUS) + log_notice(LD_GENERAL, "Wow! I detected that you have %d CPUs. I " + "will not autodetect any more than %d, though. If you " + "want to configure more, set NumCPUs in your torrc", + num_cpus, MAX_DETECTABLE_CPUS); + } + return num_cpus; +} + /** Set *timeval to the current time of day. On error, log and terminate. * (Same as gettimeofday(timeval,NULL), but never returns -1.) */ diff --git a/src/common/compat.h b/src/common/compat.h index eb79b04449..db541623d3 100644 --- a/src/common/compat.h +++ b/src/common/compat.h @@ -9,8 +9,12 @@ #include "orconfig.h" #include "torint.h" #ifdef MS_WINDOWS +#ifndef WIN32_WINNT #define WIN32_WINNT 0x400 +#endif +#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x400 +#endif #define WIN32_LEAN_AND_MEAN #if defined(_MSC_VER) && (_MSC_VER < 1300) #include <winsock.h> @@ -41,9 +45,6 @@ #ifdef HAVE_SYS_SOCKET_H #include <sys/socket.h> #endif -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif #ifdef HAVE_NETINET_IN_H #include <netinet/in.h> #endif @@ -51,6 +52,8 @@ #include <netinet6/in6.h> #endif +#include <stdio.h> + #if defined (WINCE) #include <fcntl.h> #include <io.h> @@ -132,7 +135,6 @@ extern INLINE double U64_TO_DBL(uint64_t x) { /* GCC has several useful attributes. */ #if defined(__GNUC__) && __GNUC__ >= 3 #define ATTR_NORETURN __attribute__((noreturn)) -#define ATTR_PURE __attribute__((pure)) #define ATTR_CONST __attribute__((const)) #define ATTR_MALLOC __attribute__((malloc)) #define ATTR_NORETURN __attribute__((noreturn)) @@ -165,7 +167,6 @@ extern INLINE double U64_TO_DBL(uint64_t x) { #define PREDICT_UNLIKELY(exp) __builtin_expect(!!(exp), 0) #else #define ATTR_NORETURN -#define ATTR_PURE #define ATTR_CONST #define ATTR_MALLOC #define ATTR_NORETURN @@ -177,6 +178,10 @@ extern INLINE double U64_TO_DBL(uint64_t x) { /** Expands to a syntactically valid empty statement. */ #define STMT_NIL (void)0 +/** Expands to a syntactically valid empty statement, explicitly (void)ing its + * argument. */ +#define STMT_VOID(a) while (0) { (void)(a); } + #ifdef __GNUC__ /** STMT_BEGIN and STMT_END are used to wrap blocks inside macros so that * the macro can be used as if it were a single C statement. */ @@ -264,9 +269,9 @@ int tor_asprintf(char **strp, const char *fmt, ...) int tor_vasprintf(char **strp, const char *fmt, va_list args); const void *tor_memmem(const void *haystack, size_t hlen, const void *needle, - size_t nlen) ATTR_PURE ATTR_NONNULL((1,3)); + size_t nlen) ATTR_NONNULL((1,3)); static const void *tor_memstr(const void *haystack, size_t hlen, - const char *needle) ATTR_PURE ATTR_NONNULL((1,3)); + const char *needle) ATTR_NONNULL((1,3)); static INLINE const void * tor_memstr(const void *haystack, size_t hlen, const char *needle) { @@ -367,6 +372,9 @@ struct tm *tor_gmtime_r(const time_t *timep, struct tm *result); #endif /* ===== File compatibility */ +int tor_open_cloexec(const char *path, int flags, unsigned mode); +FILE *tor_fopen_cloexec(const char *path, const char *mode); + int replace_file(const char *from, const char *to); int touch_file(const char *fname); @@ -392,7 +400,7 @@ typedef int socklen_t; #ifdef MS_WINDOWS #define tor_socket_t intptr_t -#define SOCKET_OK(s) ((s) != INVALID_SOCKET) +#define SOCKET_OK(s) ((unsigned)(s) != INVALID_SOCKET) #else #define tor_socket_t int #define SOCKET_OK(s) ((s) >= 0) @@ -536,9 +544,9 @@ long tor_weak_random(void); /* ===== OS compatibility */ const char *get_uname(void); -uint16_t get_uint16(const void *cp) ATTR_PURE ATTR_NONNULL((1)); -uint32_t get_uint32(const void *cp) ATTR_PURE ATTR_NONNULL((1)); -uint64_t get_uint64(const void *cp) ATTR_PURE ATTR_NONNULL((1)); +uint16_t get_uint16(const void *cp) ATTR_NONNULL((1)); +uint32_t get_uint32(const void *cp) ATTR_NONNULL((1)); +uint64_t get_uint64(const void *cp) ATTR_NONNULL((1)); void set_uint16(void *cp, uint16_t v) ATTR_NONNULL((1)); void set_uint32(void *cp, uint32_t v) ATTR_NONNULL((1)); void set_uint64(void *cp, uint64_t v) ATTR_NONNULL((1)); @@ -556,6 +564,7 @@ set_uint8(void *cp, uint8_t v) typedef unsigned long rlim_t; #endif int set_max_file_descriptors(rlim_t limit, int *max); +int tor_disable_debugger_attach(void); int switch_id(const char *user); #ifdef HAVE_PWD_H char *get_user_homedir(const char *username); @@ -577,6 +586,8 @@ void spawn_exit(void) ATTR_NORETURN; #undef TOR_IS_MULTITHREADED #endif +int compute_num_cpus(void); + /* Because we use threads instead of processes on most platforms (Windows, * Linux, etc), we need locking for them. On platforms with poor thread * support or broken gethostbyname_r, these functions are no-ops. */ @@ -610,7 +621,7 @@ void tor_threads_init(void); #else #define tor_mutex_new() ((tor_mutex_t*)tor_malloc(sizeof(int))) #define tor_mutex_init(m) STMT_NIL -#define tor_mutex_acquire(m) STMT_NIL +#define tor_mutex_acquire(m) STMT_VOID(m) #define tor_mutex_release(m) STMT_NIL #define tor_mutex_free(m) STMT_BEGIN tor_free(m); STMT_END #define tor_mutex_uninit(m) STMT_NIL diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c index 6d89be804b..67f465927c 100644 --- a/src/common/compat_libevent.c +++ b/src/common/compat_libevent.c @@ -19,6 +19,10 @@ #ifdef HAVE_EVENT2_EVENT_H #include <event2/event.h> +#include <event2/thread.h> +#ifdef USE_BUFFEREVENTS +#include <event2/bufferevent.h> +#endif #else #include <event.h> #endif @@ -163,11 +167,24 @@ struct event_base *the_event_base = NULL; #endif #endif +#ifdef USE_BUFFEREVENTS +static int using_iocp_bufferevents = 0; +static void tor_libevent_set_tick_timeout(int msec_per_tick); + +int +tor_libevent_using_iocp_bufferevents(void) +{ + return using_iocp_bufferevents; +} +#endif + /** Initialize the Libevent library and set up the event base. */ void -tor_libevent_initialize(void) +tor_libevent_initialize(tor_libevent_cfg *torcfg) { tor_assert(the_event_base == NULL); + /* some paths below don't use torcfg, so avoid unused variable warnings */ + (void)torcfg; #ifdef __APPLE__ if (MACOSX_KQUEUE_IS_BROKEN || @@ -177,11 +194,76 @@ tor_libevent_initialize(void) #endif #ifdef HAVE_EVENT2_EVENT_H - the_event_base = event_base_new(); + { + int attempts = 0; + int using_threads; + struct event_config *cfg; + + retry: + ++attempts; + using_threads = 0; + cfg = event_config_new(); + tor_assert(cfg); + +#if defined(MS_WINDOWS) && defined(USE_BUFFEREVENTS) + if (! torcfg->disable_iocp) { + evthread_use_windows_threads(); + event_config_set_flag(cfg, EVENT_BASE_FLAG_STARTUP_IOCP); + using_iocp_bufferevents = 1; + using_threads = 1; + } else { + using_iocp_bufferevents = 0; + } +#endif + + if (!using_threads) { + /* Telling Libevent not to try to turn locking on can avoid a needless + * socketpair() attempt. */ + event_config_set_flag(cfg, EVENT_BASE_FLAG_NOLOCK); + } + +#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); + + if (using_threads && the_event_base == NULL && attempts < 2) { + /* This could be a socketpair() failure, which can happen sometimes on + * windows boxes with obnoxious firewall rules. Downgrade and try + * again. */ +#if defined(MS_WINDOWS) && defined(USE_BUFFEREVENTS) + if (torcfg->disable_iocp == 0) { + log_warn(LD_GENERAL, "Unable to initialize Libevent. Trying again " + "with IOCP disabled."); + } else +#endif + { + log_warn(LD_GENERAL, "Unable to initialize Libevent. Trying again."); + } + + torcfg->disable_iocp = 1; + goto retry; + } + } #else the_event_base = event_init(); #endif + if (!the_event_base) { + log_err(LD_GENERAL, "Unable to initialize Libevent: cannot continue."); + exit(1); + } + #if defined(HAVE_EVENT_GET_VERSION) && defined(HAVE_EVENT_GET_METHOD) /* Making this a NOTICE for now so we can link bugs to a libevent versions * or methods better. */ @@ -195,6 +277,10 @@ tor_libevent_initialize(void) "You have a *VERY* old version of libevent. It is likely to be buggy; " "please build Tor with a more recent version."); #endif + +#ifdef USE_BUFFEREVENTS + tor_libevent_set_tick_timeout(torcfg->msec_per_tick); +#endif } /** Return the current Libevent event base that we're set up to use. */ @@ -240,7 +326,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 +334,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) { @@ -472,6 +558,60 @@ tor_check_libevent_header_compatibility(void) #endif } +struct tor_libevent_action_t { + struct event *ev; + void (*cb)(void *arg); + void *arg; +}; + +/** Callback for tor_run_in_libevent_loop */ +static void +run_runnable_cb(evutil_socket_t s, short what, void *arg) +{ + tor_libevent_action_t *r = arg; + void (*cb)(void *) = r->cb; + void *cb_arg = r->arg; + (void)what; + (void)s; + tor_event_free(r->ev); + tor_free(r); + + cb(cb_arg); +} + +/** Cause cb(arg) to run later on this iteration of the libevent loop, or in + * the next iteration of the libevent loop. This is useful for when you're + * deep inside a no-reentrant code and there's some function you want to call + * without worrying about whether it might cause reeentrant invocation. + */ +tor_libevent_action_t * +tor_run_in_libevent_loop(void (*cb)(void *arg), void *arg) +{ + tor_libevent_action_t *r = tor_malloc(sizeof(tor_libevent_action_t)); + r->cb = cb; + r->arg = arg; + r->ev = tor_event_new(tor_libevent_get_base(), -1, EV_TIMEOUT, + run_runnable_cb, r); + if (!r->ev) { + tor_free(r); + return NULL; + } + /* Make the event active immediately. */ + event_active(r->ev, EV_TIMEOUT, 1); + + return r; +} + +/** + * Cancel <b>action</b> without running it. + */ +void +tor_cancel_libevent_action(tor_libevent_action_t *action) +{ + tor_event_free(action->ev); + tor_free(action); +} + /* If possible, we're going to try to use Libevent's periodic timer support, since it does a pretty good job of making sure that periodic events get @@ -552,3 +692,55 @@ periodic_timer_free(periodic_timer_t *timer) tor_free(timer); } +#ifdef USE_BUFFEREVENTS +static const struct timeval *one_tick = NULL; +/** + * Return a special timeout to be passed whenever libevent's O(1) timeout + * implementation should be used. Only use this when the timer is supposed + * to fire after msec_per_tick ticks have elapsed. +*/ +const struct timeval * +tor_libevent_get_one_tick_timeout(void) +{ + tor_assert(one_tick); + return one_tick; +} + +/** Initialize the common timeout that we'll use to refill the buckets every + * time a tick elapses. */ +static void +tor_libevent_set_tick_timeout(int msec_per_tick) +{ + struct event_base *base = tor_libevent_get_base(); + struct timeval tv; + + tor_assert(! one_tick); + tv.tv_sec = msec_per_tick / 1000; + tv.tv_usec = (msec_per_tick % 1000) * 1000; + one_tick = event_base_init_common_timeout(base, &tv); +} + +static struct bufferevent * +tor_get_root_bufferevent(struct bufferevent *bev) +{ + struct bufferevent *u; + while ((u = bufferevent_get_underlying(bev)) != NULL) + bev = u; + return bev; +} + +int +tor_set_bufferevent_rate_limit(struct bufferevent *bev, + struct ev_token_bucket_cfg *cfg) +{ + return bufferevent_set_rate_limit(tor_get_root_bufferevent(bev), cfg); +} + +int +tor_add_bufferevent_to_rate_limit_group(struct bufferevent *bev, + struct bufferevent_rate_limit_group *g) +{ + return bufferevent_add_to_rate_limit_group(tor_get_root_bufferevent(bev), g); +} +#endif + diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h index 89b256396b..4076cc0e08 100644 --- a/src/common/compat_libevent.h +++ b/src/common/compat_libevent.h @@ -8,6 +8,11 @@ struct event; struct event_base; +#ifdef USE_BUFFEREVENTS +struct bufferevent; +struct ev_token_bucket_cfg; +struct bufferevent_rate_limit_group; +#endif #ifdef HAVE_EVENT2_EVENT_H #include <event2/util.h> @@ -39,8 +44,12 @@ void tor_event_free(struct event *ev); #define tor_evdns_add_server_port evdns_add_server_port #endif -typedef struct periodic_timer_t periodic_timer_t; +typedef struct tor_libevent_action_t tor_libevent_action_t; +tor_libevent_action_t *tor_run_in_libevent_loop(void (*cb)(void *arg), + void *arg); +void tor_cancel_libevent_action(tor_libevent_action_t *action); +typedef struct periodic_timer_t periodic_timer_t; periodic_timer_t *periodic_timer_new(struct event_base *base, const struct timeval *tv, void (*cb)(periodic_timer_t *timer, void *data), @@ -54,7 +63,13 @@ struct timeval; int tor_event_base_loopexit(struct event_base *base, struct timeval *tv); #endif -void tor_libevent_initialize(void); +typedef struct tor_libevent_cfg { + int disable_iocp; + int num_cpus; + int msec_per_tick; +} tor_libevent_cfg; + +void tor_libevent_initialize(tor_libevent_cfg *cfg); struct event_base *tor_libevent_get_base(void); const char *tor_libevent_get_method(void); void tor_check_libevent_version(const char *m, int server, @@ -62,5 +77,14 @@ void tor_check_libevent_version(const char *m, int server, void tor_check_libevent_header_compatibility(void); const char *tor_libevent_get_version_str(void); +#ifdef USE_BUFFEREVENTS +const struct timeval *tor_libevent_get_one_tick_timeout(void); +int tor_libevent_using_iocp_bufferevents(void); +int tor_set_bufferevent_rate_limit(struct bufferevent *bev, + struct ev_token_bucket_cfg *cfg); +int tor_add_bufferevent_to_rate_limit_group(struct bufferevent *bev, + struct bufferevent_rate_limit_group *g); +#endif + #endif diff --git a/src/common/container.c b/src/common/container.c index 1515c387ad..31cc6c5a6c 100644 --- a/src/common/container.c +++ b/src/common/container.c @@ -62,13 +62,22 @@ smartlist_clear(smartlist_t *sl) static INLINE void smartlist_ensure_capacity(smartlist_t *sl, int size) { +#if SIZEOF_SIZE_T > SIZEOF_INT +#define MAX_CAPACITY (INT_MAX) +#else +#define MAX_CAPACITY (int)((SIZE_MAX / (sizeof(void*)))) +#endif if (size > sl->capacity) { - int higher = sl->capacity * 2; - while (size > higher) - higher *= 2; - tor_assert(higher > 0); /* detect overflow */ + int higher = sl->capacity; + if (PREDICT_UNLIKELY(size > MAX_CAPACITY/2)) { + tor_assert(size <= MAX_CAPACITY); + higher = MAX_CAPACITY; + } else { + while (size > higher) + higher *= 2; + } sl->capacity = higher; - sl->list = tor_realloc(sl->list, sizeof(void*)*sl->capacity); + sl->list = tor_realloc(sl->list, sizeof(void*)*((size_t)sl->capacity)); } } @@ -287,7 +296,6 @@ smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2) /** Remove the <b>idx</b>th element of sl; if idx is not the last * element, swap the last element of sl into the <b>idx</b>th space. - * Return the old value of the <b>idx</b>th element. */ void smartlist_del(smartlist_t *sl, int idx) diff --git a/src/common/container.h b/src/common/container.h index 4a6eba789d..fe071cc1b3 100644 --- a/src/common/container.h +++ b/src/common/container.h @@ -35,19 +35,14 @@ void smartlist_remove(smartlist_t *sl, const void *element); void *smartlist_pop_last(smartlist_t *sl); void smartlist_reverse(smartlist_t *sl); void smartlist_string_remove(smartlist_t *sl, const char *element); -int smartlist_isin(const smartlist_t *sl, const void *element) ATTR_PURE; -int smartlist_string_isin(const smartlist_t *sl, const char *element) - ATTR_PURE; -int smartlist_string_pos(const smartlist_t *, const char *elt) ATTR_PURE; -int smartlist_string_isin_case(const smartlist_t *sl, const char *element) - ATTR_PURE; -int smartlist_string_num_isin(const smartlist_t *sl, int num) ATTR_PURE; -int smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2) - ATTR_PURE; -int smartlist_digest_isin(const smartlist_t *sl, const char *element) - ATTR_PURE; -int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2) - ATTR_PURE; +int smartlist_isin(const smartlist_t *sl, const void *element); +int smartlist_string_isin(const smartlist_t *sl, const char *element); +int smartlist_string_pos(const smartlist_t *, const char *elt); +int smartlist_string_isin_case(const smartlist_t *sl, const char *element); +int smartlist_string_num_isin(const smartlist_t *sl, int num); +int smartlist_strings_eq(const smartlist_t *sl1, const smartlist_t *sl2); +int smartlist_digest_isin(const smartlist_t *sl, const char *element); +int smartlist_overlap(const smartlist_t *sl1, const smartlist_t *sl2); void smartlist_intersect(smartlist_t *sl1, const smartlist_t *sl2); void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2); @@ -55,14 +50,14 @@ void smartlist_subtract(smartlist_t *sl1, const smartlist_t *sl2); #ifdef DEBUG_SMARTLIST /** Return the number of items in sl. */ -static INLINE int smartlist_len(const smartlist_t *sl) ATTR_PURE; +static INLINE int smartlist_len(const smartlist_t *sl); static INLINE int smartlist_len(const smartlist_t *sl) { tor_assert(sl); return (sl)->num_used; } /** Return the <b>idx</b>th element of sl. */ -static INLINE void *smartlist_get(const smartlist_t *sl, int idx) ATTR_PURE; +static INLINE void *smartlist_get(const smartlist_t *sl, int idx); static INLINE void *smartlist_get(const smartlist_t *sl, int idx) { tor_assert(sl); tor_assert(idx>=0); @@ -114,8 +109,7 @@ void smartlist_uniq_strings(smartlist_t *sl); void smartlist_uniq_digests(smartlist_t *sl); void smartlist_uniq_digests256(smartlist_t *sl); void *smartlist_bsearch(smartlist_t *sl, const void *key, - int (*compare)(const void *key, const void **member)) - ATTR_PURE; + int (*compare)(const void *key, const void **member)); int smartlist_bsearch_idx(const smartlist_t *sl, const void *key, int (*compare)(const void *key, const void **member), int *found_out); diff --git a/src/common/crypto.c b/src/common/crypto.c index 851f11bf3b..ebaa0122fd 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -13,8 +13,12 @@ #include "orconfig.h" #ifdef MS_WINDOWS +#ifndef WIN32_WINNT #define WIN32_WINNT 0x400 +#endif +#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x400 +#endif #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <wincrypt.h> @@ -60,8 +64,6 @@ #error "We require OpenSSL >= 0.9.7" #endif -#include <openssl/engine.h> - #ifdef ANDROID /* Android's OpenSSL seems to have removed all of its Engine support. */ #define DISABLE_ENGINES @@ -274,6 +276,9 @@ crypto_global_init(int useAccel, const char *accelName, const char *accelDir) } else { log_info(LD_CRYPTO, "NOT using OpenSSL engine support."); } + + evaluate_evp_for_aes(-1); + return crypto_seed_rng(1); } return 0; @@ -948,7 +953,7 @@ crypto_pk_public_checksig_digest(crypto_pk_env_t *env, const char *data, log_warn(LD_BUG, "couldn't compute digest"); return -1; } - buflen = crypto_pk_keysize(env)+1; + buflen = crypto_pk_keysize(env); buf = tor_malloc(buflen); r = crypto_pk_public_checksig(env,buf,buflen,sig,siglen); if (r != DIGEST_LEN) { @@ -1133,8 +1138,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, @@ -1202,9 +1207,6 @@ crypto_pk_asn1_decode(const char *str, size_t len) { RSA *rsa; unsigned char *buf; - /* This ifdef suppresses a type warning. Take out the first case once - * everybody is using OpenSSL 0.9.7 or later. - */ const unsigned char *cp; cp = buf = tor_malloc(len); memcpy(buf,str,len); @@ -1245,6 +1247,32 @@ crypto_pk_get_digest(crypto_pk_env_t *pk, char *digest_out) return 0; } +/** Compute all digests of the DER encoding of <b>pk</b>, and store them + * in <b>digests_out</b>. Return 0 on success, -1 on failure. */ +int +crypto_pk_get_all_digests(crypto_pk_env_t *pk, digests_t *digests_out) +{ + unsigned char *buf, *bufp; + int len; + + len = i2d_RSAPublicKey(pk->key, NULL); + if (len < 0) + return -1; + buf = bufp = tor_malloc(len+1); + len = i2d_RSAPublicKey(pk->key, &bufp); + if (len < 0) { + crypto_log_errors(LOG_WARN,"encoding public key"); + tor_free(buf); + return -1; + } + if (crypto_digest_all(digests_out, (char*)buf, len) < 0) { + tor_free(buf); + return -1; + } + tor_free(buf); + return 0; +} + /** Copy <b>in</b> to the <b>outlen</b>-byte buffer <b>out</b>, adding spaces * every four spaces. */ /* static */ void @@ -1663,6 +1691,10 @@ crypto_digest_get_digest(crypto_digest_env_t *digest, SHA256_Final(r, &tmpenv.d.sha2); break; default: + log_warn(LD_BUG, "Called with unknown algorithm %d", digest->algorithm); + /* If fragile_assert is not enabled, then we should at least not + * leak anything. */ + memset(r, 0xff, sizeof(r)); tor_fragile_assert(); break; } @@ -1710,8 +1742,79 @@ crypto_hmac_sha1(char *hmac_out, (unsigned char*)hmac_out, NULL); } +/** Compute the HMAC-SHA-256 of the <b>msg_len</b> bytes in <b>msg</b>, using + * the <b>key</b> of length <b>key_len</b>. Store the DIGEST_LEN-byte result + * in <b>hmac_out</b>. + */ +void +crypto_hmac_sha256(char *hmac_out, + const char *key, size_t key_len, + const char *msg, size_t msg_len) +{ +#if (OPENSSL_VERSION_NUMBER >= 0x00908000l) + /* If we've got OpenSSL >=0.9.8 we can use its hmac implementation. */ + tor_assert(key_len < INT_MAX); + tor_assert(msg_len < INT_MAX); + HMAC(EVP_sha256(), key, (int)key_len, (unsigned char*)msg, (int)msg_len, + (unsigned char*)hmac_out, NULL); +#else + /* OpenSSL doesn't have an EVP implementation for SHA256. We'll need + to do HMAC on our own. + + HMAC isn't so hard: To compute HMAC(key, msg): + 1. If len(key) > blocksize, key = H(key). + 2. If len(key) < blocksize, right-pad key up to blocksize with 0 bytes. + 3. let ipad = key xor 0x363636363636....36 + let opad = key xor 0x5c5c5c5c5c5c....5c + The result is H(opad | H( ipad | msg ) ) + */ +#define BLOCKSIZE 64 +#define DIGESTSIZE 32 + uint8_t k[BLOCKSIZE]; + uint8_t pad[BLOCKSIZE]; + uint8_t d[DIGESTSIZE]; + int i; + SHA256_CTX st; + + tor_assert(key_len < INT_MAX); + tor_assert(msg_len < INT_MAX); + + if (key_len <= BLOCKSIZE) { + memset(k, 0, sizeof(k)); + memcpy(k, key, key_len); /* not time invariant in key_len */ + } else { + SHA256((const uint8_t *)key, key_len, k); + memset(k+DIGESTSIZE, 0, sizeof(k)-DIGESTSIZE); + } + for (i = 0; i < BLOCKSIZE; ++i) + pad[i] = k[i] ^ 0x36; + SHA256_Init(&st); + SHA256_Update(&st, pad, BLOCKSIZE); + SHA256_Update(&st, (uint8_t*)msg, msg_len); + SHA256_Final(d, &st); + + for (i = 0; i < BLOCKSIZE; ++i) + pad[i] = k[i] ^ 0x5c; + SHA256_Init(&st); + SHA256_Update(&st, pad, BLOCKSIZE); + SHA256_Update(&st, d, DIGESTSIZE); + SHA256_Final((uint8_t*)hmac_out, &st); + + /* Now clear everything. */ + memset(k, 0, sizeof(k)); + memset(pad, 0, sizeof(pad)); + memset(d, 0, sizeof(d)); + memset(&st, 0, sizeof(st)); +#undef BLOCKSIZE +#undef DIGESTSIZE +#endif +} + /* DH */ +/** Our DH 'g' parameter */ +#define DH_GENERATOR 2 + /** Shared P parameter for our circuit-crypto DH key exchanges. */ static BIGNUM *dh_param_p = NULL; /** Shared P parameter for our TLS DH key exchanges. */ @@ -1719,49 +1822,303 @@ static BIGNUM *dh_param_p_tls = NULL; /** Shared G parameter for our DH key exchanges. */ static BIGNUM *dh_param_g = NULL; +/** Generate and return a reasonable and safe DH parameter p. */ +static BIGNUM * +crypto_generate_dynamic_dh_modulus(void) +{ + BIGNUM *dynamic_dh_modulus; + DH *dh_parameters; + int r, dh_codes; + char *s; + + dynamic_dh_modulus = BN_new(); + tor_assert(dynamic_dh_modulus); + + dh_parameters = DH_generate_parameters(DH_BYTES*8, DH_GENERATOR, NULL, NULL); + tor_assert(dh_parameters); + + r = DH_check(dh_parameters, &dh_codes); + tor_assert(r && !dh_codes); + + BN_copy(dynamic_dh_modulus, dh_parameters->p); + tor_assert(dynamic_dh_modulus); + + DH_free(dh_parameters); + + { /* log the dynamic DH modulus: */ + s = BN_bn2hex(dynamic_dh_modulus); + tor_assert(s); + log_info(LD_OR, "Dynamic DH modulus generated: [%s]", s); + OPENSSL_free(s); + } + + return dynamic_dh_modulus; +} + +/** Store our dynamic DH modulus (and its group parameters) to + <b>fname</b> for future use. */ +static int +crypto_store_dynamic_dh_modulus(const char *fname) +{ + int len, new_len; + DH *dh = NULL; + unsigned char *dh_string_repr = NULL, *cp = NULL; + char *base64_encoded_dh = NULL; + int retval = -1; + + tor_assert(fname); + + if (!dh_param_p_tls) { + log_info(LD_CRYPTO, "Tried to store a DH modulus that does not exist."); + goto done; + } + + if (!(dh = DH_new())) + goto done; + if (!(dh->p = BN_dup(dh_param_p_tls))) + goto done; + if (!(dh->g = BN_new())) + goto done; + if (!BN_set_word(dh->g, DH_GENERATOR)) + goto done; + + len = i2d_DHparams(dh, NULL); + if (len < 0) { + log_warn(LD_CRYPTO, "Error occured while DER encoding DH modulus (1)."); + goto done; + } + + cp = dh_string_repr = tor_malloc_zero(len+1); + len = i2d_DHparams(dh, &cp); + if ((len < 0) || ((cp - dh_string_repr) != len)) { + log_warn(LD_CRYPTO, "Error occured while DER encoding DH modulus (2)."); + goto done; + } + + base64_encoded_dh = tor_malloc_zero(len * 2); /* should be enough */ + new_len = base64_encode(base64_encoded_dh, len * 2, + (char *)dh_string_repr, len); + if (new_len < 0) { + log_warn(LD_CRYPTO, "Error occured while base64-encoding DH modulus."); + goto done; + } + + if (write_bytes_to_new_file(fname, base64_encoded_dh, new_len, 0) < 0) { + log_info(LD_CRYPTO, "'%s' was already occupied.", fname); + goto done; + } + + retval = 0; + + done: + if (dh) + DH_free(dh); + tor_free(dh_string_repr); + tor_free(base64_encoded_dh); + + return retval; +} + +/** Return the dynamic DH modulus stored in <b>fname</b>. If there is no + dynamic DH modulus stored in <b>fname</b>, return NULL. */ +static BIGNUM * +crypto_get_stored_dynamic_dh_modulus(const char *fname) +{ + int retval; + char *contents = NULL; + int dh_codes; + char *fname_new = NULL; + DH *stored_dh = NULL; + BIGNUM *dynamic_dh_modulus = NULL; + int length = 0; + unsigned char *base64_decoded_dh = NULL; + const unsigned char *cp = NULL; + + tor_assert(fname); + + contents = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL); + if (!contents) { + log_info(LD_CRYPTO, "Could not open file '%s'", fname); + goto done; /*usually means that ENOENT. don't try to move file to broken.*/ + } + + /* 'fname' contains the DH parameters stored in base64-ed DER + format. We are only interested in the DH modulus. */ + + cp = base64_decoded_dh = tor_malloc_zero(strlen(contents)); + length = base64_decode((char *)base64_decoded_dh, strlen(contents), + contents, strlen(contents)); + if (length < 0) { + log_warn(LD_CRYPTO, "Stored dynamic DH modulus seems corrupted (base64)."); + goto err; + } + + stored_dh = d2i_DHparams(NULL, &cp, length); + if ((!stored_dh) || (cp - base64_decoded_dh != length)) { + log_warn(LD_CRYPTO, "Stored dynamic DH modulus seems corrupted (d2i)."); + goto err; + } + + { /* check the cryptographic qualities of the stored dynamic DH modulus: */ + retval = DH_check(stored_dh, &dh_codes); + if (!retval || dh_codes) { + log_warn(LD_CRYPTO, "Stored dynamic DH modulus is not a safe prime."); + goto err; + } + + retval = DH_size(stored_dh); + if (retval < DH_BYTES) { + log_warn(LD_CRYPTO, "Stored dynamic DH modulus is smaller " + "than '%d' bits.", DH_BYTES*8); + goto err; + } + + if (!BN_is_word(stored_dh->g, 2)) { + log_warn(LD_CRYPTO, "Stored dynamic DH parameters do not use '2' " + "as the group generator."); + goto err; + } + } + + { /* log the dynamic DH modulus: */ + char *s = BN_bn2hex(stored_dh->p); + tor_assert(s); + log_info(LD_OR, "Found stored dynamic DH modulus: [%s]", s); + OPENSSL_free(s); + } + + goto done; + + err: + + { /* move broken prime to $filename.broken */ + fname_new = tor_malloc(strlen(fname) + 8); + + /* no can do if these functions return error */ + strlcpy(fname_new, fname, strlen(fname) + 8); + strlcat(fname_new, ".broken", strlen(fname) + 8); + + log_warn(LD_CRYPTO, "Moving broken dynamic DH prime to '%s'.", fname_new); + + if (replace_file(fname, fname_new)) + log_notice(LD_CRYPTO, "Error while moving '%s' to '%s'.", + fname, fname_new); + + tor_free(fname_new); + } + + if (stored_dh) { + DH_free(stored_dh); + stored_dh = NULL; + } + + done: + tor_free(contents); + tor_free(base64_decoded_dh); + + if (stored_dh) { + dynamic_dh_modulus = BN_dup(stored_dh->p); + DH_free(stored_dh); + } + + return dynamic_dh_modulus; +} + +/** Set the global TLS Diffie-Hellman modulus. + * If <b>dynamic_dh_modulus_fname</b> is set, try to read a dynamic DH modulus + * off it and use it as the DH modulus. If that's not possible, + * generate a new dynamic DH modulus. + * If <b>dynamic_dh_modulus_fname</b> is NULL, use the Apache mod_ssl DH + * modulus. */ +void +crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname) +{ + BIGNUM *tls_prime = NULL; + int store_dh_prime_afterwards = 0; + int r; + + /* If the space is occupied, free the previous TLS DH prime */ + if (dh_param_p_tls) { + BN_free(dh_param_p_tls); + dh_param_p_tls = NULL; + } + + if (dynamic_dh_modulus_fname) { /* use dynamic DH modulus: */ + log_info(LD_OR, "Using stored dynamic DH modulus."); + tls_prime = crypto_get_stored_dynamic_dh_modulus(dynamic_dh_modulus_fname); + + if (!tls_prime) { + log_notice(LD_OR, "Generating fresh dynamic DH modulus. " + "This might take a while..."); + tls_prime = crypto_generate_dynamic_dh_modulus(); + + store_dh_prime_afterwards++; + } + } else { /* use the static DH prime modulus used by Apache in mod_ssl: */ + tls_prime = BN_new(); + tor_assert(tls_prime); + + /* This is the 1024-bit safe prime that Apache uses for its DH stuff; see + * modules/ssl/ssl_engine_dh.c; Apache also uses a generator of 2 with this + * prime. + */ + r =BN_hex2bn(&tls_prime, + "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98" + "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A" + "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7" + "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68" + "B0E7393E0F24218EB3"); + tor_assert(r); + } + + tor_assert(tls_prime); + + dh_param_p_tls = tls_prime; + + if (store_dh_prime_afterwards) + /* save the new dynamic DH modulus to disk. */ + if (crypto_store_dynamic_dh_modulus(dynamic_dh_modulus_fname)) { + log_notice(LD_CRYPTO, "Failed while storing dynamic DH modulus. " + "Make sure your data directory is sane."); + } +} + /** Initialize dh_param_p and dh_param_g if they are not already * set. */ static void init_dh_param(void) { - BIGNUM *p, *p2, *g; + BIGNUM *circuit_dh_prime, *generator; int r; - if (dh_param_p && dh_param_g && dh_param_p_tls) + if (dh_param_p && dh_param_g) return; - p = BN_new(); - p2 = BN_new(); - g = BN_new(); - tor_assert(p); - tor_assert(p2); - tor_assert(g); + circuit_dh_prime = BN_new(); + generator = BN_new(); + tor_assert(circuit_dh_prime && generator); + + /* Set our generator for all DH parameters */ + r = BN_set_word(generator, DH_GENERATOR); + tor_assert(r); /* This is from rfc2409, section 6.2. It's a safe prime, and supposedly it equals: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }. */ - r = BN_hex2bn(&p, + r = BN_hex2bn(&circuit_dh_prime, "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" "49286651ECE65381FFFFFFFFFFFFFFFF"); tor_assert(r); - /* This is the 1024-bit safe prime that Apache uses for its DH stuff; see - * modules/ssl/ssl_engine_dh.c */ - r = BN_hex2bn(&p2, - "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98" - "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A" - "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7" - "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68" - "B0E7393E0F24218EB3"); - tor_assert(r); - r = BN_set_word(g, 2); - tor_assert(r); - dh_param_p = p; - dh_param_p_tls = p2; - dh_param_g = g; + /* Set the new values as the global DH parameters. */ + dh_param_p = circuit_dh_prime; + dh_param_g = generator; + + /* Should be already set by config.c. */ + tor_assert(dh_param_p_tls); } /** Number of bits to use when choosing the x or y value in a Diffie-Hellman diff --git a/src/common/crypto.h b/src/common/crypto.h index 1a8c81f837..771c49c2d1 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -91,6 +91,8 @@ int crypto_global_cleanup(void); crypto_pk_env_t *crypto_new_pk_env(void); void crypto_free_pk_env(crypto_pk_env_t *env); +void crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname); + /* convenience function: wraps crypto_create_crypto_env, set_key, and init. */ crypto_cipher_env_t *crypto_create_init_cipher(const char *key, int encrypt_mode); @@ -150,6 +152,7 @@ int crypto_pk_private_hybrid_decrypt(crypto_pk_env_t *env, char *to, int crypto_pk_asn1_encode(crypto_pk_env_t *pk, char *dest, size_t dest_len); crypto_pk_env_t *crypto_pk_asn1_decode(const char *str, size_t len); int crypto_pk_get_digest(crypto_pk_env_t *pk, char *digest_out); +int crypto_pk_get_all_digests(crypto_pk_env_t *pk, digests_t *digests_out); int crypto_pk_get_fingerprint(crypto_pk_env_t *pk, char *fp_out,int add_space); int crypto_pk_check_fingerprint_syntax(const char *s); @@ -195,6 +198,9 @@ void crypto_digest_assign(crypto_digest_env_t *into, void crypto_hmac_sha1(char *hmac_out, const char *key, size_t key_len, const char *msg, size_t msg_len); +void crypto_hmac_sha256(char *hmac_out, + const char *key, size_t key_len, + const char *msg, size_t msg_len); /* Key negotiation */ #define DH_TYPE_CIRCUIT 1 @@ -245,7 +251,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 ac98f13539..97400623e5 100644 --- a/src/common/log.c +++ b/src/common/log.c @@ -154,6 +154,17 @@ log_set_application_name(const char *name) appname = name ? tor_strdup(name) : NULL; } +/** Log time granularity in milliseconds. */ +static int log_time_granularity = 1; + +/** Define log time granularity for all logs to be <b>granularity_msec</b> + * milliseconds. */ +void +set_log_time_granularity(int granularity_msec) +{ + log_time_granularity = granularity_msec; +} + /** Helper: Write the standard prefix for log lines to a * <b>buf_len</b> character buffer in <b>buf</b>. */ @@ -164,14 +175,22 @@ _log_prefix(char *buf, size_t buf_len, int severity) struct timeval now; struct tm tm; size_t n; - int r; + int r, ms; tor_gettimeofday(&now); t = (time_t)now.tv_sec; + ms = (int)now.tv_usec / 1000; + if (log_time_granularity >= 1000) { + t -= t % (log_time_granularity / 1000); + ms = 0; + } else { + ms -= ((int)now.tv_usec / 1000) % log_time_granularity; + } n = strftime(buf, buf_len, "%b %d %H:%M:%S", tor_localtime_r(&t, &tm)); - r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ", - (int)now.tv_usec / 1000, sev_to_string(severity)); + r = tor_snprintf(buf+n, buf_len-n, ".%.3i [%s] ", ms, + sev_to_string(severity)); + if (r<0) return buf_len-1; else @@ -703,7 +722,7 @@ change_callback_log_severity(int loglevelMin, int loglevelMax, UNLOCK_LOGS(); } -/** If there are any log messages that were genered with LD_NOCB waiting to +/** If there are any log messages that were generated with LD_NOCB waiting to * be sent to callback-based loggers, send them now. */ void flush_pending_log_callbacks(void) @@ -803,7 +822,7 @@ add_file_log(const log_severity_list_t *severity, const char *filename) int fd; logfile_t *lf; - fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0644); + fd = tor_open_cloexec(filename, O_WRONLY|O_CREAT|O_APPEND, 0644); if (fd<0) return -1; if (tor_fd_seekend(fd)<0) @@ -880,7 +899,7 @@ log_level_to_string(int level) static const char *domain_list[] = { "GENERAL", "CRYPTO", "NET", "CONFIG", "FS", "PROTOCOL", "MM", "HTTP", "APP", "CONTROL", "CIRC", "REND", "BUG", "DIR", "DIRSERV", - "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", NULL + "OR", "EDGE", "ACCT", "HIST", "HANDSHAKE", "HEARTBEAT", NULL }; /** Return a bitmask for the log domain for which <b>domain</b> is the name, diff --git a/src/common/mempool.c b/src/common/mempool.c index c444923189..1462c5f8fe 100644 --- a/src/common/mempool.c +++ b/src/common/mempool.c @@ -62,7 +62,6 @@ #if 1 /* Tor dependencies */ -#include "orconfig.h" #include "util.h" #include "compat.h" #include "torlog.h" @@ -137,7 +136,7 @@ struct mp_chunk_t { int capacity; /**< Number of items that can be fit into this chunk. */ size_t mem_size; /**< Number of usable bytes in mem. */ char *next_mem; /**< Pointer into part of <b>mem</b> not yet carved up. */ - char mem[1]; /**< Storage for this chunk. (Not actual size.) */ + char mem[FLEXIBLE_ARRAY_MEMBER]; /**< Storage for this chunk. */ }; /** Number of extra bytes needed beyond mem_size to allocate a chunk. */ diff --git a/src/common/torgzip.c b/src/common/torgzip.c index a26e5b21e5..62e4a07035 100644 --- a/src/common/torgzip.c +++ b/src/common/torgzip.c @@ -44,11 +44,7 @@ #define off64_t int64_t #endif -#ifdef _MSC_VER -#include "..\..\contrib\zlib\zlib.h" -#else #include <zlib.h> -#endif /** Set to 1 if zlib is a version that supports gzip; set to 0 if it doesn't; * set to -1 if we haven't checked yet. */ diff --git a/src/common/torint.h b/src/common/torint.h index 0b5c29adc0..af975471f1 100644 --- a/src/common/torint.h +++ b/src/common/torint.h @@ -111,6 +111,15 @@ typedef signed int int32_t; typedef unsigned int uint32_t; #define HAVE_UINT32_T #endif +#ifndef UINT16_MAX +#define UINT16_MAX 0xffffu +#endif +#ifndef INT16_MAX +#define INT16_MAX 0x7fff +#endif +#ifndef INT16_MIN +#define INT16_MIN (-INT16_MAX-1) +#endif #ifndef UINT32_MAX #define UINT32_MAX 0xffffffffu #endif diff --git a/src/common/torlog.h b/src/common/torlog.h index 541a0d1738..4c5729ef53 100644 --- a/src/common/torlog.h +++ b/src/common/torlog.h @@ -92,8 +92,10 @@ #define LD_HIST (1u<<18) /** OR handshaking */ #define LD_HANDSHAKE (1u<<19) +/** Heartbeat messages */ +#define LD_HEARTBEAT (1u<<20) /** Number of logging domains in the code. */ -#define N_LOGGING_DOMAINS 20 +#define N_LOGGING_DOMAINS 21 /** This log message is not safe to send to a callback-based logger * immediately. Used as a flag, not a log domain. */ @@ -145,6 +147,7 @@ void change_callback_log_severity(int loglevelMin, int loglevelMax, log_callback cb); void flush_pending_log_callbacks(void); void log_set_application_name(const char *name); +void set_log_time_granularity(int granularity_msec); void tor_log(int severity, log_domain_mask_t domain, const char *format, ...) CHECK_PRINTF(3,4); diff --git a/src/common/tortls.c b/src/common/tortls.c index 10f4440cb4..18f2684707 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -22,8 +22,12 @@ #include <assert.h> #ifdef MS_WINDOWS /*wrkard for dtls1.h >= 0.9.8m of "#include <winsock.h>"*/ + #ifndef WIN32_WINNT #define WIN32_WINNT 0x400 + #endif + #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x400 + #endif #define WIN32_LEAN_AND_MEAN #if defined(_MSC_VER) && (_MSC_VER < 1300) #include <winsock.h> @@ -44,15 +48,22 @@ #error "We require OpenSSL >= 0.9.7" #endif +#ifdef USE_BUFFEREVENTS +#include <event2/bufferevent_ssl.h> +#include <event2/buffer.h> +#include <event2/event.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> +#include "compat_libevent.h" /* Enable the "v2" TLS handshake. */ @@ -86,22 +97,36 @@ static int use_unsafe_renegotiation_op = 0; * SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION? */ static int use_unsafe_renegotiation_flag = 0; +/** Structure that we use for a single certificate. */ +struct tor_cert_t { + X509 *cert; + uint8_t *encoded; + size_t encoded_len; + unsigned pkey_digests_set : 1; + digests_t cert_digests; + digests_t pkey_digests; +}; + /** Holds a SSL_CTX object and related state used to configure TLS * connections. */ typedef struct tor_tls_context_t { int refcnt; SSL_CTX *ctx; - X509 *my_cert; - X509 *my_id_cert; - crypto_pk_env_t *key; + tor_cert_t *my_link_cert; + tor_cert_t *my_id_cert; + tor_cert_t *my_auth_cert; + crypto_pk_env_t *link_key; + crypto_pk_env_t *auth_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 +134,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 +143,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. */ + unsigned int server_handshake_count:2; size_t wantwrite_n; /**< 0 normally, >0 if we returned wantwrite last * time. */ /** Last values retrieved from BIO_number_read()/write(); see @@ -129,6 +157,11 @@ struct tor_tls_t { /** If set, a callback to invoke whenever the client tries to renegotiate * the handshake. */ void (*negotiated_callback)(tor_tls_t *tls, void *arg); + + /** Callback to invoke whenever a client tries to renegotiate more + than once. */ + void (*excess_renegotiations_callback)(void *); + /** Argument to pass to negotiated_callback. */ void *callback_arg; }; @@ -143,42 +176,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,17 +209,22 @@ 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); + unsigned int key_lifetime, + int is_client); static tor_tls_context_t *tor_tls_context_new(crypto_pk_env_t *identity, - unsigned int key_lifetime); + unsigned int key_lifetime, + int is_client); +static int check_cert_lifetime_internal(int severity, const X509 *cert, + int past_tolerance, int future_tolerance); /** Global TLS contexts. We keep them here because nobody else needs * 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 +248,96 @@ ssl_state_to_string(int ssl_state) return buf; } +/** Write a description of the current state of <b>tls</b> into the + * <b>sz</b>-byte buffer at <b>buf</b>. */ +void +tor_tls_get_state_description(tor_tls_t *tls, char *buf, size_t sz) +{ + const char *ssl_state; + const char *tortls_state; + + if (PREDICT_UNLIKELY(!tls || !tls->ssl)) { + strlcpy(buf, "(No SSL object)", sz); + return; + } + + ssl_state = ssl_state_to_string(tls->ssl->state); + switch (tls->state) { +#define CASE(st) case TOR_TLS_ST_##st: tortls_state = " in "#st ; break + CASE(HANDSHAKE); + CASE(OPEN); + CASE(GOTCLOSE); + CASE(SENTCLOSE); + CASE(CLOSED); + CASE(RENEGOTIATE); +#undef CASE + case TOR_TLS_ST_BUFFEREVENT: + tortls_state = ""; + break; + default: + tortls_state = " in unknown TLS state"; + break; + } + + tor_snprintf(buf, sz, "%s%s", ssl_state, tortls_state); +} + +void +tor_tls_log_one_error(tor_tls_t *tls, unsigned long err, + int severity, int domain, const char *doing) +{ + const char *state = NULL, *addr; + const char *msg, *lib, *func; + int st; + + st = (tls && tls->ssl) ? tls->ssl->state : -1; + state = (st>=0)?ssl_state_to_string(st):"---"; + + addr = tls ? tls->address : NULL; + + /* Some errors are known-benign, meaning they are the fault of the other + * side of the connection. The caller doesn't know this, so override the + * priority for those cases. */ + switch (ERR_GET_REASON(err)) { + case SSL_R_HTTP_REQUEST: + case SSL_R_HTTPS_PROXY_REQUEST: + case SSL_R_RECORD_LENGTH_MISMATCH: + case SSL_R_RECORD_TOO_LARGE: + case SSL_R_UNKNOWN_PROTOCOL: + case SSL_R_UNSUPPORTED_PROTOCOL: + severity = LOG_INFO; + break; + default: + break; + } + + msg = (const char*)ERR_reason_error_string(err); + lib = (const char*)ERR_lib_error_string(err); + func = (const char*)ERR_func_error_string(err); + if (!msg) msg = "(null)"; + if (!lib) lib = "(null)"; + if (!func) func = "(null)"; + if (doing) { + log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)", + doing, addr?" with ":"", addr?addr:"", + msg, lib, func, state); + } else { + log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)", + addr?" with ":"", addr?addr:"", + msg, lib, func, state); + } +} + /** Log all pending tls errors at level <b>severity</b>. Use * <b>doing</b> to describe our current activities. */ static void tls_log_errors(tor_tls_t *tls, int severity, int domain, const char *doing) { - const char *state = NULL; - int st; unsigned long err; - const char *msg, *lib, *func, *addr; - addr = tls ? tls->address : NULL; - st = (tls && tls->ssl) ? tls->ssl->state : -1; + while ((err = ERR_get_error()) != 0) { - msg = (const char*)ERR_reason_error_string(err); - lib = (const char*)ERR_lib_error_string(err); - func = (const char*)ERR_func_error_string(err); - if (!state) - state = (st>=0)?ssl_state_to_string(st):"---"; - if (!msg) msg = "(null)"; - if (!lib) lib = "(null)"; - if (!func) func = "(null)"; - if (doing) { - log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)", - doing, addr?" with ":"", addr?addr:"", - msg, lib, func, state); - } else { - log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)", - addr?" with ":"", addr?addr:"", - msg, lib, func, state); - } + tor_tls_log_one_error(tls, err, severity, domain, doing); } } @@ -427,6 +512,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 +532,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); @@ -502,7 +585,13 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa, const char *cname_sign, unsigned int cert_lifetime) { + /* OpenSSL generates self-signed certificates with random 64-bit serial + * numbers, so let's do that too. */ +#define SERIAL_NUMBER_SIZE 8 + time_t start_time, end_time; + BIGNUM *serial_number = NULL; + unsigned char serial_tmp[SERIAL_NUMBER_SIZE]; EVP_PKEY *sign_pkey = NULL, *pkey=NULL; X509 *x509 = NULL; X509_NAME *name = NULL, *name_issuer=NULL; @@ -523,8 +612,15 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa, goto error; if (!(X509_set_version(x509, 2))) goto error; - if (!(ASN1_INTEGER_set(X509_get_serialNumber(x509), (long)start_time))) - goto error; + + { /* our serial number is 8 random bytes. */ + if (crypto_rand((char *)serial_tmp, sizeof(serial_tmp)) < 0) + goto error; + if (!(serial_number = BN_bin2bn(serial_tmp, sizeof(serial_tmp), NULL))) + goto error; + if (!(BN_to_ASN1_INTEGER(serial_number, X509_get_serialNumber(x509)))) + goto error; + } if (!(name = tor_x509_name_new(cname))) goto error; @@ -557,11 +653,15 @@ tor_tls_create_certificate(crypto_pk_env_t *rsa, EVP_PKEY_free(sign_pkey); if (pkey) EVP_PKEY_free(pkey); + if (serial_number) + BN_free(serial_number); if (name) X509_NAME_free(name); if (name_issuer) X509_NAME_free(name_issuer); return x509; + +#undef SERIAL_NUMBER_SIZE } /** List of ciphers that servers should select from.*/ @@ -608,6 +708,137 @@ static const int N_CLIENT_CIPHERS = SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA) #endif +/** Free all storage held in <b>cert</b> */ +void +tor_cert_free(tor_cert_t *cert) +{ + if (! cert) + return; + if (cert->cert) + X509_free(cert->cert); + tor_free(cert->encoded); + memset(cert, 0x03, sizeof(*cert)); + tor_free(cert); +} + +/** + * Allocate a new tor_cert_t to hold the certificate "x509_cert". + * + * Steals a reference to x509_cert. + */ +static tor_cert_t * +tor_cert_new(X509 *x509_cert) +{ + tor_cert_t *cert; + EVP_PKEY *pkey; + RSA *rsa; + int length, length2; + unsigned char *cp; + + if (!x509_cert) + return NULL; + + length = i2d_X509(x509_cert, NULL); + cert = tor_malloc_zero(sizeof(tor_cert_t)); + if (length <= 0) { + tor_free(cert); + log_err(LD_CRYPTO, "Couldn't get length of encoded x509 certificate"); + X509_free(x509_cert); + return NULL; + } + cert->encoded_len = (size_t) length; + cp = cert->encoded = tor_malloc(length); + length2 = i2d_X509(x509_cert, &cp); + tor_assert(length2 == length); + + cert->cert = x509_cert; + + crypto_digest_all(&cert->cert_digests, + (char*)cert->encoded, cert->encoded_len); + + if ((pkey = X509_get_pubkey(x509_cert)) && + (rsa = EVP_PKEY_get1_RSA(pkey))) { + crypto_pk_env_t *pk = _crypto_new_pk_env_rsa(rsa); + crypto_pk_get_all_digests(pk, &cert->pkey_digests); + cert->pkey_digests_set = 1; + crypto_free_pk_env(pk); + EVP_PKEY_free(pkey); + } + + return cert; +} + +/** Read a DER-encoded X509 cert, of length exactly <b>certificate_len</b>, + * from a <b>certificate</b>. Return a newly allocated tor_cert_t on success + * and NULL on failure. */ +tor_cert_t * +tor_cert_decode(const uint8_t *certificate, size_t certificate_len) +{ + X509 *x509; + const unsigned char *cp = (const unsigned char *)certificate; + tor_cert_t *newcert; + tor_assert(certificate); + + if (certificate_len > INT_MAX) + return NULL; + +#if OPENSSL_VERSION_NUMBER < 0x00908000l + /* This ifdef suppresses a type warning. Take out this case once everybody + * is using OpenSSL 0.9.8 or later. */ + x509 = d2i_X509(NULL, (unsigned char**)&cp, (int)certificate_len); +#else + x509 = d2i_X509(NULL, &cp, (int)certificate_len); +#endif + if (!x509) + return NULL; /* Couldn't decode */ + if (cp - certificate != (int)certificate_len) { + X509_free(x509); + return NULL; /* Didn't use all the bytes */ + } + newcert = tor_cert_new(x509); + if (!newcert) { + return NULL; + } + if (newcert->encoded_len != certificate_len || + fast_memneq(newcert->encoded, certificate, certificate_len)) { + /* Cert wasn't in DER */ + tor_cert_free(newcert); + return NULL; + } + return newcert; +} + +/** Set *<b>encoded_out</b> and *<b>size_out/b> to <b>cert</b>'s encoded DER + * representation and length, respectively. */ +void +tor_cert_get_der(const tor_cert_t *cert, + const uint8_t **encoded_out, size_t *size_out) +{ + tor_assert(cert); + tor_assert(encoded_out); + tor_assert(size_out); + *encoded_out = cert->encoded; + *size_out = cert->encoded_len; +} + +/** Return a set of digests for the public key in <b>cert</b>, or NULL if this + * cert's public key is not one we know how to take the digest of. */ +const digests_t * +tor_cert_get_id_digests(const tor_cert_t *cert) +{ + if (cert->pkey_digests_set) + return &cert->pkey_digests; + else + return NULL; +} + +/** Return a set of digests for the public key in <b>cert</b>. */ +const digests_t * +tor_cert_get_cert_digests(const tor_cert_t *cert) +{ + return &cert->cert_digests; +} + /** Remove a reference to <b>ctx</b>, and free it if it has no more * references. */ static void @@ -616,13 +847,172 @@ tor_tls_context_decref(tor_tls_context_t *ctx) tor_assert(ctx); if (--ctx->refcnt == 0) { SSL_CTX_free(ctx->ctx); - X509_free(ctx->my_cert); - X509_free(ctx->my_id_cert); - crypto_free_pk_env(ctx->key); + tor_cert_free(ctx->my_link_cert); + tor_cert_free(ctx->my_id_cert); + tor_cert_free(ctx->my_auth_cert); + crypto_free_pk_env(ctx->link_key); + crypto_free_pk_env(ctx->auth_key); tor_free(ctx); } } +/** Set *<b>link_cert_out</b> and *<b>id_cert_out</b> to the link certificate + * and ID certificate that we're currently using for our V3 in-protocol + * handshake's certificate chain. If <b>server</b> is true, provide the certs + * that we use in server mode; otherwise, provide the certs that we use in + * client mode. */ +int +tor_tls_get_my_certs(int server, + const tor_cert_t **link_cert_out, + const tor_cert_t **id_cert_out) +{ + tor_tls_context_t *ctx = server ? server_tls_context : client_tls_context; + if (! ctx) + return -1; + if (link_cert_out) + *link_cert_out = server ? ctx->my_link_cert : ctx->my_auth_cert; + if (id_cert_out) + *id_cert_out = ctx->my_id_cert; + return 0; +} + +/** + * Return the authentication key that we use to authenticate ourselves as a + * client in the V3 in-protocol handshake. + */ +crypto_pk_env_t * +tor_tls_get_my_client_auth_key(void) +{ + if (! client_tls_context) + return NULL; + return client_tls_context->auth_key; +} + +/** + * Return a newly allocated copy of the public key that a certificate + * certifies. Return NULL if the cert's key is not RSA. + */ +crypto_pk_env_t * +tor_tls_cert_get_key(tor_cert_t *cert) +{ + crypto_pk_env_t *result = NULL; + EVP_PKEY *pkey = X509_get_pubkey(cert->cert); + RSA *rsa; + if (!pkey) + return NULL; + rsa = EVP_PKEY_get1_RSA(pkey); + if (!rsa) { + EVP_PKEY_free(pkey); + return NULL; + } + result = _crypto_new_pk_env_rsa(rsa); + EVP_PKEY_free(pkey); + return result; +} + +/** Return true iff <b>a</b> and <b>b</b> represent the same public key. */ +static int +pkey_eq(EVP_PKEY *a, EVP_PKEY *b) +{ + /* We'd like to do this, but openssl 0.9.7 doesn't have it: + return EVP_PKEY_cmp(a,b) == 1; + */ + unsigned char *a_enc=NULL, *b_enc=NULL, *a_ptr, *b_ptr; + int a_len1, b_len1, a_len2, b_len2, result; + a_len1 = i2d_PublicKey(a, NULL); + b_len1 = i2d_PublicKey(b, NULL); + if (a_len1 != b_len1) + return 0; + a_ptr = a_enc = tor_malloc(a_len1); + b_ptr = b_enc = tor_malloc(b_len1); + a_len2 = i2d_PublicKey(a, &a_ptr); + b_len2 = i2d_PublicKey(b, &b_ptr); + tor_assert(a_len2 == a_len1); + tor_assert(b_len2 == b_len1); + result = tor_memeq(a_enc, b_enc, a_len1); + tor_free(a_enc); + tor_free(b_enc); + return result; +} + +/** Return true iff the other side of <b>tls</b> has authenticated to us, and + * the key certified in <b>cert</b> is the same as the key they used to do it. + */ +int +tor_tls_cert_matches_key(const tor_tls_t *tls, const tor_cert_t *cert) +{ + X509 *peercert = SSL_get_peer_certificate(tls->ssl); + EVP_PKEY *link_key = NULL, *cert_key = NULL; + int result; + + if (!peercert) + return 0; + link_key = X509_get_pubkey(peercert); + cert_key = X509_get_pubkey(cert->cert); + + result = link_key && cert_key && pkey_eq(cert_key, link_key); + + X509_free(peercert); + if (link_key) + EVP_PKEY_free(link_key); + if (cert_key) + EVP_PKEY_free(cert_key); + + return result; +} + +/** Check whether <b>cert</b> is well-formed, currently live, and correctly + * signed by the public key in <b>signing_cert</b>. If <b>check_rsa_1024</b>, + * make sure that it has an RSA key with 1024 bits; otherwise, just check that + * the key is long enough. Return 1 if the cert is good, and 0 if it's bad or + * we couldn't check it. */ +int +tor_tls_cert_is_valid(int severity, + const tor_cert_t *cert, + const tor_cert_t *signing_cert, + int check_rsa_1024) +{ + EVP_PKEY *cert_key; + EVP_PKEY *signing_key = X509_get_pubkey(signing_cert->cert); + int r, key_ok = 0; + if (!signing_key) + return 0; + r = X509_verify(cert->cert, signing_key); + EVP_PKEY_free(signing_key); + if (r <= 0) + return 0; + + /* okay, the signature checked out right. Now let's check the check the + * lifetime. */ + if (check_cert_lifetime_internal(severity, cert->cert, + 48*60*60, 30*24*60*60) < 0) + return 0; + + cert_key = X509_get_pubkey(cert->cert); + if (check_rsa_1024 && cert_key) { + RSA *rsa = EVP_PKEY_get1_RSA(cert_key); + if (rsa && BN_num_bits(rsa->n) == 1024) + key_ok = 1; + if (rsa) + RSA_free(rsa); + } else if (cert_key) { + int min_bits = 1024; +#ifdef EVP_PKEY_EC + if (EVP_PKEY_type(cert_key->type) == EVP_PKEY_EC) + min_bits = 128; +#endif + if (EVP_PKEY_bits(cert_key) >= min_bits) + key_ok = 1; + } + EVP_PKEY_free(cert_key); + if (!key_ok) + return 0; + + /* XXXX compare DNs or anything? */ + + return 1; +} + /** Increase the reference count of <b>ctx</b>. */ static void tor_tls_context_incref(tor_tls_context_t *ctx) @@ -653,7 +1043,7 @@ tor_tls_context_init(int is_public_server, rv1 = tor_tls_context_init_one(&server_tls_context, server_identity, - key_lifetime); + key_lifetime, 0); if (rv1 >= 0) { new_ctx = server_tls_context; @@ -669,7 +1059,8 @@ tor_tls_context_init(int is_public_server, if (server_identity != NULL) { rv1 = tor_tls_context_init_one(&server_tls_context, server_identity, - key_lifetime); + key_lifetime, + 0); } else { tor_tls_context_t *old_ctx = server_tls_context; server_tls_context = NULL; @@ -681,7 +1072,8 @@ tor_tls_context_init(int is_public_server, rv2 = tor_tls_context_init_one(&client_tls_context, client_identity, - key_lifetime); + key_lifetime, + 1); } return MIN(rv1, rv2); @@ -696,10 +1088,12 @@ tor_tls_context_init(int is_public_server, static int tor_tls_context_init_one(tor_tls_context_t **ppcontext, crypto_pk_env_t *identity, - unsigned int key_lifetime) + unsigned int key_lifetime, + int is_client) { tor_tls_context_t *new_ctx = tor_tls_context_new(identity, - key_lifetime); + key_lifetime, + is_client); tor_tls_context_t *old_ctx = *ppcontext; if (new_ctx != NULL) { @@ -721,39 +1115,61 @@ tor_tls_context_init_one(tor_tls_context_t **ppcontext, * certificate. */ static tor_tls_context_t * -tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime) +tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime, + int is_client) { - crypto_pk_env_t *rsa = NULL; + crypto_pk_env_t *rsa = NULL, *rsa_auth = NULL; EVP_PKEY *pkey = NULL; tor_tls_context_t *result = NULL; - X509 *cert = NULL, *idcert = NULL; + X509 *cert = NULL, *idcert = NULL, *authcert = NULL; char *nickname = NULL, *nn2 = NULL; tor_tls_init(); nickname = crypto_random_hostname(8, 20, "www.", ".net"); +#ifdef DISABLE_V3_LINKPROTO_SERVERSIDE nn2 = crypto_random_hostname(8, 20, "www.", ".net"); +#else + nn2 = crypto_random_hostname(8, 20, "www.", ".com"); +#endif - /* Generate short-term RSA key. */ + /* Generate short-term RSA key for use with TLS. */ if (!(rsa = crypto_new_pk_env())) goto error; if (crypto_pk_generate_key(rsa)<0) goto error; - /* Create certificate signed by identity key. */ - cert = tor_tls_create_certificate(rsa, identity, nickname, nn2, - key_lifetime); - /* Create self-signed certificate for identity key. */ - idcert = tor_tls_create_certificate(identity, identity, nn2, nn2, - IDENTITY_CERT_LIFETIME); - if (!cert || !idcert) { - log(LOG_WARN, LD_CRYPTO, "Error creating certificate"); - goto error; + if (!is_client) { + /* Generate short-term RSA key for use in the in-protocol ("v3") + * authentication handshake. */ + if (!(rsa_auth = crypto_new_pk_env())) + goto error; + if (crypto_pk_generate_key(rsa_auth)<0) + goto error; + /* Create a link certificate signed by identity key. */ + cert = tor_tls_create_certificate(rsa, identity, nickname, nn2, + key_lifetime); + /* Create self-signed certificate for identity key. */ + idcert = tor_tls_create_certificate(identity, identity, nn2, nn2, + IDENTITY_CERT_LIFETIME); + /* Create an authentication certificate signed by identity key. */ + authcert = tor_tls_create_certificate(rsa_auth, identity, nickname, nn2, + key_lifetime); + if (!cert || !idcert || !authcert) { + log(LOG_WARN, LD_CRYPTO, "Error creating certificate"); + goto error; + } } result = tor_malloc_zero(sizeof(tor_tls_context_t)); result->refcnt = 1; - result->my_cert = X509_dup(cert); - result->my_id_cert = X509_dup(idcert); - result->key = crypto_pk_dup_key(rsa); + if (!is_client) { + result->my_link_cert = tor_cert_new(X509_dup(cert)); + result->my_id_cert = tor_cert_new(X509_dup(idcert)); + result->my_auth_cert = tor_cert_new(X509_dup(authcert)); + if (!result->my_link_cert || !result->my_id_cert || !result->my_auth_cert) + goto error; + result->link_key = crypto_pk_dup_key(rsa); + result->auth_key = crypto_pk_dup_key(rsa_auth); + } #ifdef EVERYONE_HAS_AES /* Tell OpenSSL to only use TLS1 */ @@ -785,27 +1201,31 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime) #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(result->ctx, SSL_MODE_RELEASE_BUFFERS); #endif - if (cert && !SSL_CTX_use_certificate(result->ctx,cert)) - goto error; - X509_free(cert); /* We just added a reference to cert. */ - cert=NULL; - if (idcert) { - X509_STORE *s = SSL_CTX_get_cert_store(result->ctx); - tor_assert(s); - X509_STORE_add_cert(s, idcert); - X509_free(idcert); /* The context now owns the reference to idcert */ - idcert = NULL; + if (! is_client) { + if (cert && !SSL_CTX_use_certificate(result->ctx,cert)) + goto error; + X509_free(cert); /* We just added a reference to cert. */ + cert=NULL; + if (idcert) { + X509_STORE *s = SSL_CTX_get_cert_store(result->ctx); + tor_assert(s); + X509_STORE_add_cert(s, idcert); + X509_free(idcert); /* The context now owns the reference to idcert */ + idcert = NULL; + } } SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF); - tor_assert(rsa); - if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,1))) - goto error; - if (!SSL_CTX_use_PrivateKey(result->ctx, pkey)) - goto error; - EVP_PKEY_free(pkey); - pkey = NULL; - if (!SSL_CTX_check_private_key(result->ctx)) - goto error; + if (!is_client) { + tor_assert(rsa); + if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,1))) + goto error; + if (!SSL_CTX_use_PrivateKey(result->ctx, pkey)) + goto error; + EVP_PKEY_free(pkey); + pkey = NULL; + if (!SSL_CTX_check_private_key(result->ctx)) + goto error; + } { crypto_dh_env_t *dh = crypto_dh_new(DH_TYPE_TLS); tor_assert(dh); @@ -819,6 +1239,9 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime) if (rsa) crypto_free_pk_env(rsa); + if (rsa_auth) + crypto_free_pk_env(rsa_auth); + X509_free(authcert); tor_free(nickname); tor_free(nn2); return result; @@ -831,12 +1254,16 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime) EVP_PKEY_free(pkey); if (rsa) crypto_free_pk_env(rsa); + if (rsa_auth) + crypto_free_pk_env(rsa_auth); if (result) tor_tls_context_decref(result); if (cert) X509_free(cert); if (idcert) X509_free(idcert); + if (authcert) + X509_free(authcert); return NULL; } @@ -892,45 +1319,49 @@ tor_tls_client_is_using_v2_ciphers(const SSL *ssl, const char *address) return 1; } -/** 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 - * do not send or request extra certificates in v2 handshakes.</li> - * <li>To detect renegotiation</li></ul> - */ +/** We got an SSL ClientHello message. This might mean that the + * client wants to initiate a renegotiation and appropriate actions + * must be taken. */ static void -tor_tls_server_info_callback(const SSL *ssl, int type, int val) +tor_tls_got_client_hello(tor_tls_t *tls) { - tor_tls_t *tls; - (void) val; - if (type != SSL_CB_ACCEPT_LOOP) - return; - if (ssl->state != SSL3_ST_SW_SRVR_HELLO_A) - return; + if (tls->server_handshake_count < 3) + ++tls->server_handshake_count; - tls = tor_tls_get_by_ssl(ssl); - if (tls) { - /* Check whether we're watching for renegotiates. If so, this is one! */ - if (tls->negotiated_callback) - tls->got_renegotiate = 1; - } else { - log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!"); + if (tls->server_handshake_count == 2) { + if (!tls->negotiated_callback) { + log_warn(LD_BUG, "Got a renegotiation request but we don't" + " have a renegotiation callback set!"); + } + + tls->got_renegotiate = 1; + } else if (tls->server_handshake_count > 2 && + tls->excess_renegotiations_callback) { + /* We got more than one renegotiation requests. The Tor protocol + needs just one renegotiation; more than that probably means + They are trying to DoS us and we have to stop them. */ + + tls->excess_renegotiations_callback(tls->callback_arg); } /* Now check the cipher list. */ - if (tor_tls_client_is_using_v2_ciphers(ssl, ADDR(tls))) { + if (tor_tls_client_is_using_v2_ciphers(tls->ssl, ADDR(tls))) { /*XXXX_TLS keep this from happening more than once! */ /* Yes, we're casting away the const from ssl. This is very naughty of us. * Let's hope openssl doesn't notice! */ /* Set SSL_MODE_NO_AUTO_CHAIN to keep from sending back any extra certs. */ - SSL_set_mode((SSL*) ssl, SSL_MODE_NO_AUTO_CHAIN); + SSL_set_mode((SSL*) tls->ssl, SSL_MODE_NO_AUTO_CHAIN); /* Don't send a hello request. */ - SSL_set_verify((SSL*) ssl, SSL_VERIFY_NONE, NULL); + SSL_set_verify((SSL*) tls->ssl, SSL_VERIFY_NONE, NULL); 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!"); } @@ -938,6 +1369,34 @@ tor_tls_server_info_callback(const SSL *ssl, int type, int val) } #endif +/** This is a callback function for SSL_set_info_callback() and it + * will be called in every SSL state change. + * It logs the SSL state change, and executes any actions that must be + * taken. */ +static void +tor_tls_state_changed_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); + +#ifdef V2_HANDSHAKE_SERVER + if (type == SSL_CB_ACCEPT_LOOP && + ssl->state == SSL3_ST_SW_SRVR_HELLO_A) { + + /* Call tor_tls_got_client_hello() for every SSL ClientHello we + receive. */ + + tor_tls_t *tls = tor_tls_get_by_ssl(ssl); + if (!tls) { + log_warn(LD_BUG, "Couldn't look up the tls for an SSL*. How odd!"); + return; + } + + tor_tls_got_client_hello(tls); + } +#endif +} + /** Replace *<b>ciphers</b> with a new list of SSL ciphersuites: specifically, * a list designed to mimic a common web browser. Some of the ciphers in the * list won't actually be implemented by OpenSSL: that's okay so long as the @@ -1018,6 +1477,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 +1518,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; @@ -1071,11 +1538,8 @@ tor_tls_new(int sock, int isServer) log_warn(LD_NET, "Newly created BIO has read count %lu, write count %lu", result->last_read_count, result->last_write_count); } -#ifdef V2_HANDSHAKE_SERVER - if (isServer) { - SSL_set_info_callback(result->ssl, tor_tls_server_info_callback); - } -#endif + + SSL_set_info_callback(result->ssl, tor_tls_state_changed_callback); /* Not expected to get called. */ tls_log_errors(NULL, LOG_WARN, LD_NET, "creating tor_tls_t object"); @@ -1093,31 +1557,28 @@ tor_tls_set_logged_address(tor_tls_t *tls, const char *address) tls->address = tor_strdup(address); } -/** Set <b>cb</b> to be called with argument <b>arg</b> whenever <b>tls</b> - * next gets a client-side renegotiate in the middle of a read. Do not - * invoke this function until <em>after</em> initial handshaking is done! +/** Set <b>cb</b> to be called with argument <b>arg</b> whenever + * <b>tls</b> next gets a client-side renegotiate in the middle of a + * read. Set <b>cb2</b> to be called with argument <b>arg</b> whenever + * <b>tls</b> gets excess renegotiation requests. Do not invoke this + * function until <em>after</em> initial handshaking is done! */ void -tor_tls_set_renegotiate_callback(tor_tls_t *tls, +tor_tls_set_renegotiate_callbacks(tor_tls_t *tls, void (*cb)(tor_tls_t *, void *arg), + void (*cb2)(void *), void *arg) { tls->negotiated_callback = cb; + tls->excess_renegotiations_callback = cb2; tls->callback_arg = arg; tls->got_renegotiate = 0; -#ifdef V2_HANDSHAKE_SERVER - if (cb) { - SSL_set_info_callback(tls->ssl, tor_tls_server_info_callback); - } else { - SSL_set_info_callback(tls->ssl, NULL); - } -#endif } /** 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 @@ -1131,14 +1592,17 @@ tor_tls_unblock_renegotiation(tor_tls_t *tls) } } -/** If this version of openssl supports it, turn off renegotiation on - * <b>tls</b>. (Our protocol never requires this for security, but it's nice - * to use belt-and-suspenders here.) - */ void -tor_tls_block_renegotiation(tor_tls_t *tls) +tor_tls_assert_renegotiation_unblocked(tor_tls_t *tls) { - tls->ssl->s3->flags &= ~SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION; + 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 @@ -1156,23 +1620,20 @@ 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 SSL_free(tls->ssl); tls->ssl = NULL; tls->negotiated_callback = NULL; + tls->excess_renegotiations_callback = NULL; if (tls->context) tor_tls_context_decref(tls->context); tor_free(tls->address); + tls->magic = 0x99999999; tor_free(tls); } @@ -1190,19 +1651,30 @@ tor_tls_read(tor_tls_t *tls, char *cp, size_t len) tor_assert(tls->state == TOR_TLS_ST_OPEN); tor_assert(len<INT_MAX); r = SSL_read(tls->ssl, cp, (int)len); - if (r > 0) { + if (r > 0) /* return the number of characters read */ + return r; + + /* If we got here, SSL_read() did not go as expected. */ + + err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_DEBUG, LD_NET); + #ifdef V2_HANDSHAKE_SERVER - if (tls->got_renegotiate) { - /* Renegotiation happened! */ - log_info(LD_NET, "Got a TLS renegotiation from %s", ADDR(tls)); - if (tls->negotiated_callback) - tls->negotiated_callback(tls, tls->callback_arg); - tls->got_renegotiate = 0; + if (tls->got_renegotiate) { + if (tls->server_handshake_count != 2) { + log_warn(LD_BUG, "We did not notice renegotiation in a timely " + "fashion (%u)!", tls->server_handshake_count); } -#endif + + /* Renegotiation happened! */ + log_info(LD_NET, "Got a TLS renegotiation from %s", ADDR(tls)); + if (tls->negotiated_callback) + tls->negotiated_callback(tls, tls->callback_arg); + tls->got_renegotiate = 0; + return r; } - err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_DEBUG, LD_NET); +#endif + if (err == _TOR_TLS_ZERORETURN || err == TOR_TLS_CLOSE) { log_debug(LD_NET,"read returned r=%d; TLS is closed",r); tls->state = TOR_TLS_ST_CLOSED; @@ -1239,6 +1711,7 @@ tor_tls_write(tor_tls_t *tls, const char *cp, size_t n) } r = SSL_write(tls->ssl, cp, (int)n); err = tor_tls_get_error(tls, r, 0, "writing", LOG_INFO, LD_NET); + if (err == TOR_TLS_DONE) { return r; } @@ -1285,56 +1758,85 @@ 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_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. @@ -1440,9 +1942,21 @@ tor_tls_peer_has_cert(tor_tls_t *tls) return 1; } +/** Return the peer certificate, or NULL if there isn't one. */ +tor_cert_t * +tor_tls_get_peer_cert(tor_tls_t *tls) +{ + X509 *cert; + cert = SSL_get_peer_certificate(tls->ssl); + tls_log_errors(tls, LOG_WARN, LD_HANDSHAKE, "getting peer certificate"); + if (!cert) + return NULL; + return tor_cert_new(cert); +} + /** Warn that a certificate lifetime extends through a certain range. */ static void -log_cert_lifetime(X509 *cert, const char *problem) +log_cert_lifetime(int severity, const X509 *cert, const char *problem) { BIO *bio = NULL; BUF_MEM *buf; @@ -1452,9 +1966,10 @@ log_cert_lifetime(X509 *cert, const char *problem) struct tm tm; if (problem) - log_warn(LD_GENERAL, - "Certificate %s: is your system clock set incorrectly?", - problem); + log(severity, LD_GENERAL, + "Certificate %s. Either their clock is set wrong, or your clock " + "is wrong.", + problem); if (!(bio = BIO_new(BIO_s_mem()))) { log_warn(LD_GENERAL, "Couldn't allocate BIO!"); goto end; @@ -1476,9 +1991,9 @@ log_cert_lifetime(X509 *cert, const char *problem) strftime(mytime, 32, "%b %d %H:%M:%S %Y GMT", tor_gmtime_r(&now, &tm)); - log_warn(LD_GENERAL, - "(certificate lifetime runs from %s through %s. Your time is %s.)", - s1,s2,mytime); + log(severity, LD_GENERAL, + "(certificate lifetime runs from %s through %s. Your time is %s.)", + s1,s2,mytime); end: /* Not expected to get invoked */ @@ -1551,6 +2066,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"); @@ -1578,34 +2095,25 @@ tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_env_t **identity_key) return r; } -/** Check whether the certificate set on the connection <b>tls</b> is - * expired or not-yet-valid, give or take <b>tolerance</b> - * seconds. Return 0 for valid, -1 for failure. +/** Check whether the certificate set on the connection <b>tls</b> is expired + * give or take <b>past_tolerance</b> seconds, or not-yet-valid give or take + * <b>future_tolerance</b> seconds. Return 0 for valid, -1 for failure. * * NOTE: you should call tor_tls_verify before tor_tls_check_lifetime. */ int -tor_tls_check_lifetime(tor_tls_t *tls, int tolerance) +tor_tls_check_lifetime(int severity, tor_tls_t *tls, + int past_tolerance, int future_tolerance) { - time_t now, t; X509 *cert; int r = -1; - now = time(NULL); - if (!(cert = SSL_get_peer_certificate(tls->ssl))) goto done; - t = now + tolerance; - if (X509_cmp_time(X509_get_notBefore(cert), &t) > 0) { - log_cert_lifetime(cert, "not yet valid"); - goto done; - } - t = now - tolerance; - if (X509_cmp_time(X509_get_notAfter(cert), &t) < 0) { - log_cert_lifetime(cert, "already expired"); + if (check_cert_lifetime_internal(severity, cert, + past_tolerance, future_tolerance) < 0) goto done; - } r = 0; done: @@ -1617,6 +2125,32 @@ tor_tls_check_lifetime(tor_tls_t *tls, int tolerance) return r; } +/** Helper: check whether <b>cert</b> is expired give or take + * <b>past_tolerance</b> seconds, or not-yet-valid give or take + * <b>future_tolerance</b> seconds. If it is live, return 0. If it is not + * live, log a message and return -1. */ +static int +check_cert_lifetime_internal(int severity, const X509 *cert, + int past_tolerance, int future_tolerance) +{ + time_t now, t; + + now = time(NULL); + + t = now + future_tolerance; + if (X509_cmp_time(X509_get_notBefore(cert), &t) > 0) { + log_cert_lifetime(severity, cert, "not yet valid"); + return -1; + } + t = now - past_tolerance; + if (X509_cmp_time(X509_get_notAfter(cert), &t) < 0) { + log_cert_lifetime(severity, cert, "already expired"); + return -1; + } + + return 0; +} + /** Return the number of bytes available for reading from <b>tls</b>. */ int @@ -1700,6 +2234,138 @@ tor_tls_used_v1_handshake(tor_tls_t *tls) return 1; } +/** Return true iff <b>name</b> is a DN of a kind that could only + * occur in a v3-handshake-indicating certificate */ +static int +dn_indicates_v3_cert(X509_NAME *name) +{ +#ifdef DISABLE_V3_LINKPROTO_CLIENTSIDE + (void)name; + return 0; +#else + X509_NAME_ENTRY *entry; + int n_entries; + ASN1_OBJECT *obj; + ASN1_STRING *str; + unsigned char *s; + int len, r; + + n_entries = X509_NAME_entry_count(name); + if (n_entries != 1) + return 1; /* More than one entry in the DN. */ + entry = X509_NAME_get_entry(name, 0); + + obj = X509_NAME_ENTRY_get_object(entry); + if (OBJ_obj2nid(obj) != OBJ_txt2nid("commonName")) + return 1; /* The entry isn't a commonName. */ + + str = X509_NAME_ENTRY_get_data(entry); + len = ASN1_STRING_to_UTF8(&s, str); + if (len < 0) + return 0; + r = fast_memneq(s + len - 4, ".net", 4); + OPENSSL_free(s); + return r; +#endif +} + +/** Return true iff the peer certificate we're received on <b>tls</b> + * indicates that this connection should use the v3 (in-protocol) + * authentication handshake. + * + * Only the connection initiator should use this, and only once the initial + * handshake is done; the responder detects a v1 handshake by cipher types, + * and a v3/v2 handshake by Versions cell vs renegotiation. + */ +int +tor_tls_received_v3_certificate(tor_tls_t *tls) +{ + X509 *cert = SSL_get_peer_certificate(tls->ssl); + EVP_PKEY *key = NULL; + X509_NAME *issuer_name, *subject_name; + int is_v3 = 0; + + if (!cert) { + log_warn(LD_BUG, "Called on a connection with no peer certificate"); + goto done; + } + + subject_name = X509_get_subject_name(cert); + issuer_name = X509_get_issuer_name(cert); + + if (X509_name_cmp(subject_name, issuer_name) == 0) { + is_v3 = 1; /* purportedly self signed */ + goto done; + } + + if (dn_indicates_v3_cert(subject_name) || + dn_indicates_v3_cert(issuer_name)) { + is_v3 = 1; /* DN is fancy */ + goto done; + } + + key = X509_get_pubkey(cert); + if (EVP_PKEY_bits(key) != 1024 || + EVP_PKEY_type(key->type) != EVP_PKEY_RSA) { + is_v3 = 1; /* Key is fancy */ + goto done; + } + + done: + if (key) + EVP_PKEY_free(key); + if (cert) + X509_free(cert); + + return is_v3; +} + +/** 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; +} + +/** Set the DIGEST256_LEN buffer at <b>secrets_out</b> to the value used in + * the v3 handshake to prove that the client knows the TLS secrets for the + * connection <b>tls</b>. Return 0 on success, -1 on failure. + */ +int +tor_tls_get_tlssecrets(tor_tls_t *tls, uint8_t *secrets_out) +{ +#define TLSSECRET_MAGIC "Tor V3 handshake TLS cross-certification" + char buf[128]; + size_t len; + tor_assert(tls); + tor_assert(tls->ssl); + tor_assert(tls->ssl->s3); + tor_assert(tls->ssl->session); + /* + The value is an HMAC, using the TLS master key as the HMAC key, of + client_random | server_random | TLSSECRET_MAGIC + */ + memcpy(buf + 0, tls->ssl->s3->client_random, 32); + memcpy(buf + 32, tls->ssl->s3->server_random, 32); + memcpy(buf + 64, TLSSECRET_MAGIC, strlen(TLSSECRET_MAGIC) + 1); + len = 64 + strlen(TLSSECRET_MAGIC) + 1; + crypto_hmac_sha256((char*)secrets_out, + (char*)tls->ssl->session->master_key, + tls->ssl->session->master_key_length, + buf, len); + memset(buf, 0, sizeof(buf)); + return 0; +} + /** 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 +2388,75 @@ tor_tls_get_buffer_sizes(tor_tls_t *tls, *wbuf_bytes = tls->ssl->s3->wbuf.left; } +#ifdef USE_BUFFEREVENTS +/** Construct and return an TLS-encrypting bufferevent to send data over + * <b>socket</b>, which must match the socket of the underlying bufferevent + * <b>bufev_in</b>. The TLS object <b>tls</b> is used for encryption. + * + * This function will either create a filtering bufferevent that wraps around + * <b>bufev_in</b>, or it will free bufev_in and return a new bufferevent that + * uses the <b>tls</b> to talk to the network directly. Do not use + * <b>bufev_in</b> after calling this function. + * + * The connection will start out doing a server handshake if <b>receiving</b> + * is strue, and a client handshake otherwise. + * + * Returns NULL on failure. + */ +struct bufferevent * +tor_tls_init_bufferevent(tor_tls_t *tls, struct bufferevent *bufev_in, + evutil_socket_t socket, int receiving, + int filter) +{ + struct bufferevent *out; + const enum bufferevent_ssl_state state = receiving ? + BUFFEREVENT_SSL_ACCEPTING : BUFFEREVENT_SSL_CONNECTING; + + if (filter || tor_libevent_using_iocp_bufferevents()) { + /* Grab an extra reference to the SSL, since BEV_OPT_CLOSE_ON_FREE + means that the SSL will get freed too. + + This increment makes our SSL usage not-threadsafe, BTW. We should + see if we're allowed to use CRYPTO_add from outside openssl. */ + tls->ssl->references += 1; + out = bufferevent_openssl_filter_new(tor_libevent_get_base(), + bufev_in, + tls->ssl, + state, + BEV_OPT_DEFER_CALLBACKS| + BEV_OPT_CLOSE_ON_FREE); + /* Tell the underlying bufferevent when to accept more data from the SSL + filter (only when it's got less than 32K to write), and when to notify + the SSL filter that it could write more (when it drops under 24K). */ + bufferevent_setwatermark(bufev_in, EV_WRITE, 24*1024, 32*1024); + } else { + if (bufev_in) { + evutil_socket_t s = bufferevent_getfd(bufev_in); + tor_assert(s == -1 || s == socket); + tor_assert(evbuffer_get_length(bufferevent_get_input(bufev_in)) == 0); + tor_assert(evbuffer_get_length(bufferevent_get_output(bufev_in)) == 0); + tor_assert(BIO_number_read(SSL_get_rbio(tls->ssl)) == 0); + tor_assert(BIO_number_written(SSL_get_rbio(tls->ssl)) == 0); + bufferevent_free(bufev_in); + } + + /* Current versions (as of 2.0.x) of Libevent need to defer + * bufferevent_openssl callbacks, or else our callback functions will + * get called reentrantly, which is bad for us. + */ + out = bufferevent_openssl_socket_new(tor_libevent_get_base(), + socket, + tls->ssl, + state, + BEV_OPT_DEFER_CALLBACKS); + } + tls->state = TOR_TLS_ST_BUFFEREVENT; + + /* Unblock _after_ creating the bufferevent, since accept/connect tend to + * clear flags. */ + tor_tls_unblock_renegotiation(tls); + + return out; +} +#endif + diff --git a/src/common/tortls.h b/src/common/tortls.h index 55fee81aea..9f86e37127 100644 --- a/src/common/tortls.h +++ b/src/common/tortls.h @@ -13,10 +13,14 @@ #include "crypto.h" #include "compat.h" +#include "compat_libevent.h" /* Opaque structure to hold a TLS connection. */ typedef struct tor_tls_t tor_tls_t; +/* Opaque structure to hold an X509 certificate. */ +typedef struct tor_cert_t tor_cert_t; + /* Possible return values for most tor_tls_* functions. */ #define _MIN_TOR_TLS_ERROR_VAL -9 #define TOR_TLS_ERROR_MISC -9 @@ -48,6 +52,7 @@ typedef struct tor_tls_t tor_tls_t; #define TOR_TLS_IS_ERROR(rv) ((rv) < TOR_TLS_CLOSE) const char *tor_tls_err_to_string(int err); +void tor_tls_get_state_description(tor_tls_t *tls, char *buf, size_t sz); void tor_tls_free_all(void); int tor_tls_context_init(int is_public_server, @@ -56,19 +61,25 @@ int tor_tls_context_init(int is_public_server, unsigned int key_lifetime); tor_tls_t *tor_tls_new(int sock, int is_server); void tor_tls_set_logged_address(tor_tls_t *tls, const char *address); -void tor_tls_set_renegotiate_callback(tor_tls_t *tls, +void tor_tls_set_renegotiate_callbacks(tor_tls_t *tls, void (*cb)(tor_tls_t *, void *arg), + void (*cb2)(void *), void *arg); int tor_tls_is_server(tor_tls_t *tls); void tor_tls_free(tor_tls_t *tls); int tor_tls_peer_has_cert(tor_tls_t *tls); +tor_cert_t *tor_tls_get_peer_cert(tor_tls_t *tls); int tor_tls_verify(int severity, tor_tls_t *tls, crypto_pk_env_t **identity); -int tor_tls_check_lifetime(tor_tls_t *tls, int tolerance); +int tor_tls_check_lifetime(int severity, + tor_tls_t *tls, int past_tolerance, + int future_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_block_renegotiation(tor_tls_t *tls); +void tor_tls_unblock_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 +92,44 @@ 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_received_v3_certificate(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); +int tor_tls_get_tlssecrets(tor_tls_t *tls, uint8_t *secrets_out); /* 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 + +void tor_cert_free(tor_cert_t *cert); +tor_cert_t *tor_cert_decode(const uint8_t *certificate, + size_t certificate_len); +void tor_cert_get_der(const tor_cert_t *cert, + const uint8_t **encoded_out, size_t *size_out); +const digests_t *tor_cert_get_id_digests(const tor_cert_t *cert); +const digests_t *tor_cert_get_cert_digests(const tor_cert_t *cert); +int tor_tls_get_my_certs(int server, + const tor_cert_t **link_cert_out, + const tor_cert_t **id_cert_out); +crypto_pk_env_t *tor_tls_get_my_client_auth_key(void); +crypto_pk_env_t *tor_tls_cert_get_key(tor_cert_t *cert); +int tor_tls_cert_matches_key(const tor_tls_t *tls, const tor_cert_t *cert); +int tor_tls_cert_is_valid(int severity, + const tor_cert_t *cert, + const tor_cert_t *signing_cert, + int check_rsa_1024); #endif diff --git a/src/common/util.c b/src/common/util.c index de1ca3684d..6d488d9963 100644 --- a/src/common/util.c +++ b/src/common/util.c @@ -14,6 +14,10 @@ #define _GNU_SOURCE #include "orconfig.h" +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif +#define UTIL_PRIVATE #include "util.h" #include "torlog.h" #undef log @@ -27,6 +31,7 @@ #include <direct.h> #include <process.h> #include <tchar.h> +#include <Winbase.h> #else #include <dirent.h> #include <pwd.h> @@ -42,6 +47,7 @@ #include <stdio.h> #include <string.h> #include <assert.h> +#include <signal.h> #ifdef HAVE_NETINET_IN_H #include <netinet/in.h> @@ -67,9 +73,6 @@ #ifdef HAVE_SYS_FCNTL_H #include <sys/fcntl.h> #endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif #ifdef HAVE_TIME_H #include <time.h> #endif @@ -87,6 +90,9 @@ #ifdef HAVE_MALLOC_NP_H #include <malloc_np.h> #endif +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif /* ===== * Memory management @@ -417,6 +423,32 @@ round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor) return number; } +/** Return the number of bits set in <b>v</b>. */ +int +n_bits_set_u8(uint8_t v) +{ + static const int nybble_table[] = { + 0, /* 0000 */ + 1, /* 0001 */ + 1, /* 0010 */ + 2, /* 0011 */ + 1, /* 0100 */ + 2, /* 0101 */ + 2, /* 0110 */ + 3, /* 0111 */ + 1, /* 1000 */ + 2, /* 1001 */ + 2, /* 1010 */ + 3, /* 1011 */ + 2, /* 1100 */ + 3, /* 1101 */ + 3, /* 1110 */ + 4, /* 1111 */ + }; + + return nybble_table[v & 15] + nybble_table[v>>4]; +} + /* ===== * String manipulation * ===== */ @@ -500,6 +532,23 @@ tor_strisnonupper(const char *s) return 1; } +/** As strcmp, except that either string may be NULL. The NULL string is + * considered to be before any non-NULL string. */ +int +strcmp_opt(const char *s1, const char *s2) +{ + if (!s1) { + if (!s2) + return 0; + else + return -1; + } else if (!s2) { + return 1; + } else { + return strcmp(s1, s2); + } +} + /** Compares the first strlen(s2) characters of s1 with s2. Returns as for * strcmp. */ @@ -722,6 +771,34 @@ find_str_at_start_of_line(const char *haystack, const char *needle) return NULL; } +/** Returns true if <b>string</b> could be a C identifier. + A C identifier must begin with a letter or an underscore and the + rest of its characters can be letters, numbers or underscores. No + length limit is imposed. */ +int +string_is_C_identifier(const char *string) +{ + size_t iter; + size_t length = strlen(string); + if (!length) + return 0; + + for (iter = 0; iter < length ; iter++) { + if (iter == 0) { + if (!(TOR_ISALPHA(string[iter]) || + string[iter] == '_')) + return 0; + } else { + if (!(TOR_ISALPHA(string[iter]) || + TOR_ISDIGIT(string[iter]) || + string[iter] == '_')) + return 0; + } + } + + return 1; +} + /** Return true iff the 'len' bytes at 'mem' are all zero. */ int tor_mem_is_zero(const char *mem, size_t len) @@ -958,7 +1035,7 @@ esc_for_log(const char *s) char *result, *outp; size_t len = 3; if (!s) { - return tor_strdup(""); + return tor_strdup("(null)"); } for (cp = s; *cp; ++cp) { @@ -1698,6 +1775,8 @@ check_private_dir(const char *dirname, cpd_check_t check, struct passwd *pw = NULL; uid_t running_uid; gid_t running_gid; +#else + (void)effective_user; #endif tor_assert(dirname); @@ -1897,7 +1976,7 @@ start_writing_to_file(const char *fname, int open_flags, int mode, if (open_flags & O_BINARY) new_file->binary = 1; - new_file->fd = open(open_name, open_flags, mode); + new_file->fd = tor_open_cloexec(open_name, open_flags, mode); if (new_file->fd < 0) { log_warn(LD_FS, "Couldn't open \"%s\" (%s) for writing: %s", open_name, fname, strerror(errno)); @@ -2058,13 +2137,12 @@ write_chunks_to_file(const char *fname, const smartlist_t *chunks, int bin) return write_chunks_to_file_impl(fname, chunks, flags); } -/** As write_str_to_file, but does not assume a NUL-terminated - * string. Instead, we write <b>len</b> bytes, starting at <b>str</b>. */ -int -write_bytes_to_file(const char *fname, const char *str, size_t len, - int bin) +/** Write <b>len</b> bytes, starting at <b>str</b>, to <b>fname</b> + using the open() flags passed in <b>flags</b>. */ +static int +write_bytes_to_file_impl(const char *fname, const char *str, size_t len, + int flags) { - int flags = OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT); int r; sized_chunk_t c = { str, len }; smartlist_t *chunks = smartlist_create(); @@ -2074,20 +2152,35 @@ write_bytes_to_file(const char *fname, const char *str, size_t len, return r; } +/** As write_str_to_file, but does not assume a NUL-terminated + * string. Instead, we write <b>len</b> bytes, starting at <b>str</b>. */ +int +write_bytes_to_file(const char *fname, const char *str, size_t len, + int bin) +{ + return write_bytes_to_file_impl(fname, str, len, + OPEN_FLAGS_REPLACE|(bin?O_BINARY:O_TEXT)); +} + /** As write_bytes_to_file, but if the file already exists, append the bytes * to the end of the file instead of overwriting it. */ int append_bytes_to_file(const char *fname, const char *str, size_t len, int bin) { - int flags = OPEN_FLAGS_APPEND|(bin?O_BINARY:O_TEXT); - int r; - sized_chunk_t c = { str, len }; - smartlist_t *chunks = smartlist_create(); - smartlist_add(chunks, &c); - r = write_chunks_to_file_impl(fname, chunks, flags); - smartlist_free(chunks); - return r; + return write_bytes_to_file_impl(fname, str, len, + OPEN_FLAGS_APPEND|(bin?O_BINARY:O_TEXT)); +} + +/** Like write_str_to_file(), but also return -1 if there was a file + already residing in <b>fname</b>. */ +int +write_bytes_to_new_file(const char *fname, const char *str, size_t len, + int bin) +{ + return write_bytes_to_file_impl(fname, str, len, + OPEN_FLAGS_DONT_REPLACE| + (bin?O_BINARY:O_TEXT)); } /** Read the contents of <b>filename</b> into a newly allocated @@ -2118,7 +2211,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; @@ -2504,18 +2597,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; @@ -2577,11 +2673,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; @@ -2618,9 +2715,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 @@ -2637,6 +2734,30 @@ tor_sscanf(const char *buf, const char *pattern, ...) return r; } +/** Append the string produced by tor_asprintf(<b>pattern</b>, <b>...</b>) + * to <b>sl</b>. */ +void +smartlist_asprintf_add(struct smartlist_t *sl, const char *pattern, ...) +{ + va_list ap; + va_start(ap, pattern); + smartlist_vasprintf_add(sl, pattern, ap); + va_end(ap); +} + +/** va_list-based backend of smartlist_asprintf_add. */ +void +smartlist_vasprintf_add(struct smartlist_t *sl, const char *pattern, + va_list args) +{ + char *str = NULL; + + tor_vasprintf(&str, pattern, args); + tor_assert(str != NULL); + + smartlist_add(sl, str); +} + /** Return a new list containing the filenames in the directory <b>dirname</b>. * Return NULL on error or if <b>dirname</b> is not a directory. */ @@ -2814,7 +2935,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); @@ -2885,3 +3006,1166 @@ load_windows_system_library(const TCHAR *library_name) } #endif +/** Format a single argument for being put on a Windows command line. + * Returns a newly allocated string */ +static char * +format_win_cmdline_argument(const char *arg) +{ + char *formatted_arg; + char need_quotes; + const char *c; + int i; + int bs_counter = 0; + /* Backslash we can point to when one is inserted into the string */ + const char backslash = '\\'; + + /* Smartlist of *char */ + smartlist_t *arg_chars; + arg_chars = smartlist_create(); + + /* Quote string if it contains whitespace or is empty */ + need_quotes = (strchr(arg, ' ') || strchr(arg, '\t') || '\0' == arg[0]); + + /* Build up smartlist of *chars */ + for (c=arg; *c != '\0'; c++) { + if ('"' == *c) { + /* Double up backslashes preceding a quote */ + for (i=0; i<(bs_counter*2); i++) + smartlist_add(arg_chars, (void*)&backslash); + bs_counter = 0; + /* Escape the quote */ + smartlist_add(arg_chars, (void*)&backslash); + smartlist_add(arg_chars, (void*)c); + } else if ('\\' == *c) { + /* Count backslashes until we know whether to double up */ + bs_counter++; + } else { + /* Don't double up slashes preceding a non-quote */ + for (i=0; i<bs_counter; i++) + smartlist_add(arg_chars, (void*)&backslash); + bs_counter = 0; + smartlist_add(arg_chars, (void*)c); + } + } + /* Don't double up trailing backslashes */ + for (i=0; i<bs_counter; i++) + smartlist_add(arg_chars, (void*)&backslash); + + /* Allocate space for argument, quotes (if needed), and terminator */ + formatted_arg = tor_malloc(sizeof(char) * + (smartlist_len(arg_chars) + (need_quotes?2:0) + 1)); + + /* Add leading quote */ + i=0; + if (need_quotes) + formatted_arg[i++] = '"'; + + /* Add characters */ + SMARTLIST_FOREACH(arg_chars, char*, c, + { + formatted_arg[i++] = *c; + }); + + /* Add trailing quote */ + if (need_quotes) + formatted_arg[i++] = '"'; + formatted_arg[i] = '\0'; + + smartlist_free(arg_chars); + return formatted_arg; +} + +/** Format a command line for use on Windows, which takes the command as a + * string rather than string array. Follows the rules from "Parsing C++ + * Command-Line Arguments" in MSDN. Algorithm based on list2cmdline in the + * Python subprocess module. Returns a newly allocated string */ +char * +tor_join_win_cmdline(const char *argv[]) +{ + smartlist_t *argv_list; + char *joined_argv; + int i; + + /* Format each argument and put the result in a smartlist */ + argv_list = smartlist_create(); + for (i=0; argv[i] != NULL; i++) { + smartlist_add(argv_list, (void *)format_win_cmdline_argument(argv[i])); + } + + /* Join the arguments with whitespace */ + joined_argv = smartlist_join_strings(argv_list, " ", 0, NULL); + + /* Free the newly allocated arguments, and the smartlist */ + SMARTLIST_FOREACH(argv_list, char *, arg, + { + tor_free(arg); + }); + smartlist_free(argv_list); + + return joined_argv; +} + +/** Format <b>child_state</b> and <b>saved_errno</b> as a hex string placed in + * <b>hex_errno</b>. Called between fork and _exit, so must be signal-handler + * safe. + * + * <b>hex_errno</b> must have at least HEX_ERRNO_SIZE bytes available. + * + * The format of <b>hex_errno</b> is: "CHILD_STATE/ERRNO\n", left-padded + * with spaces. Note that there is no trailing \0. CHILD_STATE indicates where + * in the processs of starting the child process did the failure occur (see + * CHILD_STATE_* macros for definition), and SAVED_ERRNO is the value of + * errno when the failure occurred. + */ + +void +format_helper_exit_status(unsigned char child_state, int saved_errno, + char *hex_errno) +{ + unsigned int unsigned_errno; + char *cur; + size_t i; + + /* Fill hex_errno with spaces, and a trailing newline (memset may + not be signal handler safe, so we can't use it) */ + for (i = 0; i < (HEX_ERRNO_SIZE - 1); i++) + hex_errno[i] = ' '; + hex_errno[HEX_ERRNO_SIZE - 1] = '\n'; + + /* Convert errno to be unsigned for hex conversion */ + if (saved_errno < 0) { + unsigned_errno = (unsigned int) -saved_errno; + } else { + unsigned_errno = (unsigned int) saved_errno; + } + + /* Convert errno to hex (start before \n) */ + cur = hex_errno + HEX_ERRNO_SIZE - 2; + + /* Check for overflow on first iteration of the loop */ + if (cur < hex_errno) + return; + + do { + *cur-- = "0123456789ABCDEF"[unsigned_errno % 16]; + unsigned_errno /= 16; + } while (unsigned_errno != 0 && cur >= hex_errno); + + /* Prepend the minus sign if errno was negative */ + if (saved_errno < 0 && cur >= hex_errno) + *cur-- = '-'; + + /* Leave a gap */ + if (cur >= hex_errno) + *cur-- = '/'; + + /* Check for overflow on first iteration of the loop */ + if (cur < hex_errno) + return; + + /* Convert child_state to hex */ + do { + *cur-- = "0123456789ABCDEF"[child_state % 16]; + child_state /= 16; + } while (child_state != 0 && cur >= hex_errno); +} + +/* Maximum number of file descriptors, if we cannot get it via sysconf() */ +#define DEFAULT_MAX_FD 256 + +/** Terminate the process of <b>process_handle</b>. + * Code borrowed from Python's os.kill. */ +int +tor_terminate_process(process_handle_t *process_handle) +{ +#ifdef MS_WINDOWS + if (tor_get_exit_code(process_handle, 0, NULL) == PROCESS_EXIT_RUNNING) { + HANDLE handle; + /* If the signal is outside of what GenerateConsoleCtrlEvent can use, + attempt to open and terminate the process. */ + handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, + process_handle->pid.dwProcessId); + if (!handle) + return -1; + + if (!TerminateProcess(handle, 0)) + return -1; + else + return 0; + } +#else /* Unix */ + return kill(process_handle->pid, SIGTERM); +#endif + + return -1; +} + +/** Return the Process ID of <b>process_handle</b>. */ +int +tor_process_get_pid(process_handle_t *process_handle) +{ +#ifdef MS_WINDOWS + return (int) process_handle->pid.dwProcessId; +#else + return (int) process_handle->pid; +#endif +} + +#ifdef MS_WINDOWS +HANDLE +tor_process_get_stdout_pipe(process_handle_t *process_handle) +{ + return process_handle->stdout_pipe; +} +#else +FILE * +tor_process_get_stdout_pipe(process_handle_t *process_handle) +{ + return process_handle->stdout_handle; +} +#endif + +static process_handle_t * +process_handle_new(void) +{ + process_handle_t *out = tor_malloc_zero(sizeof(process_handle_t)); + +#ifndef MS_WINDOWS + out->stdout_pipe = -1; + out->stderr_pipe = -1; +#endif + + return out; +} + +/*DOCDOC*/ +#define CHILD_STATE_INIT 0 +#define CHILD_STATE_PIPE 1 +#define CHILD_STATE_MAXFD 2 +#define CHILD_STATE_FORK 3 +#define CHILD_STATE_DUPOUT 4 +#define CHILD_STATE_DUPERR 5 +#define CHILD_STATE_REDIRECT 6 +#define CHILD_STATE_CLOSEFD 7 +#define CHILD_STATE_EXEC 8 +#define CHILD_STATE_FAILEXEC 9 + +/** Start a program in the background. If <b>filename</b> contains a '/', then + * it will be treated as an absolute or relative path. Otherwise, on + * non-Windows systems, the system path will be searched for <b>filename</b>. + * On Windows, only the current directory will be searched. Here, to search the + * system path (as well as the application directory, current working + * directory, and system directories), set filename to NULL. + * + * The strings in <b>argv</b> will be passed as the command line arguments of + * the child program (following convention, argv[0] should normally be the + * filename of the executable, and this must be the case if <b>filename</b> is + * NULL). The last element of argv must be NULL. A handle to the child process + * will be returned in process_handle (which must be non-NULL). Read + * process_handle.status to find out if the process was successfully launched. + * For convenience, process_handle.status is returned by this function. + * + * Some parts of this code are based on the POSIX subprocess module from + * Python, and example code from + * http://msdn.microsoft.com/en-us/library/ms682499%28v=vs.85%29.aspx. + */ +int +tor_spawn_background(const char *const filename, const char **argv, +#ifdef MS_WINDOWS + LPVOID envp, +#else + const char **envp, +#endif + process_handle_t **process_handle_out) +{ +#ifdef MS_WINDOWS + HANDLE stdout_pipe_read = NULL; + HANDLE stdout_pipe_write = NULL; + HANDLE stderr_pipe_read = NULL; + HANDLE stderr_pipe_write = NULL; + process_handle_t *process_handle; + int status; + + STARTUPINFO siStartInfo; + BOOL retval = FALSE; + + SECURITY_ATTRIBUTES saAttr; + char *joined_argv; + + (void)envp; // Unused on Windows + + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + saAttr.bInheritHandle = TRUE; + /* TODO: should we set explicit security attributes? (#2046, comment 5) */ + saAttr.lpSecurityDescriptor = NULL; + + /* Assume failure to start process */ + status = PROCESS_STATUS_ERROR; + + /* Set up pipe for stdout */ + if (!CreatePipe(&stdout_pipe_read, &stdout_pipe_write, &saAttr, 0)) { + log_warn(LD_GENERAL, + "Failed to create pipe for stdout communication with child process: %s", + format_win32_error(GetLastError())); + return status; + } + if (!SetHandleInformation(stdout_pipe_read, HANDLE_FLAG_INHERIT, 0)) { + log_warn(LD_GENERAL, + "Failed to configure pipe for stdout communication with child " + "process: %s", format_win32_error(GetLastError())); + return status; + } + + /* Set up pipe for stderr */ + if (!CreatePipe(&stderr_pipe_read, &stderr_pipe_write, &saAttr, 0)) { + log_warn(LD_GENERAL, + "Failed to create pipe for stderr communication with child process: %s", + format_win32_error(GetLastError())); + return status; + } + if (!SetHandleInformation(stderr_pipe_read, HANDLE_FLAG_INHERIT, 0)) { + log_warn(LD_GENERAL, + "Failed to configure pipe for stderr communication with child " + "process: %s", format_win32_error(GetLastError())); + return status; + } + + /* Create the child process */ + + /* Windows expects argv to be a whitespace delimited string, so join argv up + */ + joined_argv = tor_join_win_cmdline(argv); + + process_handle = process_handle_new(); + process_handle->status = status; + + ZeroMemory(&(process_handle->pid), sizeof(PROCESS_INFORMATION)); + ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); + siStartInfo.cb = sizeof(STARTUPINFO); + siStartInfo.hStdError = stderr_pipe_write; + siStartInfo.hStdOutput = stdout_pipe_write; + siStartInfo.hStdInput = NULL; + siStartInfo.dwFlags |= STARTF_USESTDHANDLES; + + /* Create the child process */ + + retval = CreateProcess(filename, // module name + joined_argv, // command line + /* TODO: should we set explicit security attributes? (#2046, comment 5) */ + NULL, // process security attributes + NULL, // primary thread security attributes + TRUE, // handles are inherited + /*(TODO: set CREATE_NEW CONSOLE/PROCESS_GROUP to make GetExitCodeProcess() + * work?) */ + 0, // creation flags + envp, // use parent's environment + NULL, // use parent's current directory + &siStartInfo, // STARTUPINFO pointer + &(process_handle->pid)); // receives PROCESS_INFORMATION + + tor_free(joined_argv); + + if (!retval) { + log_warn(LD_GENERAL, + "Failed to create child process %s: %s", filename?filename:argv[0], + format_win32_error(GetLastError())); + tor_free(process_handle); + } else { + /* TODO: Close hProcess and hThread in process_handle->pid? */ + process_handle->stdout_pipe = stdout_pipe_read; + process_handle->stderr_pipe = stderr_pipe_read; + status = process_handle->status = PROCESS_STATUS_RUNNING; + } + + /* TODO: Close pipes on exit */ + *process_handle_out = process_handle; + return status; +#else // MS_WINDOWS + pid_t pid; + int stdout_pipe[2]; + int stderr_pipe[2]; + int fd, retval; + ssize_t nbytes; + process_handle_t *process_handle; + int status; + + 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; + + status = PROCESS_STATUS_ERROR; + + /* We do the strlen here because strlen() is not signal handler safe, + and we are not allowed to use unsafe functions between fork and exec */ + error_message_length = strlen(error_message); + + child_state = CHILD_STATE_PIPE; + + /* Set up pipe for redirecting stdout and stderr of child */ + retval = pipe(stdout_pipe); + if (-1 == retval) { + log_warn(LD_GENERAL, + "Failed to set up pipe for stdout communication with child process: %s", + strerror(errno)); + return status; + } + + retval = pipe(stderr_pipe); + if (-1 == retval) { + log_warn(LD_GENERAL, + "Failed to set up pipe for stderr communication with child process: %s", + strerror(errno)); + return status; + } + + child_state = CHILD_STATE_MAXFD; + +#ifdef _SC_OPEN_MAX + if (-1 != max_fd) { + max_fd = (int) sysconf(_SC_OPEN_MAX); + if (max_fd == -1) + max_fd = DEFAULT_MAX_FD; + log_warn(LD_GENERAL, + "Cannot find maximum file descriptor, assuming %d", max_fd); + } +#else + max_fd = DEFAULT_MAX_FD; +#endif + + child_state = CHILD_STATE_FORK; + + pid = fork(); + if (0 == pid) { + /* In child */ + + child_state = CHILD_STATE_DUPOUT; + + /* Link child stdout to the write end of the pipe */ + retval = dup2(stdout_pipe[1], STDOUT_FILENO); + if (-1 == retval) + goto error; + + child_state = CHILD_STATE_DUPERR; + + /* Link child stderr to the write end of the pipe */ + retval = dup2(stderr_pipe[1], STDERR_FILENO); + if (-1 == retval) + goto error; + + child_state = CHILD_STATE_REDIRECT; + + /* Link stdin to /dev/null */ + fd = open("/dev/null", O_RDONLY); /* NOT cloexec, obviously. */ + if (fd != -1) + dup2(fd, STDIN_FILENO); + else + goto error; + + child_state = CHILD_STATE_CLOSEFD; + + close(stderr_pipe[0]); + close(stderr_pipe[1]); + close(stdout_pipe[0]); + close(stdout_pipe[1]); + close(fd); + + /* Close all other fds, including the read end of the pipe */ + /* XXX: We should now be doing enough FD_CLOEXEC setting to make + * this needless. */ + for (fd = STDERR_FILENO + 1; fd < max_fd; fd++) { + close(fd); + } + + child_state = CHILD_STATE_EXEC; + + /* Call the requested program. We need the cast because + execvp doesn't define argv as const, even though it + does not modify the arguments */ + if (envp) + execve(filename, (char *const *) argv, (char*const*)envp); + else + execvp(filename, (char *const *) argv); + + /* If we got here, the exec or open(/dev/null) failed */ + + child_state = CHILD_STATE_FAILEXEC; + + error: + /* XXX: are we leaking fds from the pipe? */ + + format_helper_exit_status(child_state, errno, hex_errno); + + /* Write the error message. GCC requires that we check the return + value, but there is nothing we can do if it fails */ + /* TODO: Don't use STDOUT, use a pipe set up just for this purpose */ + nbytes = write(STDOUT_FILENO, error_message, error_message_length); + nbytes = write(STDOUT_FILENO, hex_errno, sizeof(hex_errno)); + + (void) nbytes; + + _exit(255); + /* Never reached, but avoids compiler warning */ + return status; + } + + /* In parent */ + + if (-1 == pid) { + log_warn(LD_GENERAL, "Failed to fork child process: %s", strerror(errno)); + close(stdout_pipe[0]); + close(stdout_pipe[1]); + close(stderr_pipe[0]); + close(stderr_pipe[1]); + return status; + } + + process_handle = process_handle_new(); + process_handle->status = status; + process_handle->pid = pid; + + /* TODO: If the child process forked but failed to exec, waitpid it */ + + /* Return read end of the pipes to caller, and close write end */ + process_handle->stdout_pipe = stdout_pipe[0]; + retval = close(stdout_pipe[1]); + + if (-1 == retval) { + log_warn(LD_GENERAL, + "Failed to close write end of stdout pipe in parent process: %s", + strerror(errno)); + } + + process_handle->stderr_pipe = stderr_pipe[0]; + retval = close(stderr_pipe[1]); + + if (-1 == retval) { + log_warn(LD_GENERAL, + "Failed to close write end of stderr pipe in parent process: %s", + strerror(errno)); + } + + status = process_handle->status = PROCESS_STATUS_RUNNING; + /* Set stdout/stderr pipes to be non-blocking */ + fcntl(process_handle->stdout_pipe, F_SETFL, O_NONBLOCK); + fcntl(process_handle->stderr_pipe, F_SETFL, O_NONBLOCK); + /* Open the buffered IO streams */ + process_handle->stdout_handle = fdopen(process_handle->stdout_pipe, "r"); + process_handle->stderr_handle = fdopen(process_handle->stderr_pipe, "r"); + + *process_handle_out = process_handle; + return process_handle->status; +#endif // MS_WINDOWS +} + +/** Destroy all resources allocated by the process handle in + * <b>process_handle</b>. + * If <b>also_terminate_process</b> is true, also terminate the + * process of the process handle. */ +void +tor_process_handle_destroy(process_handle_t *process_handle, + int also_terminate_process) +{ + if (!process_handle) + return; + + if (also_terminate_process) { + if (tor_terminate_process(process_handle) < 0) { + log_notice(LD_GENERAL, "Failed to terminate process with PID '%d'", + tor_process_get_pid(process_handle)); + } else { + log_info(LD_GENERAL, "Terminated process with PID '%d'", + tor_process_get_pid(process_handle)); + } + } + + process_handle->status = PROCESS_STATUS_NOTRUNNING; + +#ifdef MS_WINDOWS + if (process_handle->stdout_pipe) + CloseHandle(process_handle->stdout_pipe); + + if (process_handle->stderr_pipe) + CloseHandle(process_handle->stderr_pipe); +#else + if (process_handle->stdout_handle) + fclose(process_handle->stdout_handle); + + if (process_handle->stderr_handle) + fclose(process_handle->stderr_handle); +#endif + + memset(process_handle, 0x0f, sizeof(process_handle_t)); + tor_free(process_handle); +} + +/** Get the exit code of a process specified by <b>process_handle</b> and store + * it in <b>exit_code</b>, if set to a non-NULL value. If <b>block</b> is set + * to true, the call will block until the process has exited. Otherwise if + * the process is still running, the function will return + * PROCESS_EXIT_RUNNING, and exit_code will be left unchanged. Returns + * PROCESS_EXIT_EXITED if the process did exit. If there is a failure, + * PROCESS_EXIT_ERROR will be returned and the contents of exit_code (if + * non-NULL) will be undefined. N.B. Under *nix operating systems, this will + * probably not work in Tor, because waitpid() is called in main.c to reap any + * terminated child processes.*/ +int +tor_get_exit_code(const process_handle_t *process_handle, + int block, int *exit_code) +{ +#ifdef MS_WINDOWS + DWORD retval; + BOOL success; + + if (block) { + /* Wait for the process to exit */ + retval = WaitForSingleObject(process_handle->pid.hProcess, INFINITE); + if (retval != WAIT_OBJECT_0) { + log_warn(LD_GENERAL, "WaitForSingleObject() failed (%d): %s", + (int)retval, format_win32_error(GetLastError())); + return PROCESS_EXIT_ERROR; + } + } else { + retval = WaitForSingleObject(process_handle->pid.hProcess, 0); + if (WAIT_TIMEOUT == retval) { + /* Process has not exited */ + return PROCESS_EXIT_RUNNING; + } else if (retval != WAIT_OBJECT_0) { + log_warn(LD_GENERAL, "WaitForSingleObject() failed (%d): %s", + (int)retval, format_win32_error(GetLastError())); + return PROCESS_EXIT_ERROR; + } + } + + if (exit_code != NULL) { + success = GetExitCodeProcess(process_handle->pid.hProcess, + (PDWORD)exit_code); + if (!success) { + log_warn(LD_GENERAL, "GetExitCodeProcess() failed: %s", + format_win32_error(GetLastError())); + return PROCESS_EXIT_ERROR; + } + } +#else + int stat_loc; + int retval; + + retval = waitpid(process_handle->pid, &stat_loc, block?0:WNOHANG); + if (!block && 0 == retval) { + /* Process has not exited */ + return PROCESS_EXIT_RUNNING; + } else if (retval != process_handle->pid) { + log_warn(LD_GENERAL, "waitpid() failed for PID %d: %s", + process_handle->pid, strerror(errno)); + return PROCESS_EXIT_ERROR; + } + + if (!WIFEXITED(stat_loc)) { + log_warn(LD_GENERAL, "Process %d did not exit normally", + process_handle->pid); + return PROCESS_EXIT_ERROR; + } + + if (exit_code != NULL) + *exit_code = WEXITSTATUS(stat_loc); +#endif // MS_WINDOWS + + return PROCESS_EXIT_EXITED; +} + +#ifdef MS_WINDOWS +/** Read from a handle <b>h</b> into <b>buf</b>, up to <b>count</b> bytes. If + * <b>hProcess</b> is NULL, the function will return immediately if there is + * nothing more to read. Otherwise <b>hProcess</b> should be set to the handle + * to the process owning the <b>h</b>. In this case, the function will exit + * only once the process has exited, or <b>count</b> bytes are read. Returns + * the number of bytes read, or -1 on error. */ +ssize_t +tor_read_all_handle(HANDLE h, char *buf, size_t count, + const process_handle_t *process) +{ + size_t numread = 0; + BOOL retval; + DWORD byte_count; + BOOL process_exited = FALSE; + + if (count > SIZE_T_CEILING || count > SSIZE_T_MAX) + return -1; + + while (numread != count) { + /* Check if there is anything to read */ + retval = PeekNamedPipe(h, NULL, 0, NULL, &byte_count, NULL); + if (!retval) { + log_warn(LD_GENERAL, + "Failed to peek from handle: %s", + format_win32_error(GetLastError())); + return -1; + } else if (0 == byte_count) { + /* Nothing available: process exited or it is busy */ + + /* Exit if we don't know whether the process is running */ + if (NULL == process) + break; + + /* The process exited and there's nothing left to read from it */ + if (process_exited) + break; + + /* If process is not running, check for output one more time in case + it wrote something after the peek was performed. Otherwise keep on + waiting for output */ + tor_assert(process != NULL); + byte_count = WaitForSingleObject(process->pid.hProcess, 0); + if (WAIT_TIMEOUT != byte_count) + process_exited = TRUE; + + continue; + } + + /* There is data to read; read it */ + retval = ReadFile(h, buf+numread, count-numread, &byte_count, NULL); + tor_assert(byte_count + numread <= count); + if (!retval) { + log_warn(LD_GENERAL, "Failed to read from handle: %s", + format_win32_error(GetLastError())); + return -1; + } else if (0 == byte_count) { + /* End of file */ + break; + } + numread += byte_count; + } + return (ssize_t)numread; +} +#else +/** Read from a handle <b>h</b> into <b>buf</b>, up to <b>count</b> bytes. If + * <b>process</b> is NULL, the function will return immediately if there is + * nothing more to read. Otherwise data will be read until end of file, or + * <b>count</b> bytes are read. Returns the number of bytes read, or -1 on + * error. Sets <b>eof</b> to true if <b>eof</b> is not NULL and the end of the + * file has been reached. */ +ssize_t +tor_read_all_handle(FILE *h, char *buf, size_t count, + const process_handle_t *process, + int *eof) +{ + size_t numread = 0; + char *retval; + + if (eof) + *eof = 0; + + if (count > SIZE_T_CEILING || count > SSIZE_T_MAX) + return -1; + + while (numread != count) { + /* Use fgets because that is what we use in log_from_pipe() */ + retval = fgets(buf+numread, (int)(count-numread), h); + if (NULL == retval) { + if (feof(h)) { + log_debug(LD_GENERAL, "fgets() reached end of file"); + if (eof) + *eof = 1; + break; + } else { + if (EAGAIN == errno) { + if (process) + continue; + else + break; + } else { + log_warn(LD_GENERAL, "fgets() from handle failed: %s", + strerror(errno)); + return -1; + } + } + } + tor_assert(retval != NULL); + tor_assert(strlen(retval) + numread <= count); + numread += strlen(retval); + } + + log_debug(LD_GENERAL, "fgets() read %d bytes from handle", (int)numread); + return (ssize_t)numread; +} +#endif + +/** Read from stdout of a process until the process exits. */ +ssize_t +tor_read_all_from_process_stdout(const process_handle_t *process_handle, + char *buf, size_t count) +{ +#ifdef MS_WINDOWS + return tor_read_all_handle(process_handle->stdout_pipe, buf, count, + process_handle); +#else + return tor_read_all_handle(process_handle->stdout_handle, buf, count, + process_handle, NULL); +#endif +} + +/** Read from stdout of a process until the process exits. */ +ssize_t +tor_read_all_from_process_stderr(const process_handle_t *process_handle, + char *buf, size_t count) +{ +#ifdef MS_WINDOWS + return tor_read_all_handle(process_handle->stderr_pipe, buf, count, + process_handle); +#else + return tor_read_all_handle(process_handle->stderr_handle, buf, count, + process_handle, NULL); +#endif +} + +/** Split buf into lines, and add to smartlist. The buffer <b>buf</b> will be + * modified. The resulting smartlist will consist of pointers to buf, so there + * is no need to free the contents of sl. <b>buf</b> must be a NUL-terminated + * string. <b>len</b> should be set to the length of the buffer excluding the + * NUL. Non-printable characters (including NUL) will be replaced with "." */ +int +tor_split_lines(smartlist_t *sl, char *buf, int len) +{ + /* Index in buf of the start of the current line */ + int start = 0; + /* Index in buf of the current character being processed */ + int cur = 0; + /* Are we currently in a line */ + char in_line = 0; + + /* Loop over string */ + while (cur < len) { + /* Loop until end of line or end of string */ + for (; cur < len; cur++) { + if (in_line) { + if ('\r' == buf[cur] || '\n' == buf[cur]) { + /* End of line */ + buf[cur] = '\0'; + /* Point cur to the next line */ + cur++; + /* Line starts at start and ends with a nul */ + break; + } else { + if (!TOR_ISPRINT(buf[cur])) + buf[cur] = '.'; + } + } else { + if ('\r' == buf[cur] || '\n' == buf[cur]) { + /* Skip leading vertical space */ + ; + } else { + in_line = 1; + start = cur; + if (!TOR_ISPRINT(buf[cur])) + buf[cur] = '.'; + } + } + } + /* We are at the end of the line or end of string. If in_line is true there + * is a line which starts at buf+start and ends at a NUL. cur points to + * the character after the NUL. */ + if (in_line) + smartlist_add(sl, (void *)(buf+start)); + in_line = 0; + } + return smartlist_len(sl); +} + +#ifdef MS_WINDOWS +/** Read from stream, and send lines to log at the specified log level. + * Returns -1 if there is a error reading, and 0 otherwise. + * If the generated stream is flushed more often than on new lines, or + * a read exceeds 256 bytes, lines will be truncated. This should be fixed, + * along with the corresponding problem on *nix (see bug #2045). + */ +static int +log_from_handle(HANDLE *pipe, int severity) +{ + char buf[256]; + int pos; + smartlist_t *lines; + + pos = tor_read_all_handle(pipe, buf, sizeof(buf) - 1, NULL); + if (pos < 0) { + /* Error */ + log_warn(LD_GENERAL, "Failed to read data from subprocess"); + return -1; + } + + if (0 == pos) { + /* There's nothing to read (process is busy or has exited) */ + log_debug(LD_GENERAL, "Subprocess had nothing to say"); + return 0; + } + + /* End with a null even if there isn't a \r\n at the end */ + /* TODO: What if this is a partial line? */ + buf[pos] = '\0'; + log_debug(LD_GENERAL, "Subprocess had %d bytes to say", pos); + + /* Split up the buffer */ + lines = smartlist_create(); + tor_split_lines(lines, buf, pos); + + /* Log each line */ + SMARTLIST_FOREACH(lines, char *, line, + { + log_fn(severity, LD_GENERAL, "Port forwarding helper says: %s", line); + }); + smartlist_free(lines); + + return 0; +} + +#else + +/** Read from stream, and send lines to log at the specified log level. + * Returns 1 if stream is closed normally, -1 if there is a error reading, and + * 0 otherwise. Handles lines from tor-fw-helper and + * tor_spawn_background() specially. + */ +static int +log_from_pipe(FILE *stream, int severity, const char *executable, + int *child_status) +{ + char buf[256]; + enum stream_status r; + + for (;;) { + r = get_string_from_pipe(stream, buf, sizeof(buf) - 1); + + if (r == IO_STREAM_CLOSED) { + return 1; + } else if (r == IO_STREAM_EAGAIN) { + return 0; + } else if (r == IO_STREAM_TERM) { + return -1; + } + + tor_assert(r == IO_STREAM_OKAY); + + /* Check if buf starts with SPAWN_ERROR_MESSAGE */ + if (strcmpstart(buf, SPAWN_ERROR_MESSAGE) == 0) { + /* Parse error message */ + int retval, child_state, saved_errno; + retval = tor_sscanf(buf, SPAWN_ERROR_MESSAGE "%x/%x", + &child_state, &saved_errno); + if (retval == 2) { + log_warn(LD_GENERAL, + "Failed to start child process \"%s\" in state %d: %s", + executable, child_state, strerror(saved_errno)); + if (child_status) + *child_status = 1; + } else { + /* Failed to parse message from child process, log it as a + warning */ + log_warn(LD_GENERAL, + "Unexpected message from port forwarding helper \"%s\": %s", + executable, buf); + } + } else { + log_fn(severity, LD_GENERAL, "Port forwarding helper says: %s", buf); + } + } + + /* We should never get here */ + return -1; +} +#endif + +/** Reads from <b>stream</b> and stores input in <b>buf_out</b> making + * sure it's below <b>count</b> bytes. + * If the string has a trailing newline, we strip it off. + * + * This function is specifically created to handle input from managed + * proxies, according to the pluggable transports spec. Make sure it + * fits your needs before using it. + * + * Returns: + * IO_STREAM_CLOSED: If the stream is closed. + * IO_STREAM_EAGAIN: If there is nothing to read and we should check back + * later. + * IO_STREAM_TERM: If something is wrong with the stream. + * IO_STREAM_OKAY: If everything went okay and we got a string + * in <b>buf_out</b>. */ +enum stream_status +get_string_from_pipe(FILE *stream, char *buf_out, size_t count) +{ + char *retval; + size_t len; + + tor_assert(count <= INT_MAX); + + retval = fgets(buf_out, (int)count, stream); + + if (!retval) { + if (feof(stream)) { + /* Program has closed stream (probably it exited) */ + /* TODO: check error */ + return IO_STREAM_CLOSED; + } else { + if (EAGAIN == errno) { + /* Nothing more to read, try again next time */ + return IO_STREAM_EAGAIN; + } else { + /* There was a problem, abandon this child process */ + return IO_STREAM_TERM; + } + } + } else { + len = strlen(buf_out); + tor_assert(len>0); + + if (buf_out[len - 1] == '\n') { + /* Remove the trailing newline */ + buf_out[len - 1] = '\0'; + } else { + /* No newline; check whether we overflowed the buffer */ + if (!feof(stream)) + log_info(LD_GENERAL, + "Line from stream was truncated: %s", buf_out); + /* TODO: What to do with this error? */ + } + + return IO_STREAM_OKAY; + } + + /* We should never get here */ + return IO_STREAM_TERM; +} + +void +tor_check_port_forwarding(const char *filename, int dir_port, int or_port, + time_t now) +{ +/* When fw-helper succeeds, how long do we wait until running it again */ +#define TIME_TO_EXEC_FWHELPER_SUCCESS 300 +/* When fw-helper failed to start, how long do we wait until running it again + */ +#define TIME_TO_EXEC_FWHELPER_FAIL 60 + + /* Static variables are initialized to zero, so child_handle.status=0 + * which corresponds to it not running on startup */ + static process_handle_t *child_handle=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 ((!child_handle || child_handle->status != PROCESS_STATUS_RUNNING) && + time_to_run_helper < now) { + int status; + + /* Assume tor-fw-helper will succeed, start it later*/ + time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_SUCCESS; + + if (child_handle) { + tor_process_handle_destroy(child_handle, 1); + child_handle = NULL; + } + +#ifdef MS_WINDOWS + /* Passing NULL as lpApplicationName makes Windows search for the .exe */ + status = tor_spawn_background(NULL, argv, NULL, &child_handle); +#else + status = tor_spawn_background(filename, argv, NULL, &child_handle); +#endif + + if (PROCESS_STATUS_ERROR == status) { + log_warn(LD_GENERAL, "Failed to start port forwarding helper %s", + filename); + time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_FAIL; + return; + } + + log_info(LD_GENERAL, + "Started port forwarding helper (%s) with pid '%d'", + filename, tor_process_get_pid(child_handle)); + } + + /* If child is running, read from its stdout and stderr) */ + if (child_handle && PROCESS_STATUS_RUNNING == child_handle->status) { + /* Read from stdout/stderr and log result */ + retval = 0; +#ifdef MS_WINDOWS + stdout_status = log_from_handle(child_handle->stdout_pipe, LOG_INFO); + stderr_status = log_from_handle(child_handle->stderr_pipe, LOG_WARN); + /* If we got this far (on Windows), the process started */ + retval = 0; +#else + stdout_status = log_from_pipe(child_handle->stdout_handle, + LOG_INFO, filename, &retval); + stderr_status = log_from_pipe(child_handle->stderr_handle, + LOG_WARN, filename, &retval); +#endif + if (retval) { + /* There was a problem in the child process */ + time_to_run_helper = now + TIME_TO_EXEC_FWHELPER_FAIL; + } + + /* Combine the two statuses in order of severity */ + if (-1 == stdout_status || -1 == stderr_status) + /* There was a failure */ + retval = -1; +#ifdef MS_WINDOWS + else if (!child_handle || tor_get_exit_code(child_handle, 0, NULL) != + PROCESS_EXIT_RUNNING) { + /* process has exited or there was an error */ + /* TODO: Do something with the process return value */ + /* TODO: What if the process output something since + * between log_from_handle and tor_get_exit_code? */ + retval = 1; + } +#else + else if (1 == stdout_status || 1 == stderr_status) + /* stdout or stderr was closed, the process probably + * exited. It will be reaped by waitpid() in main.c */ + /* TODO: Do something with the process return value */ + retval = 1; +#endif + else + /* Both are fine */ + retval = 0; + + /* If either pipe indicates a failure, act on it */ + if (0 != retval) { + if (1 == retval) { + log_info(LD_GENERAL, "Port forwarding helper terminated"); + child_handle->status = PROCESS_STATUS_NOTRUNNING; + } else { + log_warn(LD_GENERAL, "Failed to read from port forwarding helper"); + child_handle->status = PROCESS_STATUS_ERROR; + } + + /* TODO: The child might not actually be finished (maybe it failed or + closed stdout/stderr), so maybe we shouldn't start another? */ + } + } +} + diff --git a/src/common/util.h b/src/common/util.h index b9db25ca73..3a68f3993d 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -160,6 +160,7 @@ uint64_t round_to_power_of_2(uint64_t u64); unsigned round_to_next_multiple_of(unsigned number, unsigned divisor); uint32_t round_uint32_to_next_multiple_of(uint32_t number, uint32_t divisor); uint64_t round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor); +int n_bits_set_u8(uint8_t v); /* Compute the CEIL of <b>a</b> divided by <b>b</b>, for nonnegative <b>a</b> * and positive <b>b</b>. Works on integer types only. Not defined if a+b can @@ -172,18 +173,15 @@ uint64_t round_uint64_to_next_multiple_of(uint64_t number, uint64_t divisor); #define HEX_CHARACTERS "0123456789ABCDEFabcdef" void tor_strlower(char *s) ATTR_NONNULL((1)); void tor_strupper(char *s) ATTR_NONNULL((1)); -int tor_strisprint(const char *s) ATTR_PURE ATTR_NONNULL((1)); -int tor_strisnonupper(const char *s) ATTR_PURE ATTR_NONNULL((1)); -int strcmpstart(const char *s1, const char *s2) ATTR_PURE ATTR_NONNULL((1,2)); -int strcmp_len(const char *s1, const char *s2, size_t len) - ATTR_PURE ATTR_NONNULL((1,2)); -int strcasecmpstart(const char *s1, const char *s2) - ATTR_PURE ATTR_NONNULL((1,2)); -int strcmpend(const char *s1, const char *s2) ATTR_PURE ATTR_NONNULL((1,2)); -int strcasecmpend(const char *s1, const char *s2) - ATTR_PURE ATTR_NONNULL((1,2)); -int fast_memcmpstart(const void *mem, size_t memlen, - const char *prefix) ATTR_PURE; +int tor_strisprint(const char *s) ATTR_NONNULL((1)); +int tor_strisnonupper(const char *s) ATTR_NONNULL((1)); +int strcmp_opt(const char *s1, const char *s2); +int strcmpstart(const char *s1, const char *s2) ATTR_NONNULL((1,2)); +int strcmp_len(const char *s1, const char *s2, size_t len) ATTR_NONNULL((1,2)); +int strcasecmpstart(const char *s1, const char *s2) ATTR_NONNULL((1,2)); +int strcmpend(const char *s1, const char *s2) ATTR_NONNULL((1,2)); +int strcasecmpend(const char *s1, const char *s2) ATTR_NONNULL((1,2)); +int fast_memcmpstart(const void *mem, size_t memlen, const char *prefix); void tor_strstrip(char *s, const char *strip) ATTR_NONNULL((1,2)); long tor_parse_long(const char *s, int base, long min, @@ -195,17 +193,19 @@ double tor_parse_double(const char *s, double min, double max, int *ok, uint64_t tor_parse_uint64(const char *s, int base, uint64_t min, uint64_t max, int *ok, char **next); const char *hex_str(const char *from, size_t fromlen) ATTR_NONNULL((1)); -const char *eat_whitespace(const char *s) ATTR_PURE; -const char *eat_whitespace_eos(const char *s, const char *eos) ATTR_PURE; -const char *eat_whitespace_no_nl(const char *s) ATTR_PURE; -const char *eat_whitespace_eos_no_nl(const char *s, const char *eos) ATTR_PURE; -const char *find_whitespace(const char *s) ATTR_PURE; -const char *find_whitespace_eos(const char *s, const char *eos) ATTR_PURE; -const char *find_str_at_start_of_line(const char *haystack, const char *needle) - ATTR_PURE; -int tor_mem_is_zero(const char *mem, size_t len) ATTR_PURE; -int tor_digest_is_zero(const char *digest) ATTR_PURE; -int tor_digest256_is_zero(const char *digest) ATTR_PURE; +const char *eat_whitespace(const char *s); +const char *eat_whitespace_eos(const char *s, const char *eos); +const char *eat_whitespace_no_nl(const char *s); +const char *eat_whitespace_eos_no_nl(const char *s, const char *eos); +const char *find_whitespace(const char *s); +const char *find_whitespace_eos(const char *s, const char *eos); +const char *find_str_at_start_of_line(const char *haystack, + const char *needle); +int string_is_C_identifier(const char *string); + +int tor_mem_is_zero(const char *mem, size_t len); +int tor_digest_is_zero(const char *digest); +int tor_digest256_is_zero(const char *digest); char *esc_for_log(const char *string) ATTR_MALLOC; const char *escaped(const char *string); struct smartlist_t; @@ -218,6 +218,11 @@ int tor_sscanf(const char *buf, const char *pattern, ...) #endif ; +void smartlist_asprintf_add(struct smartlist_t *sl, const char *pattern, ...) + CHECK_PRINTF(2, 3); +void smartlist_vasprintf_add(struct smartlist_t *sl, const char *pattern, + va_list args); + int hex_decode_digit(char c); void base16_encode(char *dest, size_t destlen, const char *src, size_t srclen); int base16_decode(char *dest, size_t destlen, const char *src, size_t srclen); @@ -279,6 +284,16 @@ char *rate_limit_log(ratelim_t *lim, time_t now); ssize_t write_all(tor_socket_t fd, const char *buf, size_t count,int isSocket); ssize_t read_all(tor_socket_t fd, char *buf, size_t count, int isSocket); +/** Status of an I/O stream. */ +enum stream_status { + IO_STREAM_OKAY, + IO_STREAM_EAGAIN, + IO_STREAM_TERM, + IO_STREAM_CLOSED +}; + +enum stream_status get_string_from_pipe(FILE *stream, char *buf, size_t count); + /** Return values from file_status(); see that function's documentation * for details. */ typedef enum { FN_ERROR, FN_NOENT, FN_FILE, FN_DIR } file_status_t; @@ -296,6 +311,7 @@ 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) +#define OPEN_FLAGS_DONT_REPLACE (O_CREAT|O_EXCL|O_APPEND|O_WRONLY) typedef struct open_file_t open_file_t; int start_writing_to_file(const char *fname, int open_flags, int mode, open_file_t **data_out); @@ -317,6 +333,8 @@ int write_chunks_to_file(const char *fname, const struct smartlist_t *chunks, int bin); int append_bytes_to_file(const char *fname, const char *str, size_t len, int bin); +int write_bytes_to_new_file(const char *fname, const char *str, size_t len, + int bin); /** Flag for read_file_to_str: open the file in binary mode. */ #define RFTS_BIN 1 @@ -330,17 +348,101 @@ const char *parse_config_line_from_str(const char *line, char **key_out, char **value_out); char *expand_filename(const char *filename); struct smartlist_t *tor_listdir(const char *dirname); -int path_is_relative(const char *filename) ATTR_PURE; +int path_is_relative(const char *filename); /* Process helpers */ 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); + +typedef struct process_handle_t process_handle_t; +int tor_spawn_background(const char *const filename, const char **argv, +#ifdef MS_WINDOWS + LPVOID envp, +#else + const char **envp, +#endif + process_handle_t **process_handle_out); + +#define SPAWN_ERROR_MESSAGE "ERR: Failed to spawn background process - code " + #ifdef MS_WINDOWS HANDLE load_windows_system_library(const TCHAR *library_name); #endif +/* Values of process_handle_t.status. PROCESS_STATUS_NOTRUNNING must be + * 0 because tor_check_port_forwarding depends on this being the initial + * statue of the static instance of process_handle_t */ +#define PROCESS_STATUS_NOTRUNNING 0 +#define PROCESS_STATUS_RUNNING 1 +#define PROCESS_STATUS_ERROR -1 + +#ifdef UTIL_PRIVATE +/*DOCDOC*/ +struct process_handle_t { + int status; +#ifdef MS_WINDOWS + HANDLE stdout_pipe; + HANDLE stderr_pipe; + PROCESS_INFORMATION pid; +#else + int stdout_pipe; + int stderr_pipe; + FILE *stdout_handle; + FILE *stderr_handle; + pid_t pid; +#endif // MS_WINDOWS +}; +#endif + +/* Return values of tor_get_exit_code() */ +#define PROCESS_EXIT_RUNNING 1 +#define PROCESS_EXIT_EXITED 0 +#define PROCESS_EXIT_ERROR -1 +int tor_get_exit_code(const process_handle_t *process_handle, + int block, int *exit_code); +int tor_split_lines(struct smartlist_t *sl, char *buf, int len); +#ifdef MS_WINDOWS +ssize_t tor_read_all_handle(HANDLE h, char *buf, size_t count, + const process_handle_t *process); +#else +ssize_t tor_read_all_handle(FILE *h, char *buf, size_t count, + const process_handle_t *process, + int *eof); +#endif +ssize_t tor_read_all_from_process_stdout( + const process_handle_t *process_handle, char *buf, size_t count); +ssize_t tor_read_all_from_process_stderr( + const process_handle_t *process_handle, char *buf, size_t count); +char *tor_join_win_cmdline(const char *argv[]); + +int tor_process_get_pid(process_handle_t *process_handle); +#ifdef MS_WINDOWS +HANDLE tor_process_get_stdout_pipe(process_handle_t *process_handle); +#else +FILE *tor_process_get_stdout_pipe(process_handle_t *process_handle); +#endif + +int tor_terminate_process(process_handle_t *process_handle); +void tor_process_handle_destroy(process_handle_t *process_handle, + int also_terminate_process); + +#ifdef UTIL_PRIVATE +/* Prototypes for private functions only used by util.c (and unit tests) */ + +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 8043d8ebf2..9ada6a3017 100644 --- a/src/config/geoip +++ b/src/config/geoip @@ -1,4 +1,4 @@ -# Last updated based on September 6 2011 Maxmind GeoLite Country +# Last updated based on November 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 @@ -68,7 +68,8 @@ 29884416,29949951,TW 29949952,30015487,KR 30015488,30408703,CN -30408704,33554431,KR +30408704,33488895,KR +33488896,33554431,AU 33554432,34603007,FR 34603008,34604543,EU 34604544,34605055,DE @@ -112,8 +113,7 @@ 34928640,34930687,EU 34930688,34938879,DE 34938880,34947071,FR -34947072,34952703,EU -34952704,34953215,SE +34947072,34953215,EU 34953216,34954751,AT 34954752,34955263,NL 34955264,34959359,AT @@ -126,16 +126,29 @@ 34994176,34995711,FR 34995712,34995967,EU 34995968,34996223,NL -34996224,35000319,EU -35000320,35002367,SE -35002368,35054079,EU +34996224,34999295,EU +34999296,35001343,GB +35001344,35002367,FR +35002368,35008511,EU +35008512,35009023,FR +35009024,35010303,EU +35010304,35010559,BE +35010560,35011583,FR +35011584,35020799,EU +35020800,35037183,GB +35037184,35054079,FR 35054080,35054591,SE -35054592,35055615,EU +35054592,35055103,EU +35055104,35055359,ES +35055360,35055615,EU 35055616,35055871,GB 35055872,35056127,NL -35056128,35069951,EU -35069952,35074047,SE -35074048,35090431,EU +35056128,35059199,EU +35059200,35059711,GB +35059712,35060735,EU +35060736,35061247,GB +35061248,35061759,FR +35061760,35090431,EU 35090432,35094527,GR 35094528,35127295,EU 35127296,35651583,GB @@ -295,11 +308,12 @@ 203658384,203658399,US 203658400,203658415,PR 203658416,203658423,VI -203658424,203658479,US +203658424,203658431,US +203658432,203658479,VI 203658480,203658751,PR 203658752,203658831,VI -203658832,203658847,US -203658848,203658911,PR +203658832,203658863,US +203658864,203658911,PR 203658912,203658935,VI 203658936,203658951,PR 203658952,203658967,US @@ -327,7 +341,7 @@ 204047248,204047255,US 204047256,204047263,VI 204047264,204047279,US -204047280,204047295,VI +204047280,204047295,PR 204047296,204047303,US 204047304,204047311,PR 204047312,204047335,VI @@ -508,14 +522,10 @@ 212791456,212791479,VI 212791480,212791807,PR 212791808,212791815,US -212791816,212791839,VI -212791840,212791935,US -212791936,212792063,VI +212791816,212792063,VI 212792064,212792191,US 212792192,212792199,PR -212792200,212792207,VI -212792208,212792215,PR -212792216,212792231,VI +212792200,212792231,VI 212792232,212792239,US 212792240,212792247,PR 212792248,212792271,US @@ -535,8 +545,8 @@ 212793328,212793343,US 212793344,212794367,VI 212794368,212794559,PR -212794560,212794575,US -212794576,212794583,VI +212794560,212794567,US +212794568,212794583,VI 212794584,212794599,US 212794600,212794783,PR 212794784,212794791,VI @@ -618,8 +628,9 @@ 214187816,214187823,US 214187824,214187831,PR 214187832,214187839,US -214187840,214187855,PR -214187856,214187887,US +214187840,214187863,PR +214187864,214187871,VI +214187872,214187887,US 214187888,214187903,PR 214187904,214188031,VI 214188032,214237247,US @@ -705,7 +716,6 @@ 234951680,234952703,HK 234952704,234954751,JP 234954752,234971135,NZ -234971136,234979327,IN 234979328,235012095,MY 235012096,235077631,AU 235077632,235143167,JP @@ -723,7 +733,6 @@ 241602560,241604607,MY 241604608,241605631,ID 241605632,241606655,CN -241606656,241614847,IN 241614848,241623039,JP 241623040,241627135,IN 241627136,241631231,HK @@ -777,12 +786,18 @@ 355993888,355993895,IT 355993896,368674047,US 368674048,368674303,ES -368674304,405012479,US +368674304,386924543,US +386924544,387055615,CA +387055616,387121151,PR +387121152,387164415,US +387164416,387164671,CA +387164672,387448831,US +387973120,390332415,US +402653184,405012479,US 405012480,405143551,CA 405143552,405180415,US 405180416,405184511,CA -405184512,405192703,US -405209088,405372927,US +405184512,405372927,US 405372928,405422079,PR 405422080,405798911,US 405798912,405831679,CA @@ -798,7 +813,7 @@ 406003712,406011903,US 406011904,406028287,BS 406028288,406110207,US -406110208,406126591,CA +406110208,406142975,CA 406142976,406147071,US 406147072,406151167,CA 406159360,406175743,US @@ -817,16 +832,19 @@ 408518656,408535039,US 408535040,408551423,CA 408551424,408719359,US -408719360,408721407,LC -408721408,408723455,VC +408719360,408723455,LC 408723456,409337855,US 409337856,409354239,CA 409370624,409731071,US 409731072,409862143,CA 409862144,410124287,US -410124288,410177751,CA +410124288,410174779,CA +410174780,410174787,US +410174788,410177751,CA 410177752,410177755,US -410177756,410178463,CA +410177756,410178343,CA +410178344,410178347,US +410178348,410178463,CA 410178464,410178467,US 410178468,410180643,CA 410180644,410180647,US @@ -834,15 +852,13 @@ 410180696,410180703,US 410180704,410180711,CA 410180712,410180715,US -410180716,410180771,CA +410180716,410180759,CA +410180760,410180763,US +410180764,410180771,CA 410180772,410180775,US -410180776,410185355,CA -410185356,410185359,US -410185360,410185407,CA +410180776,410185407,CA 410185408,410185411,US -410185412,410185519,CA -410185520,410185523,US -410185524,410185539,CA +410185412,410185539,CA 410185540,410185543,US 410185544,410185551,CA 410185552,410185559,US @@ -883,7 +899,9 @@ 411779072,411828223,PR 411828224,411893759,US 411893760,411975679,CA -411975680,412221439,US +411975680,411979775,US +411979776,411983871,CA +411983872,412221439,US 412221440,412229631,CA 412254208,412483583,US 412483584,412549119,CA @@ -896,6 +914,7 @@ 412708864,412909567,US 412909568,412942335,CA 412942336,412946431,US +412975104,413007871,CA 413007872,413908991,US 413908992,413925375,PR 413925376,415760383,US @@ -908,8 +927,7 @@ 416546816,416579583,CA 416612352,416628735,US 416628736,416636927,CA -416636928,416641023,US -416645120,416743423,US +416636928,416743423,US 416743424,416776191,CA 416776192,417202175,US 417202176,417267711,CA @@ -1220,16 +1238,23 @@ 520355840,520421375,ES 520421376,520486911,AT 520486912,520488959,NL -520488960,520491007,IT +520488960,520489983,IT +520489984,520491007,RU 520491008,520493567,GB -520493568,520494079,FR -520494080,520495871,IT -520495872,520496383,DE -520496384,520497663,IT -520497664,520497919,FR -520497920,520500479,IT -520500480,520500735,DE -520500736,520501759,IT +520493568,520494335,FR +520494336,520494591,TR +520494592,520495103,CH +520495104,520496383,DE +520496384,520496895,TR +520496896,520497151,ES +520497152,520497407,FR +520497408,520497663,ES +520497664,520498175,FR +520498176,520498687,CH +520498688,520499711,FR +520499712,520501247,DE +520501248,520501503,IL +520501504,520501759,AE 520501760,520503295,GB 520503296,520505343,PL 520505344,520507391,GB @@ -1247,7 +1272,10 @@ 520589312,520593407,IT 520593408,520595455,AM 520595456,520597503,MK -520597504,520601599,DE +520597504,520598015,DE +520598016,520598047,IT +520598048,520598079,FR +520598080,520601599,DE 520601600,520609791,SI 520609792,520613887,RU 520613888,520615935,CZ @@ -1273,7 +1301,11 @@ 520882176,520884223,IT 520884224,520888319,MK 520888320,520896511,DE -520896512,520898559,BE +520896512,520897023,BE +520897024,520897151,LU +520897152,520897791,BE +520897792,520897807,LU +520897808,520898559,BE 520898560,520902655,GB 520902656,520902784,NL 520902785,520912895,GB @@ -1367,7 +1399,9 @@ 521746432,521748479,NL 521748480,521750527,SE 521750528,521752575,PS -521752576,521754623,FR +521752576,521754367,FR +521754368,521754383,US +521754384,521754623,FR 521754624,521756671,IR 521756672,521758719,NL 521758720,521760767,IR @@ -1479,7 +1513,10 @@ 523018240,523022335,IT 523022336,523024639,RU 523024640,523024895,GB -523024896,523026431,RU +523024896,523025407,RU +523025408,523025663,UA +523025664,523025919,CH +523025920,523026431,NL 523026432,523030527,TR 523030528,523034623,FR 523034624,523038719,SE @@ -1600,13 +1637,13 @@ 529596416,529661951,TR 529661952,529727487,GE 529727488,529793023,HR -529793024,529826815,RU -529826816,529827839,GB -529827840,529828863,RO +529793024,529825791,RU +529825792,529826303,UA +529826304,529826815,RU +529826816,529827839,DE +529827840,529828863,CZ 529828864,529829887,RU -529829888,529830399,UA -529830400,529830911,RU -529830912,529831935,DE +529829888,529831935,NL 529831936,529832959,UA 529832960,529835007,RU 529835008,529836031,KG @@ -1624,7 +1661,8 @@ 529846784,529848319,RU 529848320,529855487,CZ 529855488,529856511,RU -529856512,529857535,CZ +529856512,529857279,CZ +529857280,529857535,KZ 529857536,529858559,UA 529858560,529924095,NL 529924096,529989631,DE @@ -1655,7 +1693,8 @@ 531234816,531236863,IE 531236864,531238911,FR 531238912,531240959,LV -531240960,531243007,SE +531240960,531242751,SE +531242752,531243007,DE 531243008,531245055,RU 531245056,531247103,IT 531247104,531251199,IR @@ -1702,9 +1741,9 @@ 531400704,531402751,UA 531402752,531404799,LU 531404800,531406847,FI -531406848,531415039,IM 531415040,531423231,RU -531423232,531425279,NO +531423232,531423487,GB +531423488,531425279,NO 531425280,531425325,FR 531425326,531425327,GB 531425328,531425391,FR @@ -1790,37 +1829,7 @@ 532736000,532738047,RU 532738048,532740095,GB 532740096,532742143,KG -532742144,532742655,GB -532742656,532742783,CN -532742784,532742911,GB -532742912,532743735,CN -532743736,532743743,AZ -532743744,532743935,CN -532743936,532744095,GB -532744096,532744127,CN -532744128,532744191,GB -532744192,532744319,IN -532744320,532744383,US -532744384,532744479,CN -532744480,532744511,IN -532744512,532744575,BE -532744576,532744639,GB -532744640,532745215,CN -532745216,532745599,GB -532745600,532745663,CN -532745664,532745727,US -532745728,532745791,CN -532745792,532745855,GB -532745856,532745983,CN -532745984,532746015,BE -532746016,532746047,CN -532746048,532746111,AU -532746112,532746143,BE -532746144,532746207,GB -532746208,532746215,CN -532746216,532746223,ES -532746224,532746231,GB -532746232,532746239,CN +532742144,532746239,GB 532746240,532750335,IT 532750336,532752383,SM 532752384,532754431,BE @@ -2283,15 +2292,31 @@ 533817344,533817344,TR 533817345,533819391,CY 533819392,533823487,DE -533823488,533823743,CD -533823744,533825535,BE +533823488,533823551,CD +533823552,533823552,BE +533823553,533823612,CD +533823613,533823616,BE +533823617,533823644,CD +533823645,533823648,BE +533823649,533823660,CD +533823661,533823664,BE +533823665,533823676,CD +533823677,533823680,BE +533823681,533823692,CD +533823693,533823696,BE +533823697,533823708,CD +533823709,533823712,BE +533823713,533823724,CD +533823725,533825535,BE 533825536,533831679,IS 533831680,533835775,DE 533835776,533837823,SE 533837824,533839871,DE 533839872,533856255,IS 533856256,533858303,FR -533858304,533860351,HU +533858304,533859343,HU +533859344,533859351,SK +533859352,533860351,HU 533860352,533861375,DE 533861376,533862399,NL 533862400,533864447,GB @@ -2318,7 +2343,11 @@ 534118400,534151167,KW 534151168,534157759,DE 534157760,534157823,US -534157824,534175743,DE +534157824,534166527,DE +534166528,534166783,AU +534166784,534167039,PL +534167040,534167295,TR +534167296,534175743,DE 534175744,534179839,NL 534179840,534181887,US 534181888,534183935,DE @@ -2339,7 +2368,9 @@ 534296576,534298623,BA 534298624,534306815,HR 534306816,534308863,SE -534308864,534310911,IE +534308864,534309943,IE +534309944,534309967,GB +534309968,534310911,IE 534310912,534315007,IT 534315008,534347775,HR 534347776,534355967,GB @@ -2365,7 +2396,9 @@ 534648832,534650879,CH 534650880,534652927,RU 534652928,534654975,AL -534654976,534663167,GB +534654976,534659583,GB +534659584,534661119,CZ +534661120,534663167,US 534663168,534675455,ES 534675456,534691839,GB 534691840,534693887,FR @@ -2474,7 +2507,8 @@ 540813184,540813247,NL 540813248,540813287,US 540813288,540813295,DE -540813296,540813311,US +540813296,540813303,SG +540813304,540813311,US 540813312,540813567,NL 540813568,540813639,DE 540813640,540813671,TW @@ -2566,7 +2600,8 @@ 654835712,655359999,TW 655360000,656408575,KR 656408576,658505727,PK -658505728,661651455,CN +658505728,660602879,CN +660602880,661651455,HK 661651456,662700031,KR 662700032,666894335,CN 666894336,671088639,ID @@ -2682,6 +2717,7 @@ 692942848,692944895,GA 692944896,692946943,MZ 692946944,692948991,EG +692948992,692951039,ZM 692969472,692971519,TZ 692973568,692975615,MZ 692975616,692977663,EG @@ -2694,7 +2730,7 @@ 692984832,692987903,ZA 692987904,692988927,GH 692988928,692989951,ZW -692989952,692990975,BF +692989952,692991999,BF 692992000,692993023,MW 692993024,692994047,EG 692994048,692995071,TZ @@ -2760,8 +2796,15 @@ 693064704,693065727,GH 693065728,693066751,MW 693066752,693067775,ZA +693067776,693068799,GH 693068800,693069823,TZ 693069824,693071871,ZA +693071872,693072895,ZW +693072896,693073919,NG +693074944,693075967,CV +693075968,693076991,CM +693076992,693078015,ZW +693084160,693085183,MU 693101568,693102591,KE 693102592,693103615,CD 693103616,693104639,GN @@ -2868,7 +2911,7 @@ 700342272,700350463,NA 700350464,700358655,UG 700358656,700366847,MZ -700366848,700375039,UG +700366848,700375039,MW 700375040,700376063,CM 700376064,700377087,NE 700377088,700378111,KE @@ -2910,7 +2953,9 @@ 700588032,700588286,KM 700588287,700589567,A2 700589568,700589695,TZ -700589696,700592383,A2 +700589696,700590335,A2 +700590336,700590591,NE +700590592,700592383,A2 700592384,700592639,KE 700592640,700593151,A2 700593152,700594175,NG @@ -2959,7 +3004,9 @@ 701382656,701390847,CI 701390848,701399039,GA 701399040,701407231,EG -701407232,701415423,CA +701407232,701408511,CA +701408512,701408767,ZA +701408768,701415423,CA 701415424,701423615,ZA 701423616,701431807,NG 701431808,701439999,CI @@ -3235,7 +3282,9 @@ 771751936,771817471,RU 771817472,771948543,TR 771948544,772014079,RU -772014080,772050575,DE +772014080,772047647,DE +772047648,772047663,IT +772047664,772050575,DE 772050576,772050583,TR 772050584,772051223,DE 772051224,772051231,CH @@ -3287,7 +3336,9 @@ 772844800,772845311,US 772845312,772845567,IT 772845568,772847615,RU -772847616,772849663,GB +772847616,772848128,GB +772848129,772848191,JO +772848192,772849663,GB 772849664,772851711,BG 772851712,772853759,CH 772853760,772855807,GB @@ -3336,7 +3387,9 @@ 772927488,772929535,UA 772929536,772931583,RU 772931584,772933631,UA -772933632,772935679,GB +772933632,772933920,GB +772933921,772933928,IE +772933929,772935679,GB 772935680,772937727,PS 772937728,772939775,IT 772939776,772941823,BE @@ -3405,9 +3458,7 @@ 773062912,773063167,US 773063168,773063424,TR 773063425,773063436,US -773063437,773064447,TR -773064448,773064703,US -773064704,773065088,TR +773063437,773065088,TR 773065089,773065215,US 773065216,773065584,TR 773065585,773065590,GB @@ -3444,20 +3495,26 @@ 773154816,773155583,SE 773155584,773155839,US 773155840,773156863,SE -773156864,773157887,FR -773157888,773158911,DE +773156864,773158143,FR +773158144,773158911,DE 773158912,773160447,FR 773160448,773160959,ES 773160960,773165055,FR 773165056,773166591,NL -773166592,773167359,US +773166592,773167207,US +773167208,773167215,NL +773167216,773167359,US 773167360,773167615,NL 773167616,773168639,US 773168640,773168671,NL 773168672,773169151,US 773169152,773171343,NL 773171344,773171359,BE -773171360,773172223,NL +773171360,773171599,NL +773171600,773171607,BE +773171608,773171615,NL +773171616,773171647,BE +773171648,773172223,NL 773172224,773172287,BE 773172288,773172351,GB 773172352,773172479,NL @@ -3566,7 +3623,7 @@ 773685248,773687295,UA 773687296,773689343,HU 773689344,773691391,PL -773691392,773695487,RU +773691392,773693439,RU 773695488,773697535,MK 773697536,773699583,LU 773699584,773701631,CZ @@ -3577,9 +3634,7 @@ 773709824,773711871,CZ 773711872,773713919,RU 773713920,773715967,NL -773715968,773715999,SE -773716000,773716063,US -773716064,773716991,SE +773715968,773716991,SE 773716992,773718015,US 773718016,773720063,DE 773720064,773722111,GB @@ -3671,9 +3726,11 @@ 773980160,773988351,GB 773988352,774003199,ES 774003200,774003263,TR -774003264,774003327,ES -774003328,774003391,TR -774003392,774003711,ES +774003264,774003311,ES +774003312,774003391,TR +774003392,774003439,ES +774003440,774003455,TR +774003456,774003711,ES 774003712,774004223,BE 774004224,774004479,ES 774004480,774004511,BE @@ -3684,9 +3741,7 @@ 774029312,774037503,RO 774037504,774045695,SK 774045696,774053887,FR -774053888,774055679,DE -774055680,774055807,BZ -774055808,774055935,DE +774053888,774055935,DE 774055936,774057983,US 774057984,774058359,DE 774058360,774058367,HR @@ -3694,9 +3749,7 @@ 774059216,774059223,ZA 774059224,774060031,DE 774060032,774060047,ES -774060048,774060671,DE -774060672,774060799,HR -774060800,774061007,DE +774060048,774061007,DE 774061008,774061023,CZ 774061024,774061103,DE 774061104,774061111,GI @@ -3808,9 +3861,7 @@ 774161569,774161578,LC 774161579,774161588,VE 774161589,774161598,TC -774161599,774161608,US -774161609,774161618,LI -774161619,774161628,US +774161599,774161628,US 774161629,774161638,PA 774161639,774161648,RU 774161649,774161658,HK @@ -3911,7 +3962,15 @@ 774162307,774162316,RE 774162317,774162326,TK 774162327,774162336,CV -774162337,774162432,VA +774162337,774162346,AZ +774162347,774162366,US +774162367,774162376,MX +774162377,774162386,GB +774162387,774162396,ZW +774162397,774162406,SZ +774162407,774162416,SD +774162417,774162426,BF +774162427,774162432,VA 774162433,774162442,GB 774162443,774162452,BA 774162453,774162462,WS @@ -3934,8 +3993,13 @@ 774162638,774162642,NF 774162643,774162687,US 774162688,774162688,VA -774162689,774162718,US -774162719,774162943,VA +774162689,774162748,US +774162749,774162753,PR +774162754,774162778,US +774162779,774162798,CA +774162799,774162803,BN +774162804,774162808,TM +774162809,774162943,VA 774162944,774163199,CH 774163200,774168575,VA 774168576,774176767,PL @@ -3943,239 +4007,7 @@ 774184960,774193151,GB 774193152,774209535,ES 774209536,774217727,RU -774217728,774217823,GB -774217824,774217855,AE -774217856,774217887,US -774217888,774217927,GB -774217928,774217935,LK -774217936,774217983,CN -774217984,774218047,CA -774218048,774218111,GB -774218112,774218495,US -774218496,774218503,SG -774218504,774218519,CN -774218520,774218527,PK -774218528,774218535,CN -774218536,774218543,IN -774218544,774218551,HR -774218552,774218559,CN -774218560,774218567,GB -774218568,774218575,TW -774218576,774218591,GB -774218592,774218599,CN -774218600,774218607,PT -774218608,774218615,TR -774218616,774218631,PT -774218632,774218639,IN -774218640,774218647,TW -774218648,774218655,PT -774218656,774218663,RU -774218664,774218671,PT -774218672,774218679,CL -774218680,774218687,CN -774218688,774218695,GB -774218696,774218703,SG -774218704,774218711,CN -774218712,774218719,GB -774218720,774218727,CN -774218728,774218735,RU -774218736,774218743,TW -774218744,774219007,GB -774219008,774219263,US -774219264,774219271,CN -774219272,774219279,TR -774219280,774219287,GB -774219288,774219295,CY -774219296,774219327,GB -774219328,774219335,TW -774219336,774219343,EG -774219344,774219359,CN -774219360,774219367,PT -774219368,774219375,IN -774219376,774219383,GB -774219384,774219391,IN -774219392,774219399,US -774219400,774219407,IN -774219408,774219423,CN -774219424,774219431,IN -774219432,774219439,HU -774219440,774219447,CN -774219448,774219455,ES -774219456,774219479,CN -774219480,774219487,HU -774219488,774219495,CN -774219496,774219503,EG -774219504,774219511,CN -774219512,774219519,SG -774219520,774219551,CN -774219552,774219559,PS -774219560,774219575,CN -774219576,774219583,GR -774219584,774219591,TR -774219592,774219599,US -774219600,774219607,CN -774219608,774219679,GB -774219680,774219687,PK -774219688,774219711,GB -774219712,774219727,BE -774219728,774219751,GB -774219752,774219759,PK -774219760,774219839,CN -774219840,774219847,UA -774219848,774219855,CN -774219856,774219863,GB -774219864,774219871,IT -774219872,774219879,RU -774219880,774219887,CN -774219888,774219895,RU -774219896,774219903,LK -774219904,774219967,US -774219968,774219975,PK -774219976,774219991,CN -774219992,774219999,RU -774220000,774220007,GB -774220008,774220015,CN -774220016,774220023,GB -774220024,774220031,PK -774220032,774220159,GB -774220160,774220191,US -774220192,774220207,GB -774220208,774220223,CN -774220224,774220287,GB -774220288,774220543,CN -774220544,774221055,GB -774221056,774221311,US -774221312,774221567,CN -774221568,774221823,US -774221824,774222079,CN -774222080,774222335,US -774222336,774222495,GB -774222496,774222511,FI -774222512,774222527,CN -774222528,774222591,GB -774222592,774222655,CN -774222656,774222687,BE -774222688,774222719,GB -774222720,774222783,CN -774222784,774222799,GB -774222800,774222815,UA -774222816,774222847,CN -774222848,774222863,UA -774222864,774222879,IT -774222880,774222895,US -774222896,774222951,GB -774222952,774222967,CN -774222968,774222975,GR -774222976,774223007,GB -774223008,774223039,CN -774223040,774223071,IT -774223072,774223103,CN -774223104,774223119,UA -774223120,774223151,CN -774223152,774223167,PK -774223168,774223183,GB -774223184,774223199,PK -774223200,774223231,GB -774223232,774223239,CN -774223240,774223247,ME -774223248,774223255,TR -774223256,774223263,ID -774223264,774223271,DE -774223272,774223279,CN -774223280,774223287,GB -774223288,774223295,CN -774223296,774223303,TR -774223304,774223311,CN -774223312,774223319,IN -774223320,774223327,ID -774223328,774223335,PK -774223336,774223351,PT -774223352,774223359,GB -774223360,774223375,UA -774223376,774223391,RU -774223392,774223407,PK -774223408,774223743,GB -774223744,774223807,US -774223808,774223839,CN -774223840,774223871,US -774223872,774223951,GB -774223952,774223959,RU -774223960,774223967,CN -774223968,774223975,RU -774223976,774223983,US -774223984,774223991,RU -774223992,774223999,PK -774224000,774224007,IT -774224008,774224023,CN -774224024,774224031,AE -774224032,774224039,TW -774224040,774224047,CA -774224048,774224055,CN -774224056,774224079,IN -774224080,774224087,DE -774224088,774224095,CN -774224096,774224103,BY -774224104,774224111,RU -774224112,774224119,CN -774224120,774224127,IN -774224128,774224191,GB -774224192,774224223,US -774224224,774224255,LT -774224256,774224383,GB -774224384,774224399,UA -774224400,774224407,LT -774224408,774224415,GB -774224416,774224423,TW -774224424,774224431,GB -774224432,774224439,CN -774224440,774224767,GB -774224768,774224831,CN -774224832,774224847,UA -774224848,774224967,GB -774224968,774224975,UA -774224976,774224983,RU -774224984,774224991,CN -774224992,774224999,LK -774225000,774225007,CN -774225008,774225015,PK -774225016,774225023,CN -774225024,774225055,US -774225056,774225151,RU -774225152,774225343,GB -774225344,774225351,CN -774225352,774225359,LT -774225360,774225375,UA -774225376,774225391,JO -774225392,774225415,UA -774225416,774225423,CN -774225424,774225431,TR -774225432,774225439,DE -774225440,774225447,CN -774225448,774225455,BY -774225456,774225463,GB -774225464,774225471,CN -774225472,774225479,IT -774225480,774225487,IN -774225488,774225495,CN -774225496,774225503,UA -774225504,774225511,CN -774225512,774225519,TR -774225520,774225527,RU -774225528,774225535,CA -774225536,774225567,GB -774225568,774225599,RU -774225600,774225615,PK -774225616,774225647,GB -774225648,774225663,UA -774225664,774225671,LK -774225672,774225687,RU -774225688,774225695,PK -774225696,774225703,CN -774225704,774225727,GB -774225728,774225743,LT -774225744,774225823,GB -774225824,774225855,US -774225856,774225919,IN +774217728,774225919,GB 774225920,774234111,UA 774234112,774242303,IT 774242304,774258687,RU @@ -4204,9 +4036,7 @@ 774520832,774537215,BH 774537216,774553599,RU 774553600,774569983,RO -774569984,774579199,GB -774579200,774580223,IT -774580224,774586367,GB +774569984,774586367,GB 774586368,774602751,PS 774602752,774619135,GB 774619136,774651903,RU @@ -4320,9 +4150,10 @@ 778666016,778666031,FR 778666032,778666047,PL 778666048,778666063,FR -778666064,778666095,PL -778666096,778666099,DE -778666100,778666103,ES +778666064,778666079,IE +778666080,778666095,ES +778666096,778666099,PL +778666100,778666103,LT 778666104,778666107,GB 778666108,778666111,IE 778666112,778666119,FR @@ -4332,9 +4163,9 @@ 778666144,778666151,FR 778666152,778666155,GB 778666156,778666159,ES -778666160,778666175,PL -778666176,778666207,FR -778666208,778666239,PL +778666160,778666175,IE +778666176,778666191,FR +778666192,778666239,PL 778666240,778666247,GB 778666248,778666259,FR 778666260,778666263,PL @@ -4430,8 +4261,7 @@ 778668576,778668607,FR 778668608,778668615,IE 778668616,778668619,PL -778668620,778668623,GB -778668624,778668639,FR +778668620,778668639,FR 778668640,778668671,PL 778668672,778668703,NL 778668704,778668707,PL @@ -4439,7 +4269,9 @@ 778668712,778668715,FR 778668716,778668719,PL 778668720,778668723,PT -778668724,778668735,PL +778668724,778668727,PL +778668728,778668731,PT +778668732,778668735,DE 778668736,778668799,IT 778668800,778669103,FR 778669104,778669107,PL @@ -4472,7 +4304,8 @@ 778669568,778669615,FR 778669616,778669623,GB 778669624,778669631,PL -778669632,778669695,FR +778669632,778669663,FR +778669664,778669695,GB 778669696,778669727,PT 778669728,778669759,NL 778669760,778669767,DE @@ -4494,12 +4327,17 @@ 778670000,778670007,PL 778670008,778670011,CZ 778670012,778670015,LT -778670016,778670143,FR +778670016,778670019,NL +778670020,778670035,IT +778670036,778670039,GB +778670040,778670043,ES +778670044,778670079,GB +778670080,778670143,FR 778670144,778670151,CZ 778670152,778670159,CH 778670160,778670163,FR -778670164,778670167,GB -778670168,778670175,FR +778670164,778670171,GB +778670172,778670175,FR 778670176,778670207,GB 778670208,778670211,DE 778670212,778670215,IT @@ -4519,7 +4357,9 @@ 778670356,778670359,FR 778670360,778670383,DE 778670384,778670387,PL -778670388,778670399,GB +778670388,778670391,NL +778670392,778670395,CZ +778670396,778670399,GB 778670400,778670407,PL 778670408,778670411,DE 778670412,778670415,NL @@ -4551,12 +4391,12 @@ 778671212,778671231,FR 778671232,778671239,GB 778671240,778671243,PL -778671244,778671247,FR +778671244,778671247,ES 778671248,778671263,PL 778671264,778671279,GB 778671280,778671311,FR 778671312,778671327,PT -778671328,778671331,FR +778671328,778671331,ES 778671332,778671335,DE 778671336,778671631,FR 778671632,778671647,PL @@ -4622,8 +4462,8 @@ 778673084,778673087,PT 778673088,778673119,FR 778673120,778673151,ES -778673152,778673191,FR -778673192,778673195,ES +778673152,778673183,FR +778673184,778673195,ES 778673196,778673199,GB 778673200,778673203,CZ 778673204,778673207,IE @@ -4694,11 +4534,15 @@ 778675004,778675007,GB 778675008,778675039,ES 778675040,778675071,FR -778675072,778675079,IT +778675072,778675075,DE +778675076,778675079,IT 778675080,778675087,ES -778675088,778675135,FR -778675136,778675199,ES -778675200,778675215,DE +778675088,778675159,FR +778675160,778675163,PL +778675164,778675167,DE +778675168,778675199,FR +778675200,778675207,ES +778675208,778675215,PL 778675216,778675219,PT 778675220,778675227,FR 778675228,778675231,NL @@ -4715,7 +4559,9 @@ 778675444,778675447,FR 778675448,778675451,PL 778675452,778675455,DE -778675456,778675471,NL +778675456,778675459,PL +778675460,778675463,FR +778675464,778675471,ES 778675472,778675475,BE 778675476,778675479,ES 778675480,778675483,CH @@ -4734,9 +4580,9 @@ 778675624,778675631,PL 778675632,778675639,ES 778675640,778675647,DE -778675648,778675663,GB -778675664,778675679,FR -778675680,778675695,DE +778675648,778675687,FR +778675688,778675691,ES +778675692,778675695,FR 778675696,778675711,NL 778675712,778675839,FR 778675840,778675843,FI @@ -4794,8 +4640,8 @@ 778676624,778676631,PL 778676632,778676635,FR 778676636,778676639,DE -778676640,778676671,GB -778676672,778676687,FR +778676640,778676655,ES +778676656,778676687,FR 778676688,778676691,ES 778676692,778676703,PL 778676704,778676719,FR @@ -4820,12 +4666,12 @@ 778676828,778676847,FR 778676848,778676851,NL 778676852,778676855,LT -778676856,778676859,FR +778676856,778676859,IE 778676860,778676863,DE 778676864,778676991,PL 778676992,778676999,FR -778677000,778677003,PL -778677004,778677023,FR +778677000,778677007,PL +778677008,778677023,FR 778677024,778677055,DE 778677056,778677075,FR 778677076,778677079,DE @@ -4838,9 +4684,11 @@ 778677152,778677167,DE 778677168,778677175,CZ 778677176,778677183,NL -778677184,778677247,GB +778677184,778677215,GB +778677216,778677247,PL 778677248,778677503,FR -778677504,778677511,DE +778677504,778677507,IE +778677508,778677511,FR 778677512,778677515,IT 778677516,778677519,GB 778677520,778677523,FR @@ -4885,17 +4733,18 @@ 778678028,778678031,FR 778678032,778678047,PL 778678048,778678115,FR -778678116,778678127,ES +778678116,778678119,ES +778678120,778678127,IT 778678128,778678143,FR 778678144,778678159,GB 778678160,778678163,PL 778678164,778678167,BE 778678168,778678191,PL -778678192,778678207,NL +778678192,778678207,FR 778678208,778678271,PL 778678272,778678783,DE 778678784,778678799,FR -778678800,778678803,DE +778678800,778678803,PL 778678804,778678807,GB 778678808,778678815,FR 778678816,778678831,PL @@ -4920,8 +4769,9 @@ 778678968,778678975,GB 778678976,778679007,FR 778679008,778679023,PL -778679024,778679039,ES -778679040,778679055,PL +778679024,778679031,GB +778679032,778679035,FR +778679036,778679055,PL 778679056,778679071,BE 778679072,778679103,ES 778679104,778679123,PL @@ -4946,8 +4796,8 @@ 778679552,778679615,FR 778679616,778679679,ES 778679680,778679695,PT -778679696,778679743,GB -778679744,778679807,ES +778679696,778679711,GB +778679712,778679807,FR 778679808,778679823,IT 778679824,778679843,PL 778679844,778679847,DE @@ -4979,7 +4829,7 @@ 778680256,778680271,IT 778680272,778680279,BE 778680280,778680287,PL -778680288,778680319,FR +778680288,778680319,DE 778680320,778680447,GB 778680448,778680451,PT 778680452,778680455,IE @@ -5003,7 +4853,9 @@ 778681152,778681215,PL 778681216,778681235,FR 778681236,778681239,ES -778681240,778681251,FR +778681240,778681243,FR +778681244,778681247,GB +778681248,778681251,FR 778681252,778681255,DE 778681256,778681279,FR 778681280,778681295,DE @@ -5012,11 +4864,15 @@ 778681316,778681319,FR 778681320,778681327,ES 778681328,778681359,GB -778681360,778681367,FR -778681368,778681383,CZ -778681384,778681399,IT -778681400,778681415,NL -778681416,778681419,GB +778681360,778681367,ES +778681368,778681371,NL +778681372,778681375,CH +778681376,778681383,FR +778681384,778681391,DE +778681392,778681399,FR +778681400,778681403,DE +778681404,778681407,ES +778681408,778681419,GB 778681420,778681423,BE 778681424,778681431,FR 778681432,778681435,DE @@ -5028,11 +4884,13 @@ 778681472,778681475,DE 778681476,778681479,PT 778681480,778681503,FR -778681504,778681519,PL -778681520,778681523,ES +778681504,778681507,ES +778681508,778681511,FR +778681512,778681515,PL +778681516,778681523,ES 778681524,778681527,FR 778681528,778681531,PL -778681532,778681535,CH +778681532,778681535,IT 778681536,778681543,FR 778681544,778681547,GB 778681548,778681551,PT @@ -5041,11 +4899,16 @@ 778681588,778681591,FR 778681592,778681595,LT 778681596,778681599,GB -778681600,778681615,ES -778681616,778681623,DE -778681624,778681663,FR -778681664,778681679,DE -778681680,778681703,FR +778681600,778681623,DE +778681624,778681631,FR +778681632,778681639,IT +778681640,778681643,PL +778681644,778681647,DE +778681648,778681651,FR +778681652,778681655,ES +778681656,778681671,DE +778681672,778681675,GB +778681676,778681703,FR 778681704,778681707,IE 778681708,778681711,ES 778681712,778681727,FR @@ -5054,7 +4917,7 @@ 778682116,778682119,PL 778682120,778682123,CH 778682124,778682127,FR -778682128,778682143,GB +778682128,778682143,IE 778682144,778682175,CH 778682176,778682195,IT 778682196,778682199,NL @@ -5098,14 +4961,24 @@ 778691044,778691047,ES 778691048,778691051,PL 778691052,778691055,PT -778691056,778691359,FR +778691056,778691063,NL +778691064,778691067,LT +778691068,778691359,FR 778691360,778691583,PT -778691584,778691743,FR +778691584,778691615,FR +778691616,778691619,DE +778691620,778691627,NL +778691628,778691631,PL +778691632,778691743,FR 778691744,778691747,PL 778691748,778691751,ES 778691752,778691755,FI 778691756,778691759,FR -778691760,778691807,GB +778691760,778691791,GB +778691792,778691795,DE +778691796,778691799,PL +778691800,778691803,ES +778691804,778691807,PL 778691808,778691839,ES 778691840,778691855,CH 778691856,778691975,FR @@ -5121,14 +4994,19 @@ 778692096,778692099,PL 778692100,778692103,DE 778692104,778692107,CH -778692108,778692111,FI -778692112,778692115,PL +778692108,778692115,PL 778692116,778692127,FR 778692128,778692143,NL 778692144,778692159,DE 778692160,778692191,FR -778692192,778692207,GB -778692208,778692615,FR +778692192,778692195,ES +778692196,778692199,CZ +778692200,778692207,ES +778692208,778692223,FR +778692224,778692255,DE +778692256,778692319,FR +778692320,778692351,IE +778692352,778692615,FR 778692616,778692619,PL 778692620,778692623,IE 778692624,778692639,NL @@ -5148,15 +5026,19 @@ 778692784,778692787,GB 778692788,778692791,DE 778692792,778692799,FR -778692800,778692831,DE +778692800,778692807,IE +778692808,778692811,PL +778692812,778692815,DE +778692816,778692823,NL +778692824,778692831,FR 778692832,778692835,BE 778692836,778692839,PT 778692840,778692843,ES 778692844,778692847,PL 778692848,778692863,ES -778692864,778692879,FR +778692864,778692879,IE 778692880,778692883,PL -778692884,778692887,IT +778692884,778692887,FR 778692888,778692891,PL 778692892,778692895,GB 778692896,778692911,FR @@ -5168,7 +5050,7 @@ 778692976,778692983,DE 778692984,778692991,FR 778692992,778693023,GB -778693024,778693027,LT +778693024,778693027,PL 778693028,778693031,ES 778693032,778693035,FR 778693036,778693039,DE @@ -5182,16 +5064,22 @@ 778693080,778693087,FR 778693088,778693091,IE 778693092,778693095,FR -778693096,778693103,IE +778693096,778693099,IT +778693100,778693103,ES 778693104,778693119,FR -778693120,778693151,BE -778693152,778693167,GB +778693120,778693135,GB +778693136,778693139,FR +778693140,778693143,PL +778693144,778693151,FR +778693152,778693155,GB +778693156,778693159,FR +778693160,778693163,BE +778693164,778693167,DE 778693168,778693171,CZ -778693172,778693175,NL -778693176,778693215,FR -778693216,778693223,PL +778693172,778693183,FR +778693184,778693223,PL 778693224,778693227,FR -778693228,778693231,ES +778693228,778693231,IT 778693232,778693235,DE 778693236,778693239,PL 778693240,778693243,ES @@ -5200,25 +5088,29 @@ 778693280,778693295,IT 778693296,778693327,FR 778693328,778693391,GB -778693392,778693407,FR -778693408,778693439,PT +778693392,778693423,FR +778693424,778693439,ES 778693440,778693455,FR 778693456,778693459,DE 778693460,778693511,FR 778693512,778693515,CZ -778693516,778693535,FR -778693536,778693567,NL +778693516,778693567,FR 778693568,778693599,BE 778693600,778693631,NL 778693632,778693663,FR 778693664,778693679,NL -778693680,778693727,DE -778693728,778693759,CZ -778693760,778693775,DE +778693680,778693695,DE +778693696,778693759,IE +778693760,778693763,NL +778693764,778693767,ES +778693768,778693771,PL +778693772,778693775,FR 778693776,778693791,IT -778693792,778693823,FR +778693792,778693799,ES +778693800,778693807,FR +778693808,778693823,PL 778693824,778693839,PT -778693840,778693855,ES +778693840,778693855,FR 778693856,778693887,DE 778693888,778693919,PT 778693920,778693927,CH @@ -5233,8 +5125,10 @@ 778694016,778694143,FR 778694144,778694147,DE 778694148,778694159,PL -778694160,778694175,FI -778694176,778694187,GB +778694160,778694163,GB +778694164,778694171,PL +778694172,778694183,FR +778694184,778694187,PL 778694188,778694191,ES 778694192,778694195,BE 778694196,778694199,PL @@ -5246,9 +5140,10 @@ 778694336,778694351,IT 778694352,778694415,FR 778694416,778694463,IT -778694464,778694479,GB +778694464,778694479,FR 778694480,778694511,IT -778694512,778694527,CZ +778694512,778694515,LT +778694516,778694527,ES 778694528,778694543,PL 778694544,778694555,DE 778694556,778694559,FR @@ -5262,12 +5157,21 @@ 778694628,778694639,FR 778694640,778694643,PL 778694644,778694647,PT -778694648,778694687,FR +778694648,778694655,FR +778694656,778694663,DE +778694664,778694671,PT +778694672,778694679,FR +778694680,778694687,PL 778694688,778694703,GB 778694704,778694719,FR 778694720,778694783,IT 778694784,778694815,FR -778694816,778694847,GB +778694816,778694823,BE +778694824,778694827,FI +778694828,778694831,PT +778694832,778694839,IT +778694840,778694843,FI +778694844,778694847,CZ 778694848,778694911,FR 778694912,778694943,GB 778694944,778694959,FR @@ -5287,7 +5191,8 @@ 778695332,778695335,GB 778695336,778695339,PL 778695340,778695343,FR -778695344,778695351,LT +778695344,778695347,PL +778695348,778695351,ES 778695352,778695383,FR 778695384,778695399,DE 778695400,778695415,GB @@ -5304,8 +5209,10 @@ 778695504,778695519,FR 778695520,778695535,GB 778695536,778695551,FR -778695552,778695567,GB -778695568,778695575,PL +778695552,778695555,BE +778695556,778695559,CH +778695560,778695563,DE +778695564,778695575,PL 778695576,778695579,ES 778695580,778695583,FI 778695584,778695615,PL @@ -5320,7 +5227,7 @@ 778695776,778695795,FR 778695796,778695799,ES 778695800,778695807,FR -778695808,778695823,ES +778695808,778695823,DE 778695824,778695839,FR 778695840,778695903,DE 778695904,778695911,FI @@ -5343,7 +5250,8 @@ 778696020,778696023,ES 778696024,778696027,DE 778696028,778696031,GB -778696032,778696063,PL +778696032,778696047,FR +778696048,778696063,ES 778696064,778696099,FR 778696100,778696103,GB 778696104,778696107,FR @@ -5356,8 +5264,10 @@ 778696188,778696199,FR 778696200,778696203,IT 778696204,778696207,ES -778696208,778696223,FR -778696224,778696255,IE +778696208,778696211,IE +778696212,778696215,DE +778696216,778696219,IT +778696220,778696255,GB 778696256,778696263,IT 778696264,778696287,ES 778696288,778696335,DE @@ -5383,7 +5293,10 @@ 778696640,778696643,ES 778696644,778696647,NL 778696648,778696655,FR -778696656,778696671,NL +778696656,778696659,NL +778696660,778696663,CH +778696664,778696667,FI +778696668,778696671,IE 778696672,778696687,FR 778696688,778696691,BE 778696692,778696695,FI @@ -5391,14 +5304,17 @@ 778696700,778696703,GB 778696704,778696959,FR 778696960,778696975,IT -778696976,778696991,GB +778696976,778696979,GB +778696980,778696983,FR +778696984,778696987,ES +778696988,778696991,FR 778696992,778696995,NL 778696996,778696999,ES 778697000,778697015,FR 778697016,778697019,PL 778697020,778697023,ES 778697024,778697055,DE -778697056,778697059,PL +778697056,778697059,GB 778697060,778697063,FR 778697064,778697067,PL 778697068,778697071,FR @@ -5407,7 +5323,7 @@ 778697096,778697099,FR 778697100,778697103,PL 778697104,778697151,IE -778697152,778697167,GB +778697152,778697167,ES 778697168,778697171,FR 778697172,778697175,DE 778697176,778697179,PL @@ -5433,7 +5349,7 @@ 778697696,778697727,FR 778697728,778697791,FI 778697792,778697807,ES -778697808,778697811,GB +778697808,778697811,DE 778697812,778697815,PL 778697816,778697819,FR 778697820,778697823,IT @@ -5457,11 +5373,11 @@ 778698452,778698455,PL 778698456,778698459,CZ 778698460,778698463,PL -778698464,778698467,GB +778698464,778698467,NL 778698468,778698471,PL 778698472,778698479,IT 778698480,778698495,FR -778698496,778698499,GB +778698496,778698499,IE 778698500,778698503,FR 778698504,778698511,CH 778698512,778698519,FI @@ -5469,9 +5385,13 @@ 778698528,778698531,IT 778698532,778698535,CH 778698536,778698539,PL -778698540,778698543,IT -778698544,778698555,PL -778698556,778698643,FR +778698540,778698543,FR +778698544,778698559,PL +778698560,778698627,FR +778698628,778698631,DE +778698632,778698635,PL +778698636,778698639,DE +778698640,778698643,NL 778698644,778698647,PL 778698648,778698655,ES 778698656,778698667,FR @@ -5481,7 +5401,7 @@ 778698696,778698703,FR 778698704,778698707,DE 778698708,778698711,ES -778698712,778698715,NL +778698712,778698715,IE 778698716,778698719,ES 778698720,778698751,FR 778698752,778764287,TR @@ -5846,8 +5766,10 @@ 782417920,782434303,AM 782434304,782449151,SI 782449152,782449407,HR -782449408,782450175,SI -782450176,782450687,BA +782449408,782449663,SI +782449664,782449695,BA +782449696,782449919,SI +782449920,782450687,BA 782450688,782467071,DE 782467072,782483455,RU 782483456,782499839,FI @@ -5868,8 +5790,7 @@ 782666752,782667007,US 782667008,782667519,RU 782667520,782667775,LU -782667776,782668031,GB -782668032,782668287,FR +782667776,782668287,FR 782668288,782668799,RU 782668800,782669567,NL 782669568,782669823,GB @@ -6041,6 +5962,7 @@ 785645568,785711103,NO 785711104,785776639,SY 785776640,785842175,RO +785842176,785907711,PL 785907712,785973247,BY 785973248,786038783,MK 786038784,786104319,FR @@ -6089,7 +6011,9 @@ 786638848,786640895,ES 786640896,786642943,GB 786642944,786644991,GR -786644992,786649087,SE +786644992,786645759,SE +786645760,786646015,MT +786646016,786649087,SE 786649088,786651135,FR 786651136,786655231,DE 786655232,786657279,PL @@ -6126,7 +6050,9 @@ 786747392,786751487,SK 786751488,786755583,PL 786755584,786759679,IT -786759680,786771967,DE +786759680,786771711,DE +786771712,786771775,AT +786771776,786771967,DE 786771968,786776063,UA 786776064,786780159,RU 786780160,786784255,IT @@ -6326,7 +6252,9 @@ 787863552,787865599,DE 787865600,787869695,FR 787869696,787873791,GB -787873792,787906559,SE +787873792,787894271,SE +787894272,787896319,US +787896320,787906559,SE 787906560,787939327,GR 787939328,787972095,GB 787972096,788004863,UA @@ -6459,14 +6387,14 @@ 788502528,788504575,IE 788504576,788506623,FR 788506624,788508671,CH -788508672,788509207,FR -788509208,788509231,AT +788508672,788509215,FR +788509216,788509231,AT 788509232,788509247,FR -788509248,788509439,AT -788509440,788509631,FR +788509248,788509279,AT +788509280,788509631,FR 788509632,788509695,AT -788509696,788509951,FR -788509952,788510719,AT +788509696,788509999,FR +788510000,788510719,AT 788510720,788512767,ES 788512768,788514815,FI 788514816,788516863,FR @@ -6538,7 +6466,9 @@ 831389696,831512575,KR 831512576,831513599,AU 831513600,831514623,NZ -831514624,831515647,HK +831514624,831514887,HK +831514888,831514895,AU +831514896,831515647,HK 831515648,831516671,AU 831516672,831518719,JP 831518720,831519743,AU @@ -6670,14 +6600,19 @@ 842597640,842597647,GT 842597648,842598703,US 842598704,842598719,CZ -842598720,843055103,US +842598720,842601607,US +842601608,842601615,AR +842601616,842602423,US +842602424,842602431,IN +842602432,843055103,US 843055104,843644927,CA 843644928,844890111,US 844890112,844988415,CA 844988416,845283327,US 845283328,845545471,CA -845545472,846725119,US -847249408,855638015,US +845545472,846442495,US +846442496,846446591,CA +846446592,855638015,US 855638016,872415231,GB 872415232,889192447,US 889192448,905969663,DE @@ -7125,9 +7060,7 @@ 1030750208,1031798783,JP 1031798784,1035993087,CN 1035993088,1037565951,JP -1037565952,1037591499,TW -1037591500,1037591503,CN -1037591504,1038614527,TW +1037565952,1038614527,TW 1038614528,1039007743,CN 1039007744,1039138815,HK 1039138816,1039400959,CN @@ -7149,12 +7082,10 @@ 1040187392,1040252927,IL 1040252928,1040318463,GR 1040318464,1040383999,CH -1040384000,1040386559,SA -1040386560,1040391167,A2 -1040391168,1040392191,SA +1040384000,1040392191,SA 1040392192,1040392447,GB -1040392448,1040399359,SA -1040399360,1040400127,GB +1040392448,1040399615,SA +1040399616,1040400127,GB 1040400128,1040400383,SA 1040400384,1040416767,GB 1040416768,1040424959,SE @@ -7247,8 +7178,8 @@ 1040984216,1040984219,TZ 1040984220,1040990207,A2 1040990208,1040994303,CY -1040994304,1040994815,RU -1040994816,1040998399,CY +1040994304,1040994559,RU +1040994560,1040998399,CY 1040998400,1041006591,EG 1041006592,1041039359,CH 1041039360,1041051647,SE @@ -7315,9 +7246,9 @@ 1041699768,1041699807,GB 1041699808,1041700423,FR 1041700424,1041700535,GB -1041700536,1041700559,FR -1041700560,1041700607,GB -1041700608,1041700983,FR +1041700536,1041700583,FR +1041700584,1041700591,GB +1041700592,1041700983,FR 1041700984,1041700991,GB 1041700992,1041701175,FR 1041701176,1041701183,GB @@ -7333,9 +7264,7 @@ 1041701720,1041701727,GB 1041701728,1041701863,FR 1041701864,1041701871,GB -1041701872,1041701911,FR -1041701912,1041701919,GB -1041701920,1041701967,FR +1041701872,1041701967,FR 1041701968,1041701975,GB 1041701976,1041702167,FR 1041702168,1041702175,GB @@ -7347,9 +7276,7 @@ 1041702352,1041702399,GB 1041702400,1041702751,FR 1041702752,1041702759,GB -1041702760,1041703575,FR -1041703576,1041703583,GB -1041703584,1041703639,FR +1041702760,1041703639,FR 1041703640,1041703647,GB 1041703648,1041703975,FR 1041703976,1041703983,GB @@ -7368,14 +7295,10 @@ 1041704384,1041704407,FR 1041704408,1041704431,GB 1041704432,1041704439,FR -1041704440,1041704455,GB -1041704456,1041704479,FR -1041704480,1041704487,GB -1041704488,1041704551,FR +1041704440,1041704447,GB +1041704448,1041704551,FR 1041704552,1041704575,GB -1041704576,1041704751,FR -1041704752,1041704759,GB -1041704760,1041704775,FR +1041704576,1041704775,FR 1041704776,1041704783,GB 1041704784,1041704815,FR 1041704816,1041704823,GB @@ -7425,9 +7348,7 @@ 1041706112,1041706143,GB 1041706144,1041706191,FR 1041706192,1041706239,GB -1041706240,1041706447,FR -1041706448,1041706463,GB -1041706464,1041706479,FR +1041706240,1041706479,FR 1041706480,1041706487,GB 1041706488,1041706791,FR 1041706792,1041706799,GB @@ -7561,8 +7482,8 @@ 1041714112,1041714175,GB 1041714176,1041714511,FR 1041714512,1041714519,GB -1041714520,1041714655,FR -1041714656,1041714687,GB +1041714520,1041714663,FR +1041714664,1041714687,GB 1041714688,1041714815,FR 1041714816,1041714847,GB 1041714848,1041714855,FR @@ -7576,12 +7497,10 @@ 1041715088,1041715095,FR 1041715096,1041715103,GB 1041715104,1041715119,FR -1041715120,1041715143,GB -1041715144,1041715151,FR -1041715152,1041715167,GB -1041715168,1041715183,FR -1041715184,1041715199,GB -1041715200,1041715527,FR +1041715120,1041715135,GB +1041715136,1041715159,FR +1041715160,1041715167,GB +1041715168,1041715527,FR 1041715528,1041715535,GB 1041715536,1041715583,FR 1041715584,1041715615,GB @@ -7631,7 +7550,9 @@ 1041717632,1041717639,GB 1041717640,1041717687,FR 1041717688,1041717695,GB -1041717696,1041718112,FR +1041717696,1041717711,FR +1041717712,1041717719,GB +1041717720,1041718112,FR 1041718113,1041718119,GB 1041718120,1041718127,FR 1041718128,1041718135,GB @@ -7675,7 +7596,9 @@ 1041719229,1041719231,GB 1041719232,1041719247,FR 1041719248,1041719263,GB -1041719264,1041719743,FR +1041719264,1041719567,FR +1041719568,1041719583,GB +1041719584,1041719743,FR 1041719744,1041719759,GB 1041719760,1041719887,FR 1041719888,1041719903,GB @@ -7709,8 +7632,8 @@ 1041721776,1041721791,GB 1041721792,1041721815,FR 1041721816,1041721823,GB -1041721824,1041722167,FR -1041722168,1041722191,GB +1041721824,1041722175,FR +1041722176,1041722191,GB 1041722192,1041722207,FR 1041722208,1041722215,GB 1041722216,1041722223,FR @@ -7748,8 +7671,8 @@ 1041723872,1041723887,FR 1041723888,1041723903,GB 1041723904,1041724455,FR -1041724456,1041724463,GB -1041724464,1041724511,FR +1041724456,1041724471,GB +1041724472,1041724511,FR 1041724512,1041724519,GB 1041724520,1041724671,FR 1041724672,1041724927,GB @@ -7783,7 +7706,9 @@ 1041726640,1041726655,GB 1041726656,1041726671,FR 1041726672,1041726687,GB -1041726688,1041726735,FR +1041726688,1041726719,FR +1041726720,1041726727,GB +1041726728,1041726735,FR 1041726736,1041726751,GB 1041726752,1041726847,FR 1041726848,1041726855,GB @@ -7921,8 +7846,8 @@ 1041737128,1041737151,GB 1041737152,1041737167,FR 1041737168,1041737183,GB -1041737184,1041737247,FR -1041737248,1041737279,GB +1041737184,1041737215,FR +1041737216,1041737279,GB 1041737280,1041737295,FR 1041737296,1041737303,GB 1041737304,1041737375,FR @@ -7935,7 +7860,9 @@ 1041737488,1041737495,GB 1041737496,1041737503,FR 1041737504,1041737511,GB -1041737512,1041737591,FR +1041737512,1041737535,FR +1041737536,1041737567,GB +1041737568,1041737591,FR 1041737592,1041737599,GB 1041737600,1041737607,FR 1041737608,1041737615,GB @@ -7984,8 +7911,8 @@ 1041739300,1041739303,GB 1041739304,1041739375,FR 1041739376,1041739383,BE -1041739384,1041739391,FR -1041739392,1041739423,GB +1041739384,1041739407,FR +1041739408,1041739423,GB 1041739424,1041739463,FR 1041739464,1041739471,GB 1041739472,1041739487,FR @@ -8000,7 +7927,9 @@ 1041740104,1041740119,GB 1041740120,1041740135,FR 1041740136,1041740143,GB -1041740144,1041740263,FR +1041740144,1041740167,FR +1041740168,1041740175,GB +1041740176,1041740263,FR 1041740264,1041740271,GB 1041740272,1041740567,FR 1041740568,1041740575,GB @@ -8023,8 +7952,8 @@ 1041741264,1041741279,FR 1041741280,1041741295,GB 1041741296,1041741567,FR -1041741568,1041741575,GB -1041741576,1041741607,FR +1041741568,1041741583,GB +1041741584,1041741607,FR 1041741608,1041741615,GB 1041741616,1041741631,FR 1041741632,1041741647,GB @@ -8094,7 +8023,9 @@ 1041744416,1041744447,GB 1041744448,1041744479,FR 1041744480,1041744543,GB -1041744544,1041744599,FR +1041744544,1041744575,FR +1041744576,1041744583,GB +1041744584,1041744599,FR 1041744600,1041744607,GB 1041744608,1041744623,FR 1041744624,1041744639,GB @@ -8122,9 +8053,7 @@ 1041745360,1041745375,GB 1041745376,1041745399,FR 1041745400,1041745407,GB -1041745408,1041745415,FR -1041745416,1041745423,GB -1041745424,1041745447,FR +1041745408,1041745447,FR 1041745448,1041745471,GB 1041745472,1041745479,FR 1041745480,1041745487,GB @@ -8188,7 +8117,9 @@ 1041750744,1041750751,GB 1041750752,1041750775,FR 1041750776,1041750783,GB -1041750784,1041751303,FR +1041750784,1041750831,FR +1041750832,1041750839,GB +1041750840,1041751303,FR 1041751304,1041751311,GB 1041751312,1041751351,FR 1041751352,1041751359,GB @@ -8196,7 +8127,9 @@ 1041751568,1041751575,GB 1041751576,1041751695,FR 1041751696,1041751719,GB -1041751720,1041751775,FR +1041751720,1041751759,FR +1041751760,1041751767,GB +1041751768,1041751775,FR 1041751776,1041751807,GB 1041751808,1041753319,FR 1041753320,1041753327,GB @@ -8484,8 +8417,8 @@ 1043357696,1043365887,CH 1043365888,1043398655,PT 1043398656,1043464191,GB -1043464192,1043464255,NL -1043464256,1043464311,GB +1043464192,1043464287,NL +1043464288,1043464311,GB 1043464312,1043464351,NL 1043464352,1043464383,GB 1043464384,1043464799,NL @@ -8551,8 +8484,8 @@ 1043468064,1043468127,NL 1043468128,1043468159,GB 1043468160,1043468191,NL -1043468192,1043468543,GB -1043468544,1043468575,NL +1043468192,1043468415,GB +1043468416,1043468575,NL 1043468576,1043468655,GB 1043468656,1043468663,NL 1043468664,1043468671,GB @@ -8610,13 +8543,19 @@ 1043472476,1043472487,GB 1043472488,1043472495,DE 1043472496,1043472503,GB -1043472504,1043472895,DE +1043472504,1043472743,DE +1043472744,1043472751,GB +1043472752,1043472895,DE 1043472896,1043473151,GB -1043473152,1043473411,DE +1043473152,1043473247,DE +1043473248,1043473255,GB +1043473256,1043473411,DE 1043473412,1043473415,GB 1043473416,1043473579,DE 1043473580,1043473583,GB -1043473584,1043474031,DE +1043473584,1043473983,DE +1043473984,1043474015,GB +1043474016,1043474031,DE 1043474032,1043474047,GB 1043474048,1043474455,DE 1043474456,1043474463,GB @@ -8632,7 +8571,11 @@ 1043475984,1043475991,GB 1043475992,1043476319,DE 1043476320,1043476351,GB -1043476352,1043476735,DE +1043476352,1043476543,DE +1043476544,1043476559,GB +1043476560,1043476575,DE +1043476576,1043476607,GB +1043476608,1043476735,DE 1043476736,1043476767,GB 1043476768,1043476815,DE 1043476816,1043476991,GB @@ -8641,15 +8584,7 @@ 1043477760,1043478179,DE 1043478180,1043478271,GB 1043478272,1043478287,DE -1043478288,1043478527,GB -1043478528,1043478623,DE -1043478624,1043478639,GB -1043478640,1043478655,DE -1043478656,1043478671,GB -1043478672,1043478735,DE -1043478736,1043478751,GB -1043478752,1043478783,DE -1043478784,1043479295,GB +1043478288,1043479295,GB 1043479296,1043479551,DE 1043479552,1043480063,GB 1043480064,1043480351,DE @@ -9193,7 +9128,9 @@ 1044455424,1044463615,EE 1044463616,1044479999,SE 1044480000,1044488191,CH -1044488192,1044496383,SK +1044488192,1044494911,SK +1044494912,1044494943,SR +1044494944,1044496383,SK 1044496384,1044512767,EE 1044512768,1044578303,DK 1044578304,1044580607,DE @@ -9405,9 +9342,7 @@ 1044932728,1044932735,BE 1044932736,1044932799,GB 1044932800,1044932831,BE -1044932832,1044932839,GB -1044932840,1044932847,BE -1044932848,1044932863,GB +1044932832,1044932863,GB 1044932864,1044932935,BE 1044932936,1044932947,GB 1044932948,1044932951,BE @@ -9430,8 +9365,8 @@ 1044933408,1044933411,GB 1044933412,1044933415,BE 1044933416,1044933439,GB -1044933440,1044933511,BE -1044933512,1044933519,GB +1044933440,1044933503,BE +1044933504,1044933519,GB 1044933520,1044933551,BE 1044933552,1044933555,GB 1044933556,1044933583,BE @@ -9466,7 +9401,9 @@ 1044934576,1044934583,GB 1044934584,1044934591,BE 1044934592,1044934599,GB -1044934600,1044934719,BE +1044934600,1044934607,BE +1044934608,1044934615,GB +1044934616,1044934719,BE 1044934720,1044934783,GB 1044934784,1044934815,BE 1044934816,1044934819,GB @@ -9502,24 +9439,24 @@ 1044935852,1044935871,GB 1044935872,1044935879,BE 1044935880,1044935887,GB -1044935888,1044935903,BE -1044935904,1044936095,GB +1044935888,1044935895,BE +1044935896,1044936095,GB 1044936096,1044936103,BE 1044936104,1044936111,GB 1044936112,1044936123,BE 1044936124,1044936151,GB 1044936152,1044936207,BE 1044936208,1044936215,GB -1044936216,1044936271,BE +1044936216,1044936231,BE +1044936232,1044936239,GB +1044936240,1044936271,BE 1044936272,1044936287,GB 1044936288,1044936303,BE 1044936304,1044936311,GB 1044936312,1044936335,BE 1044936336,1044936351,GB 1044936352,1044936439,BE -1044936440,1044936447,GB -1044936448,1044936455,BE -1044936456,1044936463,GB +1044936440,1044936463,GB 1044936464,1044936495,BE 1044936496,1044936503,GB 1044936504,1044936711,BE @@ -9562,16 +9499,20 @@ 1044938104,1044938107,GB 1044938108,1044938111,BE 1044938112,1044938143,GB -1044938144,1044938235,BE +1044938144,1044938175,BE +1044938176,1044938207,GB +1044938208,1044938235,BE 1044938236,1044938271,GB -1044938272,1044938367,BE +1044938272,1044938335,BE +1044938336,1044938343,GB +1044938344,1044938367,BE 1044938368,1044938399,GB 1044938400,1044938407,BE 1044938408,1044938415,GB 1044938416,1044938423,BE 1044938424,1044938431,GB -1044938432,1044938487,BE -1044938488,1044938511,GB +1044938432,1044938479,BE +1044938480,1044938511,GB 1044938512,1044938519,BE 1044938520,1044938523,GB 1044938524,1044938559,BE @@ -9614,17 +9555,19 @@ 1045154560,1045154591,NL 1045154592,1045154623,DE 1045154624,1045154655,GB -1045154656,1045154687,DE +1045154656,1045154687,MA 1045154688,1045154719,US 1045154720,1045154751,RU 1045154752,1045154783,SE -1045154784,1045155071,DE +1045154784,1045154815,BR +1045154816,1045155071,DE 1045155072,1045155327,CH 1045155328,1045160959,DE 1045160960,1045160991,TR 1045160992,1045161023,DE 1045161024,1045161055,AT -1045161056,1045161119,DE +1045161056,1045161087,DE +1045161088,1045161119,IN 1045161120,1045161151,SC 1045161152,1045168127,DE 1045168128,1045233663,RU @@ -9677,9 +9620,7 @@ 1045461728,1045461735,ES 1045461736,1045461743,NL 1045461744,1045463039,DE -1045463040,1045467487,FI -1045467488,1045467519,AX -1045467520,1045471231,FI +1045463040,1045471231,FI 1045471232,1045479423,UA 1045479424,1045487615,SE 1045487616,1045495807,LT @@ -9718,12 +9659,11 @@ 1045742848,1045742983,SE 1045742984,1045742991,GB 1045742992,1045743007,SE -1045743008,1045743031,GB +1045743008,1045743015,FI +1045743016,1045743031,GB 1045743032,1045743039,SE 1045743040,1045743063,GB -1045743064,1045743071,SE -1045743072,1045743087,GB -1045743088,1045743095,SE +1045743064,1045743095,SE 1045743096,1045743103,GB 1045743104,1045743231,SE 1045743232,1045743251,GB @@ -9740,11 +9680,10 @@ 1045744672,1045745407,GB 1045745408,1045745607,SE 1045745608,1045745615,FI -1045745616,1045745623,GB -1045745624,1045745627,SE +1045745616,1045745627,SE 1045745628,1045745631,GB 1045745632,1045745647,SE -1045745648,1045745663,GB +1045745648,1045745663,FI 1045745664,1045745695,SE 1045745696,1045745759,GB 1045745760,1045745768,SE @@ -9799,7 +9738,9 @@ 1046225656,1046229111,NO 1046229112,1046229119,SE 1046229120,1046282239,NO -1046282240,1046283007,DE +1046282240,1046282623,DE +1046282624,1046282751,US +1046282752,1046283007,DE 1046283008,1046283135,BZ 1046283136,1046283263,DE 1046283264,1046283327,LU @@ -9876,8 +9817,8 @@ 1046338048,1046339839,EU 1046339840,1046340095,FR 1046340096,1046343423,EU -1046343424,1046343935,NL -1046343936,1046344959,EU +1046343424,1046343679,NL +1046343680,1046344959,EU 1046344960,1046345215,DE 1046345216,1046345327,EU 1046345328,1046345727,DE @@ -10230,9 +10171,7 @@ 1046544384,1046560767,IT 1046560768,1046570591,ES 1046570592,1046570607,CH -1046570608,1046571815,ES -1046571816,1046571823,FR -1046571824,1046572007,ES +1046570608,1046572007,ES 1046572008,1046572015,DK 1046572016,1046585343,ES 1046585344,1046609919,NO @@ -10256,9 +10195,7 @@ 1046872064,1046872583,BE 1046872584,1046872607,EU 1046872608,1046872615,BE -1046872616,1046872655,EU -1046872656,1046872671,BE -1046872672,1046872975,EU +1046872616,1046872975,EU 1046872976,1046872999,BE 1046873000,1046873087,EU 1046873088,1046873279,BE @@ -10330,13 +10267,13 @@ 1046882304,1046884383,BE 1046884384,1046885375,EU 1046885376,1046888447,BE -1046888448,1046895103,GB -1046895104,1046896383,EU +1046888448,1046895359,GB +1046895360,1046896383,EU 1046896384,1046897663,GB 1046897664,1046898431,BE 1046898432,1046898687,EU -1046898688,1046898975,BE -1046898976,1046899167,EU +1046898688,1046898943,BE +1046898944,1046899167,EU 1046899168,1046904831,BE 1046904832,1046906879,SK 1046906880,1046908927,IR @@ -10401,7 +10338,9 @@ 1047527424,1047535615,BE 1047535616,1047551999,DE 1047552000,1047560191,RU -1047560192,1047561747,DE +1047560192,1047561151,DE +1047561152,1047561159,AT +1047561160,1047561747,DE 1047561748,1047561751,ES 1047561752,1047561887,DE 1047561888,1047561891,US @@ -10432,8 +10371,10 @@ 1047565132,1047565135,GB 1047565136,1047565343,DE 1047565344,1047565359,CH -1047565360,1047565855,DE -1047565856,1047565887,CH +1047565360,1047565503,DE +1047565504,1047565507,CZ +1047565508,1047565839,DE +1047565840,1047565887,CH 1047565888,1047566363,DE 1047566364,1047566367,CH 1047566368,1047566403,DE @@ -10491,9 +10432,7 @@ 1047567160,1047567163,DE 1047567164,1047567167,AT 1047567168,1047567175,CH -1047567176,1047567183,DE -1047567184,1047567191,CH -1047567192,1047567211,DE +1047567176,1047567211,DE 1047567212,1047567227,CH 1047567228,1047567239,DE 1047567240,1047567243,CH @@ -10541,8 +10480,8 @@ 1047567872,1047567875,CH 1047567876,1047567879,AT 1047567880,1047567883,CH -1047567884,1047567935,DE -1047567936,1047567939,CH +1047567884,1047567903,DE +1047567904,1047567939,CH 1047567940,1047568047,DE 1047568048,1047568051,CH 1047568052,1047568055,DE @@ -10579,15 +10518,15 @@ 1047740480,1047740543,EU 1047740544,1047740671,DE 1047740672,1047740927,A2 -1047740928,1047781663,EU -1047781664,1047781671,GB -1047781672,1047782695,EU +1047740928,1047782695,EU 1047782696,1047782703,GB 1047782704,1047782719,EU 1047782720,1047782751,SE 1047782752,1047782783,NO 1047782784,1047782815,FI -1047782816,1047789375,EU +1047782816,1047785471,EU +1047785472,1047788031,DE +1047788032,1047789375,EU 1047789376,1047789383,GB 1047789384,1047789407,EU 1047789408,1047789423,DE @@ -10610,7 +10549,9 @@ 1047941376,1047986175,RU 1047986176,1047997439,SE 1047997440,1047997503,NO -1047997504,1048012383,SE +1047997504,1048003503,SE +1048003504,1048003511,NO +1048003512,1048012383,SE 1048012384,1048012391,DE 1048012392,1048051711,SE 1048051712,1048117247,SA @@ -10664,9 +10605,7 @@ 1048605096,1048605103,UA 1048605104,1048605119,LT 1048605120,1048607231,UA -1048607232,1048607247,EE -1048607248,1048607487,UA -1048607488,1048607519,EE +1048607232,1048607519,EE 1048607520,1048607743,UA 1048607744,1048607759,EE 1048607760,1048607775,UA @@ -11120,7 +11059,9 @@ 1048887040,1048887047,DE 1048887048,1048887935,NL 1048887936,1048887999,DE -1048888000,1048891391,NL +1048888000,1048889983,NL +1048889984,1048890015,DE +1048890016,1048891391,NL 1048891392,1048891399,DE 1048891400,1048891823,NL 1048891824,1048891831,DE @@ -11379,9 +11320,7 @@ 1049004544,1049006079,DE 1049006080,1049007103,EU 1049007104,1049007111,DE -1049007112,1049007119,EU -1049007120,1049007135,DE -1049007136,1049007359,EU +1049007112,1049007359,EU 1049007360,1049009535,DE 1049009536,1049009559,EU 1049009560,1049009567,DE @@ -11550,7 +11489,9 @@ 1049759984,1049759999,AE 1049760000,1049760639,DE 1049760640,1049760703,IT -1049760704,1049760927,DE +1049760704,1049760767,DE +1049760768,1049760775,ES +1049760776,1049760927,DE 1049760928,1049760959,DK 1049760960,1049761023,PL 1049761024,1049761791,DE @@ -12075,7 +12016,9 @@ 1052020736,1052022527,EU 1052022528,1052022783,DE 1052022784,1052024831,EU -1052024832,1052041279,DE +1052024832,1052041247,DE +1052041248,1052041255,EU +1052041256,1052041279,DE 1052041280,1052041295,EU 1052041296,1052041327,DE 1052041328,1052041335,EU @@ -12085,9 +12028,7 @@ 1052041600,1052041727,EU 1052041728,1052041863,DE 1052041864,1052041983,EU -1052041984,1052042047,DE -1052042048,1052042087,NL -1052042088,1052042095,DE +1052041984,1052042095,DE 1052042096,1052042143,EU 1052042144,1052042183,DE 1052042184,1052042223,EU @@ -13024,13 +12965,17 @@ 1052876800,1052884991,NG 1052884992,1052901375,FR 1052901376,1053032447,NL -1053032448,1053097983,IT +1053032448,1053047367,IT +1053047368,1053047375,TR +1053047376,1053097983,IT 1053097984,1053106175,DE 1053106176,1053114367,GB 1053114368,1053130751,BE 1053130752,1053138943,NL 1053138944,1053147135,FI -1053147136,1053163519,SK +1053147136,1053155071,SK +1053155072,1053155327,SR +1053155328,1053163519,SK 1053163520,1053294591,DK 1053294592,1053294847,EU 1053294848,1053295103,AT @@ -13121,9 +13066,7 @@ 1053312960,1053313023,EU 1053313024,1053313471,GB 1053313472,1053313479,EU -1053313480,1053313671,GB -1053313672,1053313679,EU -1053313680,1053313791,GB +1053313480,1053313791,GB 1053313792,1053313919,EU 1053313920,1053314047,GB 1053314048,1053314063,EU @@ -13380,9 +13323,7 @@ 1053851904,1053851919,FR 1053851920,1053852031,EU 1053852032,1053852047,IT -1053852048,1053852095,EU -1053852096,1053852103,DE -1053852104,1053852111,EU +1053852048,1053852111,EU 1053852112,1053852127,GB 1053852128,1053852159,DE 1053852160,1053855743,EU @@ -13471,7 +13412,9 @@ 1053896704,1053900799,DE 1053900800,1053917183,NO 1053917184,1053925375,UZ -1053925376,1053933567,SE +1053925376,1053927159,SE +1053927160,1053927163,FI +1053927164,1053933567,SE 1053933568,1053949951,CZ 1053949952,1053984415,FR 1053984416,1053984447,US @@ -13487,11 +13430,17 @@ 1054130176,1054138367,LT 1054138368,1054146559,AZ 1054146560,1054179327,RU -1054179328,1054180095,GB -1054180096,1054180351,DE -1054180352,1054181375,GB -1054181376,1054186495,DE -1054186496,1054187519,GB +1054179328,1054180351,GB +1054180352,1054181120,DE +1054181121,1054181375,GB +1054181376,1054183168,DE +1054183169,1054183423,GB +1054183424,1054185216,DE +1054185217,1054185471,GB +1054185472,1054186240,DE +1054186241,1054186495,GB +1054186496,1054187264,DE +1054187265,1054187519,GB 1054187520,1054195711,BG 1054195712,1054212095,BE 1054212096,1054212519,DE @@ -13740,9 +13689,7 @@ 1055490048,1055522815,PL 1055522816,1055588351,NL 1055588352,1055653887,BE -1055653888,1055681055,FI -1055681056,1055681071,SE -1055681072,1055784959,FI +1055653888,1055784959,FI 1055784960,1055850495,NL 1055850496,1055916031,GB 1055916032,1055924223,RS @@ -13998,7 +13945,13 @@ 1064973056,1064973183,AU 1064973184,1065049471,US 1065049472,1065049535,CA -1065049536,1065517087,US +1065049536,1065389439,US +1065389440,1065389455,MY +1065389456,1065390591,US +1065390592,1065390599,MY +1065390600,1065390655,US +1065390656,1065390687,MX +1065390688,1065517087,US 1065517088,1065517119,A2 1065517120,1065519359,US 1065519360,1065519487,CA @@ -14021,7 +13974,7 @@ 1066311680,1066315775,CA 1066315776,1066332159,US 1066332160,1066336255,CA -1066336256,1066344447,US +1066336256,1066352639,US 1066352640,1066369023,JM 1066369024,1066584063,US 1066584064,1066586111,PE @@ -14208,7 +14161,15 @@ 1071477248,1071480831,CA 1071480832,1071488447,US 1071488448,1071488479,HK -1071488480,1071985631,US +1071488480,1071599105,US +1071599106,1071599134,PH +1071599135,1071599300,US +1071599301,1071599313,PH +1071599314,1071599392,US +1071599393,1071599415,PH +1071599416,1071599477,US +1071599478,1071599490,PH +1071599491,1071985631,US 1071985632,1071985663,ML 1071985664,1072512951,US 1072512952,1072512959,CA @@ -14348,12 +14309,10 @@ 1073045248,1073045503,PR 1073045504,1073047551,CO 1073047552,1073049599,PR -1073049600,1073053695,BS -1073053696,1073091397,US +1073049600,1073052671,BS +1073052672,1073091397,US 1073091398,1073091407,CH -1073091408,1073092335,US -1073092336,1073092351,CA -1073092352,1073093646,US +1073091408,1073093646,US 1073093647,1073093654,PE 1073093655,1073094557,US 1073094558,1073094570,IT @@ -14507,9 +14466,7 @@ 1074229248,1074241535,CA 1074241536,1074249791,US 1074249792,1074249807,BB -1074249808,1074371583,US -1074371584,1074372095,A1 -1074372096,1074375935,US +1074249808,1074375935,US 1074375936,1074376191,A1 1074376192,1074397439,US 1074397440,1074399039,CA @@ -14620,11 +14577,11 @@ 1075479104,1075479111,GB 1075479112,1075479135,CA 1075479136,1075479151,US -1075479152,1075479567,CA -1075479568,1075479583,US -1075479584,1075479607,CA +1075479152,1075479607,CA 1075479608,1075479615,US -1075479616,1075484263,CA +1075479616,1075480415,CA +1075480416,1075480423,US +1075480424,1075484263,CA 1075484264,1075484271,US 1075484272,1075494911,CA 1075494912,1075513151,US @@ -14733,7 +14690,8 @@ 1075597168,1075597183,CA 1075597184,1075597375,US 1075597376,1075597407,CA -1075597408,1075597439,IL +1075597408,1075597423,US +1075597424,1075597439,IL 1075597440,1075597551,US 1075597552,1075597599,CA 1075597600,1075598367,US @@ -14750,9 +14708,7 @@ 1075601280,1075601295,CA 1075601296,1075609599,US 1075609600,1075613695,TT -1075613696,1075744511,US -1075744512,1075744639,NL -1075744640,1075744767,US +1075613696,1075744767,US 1075744768,1075748863,A2 1075748864,1075855359,US 1075855360,1075871743,DO @@ -14762,9 +14718,13 @@ 1075972352,1075973887,US 1075973888,1075974143,CA 1075974144,1075975167,US -1075975168,1075976175,CA +1075975168,1075975679,CA +1075975680,1075975815,US +1075975816,1075976175,CA 1075976176,1075976191,US -1075976192,1075976511,CA +1075976192,1075976447,CA +1075976448,1075976479,US +1075976480,1075976511,CA 1075976512,1075976543,US 1075976544,1075976647,CA 1075976648,1075976655,US @@ -14887,8 +14847,8 @@ 1076004472,1076004479,CA 1076004480,1076004495,US 1076004496,1076004511,CA -1076004512,1076004559,US -1076004560,1076004591,CA +1076004512,1076004543,US +1076004544,1076004591,CA 1076004592,1076004607,US 1076004608,1076004639,CA 1076004640,1076004703,US @@ -14904,8 +14864,8 @@ 1076005248,1076005263,US 1076005264,1076005279,CA 1076005280,1076005311,US -1076005312,1076005319,CA -1076005320,1076005375,US +1076005312,1076005343,CA +1076005344,1076005375,US 1076005376,1076005887,CA 1076005888,1076006015,US 1076006016,1076006047,CA @@ -14952,8 +14912,8 @@ 1076026608,1076026623,SG 1076026624,1076026975,CA 1076026976,1076027031,US -1076027032,1076027263,CA -1076027264,1076027295,US +1076027032,1076027199,CA +1076027200,1076027295,US 1076027296,1076027407,CA 1076027408,1076027423,US 1076027424,1076027711,CA @@ -14974,7 +14934,9 @@ 1076029224,1076029231,DM 1076029232,1076029239,CA 1076029240,1076029247,US -1076029248,1076029311,CA +1076029248,1076029255,CA +1076029256,1076029263,US +1076029264,1076029311,CA 1076029312,1076029319,GB 1076029320,1076029415,CA 1076029416,1076029422,US @@ -15013,7 +14975,9 @@ 1076035296,1076035327,EG 1076035328,1076035415,US 1076035416,1076035423,EG -1076035424,1076036247,US +1076035424,1076035519,US +1076035520,1076035583,IN +1076035584,1076036247,US 1076036248,1076036255,IL 1076036256,1076036351,US 1076036352,1076036605,ES @@ -15061,9 +15025,13 @@ 1076179162,1076179163,IN 1076179164,1076179196,US 1076179197,1076179198,IN -1076179199,1076180795,US +1076179199,1076180201,US +1076180202,1076180222,PK +1076180223,1076180795,US 1076180796,1076180799,IN -1076180800,1076183039,US +1076180800,1076181236,US +1076181237,1076181237,CA +1076181238,1076183039,US 1076183040,1076183071,IN 1076183072,1076183231,US 1076183232,1076183295,CA @@ -15924,24 +15892,19 @@ 1077626240,1077626271,WS 1077626272,1077627167,US 1077627168,1077627199,EC -1077627200,1077628959,US -1077628960,1077628991,ES -1077628992,1077629071,US +1077627200,1077629071,US 1077629072,1077629087,CR -1077629088,1077629119,US -1077629120,1077629151,NL +1077629088,1077629151,US 1077629152,1077629183,CA 1077629184,1077629535,US 1077629536,1077629567,CA 1077629568,1077629903,US 1077629904,1077629919,AN -1077629920,1077630015,US -1077630016,1077630047,CA -1077630048,1077632159,US +1077629920,1077631167,US +1077631168,1077631231,NL +1077631232,1077632159,US 1077632160,1077632191,GB -1077632192,1077632447,US -1077632448,1077632479,NL -1077632480,1077633823,US +1077632192,1077633823,US 1077633824,1077633855,AN 1077633856,1077640799,US 1077640800,1077640831,EC @@ -16280,7 +16243,8 @@ 1077937827,1077937846,US 1077937847,1077937850,TH 1077937851,1077937854,US -1077937855,1077937866,TH +1077937855,1077937862,TH +1077937863,1077937866,SA 1077937867,1077937870,GB 1077937871,1077937878,US 1077937879,1077937882,GB @@ -16335,9 +16299,7 @@ 1077938206,1077938209,AR 1077938210,1077938221,US 1077938222,1077938225,IN -1077938226,1077938233,US -1077938234,1077938237,AR -1077938238,1077938258,US +1077938226,1077938258,US 1077938259,1077938262,PE 1077938263,1077938266,CA 1077938267,1077938269,GB @@ -16527,9 +16489,13 @@ 1077939492,1077939495,GB 1077939496,1077939523,US 1077939524,1077939533,CA -1077939534,1077939569,US +1077939534,1077939557,US +1077939558,1077939561,MU +1077939562,1077939569,US 1077939570,1077939574,OM -1077939575,1077939625,US +1077939575,1077939582,US +1077939583,1077939586,GH +1077939587,1077939625,US 1077939626,1077939630,UY 1077939631,1077939634,GB 1077939635,1077939644,US @@ -16553,7 +16519,9 @@ 1077939986,1077939997,US 1077939998,1077940001,GB 1077940002,1077940005,EG -1077940006,1077940072,US +1077940006,1077940064,US +1077940065,1077940068,GB +1077940069,1077940072,US 1077940073,1077940076,BE 1077940077,1077940133,US 1077940134,1077940137,IN @@ -16938,9 +16906,7 @@ 1078287328,1078287343,US 1078287344,1078287759,CA 1078287760,1078287767,US -1078287768,1078287775,CA -1078287776,1078287807,US -1078287808,1078287839,CA +1078287768,1078287839,CA 1078287840,1078287863,US 1078287864,1078288383,CA 1078288384,1078309695,US @@ -17078,9 +17044,7 @@ 1078621696,1078621951,IN 1078621952,1078651055,US 1078651056,1078651071,CA -1078651072,1078653695,US -1078653696,1078653727,CZ -1078653728,1078654431,US +1078651072,1078654431,US 1078654432,1078654439,AU 1078654440,1078660799,US 1078660800,1078660831,CN @@ -17315,9 +17279,7 @@ 1079385088,1079385343,US 1079385344,1079385471,CA 1079385472,1079385599,US -1079385600,1079385855,CA -1079385856,1079386111,SZ -1079386112,1079386623,CA +1079385600,1079386623,CA 1079386624,1079386879,SG 1079386880,1079387135,EG 1079387136,1079387903,US @@ -17386,7 +17348,7 @@ 1079408448,1079408639,CA 1079408640,1079408895,US 1079408896,1079409407,PK -1079409408,1079409919,LR +1079409408,1079409919,US 1079409920,1079410687,CA 1079410688,1079410943,US 1079410944,1079411199,CA @@ -17399,9 +17361,7 @@ 1079413344,1079413535,CA 1079413536,1079413567,US 1079413568,1079414271,CA -1079414272,1079414527,US -1079414528,1079414783,CA -1079414784,1079415039,US +1079414272,1079415039,US 1079415040,1079415295,HN 1079415296,1079415807,CA 1079415808,1079416319,US @@ -17638,7 +17598,9 @@ 1081368744,1081368767,CO 1081368768,1081369119,US 1081369120,1081369151,CO -1081369152,1081369599,US +1081369152,1081369183,US +1081369184,1081369215,CO +1081369216,1081369599,US 1081369600,1081370111,CO 1081370112,1081377079,US 1081377080,1081377087,VE @@ -17701,8 +17663,8 @@ 1081401568,1081401599,AR 1081401600,1081401615,US 1081401616,1081401735,AR -1081401736,1081401751,US -1081401752,1081401775,AR +1081401736,1081401743,US +1081401744,1081401775,AR 1081401776,1081401791,US 1081401792,1081401807,AR 1081401808,1081401815,US @@ -17785,31 +17747,31 @@ 1081479168,1081483247,CA 1081483248,1081483255,US 1081483256,1081483263,CA -1081483264,1081487359,US -1081487360,1081487375,A2 -1081487376,1081487383,US -1081487384,1081487391,A2 -1081487392,1081487407,US -1081487408,1081487567,A2 -1081487568,1081487583,US -1081487584,1081487919,A2 -1081487920,1081487927,US -1081487928,1081487959,A2 -1081487960,1081487967,US -1081487968,1081488055,A2 -1081488056,1081488079,US -1081488080,1081488087,A2 -1081488088,1081488095,US -1081488096,1081488135,A2 -1081488136,1081488151,US -1081488152,1081488199,A2 -1081488200,1081488215,US -1081488216,1081488223,A2 -1081488224,1081488247,US -1081488248,1081488255,A2 -1081488256,1081488287,US -1081488288,1081491455,A2 -1081491456,1081565183,US +1081483264,1081487367,US +1081487368,1081487375,A2 +1081487376,1081487407,US +1081487408,1081487519,A2 +1081487520,1081487583,US +1081487584,1081487871,A2 +1081487872,1081487979,US +1081487980,1081487991,A2 +1081487992,1081488111,US +1081488112,1081488119,A2 +1081488120,1081488123,US +1081488124,1081488135,A2 +1081488136,1081488159,US +1081488160,1081488167,A2 +1081488168,1081488295,US +1081488296,1081488303,A2 +1081488304,1081488335,US +1081488336,1081488343,A2 +1081488344,1081488351,US +1081488352,1081488383,A2 +1081488384,1081489671,US +1081489672,1081489679,A2 +1081489680,1081489687,US +1081489688,1081489919,A2 +1081489920,1081565183,US 1081565184,1081573375,CA 1081573376,1081581615,US 1081581616,1081581623,JP @@ -17908,7 +17870,19 @@ 1081589112,1081589759,US 1081589760,1081593855,BB 1081593856,1081597951,CA -1081597952,1081609823,US +1081597952,1081608191,US +1081608192,1081608207,CA +1081608208,1081608223,US +1081608224,1081608231,CA +1081608232,1081608319,US +1081608320,1081608327,CA +1081608328,1081608335,US +1081608336,1081608343,CA +1081608344,1081608503,US +1081608504,1081608511,CA +1081608512,1081608575,US +1081608576,1081608583,CA +1081608584,1081609823,US 1081609824,1081609831,LK 1081609832,1081609887,US 1081609888,1081609919,IN @@ -18043,9 +18017,13 @@ 1082434240,1082434255,IN 1082434256,1082621987,US 1082621988,1082621991,ME -1082621992,1082683391,US +1082621992,1082679807,US 1082683392,1082687487,CA -1082687488,1082885311,US +1082687488,1082788447,US +1082788448,1082788455,SG +1082788456,1082788767,US +1082788768,1082788799,SG +1082788800,1082885311,US 1082885312,1082885343,CA 1082885344,1082885855,US 1082885856,1082885887,CA @@ -18254,7 +18232,13 @@ 1086922752,1086923343,CA 1086923344,1086923351,US 1086923352,1086930943,CA -1086930944,1086955519,US +1086930944,1086941831,US +1086941832,1086941835,CA +1086941836,1086942079,US +1086942080,1086942087,CA +1086942088,1086942975,US +1086942976,1086943231,CA +1086943232,1086955519,US 1086955520,1086971903,CA 1086971904,1087008767,US 1087008768,1087009279,CY @@ -18267,7 +18251,7 @@ 1087420160,1087440895,US 1087440896,1087442943,PR 1087442944,1087444223,US -1087444224,1087444479,CY +1087444224,1087444479,GB 1087444480,1087495519,US 1087495520,1087495535,TW 1087495536,1087496703,US @@ -18491,7 +18475,18 @@ 1089265664,1089265919,GB 1089265920,1089266431,US 1089266432,1089266943,GB -1089266944,1089306623,US +1089266944,1089282059,US +1089282060,1089282063,CA +1089282064,1089282075,US +1089282076,1089282079,CA +1089282080,1089282095,US +1089282096,1089282099,CA +1089282100,1089282687,US +1089282688,1089282703,A1 +1089282704,1089282711,CA +1089282712,1089285439,US +1089285440,1089285455,A1 +1089285456,1089306623,US 1089306624,1089339391,PR 1089339392,1089393295,US 1089393296,1089393407,CA @@ -18693,9 +18688,7 @@ 1091695214,1091695223,CA 1091695224,1091695283,US 1091695284,1091695293,CA -1091695294,1091797263,US -1091797264,1091797279,IT -1091797280,1091797855,US +1091695294,1091797855,US 1091797856,1091797871,IT 1091797872,1091798639,US 1091798640,1091798647,CN @@ -19595,9 +19588,7 @@ 1096890880,1096891135,GB 1096891136,1096925183,US 1096925184,1096941567,CA -1096941568,1096942679,US -1096942680,1096942687,IE -1096942688,1096947471,US +1096941568,1096947471,US 1096947472,1096947479,MY 1096947480,1096950551,US 1096950552,1096950559,CA @@ -19621,13 +19612,19 @@ 1096960768,1096960895,GB 1096960896,1096964263,US 1096964264,1096964271,IN -1096964272,1096968127,US +1096964272,1096966303,US +1096966304,1096966311,IN +1096966312,1096968127,US 1096968128,1096968159,CA 1096968160,1096968191,US 1096968192,1096968319,GB -1096968320,1096969471,US +1096968320,1096969071,US +1096969072,1096969079,CA +1096969080,1096969471,US 1096969472,1096969479,IN -1096969480,1097057623,US +1096969480,1097056559,US +1097056560,1097056575,SE +1097056576,1097057623,US 1097057624,1097057631,IT 1097057632,1097057655,US 1097057656,1097057663,NZ @@ -19665,7 +19662,9 @@ 1097731456,1097736191,CA 1097736192,1097768959,US 1097768960,1097777151,CA -1097777152,1097830399,US +1097777152,1097797631,US +1097797632,1097797887,DE +1097797888,1097830399,US 1097830400,1097834495,CA 1097834496,1097896191,US 1097896192,1097896711,VI @@ -20076,9 +20075,7 @@ 1106605696,1106605703,DE 1106605704,1106685047,US 1106685048,1106685055,CA -1106685056,1106740991,US -1106740992,1106741247,CR -1106741248,1106758655,US +1106685056,1106758655,US 1106758656,1106759167,EC 1106759168,1106759679,CO 1106759680,1106767871,US @@ -20101,15 +20098,15 @@ 1107288064,1107292159,CA 1107292160,1107701759,US 1107701760,1107705855,CA -1107705856,1107800063,US -1107800064,1107800319,CA -1107800320,1107801367,US +1107705856,1107801367,US 1107801368,1107801375,CA 1107801376,1107808842,US 1107808843,1107808846,PE 1107808847,1107808877,US 1107808878,1107808881,PE -1107808882,1107820543,US +1107808882,1107809850,US +1107809851,1107809851,CA +1107809852,1107820543,US 1107820544,1107853311,ZA 1107853312,1107895039,US 1107895040,1107895807,GB @@ -20483,8 +20480,8 @@ 1110700032,1110704127,CA 1110704128,1110863871,US 1110863872,1110865919,JM -1110865920,1110867200,KY -1110867201,1110867967,JM +1110865920,1110867455,KY +1110867456,1110867967,JM 1110867968,1110870791,US 1110870792,1110870799,HK 1110870800,1110870815,US @@ -20517,7 +20514,20 @@ 1112433152,1112440831,CA 1112440832,1112530943,US 1112530944,1112539135,CA -1112539136,1113212479,US +1112539136,1112900711,US +1112900712,1112900719,MV +1112900720,1112901623,US +1112901624,1112901631,EG +1112901632,1112901759,US +1112901760,1112901767,EG +1112901768,1112903711,US +1112903712,1112903719,TR +1112903720,1112906431,US +1112906432,1112906439,GB +1112906440,1112907919,US +1112907920,1112907935,EG +1112907936,1112915967,US +1112924160,1113212479,US 1113212480,1113212495,CA 1113212496,1113591807,US 1113591808,1113595903,CA @@ -20624,10 +20634,11 @@ 1114875392,1114876159,CA 1114876160,1114876447,US 1114876448,1114876463,CA -1114876464,1114876479,US +1114876464,1114876479,AD 1114876480,1114876543,CA 1114876544,1114876575,GB -1114876576,1114876927,US +1114876576,1114876911,US +1114876912,1114876927,AD 1114876928,1114877183,CA 1114877184,1114877439,CY 1114877440,1114877695,US @@ -20651,7 +20662,9 @@ 1114881472,1114881535,CY 1114881536,1114928863,US 1114928864,1114928871,GB -1114928872,1114930175,US +1114928872,1114929071,US +1114929072,1114929087,RU +1114929088,1114930175,US 1114930176,1114930303,GB 1114930304,1114966815,US 1114966816,1114966831,GB @@ -21036,13 +21049,7 @@ 1117814824,1117814831,CN 1117814832,1117815295,US 1117815296,1117815551,CN -1117815552,1117816831,US -1117816832,1117816863,CN -1117816864,1117816879,US -1117816880,1117816887,CN -1117816888,1117816895,US -1117816896,1117816959,CN -1117816960,1117817919,US +1117815552,1117817919,US 1117817920,1117817983,CA 1117817984,1117818495,US 1117818496,1117818623,IT @@ -21139,8 +21146,8 @@ 1118133632,1118133695,US 1118133696,1118133759,IN 1118133760,1118133887,CA -1118133888,1118134783,US -1118134784,1118134879,CA +1118133888,1118134815,US +1118134816,1118134879,CA 1118134880,1118134911,US 1118134912,1118134975,CA 1118134976,1118135007,US @@ -21149,9 +21156,7 @@ 1118135568,1118135583,CA 1118135584,1118135615,US 1118135616,1118135631,TZ -1118135632,1118135647,US -1118135648,1118135663,CA -1118135664,1118135807,US +1118135632,1118135807,US 1118135808,1118136191,CA 1118136192,1118136831,US 1118136832,1118136863,IN @@ -21295,7 +21300,9 @@ 1118535680,1118539775,CA 1118539776,1118543871,US 1118543872,1118547967,CA -1118547968,1118564607,US +1118547968,1118563839,US +1118563840,1118564351,BZ +1118564352,1118564607,US 1118564608,1118564639,NO 1118564640,1118564655,US 1118564656,1118564671,IN @@ -21520,7 +21527,7 @@ 1118973160,1118973167,NI 1118973168,1118973183,A2 1118973184,1118973439,VE -1118973440,1118973695,HK +1118973440,1118973695,US 1118973696,1118973951,NG 1118973952,1118974015,GY 1118974016,1118974047,A2 @@ -21674,7 +21681,9 @@ 1118983424,1118983679,NI 1118983680,1118983743,TZ 1118983744,1118983759,VE -1118983760,1118983871,A2 +1118983760,1118983807,A2 +1118983808,1118983839,NG +1118983840,1118983871,A2 1118983872,1118983879,TZ 1118983880,1118983919,US 1118983920,1118984447,A2 @@ -21940,11 +21949,15 @@ 1120315136,1120315391,US 1120315392,1120321535,CA 1120321536,1120346111,US -1120346112,1120347527,CA +1120346112,1120347039,CA +1120347040,1120347055,US +1120347056,1120347135,CA +1120347136,1120347391,US +1120347392,1120347527,CA 1120347528,1120347535,US 1120347536,1120347591,CA -1120347592,1120347599,US -1120347600,1120350207,CA +1120347592,1120347607,US +1120347608,1120350207,CA 1120350208,1120370687,US 1120370688,1120371199,CA 1120371200,1120371455,US @@ -21984,8 +21997,8 @@ 1120376304,1120376327,CA 1120376328,1120376383,US 1120376384,1120376447,CA -1120376448,1120376479,US -1120376480,1120376494,CA +1120376448,1120376455,US +1120376456,1120376494,CA 1120376495,1120376559,US 1120376560,1120376647,CA 1120376648,1120376671,US @@ -22015,7 +22028,9 @@ 1120380128,1120380131,CA 1120380132,1120380223,US 1120380224,1120380239,CA -1120380240,1120380415,US +1120380240,1120380263,US +1120380264,1120380271,CA +1120380272,1120380415,US 1120380416,1120380431,VG 1120380432,1120380447,CA 1120380448,1120380479,US @@ -22183,35 +22198,46 @@ 1120874496,1120874503,A2 1120874504,1120874511,US 1120874512,1120874519,A2 -1120874520,1120874527,US -1120874528,1120874631,A2 +1120874520,1120874543,US +1120874544,1120874563,A2 +1120874564,1120874575,US +1120874576,1120874587,A2 +1120874588,1120874591,US +1120874592,1120874631,A2 1120874632,1120874639,US -1120874640,1120874655,A2 -1120874656,1120874703,US +1120874640,1120874651,A2 +1120874652,1120874703,US 1120874704,1120874719,CA 1120874720,1120874727,A2 -1120874728,1120874751,US -1120874752,1120874783,A2 -1120874784,1120874815,US -1120874816,1120874855,A2 -1120874856,1120874871,US -1120874872,1120874911,A2 +1120874728,1120874763,US +1120874764,1120874767,A2 +1120874768,1120874775,US +1120874776,1120874779,A2 +1120874780,1120874815,US +1120874816,1120874831,A2 +1120874832,1120874839,US +1120874840,1120874847,A2 +1120874848,1120874879,US +1120874880,1120874887,A2 +1120874888,1120874895,US +1120874896,1120874911,A2 1120874912,1120874935,US 1120874936,1120874943,A2 1120874944,1120874959,CA -1120874960,1120874967,A2 -1120874968,1120874975,US -1120874976,1120874983,A2 -1120874984,1120875007,US -1120875008,1120875263,A2 -1120875264,1120876287,US +1120874960,1120874979,US +1120874980,1120874983,A2 +1120874984,1120876287,US 1120876288,1120876543,A2 1120876544,1120876567,JO 1120876568,1120876575,A2 1120876576,1120876591,JO 1120876592,1120876599,A2 1120876600,1120876607,JO -1120876608,1120876799,A2 +1120876608,1120876615,A2 +1120876616,1120876623,US +1120876624,1120876655,A2 +1120876656,1120876671,US +1120876672,1120876799,A2 1120876800,1120878359,US 1120878360,1120878591,A2 1120878592,1120886783,US @@ -22262,7 +22288,7 @@ 1121247568,1121247583,MT 1121247584,1121247591,CY 1121247592,1121247615,CA -1121247616,1121247631,PA +1121247616,1121247631,BZ 1121247632,1121247639,AW 1121247640,1121247647,VG 1121247648,1121247663,US @@ -22350,18 +22376,19 @@ 1121251048,1121251055,AW 1121251056,1121251071,CA 1121251072,1121251079,GB -1121251080,1121251095,CY +1121251080,1121251087,CA +1121251088,1121251095,CY 1121251096,1121251103,CA 1121251104,1121251119,BZ 1121251120,1121251135,CA 1121251136,1121251167,AG 1121251168,1121251199,VG 1121251200,1121251263,AW -1121251264,1121251271,CA -1121251272,1121251279,KN -1121251280,1121251295,CA +1121251264,1121251279,CA +1121251280,1121251287,BZ +1121251288,1121251295,CA 1121251296,1121251311,IM -1121251312,1121251327,PA +1121251312,1121251327,BZ 1121251328,1121251583,CA 1121251584,1121251591,BZ 1121251592,1121251599,MT @@ -22373,15 +22400,14 @@ 1121251664,1121251671,MT 1121251672,1121251679,CA 1121251680,1121251687,AG -1121251688,1121251775,BZ -1121251776,1121251791,CA +1121251688,1121251791,BZ 1121251792,1121251807,VG 1121251808,1121251831,CA 1121251832,1121251839,VG 1121251840,1121251847,BZ 1121251848,1121251855,PA 1121251856,1121251863,AN -1121251864,1121251871,CA +1121251864,1121251871,BZ 1121251872,1121251887,VG 1121251888,1121251895,CY 1121251896,1121251903,CA @@ -22751,7 +22777,9 @@ 1122101376,1122101383,CO 1122101384,1122101431,US 1122101432,1122101439,SG -1122101440,1122103471,US +1122101440,1122101471,US +1122101472,1122101479,VE +1122101480,1122103471,US 1122103472,1122103479,BE 1122103480,1122125996,US 1122125997,1122126004,GB @@ -22853,19 +22881,24 @@ 1123582272,1123582399,US 1123582400,1123582431,DE 1123582432,1123582463,CA -1123582464,1123583455,US -1123583456,1123583519,CY +1123582464,1123583487,US +1123583488,1123583519,CY 1123583520,1123584351,US 1123584352,1123584383,DE 1123584384,1123588063,US 1123588064,1123588095,CY -1123588096,1123588351,DE -1123588352,1123589631,US +1123588096,1123589631,US 1123589632,1123589887,DE 1123589888,1123590143,US 1123590144,1123598335,VI 1123598336,1123651583,US -1123651584,1123655679,JM +1123651584,1123651839,JM +1123651840,1123652095,BB +1123652096,1123653119,JM +1123653120,1123653375,BB +1123653376,1123653631,JM +1123653632,1123654655,KY +1123654656,1123655679,JM 1123655680,1123663871,US 1123663872,1123667967,SV 1123667968,1123670015,PR @@ -23058,7 +23091,9 @@ 1125396484,1125396491,LK 1125396492,1125396999,US 1125397000,1125397007,ES -1125397008,1125454007,US +1125397008,1125398466,US +1125398467,1125398468,LK +1125398469,1125454007,US 1125454008,1125454015,GB 1125454016,1125454111,US 1125454112,1125454119,ES @@ -23206,11 +23241,15 @@ 1125541544,1125541551,CN 1125541552,1125541807,CA 1125541808,1125541815,US -1125541816,1125543543,CA +1125541816,1125541951,CA +1125541952,1125541959,BM +1125541960,1125543543,CA 1125543544,1125543551,US 1125543552,1125543687,CA 1125543688,1125543695,US -1125543696,1125543935,CA +1125543696,1125543887,CA +1125543888,1125543903,US +1125543904,1125543935,CA 1125543936,1125545983,US 1125548032,1125548291,CA 1125548292,1125548351,US @@ -23231,13 +23270,19 @@ 1125623296,1125623551,IN 1125623552,1125628671,US 1125628672,1125628703,NZ -1125628704,1125642301,US +1125628704,1125641790,US +1125641791,1125641792,CA +1125641793,1125642185,US +1125642186,1125642189,CA +1125642190,1125642301,US 1125642302,1125642303,IN 1125642304,1125642674,US 1125642675,1125642694,BO -1125642695,1126009343,US -1126009344,1126009599,AR -1126009600,1126504223,US +1125642695,1125644770,US +1125644771,1125644771,PK +1125644772,1125645449,US +1125645450,1125645453,CA +1125645454,1126504223,US 1126504224,1126504231,PR 1126504232,1126551767,US 1126551768,1126551775,PR @@ -23354,8 +23399,14 @@ 1133785504,1133785567,US 1133785568,1133785599,BE 1133785600,1134029055,US -1134029056,1134029567,A2 -1134029568,1134444543,US +1134029056,1134029151,A2 +1134029152,1134029159,US +1134029160,1134029183,A2 +1134029184,1134029215,US +1134029216,1134029567,A2 +1134029568,1134440447,US +1134440448,1134443520,CN +1134443521,1134444543,US 1134444544,1134448639,CA 1134448640,1134545919,US 1134545920,1134545951,BH @@ -24411,7 +24462,9 @@ 1137928064,1137928191,PA 1137928192,1137928255,CA 1137928256,1137928319,BZ -1137928320,1137930143,CA +1137928320,1137929727,CA +1137929728,1137929983,IE +1137929984,1137930143,CA 1137930144,1137930159,MT 1137930160,1137934335,CA 1137934336,1137946145,US @@ -24550,9 +24603,13 @@ 1138337208,1138417663,US 1138417664,1138417695,CA 1138417696,1138417727,DE -1138417728,1138421759,US +1138417728,1138419711,US +1138419712,1138419967,DE +1138419968,1138421759,US 1138421760,1138421791,DE -1138421792,1138425855,US +1138421792,1138422271,US +1138422272,1138422527,DE +1138422528,1138425855,US 1138425856,1138427519,KN 1138427520,1138427647,US 1138427648,1138429951,KN @@ -24644,9 +24701,11 @@ 1138512896,1138512927,ID 1138512928,1138544895,US 1138544896,1138545151,GB -1138545152,1138548735,US -1138548736,1138556927,CA -1138556928,1138593791,US +1138545152,1138548991,US +1138548992,1138549247,CA +1138549248,1138553087,US +1138553088,1138553343,CA +1138553344,1138593791,US 1138593792,1138597887,CA 1138597888,1138600447,US 1138600448,1138600703,BE @@ -24692,12 +24751,14 @@ 1138656207,1138656222,US 1138656223,1138656230,EG 1138656231,1138656597,US -1138656598,1138656605,EG -1138656606,1138656661,US +1138656598,1138656613,EG +1138656614,1138656661,US 1138656662,1138656669,MA 1138656670,1138656745,US 1138656746,1138656753,AE -1138656754,1138657101,US +1138656754,1138656909,US +1138656910,1138656917,IN +1138656918,1138657101,US 1138657102,1138657109,IN 1138657110,1138657123,US 1138657124,1138657131,EG @@ -24720,7 +24781,8 @@ 1138658058,1138658123,GB 1138658124,1138658131,US 1138658132,1138658163,EG -1138658164,1138658175,US +1138658164,1138658167,US +1138658168,1138658175,EG 1138658176,1138658302,GB 1138658303,1138658431,US 1138658432,1138658496,PK @@ -24750,7 +24812,8 @@ 1138659790,1138659797,ID 1138659798,1138659805,US 1138659806,1138659813,ID -1138659814,1138659823,US +1138659814,1138659821,LK +1138659822,1138659823,US 1138659824,1138659831,ID 1138659832,1138659849,US 1138659850,1138659857,MA @@ -24761,7 +24824,9 @@ 1138659984,1138659999,EG 1138660000,1138660035,US 1138660036,1138660043,IN -1138660044,1138660105,US +1138660044,1138660050,US +1138660051,1138660058,PH +1138660059,1138660105,US 1138660106,1138660137,GB 1138660138,1138660169,US 1138660170,1138660177,MA @@ -24792,9 +24857,7 @@ 1138660806,1138660821,EG 1138660822,1138660873,US 1138660874,1138660881,EG -1138660882,1138660889,US -1138660890,1138660897,EG -1138660898,1138660921,US +1138660882,1138660921,US 1138660922,1138660929,EG 1138660930,1138660958,US 1138660959,1138660966,MA @@ -24818,7 +24881,7 @@ 1138661308,1138661417,US 1138661418,1138661425,LK 1138661426,1138661457,US -1138661458,1138661465,IN +1138661458,1138661465,EG 1138661466,1138661521,US 1138661522,1138661529,EG 1138661530,1138661553,US @@ -24840,9 +24903,7 @@ 1138661822,1138661829,MA 1138661830,1138661913,US 1138661914,1138661954,EG -1138661955,1138661977,US -1138661978,1138661993,EG -1138661994,1138662057,US +1138661955,1138662057,US 1138662058,1138662089,EG 1138662090,1138662097,ID 1138662098,1138662105,US @@ -24910,8 +24971,8 @@ 1139146752,1139154943,GT 1139154944,1139167231,JM 1139167232,1139167743,US -1139167744,1139169023,PR -1139169024,1139169279,US +1139167744,1139168895,PR +1139168896,1139169279,US 1139169280,1139170047,PR 1139170048,1139171327,US 1139171328,1139175423,GT @@ -24946,9 +25007,7 @@ 1142204104,1142204111,PR 1142204112,1142204327,US 1142204328,1142204335,PR -1142204336,1145053455,US -1145053456,1145053471,NG -1145053472,1145056703,US +1142204336,1145056703,US 1145056704,1145056719,CO 1145056720,1145188351,US 1145188352,1145192447,CA @@ -24968,9 +25027,7 @@ 1145261312,1145261375,IN 1145261376,1145307135,US 1145307136,1145311231,CA -1145311232,1145331711,US -1145331712,1145331967,DK -1145331968,1145333031,US +1145311232,1145333031,US 1145333032,1145333039,IT 1145333040,1145333191,US 1145333192,1145333199,CN @@ -25019,7 +25076,9 @@ 1145503744,1145520127,CA 1145520128,1145552895,US 1145552896,1145556991,CA -1145556992,1150043135,US +1145556992,1145567839,US +1145567840,1145567871,CN +1145567872,1150043135,US 1150043136,1150044159,VA 1150044160,1150046207,US 1150046208,1150050303,JP @@ -25095,8 +25154,8 @@ 1156130016,1156130303,CA 1156130304,1156131327,US 1156131328,1156131583,CA -1156131584,1156259839,US -1156259840,1156265983,CA +1156131584,1156263935,US +1156263936,1156265983,CA 1156265984,1156296703,US 1156296704,1156300799,CA 1156300800,1157670431,US @@ -25391,7 +25450,9 @@ 1158732885,1158736241,US 1158736242,1158736249,IN 1158736250,1158774783,US -1158774784,1158791167,CA +1158774784,1158776947,CA +1158776948,1158776951,US +1158776952,1158791167,CA 1158791168,1158794239,BM 1158794240,1158794495,US 1158794496,1158799359,BM @@ -25439,7 +25500,9 @@ 1158945096,1158945103,TH 1158945104,1158945111,RU 1158945112,1158945119,CA -1158945120,1158945271,US +1158945120,1158945127,US +1158945128,1158945135,MX +1158945136,1158945271,US 1158945272,1158945287,CA 1158945288,1158945319,US 1158945320,1158945335,CA @@ -25511,9 +25574,7 @@ 1158949288,1158949295,CA 1158949296,1158949407,US 1158949408,1158949415,ZA -1158949416,1158949775,US -1158949776,1158949783,GB -1158949784,1158950105,US +1158949416,1158950105,US 1158950106,1158950107,CA 1158950108,1158950319,US 1158950320,1158950327,CA @@ -25542,7 +25603,9 @@ 1158951744,1158951751,IN 1158951752,1158951839,US 1158951840,1158951855,CA -1158951856,1158952743,US +1158951856,1158952711,US +1158952712,1158952719,IN +1158952720,1158952743,US 1158952744,1158952751,FI 1158952752,1158952815,US 1158952816,1158952823,CA @@ -25568,22 +25631,23 @@ 1158957472,1158957647,US 1158957648,1158957655,AU 1158957656,1158957663,PE -1158957664,1158957695,US -1158957696,1158957703,TH -1158957704,1158958295,US +1158957664,1158958295,US 1158958296,1158958303,AG 1158958304,1158958311,ES 1158958312,1158958367,US 1158958368,1158958375,CA 1158958376,1158958591,US 1158958592,1158958599,ZA -1158958600,1158958671,US +1158958600,1158958607,IL +1158958608,1158958671,US 1158958672,1158958679,SA 1158958680,1158958719,US 1158958720,1158958751,CA 1158958752,1158959031,US 1158959032,1158959039,CA -1158959040,1158959135,US +1158959040,1158959079,US +1158959080,1158959081,BG +1158959082,1158959135,US 1158959136,1158959151,BD 1158959152,1158959679,US 1158959680,1158959687,CR @@ -25605,7 +25669,9 @@ 1158961256,1158961263,ES 1158961264,1158961775,US 1158961776,1158961783,CA -1158961784,1158962175,US +1158961784,1158962023,US +1158962024,1158962027,IL +1158962028,1158962175,US 1158962176,1158962183,GB 1158962184,1158962287,US 1158962288,1158962295,ZA @@ -25735,9 +25801,12 @@ 1159262492,1159262727,US 1159262728,1159262731,DE 1159262732,1159262735,RU -1159262736,1159262743,US +1159262736,1159262739,US +1159262740,1159262743,DE 1159262744,1159262751,RU -1159262752,1159266935,US +1159262752,1159262967,US +1159262968,1159262975,RU +1159262976,1159266935,US 1159266936,1159266943,PR 1159266944,1159269119,US 1159269120,1159269375,AR @@ -25745,17 +25814,15 @@ 1159274496,1159274751,GB 1159274752,1159276799,US 1159276800,1159277055,A2 -1159277056,1159279359,US -1159279360,1159279615,PR -1159279616,1159281151,US -1159281152,1159281407,HK -1159281408,1159281679,US +1159277056,1159281679,US 1159281680,1159281695,HK 1159281696,1159281727,US 1159281728,1159281743,HK 1159281744,1159281919,US -1159281920,1159282175,HK -1159282176,1159292807,US +1159281920,1159282175,GB +1159282176,1159290655,US +1159290656,1159290687,CA +1159290688,1159292807,US 1159292808,1159292815,AU 1159292816,1159293343,US 1159293344,1159293359,KR @@ -25841,9 +25908,7 @@ 1159521824,1159521855,US 1159521856,1159522031,CA 1159522032,1159522047,US -1159522048,1159522063,CA -1159522064,1159522071,US -1159522072,1159522095,CA +1159522048,1159522095,CA 1159522096,1159522111,US 1159522112,1159522143,CA 1159522144,1159522167,US @@ -26080,7 +26145,9 @@ 1160662488,1160662495,GB 1160662496,1160662743,US 1160662744,1160662751,GB -1160662752,1160665623,US +1160662752,1160663679,US +1160663680,1160663711,HK +1160663712,1160665623,US 1160665624,1160665631,GB 1160665632,1160665807,US 1160665808,1160665815,GB @@ -26322,17 +26389,21 @@ 1161627704,1161627711,DE 1161627712,1161627727,US 1161627728,1161627743,AR -1161627744,1161627751,RO -1161627752,1161627759,US +1161627744,1161627751,US +1161627752,1161627759,PL 1161627760,1161627775,GB -1161627776,1161627807,US +1161627776,1161627783,US +1161627784,1161627791,GB +1161627792,1161627807,US 1161627808,1161627815,SI 1161627816,1161627823,US 1161627824,1161627831,AU 1161627832,1161627839,US -1161627840,1161627863,AR +1161627840,1161627847,AR +1161627848,1161627855,US +1161627856,1161627863,AR 1161627864,1161627871,CA -1161627872,1161627879,HR +1161627872,1161627879,SI 1161627880,1161627895,US 1161627896,1161627903,CA 1161627904,1161628447,US @@ -26340,7 +26411,9 @@ 1161628456,1161628463,GB 1161628464,1161628479,US 1161628480,1161628487,GB -1161628488,1161628607,US +1161628488,1161628519,US +1161628520,1161628527,PL +1161628528,1161628607,US 1161628608,1161628639,AR 1161628640,1161628647,IN 1161628648,1161628663,US @@ -26357,7 +26430,7 @@ 1161629344,1161629375,FI 1161629376,1161629383,CA 1161629384,1161629391,AR -1161629392,1161629399,IE +1161629392,1161629399,GB 1161629400,1161629407,IL 1161629408,1161629415,GB 1161629416,1161629423,SI @@ -26366,10 +26439,10 @@ 1161629440,1161629519,US 1161629520,1161629527,GB 1161629528,1161629535,MY -1161629536,1161629567,GB -1161629568,1161629583,US +1161629536,1161629583,US 1161629584,1161629599,GB -1161629600,1161629615,US +1161629600,1161629607,PL +1161629608,1161629615,US 1161629616,1161629631,GB 1161629632,1161629663,US 1161629664,1161629671,AU @@ -26377,7 +26450,8 @@ 1161629696,1161629951,PL 1161629952,1161630223,US 1161630224,1161630231,NL -1161630232,1161630255,US +1161630232,1161630247,US +1161630248,1161630255,HR 1161630256,1161630263,NL 1161630264,1161630271,AR 1161630272,1161630335,US @@ -26472,7 +26546,16 @@ 1161633024,1161633055,CA 1161633056,1161633215,US 1161633216,1161633231,EE -1161633232,1161633631,US +1161633232,1161633239,US +1161633240,1161633247,AU +1161633248,1161633263,US +1161633264,1161633271,PL +1161633272,1161633543,US +1161633544,1161633551,AR +1161633552,1161633559,US +1161633560,1161633567,IL +1161633568,1161633583,PL +1161633584,1161633631,US 1161633632,1161633639,CA 1161633640,1161634055,US 1161634056,1161634063,IN @@ -26488,29 +26571,26 @@ 1161634224,1161634231,VN 1161634232,1161634239,US 1161634240,1161634247,GB -1161634248,1161634271,US -1161634272,1161634287,CH -1161634288,1161634335,US -1161634336,1161634352,PL -1161634353,1161634495,US +1161634248,1161634335,US +1161634336,1161634351,PL +1161634352,1161634495,US 1161634496,1161634503,GB 1161634504,1161634519,US 1161634520,1161634527,BG -1161634528,1161634943,US +1161634528,1161634815,US +1161634816,1161634831,PL +1161634832,1161634943,US 1161634944,1161634959,PL -1161634960,1161634975,US -1161634976,1161635007,PL +1161634960,1161635007,US 1161635008,1161635071,KW 1161635072,1161635855,US 1161635856,1161635871,BE -1161635872,1161636063,US -1161636064,1161636095,IL +1161635872,1161635887,PL +1161635888,1161636095,US 1161636096,1161636127,GB 1161636128,1161636159,US 1161636160,1161636223,IL -1161636224,1161636415,US -1161636416,1161636447,PL -1161636448,1161636463,US +1161636224,1161636463,US 1161636464,1161636471,EG 1161636472,1161636495,US 1161636496,1161636503,CA @@ -26734,14 +26814,18 @@ 1161791322,1161791330,CA 1161791331,1161791381,US 1161791382,1161791386,CA -1161791387,1161795979,US +1161791387,1161794468,US +1161794469,1161794472,ZA +1161794473,1161794649,US +1161794650,1161794654,ZA +1161794655,1161795979,US 1161795980,1161795983,CA 1161795984,1161818111,US 1161818112,1161822207,CA 1161822208,1161832767,US 1161832768,1161832831,BR 1161832832,1161833759,US -1161833760,1161833791,FR +1161833760,1161833791,TR 1161833792,1161833855,US 1161833856,1161833887,FR 1161833888,1161833919,US @@ -26846,7 +26930,7 @@ 1162383072,1162393759,US 1162393760,1162393767,IN 1162393768,1162394463,US -1162394464,1162394471,IE +1162394464,1162394471,GB 1162394472,1162401519,US 1162401520,1162401527,IN 1162401528,1162408455,US @@ -26998,7 +27082,9 @@ 1163398144,1163398239,A2 1163398240,1163398303,BD 1163398304,1163398367,A2 -1163398368,1163399039,BD +1163398368,1163398399,BD +1163398400,1163398655,US +1163398656,1163399039,BD 1163399040,1163399103,A2 1163399104,1163399295,BD 1163399296,1163399679,A2 @@ -27052,17 +27138,15 @@ 1163477728,1163478047,US 1163478048,1163478063,JP 1163478064,1163526143,US -1163526144,1163526463,CA -1163526464,1163526655,US +1163526144,1163526471,CA +1163526472,1163526655,US 1163526656,1163527023,CA 1163527024,1163527039,BV 1163527040,1163527059,CA 1163527060,1163527071,US 1163527072,1163527103,CA 1163527104,1163527135,US -1163527136,1163527679,CA -1163527680,1163527743,US -1163527744,1163527783,CA +1163527136,1163527783,CA 1163527784,1163527791,US 1163527792,1163529215,CA 1163529216,1163530239,US @@ -27080,9 +27164,7 @@ 1163530960,1163530967,US 1163530968,1163533023,CA 1163533024,1163533055,US -1163533056,1163533511,CA -1163533512,1163533519,US -1163533520,1163533551,CA +1163533056,1163533551,CA 1163533552,1163533567,PA 1163533568,1163533695,CA 1163533696,1163533727,US @@ -27176,9 +27258,7 @@ 1163547536,1163547539,US 1163547540,1163547567,CA 1163547568,1163547583,VG -1163547584,1163547647,CA -1163547648,1163547903,US -1163547904,1163547951,CA +1163547584,1163547951,CA 1163547952,1163547983,US 1163547984,1163550335,CA 1163550336,1163550351,US @@ -27206,7 +27286,9 @@ 1163552576,1163552607,PA 1163552608,1163552679,CA 1163552680,1163552687,US -1163552688,1163553855,CA +1163552688,1163552695,CA +1163552696,1163552703,US +1163552704,1163553855,CA 1163553856,1163553871,US 1163553872,1163553919,CA 1163553920,1163553935,BV @@ -27248,9 +27330,7 @@ 1163570496,1163571199,US 1163571200,1163571983,CA 1163571984,1163571999,US -1163572000,1163572031,CA -1163572032,1163572063,BE -1163572064,1163572175,CA +1163572000,1163572175,CA 1163572176,1163572183,US 1163572184,1163572687,CA 1163572688,1163572703,US @@ -27310,12 +27390,12 @@ 1163582160,1163582167,FI 1163582168,1163582183,CA 1163582184,1163582191,US -1163582192,1163583487,CA -1163583488,1163585199,US +1163582192,1163583231,CA +1163583232,1163585199,US 1163585200,1163585215,CA 1163585216,1163585855,US -1163585856,1163585887,CA -1163585888,1163585889,US +1163585856,1163585871,CA +1163585872,1163585889,US 1163585890,1163585905,GB 1163585906,1163586740,US 1163586741,1163586743,CA @@ -27331,12 +27411,14 @@ 1163588216,1163588223,US 1163588224,1163588607,CA 1163588608,1163588608,US -1163588609,1163588655,CA -1163588656,1163588671,US -1163588672,1163588695,CA +1163588609,1163588695,CA 1163588696,1163588703,US 1163588704,1163588727,CA -1163588728,1163588863,US +1163588728,1163588799,US +1163588800,1163588815,CA +1163588816,1163588831,US +1163588832,1163588847,CA +1163588848,1163588863,US 1163588864,1163589631,CA 1163589632,1163870575,US 1163870576,1163870583,CN @@ -27348,7 +27430,13 @@ 1167319112,1167319119,ZA 1167319120,1167319255,US 1167319256,1167319263,CA -1167319264,1167321959,US +1167319264,1167319359,US +1167319360,1167319367,CA +1167319368,1167320071,US +1167320072,1167320079,CA +1167320080,1167321447,US +1167321448,1167321455,CA +1167321456,1167321959,US 1167321960,1167321967,GB 1167321968,1167322695,US 1167322696,1167322703,IN @@ -27360,7 +27448,9 @@ 1167324048,1167324055,CA 1167324056,1167324287,US 1167324288,1167324295,GB -1167324296,1167325727,US +1167324296,1167324311,US +1167324312,1167324319,CA +1167324320,1167325727,US 1167325728,1167325735,CA 1167325736,1167325935,US 1167325936,1167325951,CA @@ -27457,9 +27547,7 @@ 1168954076,1168954079,CA 1168954080,1168954623,US 1168954624,1168954687,IN -1168954688,1168954751,US -1168954752,1168954879,CA -1168954880,1168955647,US +1168954688,1168955647,US 1168955648,1168956159,CA 1168956160,1168957439,US 1168957440,1168958047,CA @@ -27474,7 +27562,8 @@ 1168958212,1168958215,CA 1168958216,1168958223,US 1168958224,1168958231,SG -1168958232,1168958423,CA +1168958232,1168958239,US +1168958240,1168958423,CA 1168958424,1168958463,US 1168958464,1168958479,CA 1168958480,1168958495,US @@ -27549,8 +27638,7 @@ 1170457664,1170458063,US 1170458064,1170458079,DE 1170458080,1170461055,US -1170461056,1170461439,CO -1170461440,1170461695,US +1170461056,1170461695,CO 1170461696,1170462719,IL 1170462720,1170465791,US 1170465792,1170466047,CY @@ -27561,7 +27649,14 @@ 1170467840,1170468351,DO 1170468352,1170469055,US 1170469056,1170469071,VG -1170469072,1170472959,US +1170469072,1170470911,US +1170470912,1170471167,ES +1170471168,1170471375,US +1170471376,1170471391,UY +1170471392,1170471903,US +1170471904,1170471919,BE +1170471920,1170472703,US +1170472704,1170472959,VG 1170472960,1170481151,CA 1170481152,1170489343,US 1170489344,1170497535,CA @@ -27578,22 +27673,24 @@ 1170539461,1170539461,PK 1170539462,1170539522,US 1170539523,1170539523,AU -1170539524,1170539589,US +1170539524,1170539586,US +1170539587,1170539587,SC +1170539588,1170539589,US 1170539590,1170539590,SA 1170539591,1170539591,CN 1170539592,1170539592,AU -1170539593,1170539650,US -1170539651,1170539651,TR -1170539652,1170539652,US +1170539593,1170539652,US 1170539653,1170539653,GB 1170539654,1170539712,US 1170539713,1170539713,CN 1170539714,1170539714,US 1170539715,1170539715,PK -1170539716,1170539777,US +1170539716,1170539776,US +1170539777,1170539777,SC 1170539778,1170539778,CN -1170539779,1170539780,US -1170539781,1170539781,KR +1170539779,1170539779,SC +1170539780,1170539780,US +1170539781,1170539781,PR 1170539782,1170539841,US 1170539842,1170539842,BD 1170539843,1170539843,MY @@ -27611,9 +27708,7 @@ 1170540106,1170540106,CN 1170540107,1170540163,US 1170540164,1170540164,RO -1170540165,1170540228,US -1170540229,1170540229,TR -1170540230,1170540230,US +1170540165,1170540230,US 1170540231,1170540231,KR 1170540232,1170540232,CN 1170540233,1170540288,US @@ -27622,8 +27717,7 @@ 1170540292,1170540292,TR 1170540293,1170540294,US 1170540295,1170540295,CN -1170540296,1170540296,TR -1170540297,1170540353,US +1170540296,1170540353,US 1170540354,1170540354,CN 1170540355,1170540359,US 1170540360,1170540360,CN @@ -27638,17 +27732,21 @@ 1170540429,1170540429,TR 1170540430,1170540480,US 1170540481,1170540481,TR -1170540482,1170540485,US -1170540486,1170540487,TR +1170540482,1170540486,US +1170540487,1170540487,TR 1170540488,1170540491,US 1170540492,1170540494,TR -1170540495,1170540608,US +1170540495,1170540496,US +1170540497,1170540497,CZ +1170540498,1170540608,US 1170540609,1170540609,CN 1170540610,1170540616,US 1170540617,1170540617,TR 1170540618,1170542863,US 1170542864,1170542871,CN -1170542872,1170544127,US +1170542872,1170543747,US +1170543748,1170543751,PR +1170543752,1170544127,US 1170544128,1170544191,CN 1170544192,1170544195,US 1170544196,1170544199,BD @@ -27664,19 +27762,20 @@ 1170544396,1170544431,US 1170544432,1170544439,CN 1170544440,1170544443,AU -1170544444,1170544511,US -1170544512,1170544543,TR -1170544544,1170544807,US +1170544444,1170544807,US 1170544808,1170544815,CN 1170544816,1170544831,US 1170544832,1170544959,CN 1170544960,1170544983,US 1170544984,1170544987,CN -1170544988,1170545055,US +1170544988,1170544991,US +1170544992,1170545023,SC +1170545024,1170545055,US 1170545056,1170545087,CN 1170545088,1170545407,US 1170545408,1170545439,TR -1170545440,1170545595,US +1170545440,1170545471,SC +1170545472,1170545595,US 1170545596,1170545599,CN 1170545600,1170552607,US 1170552608,1170552611,CN @@ -27702,16 +27801,15 @@ 1170553628,1170553631,TR 1170553632,1170553635,US 1170553636,1170553643,SA -1170553644,1170553647,TR -1170553648,1170553651,US +1170553644,1170553651,US 1170553652,1170553655,TR 1170553656,1170553663,US 1170553664,1170553667,SA -1170553668,1170553683,US +1170553668,1170553675,US +1170553676,1170553679,SC +1170553680,1170553683,US 1170553684,1170553687,CN -1170553688,1170553707,US -1170553708,1170553711,TR -1170553712,1170553855,US +1170553688,1170553855,US 1170553856,1170553983,MY 1170553984,1170554047,CN 1170554048,1170554367,US @@ -27745,7 +27843,9 @@ 1176512152,1176512159,GB 1176512160,1176512703,US 1176512704,1176512711,ZA -1176512712,1176513879,US +1176512712,1176513479,US +1176513480,1176513487,CA +1176513488,1176513879,US 1176513880,1176513887,GB 1176513888,1176514271,US 1176514272,1176514303,IN @@ -27789,10 +27889,9 @@ 1176621888,1176622047,CA 1176622048,1176622079,US 1176622080,1176622335,GB -1176622336,1176622367,US -1176622368,1176622431,CA -1176622432,1176622527,US -1176622528,1176622559,CA +1176622336,1176622431,CA +1176622432,1176622455,US +1176622456,1176622559,CA 1176622560,1176622591,US 1176622592,1176623359,CA 1176623360,1176623487,US @@ -28115,7 +28214,9 @@ 1177165312,1177165823,CA 1177165824,1177167743,US 1177167744,1177167751,LB -1177167752,1177168223,US +1177167752,1177167839,US +1177167840,1177167847,IL +1177167848,1177168223,US 1177168224,1177168231,IE 1177168232,1177175199,US 1177175200,1177175231,CZ @@ -28408,7 +28509,9 @@ 1208205984,1208205991,GB 1208205992,1208206439,US 1208206440,1208206463,CA -1208206464,1208207183,US +1208206464,1208207095,US +1208207096,1208207097,IN +1208207098,1208207183,US 1208207184,1208207191,AU 1208207192,1208207303,US 1208207304,1208207311,ZA @@ -28542,7 +28645,8 @@ 1208338176,1208516607,US 1208516608,1208516623,MX 1208516624,1208516639,US -1208516640,1208516735,TR +1208516640,1208516671,TR +1208516672,1208516735,US 1208516736,1208516799,ID 1208516800,1208516855,US 1208516856,1208516859,CN @@ -28584,8 +28688,9 @@ 1208518400,1208518655,ID 1208518656,1208519167,US 1208519168,1208519423,CN -1208519424,1208519551,TR -1208519552,1208521983,US +1208519424,1208519679,US +1208519680,1208519935,GB +1208519936,1208521983,US 1208521984,1208522239,CN 1208522240,1208522271,US 1208522272,1208522303,TR @@ -28599,8 +28704,7 @@ 1208523992,1208523995,TR 1208523996,1208523999,US 1208524000,1208524031,TR -1208524032,1208524047,US -1208524048,1208524055,TR +1208524032,1208524055,US 1208524056,1208524059,CN 1208524060,1208524063,US 1208524064,1208524079,CN @@ -28625,21 +28729,23 @@ 1208526080,1208526335,US 1208526336,1208526591,CN 1208526592,1208526607,TR -1208526608,1208526623,US -1208526624,1208526655,TR -1208526656,1208526815,US +1208526608,1208526815,US 1208526816,1208526847,CN 1208526848,1208527871,US 1208527872,1208527887,VN 1208527888,1208527903,US -1208527904,1208528127,VN +1208527904,1208528015,VN +1208528016,1208528031,SC +1208528032,1208528127,VN 1208528128,1208531007,US 1208531008,1208531071,CN 1208531072,1208531455,US 1208531456,1208531583,CN 1208531584,1208531711,US 1208531712,1208531967,PK -1208531968,1208532287,US +1208531968,1208531995,US +1208531996,1208531999,GB +1208532000,1208532287,US 1208532288,1208532351,PK 1208532352,1208586364,US 1208586365,1208586372,MA @@ -28651,7 +28757,7 @@ 1208586527,1208586536,TR 1208586537,1208586573,US 1208586574,1208586581,MX -1208586582,1208586589,US +1208586582,1208586589,LK 1208586590,1208586597,NZ 1208586598,1208586662,US 1208586663,1208586670,GB @@ -28675,7 +28781,9 @@ 1208587026,1208587033,NZ 1208587034,1208587045,US 1208587046,1208587053,IN -1208587054,1208587169,US +1208587054,1208587087,US +1208587088,1208587095,LK +1208587096,1208587169,US 1208587170,1208587177,MX 1208587178,1208587187,US 1208587188,1208587195,EG @@ -28751,15 +28859,21 @@ 1208588973,1208588985,GB 1208588986,1208588989,US 1208588990,1208589000,GB -1208589001,1208589065,US +1208589001,1208589043,US +1208589044,1208589051,BH +1208589052,1208589065,US 1208589066,1208589081,CA 1208589082,1208589156,US 1208589157,1208589165,GB 1208589166,1208589174,US 1208589175,1208589186,CA -1208589187,1208589321,US +1208589187,1208589299,US +1208589300,1208589307,LK +1208589308,1208589321,US 1208589322,1208589329,CA -1208589330,1208589379,US +1208589330,1208589341,US +1208589342,1208589349,ID +1208589350,1208589379,US 1208589380,1208589387,EG 1208589388,1208589577,US 1208589578,1208589585,GB @@ -28767,11 +28881,19 @@ 1208589640,1208589651,TR 1208589652,1208589857,US 1208589858,1208589865,MA -1208589866,1208589970,US +1208589866,1208589901,US +1208589902,1208589913,EG +1208589914,1208589915,US +1208589916,1208589917,EG +1208589918,1208589970,US 1208589971,1208590002,GB 1208590003,1208590004,US 1208590005,1208590014,GB -1208590015,1208590061,US +1208590015,1208590031,US +1208590032,1208590033,EG +1208590034,1208590041,US +1208590042,1208590055,EG +1208590056,1208590061,US 1208590062,1208590071,CN 1208590072,1208590091,US 1208590092,1208590108,GB @@ -28956,10 +29078,11 @@ 1209271084,1209271087,BR 1209271088,1209271127,US 1209271128,1209271131,SA -1209271132,1209271187,US -1209271188,1209271191,TR +1209271132,1209271191,US 1209271192,1209271195,RO -1209271196,1209271215,US +1209271196,1209271207,US +1209271208,1209271211,SC +1209271212,1209271215,US 1209271216,1209271219,IN 1209271220,1209271367,US 1209271368,1209271371,TR @@ -28980,8 +29103,7 @@ 1209271544,1209271551,CN 1209271552,1209271567,US 1209271568,1209271571,PL -1209271572,1209271575,TR -1209271576,1209271579,US +1209271572,1209271579,US 1209271580,1209271583,BD 1209271584,1209271607,US 1209271608,1209271611,KH @@ -29011,7 +29133,9 @@ 1209271848,1209271855,IN 1209271856,1209271867,US 1209271868,1209271871,BR -1209271872,1209271951,US +1209271872,1209271923,US +1209271924,1209271927,CA +1209271928,1209271951,US 1209271952,1209271955,KH 1209271956,1209271963,US 1209271964,1209271967,TR @@ -29019,20 +29143,15 @@ 1209271972,1209271975,TR 1209271976,1209271979,CA 1209271980,1209271983,ZA -1209271984,1209271999,US +1209271984,1209271995,US +1209271996,1209271999,SC 1209272000,1209272007,TR 1209272008,1209272011,PL -1209272012,1209272043,US -1209272044,1209272047,TR -1209272048,1209272079,US -1209272080,1209272095,TR -1209272096,1209272127,US +1209272012,1209272127,US 1209272128,1209272159,CN 1209272160,1209272175,US 1209272176,1209272191,BR -1209272192,1209272223,TR -1209272224,1209272239,US -1209272240,1209272255,TR +1209272192,1209272255,US 1209272256,1209272287,CN 1209272288,1209272383,US 1209272384,1209272399,CN @@ -29050,11 +29169,9 @@ 1209272624,1209272655,US 1209272656,1209272671,TR 1209272672,1209272719,US -1209272720,1209272767,CN -1209272768,1209272783,TR -1209272784,1209272847,US -1209272848,1209272863,TR -1209272864,1209272895,US +1209272720,1209272735,PR +1209272736,1209272767,CN +1209272768,1209272895,US 1209272896,1209272959,CN 1209272960,1209273023,BR 1209273024,1209273055,US @@ -29068,15 +29185,18 @@ 1209273280,1209273311,BR 1209273312,1209273359,US 1209273360,1209273407,TR -1209273408,1209273555,US +1209273408,1209273471,CZ +1209273472,1209273555,US 1209273556,1209273559,CA 1209273560,1209273647,US 1209273648,1209273655,CN 1209273656,1209273663,AU 1209273664,1209273671,BD -1209273672,1209273999,US -1209274000,1209274015,TR -1209274016,1209274023,US +1209273672,1209273675,US +1209273676,1209273679,GB +1209273680,1209273991,US +1209273992,1209273999,SC +1209274000,1209274023,US 1209274024,1209274031,RO 1209274032,1209274039,TR 1209274040,1209274047,US @@ -29084,28 +29204,34 @@ 1209274112,1209274115,US 1209274116,1209274119,CZ 1209274120,1209274135,US -1209274136,1209274151,TR -1209274152,1209274367,US -1209274368,1209274495,TR +1209274136,1209274143,TR +1209274144,1209274175,US +1209274176,1209274239,SC +1209274240,1209274495,US 1209274496,1209274527,CN 1209274528,1209274543,US 1209274544,1209274559,TR -1209274560,1209274815,US +1209274560,1209274607,US +1209274608,1209274623,SC +1209274624,1209274815,US 1209274816,1209274879,CA -1209274880,1209274911,CZ +1209274880,1209274911,CN 1209274912,1209274927,US 1209274928,1209274943,TR 1209274944,1209274959,US 1209274960,1209274967,PH 1209274968,1209275071,US 1209275072,1209275135,GB -1209275136,1209275679,US +1209275136,1209275647,US +1209275648,1209275679,SC 1209275680,1209275695,TR 1209275696,1209275791,US 1209275792,1209275799,TR 1209275800,1209275823,US 1209275824,1209275827,CN -1209275828,1209275906,US +1209275828,1209275863,US +1209275864,1209275871,SC +1209275872,1209275906,US 1209275907,1209275908,KH 1209275909,1209275913,US 1209275914,1209275914,KH @@ -29136,7 +29262,9 @@ 1209276808,1209276903,US 1209276904,1209276911,CN 1209276912,1209276927,TR -1209276928,1209277103,US +1209276928,1209277087,US +1209277088,1209277095,SC +1209277096,1209277103,US 1209277104,1209277119,TR 1209277120,1209277135,RO 1209277136,1209277143,US @@ -29148,7 +29276,10 @@ 1209277158,1209277158,IN 1209277159,1209277159,US 1209277160,1209277160,CN -1209277161,1209277166,US +1209277161,1209277161,SC +1209277162,1209277163,US +1209277164,1209277165,SC +1209277166,1209277166,GB 1209277167,1209277167,CN 1209277168,1209277168,AU 1209277169,1209277171,US @@ -29204,8 +29335,7 @@ 1209279232,1209279295,BR 1209279296,1209279615,US 1209279616,1209279743,GB -1209279744,1209279855,US -1209279856,1209279871,TR +1209279744,1209279871,US 1209279872,1209279935,MY 1209279936,1209279951,GB 1209279952,1209279967,US @@ -29216,7 +29346,8 @@ 1209280032,1209280047,IN 1209280048,1209280191,US 1209280192,1209280255,ID -1209280256,1209280419,US +1209280256,1209280319,SC +1209280320,1209280419,US 1209280420,1209280423,CN 1209280424,1209280439,US 1209280440,1209280447,CN @@ -29226,27 +29357,25 @@ 1209280512,1209280515,US 1209280516,1209280519,TR 1209280520,1209280527,AU -1209280528,1209280623,US -1209280624,1209280639,TR -1209280640,1209280895,US +1209280528,1209280575,US +1209280576,1209280607,SC +1209280608,1209280895,US 1209280896,1209280959,BR -1209280960,1209281007,US -1209281008,1209281023,TR -1209281024,1209281151,US +1209280960,1209281151,US 1209281152,1209281231,CN 1209281232,1209281247,US 1209281248,1209281279,CA 1209281280,1209281535,KH 1209281536,1209281791,IN -1209281792,1209281871,US -1209281872,1209281887,TR -1209281888,1209281927,US +1209281792,1209281863,US +1209281864,1209281871,SC +1209281872,1209281927,US 1209281928,1209281935,IN -1209281936,1209281983,US -1209281984,1209282047,TR -1209282048,1209282063,US +1209281936,1209282063,US 1209282064,1209282067,SA -1209282068,1209282159,US +1209282068,1209282111,US +1209282112,1209282143,SC +1209282144,1209282159,US 1209282160,1209282175,CN 1209282176,1209282559,US 1209282560,1209282623,CN @@ -29264,16 +29393,16 @@ 1209283752,1209283759,BD 1209283760,1209283775,US 1209283776,1209283807,ZA -1209283808,1209283839,CA -1209283840,1209283871,US -1209283872,1209283875,TR -1209283876,1209283887,US +1209283808,1209283839,MY +1209283840,1209283887,US 1209283888,1209283903,BR 1209283904,1209283915,US 1209283916,1209283919,KR -1209283920,1209284159,US +1209283920,1209284095,US +1209284096,1209284127,CA +1209284128,1209284159,US 1209284160,1209284223,TR -1209284224,1209284351,IE +1209284224,1209284351,CN 1209284352,1209284391,US 1209284392,1209284399,RO 1209284400,1209284415,TR @@ -29282,18 +29411,15 @@ 1209284448,1209284607,US 1209284608,1209284671,TR 1209284672,1209284735,CN -1209284736,1209284767,US +1209284736,1209284759,US +1209284760,1209284767,SC 1209284768,1209284799,MY 1209284800,1209284831,TR -1209284832,1209284839,US -1209284840,1209284843,TR -1209284844,1209284855,US +1209284832,1209284855,US 1209284856,1209284863,CN 1209284864,1209284993,US 1209284994,1209284994,TR -1209284995,1209284995,US -1209284996,1209284996,TR -1209284997,1209284997,US +1209284995,1209284997,US 1209284998,1209284998,CN 1209284999,1209284999,US 1209285000,1209285000,CA @@ -29380,7 +29506,11 @@ 1209877935,1209877938,PK 1209877939,1209879554,US 1209879555,1209879558,PE -1209879559,1209884671,US +1209879559,1209880125,US +1209880126,1209880126,CA +1209880127,1209882516,US +1209882517,1209882517,CA +1209882518,1209884671,US 1209884672,1209884679,IT 1209884680,1209884687,ES 1209884688,1209884823,US @@ -29845,7 +29975,9 @@ 1210101280,1210101311,US 1210101312,1210101319,IE 1210101320,1210101327,IL -1210101328,1210101559,US +1210101328,1210101519,US +1210101520,1210101527,IL +1210101528,1210101559,US 1210101560,1210101567,AU 1210101568,1210101727,US 1210101728,1210101743,GB @@ -30122,9 +30254,7 @@ 1211039088,1211039103,RU 1211039104,1211039503,US 1211039504,1211039519,A2 -1211039520,1211039551,US -1211039552,1211039567,BM -1211039568,1211039647,US +1211039520,1211039647,US 1211039648,1211039663,AR 1211039664,1211039679,US 1211039680,1211039695,BR @@ -30246,13 +30376,17 @@ 1211394064,1211394079,ES 1211394080,1211394751,US 1211394752,1211395071,IT -1211395072,1211407293,US +1211395072,1211404421,US +1211404422,1211404422,CA +1211404423,1211407293,US 1211407294,1211407333,MX 1211407334,1211413247,US 1211413248,1211413503,CA 1211413504,1211419489,US 1211419490,1211419497,CA -1211419498,1211432959,US +1211419498,1211421739,US +1211421740,1211421740,CA +1211421741,1211432959,US 1211432960,1211473919,CA 1211473920,1211596799,US 1211596800,1211613183,CA @@ -30470,13 +30604,25 @@ 1247483096,1247483111,US 1247483112,1247483119,CN 1247483120,1247483647,US -1247483648,1247484671,CN +1247483648,1247483951,CN +1247483952,1247483967,US +1247483968,1247484031,CN +1247484032,1247484047,US +1247484048,1247484287,CN +1247484288,1247484319,US +1247484320,1247484543,CN +1247484544,1247484551,US +1247484552,1247484559,CN +1247484560,1247484567,US +1247484568,1247484671,CN 1247484672,1247484927,US 1247484928,1247485191,CN 1247485192,1247485231,US 1247485232,1247485263,CN 1247485264,1247485439,US -1247485440,1247485543,CN +1247485440,1247485471,CN +1247485472,1247485479,US +1247485480,1247485543,CN 1247485544,1247485615,US 1247485616,1247485623,CN 1247485624,1247485631,US @@ -30503,7 +30649,9 @@ 1248897264,1248897271,FR 1248897272,1248899071,US 1248899072,1248900095,CA -1248900096,1248903695,US +1248900096,1248902143,US +1248902144,1248903167,CA +1248903168,1248903695,US 1248903696,1248903711,ZA 1248903712,1248903775,US 1248903776,1248903791,FR @@ -30596,9 +30744,7 @@ 1249105120,1249105127,AR 1249105128,1249105135,US 1249105136,1249105143,CH -1249105144,1249105183,US -1249105184,1249105191,ZA -1249105192,1249105279,US +1249105144,1249105279,US 1249105280,1249105295,CA 1249105296,1249105367,US 1249105368,1249105375,ES @@ -30656,7 +30802,9 @@ 1249229217,1249229217,CA 1249229218,1249229289,US 1249229290,1249229291,CA -1249229292,1249236991,US +1249229292,1249229591,US +1249229592,1249229599,ES +1249229600,1249236991,US 1249236992,1249239039,KY 1249239040,1249245183,US 1249245184,1249247231,CA @@ -30724,7 +30872,9 @@ 1249440280,1249440287,FR 1249440288,1249452031,US 1249452032,1249453055,CA -1249453056,1249474559,US +1249453056,1249460671,US +1249460672,1249460687,CA +1249460688,1249474559,US 1249474560,1249475583,CA 1249475584,1249484799,US 1249484800,1249486847,CA @@ -30749,7 +30899,9 @@ 1249572864,1249577087,US 1249577088,1249577232,CA 1249577233,1249577343,US -1249577344,1249577480,CA +1249577344,1249577403,CA +1249577404,1249577468,US +1249577469,1249577480,CA 1249577481,1249577545,US 1249577546,1249577730,CA 1249577731,1249577794,US @@ -30837,7 +30989,9 @@ 1254704904,1254704911,PH 1254704912,1254713359,US 1254713360,1254713407,CA -1254713408,1254924687,US +1254713408,1254752191,US +1254752192,1254752207,CH +1254752208,1254924687,US 1254924688,1254924703,RO 1254924704,1254948927,US 1254948928,1254948935,SG @@ -31125,9 +31279,7 @@ 1254966928,1254966943,FR 1254966944,1254966975,US 1254966976,1254966991,IL -1254966992,1254967007,US -1254967008,1254967023,AE -1254967024,1254967079,US +1254966992,1254967079,US 1254967080,1254967087,PH 1254967088,1254967127,US 1254967128,1254967143,BM @@ -31217,7 +31369,8 @@ 1254970336,1254970343,CH 1254970344,1254970527,US 1254970528,1254970543,GB -1254970544,1254970607,US +1254970544,1254970591,US +1254970592,1254970607,PH 1254970608,1254970623,GH 1254970624,1254970631,MX 1254970632,1254970903,US @@ -31383,9 +31536,7 @@ 1255057888,1255057919,NL 1255057920,1255058671,US 1255058672,1255058687,GB -1255058688,1255059151,US -1255059152,1255059167,GB -1255059168,1255059327,US +1255058688,1255059327,US 1255059328,1255059343,NL 1255059344,1255059359,US 1255059360,1255059391,CA @@ -31411,7 +31562,9 @@ 1255063552,1255071743,PR 1255071744,1255210495,US 1255210496,1255211007,DE -1255211008,1255265279,US +1255211008,1255264511,US +1255264512,1255264767,SG +1255264768,1255265279,US 1255265280,1255266303,SG 1255266304,1255274047,US 1255274048,1255274079,GB @@ -31419,11 +31572,9 @@ 1255274496,1255274751,SG 1255274752,1255276543,US 1255276544,1255342079,CA -1255342080,1255369055,US -1255369056,1255369087,DE -1255369088,1255373759,US -1255373760,1255373791,DE -1255373792,1255489535,US +1255342080,1255367167,US +1255367168,1255367423,DE +1255367424,1255489535,US 1255489536,1255505919,PR 1255505920,1255514111,US 1255514112,1255522303,CA @@ -31443,9 +31594,7 @@ 1255770368,1255770623,CA 1255770624,1255776431,US 1255776432,1255776439,LB -1255776440,1255780351,US -1255780352,1255782399,CA -1255782400,1255784959,US +1255776440,1255784959,US 1255784960,1255784967,BE 1255784968,1255788511,US 1255788512,1255788543,BE @@ -31502,16 +31651,25 @@ 1264737280,1264738175,US 1264738176,1264738207,IL 1264738208,1264762879,US -1264762880,1264766975,CA -1264766976,1264980735,US +1264762880,1264763391,CA +1264763392,1264763647,IE +1264763648,1264764927,CA +1264764928,1264764959,US +1264764960,1264766975,CA +1264766976,1264978623,US +1264978624,1264978639,CA +1264978640,1264980735,US 1264980736,1264980743,CA -1264980744,1264982895,US +1264980744,1264982847,US +1264982848,1264982855,CA +1264982856,1264982895,US 1264982896,1264982903,AF 1264982904,1264983031,US 1264983032,1264983039,AU 1264983040,1264984703,US 1264984704,1264984711,CA -1264984712,1264984799,US +1264984712,1264984791,US +1264984792,1264984799,CA 1264984800,1264984807,AF 1264984808,1266107759,US 1266107760,1266107775,UM @@ -31888,7 +32046,9 @@ 1279828568,1279828575,CA 1279828576,1279828615,US 1279828616,1279828623,CA -1279828624,1279848447,US +1279828624,1279829711,US +1279829712,1279829759,FR +1279829760,1279848447,US 1279848448,1279852543,PR 1279852544,1279921919,US 1279921920,1279922047,IE @@ -31919,13 +32079,15 @@ 1279953760,1279953791,GB 1279953792,1279953951,CA 1279953952,1279953967,US -1279953968,1279954095,CA +1279953968,1279954015,CA +1279954016,1279954047,US +1279954048,1279954095,CA 1279954096,1279954119,US 1279954120,1279954303,CA 1279954304,1279954431,US 1279954432,1279954527,CA -1279954528,1279954559,US -1279954560,1279954623,CA +1279954528,1279954543,US +1279954544,1279954623,CA 1279954624,1279954655,FI 1279954656,1279954719,CA 1279954720,1279954727,US @@ -31997,11 +32159,15 @@ 1279960528,1279960535,US 1279960536,1279960559,CA 1279960560,1279960567,MX -1279960568,1279962175,US +1279960568,1279961087,US +1279961088,1279961343,IN +1279961344,1279962175,US 1279962176,1279962207,CA 1279962208,1279962223,US 1279962224,1279962239,CA -1279962240,1279962895,US +1279962240,1279962783,US +1279962784,1279962791,CN +1279962792,1279962895,US 1279962896,1279962911,CA 1279962912,1279962927,CN 1279962928,1279962943,US @@ -32347,7 +32513,7 @@ 1296250080,1296250111,IL 1296250112,1296250143,IE 1296250144,1296250175,GB -1296250176,1296250207,BE +1296250176,1296250207,FR 1296250208,1296250239,ES 1296250240,1296250271,BE 1296250272,1296250303,DE @@ -32369,7 +32535,7 @@ 1296251968,1296252015,NL 1296252016,1296252039,US 1296252040,1296252055,DE -1296252056,1296252063,BE +1296252056,1296252063,FR 1296252064,1296252079,IT 1296252080,1296252087,IE 1296252088,1296252095,FR @@ -32386,7 +32552,8 @@ 1296252256,1296252271,GB 1296252272,1296252303,FR 1296252304,1296252319,IL -1296252320,1296252367,FR +1296252320,1296252335,GB +1296252336,1296252367,FR 1296252368,1296252383,DE 1296252384,1296252399,FR 1296252400,1296252415,IE @@ -32394,8 +32561,7 @@ 1296252672,1296252679,GB 1296252680,1296252687,FR 1296252688,1296252695,NL -1296252696,1296252703,FR -1296252704,1296252711,DE +1296252696,1296252711,DE 1296252712,1296252719,FR 1296252720,1296252727,BE 1296252728,1296252735,IL @@ -32408,8 +32574,8 @@ 1296252840,1296252847,DE 1296252848,1296252855,GB 1296252856,1296252871,IE -1296252872,1296252879,BE -1296252880,1296252887,FR +1296252872,1296252879,FR +1296252880,1296252887,DE 1296252888,1296252895,IE 1296252896,1296252911,BE 1296252912,1296252919,GB @@ -32429,7 +32595,7 @@ 1296260608,1296262143,DE 1296262144,1296262399,FR 1296262400,1296262655,US -1296262656,1296262911,CA +1296262656,1296262911,FR 1296262912,1296263935,US 1296263936,1296263943,FR 1296263944,1296263999,US @@ -32494,12 +32660,10 @@ 1296466656,1296466671,BJ 1296466672,1296466687,NO 1296466688,1296466719,BJ -1296466720,1296466751,NO -1296466752,1296466759,ML +1296466720,1296466759,NO 1296466760,1296466767,SL 1296466768,1296466775,BF -1296466776,1296466783,GN -1296466784,1296468479,NO +1296466776,1296468479,NO 1296468480,1296469247,NG 1296469248,1296472383,NO 1296472384,1296472415,BI @@ -32859,7 +33023,19 @@ 1298126848,1298127615,SA 1298127616,1298128127,IR 1298128128,1298128895,SA -1298128896,1298130943,NL +1298128896,1298129465,NL +1298129466,1298129466,IR +1298129467,1298129738,NL +1298129739,1298129739,IT +1298129740,1298129744,NL +1298129745,1298129745,US +1298129746,1298129751,NL +1298129752,1298129755,US +1298129756,1298129788,NL +1298129789,1298129792,IT +1298129793,1298130180,NL +1298130181,1298130426,TR +1298130427,1298130943,NL 1298130944,1298132991,BG 1298132992,1298135039,FI 1298135040,1298137087,NL @@ -32877,7 +33053,9 @@ 1298841600,1298857983,RU 1298857984,1298874367,SE 1298874368,1298907135,GB -1298907136,1298923519,IE +1298907136,1298915199,IE +1298915200,1298915215,CA +1298915216,1298923519,IE 1298923520,1298939903,IT 1298939904,1298956287,RU 1298956288,1298972671,GB @@ -32946,7 +33124,9 @@ 1306238976,1306263551,SE 1306263552,1306271743,KE 1306271744,1306279935,RU -1306279936,1306286079,IT +1306279936,1306285775,IT +1306285776,1306285783,US +1306285784,1306286079,IT 1306286080,1306287103,CH 1306287104,1306287615,IT 1306287616,1306287903,CH @@ -33222,9 +33402,9 @@ 1307983360,1307983423,ZA 1307983424,1307983487,BW 1307983488,1307983551,ZM -1307983552,1307983583,MZ -1307983584,1307983615,ZA -1307983616,1307983871,GB +1307983552,1307983615,MZ +1307983616,1307983743,ZA +1307983744,1307983871,ZM 1307983872,1307987967,LB 1307987968,1307992063,FR 1307992064,1307996159,RU @@ -33545,8 +33725,10 @@ 1311263616,1311263679,FR 1311263680,1311263871,CH 1311263872,1311263999,FR -1311264000,1311264111,CH -1311264112,1311264767,FR +1311264000,1311264119,CH +1311264120,1311264127,FR +1311264128,1311264191,CH +1311264192,1311264767,FR 1311264768,1311266815,RU 1311266816,1311268863,FR 1311268864,1311270911,BE @@ -33653,7 +33835,9 @@ 1311676024,1311676031,IT 1311676032,1311707655,DE 1311707656,1311707663,NL -1311707664,1311756823,DE +1311707664,1311755407,DE +1311755408,1311755415,IT +1311755416,1311756823,DE 1311756824,1311756831,ES 1311756832,1311757439,DE 1311757440,1311757447,ES @@ -33858,7 +34042,9 @@ 1315926016,1315930111,CZ 1315930112,1315930623,DE 1315930624,1315930879,LB -1315930880,1315934207,DE +1315930880,1315931135,DE +1315931136,1315931391,LB +1315931392,1315934207,DE 1315934208,1315938303,RU 1315938304,1315942399,DK 1315942400,1315946495,UA @@ -33874,9 +34060,7 @@ 1317113104,1317113119,IE 1317113120,1317113855,GB 1317113856,1317114111,US -1317114112,1317115135,GB -1317115136,1317115391,IE -1317115392,1317118207,GB +1317114112,1317118207,GB 1317118208,1317118463,IN 1317118464,1317126399,GB 1317126400,1317126655,US @@ -33951,7 +34135,7 @@ 1317650136,1317650143,GB 1317650144,1317650431,IE 1317650432,1317666815,PT -1317666816,1317666823,IQ +1317666816,1317666823,A2 1317666824,1317666831,CD 1317666832,1317666839,A2 1317666840,1317666855,GH @@ -33978,7 +34162,9 @@ 1317667160,1317667167,AO 1317667168,1317667175,NG 1317667176,1317667191,A2 -1317667192,1317667231,NG +1317667192,1317667207,NG +1317667208,1317667215,A2 +1317667216,1317667231,NG 1317667232,1317667239,A2 1317667240,1317667247,NG 1317667248,1317667263,A2 @@ -34002,9 +34188,7 @@ 1317667496,1317667503,NG 1317667504,1317667551,A2 1317667552,1317667567,NG -1317667568,1317667711,A2 -1317667712,1317667719,NG -1317667720,1317667735,A2 +1317667568,1317667735,A2 1317667736,1317667743,NG 1317667744,1317667751,A2 1317667752,1317667759,NG @@ -34015,7 +34199,8 @@ 1317667792,1317667799,NG 1317667800,1317667807,A2 1317667808,1317667815,NG -1317667816,1317668095,A2 +1317667816,1317667824,UG +1317667825,1317668095,A2 1317668096,1317668103,GH 1317668104,1317668143,A2 1317668144,1317668151,AO @@ -34193,7 +34378,9 @@ 1317671680,1317671687,LR 1317671688,1317671719,A2 1317671720,1317671727,NG -1317671728,1317671783,A2 +1317671728,1317671759,A2 +1317671760,1317671767,AO +1317671768,1317671783,A2 1317671784,1317671807,NG 1317671808,1317671823,CI 1317671824,1317671831,NG @@ -34214,9 +34401,7 @@ 1317672472,1317672479,A2 1317672480,1317672487,ZM 1317672488,1317672503,NG -1317672504,1317672543,A2 -1317672544,1317672551,CD -1317672552,1317672583,A2 +1317672504,1317672583,A2 1317672584,1317672591,CD 1317672592,1317672615,A2 1317672616,1317672623,NG @@ -34240,8 +34425,7 @@ 1317672920,1317672927,GH 1317672928,1317672935,A2 1317672936,1317672943,NG -1317672944,1317672951,UG -1317672952,1317672959,A2 +1317672944,1317672959,A2 1317672960,1317673231,NG 1317673232,1317673239,A2 1317673240,1317673247,NG @@ -34326,7 +34510,7 @@ 1317674544,1317674567,NG 1317674568,1317674607,A2 1317674608,1317674615,NG -1317674616,1317674623,IQ +1317674616,1317674623,A2 1317674624,1317674631,NG 1317674632,1317674639,A2 1317674640,1317674647,NG @@ -34413,22 +34597,22 @@ 1317675800,1317675807,GB 1317675808,1317675815,NG 1317675816,1317675823,A2 -1317675824,1317675847,NG +1317675824,1317675839,NG +1317675840,1317675847,A2 1317675848,1317675855,TD 1317675856,1317675863,NG 1317675864,1317675887,A2 1317675888,1317675895,CD 1317675896,1317675903,A2 1317675904,1317675911,UG -1317675912,1317675919,A2 +1317675912,1317675919,NG 1317675920,1317675927,UG 1317675928,1317675935,LR 1317675936,1317675951,A2 1317675952,1317675959,NG 1317675960,1317675967,A2 1317675968,1317675975,NG -1317675976,1317675983,A2 -1317675984,1317675991,ML +1317675976,1317675991,A2 1317675992,1317675999,NG 1317676000,1317676007,A2 1317676008,1317676015,GH @@ -34471,7 +34655,8 @@ 1317676584,1317676591,NG 1317676592,1317676599,AO 1317676600,1317676607,UG -1317676608,1317676639,A2 +1317676608,1317676631,A2 +1317676632,1317676639,NG 1317676640,1317676647,CD 1317676648,1317676655,A2 1317676656,1317676671,NG @@ -34479,8 +34664,7 @@ 1317676688,1317676695,LR 1317676696,1317676711,A2 1317676712,1317676719,NG -1317676720,1317676751,A2 -1317676752,1317676759,ML +1317676720,1317676759,A2 1317676760,1317676767,LR 1317676768,1317676775,A2 1317676776,1317676783,UG @@ -34502,8 +34686,7 @@ 1317676952,1317676983,A2 1317676984,1317676999,NG 1317677000,1317677007,IQ -1317677008,1317677015,CD -1317677016,1317677023,A2 +1317677008,1317677023,A2 1317677024,1317677039,NG 1317677040,1317677047,A2 1317677048,1317677055,NG @@ -34548,7 +34731,8 @@ 1317677496,1317677527,NG 1317677528,1317677535,GQ 1317677536,1317677551,CD -1317677552,1317677567,NG +1317677552,1317677559,A2 +1317677560,1317677567,NG 1317677568,1317677663,A2 1317677664,1317677671,GB 1317677672,1317677823,A2 @@ -34582,7 +34766,9 @@ 1317678224,1317678231,NG 1317678232,1317678239,BF 1317678240,1317678247,CD -1317678248,1317678271,A2 +1317678248,1317678255,A2 +1317678256,1317678263,CD +1317678264,1317678271,A2 1317678272,1317678287,NG 1317678288,1317678295,GR 1317678296,1317678311,A2 @@ -34632,17 +34818,22 @@ 1317679752,1317679767,NG 1317679768,1317679775,A2 1317679776,1317679799,NG -1317679800,1317679815,A2 +1317679800,1317679807,A2 +1317679808,1317679815,AO 1317679816,1317679831,NG 1317679832,1317679839,A2 1317679840,1317679847,NG 1317679848,1317679863,A2 1317679864,1317679871,NG -1317679872,1317681175,A2 +1317679872,1317681159,A2 +1317681160,1317681167,NG +1317681168,1317681175,A2 1317681176,1317681191,NG 1317681192,1317681279,A2 1317681280,1317681287,NG -1317681288,1317683199,A2 +1317681288,1317681927,A2 +1317681928,1317681931,NG +1317681932,1317683199,A2 1317683200,1317683839,DE 1317683840,1317683855,CH 1317683856,1317683863,DE @@ -34665,7 +34856,7 @@ 1317831840,1317831871,CA 1317831872,1317832191,NL 1317832192,1317832447,GB -1317832448,1317832511,SC +1317832448,1317832511,CY 1317832512,1317832575,NL 1317832576,1317832703,GI 1317832704,1317832959,NL @@ -34681,7 +34872,7 @@ 1317835712,1317835775,GI 1317835776,1317836031,CY 1317836032,1317836863,NL -1317836864,1317836927,SC +1317836864,1317836927,CY 1317836928,1317836991,NL 1317836992,1317837007,GB 1317837008,1317837023,RU @@ -34699,16 +34890,16 @@ 1317841408,1317841439,SC 1317841440,1317841471,MT 1317841472,1317841535,CY -1317841536,1317841599,NL +1317841536,1317841567,HK +1317841568,1317841599,NL 1317841600,1317841663,GI 1317841664,1317841727,HK -1317841728,1317841791,SC -1317841792,1317841855,CY +1317841728,1317841855,CY 1317841856,1317841887,IL 1317841888,1317842943,NL 1317842944,1317843071,CY 1317843072,1317843135,HK -1317843136,1317843199,SC +1317843136,1317843199,CY 1317843200,1317843391,US 1317843392,1317843423,NL 1317843424,1317843455,PR @@ -34731,12 +34922,12 @@ 1317977408,1317977415,MT 1317977416,1317978111,AT 1317978112,1317994495,RU -1317994496,1317995519,NL -1317995520,1317996095,DE +1317994496,1317995007,NL +1317995008,1317996095,DE 1317996096,1317996287,NL 1317996288,1317998207,DE -1317998208,1317998591,NL -1317998592,1318000383,DE +1317998208,1317998335,NL +1317998336,1318000383,DE 1318000384,1318000447,NL 1318000448,1318002175,DE 1318002176,1318002431,NL @@ -34822,8 +35013,8 @@ 1318871040,1318879231,DK 1318879232,1318887423,CZ 1318887424,1318895615,PL -1318895616,1318899711,SE -1318899712,1318903807,DK +1318895616,1318897663,SE +1318897664,1318903807,DK 1318903808,1318911999,RU 1318912000,1318920191,MK 1318920192,1318928383,IR @@ -35014,6 +35205,7 @@ 1332477952,1332609023,ES 1332609024,1332613119,PL 1332613120,1332617215,UA +1332617216,1332621311,CZ 1332621312,1332625407,UA 1332625408,1332629503,RU 1332629504,1332633599,DE @@ -35146,7 +35338,9 @@ 1334651904,1334652159,DE 1334652160,1334652543,GB 1334652544,1334652559,NL -1334652560,1334652927,GB +1334652560,1334652863,GB +1334652864,1334652895,FR +1334652896,1334652927,GB 1334652928,1334661119,RU 1334661120,1334665215,CH 1334665216,1334669311,NO @@ -35182,7 +35376,13 @@ 1334729984,1334730027,KZ 1334730028,1334730031,RU 1334730032,1334730043,KZ -1334730044,1334730239,RU +1334730044,1334730047,RU +1334730048,1334730055,KZ +1334730056,1334730063,RU +1334730064,1334730107,KZ +1334730108,1334730111,RU +1334730112,1334730127,KZ +1334730128,1334730239,RU 1334730240,1334730431,KZ 1334730432,1334730439,RU 1334730440,1334730443,KZ @@ -35476,17 +35676,23 @@ 1346538016,1346538031,CH 1346538032,1346538143,BE 1346538144,1346538175,HR -1346538176,1346539519,BE +1346538176,1346538239,BE +1346538240,1346538303,AT +1346538304,1346539519,BE 1346539520,1346543615,RU 1346543616,1346547711,FI 1346547712,1346551807,IR 1346551808,1346555903,DE 1346555904,1346559999,IT -1346560000,1346563071,LI +1346560000,1346561535,LI +1346561536,1346561599,CH +1346561600,1346563071,LI 1346563072,1346563327,CH 1346563328,1346564095,LI 1346564096,1346568191,EE -1346568192,1346571775,SE +1346568192,1346571199,SE +1346571200,1346571207,SK +1346571208,1346571775,SE 1346571776,1346572287,A1 1346572288,1346576383,DE 1346576384,1346580479,DK @@ -35631,21 +35837,7 @@ 1347010560,1347014655,RU 1347014656,1347018751,GG 1347018752,1347022847,IT -1347022848,1347024911,AT -1347024912,1347024927,GB -1347024928,1347024959,AT -1347024960,1347025071,GB -1347025072,1347025079,FR -1347025080,1347025087,GB -1347025088,1347025103,AT -1347025104,1347025111,FR -1347025112,1347025119,GB -1347025120,1347025151,AT -1347025152,1347025215,US -1347025216,1347025279,GB -1347025280,1347025343,ES -1347025344,1347025407,DE -1347025408,1347026943,AT +1347022848,1347026943,AT 1347026944,1347035135,GB 1347035136,1347039231,CZ 1347039232,1347043327,RO @@ -35849,9 +36041,7 @@ 1347309840,1347309855,CH 1347309856,1347313663,DE 1347313664,1347321855,RU -1347321856,1347323775,KW -1347323776,1347323903,IR -1347323904,1347325951,KW +1347321856,1347325951,KW 1347325952,1347327231,CZ 1347327232,1347327487,SK 1347327488,1347327743,CZ @@ -35994,17 +36184,7 @@ 1347694592,1347706879,GB 1347706880,1347710975,IT 1347710976,1347715071,RU -1347715072,1347715519,ES -1347715520,1347715527,SA -1347715528,1347716151,ES -1347716152,1347716159,LB -1347716160,1347716207,ES -1347716208,1347716223,CY -1347716224,1347719711,ES -1347719712,1347719719,SO -1347719720,1347722495,ES -1347722496,1347722751,LB -1347722752,1347723263,ES +1347715072,1347723263,ES 1347723264,1347727359,GB 1347727360,1347731455,UA 1347731456,1347739647,DE @@ -36062,11 +36242,14 @@ 1347837952,1347846143,RO 1347846144,1347850239,NO 1347850240,1347854335,IT -1347854336,1347854871,DE +1347854336,1347854847,EU +1347854848,1347854871,DE 1347854872,1347854879,EU 1347854880,1347854887,DE 1347854888,1347854911,EU -1347854912,1347855071,DE +1347854912,1347855023,DE +1347855024,1347855039,EU +1347855040,1347855071,DE 1347855072,1347855087,EU 1347855088,1347855103,DE 1347855104,1347855359,CH @@ -36080,13 +36263,17 @@ 1347856064,1347856079,EU 1347856080,1347856087,DE 1347856088,1347856095,EU -1347856096,1347856239,DE +1347856096,1347856127,DE +1347856128,1347856191,EU +1347856192,1347856239,DE 1347856240,1347856255,EU 1347856256,1347856383,DE 1347856384,1347856399,EU -1347856400,1347856431,DE -1347856432,1347856447,EU -1347856448,1347856639,DE +1347856400,1347856423,DE +1347856424,1347856447,EU +1347856448,1347856591,DE +1347856592,1347856607,EU +1347856608,1347856639,DE 1347856640,1347856895,AT 1347856896,1347858495,DE 1347858496,1347858503,EU @@ -36101,8 +36288,8 @@ 1347859344,1347859351,DE 1347859352,1347859359,EU 1347859360,1347859383,DE -1347859384,1347859407,EU -1347859408,1347859423,DE +1347859384,1347859391,EU +1347859392,1347859423,DE 1347859424,1347859455,EU 1347859456,1347860863,DE 1347860864,1347860879,EU @@ -36460,7 +36647,9 @@ 1352058432,1352058495,US 1352058496,1352139671,DE 1352139672,1352139679,IT -1352139680,1352144519,DE +1352139680,1352141311,DE +1352141312,1352141567,NL +1352141568,1352144519,DE 1352144520,1352144527,IT 1352144528,1352144535,US 1352144536,1352147007,DE @@ -36495,7 +36684,9 @@ 1352149856,1352149871,SE 1352149872,1352277535,DE 1352277536,1352277567,IT -1352277568,1352402791,DE +1352277568,1352304639,DE +1352304640,1352304895,CH +1352304896,1352402791,DE 1352402792,1352402799,BE 1352402800,1352404599,DE 1352404600,1352404607,NL @@ -36546,24 +36737,29 @@ 1353265952,1353266959,GB 1353266960,1353266975,IE 1353266976,1353267455,GB -1353267456,1353268223,IE +1353267456,1353267711,IE +1353267712,1353267719,GB +1353267720,1353268223,IE 1353268224,1353268479,GB 1353268480,1353268599,BE 1353268600,1353268607,GB -1353268608,1353269215,BE -1353269216,1353270527,GB +1353268608,1353269007,BE +1353269008,1353269015,GB +1353269016,1353269223,BE +1353269224,1353269231,FR +1353269232,1353269247,BE +1353269248,1353270527,GB 1353270528,1353270783,IE 1353270784,1353271295,GB 1353271296,1353271423,IE 1353271424,1353271815,GB 1353271816,1353271831,ES 1353271832,1353271839,GB -1353271840,1353272031,ES -1353272032,1353272039,FR +1353271840,1353272039,ES 1353272040,1353272047,GB 1353272048,1353272055,ES -1353272056,1353272063,GB -1353272064,1353272199,ES +1353272056,1353272071,GB +1353272072,1353272199,ES 1353272200,1353272207,GB 1353272208,1353272245,ES 1353272246,1353272247,GB @@ -36580,37 +36776,33 @@ 1353274368,1353274759,ES 1353274760,1353274767,GB 1353274768,1353274791,ES -1353274792,1353274799,GB -1353274800,1353274895,ES +1353274792,1353274807,GB +1353274808,1353274895,ES 1353274896,1353274911,GB 1353274912,1353275007,ES 1353275008,1353275015,GB 1353275016,1353275391,ES 1353275392,1353277439,GB 1353277440,1353279487,CH -1353279488,1353279575,IT -1353279576,1353279591,GB -1353279592,1353279615,IT +1353279488,1353279615,IT 1353279616,1353279623,GB 1353279624,1353279743,IT 1353279744,1353279751,GB 1353279752,1353279759,IT 1353279760,1353279763,GB -1353279764,1353280039,IT -1353280040,1353280047,GB -1353280048,1353280119,IT +1353279764,1353280119,IT 1353280120,1353280127,GB 1353280128,1353280143,IT 1353280144,1353280151,GB -1353280152,1353280159,IT -1353280160,1353280167,GB -1353280168,1353280191,IT +1353280152,1353280191,IT 1353280192,1353280199,GB 1353280200,1353280287,IT 1353280288,1353280295,GB 1353280296,1353280463,IT 1353280464,1353280479,GB -1353280480,1353281023,IT +1353280480,1353280567,IT +1353280568,1353280575,GB +1353280576,1353281023,IT 1353281024,1353281535,BE 1353281536,1353282047,GB 1353282048,1353282103,IT @@ -36622,9 +36814,7 @@ 1353282224,1353282559,IT 1353282560,1353283071,GB 1353283072,1353283327,IT -1353283328,1353287327,GB -1353287328,1353287359,IE -1353287360,1353287679,GB +1353283328,1353287679,GB 1353287680,1353288031,IE 1353288032,1353288063,GB 1353288064,1353288151,IE @@ -36659,9 +36849,7 @@ 1353289084,1353289087,GB 1353289088,1353289247,IE 1353289248,1353289255,GB -1353289256,1353289279,IE -1353289280,1353289295,GB -1353289296,1353289359,IE +1353289256,1353289359,IE 1353289360,1353289367,GB 1353289368,1353289391,IE 1353289392,1353289407,GB @@ -36691,8 +36879,8 @@ 1353298832,1353298839,SE 1353298840,1353298847,IE 1353298848,1353298863,SE -1353298864,1353298879,GB -1353298880,1353298881,SE +1353298864,1353298871,GB +1353298872,1353298881,SE 1353298882,1353298887,GB 1353298888,1353299503,SE 1353299504,1353299511,GB @@ -36704,11 +36892,12 @@ 1353299920,1353299927,GB 1353299928,1353299951,SE 1353299952,1353299967,GB -1353299968,1353300079,SE -1353300080,1353300095,PT -1353300096,1353300103,GB +1353299968,1353300095,SE +1353300096,1353300103,CH 1353300104,1353300111,SE -1353300112,1353300175,GB +1353300112,1353300119,FI +1353300120,1353300127,SE +1353300128,1353300175,GB 1353300176,1353300191,SE 1353300192,1353300239,GB 1353300240,1353300247,SE @@ -36716,7 +36905,9 @@ 1353300280,1353300735,SE 1353300736,1353301095,GB 1353301096,1353301103,US -1353301104,1353306111,GB +1353301104,1353304335,GB +1353304336,1353304351,DE +1353304352,1353306111,GB 1353306112,1353306623,ES 1353306624,1353306687,GB 1353306688,1353306735,BE @@ -36733,12 +36924,14 @@ 1353310488,1353310599,ES 1353310600,1353310607,DE 1353310608,1353310719,ES -1353310720,1353311135,IT +1353310720,1353311071,IT +1353311072,1353311079,GB +1353311080,1353311135,IT 1353311136,1353311143,GB 1353311144,1353311175,IT 1353311176,1353311183,ES -1353311184,1353311214,IT -1353311215,1353312255,GB +1353311184,1353311231,IT +1353311232,1353312255,GB 1353312256,1353312767,CH 1353312768,1353312815,IT 1353312816,1353312823,GB @@ -36932,7 +37125,8 @@ 1357250560,1357316095,IL 1357316096,1357316607,ES 1357316608,1357317119,LU -1357317120,1357317631,EU +1357317120,1357317375,GB +1357317376,1357317631,EU 1357317632,1357318143,LY 1357318144,1357320191,QA 1357320192,1357320703,FR @@ -36945,10 +37139,9 @@ 1357321024,1357321087,KE 1357321088,1357321215,HK 1357321216,1357321471,GB -1357321472,1357321503,ES -1357321504,1357321727,EU +1357321472,1357321727,ES 1357321728,1357321983,CY -1357321984,1357322239,EU +1357321984,1357322239,GB 1357322240,1357322751,DE 1357322752,1357323263,BH 1357323264,1357323519,ES @@ -37106,7 +37299,9 @@ 1357875216,1357875247,DE 1357875248,1357875263,US 1357875264,1357875279,AT -1357875280,1357875423,DE +1357875280,1357875295,DE +1357875296,1357875327,EU +1357875328,1357875423,DE 1357875424,1357875439,GB 1357875440,1357875711,DE 1357875712,1357875967,PL @@ -37156,8 +37351,8 @@ 1357881088,1357881343,DE 1357881344,1357883391,FR 1357883392,1357883407,ES -1357883408,1357883423,EU -1357883424,1357883519,FR +1357883408,1357883455,EU +1357883456,1357883519,FR 1357883520,1357883535,EU 1357883536,1357883543,FR 1357883544,1357883583,EU @@ -37228,7 +37423,7 @@ 1357892200,1357892207,NL 1357892208,1357892215,SE 1357892216,1357892223,US -1357892224,1357892351,EU +1357892224,1357892351,FR 1357892352,1357893119,NL 1357893120,1357893375,SE 1357893376,1357893407,EU @@ -37236,9 +37431,18 @@ 1357893440,1357893471,IT 1357893472,1357893503,PL 1357893504,1357893631,DE -1357893632,1357897343,EU +1357893632,1357894911,EU +1357894912,1357895423,FR +1357895424,1357897215,EU +1357897216,1357897279,SE +1357897280,1357897343,EU 1357897344,1357897375,HU -1357897376,1357897855,EU +1357897376,1357897471,EU +1357897472,1357897487,DE +1357897488,1357897535,EU +1357897536,1357897543,CZ +1357897544,1357897551,SE +1357897552,1357897855,EU 1357897856,1357898495,DE 1357898496,1357898751,EU 1357898752,1357899015,DE @@ -37256,7 +37460,8 @@ 1357899280,1357899287,RU 1357899288,1357899527,EU 1357899528,1357899535,BR -1357899536,1357899551,EU +1357899536,1357899543,CZ +1357899544,1357899551,EU 1357899552,1357899567,AT 1357899568,1357899647,EU 1357899648,1357899775,GB @@ -37433,8 +37638,8 @@ 1358225128,1358225135,DE 1358225136,1358225183,IT 1358225184,1358225191,DE -1358225192,1358225199,IT -1358225200,1358225407,DE +1358225192,1358225207,IT +1358225208,1358225407,DE 1358225408,1358229503,RU 1358229504,1358230111,DE 1358230112,1358230115,AT @@ -37680,7 +37885,9 @@ 1358669464,1358669471,GB 1358669472,1358669543,PT 1358669544,1358669551,GB -1358669552,1358669975,PT +1358669552,1358669823,PT +1358669824,1358669855,GB +1358669856,1358669975,PT 1358669976,1358669983,GB 1358669984,1358670015,PT 1358670016,1358670023,GB @@ -37690,8 +37897,8 @@ 1358670944,1358670951,FR 1358670952,1358671047,PT 1358671048,1358671055,ES -1358671056,1358671071,PT -1358671072,1358671103,GB +1358671056,1358671095,PT +1358671096,1358671103,GB 1358671104,1358671415,PT 1358671416,1358671423,GB 1358671424,1358671431,PT @@ -37784,9 +37991,7 @@ 1358740884,1358740887,NL 1358740888,1358740927,SE 1358740928,1358740943,DK -1358740944,1358741055,SE -1358741056,1358741071,GB -1358741072,1358741503,SE +1358740944,1358741503,SE 1358741504,1358745599,IT 1358745600,1358749695,SE 1358749696,1358753791,IT @@ -37829,7 +38034,8 @@ 1358862336,1358862847,US 1358862848,1358863103,DK 1358863104,1358863359,CH -1358863360,1358864383,US +1358863360,1358863871,US +1358863872,1358864383,GB 1358864384,1358864399,CH 1358864400,1358864407,IN 1358864408,1358864535,CH @@ -37841,7 +38047,12 @@ 1358884864,1358888959,SE 1358888960,1358889599,DE 1358889600,1358889631,IN -1358889632,1358893055,DE +1358889632,1358890943,DE +1358890944,1358890975,GB +1358890976,1358891007,IT +1358891008,1358891647,DE +1358891648,1358891679,IT +1358891680,1358893055,DE 1358893056,1358897151,RU 1358897152,1358898175,A2 1358898176,1358898239,CA @@ -38055,8 +38266,8 @@ 1359467488,1359467495,DE 1359467496,1359467647,US 1359467648,1359467775,DE -1359467776,1359467839,US -1359467840,1359467903,DE +1359467776,1359467855,US +1359467856,1359467903,DE 1359467904,1359468063,US 1359468064,1359468575,DE 1359468576,1359468583,SG @@ -38304,14 +38515,15 @@ 1360621568,1360625663,ES 1360625664,1360626687,DE 1360626688,1360627199,LB -1360627200,1360627455,DE +1360627200,1360627455,A2 1360627456,1360627520,IQ 1360627521,1360627711,DE 1360627712,1360627743,LB 1360627744,1360627967,DE 1360627968,1360628095,IQ 1360628096,1360628223,LU -1360628224,1360628735,LB +1360628224,1360628479,A2 +1360628480,1360628735,LB 1360628736,1360628991,IQ 1360628992,1360629055,TR 1360629056,1360629247,DE @@ -39091,17 +39303,15 @@ 1365103744,1365103775,ES 1365103776,1365103791,GB 1365103792,1365103871,ES -1365103872,1365104135,GB -1365104136,1365104199,ES +1365103872,1365104127,GB +1365104128,1365104199,ES 1365104200,1365104207,GB 1365104208,1365106687,ES 1365106688,1365110783,GB 1365110784,1365114879,FR 1365114880,1365118975,BA 1365118976,1365127167,RU -1365127168,1365127427,AT -1365127428,1365127431,TR -1365127432,1365130271,AT +1365127168,1365130271,AT 1365130272,1365130303,IT 1365130304,1365130495,AT 1365130496,1365131007,IT @@ -39359,6 +39569,7 @@ 1369677824,1369686015,RU 1369686016,1369690111,PL 1369690112,1369694207,UA +1369694208,1369702399,RU 1369702400,1369833471,BE 1369833472,1369964543,NO 1369964544,1369997311,GB @@ -39553,8 +39764,8 @@ 1372589824,1372618751,IT 1372618752,1372651519,GB 1372651520,1372684287,FI -1372684288,1372685599,DE -1372685600,1372685655,EU +1372684288,1372685631,DE +1372685632,1372685655,EU 1372685656,1372685663,DE 1372685664,1372685695,EU 1372685696,1372685823,DE @@ -39593,8 +39804,8 @@ 1372694784,1372694815,DE 1372694816,1372694831,EU 1372694832,1372695039,DE -1372695040,1372695167,EU -1372695168,1372695423,DE +1372695040,1372695295,EU +1372695296,1372695423,DE 1372695424,1372695551,EU 1372695552,1372695807,CZ 1372695808,1372696007,DK @@ -39607,7 +39818,9 @@ 1372697280,1372697343,EU 1372697344,1372698471,DE 1372698472,1372698559,EU -1372698560,1372700159,DE +1372698560,1372699135,DE +1372699136,1372699391,EU +1372699392,1372700159,DE 1372700160,1372700415,SE 1372700416,1372700671,EU 1372700672,1372702463,DE @@ -39621,14 +39834,8 @@ 1372703328,1372703391,DE 1372703392,1372703423,EU 1372703424,1372703487,DE -1372703488,1372703743,EU -1372703744,1372713327,DE -1372713328,1372713343,EU -1372713344,1372713375,DE -1372713376,1372713471,EU -1372713472,1372714239,DE -1372714240,1372714495,EU -1372714496,1372717055,DE +1372703488,1372704767,EU +1372704768,1372717055,DE 1372717056,1372749823,PL 1372749824,1372782591,DE 1372782592,1372815359,RU @@ -39837,7 +40044,15 @@ 1383098112,1383098367,DE 1383098368,1383098879,GB 1383098880,1383099159,DE -1383099160,1383099391,GB +1383099160,1383099163,BE +1383099164,1383099167,NL +1383099168,1383099171,IT +1383099172,1383099175,RU +1383099176,1383099179,GB +1383099180,1383099183,DE +1383099184,1383099199,GB +1383099200,1383099263,DE +1383099264,1383099391,GB 1383099392,1383099679,DE 1383099680,1383099687,GB 1383099688,1383099695,DE @@ -40260,8 +40475,7 @@ 1385568768,1385569279,EU 1385569280,1385569407,FR 1385569408,1385569487,CZ -1385569488,1385569503,FR -1385569504,1385569791,EU +1385569488,1385569791,EU 1385569792,1385570303,FR 1385570304,1385578495,HU 1385578496,1385586687,TR @@ -40347,15 +40561,11 @@ 1388388944,1388388951,NG 1388388952,1388388959,IT 1388388960,1388388967,NG -1388388968,1388389119,IT -1388389120,1388389135,NG -1388389136,1388389151,IT +1388388968,1388389151,IT 1388389152,1388389167,NG 1388389168,1388389567,IT 1388389568,1388389631,NG -1388389632,1388389927,IT -1388389928,1388389935,NG -1388389936,1388389943,IT +1388389632,1388389943,IT 1388389944,1388390015,NG 1388390016,1388390143,IT 1388390144,1388394495,NG @@ -40453,9 +40663,7 @@ 1388679168,1388679423,FR 1388679424,1388679455,DE 1388679456,1388679679,EU -1388679680,1388680703,DE -1388680704,1388680959,EU -1388680960,1388682239,DE +1388679680,1388682239,DE 1388682240,1388682751,EU 1388682752,1388683263,DE 1388683264,1388689639,CH @@ -40463,13 +40671,12 @@ 1388689648,1388691455,CH 1388691456,1388699647,NL 1388699648,1388707839,SE -1388707840,1388708607,RU +1388707840,1388708095,RU +1388708096,1388708607,LB 1388708608,1388709119,LT 1388709120,1388709375,IQ 1388709376,1388709887,RU -1388709888,1388710143,LB -1388710144,1388710399,RU -1388710400,1388710911,LB +1388709888,1388710911,LB 1388710912,1388711167,IQ 1388711168,1388711679,RU 1388711680,1388711935,IQ @@ -40487,30 +40694,16 @@ 1388716032,1388724223,ES 1388724224,1388728600,DE 1388728601,1388728608,CZ -1388728609,1388728640,DE -1388728641,1388728673,AT -1388728674,1388728734,DE -1388728735,1388728762,AT -1388728763,1388728783,DE -1388728784,1388728799,AT -1388728800,1388728815,DE -1388728816,1388728820,AT -1388728821,1388729208,DE -1388729209,1388729240,AT -1388729241,1388729280,DE -1388729281,1388729296,AT -1388729297,1388729304,DE -1388729305,1388729320,AT -1388729321,1388729856,DE -1388729857,1388729888,AT -1388729889,1388731136,DE -1388731137,1388731391,AT -1388731392,1388732415,DE +1388728609,1388732415,DE 1388732416,1388740607,ES 1388740608,1388740623,GB -1388740624,1388740719,IE +1388740624,1388740703,IE +1388740704,1388740707,GB +1388740708,1388740719,IE 1388740720,1388740735,GB -1388740736,1388741375,IE +1388740736,1388740847,IE +1388740848,1388740863,GB +1388740864,1388741375,IE 1388741376,1388741443,GB 1388741444,1388741535,IE 1388741536,1388741551,GB @@ -40524,9 +40717,9 @@ 1388741746,1388741747,GB 1388741748,1388741751,IE 1388741752,1388741759,GB -1388741760,1388741775,IE -1388741776,1388741787,GB -1388741788,1388741799,IE +1388741760,1388741787,IE +1388741788,1388741791,GB +1388741792,1388741799,IE 1388741800,1388741800,GB 1388741801,1388741807,IE 1388741808,1388741815,GB @@ -40538,7 +40731,9 @@ 1388742020,1388742023,GB 1388742024,1388742024,IE 1388742025,1388742031,GB -1388742032,1388742655,IE +1388742032,1388742067,IE +1388742068,1388742079,GB +1388742080,1388742655,IE 1388742656,1388742719,GB 1388742720,1388742731,IE 1388742732,1388742735,IR @@ -40559,10 +40754,12 @@ 1388743452,1388743555,IE 1388743556,1388743559,GB 1388743560,1388743571,IE -1388743572,1388743583,GB -1388743584,1388743919,IE +1388743572,1388743582,GB +1388743583,1388743919,IE 1388743920,1388743935,GB -1388743936,1388744087,IE +1388743936,1388744047,IE +1388744048,1388744055,GB +1388744056,1388744087,IE 1388744088,1388744095,GB 1388744096,1388744117,IE 1388744118,1388744127,GB @@ -40576,51 +40773,47 @@ 1388745500,1388745503,GB 1388745504,1388745559,IE 1388745560,1388745563,GB -1388745564,1388745651,IE -1388745652,1388745663,GB -1388745664,1388745683,IE -1388745684,1388745727,GB +1388745564,1388745671,IE +1388745672,1388745687,GB +1388745688,1388745726,IE +1388745727,1388745727,GB 1388745728,1388745911,IE -1388745912,1388745919,GB -1388745920,1388745927,IE +1388745912,1388745915,GB +1388745916,1388745927,IE 1388745928,1388745931,GB 1388745932,1388746155,IE 1388746156,1388746159,GB -1388746160,1388746175,IE -1388746176,1388746239,GB -1388746240,1388746659,IE +1388746160,1388746187,IE +1388746188,1388746191,GB +1388746192,1388746659,IE 1388746660,1388746671,GB 1388746672,1388746675,IE 1388746676,1388746695,GB 1388746696,1388746703,IE -1388746704,1388746719,GB -1388746720,1388746895,IE -1388746896,1388746903,GB -1388746904,1388746959,IE -1388746960,1388746975,GB -1388746976,1388747083,IE -1388747084,1388747087,GB -1388747088,1388747543,IE -1388747544,1388747555,GB -1388747556,1388747575,IE -1388747576,1388747647,GB -1388747648,1388747671,IE -1388747672,1388747675,GB -1388747676,1388747783,IE +1388746704,1388746711,GB +1388746712,1388746851,IE +1388746852,1388746863,GB +1388746864,1388746967,IE +1388746968,1388746975,GB +1388746976,1388747543,IE +1388747544,1388747547,GB +1388747548,1388747575,IE +1388747576,1388747599,GB +1388747600,1388747627,IE +1388747628,1388747647,GB +1388747648,1388747783,IE 1388747784,1388747791,GB -1388747792,1388747835,IE -1388747836,1388747839,GB -1388747840,1388747859,IE +1388747792,1388747859,IE 1388747860,1388747875,GB 1388747876,1388747983,IE 1388747984,1388747987,GB -1388747988,1388747999,IE -1388748000,1388748031,GB +1388747988,1388748030,IE +1388748031,1388748031,GB 1388748032,1388748223,IE 1388748224,1388748255,GB 1388748256,1388748287,IE -1388748288,1388748295,GB -1388748296,1388748349,IE +1388748288,1388748319,GB +1388748320,1388748349,IE 1388748350,1388748351,GB 1388748352,1388748799,IE 1388748800,1388756991,RU @@ -40643,8 +40836,8 @@ 1388806144,1388807679,DE 1388807680,1388807711,BZ 1388807712,1388808255,DE -1388808256,1388808283,BZ -1388808284,1388814335,DE +1388808256,1388808287,BZ +1388808288,1388814335,DE 1388814336,1388815103,AX 1388815104,1388815231,FI 1388815232,1388818687,AX @@ -40933,7 +41126,8 @@ 1389293056,1389293311,US 1389293312,1389293567,KE 1389293568,1389294335,A2 -1389294336,1389294719,US +1389294336,1389294591,US +1389294592,1389294719,A2 1389294720,1389294847,IQ 1389294848,1389295615,US 1389295616,1389295871,ZA @@ -40980,9 +41174,7 @@ 1389555264,1389555327,AT 1389555328,1389556751,DE 1389556752,1389556759,CH -1389556760,1389559039,DE -1389559040,1389559103,CH -1389559104,1389559743,DE +1389556760,1389559743,DE 1389559744,1389559807,CH 1389559808,1389561343,DE 1389561344,1389561407,IT @@ -41138,17 +41330,17 @@ 1400111104,1400373247,NL 1400373248,1400705279,DE 1400705280,1400705791,EU -1400705792,1400708607,DE -1400708608,1400709120,EU +1400705792,1400707071,DE +1400707072,1400708095,EU +1400708096,1400708863,DE +1400708864,1400709120,EU 1400709121,1400710142,DE 1400710143,1400710399,EU 1400710400,1400712191,DE 1400712192,1400712447,EU 1400712448,1400712703,DE 1400712704,1400712959,EU -1400712960,1400716287,DE -1400716288,1400717311,EU -1400717312,1400718335,DE +1400712960,1400718335,DE 1400718336,1400718847,EU 1400718848,1400721407,DE 1400721408,1400721919,EU @@ -41555,6 +41747,7 @@ 1401927680,1401929727,NL 1401929728,1401931775,RU 1401931776,1401933823,UA +1401933824,1401935871,DE 1401935872,1401937919,FI 1401937920,1401939967,GB 1401939968,1401942015,UA @@ -41643,7 +41836,9 @@ 1403445248,1403461631,RU 1403461632,1403464663,FR 1403464664,1403464671,BE -1403464672,1403469423,FR +1403464672,1403465727,FR +1403465728,1403465743,GB +1403465744,1403469423,FR 1403469424,1403469431,US 1403469432,1403469823,FR 1403469824,1403486207,RU @@ -41768,7 +41963,7 @@ 1404010496,1404026879,PL 1404026880,1404043263,ES 1404043264,1404051455,EE -1404051456,1404059647,KZ +1404051456,1404059647,HR 1404059648,1404076031,NO 1404076032,1404084223,DE 1404084224,1404092415,NO @@ -41791,9 +41986,7 @@ 1404197888,1404198911,LT 1404198912,1404200959,SE 1404200960,1404203007,NL -1404203008,1404204800,HR -1404204801,1404205055,SE -1404205056,1404207103,HR +1404203008,1404207103,HR 1404207104,1404210175,NO 1404210176,1404212223,LV 1404212224,1404215295,SE @@ -41855,7 +42048,10 @@ 1404928000,1404944383,SE 1404944384,1404952575,DE 1404952576,1404960767,NL -1404960768,1405050879,SE +1404960768,1405026303,SE +1405026304,1405042687,NO +1405042688,1405048831,SE +1405048832,1405050879,HR 1405050880,1405059071,AT 1405059072,1405063167,SE 1405063168,1405067263,NO @@ -41937,7 +42133,31 @@ 1406763008,1406771199,BE 1406771200,1406779391,GB 1406779392,1406787583,RU -1406787584,1406795775,ES +1406787584,1406787679,GB +1406787680,1406787695,ES +1406787696,1406787927,GB +1406787928,1406787967,ES +1406787968,1406788055,GB +1406788056,1406788351,ES +1406788352,1406788479,BG +1406788480,1406788607,ES +1406788608,1406788711,GB +1406788712,1406789119,ES +1406789120,1406789135,GB +1406789136,1406789183,ES +1406789184,1406789247,GB +1406789248,1406789375,ES +1406789376,1406789503,RO +1406789504,1406789631,ES +1406789632,1406789887,FR +1406789888,1406790015,HU +1406790016,1406790143,ES +1406790144,1406790399,GB +1406790400,1406790655,ES +1406790656,1406790927,GB +1406790928,1406790943,ES +1406790944,1406790959,GB +1406790960,1406795775,ES 1406795776,1406803967,GB 1406803968,1406812159,DE 1406812160,1406820351,SE @@ -42051,7 +42271,9 @@ 1407517032,1407517039,NG 1407517040,1407517047,A2 1407517048,1407517055,GQ -1407517056,1407517151,A2 +1407517056,1407517135,A2 +1407517136,1407517143,NG +1407517144,1407517151,A2 1407517152,1407517159,CD 1407517160,1407517167,ML 1407517168,1407517175,A2 @@ -42179,7 +42401,9 @@ 1407520208,1407520215,NG 1407520216,1407520223,CD 1407520224,1407520231,SD -1407520232,1407520271,A2 +1407520232,1407520239,A2 +1407520240,1407520247,NE +1407520248,1407520271,A2 1407520272,1407520279,NG 1407520280,1407520311,A2 1407520312,1407520327,NG @@ -42219,7 +42443,7 @@ 1407520752,1407520759,BF 1407520760,1407520767,CD 1407520768,1407520775,TZ -1407520776,1407520783,CD +1407520776,1407520783,A2 1407520784,1407520791,SD 1407520792,1407520799,ZA 1407520800,1407520807,A2 @@ -42306,8 +42530,7 @@ 1407522488,1407522495,ZW 1407522496,1407522503,LR 1407522504,1407522511,ZW -1407522512,1407522519,UG -1407522520,1407522527,A2 +1407522512,1407522527,A2 1407522528,1407522535,ZM 1407522536,1407522543,NG 1407522544,1407522559,UG @@ -42361,11 +42584,11 @@ 1407522976,1407522983,CD 1407522984,1407522991,A2 1407522992,1407522999,CD -1407523000,1407523007,A2 -1407523008,1407523015,NG +1407523000,1407523015,A2 1407523016,1407523023,KE 1407523024,1407523031,MU -1407523032,1407523055,A2 +1407523032,1407523047,A2 +1407523048,1407523055,NG 1407523056,1407523063,MU 1407523064,1407523071,A2 1407523072,1407523079,CD @@ -42399,9 +42622,12 @@ 1407523336,1407523351,A2 1407523352,1407523359,LU 1407523360,1407523455,A2 -1407523456,1407523519,MW +1407523456,1407523487,MW +1407523488,1407523495,LR +1407523496,1407523519,MW 1407523520,1407523535,A2 -1407523536,1407523551,NG +1407523536,1407523543,SO +1407523544,1407523551,NG 1407523552,1407523559,CM 1407523560,1407523567,KE 1407523568,1407523583,A2 @@ -42416,9 +42642,10 @@ 1407523744,1407523751,IQ 1407523752,1407523791,A2 1407523792,1407523799,IQ -1407523800,1407523831,A2 +1407523800,1407523807,SY +1407523808,1407523831,A2 1407523832,1407523839,IQ -1407523840,1407524351,MW +1407523840,1407524351,A2 1407524352,1407524607,GB 1407524608,1407524615,ZW 1407524616,1407524623,CD @@ -42472,7 +42699,8 @@ 1407525048,1407525055,NG 1407525056,1407525063,ZA 1407525064,1407525071,SO -1407525072,1407525087,A2 +1407525072,1407525079,CD +1407525080,1407525087,A2 1407525088,1407525095,MW 1407525096,1407525103,ZW 1407525104,1407525111,NG @@ -42535,10 +42763,8 @@ 1407529024,1407529087,NG 1407529088,1407529095,SO 1407529096,1407529103,A2 -1407529104,1407529111,NG -1407529112,1407529119,A2 -1407529120,1407529127,SD -1407529128,1407529175,A2 +1407529104,1407529111,SO +1407529112,1407529175,A2 1407529176,1407529183,SO 1407529184,1407529191,NG 1407529192,1407529207,A2 @@ -42549,7 +42775,7 @@ 1407531552,1407531559,SD 1407531560,1407531567,A2 1407531568,1407531575,CD -1407531576,1407531583,A2 +1407531576,1407531583,GQ 1407531584,1407531591,CD 1407531592,1407531599,A2 1407531600,1407531607,LY @@ -42562,7 +42788,7 @@ 1407531664,1407531671,MZ 1407531672,1407531687,CD 1407531688,1407531703,A2 -1407531704,1407531711,IQ +1407531704,1407531711,SD 1407531712,1407531735,CD 1407531736,1407531743,ZW 1407531744,1407531751,A2 @@ -42591,7 +42817,8 @@ 1407533408,1407533423,A2 1407533424,1407533567,GH 1407533568,1407533583,NG -1407533584,1407533607,A2 +1407533584,1407533591,NE +1407533592,1407533607,A2 1407533608,1407533631,NG 1407533632,1407533679,A2 1407533680,1407533695,NG @@ -42812,15 +43039,16 @@ 1407539720,1407539727,A2 1407539728,1407539735,GR 1407539736,1407539743,NG -1407539744,1407539767,A2 +1407539744,1407539751,A2 +1407539752,1407539759,NG +1407539760,1407539767,A2 1407539768,1407539775,GR 1407539776,1407539783,A2 1407539784,1407539791,GR 1407539792,1407539799,NG 1407539800,1407539823,A2 1407539824,1407539831,NG -1407539832,1407539847,A2 -1407539848,1407539855,NG +1407539832,1407539855,A2 1407539856,1407539863,CD 1407539864,1407539879,NG 1407539880,1407539887,A2 @@ -42828,7 +43056,8 @@ 1407539896,1407539903,CD 1407539904,1407539911,A2 1407539912,1407539927,NG -1407539928,1407539943,A2 +1407539928,1407539935,A2 +1407539936,1407539943,GN 1407539944,1407539951,CD 1407539952,1407539959,LR 1407539960,1407539967,A2 @@ -42871,7 +43100,9 @@ 1407540432,1407540439,CI 1407540440,1407540447,A2 1407540448,1407540455,LR -1407540456,1407540479,A2 +1407540456,1407540463,A2 +1407540464,1407540471,MU +1407540472,1407540479,A2 1407540480,1407540487,CM 1407540488,1407540495,A2 1407540496,1407540503,NG @@ -42896,7 +43127,9 @@ 1407541032,1407541039,NG 1407541040,1407541047,A2 1407541048,1407541055,NG -1407541056,1407541095,A2 +1407541056,1407541063,A2 +1407541064,1407541071,NG +1407541072,1407541095,A2 1407541096,1407541103,GQ 1407541104,1407541175,A2 1407541176,1407541183,NG @@ -42956,7 +43189,8 @@ 1407545856,1407545863,CI 1407545864,1407545871,A2 1407545872,1407545879,CD -1407545880,1407545895,A2 +1407545880,1407545887,A2 +1407545888,1407545895,NG 1407545896,1407545903,CD 1407545904,1407545911,A2 1407545912,1407545927,NG @@ -42966,8 +43200,7 @@ 1407545952,1407545959,BJ 1407545960,1407545967,A2 1407545968,1407545975,GQ -1407545976,1407545983,A2 -1407545984,1407545991,MU +1407545976,1407545991,A2 1407545992,1407545999,GN 1407546000,1407546007,CF 1407546008,1407546023,A2 @@ -43015,15 +43248,15 @@ 1407548128,1407548143,CM 1407548144,1407548151,A2 1407548152,1407548415,NG -1407548416,1407548543,GE +1407548416,1407548443,GE +1407548444,1407548447,NE +1407548448,1407548543,GE 1407548544,1407548711,A2 1407548712,1407548719,CD 1407548720,1407548767,A2 1407548768,1407548775,CD 1407548776,1407548927,A2 -1407548928,1407548943,NG -1407548944,1407548951,A2 -1407548952,1407548959,NG +1407548928,1407548959,NG 1407548960,1407548967,A2 1407548968,1407548975,CM 1407548976,1407548983,A2 @@ -43066,7 +43299,9 @@ 1407693160,1407693167,ES 1407693168,1407695215,GB 1407695216,1407695223,ES -1407695224,1407700271,GB +1407695224,1407696487,GB +1407696488,1407696495,AU +1407696496,1407700271,GB 1407700272,1407700287,DE 1407700288,1407702015,GB 1407702016,1407702271,FR @@ -43086,9 +43321,7 @@ 1407704384,1407704447,FR 1407704448,1407705207,GB 1407705208,1407705215,ES -1407705216,1407705247,GB -1407705248,1407705279,ES -1407705280,1407705599,GB +1407705216,1407705599,GB 1407705600,1407705727,FR 1407705728,1407705759,GB 1407705760,1407705791,FR @@ -43214,8 +43447,7 @@ 1410009344,1410009479,US 1410009480,1410009487,A2 1410009488,1410009535,GI -1410009536,1410010367,A2 -1410010368,1410010399,IR +1410009536,1410010399,A2 1410010400,1410010431,LY 1410010432,1410010543,A2 1410010544,1410010575,LY @@ -43232,10 +43464,7 @@ 1410010832,1410010879,A2 1410010880,1410011135,IR 1410011136,1410011647,DE -1410011648,1410012159,A2 -1410012160,1410012415,IQ -1410012416,1410012447,AF -1410012448,1410012671,A2 +1410011648,1410012671,A2 1410012672,1410013183,DE 1410013184,1410013439,ES 1410013440,1410013471,IR @@ -43312,15 +43541,9 @@ 1410018560,1410018591,A2 1410018592,1410018607,IR 1410018608,1410018623,LY -1410018624,1410018815,A2 -1410018816,1410018831,DE -1410018832,1410018847,A2 -1410018848,1410018863,DE -1410018864,1410020103,A2 +1410018624,1410020103,A2 1410020104,1410020111,US -1410020112,1410020351,A2 -1410020352,1410020863,US -1410020864,1410021375,A2 +1410020112,1410021375,A2 1410021376,1410021407,IR 1410021408,1410021631,A2 1410021632,1410021663,IR @@ -43394,8 +43617,7 @@ 1410037760,1410038015,US 1410038016,1410042815,A2 1410042816,1410042831,US -1410042832,1410044927,A2 -1410044928,1410045183,VG +1410042832,1410045183,A2 1410045184,1410045439,IQ 1410045440,1410045695,LB 1410045696,1410071815,A2 @@ -43488,7 +43710,7 @@ 1410573440,1410573695,DE 1410573696,1410573711,RU 1410573712,1410573759,DE -1410573760,1410573775,BA +1410573760,1410573775,RU 1410573776,1410573799,DE 1410573800,1410573815,IT 1410573816,1410573823,RU @@ -43502,7 +43724,9 @@ 1410574584,1410574591,RU 1410574592,1410574719,DE 1410574720,1410574727,RU -1410574728,1410575103,DE +1410574728,1410574847,DE +1410574848,1410574975,BR +1410574976,1410575103,DE 1410575104,1410575111,US 1410575112,1410575119,IT 1410575120,1410575135,DE @@ -43524,7 +43748,9 @@ 1410575856,1410575871,DE 1410575872,1410575999,DK 1410576000,1410576255,DE -1410576256,1410576383,IT +1410576256,1410576319,IT +1410576320,1410576351,DE +1410576352,1410576383,IT 1410576384,1410588671,DE 1410588672,1410596863,GB 1410596864,1410605055,ES @@ -43546,7 +43772,166 @@ 1410711552,1410719743,BG 1410719744,1410727935,RU 1410727936,1410736127,BG -1410736128,1410744319,RS +1410736128,1410736128,RS +1410736129,1410736382,AL +1410736383,1410736384,RS +1410736385,1410736638,AL +1410736639,1410736640,RS +1410736641,1410736894,AL +1410736895,1410736896,RS +1410736897,1410736911,AL +1410736912,1410736928,RS +1410736929,1410736991,AL +1410736992,1410737415,RS +1410737416,1410737423,AL +1410737424,1410737431,RS +1410737432,1410737439,AL +1410737440,1410737664,RS +1410737665,1410737918,AL +1410737919,1410737920,RS +1410737921,1410738174,AL +1410738175,1410738175,RS +1410738176,1410738215,AL +1410738216,1410738223,RS +1410738224,1410738247,AL +1410738248,1410738263,RS +1410738264,1410738271,AL +1410738272,1410738279,RS +1410738280,1410738295,AL +1410738296,1410738304,RS +1410738305,1410738310,AL +1410738311,1410738320,RS +1410738321,1410738326,AL +1410738327,1410738328,RS +1410738329,1410738334,AL +1410738335,1410738351,RS +1410738352,1410738359,AL +1410738360,1410738384,RS +1410738385,1410738390,AL +1410738391,1410738439,RS +1410738440,1410738447,AL +1410738448,1410738703,RS +1410738704,1410738718,AL +1410738719,1410738720,RS +1410738721,1410738734,AL +1410738735,1410738752,RS +1410738753,1410738766,AL +1410738767,1410738768,RS +1410738769,1410738782,AL +1410738783,1410738800,RS +1410738801,1410738814,AL +1410738815,1410738816,RS +1410738817,1410738830,AL +1410738831,1410738832,RS +1410738833,1410738846,AL +1410738847,1410738864,RS +1410738865,1410738878,AL +1410738879,1410738896,RS +1410738897,1410738902,AL +1410738903,1410738912,RS +1410738913,1410738927,AL +1410738928,1410739200,RS +1410739201,1410739326,AL +1410739327,1410739328,RS +1410739329,1410739390,AL +1410739391,1410739472,RS +1410739473,1410739486,AL +1410739487,1410739520,RS +1410739521,1410739534,AL +1410739535,1410739543,RS +1410739544,1410739550,AL +1410739551,1410739568,RS +1410739569,1410739582,AL +1410739583,1410739616,RS +1410739617,1410739630,AL +1410739631,1410739696,RS +1410739697,1410739710,AL +1410739711,1410739712,RS +1410739713,1410739719,AL +1410739720,1410739720,RS +1410739721,1410739727,AL +1410739728,1410739728,RS +1410739729,1410739734,AL +1410739735,1410739736,RS +1410739737,1410739742,AL +1410739743,1410739744,RS +1410739745,1410739750,AL +1410739751,1410739752,RS +1410739753,1410739759,AL +1410739760,1410739776,RS +1410739777,1410739783,AL +1410739784,1410739791,RS +1410739792,1410739799,AL +1410739800,1410739807,RS +1410739808,1410739879,AL +1410739880,1410739887,RS +1410739888,1410739919,AL +1410739920,1410739927,RS +1410739928,1410739951,AL +1410739952,1410739967,RS +1410739968,1410740003,AL +1410740004,1410740007,RS +1410740008,1410740043,AL +1410740044,1410740047,RS +1410740048,1410740122,AL +1410740123,1410740123,RS +1410740124,1410740135,AL +1410740136,1410740139,RS +1410740140,1410740335,AL +1410740336,1410740343,RS +1410740344,1410740383,AL +1410740384,1410740391,RS +1410740392,1410740415,AL +1410740416,1410740423,RS +1410740424,1410740471,AL +1410740472,1410740479,RS +1410740480,1410740507,AL +1410740508,1410740511,RS +1410740512,1410740515,AL +1410740516,1410740519,RS +1410740520,1410740643,AL +1410740644,1410740647,RS +1410740648,1410740675,AL +1410740676,1410740679,RS +1410740680,1410740734,AL +1410740735,1410740735,RS +1410740736,1410740751,AL +1410740752,1410740767,RS +1410740768,1410740823,AL +1410740824,1410740831,RS +1410740832,1410740871,AL +1410740872,1410740879,RS +1410740880,1410740911,AL +1410740912,1410740919,RS +1410740920,1410740931,AL +1410740932,1410740935,RS +1410740936,1410740943,AL +1410740944,1410740991,RS +1410740992,1410741303,AL +1410741304,1410741327,RS +1410741328,1410741335,AL +1410741336,1410741351,RS +1410741352,1410741427,AL +1410741428,1410741431,RS +1410741432,1410741443,AL +1410741444,1410741447,RS +1410741448,1410741479,AL +1410741480,1410741483,RS +1410741484,1410741567,AL +1410741568,1410741583,RS +1410741584,1410742279,AL +1410742280,1410742319,RS +1410742320,1410742351,AL +1410742352,1410742359,RS +1410742360,1410742415,AL +1410742416,1410742527,RS +1410742528,1410742907,AL +1410742908,1410742911,RS +1410742912,1410742923,AL +1410742924,1410743039,RS +1410743040,1410743935,AL +1410743936,1410743999,RS +1410744000,1410744319,AL 1410744320,1410744575,FR 1410744576,1410744831,A2 1410744832,1410745223,FR @@ -43596,7 +43981,8 @@ 1410755584,1410760191,AQ 1410760192,1410760447,DE 1410760448,1410760455,CN -1410760456,1410760471,AQ +1410760456,1410760463,BS +1410760464,1410760471,AQ 1410760472,1410760487,DE 1410760488,1410760503,AQ 1410760504,1410760703,DE @@ -43721,19 +44107,23 @@ 1411999904,1411999911,BA 1411999912,1411999919,SI 1411999920,1411999927,BA -1411999928,1411999951,SI +1411999928,1411999935,SI +1411999936,1411999943,BA +1411999944,1411999951,SI 1411999952,1411999959,BA -1411999960,1411999983,SI -1411999984,1412000767,BA +1411999960,1411999967,SI +1411999968,1412000767,BA 1412000768,1412000783,SI 1412000784,1412000791,BA 1412000792,1412000863,SI 1412000864,1412000879,BA -1412000880,1412000903,SI -1412000904,1412000911,BA +1412000880,1412000895,SI +1412000896,1412000911,BA 1412000912,1412000943,SI -1412000944,1412000991,BA -1412000992,1412001007,SI +1412000944,1412000959,BA +1412000960,1412000967,SI +1412000968,1412000999,BA +1412001000,1412001007,SI 1412001008,1412001015,BA 1412001016,1412001311,SI 1412001312,1412001319,DE @@ -43746,7 +44136,9 @@ 1412002784,1412002815,SI 1412002816,1412002847,BA 1412002848,1412002863,SI -1412002864,1412002911,BA +1412002864,1412002895,BA +1412002896,1412002903,SI +1412002904,1412002911,BA 1412002912,1412002919,SI 1412002920,1412003015,BA 1412003016,1412003023,SI @@ -43764,7 +44156,9 @@ 1412003264,1412003271,SI 1412003272,1412003303,BA 1412003304,1412003327,SI -1412003328,1412003351,BA +1412003328,1412003335,BA +1412003336,1412003343,SI +1412003344,1412003351,BA 1412003352,1412003375,SI 1412003376,1412003383,BA 1412003384,1412003391,SI @@ -43777,11 +44171,7 @@ 1412003624,1412003631,BA 1412003632,1412003639,SI 1412003640,1412003647,BA -1412003648,1412003727,SI -1412003728,1412003783,BA -1412003784,1412003791,SI -1412003792,1412003823,BA -1412003824,1412003855,SI +1412003648,1412003855,SI 1412003856,1412003903,BG 1412003904,1412003935,SI 1412003936,1412004351,BG @@ -43878,7 +44268,9 @@ 1422403840,1422403903,IT 1422403904,1422406399,DE 1422406400,1422406463,GB -1422406464,1422468207,DE +1422406464,1422410367,DE +1422410368,1422410495,IT +1422410496,1422468207,DE 1422468208,1422468223,IT 1422468224,1422468671,DE 1422468672,1422468735,IT @@ -43934,7 +44326,7 @@ 1424588800,1424588839,DE 1424588840,1424588847,GB 1424588848,1424588863,DE -1424588864,1424588927,GB +1424588864,1424588927,US 1424588928,1424588951,DE 1424588952,1424588959,GB 1424588960,1424588963,IT @@ -43964,12 +44356,16 @@ 1424593968,1424593983,GB 1424593984,1424594055,FR 1424594056,1424594063,IT -1424594064,1424594103,FR +1424594064,1424594087,FR +1424594088,1424594095,GB +1424594096,1424594103,FR 1424594104,1424594111,GB 1424594112,1424594175,FR 1424594176,1424594431,GB 1424594432,1424594519,IE -1424594520,1424595455,GB +1424594520,1424594527,GB +1424594528,1424594535,IE +1424594536,1424595455,GB 1424595456,1424595527,IT 1424595528,1424595535,GB 1424595536,1424595575,IT @@ -43986,8 +44382,8 @@ 1424597352,1424597375,GB 1424597376,1424597391,CZ 1424597392,1424597407,GB -1424597408,1424597423,CZ -1424597424,1424597503,GB +1424597408,1424597431,CZ +1424597432,1424597503,GB 1424597504,1424597759,FR 1424597760,1424598015,IT 1424598016,1424599039,GB @@ -44011,7 +44407,8 @@ 1424600576,1424600831,FR 1424600832,1424601087,BE 1424601088,1424601343,GB -1424601344,1424601599,ES +1424601344,1424601351,ES +1424601352,1424601599,GB 1424601600,1424601855,CH 1424601856,1424602111,GB 1424602112,1424602623,DE @@ -44020,7 +44417,8 @@ 1424602744,1424602879,GB 1424602880,1424602911,US 1424602912,1424602927,FR -1424602928,1424603007,US +1424602928,1424602935,GB +1424602936,1424603007,US 1424603008,1424603023,GB 1424603024,1424603087,US 1424603088,1424603095,GB @@ -44028,8 +44426,8 @@ 1424603136,1424603391,SK 1424603392,1424603647,DE 1424603648,1424603903,GB -1424603904,1424604031,ES -1424604032,1424604047,GB +1424603904,1424604039,ES +1424604040,1424604047,GB 1424604048,1424604159,ES 1424604160,1424604543,NL 1424604544,1424604671,GB @@ -44072,8 +44470,8 @@ 1424608328,1424608383,FR 1424608384,1424608399,ES 1424608400,1424608511,FR -1424608512,1424608543,ES -1424608544,1424608567,GB +1424608512,1424608559,ES +1424608560,1424608567,GB 1424608568,1424608687,ES 1424608688,1424608691,GB 1424608692,1424609023,ES @@ -44084,7 +44482,9 @@ 1424609396,1424609399,GB 1424609400,1424609535,CH 1424609536,1424609543,GB -1424609544,1424609791,CH +1424609544,1424609743,CH +1424609744,1424609759,GB +1424609760,1424609791,CH 1424609792,1424610303,GB 1424610304,1424610559,TZ 1424610560,1424610815,PL @@ -44092,8 +44492,8 @@ 1424611072,1424611135,BE 1424611136,1424611151,GB 1424611152,1424611271,BE -1424611272,1424611295,GB -1424611296,1424611327,BE +1424611272,1424611279,LU +1424611280,1424611327,BE 1424611328,1424611583,PL 1424611584,1424612095,GB 1424612096,1424612231,CZ @@ -44112,11 +44512,9 @@ 1424614136,1424614143,IT 1424614144,1424614399,GB 1424614400,1424614415,FR -1424614416,1424614431,IT -1424614432,1424614439,GB -1424614440,1424614495,IT -1424614496,1424614527,GB -1424614528,1424614655,IT +1424614416,1424614503,IT +1424614504,1424614511,GB +1424614512,1424614655,IT 1424614656,1424614911,FR 1424614912,1424615167,RO 1424615168,1424615679,GB @@ -44125,7 +44523,8 @@ 1424615808,1424615935,IT 1424615936,1424616191,FR 1424616192,1424616447,IT -1424616448,1424616483,ES +1424616448,1424616479,GB +1424616480,1424616483,ES 1424616484,1424616487,GB 1424616488,1424616503,ES 1424616504,1424616511,GB @@ -44145,8 +44544,7 @@ 1424617396,1424617399,GB 1424617400,1424617407,IT 1424617408,1424617423,ES -1424617424,1424617431,GB -1424617432,1424617439,ES +1424617424,1424617439,GB 1424617440,1424617447,IT 1424617448,1424617455,GB 1424617456,1424617463,IT @@ -44621,33 +45019,18 @@ 1426800640,1426817023,PL 1426817024,1426833407,BG 1426833408,1426849791,SE -1426849792,1426850303,NL -1426850304,1426850335,SE -1426850336,1426850367,GB -1426850368,1426850463,NL -1426850464,1426850495,GB -1426850496,1426851519,NL +1426849792,1426851519,NL 1426851520,1426851583,PA -1426851584,1426851839,NL -1426851840,1426852095,SE -1426852096,1426852352,NL +1426851584,1426852352,NL 1426852353,1426852359,RU 1426852360,1426852367,SE 1426852368,1426852375,NL 1426852376,1426852383,US -1426852384,1426852543,GB -1426852544,1426856447,NL -1426856448,1426856703,ES -1426856704,1426857472,NL +1426852384,1426857472,NL 1426857473,1426857500,ES -1426857501,1426859263,NL -1426859264,1426859519,RU -1426859520,1426864511,NL +1426857501,1426864511,NL 1426864512,1426864639,PA -1426864640,1426864895,FR -1426864896,1426865663,NL -1426865664,1426865919,BE -1426865920,1426866175,ES +1426864640,1426866175,NL 1426866176,1426882559,GB 1426882560,1426898943,FR 1426898944,1426915327,RU @@ -44670,7 +45053,9 @@ 1426968792,1426968800,ES 1426968801,1426969135,GB 1426969136,1426969151,ES -1426969152,1426972319,GB +1426969152,1426971855,GB +1426971856,1426971863,ES +1426971864,1426972319,GB 1426972320,1426972326,FR 1426972327,1426973335,GB 1426973336,1426973343,ES @@ -44732,8 +45117,7 @@ 1427728480,1427728511,CY 1427728512,1427728543,BR 1427728544,1427728575,DE -1427728576,1427728607,BR -1427728608,1427728639,TW +1427728576,1427728639,BR 1427728640,1427728671,DE 1427728672,1427728703,TR 1427728704,1427728735,RU @@ -44748,52 +45132,62 @@ 1427729056,1427729087,CA 1427729088,1427729119,DE 1427729120,1427729151,BR -1427729152,1427729311,DE +1427729152,1427729215,DE +1427729216,1427729279,IN +1427729280,1427729311,DE 1427729312,1427729343,GR 1427729344,1427742719,DE 1427742720,1427742751,IO -1427742752,1427742975,DE +1427742752,1427742911,DE +1427742912,1427742943,US +1427742944,1427742975,DE 1427742976,1427743007,RU 1427743008,1427743039,US 1427743040,1427743071,BR 1427743072,1427743103,CY 1427743104,1427743135,BR -1427743136,1427743199,DE +1427743136,1427743167,IN +1427743168,1427743199,DE 1427743200,1427743231,TR 1427743232,1427743263,GR 1427743264,1427743327,DE 1427743328,1427743359,NL -1427743360,1427743391,DE -1427743392,1427743423,BR -1427743424,1427743455,DE +1427743360,1427743423,BR +1427743424,1427743455,TR 1427743456,1427743487,CY 1427743488,1427743583,DE 1427743584,1427743615,LV 1427743616,1427743647,DK -1427743648,1427743775,DE +1427743648,1427743679,DE +1427743680,1427743711,RU +1427743712,1427743775,DE 1427743776,1427743807,ZA 1427743808,1427743839,DE 1427743840,1427743871,RU -1427743872,1427743935,DE +1427743872,1427743903,DE +1427743904,1427743935,US 1427743936,1427743967,RU 1427743968,1427743999,US -1427744000,1427744031,TW -1427744032,1427744127,DE +1427744000,1427744031,DE +1427744032,1427744063,RU +1427744064,1427744127,DE 1427744128,1427744159,PL 1427744160,1427744191,RU 1427744192,1427744255,DE 1427744256,1427744287,US 1427744288,1427744319,TR -1427744320,1427744351,DE +1427744320,1427744351,IN 1427744352,1427744383,UA 1427744384,1427744415,PL 1427744416,1427744447,UA 1427744448,1427744479,US -1427744480,1427744639,DE +1427744480,1427744575,DE +1427744576,1427744607,PL +1427744608,1427744639,DE 1427744640,1427744671,TR -1427744672,1427744735,DE -1427744736,1427744767,DK -1427744768,1427744863,DE +1427744672,1427744767,DE +1427744768,1427744799,BR +1427744800,1427744863,DE 1427744864,1427744927,TR 1427744928,1427744959,HU 1427744960,1427744991,RU @@ -44803,11 +45197,12 @@ 1427745088,1427745151,DE 1427745152,1427745183,RO 1427745184,1427745215,CH -1427745216,1427745279,DE +1427745216,1427745247,TR +1427745248,1427745279,DE 1427745280,1427745311,MA 1427745312,1427745343,TH 1427745344,1427745375,DE -1427745376,1427745407,TW +1427745376,1427745407,BR 1427745408,1427745471,US 1427745472,1427745503,RO 1427745504,1427745535,RU @@ -44822,9 +45217,11 @@ 1427745792,1427745823,GB 1427745824,1427745855,US 1427745856,1427745887,BR -1427745888,1427745919,DE +1427745888,1427745919,IN 1427745920,1427745951,ES -1427745952,1427746047,DE +1427745952,1427745983,IN +1427745984,1427746015,DE +1427746016,1427746047,TR 1427746048,1427746079,SE 1427746080,1427746111,GB 1427746112,1427746143,DE @@ -44845,18 +45242,25 @@ 1427748160,1427748191,GB 1427748192,1427748255,DE 1427748256,1427748287,US -1427748288,1427748447,DE +1427748288,1427748351,DE +1427748352,1427748383,BR +1427748384,1427748447,DE 1427748448,1427748479,RU 1427748480,1427748511,MA -1427748512,1427748607,DE +1427748512,1427748575,DE +1427748576,1427748607,BR 1427748608,1427748639,HU -1427748640,1427748767,DE -1427748768,1427748799,BR -1427748800,1427749567,DE +1427748640,1427748735,DE +1427748736,1427748799,BR +1427748800,1427748831,MA +1427748832,1427749535,DE +1427749536,1427749567,MA 1427749568,1427749599,CY 1427749600,1427749695,DE 1427749696,1427749727,BR -1427749728,1427749855,DE +1427749728,1427749759,DE +1427749760,1427749791,BR +1427749792,1427749855,DE 1427749856,1427749887,RU 1427749888,1427749919,BR 1427749920,1427749951,US @@ -44875,18 +45279,22 @@ 1427751424,1427759903,DE 1427759904,1427759935,MA 1427759936,1427759967,HR -1427759968,1427760031,DE +1427759968,1427759999,DE +1427760000,1427760031,BR 1427760032,1427760095,US -1427760096,1427760191,DE +1427760096,1427760159,DE +1427760160,1427760191,PL 1427760192,1427760255,US 1427760256,1427760319,BR 1427760320,1427760351,TR 1427760352,1427760383,RU -1427760384,1427760415,TR -1427760416,1427760447,BR +1427760384,1427760415,IN +1427760416,1427760447,TR 1427760448,1427760575,DE 1427760576,1427760607,CH -1427760608,1427760799,DE +1427760608,1427760671,DE +1427760672,1427760703,BR +1427760704,1427760799,DE 1427760800,1427760831,US 1427760832,1427760863,DE 1427760864,1427760895,US @@ -44904,7 +45312,9 @@ 1427761312,1427761343,UA 1427761344,1427761375,CY 1427761376,1427761407,TW -1427761408,1427761503,DE +1427761408,1427761439,RU +1427761440,1427761471,US +1427761472,1427761503,IN 1427761504,1427761535,PL 1427761536,1427761567,US 1427761568,1427761599,RU @@ -45163,7 +45573,8 @@ 1433602320,1433608191,DE 1433608192,1433608959,GB 1433608960,1433609215,DE -1433609216,1433609727,GB +1433609216,1433609471,ZA +1433609472,1433609727,GB 1433609728,1433610239,CH 1433610240,1433612287,US 1433612288,1433614335,GB @@ -45198,7 +45609,8 @@ 1433806656,1433806687,IT 1433806688,1433806719,NL 1433806720,1433806751,DE -1433806752,1433812991,FR +1433806752,1433806783,ES +1433806784,1433812991,FR 1433812992,1433821183,BG 1433821184,1433829375,GE 1433829376,1433833471,RU @@ -45223,7 +45635,9 @@ 1433860096,1433862143,DE 1433862144,1433862467,CH 1433862468,1433862471,US -1433862472,1433862559,CH +1433862472,1433862519,CH +1433862520,1433862527,NL +1433862528,1433862559,CH 1433862560,1433862575,GB 1433862576,1433862751,CH 1433862752,1433862783,MC @@ -45301,8 +45715,8 @@ 1434683328,1434683391,MY 1434683392,1434685759,DE 1434685760,1434685951,NL -1434685952,1434686719,DE -1434686720,1434687231,NL +1434685952,1434686975,DE +1434686976,1434687231,NL 1434687232,1434687359,DE 1434687360,1434687487,NL 1434687488,1434687647,DE @@ -45321,9 +45735,7 @@ 1434689952,1434690015,NL 1434690016,1434692607,DE 1434692608,1434692671,NL -1434692672,1434693119,DE -1434693120,1434693375,NL -1434693376,1434694655,DE +1434692672,1434694655,DE 1434694656,1434694719,NL 1434694720,1434696447,DE 1434696448,1434696703,NL @@ -45334,17 +45746,18 @@ 1434702592,1434702655,DE 1434702656,1434702671,NL 1434702672,1434702783,DE -1434702784,1434702847,NL -1434702848,1434702975,DE +1434702784,1434702911,NL +1434702912,1434702975,DE 1434702976,1434703039,NL 1434703040,1434705727,DE 1434705728,1434705919,NL -1434705920,1434712063,DE +1434705920,1434710015,DE +1434710016,1434710527,NL +1434710528,1434712063,DE 1434712064,1434712319,NL 1434712320,1434712959,DE 1434712960,1434712975,NL -1434712976,1434713855,DE -1434713856,1434714111,NL +1434712976,1434714111,DE 1434714112,1434746879,AZ 1434746880,1434779647,CZ 1434779648,1434812415,GB @@ -45488,13 +45901,21 @@ 1438860288,1438860415,US 1438860416,1438861823,DE 1438861824,1438862079,CH -1438862080,1438869591,DE +1438862080,1438864827,DE +1438864828,1438864831,PA +1438864832,1438864927,DE +1438864928,1438864959,PA +1438864960,1438868295,DE +1438868296,1438868303,LT +1438868304,1438869591,DE 1438869592,1438869595,RU 1438869596,1438869647,DE 1438869648,1438869651,LV 1438869652,1438869655,US 1438869656,1438869663,UA -1438869664,1438873119,DE +1438869664,1438870783,DE +1438870784,1438871039,GB +1438871040,1438873119,DE 1438873120,1438873127,PA 1438873128,1438873671,DE 1438873672,1438873679,PA @@ -45631,23 +46052,27 @@ 1439467008,1439482367,RO 1439482368,1439482879,GB 1439482880,1439498239,RO -1439498240,1439503103,DE -1439503104,1439503359,PT -1439503360,1439514111,DE -1439514112,1439514367,GB -1439514368,1439514623,DE +1439498240,1439507199,DE +1439507200,1439507455,GB +1439507456,1439513599,DE +1439513600,1439514623,GB 1439514624,1439516671,IT 1439516672,1439518207,DE 1439518208,1439518719,IT -1439518720,1439529599,DE -1439529600,1439529727,GB -1439529728,1439529983,DE +1439518720,1439527935,DE +1439527936,1439528959,GB +1439528960,1439529983,DE 1439529984,1439530239,EG -1439530240,1439535103,DE -1439535104,1439538175,IT -1439538176,1439538687,DE +1439530240,1439530495,GB +1439530496,1439534079,DE +1439534080,1439535103,GB +1439535104,1439536127,IT +1439536128,1439537151,GB +1439537152,1439538175,IT +1439538176,1439538687,GB 1439538688,1439539199,IT -1439539200,1439549439,DE +1439539200,1439543295,DE +1439543296,1439549439,GB 1439549440,1439551487,IT 1439551488,1439556095,DE 1439556096,1439556607,IT @@ -45660,8 +46085,8 @@ 1439561216,1439561727,DE 1439561728,1439562239,GB 1439562240,1439562751,IE -1439562752,1439562879,DE -1439562880,1439563263,GB +1439562752,1439563007,DE +1439563008,1439563263,GB 1439563264,1439563775,DE 1439563776,1439629311,LT 1439629312,1439694847,CZ @@ -45718,7 +46143,9 @@ 1441389568,1441389599,LU 1441389600,1441389967,FR 1441389968,1441389983,CA -1441389984,1441390591,FR +1441389984,1441390383,FR +1441390384,1441390399,CA +1441390400,1441390591,FR 1441390592,1441398783,DK 1441398784,1441415167,RU 1441415168,1441423359,GB @@ -45754,7 +46181,11 @@ 1441546240,1441554431,DK 1441554432,1441554687,GB 1441554688,1441554943,NL -1441554944,1441557759,GB +1441554944,1441555199,GB +1441555200,1441555327,DE +1441555328,1441556735,GB +1441556736,1441556991,DE +1441556992,1441557759,GB 1441557760,1441558015,NL 1441558016,1441562623,GB 1441562624,1441564671,IQ @@ -45832,6 +46263,8 @@ 1442807808,1442811903,BG 1442811904,1442815999,AT 1442816000,1442820095,BG +1442820096,1442822143,UA +1442822144,1442824191,RU 1442824192,1442828287,BE 1442828288,1442832383,NL 1442832384,1442836479,GB @@ -45904,7 +46337,9 @@ 1446576128,1446608895,IR 1446608896,1446641663,BY 1446641664,1446674431,SI -1446674432,1446694543,DK +1446674432,1446678407,DK +1446678408,1446678411,US +1446678412,1446694543,DK 1446694544,1446694559,SE 1446694560,1446694591,DK 1446694592,1446694607,NO @@ -45919,7 +46354,9 @@ 1446710800,1446710815,MT 1446710816,1446710887,AT 1446710888,1446710895,MT -1446710896,1446712783,AT +1446710896,1446710903,AT +1446710904,1446710911,MT +1446710912,1446712783,AT 1446712784,1446712791,DE 1446712792,1446716399,AT 1446716400,1446716407,MT @@ -45942,11 +46379,10 @@ 1446904104,1446904111,IQ 1446904112,1446904119,GN 1446904120,1446904127,IQ -1446904128,1446904135,AF +1446904128,1446904135,A2 1446904136,1446904143,LY 1446904144,1446904151,ER -1446904152,1446904159,AF -1446904160,1446904231,A2 +1446904152,1446904231,A2 1446904232,1446904239,IQ 1446904240,1446904247,A2 1446904248,1446904255,AF @@ -45960,7 +46396,8 @@ 1446904400,1446904415,IQ 1446904416,1446904575,A2 1446904576,1446904591,SD -1446904592,1446904607,A2 +1446904592,1446904599,AF +1446904600,1446904607,A2 1446904608,1446904623,SD 1446904624,1446904639,A2 1446904640,1446904679,IQ @@ -45997,17 +46434,19 @@ 1446904956,1446904959,A2 1446904960,1446904963,IQ 1446904964,1446904967,TD -1446904968,1446904971,IQ +1446904968,1446904971,A2 1446904972,1446904975,LY 1446904976,1446904979,CG 1446904980,1446904983,TG 1446904984,1446904991,LY 1446904992,1446904995,IQ -1446904996,1446905007,A2 -1446905008,1446905011,CG +1446904996,1446905003,A2 +1446905004,1446905007,NG +1446905008,1446905011,A2 1446905012,1446905015,AF 1446905016,1446905019,NG -1446905020,1446905027,A2 +1446905020,1446905023,LY +1446905024,1446905027,A2 1446905028,1446905031,IQ 1446905032,1446905035,LY 1446905036,1446905039,IQ @@ -46015,8 +46454,7 @@ 1446905044,1446905047,IQ 1446905048,1446905051,LY 1446905052,1446905059,IQ -1446905060,1446905063,A2 -1446905064,1446905067,NG +1446905060,1446905067,NG 1446905068,1446905083,A2 1446905084,1446905095,AF 1446905096,1446905099,LY @@ -46029,8 +46467,8 @@ 1446905128,1446905131,IQ 1446905132,1446905139,LY 1446905140,1446905147,IQ -1446905148,1446905155,A2 -1446905156,1446905159,IQ +1446905148,1446905151,A2 +1446905152,1446905159,IQ 1446905160,1446905163,A2 1446905164,1446905171,LY 1446905172,1446905175,A2 @@ -46052,7 +46490,9 @@ 1446905244,1446905247,AF 1446905248,1446905251,A2 1446905252,1446905255,LY -1446905256,1446905271,A2 +1446905256,1446905259,A2 +1446905260,1446905263,IQ +1446905264,1446905271,A2 1446905272,1446905287,IQ 1446905288,1446905295,LY 1446905296,1446905303,IQ @@ -46061,16 +46501,20 @@ 1446905312,1446905315,EG 1446905316,1446905319,NG 1446905320,1446905331,IQ -1446905332,1446905335,A2 +1446905332,1446905335,NG 1446905336,1446905343,IQ 1446905344,1446905351,NG 1446905352,1446905383,A2 1446905384,1446905391,SD 1446905392,1446905583,A2 1446905584,1446905591,AF -1446905592,1446905619,A2 +1446905592,1446905611,A2 +1446905612,1446905615,IQ +1446905616,1446905619,A2 1446905620,1446905623,TD -1446905624,1446905635,A2 +1446905624,1446905627,A2 +1446905628,1446905631,IQ +1446905632,1446905635,A2 1446905636,1446905639,IQ 1446905640,1446905643,A2 1446905644,1446905647,IQ @@ -46080,7 +46524,8 @@ 1446905660,1446905663,ER 1446905664,1446905667,A2 1446905668,1446905675,AF -1446905676,1446905703,A2 +1446905676,1446905683,LY +1446905684,1446905703,A2 1446905704,1446905707,IQ 1446905708,1446905715,A2 1446905716,1446905719,IQ @@ -46090,8 +46535,7 @@ 1446905732,1446905735,AF 1446905736,1446905739,IQ 1446905740,1446905743,A2 -1446905744,1446905747,LY -1446905748,1446905759,A2 +1446905744,1446905759,LY 1446905760,1446905763,ML 1446905764,1446905767,A2 1446905768,1446905775,IQ @@ -46121,7 +46565,7 @@ 1446906072,1446906079,CY 1446906080,1446906111,A2 1446906112,1446906119,IQ -1446906120,1446906123,BG +1446906120,1446906123,A2 1446906124,1446906131,IQ 1446906132,1446906135,SD 1446906136,1446906151,A2 @@ -46154,7 +46598,8 @@ 1446906392,1446906399,CY 1446906400,1446906883,A2 1446906884,1446906887,AF -1446906888,1446906895,A2 +1446906888,1446906891,LY +1446906892,1446906895,A2 1446906896,1446906899,GN 1446906900,1446906915,A2 1446906916,1446906919,AF @@ -46320,8 +46765,7 @@ 1446908232,1446908235,LY 1446908236,1446908247,A2 1446908248,1446908251,AF -1446908252,1446908255,A2 -1446908256,1446908259,SZ +1446908252,1446908259,A2 1446908260,1446908263,IQ 1446908264,1446908267,A2 1446908268,1446908271,AF @@ -46433,7 +46877,9 @@ 1446909808,1446909815,A2 1446909816,1446909819,AF 1446909820,1446909827,IQ -1446909828,1446909999,A2 +1446909828,1446909967,A2 +1446909968,1446909971,LY +1446909972,1446909999,A2 1446910000,1446910003,AF 1446910004,1446910019,A2 1446910020,1446910023,IQ @@ -46489,8 +46935,8 @@ 1446910728,1446910731,AF 1446910732,1446910739,A2 1446910740,1446910747,AF -1446910748,1446910771,A2 -1446910772,1446910775,AF +1446910748,1446910767,A2 +1446910768,1446910775,AF 1446910776,1446910791,A2 1446910792,1446910795,LY 1446910796,1446910799,A2 @@ -46539,9 +46985,7 @@ 1446911144,1446911147,TD 1446911148,1446911163,A2 1446911164,1446911171,IQ -1446911172,1446911183,A2 -1446911184,1446911187,AF -1446911188,1446911207,A2 +1446911172,1446911207,A2 1446911208,1446911215,IQ 1446911216,1446911223,A2 1446911224,1446911227,AF @@ -46799,7 +47243,10 @@ 1450090496,1450106879,RU 1450106880,1450115071,SK 1450115072,1450123263,RU -1450123264,1450131455,AT +1450123264,1450125231,AT +1450125232,1450125239,DE +1450125240,1450125247,US +1450125248,1450131455,AT 1450131456,1450139647,UA 1450139648,1450147839,PL 1450147840,1450151935,CH @@ -46880,8 +47327,7 @@ 1466592256,1466592511,FR 1466592512,1466592767,GB 1466592768,1466592895,FR -1466592896,1466593023,DE -1466593024,1466593279,GB +1466592896,1466593279,GB 1466593280,1466604799,DE 1466604800,1466605055,ES 1466605056,1466606847,DE @@ -46921,8 +47367,7 @@ 1467367616,1467367647,SE 1467367648,1467367679,DE 1467367680,1467367695,IT -1467367696,1467367807,DE -1467367808,1467367871,CZ +1467367696,1467367871,DE 1467367872,1467367903,SE 1467367904,1467367935,DE 1467367936,1467368191,SI @@ -46931,9 +47376,7 @@ 1467368448,1467368703,DK 1467368704,1467369519,DE 1467369520,1467369535,RU -1467369536,1467369599,DE -1467369600,1467369663,IT -1467369664,1467369759,DE +1467369536,1467369759,DE 1467369760,1467369791,HR 1467369792,1467369855,SE 1467369856,1467369871,RU @@ -47056,7 +47499,7 @@ 1475131392,1475133439,RU 1475133440,1475135487,CZ 1475135488,1475137535,CH -1475137536,1475139583,IR +1475137536,1475139583,GB 1475139584,1475141631,ES 1475141632,1475143679,FI 1475143680,1475145727,JO @@ -47136,9 +47579,7 @@ 1475223552,1475229695,NO 1475229696,1475229759,SE 1475229760,1475229951,NO -1475229952,1475230175,SE -1475230176,1475230191,NO -1475230192,1475230207,SE +1475229952,1475230207,SE 1475230208,1475233791,NO 1475233792,1475234303,GB 1475234304,1475234559,IE @@ -47150,9 +47591,7 @@ 1475242240,1475243775,FR 1475243776,1475244031,MC 1475244032,1475244287,DE -1475244288,1475244311,SD -1475244312,1475244319,DE -1475244320,1475244543,SD +1475244288,1475244543,SD 1475244544,1475245183,DE 1475245184,1475245311,SD 1475245312,1475246079,DE @@ -47249,8 +47688,8 @@ 1475592192,1475608575,GB 1475608576,1475624959,RU 1475624960,1475627519,JE -1475627520,1475627662,GB -1475627663,1475627663,JE +1475627520,1475627655,GB +1475627656,1475627663,JE 1475627664,1475627688,GB 1475627689,1475627695,JE 1475627696,1475627775,GB @@ -47271,13 +47710,9 @@ 1475636432,1475636447,JE 1475636448,1475636479,GB 1475636480,1475636735,JE -1475636736,1475637479,GB -1475637480,1475637487,JE -1475637488,1475637503,GB +1475636736,1475637503,GB 1475637504,1475638783,JE -1475638784,1475639039,GB -1475639040,1475639047,JE -1475639048,1475639182,GB +1475638784,1475639182,GB 1475639183,1475639183,JE 1475639184,1475639216,GB 1475639217,1475639223,JE @@ -47292,9 +47727,7 @@ 1475639528,1475639543,JE 1475639544,1475639595,GB 1475639596,1475639599,JE -1475639600,1475639775,GB -1475639776,1475639783,JE -1475639784,1475639807,GB +1475639600,1475639807,GB 1475639808,1475641343,JE 1475641344,1475657727,UA 1475657728,1475674111,SK @@ -47303,11 +47736,13 @@ 1475706880,1475723263,RU 1475723264,1475725311,CY 1475725312,1475725951,RU -1475725952,1475726463,GB +1475725952,1475726207,GB +1475726208,1475726335,RU +1475726336,1475726463,GB 1475726464,1475726527,RU 1475726528,1475726591,GB -1475726592,1475726719,RU -1475726720,1475727103,GB +1475726592,1475726847,RU +1475726848,1475727103,GB 1475727104,1475727167,RU 1475727168,1475727343,GB 1475727344,1475727359,RU @@ -47324,7 +47759,33 @@ 1475729152,1475729215,AT 1475729216,1475729407,GB 1475729408,1475731455,UA -1475731456,1475739647,GB +1475731456,1475732479,GB +1475732480,1475732991,RU +1475732992,1475734783,GB +1475734784,1475734911,UA +1475734912,1475735295,GB +1475735296,1475735551,UA +1475735552,1475735807,US +1475735808,1475735999,RU +1475736000,1475736063,GB +1475736064,1475736127,LV +1475736128,1475736191,EE +1475736192,1475736255,GB +1475736256,1475736319,HU +1475736320,1475736447,RU +1475736448,1475736575,UA +1475736576,1475736831,RU +1475736832,1475736959,GB +1475736960,1475737023,FR +1475737024,1475737087,PL +1475737088,1475737151,NL +1475737152,1475737215,CZ +1475737216,1475737279,DE +1475737280,1475737343,AT +1475737344,1475737599,UA +1475737600,1475737855,FI +1475737856,1475738111,SE +1475738112,1475739647,RU 1475739648,1475756031,BG 1475756032,1475772415,GB 1475772416,1475788799,LV @@ -47498,7 +47959,7 @@ 1481984128,1481984255,PA 1481984256,1481984383,NL 1481984384,1481984511,GI -1481984512,1481984639,SC +1481984512,1481984639,CY 1481984640,1481985023,NL 1481985024,1481985279,MT 1481985280,1481987327,NL @@ -47610,11 +48071,9 @@ 1486317568,1486320383,RU 1486320384,1486320639,US 1486320640,1486321663,RU -1486321664,1486323711,EU 1486323712,1486325759,GB 1486325760,1486327807,PL 1486327808,1486329855,CH -1486329856,1486331903,FR 1486331904,1486333951,NO 1486333952,1486335999,SE 1486336000,1486338047,KZ @@ -47808,10 +48267,10 @@ 1489731584,1489764351,BG 1489764352,1489797119,RU 1489797120,1489829887,KZ -1489829888,1489855503,DE +1489829888,1489855495,DE +1489855496,1489855503,CH 1489855504,1489855519,RU -1489855520,1489855535,PL -1489855536,1489855543,DE +1489855520,1489855543,DE 1489855544,1489855551,PL 1489855552,1489855583,DE 1489855584,1489855615,RU @@ -47825,9 +48284,9 @@ 1489993728,1490026495,LU 1490026496,1490028543,US 1490028544,1490029055,UA -1490029056,1490041087,NL -1490041088,1490041343,UA -1490041344,1490042879,NL +1490029056,1490040855,NL +1490040856,1490040863,UA +1490040864,1490042879,NL 1490042880,1490049879,CZ 1490049880,1490049887,AT 1490049888,1490049919,CZ @@ -48095,12 +48554,16 @@ 1495236608,1495237247,AT 1495237248,1495237255,EU 1495237256,1495237271,AT -1495237272,1495237375,EU +1495237272,1495237311,EU +1495237312,1495237319,AT +1495237320,1495237375,EU 1495237376,1495237711,AT 1495237712,1495237727,NL 1495237728,1495237731,AT -1495237732,1495237759,EU -1495237760,1495237775,AT +1495237732,1495237739,EU +1495237740,1495237743,AT +1495237744,1495237751,EU +1495237752,1495237775,AT 1495237776,1495237887,EU 1495237888,1495238207,AT 1495238208,1495238223,EU @@ -48121,7 +48584,25 @@ 1495242144,1495242151,ES 1495242152,1495242159,IT 1495242160,1495242167,PL -1495242168,1495242751,FR +1495242168,1495242175,FR +1495242176,1495242183,GB +1495242184,1495242191,IE +1495242192,1495242199,DK +1495242200,1495242207,CZ +1495242208,1495242215,GR +1495242216,1495242223,PT +1495242224,1495242231,RO +1495242232,1495242367,FR +1495242368,1495242375,HU +1495242376,1495242383,BG +1495242384,1495242391,SK +1495242392,1495242399,LT +1495242400,1495242407,LV +1495242408,1495242415,SI +1495242416,1495242423,EE +1495242424,1495242431,FI +1495242432,1495242439,SE +1495242440,1495242751,FR 1495242752,1495244799,MK 1495244800,1495246847,CZ 1495246848,1495248895,IE @@ -48162,7 +48643,7 @@ 1495891968,1495927295,RO 1495927296,1495927551,AE 1495927552,1495937023,RO -1495937024,1495937535,ES +1495937024,1495937535,SE 1495937536,1495990271,RO 1495990272,1495994367,GB 1495994368,1496078335,RO @@ -48195,9 +48676,7 @@ 1500078080,1500086271,GB 1500086272,1500094463,RU 1500094464,1500102655,AT -1500102656,1500104063,NL -1500104064,1500104071,DE -1500104072,1500106527,NL +1500102656,1500106527,NL 1500106528,1500106559,DE 1500106560,1500107415,NL 1500107416,1500107423,DE @@ -48209,8 +48688,8 @@ 1500107944,1500107951,DE 1500107952,1500107999,NL 1500108000,1500108007,BE -1500108008,1500108095,NL -1500108096,1500108287,DE +1500108008,1500108159,NL +1500108160,1500108287,DE 1500108288,1500108319,NL 1500108320,1500108351,DE 1500108352,1500108367,NL @@ -48350,9 +48829,15 @@ 1502691680,1502691711,SE 1502691712,1502702835,GB 1502702836,1502702839,IE -1502702840,1502706623,GB +1502702840,1502703103,GB +1502703104,1502703615,SE +1502703616,1502706623,GB 1502706624,1502706687,CY 1502706688,1502707711,GB +1502707712,1502715903,RU +1502715904,1502717951,IT +1502717952,1502719999,GB +1502720000,1502722047,CH 1502724096,1502740479,GB 1502740480,1502756863,NL 1502756864,1502773247,UZ @@ -48519,8 +49004,7 @@ 1503898352,1503898359,CH 1503898360,1503898415,DE 1503898416,1503898423,BE -1503898424,1503898431,CH -1503898432,1503898503,DE +1503898424,1503898503,DE 1503898504,1503898511,GR 1503898512,1503898567,DE 1503898568,1503898575,NL @@ -48529,9 +49013,7 @@ 1503898608,1503898615,GR 1503898616,1503898631,DE 1503898632,1503898647,GR -1503898648,1503898679,DE -1503898680,1503898687,IT -1503898688,1503898791,DE +1503898648,1503898791,DE 1503898792,1503898799,US 1503898800,1503898815,DE 1503898816,1503898831,GB @@ -48571,7 +49053,14 @@ 1503899352,1503899367,GR 1503899368,1503899399,DE 1503899400,1503899407,CH -1503899408,1503908351,DE +1503899408,1503899423,DE +1503899424,1503899431,IT +1503899432,1503899439,GR +1503899440,1503899463,DE +1503899464,1503899479,BR +1503899480,1503899495,DE +1503899496,1503899503,IT +1503899504,1503908351,DE 1503908352,1503909375,IT 1503909376,1503920127,DE 1503920128,1503985663,HR @@ -48654,8 +49143,8 @@ 1505321664,1505321823,DE 1505321824,1505321831,AT 1505321832,1505321983,DE -1505321984,1505322287,AT -1505322288,1505322415,DE +1505321984,1505322303,AT +1505322304,1505322415,DE 1505322416,1505322895,AT 1505322896,1505324335,DE 1505324336,1505324367,AT @@ -48676,11 +49165,15 @@ 1505333624,1505333631,GB 1505333632,1505333887,IE 1505333888,1505333951,GB -1505333952,1505336063,IE +1505333952,1505335871,IE +1505335872,1505335911,GB +1505335912,1505336063,IE 1505336064,1505336071,GB 1505336072,1505336576,IE 1505336577,1505336639,GB -1505336640,1505336823,IE +1505336640,1505336655,IE +1505336656,1505336663,GB +1505336664,1505336823,IE 1505336824,1505336863,GB 1505336864,1505336864,IE 1505336865,1505336879,GB @@ -48841,19 +49334,26 @@ 1506418704,1506418719,CA 1506418720,1506418975,DE 1506418976,1506418983,CA -1506418984,1506422655,DE +1506418984,1506422079,DE +1506422080,1506422111,CY +1506422112,1506422142,CA +1506422143,1506422655,DE 1506422656,1506422687,CY 1506422688,1506422703,CA -1506422704,1506422711,GB -1506422712,1506422719,DE +1506422704,1506422719,GB 1506422720,1506422751,US -1506422752,1506427663,DE +1506422752,1506427183,DE +1506427184,1506427199,CA +1506427200,1506427663,DE 1506427664,1506427679,GB -1506427680,1506428223,DE +1506427680,1506427743,DE +1506427744,1506427759,CA +1506427760,1506428223,DE 1506428224,1506428239,US 1506428240,1506436863,DE 1506436864,1506436879,FR -1506436880,1506437119,DE +1506436880,1506436883,GB +1506436884,1506437119,DE 1506437120,1506437503,US 1506437504,1506437551,DE 1506437552,1506437567,BG @@ -48975,14 +49475,12 @@ 1506445824,1506446143,FR 1506446144,1506446151,GB 1506446152,1506446335,FR -1506446336,1506446599,NL -1506446600,1506446623,GB -1506446624,1506446719,NL +1506446336,1506446719,NL 1506446720,1506446735,GB 1506446736,1506447359,NL 1506447360,1506447423,IT -1506447424,1506447455,GB -1506447456,1506448255,IT +1506447424,1506447463,GB +1506447464,1506448255,IT 1506448256,1506448319,GB 1506448320,1506448383,IT 1506448384,1506448639,AT @@ -49092,8 +49590,7 @@ 1506462528,1506462583,GB 1506462584,1506462599,FR 1506462600,1506462607,GB -1506462608,1506462623,A2 -1506462624,1506462719,FR +1506462608,1506462719,FR 1506462720,1506463231,IT 1506463232,1506463487,SE 1506463488,1506463671,DE @@ -49110,7 +49607,11 @@ 1506466632,1506467071,GB 1506467072,1506467327,DE 1506467328,1506467583,GB -1506467584,1506468351,IT +1506467584,1506467591,IT +1506467592,1506467615,GB +1506467616,1506467647,IT +1506467648,1506467839,GB +1506467840,1506468351,IT 1506468352,1506468607,GB 1506468608,1506468863,TZ 1506468864,1506470143,IT @@ -49134,8 +49635,8 @@ 1506474256,1506474495,IT 1506474496,1506474751,FR 1506474752,1506475519,IT -1506475520,1506475559,AT -1506475560,1506475775,GB +1506475520,1506475567,AT +1506475568,1506475775,GB 1506475776,1506476031,DE 1506476032,1506508799,KW 1506508800,1506541567,CZ @@ -49152,8 +49653,7 @@ 1506743168,1506743183,DE 1506743184,1506743199,FR 1506743200,1506743215,IE -1506743216,1506743232,GB -1506743233,1506744319,SE +1506743216,1506744319,SE 1506744320,1506744383,NL 1506744384,1506744391,GB 1506744392,1506746367,NL @@ -49183,8 +49683,7 @@ 1506772148,1506772176,TR 1506772177,1506772323,NL 1506772324,1506772325,IR -1506772326,1506772326,RO -1506772327,1506772361,NL +1506772326,1506772361,NL 1506772362,1506772364,IR 1506772365,1506772938,NL 1506772939,1506772939,IR @@ -49256,7 +49755,9 @@ 1507713024,1507717119,RU 1507717120,1507717631,SE 1507717632,1507718911,NO -1507718912,1507721215,SE +1507718912,1507720191,SE +1507720192,1507720447,NO +1507720448,1507721215,SE 1507721216,1507753983,GB 1507753984,1507819519,RU 1507819520,1507852287,HU @@ -49321,9 +49822,7 @@ 1508787200,1508787455,ES 1508787456,1508788031,DE 1508788032,1508788063,BE -1508788064,1508792063,DE -1508792064,1508792318,GB -1508792319,1508802559,DE +1508788064,1508802559,DE 1508802560,1508804783,GB 1508804784,1508804791,DE 1508804792,1508805119,GB @@ -49364,9 +49863,7 @@ 1509467840,1509467871,PL 1509467872,1509469055,NL 1509469056,1509469183,PL -1509469184,1509469439,NL -1509469440,1509469567,SE -1509469568,1509469887,NL +1509469184,1509469887,NL 1509469888,1509469919,MY 1509469920,1509470207,NL 1509470208,1509478399,RU @@ -49400,9 +49897,7 @@ 1509580800,1509584895,CZ 1509584896,1509588479,NO 1509588480,1509588607,GB -1509588608,1509588751,NO -1509588752,1509588767,GB -1509588768,1509588991,NO +1509588608,1509588991,NO 1509588992,1509593087,DE 1509593088,1509601279,RU 1509601280,1509605375,NL @@ -49466,7 +49961,9 @@ 1518370816,1518403583,NL 1518403584,1518452735,SE 1518452736,1518460927,AT -1518460928,1518501887,SE +1518460928,1518479359,SE +1518479360,1518481407,EE +1518481408,1518501887,SE 1518501888,1518503935,EE 1518503936,1518508799,LT 1518508800,1518510079,SE @@ -49723,7 +50220,6 @@ 1533431808,1533433855,IE 1533433856,1533435903,DK 1533435904,1533437951,CZ -1533437952,1533439999,RU 1533440000,1533441519,PL 1533441520,1533441535,CH 1533441536,1533442047,PL @@ -49788,9 +50284,7 @@ 1533542400,1534066687,GB 1534066688,1534129151,AT 1534129152,1534129407,A2 -1534129408,1534202591,AT -1534202592,1534202595,ES -1534202596,1534328831,AT +1534129408,1534328831,AT 1534328832,1534459903,ES 1534459904,1534482091,AT 1534482092,1534482095,GB @@ -49909,7 +50403,8 @@ 1534715368,1534715371,FR 1534715372,1534715375,CH 1534715376,1534715391,ES -1534715392,1534715407,PL +1534715392,1534715399,PL +1534715400,1534715407,FR 1534715408,1534715411,GB 1534715412,1534715415,FI 1534715416,1534715419,DE @@ -49944,7 +50439,7 @@ 1534715784,1534715791,BE 1534715792,1534715807,ES 1534715808,1534715875,FR -1534715876,1534715879,NL +1534715876,1534715879,GB 1534715880,1534715883,PT 1534715884,1534715887,PL 1534715888,1534715919,FR @@ -49965,8 +50460,10 @@ 1534716224,1534716239,FR 1534716240,1534716255,GB 1534716256,1534716319,FR -1534716320,1534716359,PL -1534716360,1534716363,CZ +1534716320,1534716351,PL +1534716352,1534716355,FR +1534716356,1534716359,PL +1534716360,1534716363,FR 1534716364,1534716367,GB 1534716368,1534716375,BE 1534716376,1534716379,CH @@ -49979,8 +50476,8 @@ 1534716448,1534716479,FR 1534716480,1534716495,ES 1534716496,1534716575,FR -1534716576,1534716607,PL -1534716608,1534716639,FR +1534716576,1534716591,PL +1534716592,1534716639,FR 1534716640,1534716647,BE 1534716648,1534716655,FR 1534716656,1534716663,IE @@ -50010,7 +50507,9 @@ 1534717008,1534717011,PL 1534717012,1534717019,FR 1534717020,1534717023,DE -1534717024,1534717055,PL +1534717024,1534717039,GB +1534717040,1534717047,PL +1534717048,1534717055,FR 1534717056,1534717071,GB 1534717072,1534717103,FR 1534717104,1534717119,PL @@ -50019,7 +50518,9 @@ 1534717140,1534717143,BE 1534717144,1534717147,FR 1534717148,1534717151,IT -1534717152,1534717247,FR +1534717152,1534717215,FR +1534717216,1534717219,ES +1534717220,1534717247,FR 1534717248,1534717251,CZ 1534717252,1534717255,NL 1534717256,1534717263,FR @@ -50074,10 +50575,9 @@ 1534717920,1534717923,PL 1534717924,1534717927,ES 1534717928,1534717931,DE -1534717932,1534717935,FR -1534717936,1534717951,IT +1534717932,1534717951,FR 1534717952,1534717955,DE -1534717956,1534717959,BE +1534717956,1534717959,FR 1534717960,1534717963,PT 1534717964,1534717967,CH 1534717968,1534717983,IT @@ -50106,12 +50606,13 @@ 1534718416,1534718419,CZ 1534718420,1534718423,GB 1534718424,1534718431,ES -1534718432,1534718447,PL +1534718432,1534718435,GB +1534718436,1534718439,DE +1534718440,1534718447,ES 1534718448,1534718463,FR 1534718464,1534718467,DE 1534718468,1534718471,PT -1534718472,1534718479,FR -1534718480,1534718487,PL +1534718472,1534718487,PL 1534718488,1534718495,DE 1534718496,1534718531,FR 1534718532,1534718535,PL @@ -50120,15 +50621,19 @@ 1534718544,1534718559,FR 1534718560,1534718575,BE 1534718576,1534718591,GB -1534718592,1534718687,FR +1534718592,1534718623,FR +1534718624,1534718631,PL +1534718632,1534718687,FR 1534718688,1534718703,PL 1534718704,1534718711,FR 1534718712,1534718719,ES 1534718720,1534718735,GB -1534718736,1534718751,FR -1534718752,1534718767,PL -1534718768,1534718799,FR -1534718800,1534718815,ES +1534718736,1534718739,NL +1534718740,1534718759,FR +1534718760,1534718763,PL +1534718764,1534718767,IE +1534718768,1534718783,FR +1534718784,1534718815,ES 1534718816,1534718831,GB 1534718832,1534718847,FR 1534718848,1534718911,BE @@ -50149,8 +50654,7 @@ 1534719392,1534719395,CH 1534719396,1534719399,PT 1534719400,1534719403,IT -1534719404,1534719423,FR -1534719424,1534719439,DE +1534719404,1534719439,FR 1534719440,1534719459,PL 1534719460,1534719463,FR 1534719464,1534719471,PL @@ -50165,7 +50669,9 @@ 1534719696,1534719699,IT 1534719700,1534719703,DE 1534719704,1534719711,GB -1534719712,1534719759,FR +1534719712,1534719747,FR +1534719748,1534719751,PL +1534719752,1534719759,FR 1534719760,1534719775,IT 1534719776,1534719783,PL 1534719784,1534719787,FR @@ -50211,7 +50717,9 @@ 1534720400,1534720403,LT 1534720404,1534720411,GB 1534720412,1534720415,IE -1534720416,1534720431,FR +1534720416,1534720419,ES +1534720420,1534720423,DE +1534720424,1534720431,ES 1534720432,1534720435,DE 1534720436,1534720439,FR 1534720440,1534720443,GB @@ -50267,7 +50775,8 @@ 1534721000,1534721003,FI 1534721004,1534721007,GB 1534721008,1534721023,ES -1534721024,1534721055,FR +1534721024,1534721031,DE +1534721032,1534721055,FR 1534721056,1534721063,ES 1534721064,1534721071,FR 1534721072,1534721087,GB @@ -50308,14 +50817,18 @@ 1534721528,1534721531,ES 1534721532,1534721567,FR 1534721568,1534721583,GB -1534721584,1534721599,FR -1534721600,1534721619,ES +1534721584,1534721587,IE +1534721588,1534721595,FR +1534721596,1534721619,ES 1534721620,1534721627,PL 1534721628,1534721631,NL 1534721632,1534721647,ES 1534721648,1534721663,FR 1534721664,1534721679,ES -1534721680,1534721743,FR +1534721680,1534721695,FR +1534721696,1534721703,PL +1534721704,1534721711,DE +1534721712,1534721743,FR 1534721744,1534721747,PL 1534721748,1534721751,GB 1534721752,1534721755,DE @@ -50338,7 +50851,9 @@ 1534721968,1534721971,DE 1534721972,1534721975,PL 1534721976,1534721979,ES -1534721980,1534722007,PL +1534721980,1534721983,PL +1534721984,1534721999,FR +1534722000,1534722007,PL 1534722008,1534722011,PT 1534722012,1534722015,ES 1534722016,1534722039,FR @@ -50399,7 +50914,9 @@ 1535635456,1535639551,AZ 1535639552,1535672319,GB 1535672320,1535705087,DE -1535705088,1535720447,CH +1535705088,1535708671,CH +1535708672,1535709694,DE +1535709695,1535720447,CH 1535720448,1535720575,DE 1535720576,1535720703,CH 1535720704,1535720831,DE @@ -50490,6 +51007,10 @@ 1536262144,1536278527,PL 1536278528,1536294911,UA 1536294912,1536311295,RU +1536311296,1536319487,EE +1536319488,1536321535,ES +1536321536,1536325631,GB +1536325632,1536327679,CZ 1536327680,1536344063,HU 1536344064,1536360447,PL 1536360448,1536376831,RU @@ -50705,7 +51226,9 @@ 1539227648,1539229695,FI 1539229696,1539231743,DE 1539231744,1539233791,BE -1539233792,1539235839,LU +1539233792,1539234303,LU +1539234304,1539234559,IE +1539234560,1539235839,LU 1539235840,1539237887,DE 1539237888,1539239935,RU 1539239936,1539244031,DE @@ -51086,6 +51609,7 @@ 1539593216,1539594239,RU 1539594240,1539598335,UA 1539598336,1539599359,NL +1539599360,1539600383,PL 1539600384,1539601407,HU 1539601408,1539602431,GB 1539602432,1539603455,UA @@ -51186,7 +51710,6 @@ 1539706624,1539707135,PL 1539707136,1539707391,LT 1539707392,1539707647,GB -1539707648,1539707903,RO 1539707904,1539708159,UA 1539708160,1539708415,DE 1539708416,1539708671,GB @@ -51346,6 +51869,7 @@ 1539750400,1539750655,PL 1539750656,1539750911,DE 1539750912,1539751167,UA +1539751168,1539751423,AT 1539751424,1539751679,SI 1539751680,1539751935,FR 1539751936,1539752191,DE @@ -51572,6 +52096,7 @@ 1539812096,1539812351,RU 1539812352,1539812607,CH 1539812608,1539812863,IT +1539812864,1539813119,RU 1539813120,1539813375,AT 1539813376,1539813631,PL 1539813632,1539813887,NL @@ -51666,7 +52191,6 @@ 1539857408,1539858431,PL 1539858432,1539859455,RO 1539859456,1539860479,DE -1539860480,1539861503,UA 1539861504,1539862527,DE 1539862528,1539863551,UA 1539863552,1539864575,ES @@ -51743,7 +52267,6 @@ 1539947520,1539948543,UA 1539948544,1539949567,RO 1539949568,1539950591,MD -1539950592,1539951103,KZ 1539951104,1539951615,UA 1539951616,1539953663,RU 1539953664,1539954687,UA @@ -51998,6 +52521,8 @@ 1540248576,1540249087,GB 1540249088,1540249599,PL 1540249600,1540250111,KZ +1540250112,1540250367,PL +1540250368,1540250623,CZ 1540250624,1540251135,RU 1540251136,1540251647,GB 1540251648,1540252159,PL @@ -52195,6 +52720,7 @@ 1540361472,1540361727,DE 1540361728,1540361983,IT 1540361984,1540362239,EE +1540362240,1540362495,RU 1540362496,1540363007,DE 1540363008,1540363263,FR 1540363264,1540363519,RU @@ -52476,7 +53002,7 @@ 1540440064,1540440319,UA 1540440320,1540440575,RU 1540440576,1540440831,MD -1540440832,1540441087,FR +1540440832,1540441087,GB 1540441088,1540441343,PL 1540441344,1540441855,RU 1540441856,1540442111,GB @@ -52554,13 +53080,14 @@ 1540462592,1540463103,PL 1540463104,1540463359,FR 1540463360,1540463615,PL +1540463616,1540463871,DK 1540463872,1540464127,UA 1540464128,1540464383,CH 1540464384,1540464895,DE 1540464896,1540465407,GB 1540465408,1540465663,ES 1540465664,1540465919,NL -1540465920,1540466175,UA +1540465920,1540466175,RU 1540466176,1540466431,DK 1540466432,1540466687,RU 1540466688,1540466943,NL @@ -52637,7 +53164,7 @@ 1540487168,1540487423,PS 1540487424,1540487679,UA 1540487680,1540487935,DE -1540487936,1540488447,GB +1540488192,1540488447,GB 1540488448,1540488703,SA 1540488704,1540488959,DE 1540488960,1540489215,RO @@ -52860,12 +53387,10 @@ 1540651776,1540652031,RU 1540652032,1540652543,UA 1540652544,1540652799,TR -1540652800,1540653055,EU 1540653056,1540653311,FR 1540653312,1540653567,DK 1540653568,1540653823,DE 1540653824,1540654079,GB -1540654080,1540654335,RS 1540654336,1540654591,RU 1540654592,1540654847,SI 1540654848,1540655103,RU @@ -52885,7 +53410,6 @@ 1540659456,1540659967,UA 1540659968,1540660223,PL 1540660480,1540660735,FR -1540660736,1540660991,UA 1540660992,1540661247,RO 1540661248,1540661503,GB 1540661504,1540662015,RO @@ -52930,7 +53454,7 @@ 1540673280,1540673535,SE 1540673536,1540673791,SI 1540673792,1540674047,SE -1540674048,1540674303,GB +1540674048,1540674303,NL 1540674304,1540674559,FR 1540674560,1540674815,GB 1540674816,1540675071,GE @@ -53516,7 +54040,7 @@ 1540940800,1540941055,FR 1540941056,1540941311,CH 1540941312,1540941567,AT -1540941568,1540941823,UA +1540941568,1540942079,UA 1540942080,1540942335,RO 1540942336,1540942591,FR 1540942592,1540942847,DE @@ -53575,7 +54099,7 @@ 1540966912,1540967935,RU 1540967936,1540968447,UA 1540968448,1540969471,RO -1540969472,1540969983,GB +1540969472,1540969983,NL 1540969984,1540970495,DE 1540970496,1540971007,IE 1540971008,1540971519,UA @@ -54395,6 +54919,7 @@ 1541384704,1541384959,RU 1541384960,1541385215,PL 1541385216,1541385471,NL +1541385472,1541385727,SK 1541385728,1541385983,SI 1541385984,1541386239,PL 1541386240,1541386495,RU @@ -54440,7 +54965,6 @@ 1541396480,1541396735,UA 1541396736,1541396991,RU 1541396992,1541397247,GB -1541397248,1541397503,FR 1541397504,1541397759,NL 1541397760,1541398015,PL 1541398016,1541398271,HU @@ -54770,7 +55294,7 @@ 1541622528,1541622783,NL 1541622784,1541623295,PL 1541623296,1541623551,GB -1541623552,1541623679,RU +1541623552,1541623807,RU 1541623808,1541624831,PL 1541624832,1541625855,RU 1541625856,1541626367,PL @@ -54943,6 +55467,7 @@ 1541728000,1541728255,UA 1541728256,1541729023,GB 1541729024,1541729279,DE +1541729280,1541729535,UA 1541729536,1541729791,PL 1541729792,1541730303,RU 1541730304,1541730815,ES @@ -55039,7 +55564,7 @@ 1541779968,1541780479,DE 1541780480,1541780735,ES 1541780736,1541780991,GB -1541780992,1541781247,RO +1541780992,1541781503,RO 1541781504,1541781759,TR 1541781760,1541782015,RU 1541782016,1541782271,RO @@ -55055,6 +55580,7 @@ 1541787648,1541788159,RU 1541788160,1541788415,UA 1541788416,1541788671,RU +1541788672,1541789183,PL 1541789184,1541789695,IR 1541789696,1541790719,UA 1541790720,1541790975,SA @@ -55074,8 +55600,9 @@ 1541795584,1541795839,ES 1541795840,1541796863,UA 1541796864,1541797375,RU -1541797376,1541797887,GB +1541797376,1541797887,NL 1541797888,1541798143,UA +1541798144,1541798399,PL 1541798400,1541798911,RO 1541798912,1541799935,CZ 1541799936,1541800447,FR @@ -55239,6 +55766,105 @@ 1541879808,1541880831,UZ 1541880832,1541881343,PL 1541881344,1541881599,IT +1541881600,1541881855,SE +1541881856,1541882879,RU +1541882880,1541883135,LV +1541883136,1541883391,UA +1541883392,1541884927,PL +1541884928,1541885951,LT +1541885952,1541886975,PL +1541886976,1541887999,UA +1541888000,1541888255,RS +1541888256,1541888511,RU +1541888512,1541889023,GB +1541889024,1541889535,PL +1541889536,1541890303,RU +1541890304,1541890559,DE +1541890560,1541891071,UA +1541891072,1541893119,PL +1541893120,1541893631,BE +1541893632,1541894143,PL +1541894144,1541895167,RU +1541895168,1541897727,PL +1541897728,1541897983,RU +1541897984,1541898239,UA +1541898240,1541900799,RU +1541900800,1541901055,RO +1541901056,1541901311,FR +1541901312,1541901567,PL +1541901568,1541901823,RU +1541901824,1541902335,UA +1541902336,1541902847,GB +1541902848,1541903103,RU +1541903104,1541903359,DK +1541903360,1541904383,UA +1541904384,1541904639,PL +1541904640,1541904895,SE +1541904896,1541905407,GB +1541905408,1541905663,RU +1541905664,1541906431,RO +1541906432,1541906687,UA +1541906688,1541907455,RU +1541907456,1541908479,IT +1541908480,1541908991,PL +1541908992,1541909247,UA +1541909248,1541909503,CZ +1541909504,1541910527,NL +1541910528,1541911039,RU +1541911040,1541911295,PL +1541911296,1541911551,IT +1541911552,1541912575,RU +1541912576,1541912831,NL +1541912832,1541913087,UA +1541913088,1541914623,RU +1541914624,1541915647,IL +1541915648,1541916671,RU +1541916672,1541917695,RO +1541917696,1541917951,CH +1541917952,1541918207,PL +1541918208,1541918463,UA +1541918464,1541919743,RO +1541919744,1541919999,DK +1541920000,1541920767,RU +1541920768,1541921279,PT +1541921280,1541921791,RU +1541921792,1541922047,DE +1541922048,1541922303,PL +1541922304,1541922559,RU +1541922560,1541923839,RO +1541923840,1541924095,FR +1541924096,1541924351,UA +1541924352,1541924863,PL +1541924864,1541925119,RO +1541925120,1541926911,RU +1541926912,1541927167,UA +1541927168,1541927679,PL +1541927680,1541927935,DE +1541927936,1541929983,PL +1541929984,1541931007,RU +1541931008,1541932031,UA +1541932032,1541932543,PL +1541932544,1541935103,RU +1541935104,1541936383,RO +1541936384,1541936639,UA +1541936640,1541936895,DE +1541936896,1541937151,FR +1541937152,1541937663,NL +1541937664,1541937919,GE +1541937920,1541938175,PL +1541938176,1541939199,UA +1541939200,1541939967,RU +1541939968,1541940223,ES +1541940224,1541940479,GB +1541940480,1541940735,CH +1541940736,1541940991,PL +1541940992,1541941247,RU +1541941248,1541942271,FR +1541942272,1541944831,PL +1541944832,1541945087,DE +1541945088,1541945855,RO +1541945856,1541946111,PL +1541946112,1541946879,SE 1543503872,1545601023,GB 1545601024,1545673167,SE 1545673168,1545673175,FI @@ -55395,7 +56021,9 @@ 1546878976,1546895359,DE 1546895360,1546911743,IE 1546911744,1546928127,SK -1546928128,1546944511,GB +1546928128,1546929407,GB +1546929408,1546929415,A2 +1546929416,1546944511,GB 1546944512,1546960895,UA 1546960896,1546977279,HU 1546977280,1546993663,MK @@ -55439,7 +56067,7 @@ 1547522048,1547526143,CZ 1547526144,1547534335,HU 1547534336,1547538431,FR -1547538432,1547542527,DE +1547538432,1547542527,EU 1547542528,1547546623,FR 1547546624,1547550719,IR 1547550720,1547554815,IE @@ -55595,7 +56223,8 @@ 1547623736,1547624447,A2 1547624448,1547628543,CZ 1547628544,1547632639,BG -1547632640,1547636735,TR +1547632640,1547634687,GB +1547634688,1547636735,TR 1547636736,1547640831,SI 1547640832,1547644927,PL 1547644928,1547649023,CZ @@ -55620,7 +56249,11 @@ 1548157120,1548157183,DE 1548157184,1548157951,NL 1548157952,1548158207,SE -1548158208,1548222463,NL +1548158208,1548158623,NL +1548158624,1548158639,DE +1548158640,1548158975,NL +1548158976,1548159103,DE +1548159104,1548222463,NL 1548222464,1548746751,DE 1548746752,1549271039,RO 1549271040,1549795327,FR @@ -55917,22 +56550,24 @@ 1566400920,1566400923,NE 1566400924,1566400943,NO 1566400944,1566400955,NE -1566400956,1566400975,NO -1566400976,1566400979,GB +1566400956,1566400967,NO +1566400968,1566400979,GB 1566400980,1566400983,GE 1566400984,1566400987,NE 1566400988,1566401023,NO 1566401024,1566401055,US 1566401056,1566401087,NO -1566401088,1566401215,US -1566401216,1566401279,NO -1566401280,1566401327,US -1566401328,1566401399,NO +1566401088,1566401247,US +1566401248,1566401279,NO +1566401280,1566401311,US +1566401312,1566401399,NO 1566401400,1566401463,US 1566401464,1566401467,NO -1566401468,1566401503,US -1566401504,1566401507,NO -1566401508,1566401535,US +1566401468,1566401483,US +1566401484,1566401491,NO +1566401492,1566401499,US +1566401500,1566401503,NO +1566401504,1566401535,US 1566401536,1566401599,IN 1566401600,1566401631,HK 1566401632,1566401663,NO @@ -55945,7 +56580,7 @@ 1566401888,1566401919,US 1566401920,1566401967,NO 1566401968,1566401975,HK -1566401976,1566401987,NO +1566401976,1566401987,AU 1566401988,1566401991,HK 1566401992,1566401999,SG 1566402000,1566402003,AU @@ -55998,7 +56633,9 @@ 1566470144,1566470159,IE 1566470160,1566470171,GB 1566470172,1566470239,IE -1566470240,1566470303,GB +1566470240,1566470279,GB +1566470280,1566470283,IE +1566470284,1566470303,GB 1566470304,1566470351,IE 1566470352,1566470367,GB 1566470368,1566470511,IE @@ -56007,18 +56644,20 @@ 1566470560,1566470563,GB 1566470564,1566470623,IE 1566470624,1566470655,GB -1566470656,1566470719,IE -1566470720,1566470727,GB -1566470728,1566470739,IE +1566470656,1566470739,IE 1566470740,1566470743,GB -1566470744,1566470847,IE -1566470848,1566470879,GB -1566470880,1566470895,IE -1566470896,1566470911,GB -1566470912,1566471051,IE -1566471052,1566471191,GB +1566470744,1566470855,IE +1566470856,1566470859,GB +1566470860,1566471031,IE +1566471032,1566471039,GB +1566471040,1566471051,IE +1566471052,1566471151,GB +1566471152,1566471157,IE +1566471158,1566471191,GB 1566471192,1566471229,IE -1566471230,1566474239,GB +1566471230,1566471247,GB +1566471248,1566471263,IE +1566471264,1566474239,GB 1566474240,1566476287,DE 1566476288,1566478335,BG 1566478336,1566482431,RU @@ -56096,7 +56735,9 @@ 1567712768,1567713279,DE 1567713280,1567715327,RO 1567715328,1567717375,MD -1567717376,1567752191,RO +1567717376,1567750655,RO +1567750656,1567751167,SE +1567751168,1567752191,RO 1567752192,1567756287,MD 1567756288,1567775743,RO 1567775744,1567776767,MD @@ -56104,7 +56745,9 @@ 1567830016,1567831039,MD 1567831040,1567840255,RO 1567840256,1567842303,DE -1567842304,1567883263,RO +1567842304,1567880191,RO +1567880192,1567881215,SE +1567881216,1567883263,RO 1567883264,1567948799,MD 1567948800,1568026623,RO 1568026624,1568030719,MD @@ -56297,7 +56940,9 @@ 1570666192,1570666223,FR 1570666224,1570666227,SE 1570666228,1570666231,NO -1570666232,1570666367,SE +1570666232,1570666263,SE +1570666264,1570666267,US +1570666268,1570666367,SE 1570666368,1570666383,FR 1570666384,1570666387,SE 1570666388,1570666391,NL @@ -56338,7 +56983,8 @@ 1570667248,1570667263,SE 1570667264,1570667267,ES 1570667268,1570667283,SE -1570667284,1570667295,ES +1570667284,1570667287,MT +1570667288,1570667295,ES 1570667296,1570667327,GB 1570667328,1570667335,SE 1570667336,1570667339,GB @@ -56358,7 +57004,9 @@ 1570667588,1570667591,US 1570667592,1570667599,SE 1570667600,1570667603,DE -1570667604,1570667711,SE +1570667604,1570667647,SE +1570667648,1570667651,US +1570667652,1570667711,SE 1570667712,1570667727,FR 1570667728,1570667743,NL 1570667744,1570667775,SE @@ -56384,7 +57032,9 @@ 1570668292,1570668351,SE 1570668352,1570668415,NO 1570668416,1570668543,SE -1570668544,1570701311,RU +1570668544,1570671983,RU +1570671984,1570671987,TR +1570671988,1570701311,RU 1570701312,1570717695,PL 1570717696,1570725887,HR 1570725888,1570734079,DE @@ -56405,7 +57055,8 @@ 1571432448,1571434495,CZ 1571434496,1571435519,UA 1571435520,1571436031,NL -1571436032,1571438591,RU +1571436032,1571436287,UA +1571436288,1571438591,RU 1571438592,1571441663,UA 1571441664,1571442175,KZ 1571442176,1571442687,NL @@ -56903,9 +57554,7 @@ 1578591152,1578591183,FR 1578591184,1578591187,CH 1578591188,1578591195,GB -1578591196,1578591247,FR -1578591248,1578591263,PL -1578591264,1578591279,FR +1578591196,1578591279,FR 1578591280,1578591287,ES 1578591288,1578591291,DE 1578591292,1578591295,ES @@ -56942,7 +57591,9 @@ 1578591712,1578591743,PL 1578591744,1578591759,ES 1578591760,1578591791,FR -1578591792,1578591807,PL +1578591792,1578591795,ES +1578591796,1578591799,NL +1578591800,1578591807,PL 1578591808,1578591887,FR 1578591888,1578591891,DE 1578591892,1578591899,FR @@ -56951,8 +57602,8 @@ 1578591920,1578591939,ES 1578591940,1578591951,FR 1578591952,1578591967,PT -1578591968,1578591983,FR -1578591984,1578592031,PL +1578591968,1578591999,FR +1578592000,1578592031,PL 1578592032,1578592039,PT 1578592040,1578592043,ES 1578592044,1578592047,PL @@ -56964,7 +57615,7 @@ 1578592144,1578592159,NL 1578592160,1578592163,FR 1578592164,1578592171,IT -1578592172,1578592175,FR +1578592172,1578592175,ES 1578592176,1578592183,CZ 1578592184,1578592191,PT 1578592192,1578592199,BE @@ -56982,12 +57633,13 @@ 1578592336,1578592351,FR 1578592352,1578592367,PL 1578592368,1578592395,FR -1578592396,1578592399,ES +1578592396,1578592399,DE 1578592400,1578592415,GB 1578592416,1578592423,IT 1578592424,1578592431,IE -1578592432,1578592447,FR -1578592448,1578592495,PL +1578592432,1578592483,FR +1578592484,1578592487,PL +1578592488,1578592495,BE 1578592496,1578592511,FR 1578592512,1578592515,GB 1578592516,1578592519,PL @@ -57010,14 +57662,14 @@ 1578592752,1578592767,IE 1578592768,1578592783,DE 1578592784,1578592799,FR -1578592800,1578592807,GB -1578592808,1578592811,FR +1578592800,1578592803,IE +1578592804,1578592811,FR 1578592812,1578592815,PL 1578592816,1578592831,FR 1578592832,1578592847,PL 1578592848,1578592851,BE 1578592852,1578592855,DE -1578592856,1578592859,CH +1578592856,1578592859,FR 1578592860,1578592879,PL 1578592880,1578592883,FR 1578592884,1578592891,GB @@ -57040,7 +57692,9 @@ 1578593412,1578593415,FR 1578593416,1578593423,PL 1578593424,1578593439,FR -1578593440,1578593455,PL +1578593440,1578593443,IT +1578593444,1578593447,PL +1578593448,1578593455,DE 1578593456,1578593471,FR 1578593472,1578593479,GB 1578593480,1578593483,PL @@ -57082,7 +57736,9 @@ 1578593936,1578593943,FR 1578593944,1578593947,IT 1578593948,1578593955,FR -1578593956,1578593967,PL +1578593956,1578593959,LT +1578593960,1578593963,FR +1578593964,1578593967,ES 1578593968,1578593983,FR 1578593984,1578593999,PL 1578594000,1578594015,FR @@ -57095,17 +57751,14 @@ 1578594064,1578594079,PL 1578594080,1578594087,CH 1578594088,1578594095,CZ -1578594096,1578594111,FR -1578594112,1578594127,PL -1578594128,1578594143,FR +1578594096,1578594143,FR 1578594144,1578594147,PL 1578594148,1578594151,ES 1578594152,1578594159,IT 1578594160,1578594163,PT 1578594164,1578594167,ES 1578594168,1578594171,DE -1578594172,1578594191,FR -1578594192,1578594207,IT +1578594172,1578594207,FR 1578594208,1578594211,DE 1578594212,1578594239,PL 1578594240,1578594255,FR @@ -57149,15 +57802,13 @@ 1578594712,1578594715,IT 1578594716,1578594751,FR 1578594752,1578594767,ES -1578594768,1578594771,GB -1578594772,1578594775,FR +1578594768,1578594775,GB 1578594776,1578594783,ES 1578594784,1578594799,FR 1578594800,1578594815,DE 1578594816,1578594847,FR 1578594848,1578594863,IT -1578594864,1578594867,PL -1578594868,1578594871,BE +1578594864,1578594871,PL 1578594872,1578595039,FR 1578595040,1578595055,GB 1578595056,1578595103,FR @@ -57188,7 +57839,7 @@ 1578595388,1578595407,PL 1578595408,1578595411,IE 1578595412,1578595419,PL -1578595420,1578595423,FR +1578595420,1578595423,IT 1578595424,1578595439,PL 1578595440,1578595447,FR 1578595448,1578595455,ES @@ -57204,7 +57855,12 @@ 1578595548,1578595607,FR 1578595608,1578595611,GB 1578595612,1578595615,ES -1578595616,1578595647,PL +1578595616,1578595619,PL +1578595620,1578595623,BE +1578595624,1578595635,FR +1578595636,1578595639,ES +1578595640,1578595643,DE +1578595644,1578595647,GB 1578595648,1578595679,FR 1578595680,1578595695,PL 1578595696,1578595711,FR @@ -57225,7 +57881,9 @@ 1578595968,1578595983,IE 1578595984,1578595991,NL 1578595992,1578595995,IT -1578595996,1578596095,FR +1578595996,1578596031,FR +1578596032,1578596063,IT +1578596064,1578596095,IE 1578596096,1578596099,DE 1578596100,1578596103,GB 1578596104,1578596107,PL @@ -57270,7 +57928,7 @@ 1578610820,1578610823,NL 1578610824,1578610831,DE 1578610832,1578610847,CH -1578610848,1578610851,GB +1578610848,1578610851,PL 1578610852,1578610855,IE 1578610856,1578610859,IT 1578610860,1578610863,PL @@ -57279,7 +57937,8 @@ 1578610872,1578610879,PL 1578610880,1578610943,FR 1578610944,1578610975,ES -1578610976,1578611039,PL +1578610976,1578611007,PL +1578611008,1578611039,FR 1578611040,1578611043,ES 1578611044,1578611047,CZ 1578611048,1578611051,ES @@ -57303,7 +57962,8 @@ 1578611220,1578611223,DE 1578611224,1578611227,ES 1578611228,1578611231,PL -1578611232,1578611247,FR +1578611232,1578611235,IT +1578611236,1578611247,FR 1578611248,1578611251,ES 1578611252,1578611255,IT 1578611256,1578611263,PL @@ -57360,7 +58020,12 @@ 1578612304,1578612319,DE 1578612320,1578612383,FR 1578612384,1578612415,PL -1578612416,1578612607,FR +1578612416,1578612479,FR +1578612480,1578612575,GB +1578612576,1578612579,PL +1578612580,1578612583,FR +1578612584,1578612587,IE +1578612588,1578612607,IT 1578612608,1578612623,PT 1578612624,1578612639,CH 1578612640,1578612671,PL @@ -57387,7 +58052,8 @@ 1578613712,1578613719,BE 1578613720,1578613723,ES 1578613724,1578613727,IT -1578613728,1578613739,PL +1578613728,1578613735,FR +1578613736,1578613739,PL 1578613740,1578613743,FR 1578613744,1578613751,ES 1578613752,1578613759,NL @@ -57499,13 +58165,18 @@ 1581989888,1582006271,PL 1582006272,1582022655,RU 1582022656,1582039039,NL +1582039040,1582055423,BH 1582055424,1582071807,UA 1582071808,1582088191,ES 1582088192,1582104575,GB 1582104576,1582153727,RU 1582153728,1582170111,SA 1582170112,1582186495,CH -1582186496,1582202879,TR +1582186496,1582193919,GB +1582193920,1582194207,TR +1582194208,1582196991,GB +1582196992,1582198015,TR +1582198016,1582202879,GB 1582202880,1582219263,PL 1582219264,1582252031,RU 1582252032,1582268415,TR @@ -57581,13 +58252,13 @@ 1583783936,1583788031,EU 1583788032,1583792127,TM 1583792128,1583796223,IE -1583796224,1583800319,DE +1583796224,1583800063,DE +1583800064,1583800095,AT +1583800096,1583800319,DE 1583800320,1583804415,ME 1583804416,1583808511,GB 1583808512,1583812607,MD -1583812608,1583813139,NL -1583813140,1583813143,DE -1583813144,1583813171,NL +1583812608,1583813171,NL 1583813172,1583813183,US 1583813184,1583813199,NL 1583813200,1583813215,RU @@ -57596,17 +58267,11 @@ 1583813240,1583813243,US 1583813244,1583813663,NL 1583813664,1583813671,US -1583813672,1583813679,NL -1583813680,1583813683,GB -1583813684,1583813711,NL +1583813672,1583813711,NL 1583813712,1583813727,US 1583813728,1583813735,NL 1583813736,1583813743,DE -1583813744,1583813808,NL -1583813809,1583813815,US -1583813816,1583814655,NL -1583814656,1583814783,US -1583814784,1583815167,NL +1583813744,1583815167,NL 1583815168,1583815215,US 1583815216,1583815343,NL 1583815344,1583815351,US @@ -57662,8 +58327,8 @@ 1585205248,1585207295,FR 1585207296,1585209855,NL 1585209856,1585210111,IQ -1585210112,1585210879,IR -1585210880,1585211391,NL +1585210112,1585210367,IR +1585210368,1585211391,NL 1585211392,1585213439,CZ 1585213440,1585214463,GB 1585214464,1585217535,NL @@ -57745,6 +58410,7 @@ 1585354752,1585356799,RU 1585356800,1585358847,FI 1585358848,1585360895,PT +1585360896,1585362943,DK 1585362944,1585363455,IT 1585363456,1585363551,ES 1585363552,1585364991,IT @@ -57855,7 +58521,9 @@ 1586216960,1586225151,BG 1586225152,1586233343,RU 1586233344,1586241535,FR -1586241536,1586243779,SE +1586241536,1586242983,SE +1586242984,1586242991,DK +1586242992,1586243779,SE 1586243780,1586243787,NO 1586243788,1586249727,SE 1586249728,1586257919,SI @@ -57966,6 +58634,15 @@ 1588723712,1588854783,UA 1588854784,1588985855,RU 1588985856,1589182463,IR +1589182464,1589198847,OM +1589198848,1589200895,FR +1589200896,1589202943,IT +1589202944,1589203711,SE +1589203712,1589203967,NL +1589203968,1589204223,SE +1589204224,1589204991,NL +1589204992,1589207039,DE +1589207040,1589215231,IT 1589215232,1589247999,GB 1589248000,1589280767,NO 1589280768,1589313535,DE @@ -58161,6 +58838,7 @@ 1592326144,1592328191,UA 1592328192,1592393727,RU 1592393728,1592459263,SE +1592459264,1592524799,TR 1592524800,1592540415,GB 1592540416,1592540423,A2 1592540424,1592557567,GB @@ -58192,9 +58870,7 @@ 1593147392,1593163775,RU 1593163776,1593180159,AT 1593180160,1593196543,NO -1593196544,1593196783,SE -1593196784,1593196799,GB -1593196800,1593202687,SE +1593196544,1593202687,SE 1593202688,1593202815,NO 1593202816,1593203455,SE 1593203456,1593203487,NO @@ -58337,6 +59013,10 @@ 1599504384,1599520767,AZ 1599520768,1599537151,RU 1599537152,1599553535,BG +1599553536,1599561727,KG +1599561728,1599565823,GB +1599565824,1599567871,SY +1599567872,1599569919,IT 1599569920,1599586303,SI 1599586304,1599602687,BG 1599602688,1599864831,DE @@ -58363,7 +59043,9 @@ 1600963176,1600963183,RU 1600963184,1600963191,BY 1600963192,1600963199,KZ -1600963200,1600978943,RU +1600963200,1600971087,RU +1600971088,1600971091,TR +1600971092,1600978943,RU 1600978944,1601011711,SE 1601011712,1601044479,UA 1601044480,1601077247,RU @@ -58462,6 +59144,7 @@ 1602347008,1602349055,PL 1602349056,1602351103,RU 1602351104,1602353151,CZ +1602353152,1602355199,ES 1602355200,1602357247,GB 1602357248,1602359295,FR 1602359296,1602361343,DE @@ -58581,7 +59264,11 @@ 1603085872,1603085879,CH 1603085880,1603087047,IT 1603087048,1603087103,DE -1603087104,1603087515,IT +1603087104,1603087199,IT +1603087200,1603087231,SM +1603087232,1603087472,IT +1603087473,1603087474,CH +1603087475,1603087515,IT 1603087516,1603087517,CH 1603087518,1603087544,IT 1603087545,1603087546,CH @@ -58626,12 +59313,14 @@ 1603159824,1603159839,CH 1603159840,1603160079,DE 1603160080,1603160095,NL -1603160096,1603161007,DE +1603160096,1603160111,GB +1603160112,1603161007,DE 1603161008,1603161023,GB 1603161024,1603161103,DE 1603161104,1603161119,GB 1603161120,1603161135,AT -1603161136,1603161567,DE +1603161136,1603161151,GB +1603161152,1603161567,DE 1603161568,1603161599,FR 1603161600,1603162111,DE 1603162112,1603166207,TJ @@ -58724,13 +59413,13 @@ 1603895296,1603928063,RU 1603928064,1603944447,DK 1603944448,1603977215,RU -1603977216,1603980463,GB +1603977216,1603979295,GB +1603979296,1603979327,US +1603979328,1603980463,GB 1603980464,1603980479,CH 1603980480,1603980863,GB 1603980864,1603980927,ID -1603980928,1603981823,GB -1603981824,1603982079,IE -1603982080,1603982655,GB +1603980928,1603982655,GB 1603982656,1603982687,DK 1603982688,1603982719,AN 1603982720,1603982783,GB @@ -58774,8 +59463,7 @@ 1604853760,1604861951,HU 1604861952,1604870143,RS 1604870144,1604878335,HR -1604878336,1604886591,DE -1604886592,1604886655,US +1604878336,1604886655,DE 1604886656,1604886783,RU 1604886784,1604887039,DE 1604887040,1604887295,GB @@ -58916,7 +59604,11 @@ 1607467008,1607532543,DE 1607532544,1607569407,SE 1607569408,1607571455,DK -1607571456,1607585791,SE +1607571456,1607575551,SE +1607575552,1607577599,DK +1607577600,1607581695,SE +1607581696,1607583743,DK +1607583744,1607585791,SE 1607585792,1607598079,DK 1607598080,1607610367,IT 1607610368,1607612415,IE @@ -58972,7 +59664,7 @@ 1607968768,1607969791,SE 1607970816,1607972863,RU 1607972864,1607974911,NL -1607979008,1607980031,RU +1607976960,1607980031,RU 1607980032,1607981055,DE 1607981056,1607982079,UA 1607983104,1607984127,GB @@ -58988,7 +59680,28 @@ 1608515584,1610612735,IT 1610612736,1610678271,US 1610678272,1610743807,CA -1610743808,1611227135,US +1610743808,1611165943,US +1611165944,1611165951,BD +1611165952,1611166111,US +1611166112,1611166119,NZ +1611166120,1611166167,US +1611166168,1611166175,AF +1611166176,1611166527,US +1611166528,1611166559,IN +1611166560,1611166911,US +1611166912,1611166943,IN +1611166944,1611166975,US +1611166976,1611167039,IN +1611167040,1611167103,US +1611167104,1611167167,IN +1611167168,1611167199,US +1611167200,1611167231,IN +1611167232,1611167679,US +1611167680,1611167727,SE +1611167728,1611169279,US +1611169280,1611169663,IE +1611169664,1611169791,GB +1611169792,1611227135,US 1611227136,1611235327,CA 1611235328,1611923455,US 1611923456,1612185599,CA @@ -59081,7 +59794,9 @@ 1613635584,1613639679,CA 1613639680,1613676543,US 1613676544,1613680639,CA -1613680640,1613737983,US +1613680640,1613703670,US +1613703671,1613703678,LK +1613703679,1613737983,US 1613737984,1613742079,CA 1613742080,1613750591,US 1613750592,1613750607,BR @@ -59136,7 +59851,9 @@ 1652293632,1652310015,CA 1652310016,1652481279,US 1652481280,1652481791,CN -1652481792,1652621327,US +1652481792,1652487286,US +1652487287,1652487287,TR +1652487288,1652621327,US 1652621328,1652621335,CA 1652621336,1652621343,AU 1652621344,1652621359,CA @@ -59722,9 +60439,7 @@ 1652681472,1652681479,GB 1652681480,1652681511,US 1652681512,1652681519,IL -1652681520,1653496847,US -1653496848,1653496863,AU -1653496864,1653534719,US +1652681520,1653534719,US 1653534720,1653538815,CA 1653538816,1653555199,US 1653555200,1653560319,CA @@ -59744,8 +60459,8 @@ 1654558720,1654583103,US 1654583104,1654583135,CA 1654583136,1654597823,US -1654597824,1654597887,GB -1654597888,1654599455,US +1654597824,1654597855,GB +1654597856,1654599455,US 1654599456,1654599471,CA 1654599472,1654599487,US 1654599488,1654599519,BA @@ -60164,6 +60879,77 @@ 1728378880,1728380927,IN 1728380928,1728382975,PH 1728382976,1728383999,SG +1728384000,1728385023,HK +1728385024,1728386047,IN +1728386048,1728387071,JP +1728387072,1728388095,TH +1728388096,1728388351,NZ +1728388352,1728388607,AU +1728388608,1728389119,VN +1728389120,1728390143,TW +1728390144,1728391167,CN +1728391168,1728392191,JP +1728392192,1728393215,SG +1728393216,1728394239,ID +1728394240,1728396287,CN +1728396288,1728397311,PH +1728397312,1728398335,JP +1728398336,1728398847,AU +1728398848,1728399103,IN +1728399104,1728400383,NZ +1728400384,1728400895,AU +1728400896,1728401151,IN +1728401152,1728401407,SG +1728401408,1728402431,NZ +1728402432,1728403455,IN +1728403456,1728406527,AU +1728406528,1728407551,TW +1728407552,1728407807,JP +1728407808,1728408063,MY +1728408064,1728408319,NZ +1728408320,1728408575,ID +1728408576,1728409599,NZ +1728409600,1728410623,IN +1728410624,1728411647,JP +1728411648,1728412671,TH +1728412672,1728413695,KH +1728413696,1728414719,KR +1728414720,1728415743,IN +1728415744,1728416767,PK +1728416768,1728417791,JP +1728417792,1728418815,KR +1728418816,1728419071,ID +1728419072,1728419327,HK +1728419328,1728419583,NP +1728419584,1728419839,SG +1728419840,1728420863,JP +1728420864,1728421887,NZ +1728421888,1728422911,JP +1728422912,1728423935,AU +1728423936,1728424959,TW +1728424960,1728425983,AF +1728425984,1728427007,JP +1728427008,1728428031,MY +1728428032,1728430079,IN +1728430080,1728431103,JP +1728431104,1728431615,AF +1728431616,1728431871,HK +1728431872,1728432127,SG +1728432128,1728433151,IN +1728433152,1728435199,VN +1728435200,1728435967,AU +1728435968,1728436223,ID +1728436224,1728437247,IN +1728437248,1728438271,HK +1728438272,1728439295,NZ +1728439296,1728439807,NP +1728439808,1728440319,AU +1728440320,1728441343,BD +1728441344,1728442367,MY +1728442368,1728443391,SG +1728443392,1728444415,IN +1728444416,1728445439,JP +1728445440,1728446463,CN 1728708608,1728709631,CN 1728709632,1728710655,TW 1728710656,1728710911,AU @@ -60241,6 +61027,60 @@ 1728772096,1728773375,IN 1728773376,1728773631,ID 1728773632,1728774143,PH +1728774144,1728775167,AU +1728775168,1728776191,JP +1728776192,1728777215,AU +1728777216,1728778239,TH +1728778240,1728779263,JP +1728779264,1728779519,IN +1728779520,1728779775,NZ +1728779776,1728780287,ID +1728780288,1728781311,KR +1728781312,1728782335,ID +1728782336,1728783359,LK +1728783360,1728784383,HK +1728784384,1728785407,PH +1728785408,1728786431,KR +1728786432,1728787455,SG +1728787456,1728788479,AU +1728788480,1728789503,KR +1728789504,1728790527,PK +1728790528,1728791551,PH +1728791552,1728792575,PK +1728792576,1728793087,NZ +1728793088,1728793599,ID +1728793600,1728794623,AU +1728794624,1728796671,IN +1728796672,1728798719,HK +1728798720,1728799743,ID +1728799744,1728801279,HK +1728801280,1728801791,ID +1728801792,1728802815,HK +1728802816,1728803839,PH +1728803840,1728804863,IN +1728804864,1728805887,JP +1728805888,1728806911,NZ +1728806912,1728807935,KR +1728807936,1728808959,ID +1728808960,1728809983,BD +1728809984,1728810495,SG +1728810496,1728810751,AU +1728810752,1728811007,SG +1728811008,1728812031,AU +1728812032,1728812543,ID +1728812544,1728813055,SG +1728813056,1728814079,IN +1728814080,1728815103,JP +1728815104,1728818175,AU +1728818176,1728819199,VN +1728819200,1728819711,ID +1728819712,1728819967,NZ +1728819968,1728820223,ID +1728820224,1728821247,CN +1728821248,1728821759,AU +1728822272,1728823295,SG +1728823296,1728824319,MN +1728824320,1728825343,JP 1729495040,1729519615,CN 1729519616,1729520639,HK 1729520640,1729527807,CN @@ -60413,7 +61253,8 @@ 1744235520,1744236543,KR 1744236544,1744237567,IN 1744237568,1744238591,HK -1744238592,1744239615,NZ +1744238592,1744238847,US +1744238848,1744239615,NZ 1744239616,1744240639,JP 1769996288,1772093439,MA 1778384896,1778385151,CN @@ -60442,7 +61283,58 @@ 1790967808,1793064959,IN 1793064960,1794113535,CN 1794113536,1795162111,KR -1795162112,1815822335,US +1795162112,1795555359,US +1795555360,1795555455,CA +1795555456,1795555519,US +1795555520,1795555583,CA +1795555584,1795555839,US +1795555840,1795555855,CA +1795555856,1795555863,US +1795555864,1795555903,CA +1795555904,1795555967,AN +1795555968,1795556095,CA +1795556096,1795556103,US +1795556104,1795556127,CA +1795556128,1795556175,US +1795556176,1795556183,CA +1795556184,1795556191,US +1795556192,1795556255,CA +1795556256,1795556287,US +1795556288,1795556319,QA +1795556320,1795556351,US +1795556352,1795556607,GB +1795556608,1795556639,US +1795556640,1795556671,CA +1795556672,1795556735,US +1795556736,1795556863,CA +1795556864,1795556927,US +1795556928,1795556959,CA +1795556960,1795556991,US +1795556992,1795557119,CA +1795557120,1795557135,US +1795557136,1795557143,CA +1795557144,1795557151,US +1795557152,1795557215,CA +1795557216,1795557247,US +1795557248,1795557287,CA +1795557288,1795557311,US +1795557312,1795557375,CA +1795557376,1795557887,IN +1795557888,1795558143,US +1795558144,1795558655,IN +1795558656,1795558911,US +1795558912,1795559423,IN +1795559424,1795559679,AR +1795559680,1795559743,US +1795559744,1795559807,AE +1795559808,1795560447,US +1795560448,1795560959,CA +1795560960,1795561471,US +1795561472,1795561983,CA +1795561984,1795565055,US +1795565056,1795565567,IN +1795565568,1803550719,US +1809842176,1815822335,US 1815822336,1815826431,CA 1815826432,1815871487,US 1815871488,1815879679,CA @@ -60450,18 +61342,40 @@ 1815912448,1815920639,CA 1815920640,1815928831,US 1815928832,1815937023,BS -1815937024,1816024319,US +1815937024,1816001791,US +1816001792,1816002559,NL +1816002560,1816024319,US 1816024320,1816024575,CA 1816024576,1816068095,US 1816068096,1816133631,CA -1816133632,1828716543,US +1816133632,1822429183,US +1822429184,1822433279,CA +1822433280,1822445567,US +1822445568,1822453759,CA +1822453760,1822486527,US +1822486528,1822490623,CA +1822490624,1822498815,US +1822498816,1822502911,CA +1822502912,1822511103,US +1822515200,1822519295,US +1822519296,1822523391,CA +1822523392,1822527487,US +1822556160,1822572543,US +1822572544,1822605311,CA +1822605312,1822621695,US +1822687232,1822752767,US +1824522240,1828716543,US 1828716544,1830813695,FR 1830813696,1831337983,NL 1831337984,1831862271,DE 1831862272,1832124415,PT 1832124416,1832386559,IT 1832386560,1832517631,DK -1832517632,1832583167,SE +1832517632,1832552448,SE +1832552449,1832553471,DK +1832553472,1832553472,SE +1832553473,1832554495,DK +1832554496,1832583167,SE 1832583168,1832648703,DK 1832648704,1832681471,HR 1832681472,1832714239,RU @@ -60636,7 +61550,9 @@ 1833468160,1833468287,RU 1833468288,1833468575,CH 1833468576,1833468591,RU -1833468592,1833471999,CH +1833468592,1833469439,CH +1833469440,1833469951,IN +1833469952,1833471999,CH 1833472000,1833474047,EU 1833474048,1833474559,UA 1833474560,1833474815,RU @@ -60705,7 +61621,9 @@ 1833672704,1833676799,GB 1833676800,1833677567,DE 1833677568,1833677599,CH -1833677600,1833678903,DE +1833677600,1833677775,DE +1833677776,1833677783,FR +1833677784,1833678903,DE 1833678904,1833678935,HK 1833678936,1833678959,DE 1833678960,1833678975,BA @@ -60822,13 +61740,11 @@ 1835913216,1835917311,RU 1835917312,1835920127,GB 1835920128,1835920199,PT -1835920200,1835920223,GB -1835920224,1835920247,PT -1835920248,1835920255,GB -1835920256,1835920287,PT -1835920288,1835920295,GB -1835920296,1835920319,PT -1835920320,1835925503,GB +1835920200,1835920207,GB +1835920208,1835920271,PT +1835920272,1835920279,GB +1835920280,1835920335,PT +1835920336,1835925503,GB 1835925504,1835933695,LV 1835933696,1835941887,RU 1835941888,1835950079,UA @@ -60887,6 +61803,16 @@ 1839333376,1839366143,UA 1839366144,1839398911,IR 1839398912,1839431679,NO +1839431680,1839448063,BA +1839448064,1839450111,KZ +1839450112,1839452159,NO +1839452160,1839454207,FI +1839454208,1839456255,RU +1839456256,1839459327,RO +1839459328,1839459839,DE +1839459840,1839460351,RO +1839460352,1839462399,RU +1839462400,1839464447,FI 1839464448,1839497215,CZ 1839497216,1839529983,CH 1839529984,1839562751,RU @@ -60898,17 +61824,13 @@ 1839756328,1839756335,FR 1839756336,1839759359,IT 1839759360,1839792127,RU -1839792128,1839794687,GB -1839794688,1839794943,US -1839794944,1839795151,GB +1839792128,1839795151,GB 1839795152,1839795167,US 1839795168,1839796607,GB 1839796608,1839796671,US 1839796672,1839797759,GB 1839797760,1839798015,GR -1839798016,1839798271,GB -1839798272,1839798399,DE -1839798400,1839798527,GB +1839798016,1839798527,GB 1839798528,1839798559,US 1839798560,1839800447,GB 1839800448,1839800479,SG @@ -60917,15 +61839,15 @@ 1839800960,1839801023,GR 1839801024,1839801279,GB 1839801280,1839801311,VG -1839801312,1839801343,GB -1839801344,1839801471,CN -1839801472,1839801551,GB +1839801312,1839801551,GB 1839801552,1839801567,US 1839801568,1839802111,GB 1839802112,1839802239,RO 1839802240,1839806463,GB 1839806464,1839811071,US -1839811072,1839816703,GB +1839811072,1839812607,GB +1839812608,1839814143,US +1839814144,1839816703,GB 1839816704,1839824895,NO 1839824896,1839890431,RU 1839890432,1839923199,GB @@ -60950,6 +61872,7 @@ 1840906240,1840971775,IL 1840971776,1841102847,RU 1841102848,1841168383,NO +1841168384,1841233919,FR 1841233920,1841299455,RU 1841299456,1841430527,DE 1841430528,1841561599,RU @@ -61061,7 +61984,15 @@ 1842154240,1842154247,HK 1842154248,1842154367,NO 1842154368,1842154431,US -1842154432,1842155519,NO +1842154432,1842154495,NO +1842154496,1842154511,CN +1842154512,1842154527,SG +1842154528,1842154559,AU +1842154560,1842154751,NO +1842154752,1842154815,AU +1842154816,1842155007,NO +1842155008,1842155263,AU +1842155264,1842155519,SG 1842155520,1842157567,IT 1842157568,1842159615,AE 1842159616,1842161663,BA @@ -61143,7 +62074,10 @@ 1843789824,1843806207,SK 1843806208,1843822591,IR 1843822592,1843838975,RU -1843838976,1843849215,DE +1843838976,1843841535,DE +1843841536,1843841791,CH +1843841792,1843842047,AU +1843842048,1843849215,DE 1843849216,1843850239,GB 1843850240,1843855359,DE 1843855360,1843871743,PL @@ -61220,6 +62154,8 @@ 1844058112,1844062207,RU 1844062208,1844064255,CZ 1844064256,1844068351,IT +1844068352,1844068607,FR +1844068608,1844070399,ES 1844070400,1844072447,GB 1844072448,1844076543,ES 1844076544,1844078591,IE @@ -61296,15 +62232,19 @@ 1844170016,1844170019,NG 1844170020,1844170027,AF 1844170028,1844170031,IQ -1844170032,1844170047,AF -1844170048,1844170051,DE +1844170032,1844170043,AF +1844170044,1844170051,DE 1844170052,1844170055,GH 1844170056,1844170063,AF -1844170064,1844170239,DE +1844170064,1844170067,DE +1844170068,1844170071,NG +1844170072,1844170083,DE +1844170084,1844170091,NG +1844170092,1844170239,DE 1844170240,1844170255,AF 1844170256,1844170263,IQ -1844170264,1844170271,AF -1844170272,1844170751,DE +1844170264,1844170279,AF +1844170280,1844170751,DE 1844170752,1844174847,RU 1844174848,1844178943,DE 1844178944,1844180991,EE @@ -61377,7 +62317,8 @@ 1844318208,1844322303,IT 1844322304,1844326399,CZ 1844326400,1844329983,DK -1844329984,1844330495,LU +1844329984,1844330303,LU +1844330304,1844330495,DK 1844330496,1844334591,GB 1844334592,1844342783,RU 1844342784,1844346879,IT @@ -61733,12 +62674,7 @@ 1877721088,1877737471,TW 1877737472,1877999615,JP 1877999616,1879048191,TW -1879048192,1883218547,CN -1883218548,1883218551,ES -1883218552,1883218555,FR -1883218556,1883218579,CN -1883218580,1883218583,BE -1883218584,1883504639,CN +1879048192,1883504639,CN 1883504640,1883766783,JP 1883766784,1883770879,MN 1883770880,1883783167,KR @@ -63059,7 +63995,7 @@ 2033362944,2033364991,TH 2033364992,2033369087,TW 2033369088,2033377279,AU -2033377280,2033385471,PH +2033377280,2033385471,KR 2033385472,2033451007,CN 2033451008,2033487871,ID 2033487872,2033491967,PK @@ -63087,12 +64023,7 @@ 2033889280,2033891327,JP 2033891328,2033893375,ID 2033893376,2033909759,PH -2033909760,2034213775,CN -2034213776,2034213779,FR -2034213780,2034213783,DE -2034213784,2034213787,CN -2034213788,2034213791,SL -2034213792,2034237439,CN +2033909760,2034237439,CN 2034237440,2034499583,KR 2034499584,2034761727,CN 2034761728,2035023871,NZ @@ -63677,7 +64608,7 @@ 2090745856,2090762239,MN 2090762240,2090778623,ID 2090778624,2090786815,HK -2090786816,2090795007,SG +2090786816,2090795007,MY 2090795008,2090860543,JP 2090860544,2091384831,CN 2091384832,2091646975,AU @@ -63881,7 +64812,8 @@ 2113830912,2113863679,CN 2113863680,2113929215,AU 2113929216,2130706431,JP -2147483648,2147942399,US +2147483648,2147549183,EU +2147549184,2147942399,US 2147942400,2148007935,DE 2148007936,2148220515,US 2148220516,2148220535,AU @@ -63894,7 +64826,27 @@ 2150105088,2150236159,GB 2150236160,2150301695,US 2150301696,2150367231,CA -2150367232,2151743487,US +2150367232,2150432767,US +2150432768,2150498303,IT +2150498304,2151743487,US +2151743488,2151759871,BY +2151759872,2151768063,US +2151768064,2151770111,GB +2151770112,2151772159,BA +2151772160,2151776255,IT +2151776256,2151778303,AT +2151778304,2151780351,RU +2151780352,2151782399,DE +2151782400,2151784447,ES +2151784448,2151792639,IR +2151792640,2151794687,CH +2151794688,2151796735,IT +2151796736,2151797759,NL +2151797760,2151797775,DE +2151797776,2151800319,NL +2151800320,2151800831,DE +2151800832,2151809023,PT +2151809024,2151940095,IT 2152726528,2153119743,US 2153119744,2153250815,GB 2153250816,2153578495,US @@ -63903,12 +64855,52 @@ 2153906176,2153971711,GB 2153971712,2154037247,US 2154037248,2154102783,CA -2154102784,2156003327,US +2154102784,2155610111,US +2155610112,2155675647,UA +2155675648,2155806719,US +2155806720,2155808767,IT +2155808768,2155810815,RU +2155810816,2155812863,FR +2155812864,2155814911,GB +2155814912,2155819007,NL +2155819008,2155821055,DE +2155821056,2155823103,IT +2155823104,2155825151,DE +2155825152,2155827199,AE +2155827200,2155831295,PL +2155831296,2155833343,RU +2155833344,2155833855,SE +2155833856,2155834367,NL +2155834368,2155834879,SE +2155834880,2155835391,NL +2155835392,2155839487,RO +2155839488,2155843583,FR +2155843584,2155845631,RU +2155845632,2155847679,DE +2155847680,2155849727,ES +2155849728,2155851775,TR +2155851776,2155853823,KZ +2155853824,2155855871,SE +2155855872,2155872255,RO +2155872256,2156003327,US 2156003328,2156134399,AT 2156134400,2156265471,US 2156265472,2156331007,KR 2156331008,2156593151,US 2156593152,2156658687,IL +2156658688,2156691455,IR +2156691456,2156695551,A2 +2156695552,2156697599,FR +2156697600,2156699647,CY +2156699648,2156703743,RU +2156703744,2156707839,BG +2156707840,2156709887,RU +2156709888,2156711935,ES +2156711936,2156713983,DE +2156713984,2156716031,NL +2156716032,2156718079,RO +2156718080,2156720127,IS +2156720128,2156724223,BY 2156724224,2156855295,CH 2156855296,2156920831,US 2156920832,2156986367,CA @@ -63922,11 +64914,21 @@ 2159869952,2159935487,CA 2159935488,2160525311,US 2160525312,2160590847,GB -2160590848,2161508351,US +2160590848,2160852991,US +2160852992,2160885759,RU +2160885760,2160893951,AT +2160893952,2160902143,RU +2160902144,2160906239,NL +2160906240,2160908287,FR +2160908288,2160910335,PL +2160910336,2160914431,NL +2160914432,2160918527,SA +2160918528,2161508351,US 2161508352,2161573887,FI 2161573888,2162687999,US 2162688000,2162753535,GB 2162753536,2162819071,CA +2162819072,2162884607,RO 2162884608,2163212287,US 2163212288,2163277823,GB 2163277824,2163288063,US @@ -64030,12 +65032,32 @@ 2180579328,2180644863,JP 2180644864,2180907007,US 2180907008,2180972543,KR -2180972544,2181824511,US +2180972544,2181038079,US +2181038080,2181040127,GB +2181040128,2181042175,AZ +2181042176,2181044223,DE +2181044224,2181046271,AL +2181046272,2181054463,UA +2181054464,2181056511,AT +2181056512,2181058559,DE +2181058560,2181060607,GB +2181060608,2181062655,BA +2181062656,2181070847,FR +2181070848,2181087231,IT +2181087232,2181089279,FR +2181089280,2181091327,SE +2181091328,2181093375,IT +2181093376,2181095423,RU +2181095424,2181097471,GB +2181097472,2181099519,UA +2181099520,2181103615,SY +2181103616,2181824511,US 2181824512,2181890047,CA 2181890048,2182021119,US 2182021120,2182086655,CA 2182086656,2182610943,US 2182610944,2182676479,GB +2182676480,2182742015,IT 2182742016,2182873087,US 2182873088,2182938623,SE 2182938624,2183135231,US @@ -64044,7 +65066,11 @@ 2183266304,2183331839,JP 2183331840,2183462911,US 2183462912,2183528447,NL -2183528448,2184577023,US +2183528448,2183856127,US +2183856128,2183888895,GR +2183888896,2183905279,GB +2183905280,2183921663,HU +2183921664,2184577023,US 2184577024,2184642559,JP 2184642560,2184708095,US 2184708096,2184773631,AU @@ -64137,9 +65163,32 @@ 2191589376,2191654911,NL 2191654912,2192769023,US 2192769024,2192834559,CA +2192834560,2192867327,DE +2192867328,2192883711,SY +2192883712,2192885759,PL +2192885760,2192887807,GB +2192887808,2192891903,UA +2192891904,2192900095,RS 2192900096,2193031167,US 2193031168,2193096703,DE 2193096704,2193162239,US +2193162240,2193178623,UA +2193178624,2193180671,GB +2193180672,2193182719,IR +2193182720,2193184767,PT +2193184768,2193186815,ES +2193186816,2193188863,PL +2193188864,2193190911,DE +2193190912,2193195007,RU +2193195008,2193199103,DK +2193199104,2193201151,GB +2193201152,2193202175,SE +2193202176,2193203199,US +2193203200,2193205247,GB +2193205248,2193207295,FR +2193207296,2193209343,CZ +2193209344,2193211391,FR +2193211392,2193227775,BG 2193227776,2193293311,IT 2193293312,2193358847,US 2193358848,2193424383,FI @@ -64147,6 +65196,17 @@ 2193489920,2193555455,FR 2193555456,2193620991,US 2193620992,2193686527,IT +2193686528,2193688575,FR +2193688576,2193692671,CZ +2193692672,2193694719,FR +2193694720,2193704959,RU +2193704960,2193707007,IT +2193707008,2193711103,GB +2193711104,2193713151,DE +2193713152,2193715199,ES +2193715200,2193717247,DE +2193717248,2193719295,AM +2193719296,2193752063,IQ 2193752064,2193817599,AU 2193817600,2193883135,NZ 2193883136,2194014207,US @@ -64154,6 +65214,7 @@ 2194079744,2194210815,US 2194210816,2194276351,GB 2194276352,2194407423,US +2194407424,2194472959,BG 2194472960,2194538495,US 2194538496,2194604031,ES 2194604032,2194669567,US @@ -64176,7 +65237,18 @@ 2197225472,2197422079,US 2197422080,2197487615,CA 2197487616,2197553151,IT -2197553152,2197815295,US +2197553152,2197749759,US +2197749760,2197751807,IQ +2197751808,2197753855,RU +2197753856,2197757951,GB +2197757952,2197766143,RU +2197766144,2197768191,PS +2197768192,2197770239,IL +2197770240,2197772287,RU +2197772288,2197774335,IQ +2197774336,2197776383,IT +2197776384,2197778431,DE +2197778432,2197780479,IT 2197880832,2197946367,IT 2197946368,2204172287,US 2204172288,2204237823,SE @@ -65211,11 +66283,25 @@ 2365644800,2365652991,NO 2365652992,2366111743,DE 2366111744,2366144511,MT -2366144512,2366162943,RU +2366144512,2366149375,RU +2366149376,2366149407,DE +2366149408,2366149423,PL +2366149424,2366149439,SK +2366149440,2366149455,PT +2366149456,2366149471,ES +2366149472,2366149487,FR +2366149488,2366149495,MD +2366149496,2366149503,LT +2366149504,2366149511,LV +2366149512,2366149519,EE +2366149520,2366149527,BG +2366149528,2366149535,RS +2366149536,2366162943,RU 2366162944,2366164991,AL 2366164992,2366167039,GE 2366167040,2366169087,GB -2366169088,2366308351,DE +2366169088,2366171135,CH +2366171136,2366308351,DE 2366308352,2366373887,GB 2366373888,2367487999,DE 2367488000,2367553535,SI @@ -65237,7 +66323,9 @@ 2372218880,2372220927,FR 2372220928,2372222975,KW 2372222976,2372239359,EU -2372239360,2372272127,RU +2372239360,2372264447,RU +2372264448,2372266495,UA +2372266496,2372272127,RU 2372272128,2372337663,US 2372337664,2372403199,ID 2372403200,2372468735,US @@ -65247,7 +66335,11 @@ 2372474624,2372474879,GB 2372474880,2372483071,RU 2372483072,2372485119,JO -2372485120,2372487167,RU +2372485120,2372485247,RU +2372485248,2372485375,IN +2372485376,2372485823,RU +2372485824,2372485887,NL +2372485888,2372487167,RU 2372487168,2372489215,FR 2372489216,2372493311,LB 2372493312,2372497407,ES @@ -65302,7 +66394,8 @@ 2374512640,2374514687,SK 2374514688,2374516735,ES 2374516736,2374524927,AM -2374524928,2374529023,FR +2374524928,2374525183,DE +2374525184,2374529023,FR 2374529024,2374531071,RU 2374531072,2374533119,NL 2374533120,2374565887,HR @@ -65317,8 +66410,21 @@ 2374670336,2374672383,FR 2374672384,2374674431,PL 2374674432,2374676479,NL +2374676480,2374680575,LB 2374680576,2374684671,NL -2374684672,2374686719,GB +2374684672,2374684991,GB +2374684992,2374685119,FI +2374685120,2374685247,GB +2374685248,2374685375,NO +2374685376,2374685503,GB +2374685504,2374685631,DK +2374685632,2374685759,GB +2374685760,2374685887,NL +2374685888,2374686015,GB +2374686016,2374686143,PL +2374686144,2374686271,GB +2374686272,2374686303,NL +2374686304,2374686719,GB 2374686720,2374688767,NL 2374688768,2374696959,GB 2374696960,2374959103,US @@ -65336,6 +66442,7 @@ 2376761344,2376777727,CZ 2376777728,2376781823,BA 2376781824,2376783871,ES +2376783872,2376785919,FR 2376785920,2376794111,UA 2376794112,2376859647,CH 2376859648,2376925183,FI @@ -65638,50 +66745,7 @@ 2447679820,2447679839,IT 2447679840,2447704063,DE 2447704064,2447769599,GB -2447769600,2447769855,DE -2447769856,2447770111,GB -2447770112,2447775743,DE -2447775744,2447777791,GB -2447777792,2447781887,DE -2447781888,2447782911,GB -2447782912,2447783935,LU -2447783936,2447784959,GB -2447784960,2447785983,LU -2447785984,2447788031,DE -2447788032,2447790079,QA -2447790080,2447792127,DE -2447792128,2447792383,GB -2447792384,2447793919,DE -2447793920,2447794175,QA -2447794176,2447796223,DE -2447796224,2447798271,GB -2447798272,2447801343,DE -2447801344,2447802367,IT -2447802368,2447806463,DE -2447806464,2447808511,HU -2447808512,2447810559,DE -2447810560,2447812607,GB -2447812608,2447813631,HU -2447813632,2447813887,IE -2447813888,2447814143,DE -2447814144,2447814655,GB -2447814656,2447815679,DE -2447815680,2447816191,IT -2447816192,2447816447,GB -2447816448,2447816703,DE -2447816704,2447817727,GB -2447817728,2447821055,DE -2447821056,2447821311,QA -2447821312,2447821823,GB -2447821824,2447824895,IT -2447824896,2447826943,DE -2447826944,2447827967,GB -2447827968,2447830015,DE -2447830016,2447830527,IT -2447830528,2447833087,DE -2447833088,2447833599,GB -2447833600,2447834111,DE -2447834112,2447835135,IT +2447769600,2447835135,DE 2447835136,2447900671,FR 2447900672,2447966207,CH 2447966208,2448031743,GB @@ -65713,6 +66777,7 @@ 2449481728,2449489919,RO 2449489920,2449491967,FR 2449491968,2449494015,NL +2449494016,2449496063,UA 2449496064,2449498111,FR 2449498112,2449506303,DE 2449506304,2449539071,RO @@ -65744,6 +66809,7 @@ 2453733376,2453798911,US 2453798912,2453800959,GB 2453800960,2453803007,RU +2453803008,2453805055,KZ 2453805056,2453807103,FI 2453807104,2453815295,GB 2453815296,2453831679,RO @@ -65805,11 +66871,13 @@ 2457141248,2457206783,JP 2457206784,2457272319,AU 2457272320,2457337855,FI -2457337856,2457360895,RU -2457360896,2457361151,UA +2457337856,2457360383,RU +2457360384,2457361151,UA 2457361152,2457361407,CZ 2457361408,2457364479,RU -2457364480,2457376767,CZ +2457364480,2457366527,CZ +2457366528,2457367551,GB +2457367552,2457376767,CZ 2457376768,2457378815,DE 2457378816,2457380863,RU 2457380864,2457382911,EE @@ -65870,12 +66938,14 @@ 2461612032,2461614079,IL 2461614080,2461630463,TR 2461630464,2461651967,RU -2461651968,2461652991,GB +2461651968,2461652991,CY 2461652992,2461659135,RU 2461659136,2461659391,UA 2461659392,2461659903,RU 2461659904,2461660159,UA -2461660160,2461663231,RU +2461660160,2461660415,RU +2461660416,2461660671,RO +2461660672,2461663231,RU 2461663232,2461794303,US 2461794304,2461859839,GB 2461859840,2461990911,US @@ -66180,7 +67250,9 @@ 2500038656,2500040703,IT 2500040704,2500042751,LB 2500042752,2500046847,SA -2500046848,2500048895,IT +2500046848,2500047359,IT +2500047360,2500047615,DE +2500047616,2500048895,IT 2500048896,2500050943,MD 2500050944,2500067327,KZ 2500067328,2501574655,US @@ -66190,6 +67262,10 @@ 2503081984,2503671807,US 2503671808,2503737343,NL 2503737344,2503868415,US +2503868416,2503876607,RU +2503876608,2503880703,ES +2503880704,2503882751,RU +2503882752,2503884799,DE 2503884800,2503901183,SI 2503901184,2503905279,IT 2503905280,2503907327,CZ @@ -66248,11 +67324,9 @@ 2509928448,2509930495,FI 2509930496,2509934591,RU 2509934592,2509936639,DE -2509936640,2509936914,AT -2509936915,2509936915,IR -2509936916,2509937681,AT +2509936640,2509937681,AT 2509937682,2509937682,ME -2509937683,2509937683,AT +2509937683,2509937683,IR 2509937684,2509937684,IQ 2509937685,2509937685,AQ 2509937686,2509937686,MP @@ -66266,7 +67340,26 @@ 2509937694,2509937694,NA 2509937695,2509937695,AM 2509937696,2509937697,CN -2509937698,2509938687,AT +2509937698,2509937713,AT +2509937714,2509937714,CV +2509937715,2509937715,ER +2509937716,2509937716,ET +2509937717,2509937717,KE +2509937718,2509937718,NG +2509937719,2509937719,DO +2509937720,2509937720,JM +2509937721,2509937721,AG +2509937722,2509937722,VI +2509937723,2509937723,MQ +2509937724,2509937724,KI +2509937725,2509937725,VU +2509937726,2509937726,TK +2509937727,2509937727,MK +2509937728,2509937728,TM +2509937729,2509937729,IM +2509937730,2509938175,AT +2509938176,2509938431,US +2509938432,2509938687,DE 2509938688,2509946879,UA 2509946880,2509963263,BE 2509963264,2510028799,GB @@ -66295,14 +67388,17 @@ 2514419712,2514485247,GB 2514485248,2514514431,DE 2514514432,2514514687,NL -2514514688,2516254719,DE +2514514688,2515599359,DE +2515599360,2515664895,GB +2515664896,2516254719,DE 2516254720,2516320255,FR 2516320256,2516451327,US 2516451328,2516516863,GB 2516516864,2516520959,RU 2516520960,2516523007,SA 2516523008,2516525055,RU -2516525056,2516527103,NL +2516525056,2516525823,US +2516525824,2516527103,NL 2516527104,2516529151,GB 2516529152,2516531199,CH 2516531200,2516533247,GB @@ -66375,7 +67471,7 @@ 2531459072,2531524607,SE 2531524608,2531590143,US 2531590144,2531655679,AU -2531655680,2532048895,US +2531721216,2532048895,US 2532048896,2532114431,SE 2532114432,2532179967,GB 2532179968,2532376575,US @@ -66457,7 +67553,9 @@ 2556559360,2556624895,AU 2556624896,2556690431,KR 2556690432,2556755967,US -2556755968,2557018111,HK +2556755968,2556821503,HK +2556821504,2556887039,SG +2556887040,2557018111,HK 2557018112,2557083647,GB 2557083648,2557542399,ZA 2557542400,2557607935,US @@ -66500,12 +67598,9 @@ 2568224768,2568290303,SG 2568290304,2569142271,US 2569142272,2569404415,CN -2569404416,2569601023,US -2569601024,2569666559,CA -2569666560,2569797631,US +2569404416,2569797631,US 2569797632,2569863167,NO -2569863168,2569928703,US -2569928704,2569994239,CH +2569863168,2569994239,CH 2569994240,2570125311,US 2570125312,2570190847,BE 2570190848,2572681215,US @@ -66531,7 +67626,9 @@ 2574319616,2574647295,US 2574647296,2574778367,CN 2574778368,2583691263,JP -2583691264,2584215551,US +2583691264,2584018943,US +2584018944,2584084479,CA +2584084480,2584215551,US 2584215552,2584281087,GB 2584281088,2584346623,US 2584346624,2584412159,KR @@ -66676,9 +67773,7 @@ 2621636608,2621702143,DE 2621702144,2621767679,US 2621767680,2621833215,NZ -2621833216,2622423039,US -2622423040,2622488575,CA -2622488576,2622685183,US +2621833216,2622685183,US 2622685184,2622750719,NL 2622750720,2623602687,US 2623602688,2623668223,CL @@ -66820,7 +67915,11 @@ 2653880320,2653945855,IT 2653945856,2654011391,US 2654011392,2654076927,ES -2654076928,2654142463,FR +2654076928,2654085119,FR +2654085120,2654089215,HK +2654089216,2654093311,FR +2654093312,2654097407,US +2654097408,2654142463,FR 2654208000,2654339071,US 2654339072,2654404607,AU 2654404608,2654994431,US @@ -66937,6 +68036,9 @@ 2668892160,2668894207,BA 2668894208,2668896255,MT 2668896256,2668904447,GB +2668904448,2668912639,TR +2668912640,2668916735,IR +2668918784,2668920831,ES 2668920832,2668953599,IT 2668953600,2669019135,US 2669019136,2669084671,CH @@ -67023,6 +68125,7 @@ 2677800960,2677866495,CH 2677866496,2677997567,US 2677997568,2678063103,CA +2678063104,2678128639,UA 2678128640,2678194175,US 2678194176,2678259711,NO 2678259712,2678521855,US @@ -67055,6 +68158,7 @@ 2680553472,2680684543,US 2680684544,2680750079,SE 2680750080,2681012223,US +2681012224,2681077759,PL 2681077760,2681143295,CA 2681143296,2681208831,AU 2681208832,2681274367,CA @@ -67069,6 +68173,7 @@ 2681864192,2681929727,US 2681929728,2681995263,GB 2681995264,2682257407,US +2682257408,2682322943,UA 2682322944,2682388479,US 2682388480,2682454015,CN 2682454016,2682519551,US @@ -67093,7 +68198,54 @@ 2683699200,2683830271,US 2683830272,2683895807,AU 2683895808,2684157951,US +2684157952,2684159999,NL +2684160000,2684162047,NO +2684162048,2684164095,EE +2684164096,2684166143,SE +2684166144,2684170239,TR +2684170240,2684178431,GB +2684178432,2684180479,TR +2684180480,2684182527,DK +2684182528,2684184575,IT +2684184576,2684186623,SK +2684186624,2684188671,DE +2684188672,2684190719,RU +2684190720,2684197119,NL +2684197120,2684197631,GB +2684197632,2684198399,NL +2684198400,2684200959,GB +2684200960,2684203007,RU +2684203008,2684204031,CZ +2684204032,2684204543,HK +2684204544,2684205055,GB +2684205056,2684207103,IT +2684207104,2684213247,GB +2684213248,2684215295,MK +2684215296,2684217343,BE +2684217344,2684219391,CZ +2684219392,2684221439,PL +2684221440,2684223487,IL 2684223488,2684289023,GB +2684289024,2684297215,RU +2684297216,2684299263,IR +2684299264,2684301311,CY +2684301312,2684305407,PT +2684305408,2684321791,RU +2684321792,2684329983,IT +2684329984,2684332031,IQ +2684332032,2684334079,DE +2684334080,2684338175,PL +2684338176,2684338303,NL +2684338304,2684338399,ES +2684338400,2684338687,NL +2684338688,2684339103,ES +2684339104,2684339119,NL +2684339120,2684339135,ES +2684339136,2684339199,NL +2684339200,2684340223,ES +2684340224,2684344319,GB +2684344320,2684346367,NL +2684346368,2684354559,FI 2684354560,2684616703,US 2684616704,2684682239,NZ 2684682240,2684747775,GB @@ -67465,7 +68617,9 @@ 2755330048,2755395583,DE 2755395584,2755461119,FR 2755461120,2755526655,DE -2755526656,2755985407,US +2755526656,2755592191,US +2755592192,2755657727,GB +2755657728,2755985407,US 2755985408,2756182015,JP 2756182016,2756247551,US 2756247552,2756313087,UY @@ -67860,7 +69014,9 @@ 2816004352,2816004367,US 2816004368,2816004415,IL 2816004416,2816004479,US -2816004480,2816008191,IL +2816004480,2816004703,IL +2816004704,2816004711,GB +2816004712,2816008191,IL 2816008192,2816008207,IE 2816008208,2816010495,IL 2816010496,2816010751,US @@ -68002,7 +69158,7 @@ 2849179136,2849898495,KR 2849898496,2849898751,AU 2849898752,2849964031,KR -2849964032,2850029567,PH +2849964032,2850029567,CN 2850029568,2851995647,US 2852126720,2853306367,US 2853306368,2853371903,CL @@ -68052,8 +69208,10 @@ 2870018048,2870083583,DE 2870083584,2870087935,FR 2870087936,2870088191,ES -2870088192,2870089727,FR -2870089728,2870091775,GE +2870088192,2870088959,FR +2870088960,2870088991,ES +2870088992,2870089727,FR +2870089728,2870091775,DE 2870091776,2870095871,FR 2870095872,2870096383,SG 2870096384,2870149119,FR @@ -68155,7 +69313,9 @@ 2902507520,2902515711,CA 2902515712,2904555519,US 2904555520,2904817663,CA -2904817664,2905376767,US +2904817664,2905350751,US +2905350752,2905350783,RU +2905350784,2905376767,US 2905376768,2905377535,CA 2905377536,2905378303,US 2905378304,2905378815,CA @@ -68220,7 +69380,11 @@ 2915520512,2915521023,AU 2915521024,2915521279,JP 2915521280,2915521535,PL -2915521536,2915765279,US +2915521536,2915526911,US +2915526912,2915527167,DE +2915527168,2915527679,US +2915527680,2915528711,NL +2915528712,2915765279,US 2915765280,2915765287,IN 2915765288,2915765367,US 2915765368,2915765375,ZA @@ -68262,9 +69426,7 @@ 2915768376,2915768383,GB 2915768384,2915768431,US 2915768432,2915768439,IE -2915768440,2915768487,US -2915768488,2915768495,CA -2915768496,2915768703,US +2915768440,2915768703,US 2915768704,2915768767,GB 2915768768,2915768903,US 2915768904,2915768911,GR @@ -68291,7 +69453,8 @@ 2915772712,2915772719,GB 2915772720,2915772751,US 2915772752,2915772759,DE -2915772760,2915773023,US +2915772760,2915773015,US +2915773016,2915773023,SG 2915773024,2915773039,IN 2915773040,2915773175,US 2915773176,2915773183,KW @@ -68516,9 +69679,15 @@ 2915810648,2915810663,CA 2915810664,2915811135,US 2915811136,2915811199,IN -2915811200,2915958783,US +2915811200,2915821791,US +2915821792,2915821823,IL +2915821824,2915958783,US 2915958784,2916024319,CA -2916024320,2916118223,US +2916024320,2916101535,US +2916101536,2916101543,CA +2916101544,2916101615,US +2916101616,2916101623,CA +2916101624,2916118223,US 2916118224,2916118231,LK 2916118232,2916120823,US 2916120824,2916120831,CA @@ -68581,8 +69750,7 @@ 2916581376,2916614143,PR 2916614144,2917167679,US 2917167680,2917167743,BR -2917167744,2917167807,US -2917167808,2917167839,RS +2917167744,2917167839,US 2917167840,2917167871,TR 2917167872,2917167903,US 2917167904,2917167935,TR @@ -68628,7 +69796,9 @@ 2917210464,2917257215,US 2917257216,2917261311,KY 2917261312,2917265407,US -2917265408,2917269503,JM +2917265408,2917268223,JM +2917268224,2917268479,BB +2917268480,2917269503,JM 2917269504,2917449727,US 2917449728,2917466111,PR 2917466112,2917572607,US @@ -68741,13 +69911,13 @@ 2917710592,2917710847,CA 2917710848,2917714175,US 2917714176,2917714431,CA -2917714432,2917718527,US +2917714432,2917715967,US +2917715968,2917716223,DE +2917716224,2917718527,US 2917718528,2917719039,CA 2917719040,2917722367,US 2917722368,2917722623,CA -2917722624,2917723135,US -2917723136,2917723391,CA -2917723392,2917724159,US +2917722624,2917724159,US 2917724160,2917724415,CA 2917724416,2917726207,US 2917726208,2917726463,CA @@ -68780,7 +69950,9 @@ 2917811512,2917811519,LK 2917811520,2917811583,US 2917811584,2917811647,LK -2917811648,2917815575,US +2917811648,2917813679,US +2917813680,2917813687,LK +2917813688,2917815575,US 2917815576,2917815583,RO 2917815584,2917823871,US 2917823872,2917823887,CA @@ -68884,7 +70056,9 @@ 2918534992,2918535807,US 2918535808,2918535967,CN 2918535968,2918535999,US -2918536000,2918536127,CN +2918536000,2918536023,CN +2918536024,2918536031,US +2918536032,2918536127,CN 2918536128,2918536167,US 2918536168,2918536191,CN 2918536192,2918536703,A1 @@ -68924,12 +70098,10 @@ 2919020656,2919020711,US 2919020712,2919020719,CA 2919020720,2919020727,US -2919020728,2919020759,CA -2919020760,2919020767,US -2919020768,2919020799,CA +2919020728,2919020799,CA 2919020800,2919021343,US -2919021344,2919021471,CA -2919021472,2919063551,US +2919021344,2919021567,CA +2919021568,2919063551,US 2919063552,2919064063,MX 2919064064,2919067655,CN 2919067656,2919067695,US @@ -69147,7 +70319,11 @@ 2919070944,2919070951,BR 2919070952,2919071143,US 2919071144,2919071151,CN -2919071152,2919170327,US +2919071152,2919153695,US +2919153696,2919153703,DE +2919153704,2919153807,US +2919153808,2919153815,AU +2919153816,2919170327,US 2919170328,2919170335,PE 2919170336,2919170351,US 2919170352,2919170359,PE @@ -69167,9 +70343,7 @@ 2919170528,2919170535,BR 2919170536,2919170551,US 2919170552,2919170559,FR -2919170560,2919170575,US -2919170576,2919170583,FR -2919170584,2919170599,US +2919170560,2919170599,US 2919170600,2919170607,JP 2919170608,2919170615,US 2919170616,2919170623,CN @@ -69199,7 +70373,9 @@ 2919170936,2919170943,PH 2919170944,2919170967,US 2919170968,2919170975,NZ -2919170976,2919171071,US +2919170976,2919171055,US +2919171056,2919171063,TR +2919171064,2919171071,US 2919171072,2919171079,IN 2919171080,2919171087,CL 2919171088,2919171095,TR @@ -69229,7 +70405,11 @@ 2919171456,2919171463,BR 2919171464,2919171479,US 2919171480,2919171487,BR -2919171488,2919174143,US +2919171488,2919171535,US +2919171536,2919171543,BR +2919171544,2919171655,US +2919171656,2919171663,BR +2919171664,2919174143,US 2919174144,2919178239,CA 2919178240,2919186431,US 2919186432,2919190527,CA @@ -70310,7 +71490,17 @@ 2948595712,2952790015,KR 2952790016,2953314303,DE 2953314304,2953379839,UA -2953379840,2953445375,DE +2953379840,2953438191,DE +2953438192,2953438199,ES +2953438200,2953438231,DE +2953438232,2953438239,CH +2953438240,2953441263,DE +2953441264,2953441279,IT +2953441280,2953443031,DE +2953443032,2953443039,IT +2953443040,2953444183,DE +2953444184,2953444191,IT +2953444192,2953445375,DE 2953445376,2953453567,IT 2953453568,2953455615,IS 2953455616,2953457663,SK @@ -70323,7 +71513,9 @@ 2953466128,2953467903,EU 2953467904,2953469951,BE 2953469952,2953478143,CH -2953478144,2953510911,SE +2953478144,2953503551,SE +2953503552,2953503559,NO +2953503560,2953510911,SE 2953510912,2953576447,NO 2953576448,2953592831,BG 2953592832,2953596927,IR @@ -70331,6 +71523,7 @@ 2953598976,2953601023,IT 2953601024,2953603071,RU 2953603072,2953605119,GB +2953605120,2953609215,CZ 2953609216,2953707519,IL 2953707520,2953838591,RU 2953838592,2954100735,SA @@ -70343,14 +71536,451 @@ 2954647552,2954657791,ES 2954657792,2954756095,JO 2954756096,2954821631,TR -2954821632,2954870783,FR +2954821632,2954838015,FR +2954838016,2954838019,PL +2954838020,2954838047,FR +2954838048,2954838055,DE +2954838056,2954838087,FR +2954838088,2954838091,IT +2954838092,2954838095,FR +2954838096,2954838099,ES +2954838100,2954838111,FR +2954838112,2954838115,CZ +2954838116,2954838119,GB +2954838120,2954838123,CZ +2954838124,2954838127,IT +2954838128,2954838135,FR +2954838136,2954838139,ES +2954838140,2954838143,CH +2954838144,2954838151,FR +2954838152,2954838159,BE +2954838160,2954838167,FR +2954838168,2954838171,NL +2954838172,2954838175,IT +2954838176,2954838179,GB +2954838180,2954838183,DE +2954838184,2954838191,IT +2954838192,2954838199,NL +2954838200,2954838203,ES +2954838204,2954838207,DE +2954838208,2954838211,ES +2954838212,2954838215,IE +2954838216,2954838219,GB +2954838220,2954838223,ES +2954838224,2954838239,FR +2954838240,2954838263,PL +2954838264,2954838271,IT +2954838272,2954838279,DE +2954838280,2954838287,IT +2954838288,2954838303,BE +2954838304,2954838371,FR +2954838372,2954838375,GB +2954838376,2954838379,NL +2954838380,2954838383,PL +2954838384,2954854403,FR +2954854404,2954854407,IT +2954854408,2954854411,FR +2954854412,2954854415,PL +2954854416,2954854431,GB +2954854432,2954854495,FR +2954854496,2954854527,ES +2954854528,2954854619,FR +2954854620,2954854623,IT +2954854624,2954854691,FR +2954854692,2954854695,IT +2954854696,2954854699,PL +2954854700,2954854703,GB +2954854704,2954854711,FR +2954854712,2954854719,DE +2954854720,2954854783,ES +2954854784,2954854799,FR +2954854800,2954854815,FI +2954854816,2954854847,FR +2954854848,2954854851,PL +2954854852,2954854855,GB +2954854856,2954854863,FR +2954854864,2954854867,NL +2954854868,2954854871,GB +2954854872,2954854875,ES +2954854876,2954854895,FR +2954854896,2954854903,PL +2954854904,2954855039,FR +2954855040,2954855043,ES +2954855044,2954855047,FR +2954855048,2954855051,PL +2954855052,2954855055,ES +2954855056,2954855059,PL +2954855060,2954855063,ES +2954855064,2954855067,BE +2954855068,2954855071,ES +2954855072,2954855075,FR +2954855076,2954855079,DE +2954855080,2954855087,GB +2954855088,2954855103,FR +2954855104,2954855167,IE +2954855168,2954855199,GB +2954855200,2954855207,FR +2954855208,2954855211,NL +2954855212,2954855215,CH +2954855216,2954855295,FR +2954855296,2954855359,BE +2954855360,2954855439,FR +2954855440,2954855455,LT +2954855456,2954855479,FR +2954855480,2954855487,IT +2954855488,2954855527,GB +2954855528,2954855535,PT +2954855536,2954855551,FR +2954855552,2954855567,GB +2954855568,2954855571,FR +2954855572,2954855575,PT +2954855576,2954855583,DE +2954855584,2954855615,FR +2954855616,2954855619,IE +2954855620,2954855623,FR +2954855624,2954855627,IT +2954855628,2954855631,GB +2954855632,2954855639,FI +2954855640,2954855643,PL +2954855644,2954855655,GB +2954855656,2954855659,CH +2954855660,2954855663,FR +2954855664,2954855679,ES +2954855680,2954855711,FR +2954855712,2954855743,PL +2954855744,2954855807,FR +2954855808,2954855871,IE +2954855872,2954855879,FR +2954855880,2954855887,ES +2954855888,2954855903,FR +2954855904,2954855919,PL +2954855920,2954855999,FR +2954856000,2954856063,PL +2954856064,2954856067,FR +2954856068,2954856071,PL +2954856072,2954856079,FR +2954856080,2954856083,ES +2954856084,2954856087,FR +2954856088,2954856095,ES +2954856096,2954856167,FR +2954856168,2954856175,ES +2954856176,2954856187,PL +2954856188,2954856447,FR +2954856448,2954856511,ES +2954856512,2954856559,FR +2954856560,2954856567,BE +2954856568,2954856571,FR +2954856572,2954856575,PL +2954856576,2954856583,ES +2954856584,2954856587,FR +2954856588,2954856591,GB +2954856592,2954856607,PL +2954856608,2954856611,BE +2954856612,2954856619,ES +2954856620,2954856623,GB +2954856624,2954856627,IT +2954856628,2954856631,GB +2954856632,2954856635,FR +2954856636,2954856639,DE +2954856640,2954856671,IT +2954856672,2954856687,NL +2954856688,2954856691,BE +2954856692,2954856699,FR +2954856700,2954856959,PL +2954856960,2954856975,ES +2954856976,2954856979,PL +2954856980,2954856983,FR +2954856984,2954856987,GB +2954856988,2954856991,FR +2954856992,2954856999,FI +2954857000,2954857007,PL +2954857008,2954857087,FR +2954857088,2954857091,PL +2954857092,2954857095,CZ +2954857096,2954857099,PL +2954857100,2954857111,GB +2954857112,2954857115,PL +2954857116,2954857119,IE +2954857120,2954857135,PT +2954857136,2954857143,LT +2954857144,2954857151,ES +2954857152,2954857215,IE +2954857216,2954857343,GB +2954857344,2954857351,ES +2954857352,2954857355,PT +2954857356,2954857359,IT +2954857360,2954857367,FR +2954857368,2954857375,PT +2954857376,2954857383,PL +2954857384,2954857407,GB +2954857408,2954857423,CH +2954857424,2954857431,GB +2954857432,2954857435,IT +2954857436,2954857439,PL +2954857440,2954857471,PT +2954857472,2954857503,FR +2954857504,2954857519,IT +2954857520,2954857523,FR +2954857524,2954857527,IE +2954857528,2954857531,GB +2954857532,2954857535,NL +2954857536,2954857551,CH +2954857552,2954857567,IT +2954857568,2954857571,PL +2954857572,2954857575,PT +2954857576,2954857583,FR +2954857584,2954857599,ES +2954857600,2954857663,IE +2954857664,2954857695,FR +2954857696,2954857699,IE +2954857700,2954857703,ES +2954857704,2954857707,PL +2954857708,2954857711,ES +2954857712,2954857727,IE +2954857728,2954857751,FR +2954857752,2954857755,IE +2954857756,2954857759,PL +2954857760,2954857823,FR +2954857824,2954857855,ES +2954857856,2954857983,IE +2954857984,2954857999,IT +2954858000,2954858015,FR +2954858016,2954858023,PL +2954858024,2954858027,ES +2954858028,2954858031,IT +2954858032,2954858035,DE +2954858036,2954858039,PL +2954858040,2954858043,FR +2954858044,2954858047,IE +2954858048,2954858055,PT +2954858056,2954858059,IE +2954858060,2954858063,PL +2954858064,2954858079,IE +2954858080,2954858095,PT +2954858096,2954858111,ES +2954858112,2954858143,DE +2954858144,2954858175,ES +2954858176,2954858191,PL +2954858192,2954858207,IE +2954858208,2954858239,IT +2954858240,2954858271,NL +2954858272,2954858303,GB +2954858304,2954858335,DE +2954858336,2954858351,FR +2954858352,2954858383,PL +2954858384,2954858415,FR +2954858416,2954858423,GB +2954858424,2954858427,DE +2954858428,2954858431,IE +2954858432,2954858439,GB +2954858440,2954858443,FR +2954858444,2954858447,GB +2954858448,2954858463,IT +2954858464,2954858479,FR +2954858480,2954858483,NL +2954858484,2954858487,DE +2954858488,2954858491,IT +2954858492,2954858495,NL +2954858496,2954858751,ES +2954858752,2954858815,IE +2954858816,2954858819,ES +2954858820,2954858823,PT +2954858824,2954858827,GB +2954858828,2954858831,CZ +2954858832,2954858847,IE +2954858848,2954858879,GB +2954858880,2954858895,FR +2954858896,2954858911,ES +2954858912,2954858943,DE +2954858944,2954858975,ES +2954858976,2954858991,FR +2954858992,2954859007,GB +2954859008,2954859023,FR +2954859024,2954859027,IT +2954859028,2954859031,PT +2954859032,2954859043,FR +2954859044,2954859055,DE +2954859056,2954859071,FR +2954859072,2954859079,PL +2954859080,2954859087,GB +2954859088,2954859103,BE +2954859104,2954859119,PT +2954859120,2954859123,FR +2954859124,2954859127,NL +2954859128,2954859135,PT +2954859136,2954859239,FR +2954859240,2954859243,ES +2954859244,2954859247,PL +2954859248,2954859263,ES +2954859264,2954859271,FR +2954859272,2954859275,PL +2954859276,2954859279,ES +2954859280,2954859295,FR +2954859296,2954859327,PT +2954859328,2954859343,GB +2954859344,2954859391,FR +2954859392,2954859423,IT +2954859424,2954859455,GB +2954859456,2954859487,NL +2954859488,2954859495,FR +2954859496,2954859503,IT +2954859504,2954859519,GB +2954859520,2954859551,DE +2954859552,2954859559,FR +2954859560,2954859575,IT +2954859576,2954859579,FI +2954859580,2954859583,LT +2954859584,2954859647,FR +2954859648,2954859655,ES +2954859656,2954859663,NL +2954859664,2954859679,FR +2954859680,2954859695,CH +2954859696,2954859703,FR +2954859704,2954859707,GB +2954859708,2954859711,DE +2954859712,2954859775,FR +2954859776,2954859807,PL +2954859808,2954859839,GB +2954859840,2954859903,PL +2954859904,2954859935,DE +2954859936,2954859951,FR +2954859952,2954859955,PL +2954859956,2954859959,GB +2954859960,2954859963,ES +2954859964,2954860031,PL +2954860032,2954860063,DE +2954860064,2954860095,FR +2954860096,2954860103,GB +2954860104,2954860111,FR +2954860112,2954860127,DE +2954860128,2954860131,ES +2954860132,2954860135,FR +2954860136,2954860151,PL +2954860152,2954860167,IE +2954860168,2954860171,PL +2954860172,2954860175,IE +2954860176,2954860183,DE +2954860184,2954860191,ES +2954860192,2954860223,PT +2954860224,2954860231,BE +2954860232,2954860239,ES +2954860240,2954860255,FR +2954860256,2954860259,PT +2954860260,2954860263,FI +2954860264,2954860267,CZ +2954860268,2954860271,PL +2954860272,2954860275,GB +2954860276,2954860319,FR +2954860320,2954860327,DE +2954860328,2954860335,PL +2954860336,2954860351,CH +2954860352,2954860415,FR +2954860416,2954860423,PL +2954860424,2954860427,FR +2954860428,2954860431,IE +2954860432,2954860439,FR +2954860440,2954860443,IT +2954860444,2954860447,FI +2954860448,2954860479,PT +2954860480,2954860483,GB +2954860484,2954860487,FR +2954860488,2954860491,GB +2954860492,2954860495,DE +2954860496,2954860511,FR +2954860512,2954860543,DE +2954860544,2954860799,CZ +2954860800,2954860863,IE +2954860864,2954861067,FR +2954861068,2954861071,GB +2954861072,2954861087,FR +2954861088,2954861119,CH +2954861120,2954861135,FR +2954861136,2954861143,GB +2954861144,2954861167,ES +2954861168,2954861183,FR +2954861184,2954861191,IT +2954861192,2954861195,FR +2954861196,2954861199,IE +2954861200,2954861215,GB +2954861216,2954861231,FR +2954861232,2954861239,PL +2954861240,2954861247,FR +2954861248,2954861311,PL +2954861312,2954861323,FR +2954861324,2954861327,IT +2954861328,2954861343,NL +2954861344,2954861359,FR +2954861360,2954861363,IE +2954861364,2954861367,FR +2954861368,2954861371,ES +2954861372,2954861375,PT +2954861376,2954861407,DE +2954861408,2954861423,FR +2954861424,2954861431,CH +2954861432,2954861571,FR +2954861572,2954861575,GB +2954861576,2954861599,FR +2954861600,2954861615,PT +2954861616,2954861623,FR +2954861624,2954861631,IT +2954861632,2954861635,NL +2954861636,2954861639,GB +2954861640,2954861647,PL +2954861648,2954861651,FR +2954861652,2954861655,GB +2954861656,2954861659,FR +2954861660,2954861663,PL +2954861664,2954861671,ES +2954861672,2954861675,NL +2954861676,2954861687,PL +2954861688,2954861691,GB +2954861692,2954861695,FR +2954861696,2954861763,GB +2954861764,2954861767,PL +2954861768,2954861779,FR +2954861780,2954861783,DE +2954861784,2954861787,FR +2954861788,2954861791,PL +2954861792,2954861823,GB +2954861824,2954861827,PL +2954861828,2954861831,GB +2954861832,2954861835,DE +2954861836,2954861839,PL +2954861840,2954861843,GB +2954861844,2954861847,PL +2954861848,2954861863,FR +2954861864,2954861867,NL +2954861868,2954861871,FR +2954861872,2954861887,IE +2954861888,2954861919,PT +2954861920,2954861923,PL +2954861924,2954861927,ES +2954861928,2954861935,FR +2954861936,2954861943,DE +2954861944,2954861955,FR +2954861956,2954861967,GB +2954861968,2954861975,IE +2954861976,2954861983,DE +2954861984,2954862015,GB +2954862016,2954862047,NL +2954862048,2954862143,FR +2954862144,2954862207,ES +2954862208,2954862211,PL +2954862212,2954862215,PT +2954862216,2954862219,FR +2954862220,2954862223,DE +2954862224,2954862239,FR +2954862240,2954862247,IT +2954862248,2954862271,FR +2954862272,2954862303,FI +2954862304,2954870783,FR 2954870784,2954870787,DE 2954870788,2954870799,GB 2954870800,2954870831,FR 2954870832,2954870835,PL 2954870836,2954870839,GB 2954870840,2954870843,DE -2954870844,2954870847,GB +2954870844,2954870847,FR 2954870848,2954870863,PL 2954870864,2954870871,FR 2954870872,2954870875,ES @@ -70370,13 +72000,16 @@ 2954871636,2954871639,ES 2954871640,2954871643,FR 2954871644,2954871647,IT -2954871648,2954871663,FR -2954871664,2954871671,IE -2954871672,2954871703,FR +2954871648,2954871667,FR +2954871668,2954871671,PL +2954871672,2954871695,FR +2954871696,2954871703,DE 2954871704,2954871707,CH -2954871708,2954871711,IT -2954871712,2954871807,FR -2954871808,2954871823,NL +2954871708,2954871711,GB +2954871712,2954871743,FR +2954871744,2954871759,PT +2954871760,2954871807,FR +2954871808,2954871823,ES 2954871824,2954871831,FR 2954871832,2954871839,PL 2954871840,2954871887,FR @@ -70391,17 +72024,20 @@ 2954871948,2954871951,DE 2954871952,2954871955,ES 2954871956,2954871959,PT -2954871960,2954871967,FR +2954871960,2954871963,IE +2954871964,2954871967,FR 2954871968,2954871999,PL 2954872000,2954872323,FR 2954872324,2954872327,PL 2954872328,2954872335,DE -2954872336,2954872351,ES +2954872336,2954872351,FR 2954872352,2954872383,DE 2954872384,2954872415,GB -2954872416,2954872419,DE +2954872416,2954872419,ES 2954872420,2954872435,PL -2954872436,2954872587,FR +2954872436,2954872439,FR +2954872440,2954872447,PL +2954872448,2954872587,FR 2954872588,2954872591,DE 2954872592,2954872607,IT 2954872608,2954872639,FR @@ -70428,8 +72064,296 @@ 2954873632,2954873635,NL 2954873636,2954873639,PL 2954873640,2954873647,FR -2954873648,2954873663,GB -2954873664,2954887167,FR +2954873648,2954873663,PL +2954873664,2954873679,IT +2954873680,2954873695,FR +2954873696,2954873727,ES +2954873728,2954873759,FR +2954873760,2954873791,DE +2954873792,2954873803,FR +2954873804,2954873807,NL +2954873808,2954873815,DE +2954873816,2954873819,FI +2954873820,2954873831,FR +2954873832,2954873835,IT +2954873836,2954873839,PL +2954873840,2954873847,IT +2954873848,2954873851,GB +2954873852,2954873855,PL +2954873856,2954874111,GB +2954874112,2954874367,FR +2954874368,2954874371,BE +2954874372,2954874375,GB +2954874376,2954874387,FR +2954874388,2954874391,PL +2954874392,2954874415,IE +2954874416,2954874419,NL +2954874420,2954874423,FR +2954874424,2954874427,GB +2954874428,2954874431,ES +2954874432,2954874495,FR +2954874496,2954874559,NL +2954874560,2954874567,GB +2954874568,2954874591,FR +2954874592,2954874623,PT +2954874624,2954874627,BE +2954874628,2954874631,FR +2954874632,2954874639,GB +2954874640,2954874647,ES +2954874648,2954874651,FR +2954874652,2954874655,PL +2954874656,2954874671,FR +2954874672,2954874675,PL +2954874676,2954874679,GB +2954874680,2954874687,FR +2954874688,2954874719,IE +2954874720,2954874751,FI +2954874752,2954874799,IE +2954874800,2954874815,GB +2954874816,2954874827,FR +2954874828,2954874831,PL +2954874832,2954874855,FR +2954874856,2954874859,GB +2954874860,2954874863,LT +2954874864,2954874867,FR +2954874868,2954874871,PL +2954874872,2954874919,FR +2954874920,2954874923,PL +2954874924,2954874927,FR +2954874928,2954874943,PL +2954874944,2954874975,IE +2954874976,2954874979,PL +2954874980,2954874983,DE +2954874984,2954874987,GB +2954874988,2954874991,PL +2954874992,2954875007,IE +2954875008,2954875039,FR +2954875040,2954875047,PL +2954875048,2954875051,FR +2954875052,2954875055,NL +2954875056,2954875063,IT +2954875064,2954875067,DE +2954875068,2954875071,FI +2954875072,2954875075,NL +2954875076,2954875079,GB +2954875080,2954875099,FR +2954875100,2954875103,PL +2954875104,2954875199,FR +2954875200,2954875203,PL +2954875204,2954875207,DE +2954875208,2954875215,NL +2954875216,2954875231,FR +2954875232,2954875263,ES +2954875264,2954875295,FR +2954875296,2954875311,PL +2954875312,2954875327,FR +2954875328,2954875359,PL +2954875360,2954875383,FR +2954875384,2954875391,DE +2954875392,2954875463,ES +2954875464,2954875467,NL +2954875468,2954875471,GB +2954875472,2954875487,FR +2954875488,2954875491,LT +2954875492,2954875495,GB +2954875496,2954875503,IT +2954875504,2954875519,FR +2954875520,2954875543,PL +2954875544,2954875551,FR +2954875552,2954875583,PL +2954875584,2954875587,ES +2954875588,2954875591,IT +2954875592,2954875599,FR +2954875600,2954875615,PT +2954875616,2954875623,PL +2954875624,2954875627,DE +2954875628,2954875631,ES +2954875632,2954875639,FR +2954875640,2954875647,BE +2954875648,2954875651,ES +2954875652,2954875655,BE +2954875656,2954875659,FR +2954875660,2954875663,PT +2954875664,2954875671,ES +2954875672,2954875679,FR +2954875680,2954875711,PT +2954875712,2954875775,IE +2954875776,2954875903,PT +2954875904,2954875907,IT +2954875908,2954875911,CH +2954875912,2954875935,FR +2954875936,2954875951,PL +2954875952,2954875999,IE +2954876000,2954876031,GB +2954876032,2954876039,IT +2954876040,2954876043,FR +2954876044,2954876047,GB +2954876048,2954876051,ES +2954876052,2954876055,NL +2954876056,2954876059,PL +2954876060,2954876063,ES +2954876064,2954876079,FR +2954876080,2954876095,PL +2954876096,2954876111,FR +2954876112,2954876119,IE +2954876120,2954876123,CZ +2954876124,2954876127,NL +2954876128,2954876147,FR +2954876148,2954876151,BE +2954876152,2954876159,FR +2954876160,2954876167,FI +2954876168,2954876175,NL +2954876176,2954876191,FR +2954876192,2954876223,PT +2954876224,2954876231,FR +2954876232,2954876235,PL +2954876236,2954876239,IE +2954876240,2954876247,PL +2954876248,2954876287,ES +2954876288,2954876351,FR +2954876352,2954876383,ES +2954876384,2954876391,FR +2954876392,2954876395,DE +2954876396,2954876399,IE +2954876400,2954876403,GB +2954876404,2954876407,NL +2954876408,2954876411,LT +2954876412,2954876415,DE +2954876416,2954876575,PT +2954876576,2954876579,ES +2954876580,2954876583,FR +2954876584,2954876587,ES +2954876588,2954876591,DE +2954876592,2954876639,IE +2954876640,2954876643,DE +2954876644,2954876647,IT +2954876648,2954876655,FR +2954876656,2954876671,BE +2954876672,2954876703,PT +2954876704,2954876719,FR +2954876720,2954876727,GB +2954876728,2954876731,PL +2954876732,2954876735,DE +2954876736,2954876767,IT +2954876768,2954876783,GB +2954876784,2954876795,FR +2954876796,2954876799,DE +2954876800,2954876863,IE +2954876864,2954876895,DE +2954876896,2954876899,GB +2954876900,2954876903,IT +2954876904,2954876959,FR +2954876960,2954876975,DE +2954876976,2954876983,PL +2954876984,2954876987,FR +2954876988,2954876991,ES +2954876992,2954877007,PL +2954877008,2954877023,CZ +2954877024,2954877027,ES +2954877028,2954877031,PL +2954877032,2954877035,FR +2954877036,2954877039,GB +2954877040,2954877055,FR +2954877056,2954877059,PL +2954877060,2954877063,GB +2954877064,2954877071,DE +2954877072,2954877087,CH +2954877088,2954877119,GB +2954877120,2954877151,ES +2954877152,2954877159,NL +2954877160,2954877163,PL +2954877164,2954877167,FR +2954877168,2954877183,DE +2954877184,2954877455,FR +2954877456,2954877459,PL +2954877460,2954877463,FR +2954877464,2954877471,DE +2954877472,2954877503,FR +2954877504,2954877519,ES +2954877520,2954877523,BE +2954877524,2954877527,ES +2954877528,2954877535,FI +2954877536,2954877539,PL +2954877540,2954877547,FR +2954877548,2954877551,PL +2954877552,2954877583,FR +2954877584,2954877595,DE +2954877596,2954877599,PT +2954877600,2954877615,PL +2954877616,2954877631,NL +2954877632,2954877663,FR +2954877664,2954877667,GB +2954877668,2954877671,PL +2954877672,2954877675,FR +2954877676,2954877679,PL +2954877680,2954877727,FR +2954877728,2954877743,IE +2954877744,2954877775,FR +2954877776,2954877779,IT +2954877780,2954877783,A1 +2954877784,2954877791,IT +2954877792,2954877819,FR +2954877820,2954877823,PL +2954877824,2954877963,FR +2954877964,2954877967,DE +2954877968,2954877983,PT +2954877984,2954877991,LT +2954877992,2954877999,PL +2954878000,2954878007,FR +2954878008,2954878011,IT +2954878012,2954878031,GB +2954878032,2954878035,NL +2954878036,2954878039,FR +2954878040,2954878047,PL +2954878048,2954878063,FR +2954878064,2954878079,IT +2954878080,2954878095,FR +2954878096,2954878103,ES +2954878104,2954878111,FR +2954878112,2954878143,PT +2954878144,2954878207,FR +2954878208,2954878463,ES +2954878464,2954878471,CH +2954878472,2954878475,FR +2954878476,2954878495,NL +2954878496,2954878499,GB +2954878500,2954878511,FR +2954878512,2954878559,IE +2954878560,2954878575,FR +2954878576,2954878579,GB +2954878580,2954878583,DE +2954878584,2954878591,GB +2954878592,2954878607,BE +2954878608,2954878623,FI +2954878624,2954878631,PL +2954878632,2954878635,IT +2954878636,2954878639,FR +2954878640,2954878655,IT +2954878656,2954878687,PL +2954878688,2954878695,FR +2954878696,2954878703,IE +2954878704,2954878707,IT +2954878708,2954878711,PL +2954878712,2954878719,ES +2954878720,2954878763,FR +2954878764,2954878767,GB +2954878768,2954878783,FR +2954878784,2954878847,IE +2954878848,2954878855,FR +2954878856,2954878863,IE +2954878864,2954878879,IT +2954878880,2954878883,ES +2954878884,2954878887,PL +2954878888,2954878891,FR +2954878892,2954878895,GB +2954878896,2954878899,DE +2954878900,2954878903,GB +2954878904,2954878915,FR +2954878916,2954878919,PL +2954878920,2954878931,FR +2954878932,2954878939,GB +2954878940,2954878943,PL +2954878944,2954887167,FR 2954887168,2954891263,UA 2954891264,2954895359,IT 2954895360,2954897407,RU @@ -70440,7 +72364,9 @@ 2954905600,2954907647,IE 2954907648,2954909695,GB 2954909696,2954911743,DE -2954911744,2954919935,IE +2954911744,2954918911,IE +2954918912,2954919423,NL +2954919424,2954919935,IE 2954919936,2954928127,RU 2954928128,2954932223,PL 2954932224,2954936319,RU @@ -70600,9 +72526,13 @@ 2954942728,2954942731,RO 2954942732,2954942743,DE 2954942744,2954942747,TR -2954942748,2954942843,DE +2954942748,2954942839,DE +2954942840,2954942843,FR 2954942844,2954942847,TR -2954942848,2954942943,DE +2954942848,2954942851,FR +2954942852,2954942871,GB +2954942872,2954942875,FR +2954942876,2954942943,DE 2954942944,2954942947,TR 2954942948,2954942979,DE 2954942980,2954942983,TR @@ -70686,14 +72616,15 @@ 2954948608,2954950655,RU 2954950656,2954952703,ES 2954952704,2955018239,TR -2955018240,2955051007,IE -2955051008,2955055103,NL -2955055104,2955069439,IE +2955018240,2955026431,FR +2955026432,2955034623,NL +2955034624,2955051007,IE +2955051008,2955067391,NL +2955067392,2955069439,IE 2955069440,2955071487,NL 2955071488,2955073535,IE 2955073536,2955075583,FR -2955075584,2955081727,NL -2955081728,2955083775,IE +2955075584,2955083775,NL 2955083776,2955149311,GB 2955149312,2955411455,UA 2955411456,2955673599,TR @@ -70727,7 +72658,8 @@ 2956496896,2956500991,IR 2956500992,2956507135,RU 2956507136,2956508159,NL -2956508160,2956508671,RU +2956508160,2956508415,RU +2956508416,2956508671,FR 2956508672,2956509183,NL 2956509184,2956517375,GB 2956517376,2956521471,NL @@ -70750,6 +72682,7 @@ 2956587008,2956589055,FR 2956589056,2956593151,GB 2956593152,2956595199,ES +2956595200,2956597247,PL 2956597248,2956599295,NL 2956599296,2956607487,RU 2956607488,2956611583,PS @@ -70767,8 +72700,16 @@ 2956822528,2956823551,SE 2956823552,2956824575,US 2956824576,2956826623,PT -2956826624,2956828671,DK -2956828672,2956836863,AT +2956826624,2956827647,US +2956827648,2956828671,DK +2956828672,2956828767,BA +2956828768,2956828799,AT +2956828800,2956828943,BA +2956828944,2956828959,AT +2956828960,2956828991,BA +2956828992,2956829055,AT +2956829056,2956829695,BA +2956829696,2956836863,AT 2956836864,2956853247,SK 2956853248,2956865535,HR 2956865536,2956869631,IT @@ -70777,8 +72718,8 @@ 2956888064,2956890111,BE 2956890112,2956892159,IR 2956892160,2956894207,IT -2956894208,2956895743,BE -2956895744,2956898303,NL +2956894208,2956896255,BE +2956896256,2956898303,NL 2956898304,2956902399,RU 2956902400,2956904447,NL 2956904448,2956906495,DK @@ -70794,7 +72735,83 @@ 2957068288,2957070335,LU 2957070336,2957074431,IT 2957074432,2957082623,RU -2957082624,2957115391,DE +2957082624,2957093887,DE +2957093888,2957096959,CH +2957096960,2957105912,DE +2957105913,2957105918,AT +2957105919,2957106168,DE +2957106169,2957106174,AT +2957106175,2957106424,DE +2957106425,2957106430,AT +2957106431,2957106680,DE +2957106681,2957106686,AT +2957106687,2957106936,DE +2957106937,2957106942,AT +2957106943,2957107192,DE +2957107193,2957107198,AT +2957107199,2957107448,DE +2957107449,2957107454,AT +2957107455,2957107704,DE +2957107705,2957107710,AT +2957107711,2957107960,DE +2957107961,2957107966,AT +2957107967,2957108216,DE +2957108217,2957108222,AT +2957108223,2957108472,DE +2957108473,2957108478,AT +2957108479,2957108728,DE +2957108729,2957108734,AT +2957108735,2957108984,DE +2957108985,2957108990,AT +2957108991,2957109240,DE +2957109241,2957109246,AT +2957109247,2957109496,DE +2957109497,2957109502,AT +2957109503,2957109752,DE +2957109753,2957109758,AT +2957109759,2957110008,DE +2957110009,2957110014,AT +2957110015,2957110264,DE +2957110265,2957110270,AT +2957110271,2957110520,DE +2957110521,2957110526,AT +2957110527,2957110776,DE +2957110777,2957110782,AT +2957110783,2957111032,DE +2957111033,2957111038,AT +2957111039,2957111288,DE +2957111289,2957111294,AT +2957111295,2957111544,DE +2957111545,2957111550,AT +2957111551,2957111800,DE +2957111801,2957111806,AT +2957111807,2957112056,DE +2957112057,2957112062,AT +2957112063,2957112312,DE +2957112313,2957112318,AT +2957112319,2957112568,DE +2957112569,2957112574,AT +2957112575,2957112824,DE +2957112825,2957112830,AT +2957112831,2957113080,DE +2957113081,2957113086,AT +2957113087,2957113336,DE +2957113337,2957113342,AT +2957113343,2957113592,DE +2957113593,2957113598,AT +2957113599,2957113848,DE +2957113849,2957113854,AT +2957113855,2957114104,DE +2957114105,2957114110,AT +2957114111,2957114360,DE +2957114361,2957114366,AT +2957114367,2957114616,DE +2957114617,2957114622,AT +2957114623,2957114872,DE +2957114873,2957114878,AT +2957114879,2957115128,DE +2957115129,2957115134,AT +2957115135,2957115391,DE 2957115392,2957180927,AT 2957180928,2957189119,UA 2957189120,2957193215,LV @@ -70819,7 +72836,11 @@ 2957201872,2957201887,RU 2957201888,2957201903,KR 2957201904,2957201919,TW -2957201920,2957202431,US +2957201920,2957202175,US +2957202176,2957202179,GB +2957202180,2957202183,BR +2957202184,2957202187,CA +2957202188,2957202431,US 2957202432,2957202463,GB 2957202464,2957202467,PL 2957202468,2957202471,KR @@ -70908,7 +72929,17 @@ 2957203120,2957203123,US 2957203124,2957203127,MT 2957203128,2957203131,RS -2957203132,2957203455,US +2957203132,2957203199,US +2957203200,2957203203,AU +2957203204,2957203207,US +2957203208,2957203211,SE +2957203212,2957203215,FR +2957203216,2957203219,ZA +2957203220,2957203223,CH +2957203224,2957203227,DE +2957203228,2957203231,PL +2957203232,2957203263,GB +2957203264,2957203455,US 2957203456,2957205503,FR 2957205504,2957213695,PS 2957213696,2957221887,FR @@ -70944,7 +72975,8 @@ 2957901824,2958032895,PT 2958032896,2958557183,ES 2958557184,2958819327,TR -2958819328,2958884863,CY +2958819328,2958884863,GR +2958884864,2958950399,FI 2958950400,2959081471,DE 2959081472,2959089663,RU 2959089664,2959093759,PL @@ -70962,13 +72994,50 @@ 2959128576,2959130623,RU 2959130624,2959138815,UA 2959138816,2959147007,RU +2959147008,2959149055,UA +2959149056,2959151103,CZ +2959151104,2959155199,PL +2959155200,2959159295,RU +2959159296,2959161343,PL +2959161344,2959163391,RO +2959163392,2959167487,UA +2959167488,2959171583,PL +2959171584,2959175679,RU +2959175680,2959179775,UA +2959179776,2959181823,RU +2959181824,2959183871,PL +2959183872,2959187967,RO +2959187968,2959204351,RU +2959204352,2959208447,RO +2959208448,2959210495,CZ +2959210496,2959212543,PL +2959212544,2959220735,UA +2959220736,2959224831,RO +2959224832,2959226879,UA +2959226880,2959228927,RO +2959228928,2959237119,UA +2959237120,2959241215,CZ +2959241216,2959245311,PL +2959245312,2959253503,RU +2959253504,2959255551,DE +2959255552,2959261695,RU +2959261696,2959278079,KZ +2959278080,2959343615,DE +2959343616,2959351807,UA +2959351808,2959353855,DE +2959353856,2959355903,RU +2959355904,2959357951,RO +2959357952,2959359999,UA +2959360000,2959384575,RU +2959384576,2959392767,UA 2961178624,2965372927,FR 2965372928,2965766143,RU 2965766144,2965897215,DE 2965897216,2966028287,IT 2966028288,2966159359,QA 2966159360,2966290431,AE -2966421504,2966683647,RU +2966290432,2966421503,IT +2966421504,2966945791,RU 2969567232,2977955839,BR 2986344448,2987393023,DE 2987393024,2987397119,IM @@ -71196,11 +73265,8 @@ 2988179456,2988441599,SE 2988441600,2988441603,CH 2988441604,2988441607,GB -2988441608,2988441611,DE -2988441612,2988441615,CH -2988441616,2988441647,FR -2988441648,2988441651,GB -2988441652,2988441655,FR +2988441608,2988441615,CH +2988441616,2988441655,FR 2988441656,2988441663,DE 2988441664,2988441695,IT 2988441696,2988441791,FR @@ -71229,7 +73295,7 @@ 2988441984,2988441991,FR 2988441992,2988441995,ES 2988441996,2988441999,PT -2988442000,2988442003,FR +2988442000,2988442003,PL 2988442004,2988442007,ES 2988442008,2988442047,FR 2988442048,2988442063,GB @@ -71261,7 +73327,9 @@ 2988442920,2988442923,LT 2988442924,2988442927,GB 2988442928,2988442975,FR -2988442976,2988443007,GB +2988442976,2988442995,GB +2988442996,2988442999,IE +2988443000,2988443007,GB 2988443008,2988443023,PT 2988443024,2988443027,CZ 2988443028,2988443031,BE @@ -71336,7 +73404,9 @@ 2988445984,2988446207,DE 2988446208,2988446271,PL 2988446272,2988446275,IT -2988446276,2988446291,FR +2988446276,2988446279,FR +2988446280,2988446287,ES +2988446288,2988446291,FR 2988446292,2988446295,ES 2988446296,2988446299,GB 2988446300,2988446307,FR @@ -71374,9 +73444,7 @@ 2988448608,2988448639,ES 2988448640,2988448671,GB 2988448672,2988448691,IT -2988448692,2988448695,DE -2988448696,2988448699,IT -2988448700,2988448703,LT +2988448692,2988448703,DE 2988448704,2988448767,GB 2988448768,2988448783,FR 2988448784,2988448815,PL @@ -71385,9 +73453,7 @@ 2988448896,2988448899,PT 2988448900,2988448903,PL 2988448904,2988448907,ES -2988448908,2988448959,FR -2988448960,2988448991,DE -2988448992,2988449007,FR +2988448908,2988449007,FR 2988449008,2988449023,GB 2988449024,2988449055,PL 2988449056,2988449087,ES @@ -71397,8 +73463,15 @@ 2988449124,2988449127,DE 2988449128,2988449135,ES 2988449136,2988449151,FR -2988449152,2988449279,PL -2988449280,2988449535,GB +2988449152,2988449167,PL +2988449168,2988449175,GB +2988449176,2988449183,FR +2988449184,2988449199,PL +2988449200,2988449203,FR +2988449204,2988449207,PL +2988449208,2988449215,ES +2988449216,2988449247,FR +2988449248,2988449535,GB 2988449536,2988449579,FR 2988449580,2988449583,PL 2988449584,2988449631,FR @@ -71433,7 +73506,8 @@ 2988458280,2988458283,ES 2988458284,2988458295,FR 2988458296,2988458299,GB -2988458300,2988458319,ES +2988458300,2988458303,ES +2988458304,2988458319,FR 2988458320,2988458323,CZ 2988458324,2988458331,FR 2988458332,2988458335,GB @@ -71470,16 +73544,21 @@ 2988459184,2988459199,PL 2988459200,2988459223,FR 2988459224,2988459231,DE -2988459232,2988459235,IT +2988459232,2988459235,FR 2988459236,2988459239,PL 2988459240,2988459243,FR 2988459244,2988459247,ES 2988459248,2988459251,LT 2988459252,2988459255,GB 2988459256,2988459259,FR -2988459260,2988459263,NL +2988459260,2988459263,PL 2988459264,2988459519,ES -2988459520,2988459583,FR +2988459520,2988459535,FR +2988459536,2988459539,GB +2988459540,2988459543,PL +2988459544,2988459547,ES +2988459548,2988459551,PL +2988459552,2988459583,FR 2988459584,2988459599,ES 2988459600,2988459603,GB 2988459604,2988459615,FR @@ -71497,7 +73576,7 @@ 2988459716,2988459719,FR 2988459720,2988459727,DE 2988459728,2988459731,FR -2988459732,2988459735,BE +2988459732,2988459735,ES 2988459736,2988459743,PL 2988459744,2988459747,ES 2988459748,2988459751,PL @@ -71545,7 +73624,7 @@ 2988460336,2988460339,FR 2988460340,2988460343,GB 2988460344,2988460367,FR -2988460368,2988460375,ES +2988460368,2988460375,PL 2988460376,2988460543,FR 2988460544,2988460547,GB 2988460548,2988460551,DE @@ -71556,9 +73635,7 @@ 2988460616,2988460623,PT 2988460624,2988460679,FR 2988460680,2988460687,DE -2988460688,2988460719,FR -2988460720,2988460735,ES -2988460736,2988460755,FR +2988460688,2988460755,FR 2988460756,2988460759,PT 2988460760,2988460767,FR 2988460768,2988460799,PL @@ -71590,7 +73667,7 @@ 2988461424,2988461431,IT 2988461432,2988461435,PT 2988461436,2988461439,BE -2988461440,2988461471,FR +2988461440,2988461471,FI 2988461472,2988461475,PL 2988461476,2988461479,IE 2988461480,2988461483,CZ @@ -71603,8 +73680,12 @@ 2988461520,2988461523,GB 2988461524,2988461559,FR 2988461560,2988461567,GB -2988461568,2988461599,FR -2988461600,2988461615,BE +2988461568,2988461583,FR +2988461584,2988461587,ES +2988461588,2988461591,GB +2988461592,2988461595,ES +2988461596,2988461599,GB +2988461600,2988461615,FR 2988461616,2988461623,IT 2988461624,2988461695,FR 2988461696,2988461699,DE @@ -71633,8 +73714,8 @@ 2988461872,2988461879,FR 2988461880,2988461883,ES 2988461884,2988461887,PL -2988461888,2988461903,FR -2988461904,2988461911,ES +2988461888,2988461907,FR +2988461908,2988461911,ES 2988461912,2988461915,IT 2988461916,2988461919,NL 2988461920,2988461935,FR @@ -71741,8 +73822,7 @@ 2988463836,2988463839,FR 2988463840,2988463871,PL 2988463872,2988463907,FR -2988463908,2988463911,PL -2988463912,2988463915,FR +2988463908,2988463915,PL 2988463916,2988463919,GB 2988463920,2988463939,FR 2988463940,2988463943,DE @@ -71772,9 +73852,7 @@ 2988464356,2988464359,FR 2988464360,2988464363,PL 2988464364,2988464367,GB -2988464368,2988464511,FR -2988464512,2988464519,PT -2988464520,2988464527,FR +2988464368,2988464527,FR 2988464528,2988464543,DE 2988464544,2988464551,FR 2988464552,2988464555,IT @@ -71795,12 +73873,12 @@ 2988464796,2988464799,GB 2988464800,2988464815,DE 2988464816,2988464819,FR -2988464820,2988464823,NL +2988464820,2988464823,GB 2988464824,2988464827,ES -2988464828,2988464831,GB +2988464828,2988464831,PL 2988464832,2988464895,ES 2988464896,2988464911,PL -2988464912,2988464915,CH +2988464912,2988464915,FR 2988464916,2988464919,DE 2988464920,2988464923,FI 2988464924,2988464927,FR @@ -71814,7 +73892,8 @@ 2988464968,2988464971,PT 2988464972,2988464975,PL 2988464976,2988465215,FR -2988465216,2988465223,ES +2988465216,2988465219,ES +2988465220,2988465223,IE 2988465224,2988465235,FR 2988465236,2988465239,ES 2988465240,2988465279,FR @@ -71860,12 +73939,13 @@ 2988465620,2988465623,ES 2988465624,2988465631,FR 2988465632,2988465647,IT -2988465648,2988465663,CZ +2988465648,2988465655,CZ +2988465656,2988465663,GB 2988465664,2988466047,FR 2988466048,2988466111,PL 2988466112,2988466115,FR 2988466116,2988466127,NL -2988466128,2988466131,PT +2988466128,2988466131,PL 2988466132,2988466139,FR 2988466140,2988466143,PL 2988466144,2988466159,NL @@ -71905,15 +73985,17 @@ 2988482888,2988482891,ES 2988482892,2988482895,PL 2988482896,2988482927,GB -2988482928,2988482935,FR -2988482936,2988482939,PL +2988482928,2988482931,FR +2988482932,2988482939,PL 2988482940,2988482943,LT 2988482944,2988482959,PL 2988482960,2988482975,CZ 2988482976,2988482979,DE 2988482980,2988482983,GB 2988482984,2988482987,DE -2988482988,2988483091,FR +2988482988,2988483035,FR +2988483036,2988483039,GB +2988483040,2988483091,FR 2988483092,2988483095,BE 2988483096,2988483099,FR 2988483100,2988483103,PL @@ -71982,9 +74064,10 @@ 2988484024,2988484031,FR 2988484032,2988484039,IT 2988484040,2988484047,NL -2988484048,2988484051,FR +2988484048,2988484051,ES 2988484052,2988484055,GB -2988484056,2988484095,FR +2988484056,2988484063,FR +2988484064,2988484095,GB 2988484096,2988484111,DE 2988484112,2988484127,FR 2988484128,2988484131,PT @@ -72074,7 +74157,7 @@ 2988485616,2988485631,GB 2988485632,2988485663,ES 2988485664,2988485671,PL -2988485672,2988485675,ES +2988485672,2988485675,DE 2988485676,2988485683,FR 2988485684,2988485687,PL 2988485688,2988485691,GB @@ -72113,7 +74196,11 @@ 2988486076,2988486079,ES 2988486080,2988486083,BE 2988486084,2988486087,IT -2988486088,2988486111,FR +2988486088,2988486095,FR +2988486096,2988486099,CH +2988486100,2988486103,CZ +2988486104,2988486107,DE +2988486108,2988486111,IE 2988486112,2988486135,PL 2988486136,2988486139,FR 2988486140,2988486143,GB @@ -72124,9 +74211,9 @@ 2988486180,2988486183,DE 2988486184,2988486191,IE 2988486192,2988486195,IT -2988486196,2988486199,DE +2988486196,2988486199,FR 2988486200,2988486207,PT -2988486208,2988486211,ES +2988486208,2988486211,PL 2988486212,2988486215,DE 2988486216,2988486219,ES 2988486220,2988486223,IT @@ -72135,8 +74222,7 @@ 2988486236,2988486239,ES 2988486240,2988486287,PL 2988486288,2988486291,FR -2988486292,2988486295,DE -2988486296,2988486299,GB +2988486292,2988486299,GB 2988486300,2988486319,PL 2988486320,2988486323,IT 2988486324,2988486327,PT @@ -72144,7 +74230,9 @@ 2988486344,2988486347,FR 2988486348,2988486351,ES 2988486352,2988486399,FR -2988486400,2988486431,GB +2988486400,2988486415,PL +2988486416,2988486423,FR +2988486424,2988486431,PT 2988486432,2988486447,FR 2988486448,2988486463,ES 2988486464,2988486471,BE @@ -72152,7 +74240,8 @@ 2988486476,2988486479,PL 2988486480,2988486495,IE 2988486496,2988486503,DE -2988486504,2988486515,ES +2988486504,2988486511,PL +2988486512,2988486515,DE 2988486516,2988486527,PL 2988486528,2988486575,FR 2988486576,2988486579,PL @@ -72167,10 +74256,24 @@ 2988486644,2988486647,GB 2988486648,2988486651,ES 2988486652,2988486655,PL -2988486656,2988486719,GB -2988486720,2988486735,CZ -2988486736,2988486751,FR -2988486752,2988486783,GB +2988486656,2988486671,FR +2988486672,2988486675,DE +2988486676,2988486679,FR +2988486680,2988486687,ES +2988486688,2988486691,PL +2988486692,2988486695,FR +2988486696,2988486699,ES +2988486700,2988486711,PL +2988486712,2988486719,IT +2988486720,2988486735,FR +2988486736,2988486743,ES +2988486744,2988486747,FR +2988486748,2988486751,GB +2988486752,2988486759,PL +2988486760,2988486763,ES +2988486764,2988486767,FR +2988486768,2988486775,ES +2988486776,2988486783,BE 2988486784,2988486787,DE 2988486788,2988486795,FR 2988486796,2988486799,PL @@ -72211,18 +74314,20 @@ 2988488128,2988488159,FR 2988488160,2988488175,ES 2988488176,2988488179,GB -2988488180,2988488183,DE +2988488180,2988488183,FR 2988488184,2988488187,IT 2988488188,2988488191,DE 2988488192,2988488479,FR 2988488480,2988488487,PL 2988488488,2988488491,FR 2988488492,2988488495,ES -2988488496,2988488511,FR -2988488512,2988488543,ES -2988488544,2988488575,FR -2988488576,2988488607,NL -2988488608,2988488639,IT +2988488496,2988488543,FR +2988488544,2988488555,GB +2988488556,2988488563,ES +2988488564,2988488567,FR +2988488568,2988488571,ES +2988488572,2988488575,GB +2988488576,2988488639,FR 2988488640,2988488647,ES 2988488648,2988488655,IT 2988488656,2988488663,PL @@ -72325,14 +74430,13 @@ 2988490192,2988490195,GB 2988490196,2988490199,PT 2988490200,2988490203,DE -2988490204,2988490207,ES -2988490208,2988490223,FR +2988490204,2988490223,FR 2988490224,2988490227,DE 2988490228,2988490231,GB 2988490232,2988490239,ES 2988490240,2988490247,PL 2988490248,2988490251,ES -2988490252,2988490255,FR +2988490252,2988490255,GB 2988490256,2988490271,PL 2988490272,2988490287,ES 2988490288,2988490295,FR @@ -72340,11 +74444,14 @@ 2988490304,2988490319,ES 2988490320,2988490335,FR 2988490336,2988490367,PT -2988490368,2988490379,FR +2988490368,2988490371,ES +2988490372,2988490375,NL +2988490376,2988490379,FR 2988490380,2988490383,ES 2988490384,2988490399,FR 2988490400,2988490407,GB -2988490408,2988490415,NL +2988490408,2988490411,NL +2988490412,2988490415,ES 2988490416,2988490423,GB 2988490424,2988490463,FR 2988490464,2988490623,PL @@ -72358,8 +74465,7 @@ 2988498984,2988498991,FR 2988498992,2988499007,PL 2988499008,2988499051,DE -2988499052,2988499055,IT -2988499056,2988499063,FR +2988499052,2988499063,FR 2988499064,2988499067,DE 2988499068,2988499071,FR 2988499072,2988499103,PL @@ -72370,8 +74476,7 @@ 2988499144,2988499151,DE 2988499152,2988499167,FR 2988499168,2988499199,ES -2988499200,2988499327,FR -2988499328,2988499343,NL +2988499200,2988499343,FR 2988499344,2988499347,PL 2988499348,2988499351,FR 2988499352,2988499359,IT @@ -72429,7 +74534,7 @@ 2988499848,2988499851,DE 2988499852,2988499855,PL 2988499856,2988499871,ES -2988499872,2988499903,CH +2988499872,2988499903,IE 2988499904,2988499907,FR 2988499908,2988499911,BE 2988499912,2988499915,FR @@ -72439,15 +74544,15 @@ 2988499928,2988499935,FR 2988499936,2988499967,IE 2988499968,2988500223,FR -2988500224,2988500255,NL +2988500224,2988500255,ES 2988500256,2988500271,IT 2988500272,2988500287,BE 2988500288,2988500303,PL 2988500304,2988500307,FR -2988500308,2988500311,IT +2988500308,2988500311,DE 2988500312,2988500315,ES 2988500316,2988500319,DE -2988500320,2988500335,IT +2988500320,2988500335,FR 2988500336,2988500339,DE 2988500340,2988500343,IE 2988500344,2988500347,FR @@ -72472,9 +74577,7 @@ 2988500680,2988500687,PL 2988500688,2988500703,NL 2988500704,2988500711,PL -2988500712,2988500735,FR -2988500736,2988500751,IE -2988500752,2988500767,FR +2988500712,2988500767,FR 2988500768,2988500771,PT 2988500772,2988500775,ES 2988500776,2988500779,GB @@ -72550,18 +74653,17 @@ 2988502080,2988502095,IE 2988502096,2988502099,FI 2988502100,2988502103,CZ -2988502104,2988502111,PT -2988502112,2988502143,PL +2988502104,2988502143,PL 2988502144,2988502207,FR 2988502208,2988502223,GB 2988502224,2988502255,FR -2988502256,2988502263,GB +2988502256,2988502263,DE 2988502264,2988502267,ES 2988502268,2988502271,DE 2988502272,2988502399,FR 2988502400,2988502407,NL 2988502408,2988502411,FR -2988502412,2988502415,CH +2988502412,2988502415,NL 2988502416,2988502431,DE 2988502432,2988502447,FR 2988502448,2988502451,IE @@ -72588,7 +74690,8 @@ 2988502640,2988502655,FR 2988502656,2988502719,DE 2988502720,2988502723,ES -2988502724,2988502731,FR +2988502724,2988502727,BE +2988502728,2988502731,GB 2988502732,2988502735,PL 2988502736,2988502751,FR 2988502752,2988502783,ES @@ -72622,8 +74725,9 @@ 2988503024,2988503031,GB 2988503032,2988503035,ES 2988503036,2988503039,GB -2988503040,2988503079,FR -2988503080,2988503103,GB +2988503040,2988503071,FR +2988503072,2988503075,NL +2988503076,2988503103,GB 2988503104,2988503107,ES 2988503108,2988503111,NL 2988503112,2988503119,PL @@ -72653,9 +74757,8 @@ 2988503536,2988503551,FI 2988503552,2988503871,FR 2988503872,2988503903,DE -2988503904,2988503911,FI -2988503912,2988503919,NL -2988503920,2988503927,FR +2988503904,2988503919,FR +2988503920,2988503927,ES 2988503928,2988503931,IT 2988503932,2988503935,NL 2988503936,2988503939,FR @@ -72664,8 +74767,8 @@ 2988503948,2988503951,IE 2988503952,2988503987,FR 2988503988,2988504007,PL -2988504008,2988504015,FR -2988504016,2988504019,GB +2988504008,2988504015,BE +2988504016,2988504019,FR 2988504020,2988504023,BE 2988504024,2988504031,FR 2988504032,2988504063,ES @@ -72690,7 +74793,11 @@ 2988504432,2988504435,FR 2988504436,2988504439,ES 2988504440,2988504443,FR -2988504444,2988504463,GB +2988504444,2988504447,GB +2988504448,2988504451,BE +2988504452,2988504455,ES +2988504456,2988504459,PL +2988504460,2988504463,GB 2988504464,2988504467,DE 2988504468,2988504471,ES 2988504472,2988504479,PL @@ -72711,14 +74818,17 @@ 2988504744,2988504751,GB 2988504752,2988504767,FR 2988504768,2988504799,ES -2988504800,2988504815,PL -2988504816,2988504863,FR +2988504800,2988504823,PL +2988504824,2988504827,DE +2988504828,2988504863,FR 2988504864,2988504879,PL 2988504880,2988504959,FR 2988504960,2988504963,PT 2988504964,2988504967,FR 2988504968,2988504975,BE -2988504976,2988504991,FR +2988504976,2988504983,FR +2988504984,2988504987,ES +2988504988,2988504991,FR 2988504992,2988505023,CZ 2988505024,2988505087,FR 2988505088,2988505151,NL @@ -72735,11 +74845,20 @@ 2988505312,2988505315,DE 2988505316,2988505319,ES 2988505320,2988505323,PL -2988505324,2988505327,FR +2988505324,2988505327,ES 2988505328,2988505343,PL -2988505344,2988505439,FR +2988505344,2988505375,DE +2988505376,2988505391,FR +2988505392,2988505399,PL +2988505400,2988505407,ES +2988505408,2988505439,FR 2988505440,2988505455,PL -2988505456,2988505487,FR +2988505456,2988505459,FI +2988505460,2988505463,CH +2988505464,2988505471,IT +2988505472,2988505475,ES +2988505476,2988505479,NL +2988505480,2988505487,IE 2988505488,2988505503,PL 2988505504,2988505599,FR 2988505600,2988505603,DE @@ -72760,7 +74879,7 @@ 2988505752,2988505755,CH 2988505756,2988505759,PL 2988505760,2988505775,FR -2988505776,2988505791,ES +2988505776,2988505791,GB 2988505792,2988505807,FR 2988505808,2988505811,PL 2988505812,2988505815,DE @@ -72768,7 +74887,15 @@ 2988505820,2988505823,PL 2988505824,2988505839,FR 2988505840,2988505843,CH -2988505844,2988506111,FR +2988505844,2988505851,FR +2988505852,2988505855,PL +2988505856,2988505919,IE +2988505920,2988505935,GB +2988505936,2988505951,PL +2988505952,2988505967,GB +2988505968,2988505971,BE +2988505972,2988505975,GB +2988505976,2988506111,FR 2988506112,2988506143,BE 2988506144,2988506175,PT 2988506176,2988506191,IT @@ -72802,8 +74929,8 @@ 2988506544,2988506551,DE 2988506552,2988506559,FR 2988506560,2988506563,DE -2988506564,2988506567,A2 -2988506568,2988506571,GB +2988506564,2988506567,GB +2988506568,2988506571,PL 2988506572,2988506575,CH 2988506576,2988506623,FR 2988506624,2988506687,PL @@ -72894,8 +75021,7 @@ 2988507884,2988507887,GB 2988507888,2988507903,ES 2988507904,2988507919,PL -2988507920,2988507923,DE -2988507924,2988507927,IT +2988507920,2988507927,DE 2988507928,2988507935,BE 2988507936,2988507951,FR 2988507952,2988507955,DE @@ -72911,8 +75037,7 @@ 2988508036,2988508039,CZ 2988508040,2988508047,FR 2988508048,2988508055,GB -2988508056,2988508063,ES -2988508064,2988508067,FR +2988508056,2988508067,ES 2988508068,2988508071,PL 2988508072,2988508079,FR 2988508080,2988508095,ES @@ -72945,8 +75070,8 @@ 2988508428,2988508431,CZ 2988508432,2988508435,FR 2988508436,2988508439,DE -2988508440,2988508447,PL -2988508448,2988508479,FR +2988508440,2988508455,PL +2988508456,2988508479,FR 2988508480,2988508543,PT 2988508544,2988508607,GB 2988508608,2988508671,IT @@ -72973,7 +75098,9 @@ 2988508944,2988508947,DE 2988508948,2988508951,FR 2988508952,2988508959,ES -2988508960,2988508991,FR +2988508960,2988508983,FR +2988508984,2988508987,DE +2988508988,2988508991,PL 2988508992,2988509055,NL 2988509056,2988509119,FR 2988509120,2988509151,IT @@ -73016,7 +75143,8 @@ 2988509620,2988509623,GB 2988509624,2988509627,CZ 2988509628,2988509631,IT -2988509632,2988509711,FR +2988509632,2988509695,FR +2988509696,2988509711,IT 2988509712,2988509715,IE 2988509716,2988509719,GB 2988509720,2988509727,IT @@ -73148,7 +75276,7 @@ 2988511740,2988511743,FR 2988511744,2988511747,PL 2988511748,2988511751,GB -2988511752,2988511759,CZ +2988511752,2988511759,IT 2988511760,2988511775,FR 2988511776,2988511807,GB 2988511808,2988511823,ES @@ -73239,12 +75367,14 @@ 2988512840,2988512847,DE 2988512848,2988512851,ES 2988512852,2988512855,DE -2988512856,2988512895,FR +2988512856,2988512879,FR +2988512880,2988512895,DE 2988512896,2988512899,PL -2988512900,2988512903,GB +2988512900,2988512903,ES 2988512904,2988512907,PL -2988512908,2988512943,FR -2988512944,2988512951,GB +2988512908,2988512911,ES +2988512912,2988512943,FR +2988512944,2988512951,ES 2988512952,2988512955,FR 2988512956,2988512959,LT 2988512960,2988512963,ES @@ -73288,7 +75418,9 @@ 2988513332,2988513343,FR 2988513344,2988513351,ES 2988513352,2988513359,IT -2988513360,2988513375,GB +2988513360,2988513363,DE +2988513364,2988513367,FR +2988513368,2988513375,ES 2988513376,2988513379,FR 2988513380,2988513383,PT 2988513384,2988513387,FR @@ -73381,7 +75513,8 @@ 2988514656,2988514671,FR 2988514672,2988514675,CH 2988514676,2988514679,IT -2988514680,2988514687,FR +2988514680,2988514683,GB +2988514684,2988514687,DE 2988514688,2988514719,GB 2988514720,2988514735,ES 2988514736,2988514739,FR @@ -73429,7 +75562,19 @@ 2988523740,2988523743,FR 2988523744,2988523775,PT 2988523776,2988524031,FR -2988524032,2988524159,DE +2988524032,2988524035,DE +2988524036,2988524039,LT +2988524040,2988524047,ES +2988524048,2988524055,FR +2988524056,2988524063,CZ +2988524064,2988524067,PL +2988524068,2988524075,GB +2988524076,2988524079,ES +2988524080,2988524083,GB +2988524084,2988524087,IT +2988524088,2988524111,FR +2988524112,2988524127,IT +2988524128,2988524159,FR 2988524160,2988524163,ES 2988524164,2988524167,FR 2988524168,2988524175,ES @@ -73452,7 +75597,8 @@ 2988524272,2988524287,DE 2988524288,2988524291,ES 2988524292,2988524295,IT -2988524296,2988524303,FR +2988524296,2988524299,CZ +2988524300,2988524303,FR 2988524304,2988524307,IT 2988524308,2988524319,GB 2988524320,2988524351,FR @@ -73471,8 +75617,10 @@ 2988524576,2988524591,FR 2988524592,2988524603,PL 2988524604,2988524607,ES -2988524608,2988524623,GB -2988524624,2988524639,FR +2988524608,2988524627,GB +2988524628,2988524631,IE +2988524632,2988524635,DE +2988524636,2988524639,FR 2988524640,2988524671,DE 2988524672,2988524735,FR 2988524736,2988524751,GB @@ -73515,7 +75663,10 @@ 2988526608,2988526615,DE 2988526616,2988526655,FR 2988526656,2988526663,PL -2988526664,2988526687,FR +2988526664,2988526671,FR +2988526672,2988526679,DE +2988526680,2988526683,ES +2988526684,2988526687,FR 2988526688,2988526703,ES 2988526704,2988526711,FR 2988526712,2988526715,ES @@ -73529,17 +75680,19 @@ 2988526864,2988526867,GB 2988526868,2988526871,FR 2988526872,2988526875,DE -2988526876,2988526911,FR +2988526876,2988526879,PL +2988526880,2988526911,FR 2988526912,2988526927,GB 2988526928,2988526935,DE 2988526936,2988526943,PL 2988526944,2988526951,DE -2988526952,2988526955,IE -2988526956,2988526975,FR +2988526952,2988526955,FR +2988526956,2988526959,IT +2988526960,2988526975,FR 2988526976,2988526991,PL 2988526992,2988526995,DE -2988526996,2988526999,ES -2988527000,2988527055,FR +2988526996,2988527003,ES +2988527004,2988527055,FR 2988527056,2988527071,BE 2988527072,2988527087,FR 2988527088,2988527095,GB @@ -73569,7 +75722,8 @@ 2988527440,2988527451,PL 2988527452,2988527455,PT 2988527456,2988527459,LT -2988527460,2988527475,FR +2988527460,2988527463,IE +2988527464,2988527475,FR 2988527476,2988527479,ES 2988527480,2988527487,FR 2988527488,2988527503,GB @@ -73579,7 +75733,7 @@ 2988527536,2988527551,GB 2988527552,2988527583,PL 2988527584,2988527591,GB -2988527592,2988527595,IT +2988527592,2988527595,IE 2988527596,2988527599,DE 2988527600,2988527603,NL 2988527604,2988527607,FR @@ -73595,11 +75749,11 @@ 2988527680,2988527683,ES 2988527684,2988527695,FR 2988527696,2988527711,GB -2988527712,2988527743,FR -2988527744,2988527747,IE +2988527712,2988527747,FR 2988527748,2988527751,ES 2988527752,2988527755,DE -2988527756,2988527823,FR +2988527756,2988527759,PL +2988527760,2988527823,FR 2988527824,2988527827,ES 2988527828,2988527831,DE 2988527832,2988527839,ES @@ -73614,12 +75768,14 @@ 2988527968,2988527983,PL 2988527984,2988527999,FR 2988528000,2988528007,IT -2988528008,2988528015,ES +2988528008,2988528011,ES +2988528012,2988528015,PL 2988528016,2988528063,IE 2988528064,2988528071,GB 2988528072,2988528075,NL 2988528076,2988528079,BE -2988528080,2988528127,FR +2988528080,2988528095,ES +2988528096,2988528127,FR 2988528128,2988528159,GB 2988528160,2988528175,ES 2988528176,2988528179,CH @@ -73630,13 +75786,15 @@ 2988528208,2988528215,FR 2988528216,2988528219,IE 2988528220,2988528223,DE -2988528224,2988528231,CH +2988528224,2988528227,FR +2988528228,2988528231,IE 2988528232,2988528235,GB 2988528236,2988528239,FR 2988528240,2988528263,GB 2988528264,2988528267,PL 2988528268,2988528271,FR -2988528272,2988528303,GB +2988528272,2988528287,IE +2988528288,2988528303,GB 2988528304,2988528351,FR 2988528352,2988528383,DE 2988528384,2988528399,GB @@ -73645,7 +75803,7 @@ 2988528424,2988528431,NL 2988528432,2988528435,PL 2988528436,2988528439,FR -2988528440,2988528447,ES +2988528440,2988528447,GB 2988528448,2988528451,DE 2988528452,2988528455,IT 2988528456,2988528459,GB @@ -73663,15 +75821,9 @@ 2988528644,2988528647,PL 2988528648,2988528671,FR 2988528672,2988528703,DE -2988528704,2988528715,ES -2988528716,2988528723,IT -2988528724,2988528727,GB -2988528728,2988528731,FR -2988528732,2988528735,DE -2988528736,2988528739,FI -2988528740,2988528743,IE -2988528744,2988528747,NL -2988528748,2988528759,PL +2988528704,2988528735,IE +2988528736,2988528755,FR +2988528756,2988528759,PL 2988528760,2988528763,GB 2988528764,2988528767,FR 2988528768,2988528771,DE @@ -73721,23 +75873,28 @@ 2988529340,2988529343,DE 2988529344,2988529351,PL 2988529352,2988529359,GB -2988529360,2988529375,IE +2988529360,2988529375,IT 2988529376,2988529383,GB 2988529384,2988529387,DE 2988529388,2988529391,FR 2988529392,2988529407,PL -2988529408,2988529423,FR +2988529408,2988529411,IT +2988529412,2988529415,NL +2988529416,2988529419,PT +2988529420,2988529423,CH 2988529424,2988529431,DE 2988529432,2988529439,FR 2988529440,2988529455,PL 2988529456,2988529535,FR 2988529536,2988529567,FI 2988529568,2988529583,FR -2988529584,2988529599,GB +2988529584,2988529591,ES +2988529592,2988529595,FR +2988529596,2988529599,GB 2988529600,2988529607,IT 2988529608,2988529631,FR 2988529632,2988529647,LT -2988529648,2988529663,FI +2988529648,2988529663,FR 2988529664,2988529679,PL 2988529680,2988529703,FR 2988529704,2988529707,DE @@ -73848,7 +76005,8 @@ 2988531260,2988531271,GB 2988531272,2988531279,ES 2988531280,2988531287,PT -2988531288,2988531295,ES +2988531288,2988531291,FR +2988531292,2988531295,PL 2988531296,2988531311,IE 2988531312,2988531319,FR 2988531320,2988531323,PT @@ -73861,7 +76019,7 @@ 2988531400,2988531403,DE 2988531404,2988531427,PL 2988531428,2988531451,FR -2988531452,2988531455,CH +2988531452,2988531455,GB 2988531456,2988535807,FR 2988535808,2988537855,ES 2988537856,2988539935,FR @@ -73888,9 +76046,7 @@ 2988540276,2988540279,PL 2988540280,2988540287,FR 2988540288,2988540303,BE -2988540304,2988540319,FR -2988540320,2988540351,PT -2988540352,2988540363,FR +2988540304,2988540363,FR 2988540364,2988540367,PL 2988540368,2988540375,FR 2988540376,2988540379,GB @@ -73941,7 +76097,9 @@ 2988540800,2988540831,FR 2988540832,2988540839,PL 2988540840,2988540847,GB -2988540848,2988540931,FR +2988540848,2988540855,FR +2988540856,2988540863,IT +2988540864,2988540931,FR 2988540932,2988540935,DE 2988540936,2988540943,FR 2988540944,2988540959,ES @@ -73970,8 +76128,7 @@ 2988541336,2988541343,FR 2988541344,2988541347,GB 2988541348,2988541351,IT -2988541352,2988541355,IE -2988541356,2988541359,IT +2988541352,2988541359,IE 2988541360,2988541367,ES 2988541368,2988541371,PL 2988541372,2988541375,GB @@ -74069,8 +76226,7 @@ 2988542444,2988542447,FR 2988542448,2988542455,PL 2988542456,2988542459,FR -2988542460,2988542463,ES -2988542464,2988542495,NL +2988542460,2988542495,ES 2988542496,2988542527,FR 2988542528,2988542535,DE 2988542536,2988542539,NL @@ -74082,8 +76238,12 @@ 2988542596,2988542599,FI 2988542600,2988542603,GB 2988542604,2988542611,FR -2988542612,2988542623,DE -2988542624,2988542655,FR +2988542612,2988542627,DE +2988542628,2988542631,FR +2988542632,2988542635,CZ +2988542636,2988542639,GB +2988542640,2988542651,FR +2988542652,2988542655,PL 2988542656,2988542719,BE 2988542720,2988542783,CH 2988542784,2988542847,CZ @@ -74160,8 +76320,8 @@ 2988543744,2988543935,FR 2988543936,2988543947,PL 2988543948,2988543959,BE -2988543960,2988543967,PL -2988543968,2988543999,FR +2988543960,2988543983,PL +2988543984,2988543999,PT 2988544000,2988544015,DE 2988544016,2988544023,GB 2988544024,2988544031,IE @@ -74169,7 +76329,8 @@ 2988544036,2988544039,FR 2988544040,2988544043,DE 2988544044,2988544047,GB -2988544048,2988544063,FR +2988544048,2988544055,FR +2988544056,2988544063,FI 2988544064,2988544127,DE 2988544128,2988544159,GB 2988544160,2988544163,FR @@ -74177,7 +76338,7 @@ 2988544168,2988544175,GB 2988544176,2988544179,CH 2988544180,2988544183,IT -2988544184,2988544191,DE +2988544184,2988544191,FR 2988544192,2988544227,ES 2988544228,2988544271,FR 2988544272,2988544275,PL @@ -74194,7 +76355,8 @@ 2988544320,2988544323,PL 2988544324,2988544327,ES 2988544328,2988544331,PL -2988544332,2988544351,FR +2988544332,2988544335,A1 +2988544336,2988544351,FR 2988544352,2988544355,PL 2988544356,2988544359,DE 2988544360,2988544367,FR @@ -74287,12 +76449,12 @@ 2988545552,2988545555,PL 2988545556,2988545559,IT 2988545560,2988545563,FR -2988545564,2988545567,DE -2988545568,2988545571,NL -2988545572,2988545575,DE +2988545564,2988545575,DE 2988545576,2988545579,FR 2988545580,2988545583,ES -2988545584,2988545663,FR +2988545584,2988545599,FR +2988545600,2988545631,DE +2988545632,2988545663,FR 2988545664,2988545695,ES 2988545696,2988545727,DE 2988545728,2988545791,FR @@ -74312,7 +76474,8 @@ 2988545928,2988545931,BE 2988545932,2988545935,DE 2988545936,2988545943,FR -2988545944,2988545967,NL +2988545944,2988545947,CZ +2988545948,2988545967,FR 2988545968,2988545971,IT 2988545972,2988545975,DE 2988545976,2988545979,FR @@ -74353,7 +76516,8 @@ 2988546368,2988546439,FR 2988546440,2988546443,DE 2988546444,2988546447,FR -2988546448,2988546463,ES +2988546448,2988546451,IE +2988546452,2988546463,ES 2988546464,2988546527,FR 2988546528,2988546535,BE 2988546536,2988546539,FR @@ -74440,8 +76604,8 @@ 2988547256,2988547263,FR 2988547264,2988547267,GB 2988547268,2988547271,ES -2988547272,2988547279,NL -2988547280,2988547295,FR +2988547272,2988547275,GB +2988547276,2988547295,FR 2988547296,2988547303,BE 2988547304,2988547311,FR 2988547312,2988547327,PL @@ -74467,13 +76631,12 @@ 2988547548,2988547567,FR 2988547568,2988547583,DE 2988547584,2988547599,ES -2988547600,2988547615,FR -2988547616,2988547647,PL -2988547648,2988547655,FR +2988547600,2988547655,FR 2988547656,2988547663,PL 2988547664,2988547679,FR 2988547680,2988547711,CH -2988547712,2988547751,FR +2988547712,2988547743,FR +2988547744,2988547751,PT 2988547752,2988547759,ES 2988547760,2988547775,FR 2988547776,2988547807,ES @@ -74489,8 +76652,9 @@ 2988547972,2988547975,DE 2988547976,2988547983,PL 2988547984,2988548015,FR -2988548016,2988548031,ES -2988548032,2988548047,FR +2988548016,2988548019,ES +2988548020,2988548023,LT +2988548024,2988548047,FR 2988548048,2988548055,ES 2988548056,2988548059,PL 2988548060,2988548063,FR @@ -74520,7 +76684,7 @@ 2988556492,2988556495,DE 2988556496,2988556527,FR 2988556528,2988556535,PL -2988556536,2988556539,GB +2988556536,2988556539,FR 2988556540,2988556543,DE 2988556544,2988556831,FR 2988556832,2988556839,DE @@ -74536,8 +76700,7 @@ 2988556912,2988556919,NL 2988556920,2988556927,PL 2988556928,2988556943,FR -2988556944,2988556959,PL -2988556960,2988556963,ES +2988556944,2988556963,PL 2988556964,2988556967,FR 2988556968,2988556975,BE 2988556976,2988556979,FI @@ -74605,8 +76768,7 @@ 2988557768,2988557771,PL 2988557772,2988557775,FR 2988557776,2988557791,BE -2988557792,2988557823,FR -2988557824,2988557951,DE +2988557792,2988557951,FR 2988557952,2988557983,LT 2988557984,2988557999,FR 2988558000,2988558015,IE @@ -74641,7 +76803,8 @@ 2988558720,2988558727,PL 2988558728,2988558731,IT 2988558732,2988558735,PT -2988558736,2988558751,GB +2988558736,2988558747,FR +2988558748,2988558751,GB 2988558752,2988558767,FR 2988558768,2988558783,CH 2988558784,2988558831,FR @@ -74650,9 +76813,11 @@ 2988558884,2988558887,BE 2988558888,2988558891,GB 2988558892,2988558895,NL -2988558896,2988558903,FR +2988558896,2988558899,CH +2988558900,2988558903,FR 2988558904,2988558907,NL -2988558908,2988558935,GB +2988558908,2988558911,PL +2988558912,2988558935,GB 2988558936,2988558939,PL 2988558940,2988558943,GB 2988558944,2988558975,FR @@ -74660,17 +76825,14 @@ 2988559008,2988559011,BE 2988559012,2988559015,PL 2988559016,2988559039,FR -2988559040,2988559055,GB -2988559056,2988559071,LT +2988559040,2988559071,GB 2988559072,2988559103,ES 2988559104,2988559135,PL 2988559136,2988559139,DE 2988559140,2988559151,PL 2988559152,2988559231,FR 2988559232,2988559247,DE -2988559248,2988559255,FR -2988559256,2988559259,DE -2988559260,2988559263,GB +2988559248,2988559263,FR 2988559264,2988559295,LT 2988559296,2988559359,PL 2988559360,2988559631,FR @@ -74682,7 +76844,8 @@ 2988559700,2988559703,PL 2988559704,2988559707,DE 2988559708,2988559711,PL -2988559712,2988559727,FR +2988559712,2988559723,FR +2988559724,2988559727,IT 2988559728,2988559731,DE 2988559732,2988559735,PL 2988559736,2988559743,GB @@ -74703,7 +76866,9 @@ 2988560512,2988560519,IT 2988560520,2988560523,DE 2988560524,2988560527,BE -2988560528,2988560543,FR +2988560528,2988560531,ES +2988560532,2988560535,FR +2988560536,2988560543,IE 2988560544,2988560575,GB 2988560576,2988560591,ES 2988560592,2988560595,NL @@ -74736,8 +76901,8 @@ 2988560960,2988560975,FR 2988560976,2988560991,ES 2988560992,2988560995,FR -2988560996,2988561007,DE -2988561008,2988561023,FR +2988560996,2988560999,DE +2988561000,2988561023,FR 2988561024,2988561027,BE 2988561028,2988561039,FR 2988561040,2988561043,GB @@ -74746,7 +76911,7 @@ 2988561052,2988561055,GB 2988561056,2988561059,FR 2988561060,2988561071,PL -2988561072,2988561075,NL +2988561072,2988561075,ES 2988561076,2988561079,LT 2988561080,2988561083,PL 2988561084,2988561087,GB @@ -74803,7 +76968,8 @@ 2988561848,2988561855,FR 2988561856,2988561871,IE 2988561872,2988561875,CH -2988561876,2988561887,FR +2988561876,2988561879,A1 +2988561880,2988561887,FR 2988561888,2988561903,PL 2988561904,2988561983,FR 2988561984,2988562015,DE @@ -74828,7 +76994,7 @@ 2988562688,2988562703,GB 2988562704,2988562707,PL 2988562708,2988562711,DE -2988562712,2988562719,GB +2988562712,2988562719,FR 2988562720,2988562815,BE 2988562816,2988562823,PL 2988562824,2988562831,PT @@ -74836,8 +77002,7 @@ 2988562836,2988562839,NL 2988562840,2988562843,LT 2988562844,2988562847,PL -2988562848,2988562855,NL -2988562856,2988562863,DE +2988562848,2988562863,GB 2988562864,2988562911,FR 2988562912,2988562943,PL 2988562944,2988563011,FR @@ -74859,7 +77024,7 @@ 2988563152,2988563183,FR 2988563184,2988563187,CZ 2988563188,2988563191,PL -2988563192,2988563199,CH +2988563192,2988563199,FR 2988563200,2988563455,IE 2988563456,2988563487,FR 2988563488,2988563499,GB @@ -75158,6 +77323,7 @@ 2991538176,2991554559,SI 2991554560,2991571455,GB 2991571456,2991587327,IT +2991587328,2991718399,SA 2991718400,2991849471,CH 2991849472,2991980543,NL 2991980544,2991980807,UA @@ -75184,11 +77350,7 @@ 2991985920,2991986175,JP 2991986176,2991986431,UA 2991986432,2991986687,JP -2991986688,2991988263,UA -2991988264,2991988271,IN -2991988272,2992014727,UA -2992014728,2992014735,IN -2992014736,2992111615,UA +2991986688,2992111615,UA 2992111616,2992373759,KZ 2992373760,2992635903,UA 2992635904,2993684479,GB @@ -75198,6 +77360,26 @@ 2994733056,2994798591,GR 2994798592,2994929663,RU 2994929664,2994995199,IR +2994995200,2994997247,RU +2994997248,2994999295,BE +2994999296,2995003391,FR +2995003392,2995007487,BH +2995007488,2995009535,TR +2995009536,2995011583,ES +2995011584,2995013631,DE +2995013632,2995015679,SE +2995015680,2995017727,BG +2995017728,2995019775,IT +2995019776,2995021823,RU +2995021824,2995023871,IT +2995023872,2995044351,MD +2995044352,2995046399,ES +2995046400,2995048447,RU +2995048448,2995050495,NL +2995050496,2995052543,AL +2995052544,2995056639,DK +2995056640,2995058687,DE +2995058688,2995060735,SE 2995060736,2995126271,UA 2995126272,2995191807,GE 2995191808,2995257343,LB @@ -75280,9 +77462,7 @@ 2997000960,2997001471,DE 2997001472,2997001727,BZ 2997001728,2997001983,TR -2997001984,2997003023,DE -2997003024,2997003039,US -2997003040,2997003071,DE +2997001984,2997003071,DE 2997003072,2997003135,RU 2997003136,2997003199,DE 2997003200,2997003263,RU @@ -75302,8 +77482,7 @@ 2997005376,2997005439,GR 2997005440,2997005567,GB 2997005568,2997005823,BZ -2997005824,2997006079,DE -2997006080,2997006335,GB +2997005824,2997006335,DE 2997006336,2997006591,TR 2997006592,2997006655,DE 2997006656,2997006719,TR @@ -75318,8 +77497,7 @@ 2997009024,2997018623,DE 2997018624,2997019135,GB 2997019136,2997019391,TR -2997019392,2997019647,GB -2997019648,2997019711,DE +2997019392,2997019711,DE 2997019712,2997019903,US 2997019904,2997020415,DE 2997020416,2997020671,CA @@ -75327,9 +77505,7 @@ 2997020720,2997020735,SE 2997020736,2997020799,DE 2997020800,2997020863,CA -2997020864,2997021183,DE -2997021184,2997021695,GB -2997021696,2997022079,DE +2997020864,2997022079,DE 2997022080,2997022143,GB 2997022144,2997022239,DE 2997022240,2997022303,NL @@ -75338,8 +77514,7 @@ 2997022752,2997022783,TR 2997022784,2997022847,DE 2997022848,2997023231,BZ -2997023232,2997023287,DE -2997023288,2997023295,US +2997023232,2997023295,DE 2997023296,2997023423,IN 2997023424,2997024255,DE 2997024256,2997024511,TR @@ -75742,100 +77917,7 @@ 3001966592,3001968639,NL 3001968640,3001970687,BE 3001970688,3001974783,RU -3001974784,3001975567,GB -3001975568,3001975575,LK -3001975576,3001975591,US -3001975592,3001975599,MY -3001975600,3001975615,CN -3001975616,3001975623,UA -3001975624,3001975631,RU -3001975632,3001975655,GB -3001975656,3001975663,RU -3001975664,3001975671,FR -3001975672,3001975679,CN -3001975680,3001975687,TW -3001975688,3001975695,US -3001975696,3001975703,UA -3001975704,3001975711,DE -3001975712,3001975719,MY -3001975720,3001975727,US -3001975728,3001975735,RU -3001975736,3001975743,MY -3001975744,3001975751,CN -3001975752,3001975759,UA -3001975760,3001975767,US -3001975768,3001975783,CN -3001975784,3001975791,US -3001975792,3001975799,IT -3001975800,3001975807,US -3001975808,3001975815,UA -3001975816,3001975823,US -3001975824,3001975831,UA -3001975832,3001975847,GB -3001975848,3001975855,US -3001975856,3001975863,MY -3001975864,3001975871,AE -3001975872,3001975887,US -3001975888,3001975895,CN -3001975896,3001975919,GB -3001975920,3001975927,CN -3001975928,3001975935,AU -3001975936,3001976623,GB -3001976624,3001976639,PK -3001976640,3001976655,RU -3001976656,3001976671,GB -3001976672,3001976679,IN -3001976680,3001976687,US -3001976688,3001976831,GB -3001976832,3001976895,CN -3001976896,3001976927,GB -3001976928,3001976959,RU -3001976960,3001977103,GB -3001977104,3001977119,RU -3001977120,3001977135,IN -3001977136,3001977143,CN -3001977144,3001977151,TW -3001977152,3001977167,IN -3001977168,3001977183,LK -3001977184,3001977215,GB -3001977216,3001977247,RU -3001977248,3001977311,GB -3001977312,3001977343,CN -3001977344,3001977375,GB -3001977376,3001977407,US -3001977408,3001977447,GB -3001977448,3001977455,IT -3001977456,3001977471,US -3001977472,3001977487,IN -3001977488,3001977503,LK -3001977504,3001977519,GB -3001977520,3001977535,CN -3001977536,3001977567,GB -3001977568,3001977575,CA -3001977576,3001977599,GB -3001977600,3001977855,DK -3001977856,3001978015,GB -3001978016,3001978023,CN -3001978024,3001978031,GB -3001978032,3001978047,US -3001978048,3001978367,GB -3001978368,3001978495,US -3001978496,3001978527,RU -3001978528,3001978543,GB -3001978544,3001978559,RU -3001978560,3001978591,US -3001978592,3001978607,RU -3001978608,3001978615,IE -3001978616,3001978623,CN -3001978624,3001978687,US -3001978688,3001978751,EE -3001978752,3001978783,RU -3001978784,3001978815,US -3001978816,3001978823,LK -3001978824,3001978847,GB -3001978848,3001978863,UA -3001978864,3001978879,PK -3001978880,3001982975,GB +3001974784,3001982975,GB 3001982976,3001987071,CH 3001987072,3001991167,JO 3001991168,3001995263,IR @@ -75957,7 +78039,9 @@ 3002763264,3002765311,RS 3002765312,3002767359,NL 3002767360,3002769407,RU -3002769408,3002771711,DE +3002769408,3002771655,DE +3002771656,3002771663,NL +3002771664,3002771711,DE 3002771712,3002771719,NL 3002771720,3002773503,DE 3002773504,3002775551,GB @@ -76169,7 +78253,6 @@ 3031582720,3031584767,SG 3031584768,3031587839,JP 3031587840,3031592959,ID -3031592960,3031595007,HK 3031595008,3031596031,AU 3031596032,3031597055,KH 3031597056,3031613439,PK @@ -76301,6 +78384,8 @@ 3039428608,3039494143,CL 3039821824,3040346111,CO 3040870400,3041001471,PE +3041918976,3042967551,AR +3045064704,3045588991,CO 3053453312,3054501887,ID 3054501888,3054534655,HK 3054534656,3054537727,PH @@ -76365,7 +78450,9 @@ 3057041408,3057049599,MY 3057049600,3057050623,AU 3057050624,3057051647,SG -3057051648,3057053695,AU +3057051648,3057052415,AU +3057052416,3057052671,ES +3057052672,3057053695,AU 3057053696,3057054719,JP 3057054720,3057055743,HK 3057055744,3057057791,JP @@ -76720,29 +78807,37 @@ 3098148864,3098165247,JM 3098165248,3098181631,US 3098181632,3098185727,CA -3098185728,3098263551,US +3098185728,3098255903,US +3098255904,3098255911,MV +3098255912,3098263551,US 3098263552,3098271743,CA 3098271744,3098279943,US 3098279944,3098279951,KW 3098279952,3098280591,US 3098280592,3098280599,PA -3098280600,3098281503,US +3098280600,3098281311,US +3098281312,3098281343,EG +3098281344,3098281503,US 3098281504,3098281511,PA 3098281512,3098281711,US 3098281712,3098281719,PA -3098281720,3098286287,US +3098281720,3098281943,US +3098281944,3098281951,AU +3098281952,3098286287,US 3098286288,3098286295,IN 3098286296,3098286399,US 3098286400,3098286431,BR -3098286432,3098288343,US +3098286432,3098287711,US +3098287712,3098287719,AU +3098287720,3098288343,US 3098288344,3098288351,BR 3098288352,3098288775,US 3098288776,3098288783,BR -3098288784,3098290223,US +3098288784,3098289495,US +3098289496,3098289503,AU +3098289504,3098290223,US 3098290224,3098290231,IN -3098290232,3098291087,US -3098291088,3098291095,IN -3098291096,3098291119,US +3098290232,3098291119,US 3098291120,3098291135,NL 3098291136,3098291151,US 3098291152,3098291159,NL @@ -76756,29 +78851,39 @@ 3098322384,3098322391,BD 3098322392,3098322695,US 3098322696,3098322703,BD -3098322704,3098331151,US +3098322704,3098323679,US +3098323680,3098323711,EG +3098323712,3098331151,US 3098331152,3098331159,HK 3098331160,3098331471,US 3098331472,3098331479,CL 3098331480,3098333951,US 3098333952,3098333959,BD -3098333960,3098336303,US +3098333960,3098336047,US +3098336048,3098336055,MA +3098336056,3098336303,US 3098336304,3098336311,MY -3098336312,3098365535,US +3098336312,3098336975,US +3098336976,3098336983,BR +3098336984,3098365535,US 3098365536,3098365551,IN -3098365552,3098365951,US +3098365552,3098365631,US +3098365632,3098365639,AU +3098365640,3098365951,US 3098365952,3098365959,MX 3098365960,3098371191,US 3098371192,3098371199,BR -3098371200,3098371303,US -3098371304,3098371311,PE -3098371312,3098371495,US +3098371200,3098371495,US 3098371496,3098371503,JO -3098371504,3098375583,US +3098371504,3098373927,US +3098373928,3098373935,MX +3098373936,3098375583,US 3098375584,3098375615,BR 3098375616,3098376863,US 3098376864,3098376895,BR -3098376896,3098377727,US +3098376896,3098377655,US +3098377656,3098377663,GB +3098377664,3098377727,US 3098377728,3098377759,AR 3098377760,3098381455,US 3098381456,3098381471,LT @@ -76799,13 +78904,13 @@ 3120599040,3120601087,EC 3120601088,3120602111,AR 3120602112,3120603135,BO -3120603136,3120608255,AR -3120609280,3120610303,AR +3120603136,3120610303,AR 3120610304,3120611327,PY 3120611328,3120627711,AR 3120627712,3120644095,NI 3120644096,3120660479,DO 3120660480,3120668671,PA +3120668672,3120676863,CO 3120676864,3120680959,HT 3120680960,3120691199,AR 3120691200,3120693247,CO @@ -76832,34 +78937,37 @@ 3122298880,3122331647,VE 3122331648,3122348031,BO 3122397184,3122659327,CO -3122659328,3122675711,CR -3122675712,3122700287,GT -3122700288,3122716671,CR -3122716672,3122724863,GT +3122659328,3122675711,GT +3122675712,3122683903,SV +3122683904,3122724863,GT 3122790400,3123052543,CL 3123052544,3123183615,AR 3123183616,3123314687,CL 3123314688,3123380223,EC 3123380224,3123412991,CO +3123412992,3123429375,EC 3123445760,3123576831,TT -3123576832,3123642367,EC -3123707904,3123970047,UY -3124232192,3124772863,AR +3123576832,3123707903,EC +3123707904,3124232191,UY +3124232192,3124789247,AR 3124789248,3124822015,CR 3124822016,3124838399,EC 3124854784,3124887551,CL 3124887552,3124953087,EC 3124953088,3125018623,CL 3125018624,3125280767,EC -3125280768,3125542911,PA +3125280768,3125346303,CO +3125346304,3125542911,PA +3125542912,3125673983,NI 3125673984,3125805055,CL 3125805056,3126329343,CO 3126329344,3126853631,VE 3126853632,3126919167,AR 3126919168,3127115775,CO 3127115776,3127181311,AR -3127246848,3127377919,CO -3127377920,3127640063,CL +3127181312,3127246847,EC +3127246848,3127345151,CO +3127345152,3127640063,CL 3127640064,3127902207,AR 3127902208,3128426495,CO 3128426496,3128492031,DO @@ -76870,9 +78978,11 @@ 3129999360,3130261503,CO 3130261504,3130277887,CL 3130294272,3130302463,AR -3130310656,3130312703,PA +3130302464,3130312703,PA +3130312704,3130314751,AR 3130314752,3130315775,CL 3130315776,3130316799,CR +3130316800,3130318847,AN 3130318848,3130327039,AR 3130327040,3130392575,DO 3130458112,3130523647,GT @@ -76882,9 +78992,9 @@ 3130851328,3130916863,AR 3131047936,3131310079,PE 3131310080,3131572223,VE -3131572224,3131703295,CO +3131572224,3131834367,CO 3131834368,3132096511,CL -3132096512,3132162047,CR +3132096512,3132227583,CR 3132227584,3132293119,EC 3132358656,3132489727,CO 3132489728,3132555263,AR @@ -76912,6 +79022,7 @@ 3154313216,3154378751,TR 3154378752,3154444287,GR 3154444288,3154509823,BE +3154509824,3154575359,HU 3154575360,3154640895,FR 3154640896,3155165183,IT 3155165184,3155427327,RU @@ -76920,6 +79031,7 @@ 3155506336,3155689471,AT 3155689472,3155951615,RO 3155951616,3156213759,GB +3156213760,3156279295,RU 3156279296,3156344831,PL 3156344832,3156410367,IR 3156410368,3156475903,RU @@ -76939,6 +79051,11 @@ 3156803584,3156869119,TR 3156869120,3156934655,LU 3156934656,3157000191,RU +3157000192,3157008383,MK +3157008384,3157016575,RU +3157016576,3157024767,BE +3157024768,3157032959,RU +3157032960,3157065727,HU 3157065728,3157131263,AT 3157131264,3157196799,DE 3157196800,3157262335,PL @@ -76990,9 +79107,7 @@ 3158392832,3158394879,RU 3158394880,3158395007,AT 3158395008,3158395135,GB -3158395136,3158395151,AT -3158395152,3158395159,DE -3158395160,3158395167,AT +3158395136,3158395167,AT 3158395168,3158395175,DE 3158395176,3158395191,AT 3158395192,3158395199,DE @@ -77377,8 +79492,8 @@ 3162365952,3162374143,PL 3162374144,3162382335,BG 3162382336,3162390527,RU -3162390528,3162391551,SE -3162391552,3162398719,A1 +3162390528,3162392575,SE +3162392576,3162398719,A1 3162398720,3162406911,BE 3162406912,3162415103,IR 3162415104,3162423295,DE @@ -77420,7 +79535,8 @@ 3163062272,3163095039,IR 3163095040,3163127807,PL 3163127808,3163160575,BH -3163160576,3163161631,DE +3163160576,3163161599,DE +3163161600,3163161631,IN 3163161632,3163161663,DK 3163161664,3163161695,US 3163161696,3163161727,BG @@ -77430,34 +79546,45 @@ 3163161824,3163161855,US 3163161856,3163161887,BR 3163161888,3163161951,US -3163161952,3163162079,DE +3163161952,3163162015,DE +3163162016,3163162047,US +3163162048,3163162079,NL 3163162080,3163162111,RU 3163162112,3163162143,TR 3163162144,3163162271,DE 3163162272,3163162303,NL -3163162304,3163162367,DE +3163162304,3163162335,TH +3163162336,3163162367,DE 3163162368,3163162399,TR 3163162400,3163162431,DE 3163162432,3163162463,CY -3163162464,3163162559,DE -3163162560,3163162591,US -3163162592,3163163711,DE +3163162464,3163162495,DE +3163162496,3163162527,BR +3163162528,3163162559,DE +3163162560,3163162623,US +3163162624,3163163711,DE 3163163712,3163163743,BR -3163163744,3163163807,DE +3163163744,3163163775,DE +3163163776,3163163807,TR 3163163808,3163163839,CY -3163163840,3163163871,DE +3163163840,3163163871,PL 3163163872,3163163903,RU 3163163904,3163163935,GR -3163163936,3163163967,VG +3163163936,3163163967,BR 3163163968,3163163999,US 3163164000,3163164031,DE -3163164032,3163164063,TW +3163164032,3163164063,US 3163164064,3163164095,AM 3163164096,3163164127,RU -3163164128,3163164287,DE +3163164128,3163164159,MA +3163164160,3163164191,US +3163164192,3163164223,MA +3163164224,3163164287,DE 3163164288,3163164319,CL 3163164320,3163164351,RU -3163164352,3163164447,DE +3163164352,3163164383,DE +3163164384,3163164415,TR +3163164416,3163164447,PL 3163164448,3163164479,RU 3163164480,3163164511,DE 3163164512,3163164543,HU @@ -77467,14 +79594,16 @@ 3163164640,3163164671,US 3163164672,3163165695,DE 3163165696,3163165727,US -3163165728,3163165759,DE +3163165728,3163165759,RU 3163165760,3163165791,PL 3163165792,3163165823,RU 3163165824,3163165855,BR -3163165856,3163165983,DE -3163165984,3163166015,CH +3163165856,3163165887,DE +3163165888,3163165919,AR +3163165920,3163166015,DE 3163166016,3163166047,US -3163166048,3163166175,DE +3163166048,3163166079,BR +3163166080,3163166175,DE 3163166176,3163166207,RU 3163166208,3163166239,TR 3163166240,3163166271,IT @@ -77486,11 +79615,12 @@ 3163166496,3163166527,RO 3163166528,3163166559,DE 3163166560,3163166591,HU -3163166592,3163166623,DE +3163166592,3163166623,IN 3163166624,3163166655,US 3163166656,3163166687,DE 3163166688,3163166719,RU -3163166720,3163167775,DE +3163166720,3163167743,DE +3163167744,3163167775,RU 3163167776,3163167807,GR 3163167808,3163167839,US 3163167840,3163167871,BR @@ -77510,50 +79640,54 @@ 3163168320,3163168351,DK 3163168352,3163168383,RU 3163168384,3163168415,TR -3163168416,3163168511,DE +3163168416,3163168479,DE +3163168480,3163168511,US 3163168512,3163168543,TR 3163168544,3163168575,DE 3163168576,3163168607,US -3163168608,3163168671,DE +3163168608,3163168639,MA +3163168640,3163168671,DE 3163168672,3163168703,US 3163168704,3163168735,GR 3163168736,3163169823,DE 3163169824,3163169855,RU -3163169856,3163170015,DE +3163169856,3163169887,US +3163169888,3163170015,DE 3163170016,3163170047,ES 3163170048,3163170079,RU 3163170080,3163170111,TR -3163170112,3163170143,TW +3163170112,3163170143,CZ 3163170144,3163170175,ZA 3163170176,3163170207,DE 3163170208,3163170239,RU -3163170240,3163170271,DE -3163170272,3163170303,TW +3163170240,3163170303,DE 3163170304,3163170335,IT 3163170336,3163170367,RO -3163170368,3163170495,DE +3163170368,3163170463,DE +3163170464,3163170495,TR 3163170496,3163170527,BG 3163170528,3163170591,DE 3163170592,3163170623,BR 3163170624,3163170655,GR -3163170656,3163170751,DE +3163170656,3163170719,DE +3163170720,3163170751,MA 3163170752,3163170783,CH 3163170784,3163170815,US 3163170816,3163171871,DE 3163171872,3163171903,RO -3163171904,3163171935,BZ -3163171936,3163171967,DE +3163171904,3163171967,DE 3163171968,3163171999,US -3163172000,3163172095,DE -3163172096,3163172127,BR +3163172000,3163172127,BR 3163172128,3163172159,US 3163172160,3163172191,TR -3163172192,3163172255,DE +3163172192,3163172223,US +3163172224,3163172255,FR 3163172256,3163172287,US 3163172288,3163172319,DE 3163172320,3163172351,NL 3163172352,3163172383,GB -3163172384,3163172447,DE +3163172384,3163172415,US +3163172416,3163172447,DE 3163172448,3163172511,US 3163172512,3163172543,RU 3163172544,3163172575,DE @@ -77563,20 +79697,22 @@ 3163172672,3163172703,BR 3163172704,3163172735,DE 3163172736,3163172767,GR -3163172768,3163173919,DE -3163173920,3163173951,TW -3163173952,3163174015,DE +3163172768,3163173951,DE +3163173952,3163173983,IN +3163173984,3163174015,GB 3163174016,3163174047,RU 3163174048,3163174079,DK -3163174080,3163174111,US +3163174080,3163174111,DE 3163174112,3163174143,BE 3163174144,3163174175,BD -3163174176,3163174239,DE +3163174176,3163174207,DE +3163174208,3163174239,RU 3163174240,3163174271,TW 3163174272,3163174303,DE 3163174304,3163174335,IL 3163174336,3163174367,RU -3163174368,3163174431,DE +3163174368,3163174399,US +3163174400,3163174431,DE 3163174432,3163174463,BR 3163174464,3163174495,DE 3163174496,3163174527,US @@ -77587,32 +79723,37 @@ 3163174656,3163174687,RU 3163174688,3163174719,DE 3163174720,3163174751,NL -3163174752,3163174783,TR -3163174784,3163174815,DE +3163174752,3163174783,DE +3163174784,3163174815,TW 3163174816,3163174847,CA 3163174848,3163174879,TR 3163174880,3163174911,RU -3163174912,3163175999,DE -3163176000,3163176031,US -3163176032,3163176063,DE +3163174912,3163175967,DE +3163175968,3163176031,US +3163176032,3163176063,BG 3163176064,3163176095,RU 3163176096,3163176127,CY 3163176128,3163176159,US 3163176160,3163176255,DE 3163176256,3163176287,UG -3163176288,3163176479,DE +3163176288,3163176319,RU +3163176320,3163176351,DE +3163176352,3163176383,RO +3163176384,3163176415,IN +3163176416,3163176479,DE 3163176480,3163176511,GB -3163176512,3163176543,DE +3163176512,3163176543,RU 3163176544,3163176575,US 3163176576,3163176607,GR -3163176608,3163176639,TW -3163176640,3163176767,DE +3163176608,3163176703,DE +3163176704,3163176735,BR +3163176736,3163176767,DE 3163176768,3163176799,PL 3163176800,3163176831,EG -3163176832,3163176863,BR -3163176864,3163176895,DE +3163176832,3163176895,BR 3163176896,3163176927,SE -3163176928,3163193343,DE +3163176928,3163176959,TH +3163176960,3163193343,DE 3163193344,3163226111,MD 3163226112,3163258879,SA 3163258880,3163291647,SY @@ -77697,7 +79838,8 @@ 3164949156,3164949159,DE 3164949160,3164949163,PL 3164949164,3164949167,FR -3164949168,3164949175,GB +3164949168,3164949171,IE +3164949172,3164949175,FR 3164949176,3164949179,ES 3164949180,3164949183,FR 3164949184,3164949199,GB @@ -77745,7 +79887,8 @@ 3164950520,3164950523,FR 3164950524,3164950527,ES 3164950528,3164950543,BE -3164950544,3164950591,NL +3164950544,3164950559,IE +3164950560,3164950591,NL 3164950592,3164950623,FR 3164950624,3164950655,GB 3164950656,3164950687,FR @@ -77806,7 +79949,7 @@ 3164951936,3164951999,DE 3164952000,3164952015,ES 3164952016,3164952031,FR -3164952032,3164952063,PL +3164952032,3164952063,PT 3164952064,3164952191,FR 3164952192,3164952207,ES 3164952208,3164952215,FR @@ -77821,8 +79964,7 @@ 3164952576,3164952831,FR 3164952832,3164952959,IT 3164952960,3164952975,GB -3164952976,3164952991,FR -3164952992,3164953007,PL +3164952976,3164953007,FR 3164953008,3164953023,ES 3164953024,3164953087,FR 3164953088,3164953151,LT @@ -77830,9 +79972,7 @@ 3164953216,3164953247,FR 3164953248,3164953255,CH 3164953256,3164953263,CZ -3164953264,3164953311,FR -3164953312,3164953319,CZ -3164953320,3164953327,BE +3164953264,3164953327,FR 3164953328,3164953375,PL 3164953376,3164953379,NL 3164953380,3164953383,GB @@ -77952,7 +80092,8 @@ 3164960576,3164960591,DE 3164960592,3164960599,ES 3164960600,3164960623,DE -3164960624,3164960639,FR +3164960624,3164960627,FR +3164960628,3164960639,PL 3164960640,3164960643,LT 3164960644,3164960647,FR 3164960648,3164960651,CH @@ -77965,7 +80106,7 @@ 3164960704,3164960719,FR 3164960720,3164960723,CH 3164960724,3164960727,FR -3164960728,3164960735,GB +3164960728,3164960735,PL 3164960736,3164960767,ES 3164960768,3164960799,GB 3164960800,3164960831,ES @@ -77976,7 +80117,7 @@ 3164960936,3164960939,GB 3164960940,3164960943,DE 3164960944,3164960959,PL -3164960960,3164960963,DE +3164960960,3164960963,ES 3164960964,3164960967,PT 3164960968,3164960975,PL 3164960976,3164960991,GB @@ -78027,7 +80168,7 @@ 3164961792,3164961855,FR 3164961856,3164961859,PL 3164961860,3164961863,ES -3164961864,3164961871,FI +3164961864,3164961871,FR 3164961872,3164961887,IE 3164961888,3164961903,ES 3164961904,3164961919,GB @@ -78048,7 +80189,8 @@ 3164962112,3164962143,GB 3164962144,3164962151,ES 3164962152,3164962159,DE -3164962160,3164962199,FR +3164962160,3164962191,FR +3164962192,3164962199,DE 3164962200,3164962203,GB 3164962204,3164962207,PT 3164962208,3164962211,FI @@ -78083,8 +80225,8 @@ 3164962632,3164962639,FR 3164962640,3164962647,ES 3164962648,3164962655,PT -3164962656,3164962663,GB -3164962664,3164962687,ES +3164962656,3164962671,GB +3164962672,3164962687,FR 3164962688,3164962703,PL 3164962704,3164962715,FR 3164962716,3164962719,NL @@ -78157,8 +80299,7 @@ 3164969880,3164969883,ES 3164969884,3164969887,PL 3164969888,3164969903,IE -3164969904,3164969919,GB -3164969920,3164969983,FR +3164969904,3164969983,FR 3164969984,3164970047,IE 3164970048,3164970079,GB 3164970080,3164970111,DE @@ -78183,7 +80324,9 @@ 3164970364,3164970367,ES 3164970368,3164970371,PL 3164970372,3164970375,ES -3164970376,3164970399,IT +3164970376,3164970379,FR +3164970380,3164970383,PL +3164970384,3164970399,IT 3164970400,3164970407,CH 3164970408,3164970411,IT 3164970412,3164970415,GB @@ -78250,8 +80393,7 @@ 3164971808,3164971903,BE 3164971904,3164971967,DE 3164971968,3164971983,FR -3164971984,3164971991,ES -3164971992,3164971999,FR +3164971984,3164971999,ES 3164972000,3164972015,CH 3164972016,3164972019,ES 3164972020,3164972027,FR @@ -78275,7 +80417,8 @@ 3164972596,3164972599,PL 3164972600,3164972607,FR 3164972608,3164972639,PL -3164972640,3164972671,IE +3164972640,3164972655,IT +3164972656,3164972671,FR 3164972672,3164972679,PL 3164972680,3164972691,FR 3164972692,3164972695,FI @@ -78307,10 +80450,12 @@ 3164973628,3164973631,CH 3164973632,3164973663,IE 3164973664,3164973695,ES -3164973696,3164973727,FR +3164973696,3164973727,DE 3164973728,3164973743,GB 3164973744,3164973759,FR -3164973760,3164973815,GB +3164973760,3164973791,GB +3164973792,3164973807,DE +3164973808,3164973815,GB 3164973816,3164973823,FR 3164973824,3164973855,DE 3164973856,3164973863,PL @@ -78329,7 +80474,8 @@ 3164973944,3164973951,PL 3164973952,3164974591,FR 3164974592,3164974623,PL -3164974624,3164974647,FR +3164974624,3164974643,FR +3164974644,3164974647,PL 3164974648,3164974651,PT 3164974652,3164974655,DE 3164974656,3164974659,BE @@ -78380,8 +80526,7 @@ 3164975948,3164975951,NL 3164975952,3164975967,GB 3164975968,3164975983,NL -3164975984,3164975987,PL -3164975988,3164975991,DE +3164975984,3164975991,DE 3164975992,3164976011,PL 3164976012,3164976015,ES 3164976016,3164976023,PL @@ -78408,7 +80553,7 @@ 3164976288,3164976295,ES 3164976296,3164976303,IT 3164976304,3164976307,FR -3164976308,3164976311,DE +3164976308,3164976311,IE 3164976312,3164976315,GB 3164976316,3164976319,FR 3164976320,3164976327,DE @@ -78424,7 +80569,8 @@ 3164976404,3164976407,FR 3164976408,3164976415,DE 3164976416,3164976431,IT -3164976432,3164976459,FR +3164976432,3164976447,PT +3164976448,3164976459,FR 3164976460,3164976479,DE 3164976480,3164976511,PL 3164976512,3164976767,FR @@ -78452,8 +80598,8 @@ 3164977792,3164977823,FR 3164977824,3164977839,GB 3164977840,3164977871,FR -3164977872,3164977875,DE -3164977876,3164977879,ES +3164977872,3164977875,GB +3164977876,3164977879,NL 3164977880,3164977883,DE 3164977884,3164977887,GB 3164977888,3164977903,IT @@ -78489,19 +80635,19 @@ 3164978952,3164978955,PL 3164978956,3164978959,GB 3164978960,3164978975,FR -3164978976,3164978991,ES -3164978992,3164978999,PL +3164978976,3164978983,ES +3164978984,3164978999,PL 3164979000,3164979003,FR 3164979004,3164979007,DE 3164979008,3164979023,GB 3164979024,3164979047,FR 3164979048,3164979051,BE 3164979052,3164979103,FR -3164979104,3164979111,GB +3164979104,3164979107,PL +3164979108,3164979111,GB 3164979112,3164979119,PL 3164979120,3164979135,NL -3164979136,3164979151,DE -3164979152,3164979159,FR +3164979136,3164979159,FR 3164979160,3164979167,PL 3164979168,3164979175,DE 3164979176,3164979183,FR @@ -78576,14 +80722,19 @@ 3168829440,3168862207,RO 3168862208,3168894975,RU 3168894976,3168927743,PS -3168927744,3169058815,RU +3168927744,3169026047,RU +3169026048,3169034239,CZ +3169034240,3169042431,GB +3169042432,3169044479,GR +3169044480,3169046527,NL +3169046528,3169050623,AZ +3169050624,3169052671,HU +3169052672,3169054719,PS +3169054720,3169056767,GB +3169056768,3169058815,EE 3169058816,3169091583,DK 3169091584,3169124351,IT -3169124352,3169149439,RO -3169149440,3169149695,IT -3169149696,3169149951,PS -3169149952,3169150463,SY -3169150464,3169157119,RO +3169124352,3169157119,RO 3169157120,3169189887,SY 3169189888,3169222655,UA 3169222656,3169255423,SI @@ -78645,7 +80796,9 @@ 3170263040,3170271231,CZ 3170271232,3170279423,PL 3170279424,3170287615,RU -3170287616,3170295807,GB +3170287616,3170289151,GB +3170289152,3170289167,BA +3170289168,3170295807,GB 3170295808,3170303999,RU 3170304000,3170312191,SY 3170312192,3170320383,RU @@ -78690,7 +80843,7 @@ 3187851264,3187855359,PY 3187855360,3187857407,PA 3187859456,3187863551,PA -3187867648,3187908607,AR +3187863552,3187908607,AR 3187908608,3187910655,CO 3187910656,3187914751,CL 3187914752,3187916799,BO @@ -78702,6 +80855,7 @@ 3187953664,3187955711,CL 3187955712,3187957759,CR 3187957760,3187961855,CL +3187961856,3187965951,AR 3187965952,3187982335,AN 3187982336,3187998719,CL 3187998720,3188006911,AR @@ -78724,6 +80878,7 @@ 3188178944,3188187135,CR 3188187136,3188203519,AR 3188203520,3188207615,DO +3188207616,3188211711,AR 3188211712,3188228095,CL 3188228096,3188236287,PE 3188236288,3188237311,PA @@ -78733,7 +80888,9 @@ 3188242432,3188244479,AR 3188244480,3188260863,CO 3188260864,3188269055,AR -3188269056,3188273151,VE +3188269056,3188269439,VE +3188269440,3188269567,CO +3188269568,3188273151,VE 3188273152,3188275199,PA 3188275200,3188277247,CL 3188277248,3188293631,CO @@ -78751,14 +80908,23 @@ 3188473856,3188482047,PE 3188482048,3188490239,AR 3188490240,3188498431,CO -3188498432,3188513279,AR +3188498432,3188509695,AR +3188509696,3188510207,US +3188510208,3188513279,AR 3188513280,3188513535,US -3188513536,3188523007,AR +3188513536,3188516351,AR +3188516352,3188516607,US +3188516608,3188517119,AR +3188517120,3188517375,US +3188517376,3188523007,AR 3188523008,3188539391,CO 3188539392,3188543487,CL 3188543488,3188545535,PA 3188545536,3188547583,AR 3188547584,3188551679,CO +3188551680,3188552703,AR +3188552704,3188553727,CL +3188553728,3188555775,AN 3188555776,3188572159,CL 3188572160,3188576255,CO 3188576256,3188597759,AR @@ -78828,7 +80994,9 @@ 3191603200,3191608319,MX 3191608320,3191608831,CO 3191608832,3191609087,MX -3191609088,3191635967,CO +3191609088,3191611391,CO +3191611392,3191619583,VE +3191619584,3191635967,CO 3191635968,3191637503,AR 3191637504,3191638095,CO 3191638096,3191638103,AR @@ -78865,18 +81033,23 @@ 3193782272,3193798655,TT 3193798656,3193806847,CO 3193806848,3193810943,CR +3193810944,3193815039,PY 3193815040,3193823231,AR 3193823232,3193827327,CL 3193831424,3193864191,DO 3193864192,3193872383,EC +3193872384,3193880575,AR 3193880576,3193896959,VE 3193896960,3193929727,CL 3193929728,3193962495,EC -3193962496,3193995263,CL +3193962496,3193987071,CL +3193987072,3193989119,EC +3193991168,3193995263,AR 3193995264,3194028031,CO 3194028032,3194044415,AR 3194044416,3194052607,CO 3194052608,3194056703,TT +3194056704,3194058751,AN 3194060800,3194093567,CO 3194093568,3194126335,SR 3194126336,3194127359,GT @@ -78931,7 +81104,9 @@ 3194642432,3194646527,AR 3194650624,3194653439,AR 3194653440,3194653695,US -3194653696,3194665983,AR +3194653696,3194663167,AR +3194663168,3194663423,US +3194663424,3194665983,AR 3194665984,3194666239,US 3194666240,3194667007,AR 3194683392,3194687487,CU @@ -78950,7 +81125,7 @@ 3194781696,3194798079,CL 3194798080,3194799103,AR 3194799104,3194802175,GY -3194806272,3194810367,AR +3194806272,3194814463,AR 3194818560,3194822655,AR 3194830848,3194839039,PA 3194847232,3194863615,CO @@ -79072,8 +81247,9 @@ 3198910464,3198926847,CL 3198943232,3199500799,AR 3199500800,3199501311,US -3199501312,3199516671,AR +3199501312,3199533055,AR 3199533056,3199549439,BO +3199549440,3199565823,AR 3199565824,3199582207,NI 3199598592,3199631359,CO 3199664128,3199729663,AR @@ -79092,9 +81268,12 @@ 3201302528,3201433599,CL 3201433600,3201499135,AR 3201499136,3201515519,CL -3201515520,3201519615,AR -3201523712,3201531903,CR -3201531904,3201540095,AR +3201515520,3201522687,AR +3201522688,3201531903,CR +3201531904,3201533951,AR +3201533952,3201534975,HN +3201534976,3201535999,CO +3201536000,3201540095,AR 3201540096,3201544191,CL 3201548288,3201556479,AR 3201556480,3201560575,BO @@ -79123,8 +81302,18 @@ 3203476736,3203476991,CR 3203476992,3203477375,CO 3203477376,3203530751,CR -3203530752,3203538943,NI -3203538944,3203661823,CO +3203530752,3203531519,NI +3203531520,3203531775,PA +3203531776,3203532287,NI +3203532288,3203532543,PA +3203532544,3203532799,NI +3203532800,3203534847,PA +3203534848,3203535871,NI +3203535872,3203536383,PA +3203536384,3203538943,NI +3203538944,3203547135,CO +3203547136,3203549183,PA +3203549184,3203661823,CO 3203661824,3203923967,AR 3203923968,3204448255,CO 3221233664,3221237759,US @@ -79983,9 +82172,7 @@ 3225937664,3225938431,SE 3225938432,3225938687,US 3225938688,3225944063,SE -3225944064,3225977855,TW -3225977856,3225978111,CH -3225978112,3226008831,TW +3225944064,3226008831,TW 3226008832,3226009343,US 3226009600,3226010879,US 3226010880,3226011135,CA @@ -80016,9 +82203,7 @@ 3226191360,3226191615,US 3226191872,3226201855,CA 3226201856,3226202111,US -3226202112,3226205439,CA -3226205440,3226205695,AE -3226205696,3226205951,CA +3226202112,3226206207,CA 3226206208,3226215423,GB 3226215424,3226236927,US 3226237184,3226237439,US @@ -80904,9 +83089,15 @@ 3229151744,3229155327,US 3229155328,3229155839,SE 3229155840,3229156095,ES -3229156096,3229171455,SE +3229156096,3229168895,SE +3229168896,3229169151,JP +3229169152,3229171455,SE 3229171456,3229171711,MT -3229171712,3229200895,SE +3229171712,3229189119,SE +3229189120,3229189375,GB +3229189376,3229191167,SE +3229191168,3229191423,GB +3229191424,3229200895,SE 3229200896,3229201151,DE 3229201152,3229201663,SE 3229201664,3229201919,DK @@ -80965,22 +83156,7 @@ 3229391872,3229394943,US 3229394944,3229408255,RU 3229408256,3229412095,US -3229412096,3229470719,DE -3229470720,3229471231,IE -3229471232,3229471999,DE -3229472000,3229472255,IE -3229472256,3229472767,GB -3229472768,3229473791,DE -3229473792,3229474047,GB -3229474048,3229474303,DE -3229474304,3229475839,GB -3229475840,3229478399,DE -3229478400,3229478655,IE -3229478656,3229478911,DE -3229478912,3229480959,IE -3229480960,3229481471,DE -3229481472,3229482239,GB -3229482240,3229483007,IE +3229412096,3229483007,DE 3229483008,3229499647,FI 3229499648,3229500671,US 3229548544,3229679615,US @@ -83021,7 +85197,6 @@ 3239062784,3239063551,UA 3239063552,3239075839,DE 3239075840,3239076095,MT -3239076096,3239076351,SE 3239076352,3239076607,DE 3239076608,3239076863,PL 3239076864,3239077119,NL @@ -83066,7 +85241,6 @@ 3239108096,3239109887,DE 3239109888,3239110143,PL 3239110144,3239110655,DE -3239110656,3239110911,RU 3239110912,3239111167,UA 3239111168,3239111423,NL 3239111424,3239111935,DE @@ -83094,6 +85268,7 @@ 3239127040,3239127295,PT 3239127296,3239127551,PL 3239127552,3239127807,IL +3239127808,3239128063,RU 3239128064,3239128319,AT 3239128320,3239128575,IT 3239128576,3239128831,UA @@ -83128,7 +85303,6 @@ 3239160576,3239160831,DE 3239160832,3239161087,PL 3239161088,3239161343,BY -3239161344,3239161599,UA 3239161600,3239161855,HU 3239161856,3239162623,DE 3239162624,3239162879,BE @@ -83216,6 +85390,7 @@ 3239287808,3239288831,GB 3239288832,3239289855,DE 3239289856,3239290879,PL +3239290880,3239291903,RU 3239291904,3239292927,BG 3239292928,3239293951,CZ 3239293952,3239294975,DE @@ -83356,6 +85531,7 @@ 3239556608,3239556863,HR 3239556864,3239557119,UA 3239557120,3239567359,DE +3239567360,3239567615,GB 3239567616,3239567871,UA 3239567872,3239568127,DE 3239568128,3239568383,FR @@ -83390,6 +85566,7 @@ 3239634944,3239635967,RU 3239635968,3239636991,DE 3239636992,3239638015,BG +3239638016,3239639039,PL 3239639040,3239640063,SI 3239640064,3239641087,DE 3239641088,3239643135,PL @@ -83527,6 +85704,7 @@ 3239793664,3239794175,RO 3239794176,3239794687,NL 3239794688,3239795199,GB +3239795200,3239795711,PL 3239795712,3239796223,IL 3239796224,3239796735,NO 3239796736,3239821311,DE @@ -83601,11 +85779,12 @@ 3239877632,3239877887,UA 3239877888,3239878143,IT 3239878144,3239878399,PL -3239878400,3239882751,DE +3239878656,3239882751,DE 3239882752,3239883007,GB 3239883008,3239883263,UA 3239883264,3239883775,GB 3239883776,3239884031,DE +3239884032,3239884287,IR 3239884288,3239884543,GB 3239884544,3239884799,FR 3239884800,3239885055,UA @@ -83926,10 +86105,10 @@ 3240281600,3240281727,JO 3240281728,3240281855,PL 3240281856,3240281983,NL -3240281984,3240282111,FR 3240282112,3240282239,DE 3240282240,3240282367,UA 3240282368,3240282495,RO +3240282496,3240282623,RU 3240282624,3240282879,SE 3240282880,3240283007,UA 3240283008,3240283391,PL @@ -83944,7 +86123,16 @@ 3240296448,3240296703,RO 3240296704,3240302847,GB 3240302848,3240303103,UA -3240303104,3240361983,GB +3240303104,3240321023,GB +3240321024,3240321791,RU +3240321792,3240322047,PL +3240322048,3240322559,RU +3240322560,3240324095,CZ +3240324096,3240324351,RO +3240324352,3240324607,RU +3240324608,3240324863,PL +3240324864,3240325119,SI +3240325120,3240361983,GB 3240361984,3240362239,TR 3240362240,3240370175,GB 3240370176,3240370431,CH @@ -84117,7 +86305,6 @@ 3240730624,3240731647,ES 3240731648,3240732671,GB 3240732672,3240733695,SE -3240733696,3240734719,UA 3240734720,3240735743,IT 3240735744,3240736255,FR 3240736256,3240736767,BG @@ -84133,6 +86320,7 @@ 3240740608,3240741119,DE 3240741120,3240741375,AT 3240741376,3240741631,IL +3240741632,3240741887,RU 3240741888,3240742143,LV 3240742144,3240742399,IT 3240742400,3240742655,RO @@ -84242,7 +86430,7 @@ 3240867584,3240867839,CH 3240867840,3240873983,IT 3240873984,3240874495,RU -3240874496,3240875007,UA +3240874496,3240875007,CZ 3240875008,3240875519,AT 3240875520,3240876031,FR 3240876032,3240876543,DK @@ -84370,7 +86558,6 @@ 3241119232,3241119487,DK 3241119488,3241119743,BE 3241119744,3241119999,RO -3241120000,3241120255,UA 3241120256,3241120511,RU 3241120512,3241120767,GB 3241120768,3241121023,RU @@ -84429,7 +86616,6 @@ 3241501440,3241501951,EU 3241501952,3241502975,BE 3241502976,3241503231,GR -3241503232,3241503487,FR 3241503488,3241508095,BE 3241508096,3241508351,NL 3241508352,3241541375,BE @@ -84535,7 +86721,8 @@ 3243514112,3243514367,CH 3243514368,3243514623,IE 3243514624,3243514879,DK -3243514880,3243515391,AT +3243514880,3243515135,AT +3243515136,3243515391,CH 3243515392,3243515647,DE 3243515648,3243515903,RU 3243515904,3243520511,CZ @@ -84836,7 +87023,6 @@ 3244855552,3244855807,UA 3244856064,3244856319,IL 3244856320,3244856575,CH -3244856576,3244856831,RU 3244856832,3244857087,RO 3244857088,3244857343,IT 3244857344,3244857599,GB @@ -84904,7 +87090,6 @@ 3244875008,3244875263,PL 3244875264,3244875519,LI 3244875520,3244875775,IT -3244875776,3244876799,BZ 3244876800,3244877055,GB 3244877056,3244877311,JO 3244877312,3244877567,RU @@ -84930,7 +87115,6 @@ 3244882432,3244882687,IT 3244882688,3244882943,PL 3244882944,3244883199,NL -3244883200,3244883455,UA 3244883456,3244883711,CZ 3244883712,3244883967,NL 3244883968,3244884223,DE @@ -84946,7 +87130,6 @@ 3244886528,3244886783,DK 3244887040,3244887295,NL 3244887296,3244887551,GB -3244887552,3244887807,CZ 3244887808,3244888063,BE 3244888064,3244888319,RU 3244888320,3244888575,DE @@ -85387,6 +87570,7 @@ 3245139968,3245140479,CH 3245140480,3245140991,RO 3245140992,3245141503,UA +3245141504,3245142015,RO 3245142016,3245143039,UA 3245143040,3245144063,GB 3245144064,3245145087,UA @@ -85468,6 +87652,7 @@ 3245200384,3245200639,PL 3245200640,3245200895,GR 3245200896,3245201151,DE +3245201152,3245201407,KW 3245201408,3245201663,UA 3245201664,3245201919,NO 3245201920,3245202175,SA @@ -85745,7 +87930,9 @@ 3245909568,3245909631,US 3245909632,3245910831,IE 3245910832,3245910847,GB -3245910848,3245921279,IE +3245910848,3245919456,IE +3245919457,3245919462,IN +3245919463,3245921279,IE 3245921280,3245921535,BE 3245921536,3245922959,IE 3245922960,3245922975,US @@ -86162,7 +88349,9 @@ 3247335424,3247336447,FI 3247336448,3247337215,NO 3247337216,3247337471,CH -3247337472,3247338495,PL +3247337472,3247337983,PL +3247337984,3247338239,UA +3247338240,3247338495,PL 3247338496,3247338751,SI 3247338752,3247339519,GB 3247339520,3247340543,FI @@ -86202,7 +88391,7 @@ 3247366144,3247371007,FI 3247371008,3247371263,PL 3247371264,3247371519,SE -3247371776,3247374335,FI +3247372032,3247374335,FI 3247374336,3247374591,RU 3247374592,3247394047,FI 3247394048,3247394303,PL @@ -86220,7 +88409,8 @@ 3247438336,3247439871,FI 3247439872,3247702015,ES 3247702016,3247702271,RO -3247702272,3247704831,ES +3247702272,3247703551,ES +3247704064,3247704831,ES 3247704832,3247705087,GB 3247705088,3247705855,ES 3247705856,3247706111,RU @@ -86256,6 +88446,59 @@ 3247825920,3247826943,BE 3247826944,3247828991,CH 3247828992,3247833087,BE +3247833088,3247833599,RU +3247833600,3247834111,PL +3247834112,3247834623,DE +3247834624,3247835135,UA +3247835136,3247836159,GB +3247836160,3247837183,CZ +3247837184,3247838207,ES +3247838208,3247838719,CH +3247838720,3247839231,NO +3247839232,3247839743,CZ +3247839744,3247840255,GB +3247840256,3247841279,UA +3247841280,3247841791,RU +3247841792,3247842047,GB +3247842048,3247842303,CZ +3247842304,3247842815,PL +3247842816,3247843327,CZ +3247843328,3247843583,LT +3247843584,3247845375,PL +3247845376,3247845631,CH +3247845632,3247845887,UA +3247845888,3247846399,PL +3247846400,3247847423,RU +3247847424,3247848447,UA +3247848448,3247849471,IT +3247849472,3247849727,DE +3247849728,3247849983,RU +3247849984,3247850239,GB +3247850240,3247850495,BG +3247850496,3247850751,RU +3247850752,3247851007,PL +3247851008,3247851519,RU +3247851520,3247852543,SK +3247852544,3247853567,PL +3247853568,3247854591,RU +3247854592,3247855615,DK +3247855616,3247856127,UA +3247856128,3247856639,ES +3247856640,3247857663,RU +3247857664,3247858175,UA +3247858176,3247858687,EU +3247858688,3247859711,RU +3247859712,3247859967,SE +3247859968,3247861759,RU +3247861760,3247862015,IT +3247862016,3247862271,UA +3247862272,3247864063,RU +3247864064,3247864319,NO +3247864320,3247864575,UA +3247864576,3247864831,PL +3247864832,3247865343,RU +3247865344,3247865599,MT +3247865600,3247865855,IL 3247865856,3247871999,GB 3247872000,3247875327,NL 3247875328,3247875583,PL @@ -86335,7 +88578,12 @@ 3248522240,3248525311,NO 3248525312,3248525567,DE 3248525568,3248525823,DK -3248525824,3248545791,NO +3248525824,3248528895,NO +3248528896,3248529151,RU +3248529152,3248529407,BG +3248529408,3248540671,NO +3248540672,3248541183,RU +3248541184,3248545791,NO 3248545792,3248546815,UA 3248546816,3248547839,RU 3248547840,3248553727,NO @@ -86345,7 +88593,10 @@ 3248557056,3248558079,UA 3248558080,3248575487,NO 3248575488,3248576511,CZ -3248576512,3248619263,NO +3248576512,3248603135,NO +3248603136,3248603391,BG +3248603392,3248603647,RU +3248603648,3248619263,NO 3248619264,3248619519,UA 3248619520,3248638463,DK 3248638464,3248638719,GB @@ -86385,8 +88636,8 @@ 3248790784,3248791039,PL 3248791040,3248791295,BE 3248791296,3248791551,DE -3248791552,3248792527,GB -3248792528,3248796607,EU +3248791552,3248792543,GB +3248792544,3248796607,EU 3248796608,3248796863,GB 3248796864,3248798975,EU 3248798976,3248799231,GB @@ -86798,12 +89049,12 @@ 3250372608,3250373375,HU 3250373376,3250373631,GB 3250373632,3250374143,DE +3250374144,3250374655,PL 3250374656,3250374911,SA 3250374912,3250375679,SE 3250375680,3250376703,GB 3250376704,3250380799,AT -3250380800,3250381055,DK -3250381056,3250386943,CH +3250380800,3250386943,CH 3250386944,3250387199,SE 3250387200,3250387455,FR 3250387456,3250387711,DE @@ -86878,6 +89129,7 @@ 3250589440,3250589471,IE 3250589472,3250589503,NL 3250589504,3250589567,HR +3250589568,3250589631,RU 3250589632,3250589695,NO 3250589696,3250593791,CH 3250593792,3250594815,GB @@ -86935,7 +89187,13 @@ 3250733056,3250741247,DZ 3250741248,3250742783,RU 3250742784,3250743551,AT -3250743808,3250745343,UA +3250743552,3250743807,CY +3250743808,3250746367,UA +3250746368,3250747391,NL +3250747392,3250747903,SI +3250747904,3250748159,SA +3250748160,3250748415,PL +3250748416,3250749439,UA 3250749440,3250749695,GH 3250749696,3250749951,IT 3250749952,3250750463,RO @@ -87201,7 +89459,6 @@ 3251201536,3251201791,AT 3251201792,3251202047,FR 3251202048,3251202303,NL -3251202304,3251202559,PL 3251202560,3251202815,AT 3251202816,3251203327,ES 3251203328,3251203583,SI @@ -87446,7 +89703,44 @@ 3251927992,3251927999,NL 3251928000,3252015687,NO 3252015688,3252015695,SE -3252015696,3252289535,NO +3252015696,3252168191,NO +3252168192,3252174847,SE +3252174848,3252177151,NO +3252177152,3252177407,SE +3252177408,3252178431,NO +3252178432,3252178943,SE +3252178944,3252179199,NO +3252179200,3252189183,SE +3252189184,3252189695,NO +3252189696,3252190975,SE +3252190976,3252191231,NO +3252191232,3252197119,SE +3252197120,3252197375,NO +3252197376,3252205567,SE +3252205568,3252205823,NO +3252205824,3252211967,SE +3252211968,3252212223,NO +3252212224,3252213759,SE +3252213760,3252214527,NO +3252214528,3252218879,SE +3252218880,3252219135,NO +3252219136,3252220927,SE +3252220928,3252221183,NO +3252221184,3252222463,SE +3252222464,3252223231,NO +3252223232,3252223743,SE +3252223744,3252223999,NO +3252224000,3252233215,SE +3252233216,3252240383,NO +3252240384,3252244479,SE +3252244480,3252246527,NO +3252246528,3252276223,SE +3252276224,3252277759,NO +3252277760,3252279295,SE +3252279296,3252279807,NO +3252279808,3252286463,SE +3252286464,3252286975,NO +3252286976,3252289535,SE 3252289536,3252291327,GR 3252291328,3252291583,SK 3252291584,3252293631,FR @@ -87489,15 +89783,13 @@ 3252342528,3252342543,NO 3252342544,3252342591,DE 3252342592,3252342607,IE -3252342640,3252342655,LV 3252342656,3252342783,IL 3252342784,3252346367,DE 3252346368,3252346623,GB 3252346624,3252355071,GR 3252355072,3252355327,GB 3252355328,3252358911,LT -3252358912,3252358927,GB -3252358928,3252359167,DE +3252358912,3252359167,DE 3252359168,3252362239,DK 3252362240,3252362495,PL 3252362496,3252362751,IT @@ -87608,9 +89900,7 @@ 3252409504,3252409511,GH 3252409512,3252409519,BF 3252409520,3252409527,NG -3252409528,3252409535,LT -3252409536,3252409543,BI -3252409544,3252409599,LT +3252409528,3252409599,LT 3252409600,3252409615,MA 3252409616,3252409631,LT 3252409632,3252409647,AO @@ -87640,7 +89930,9 @@ 3252411824,3252411839,LT 3252411840,3252411855,MR 3252411856,3252411879,LT -3252411880,3252411903,CD +3252411880,3252411887,CD +3252411888,3252411895,LT +3252411896,3252411903,CD 3252411904,3252414463,LT 3252414464,3252414479,GH 3252414480,3252414511,LT @@ -87653,9 +89945,7 @@ 3252414640,3252414647,GH 3252414648,3252414655,NE 3252414656,3252414975,LT -3252414976,3252414999,IQ -3252415000,3252415015,LT -3252415016,3252415031,IQ +3252414976,3252415031,IQ 3252415032,3252415039,LT 3252415040,3252415095,IQ 3252415096,3252415103,LT @@ -87674,8 +89964,8 @@ 3252417280,3252417287,IQ 3252417288,3252417463,AF 3252417464,3252417471,LT -3252417472,3252417503,AF -3252417504,3252417791,LT +3252417472,3252417511,AF +3252417512,3252417791,LT 3252417792,3252417855,NG 3252417856,3252417919,LT 3252417920,3252417935,MW @@ -87741,8 +90031,7 @@ 3252425552,3252425575,AO 3252425576,3252425727,LT 3252425728,3252425983,A2 -3252425984,3252426239,LT -3252426240,3252426751,BW +3252425984,3252426751,LT 3252426752,3252427263,MZ 3252427264,3252427519,NG 3252427520,3252427775,LT @@ -87757,8 +90046,8 @@ 3252430336,3252430463,NE 3252430464,3252430511,LT 3252430512,3252430519,BF -3252430520,3252430527,LT -3252430528,3252430543,BF +3252430520,3252430535,LT +3252430536,3252430543,BF 3252430544,3252430559,BJ 3252430560,3252430591,LT 3252430592,3252430847,GN @@ -87779,7 +90068,9 @@ 3252434704,3252434711,TZ 3252434712,3252434719,LT 3252434720,3252434743,GH -3252434744,3252435199,LT +3252434744,3252434751,ML +3252434752,3252434759,GN +3252434760,3252435199,LT 3252435200,3252435231,TZ 3252435232,3252435247,LT 3252435248,3252435263,BW @@ -87792,8 +90083,7 @@ 3252435344,3252435375,BF 3252435376,3252435415,GN 3252435416,3252435423,LT -3252435424,3252435447,CD -3252435448,3252435455,LT +3252435424,3252435455,CD 3252435456,3252435711,TZ 3252435712,3252435855,GH 3252435856,3252435871,MR @@ -87801,8 +90091,7 @@ 3252435888,3252435903,CD 3252435904,3252435919,BW 3252435920,3252435935,BF -3252435936,3252435951,CF -3252435952,3252435967,LT +3252435936,3252435967,LT 3252435968,3252436223,TZ 3252436224,3252436239,GN 3252436240,3252436255,LT @@ -87906,7 +90195,9 @@ 3252457472,3252460799,LT 3252460800,3252460831,AF 3252460832,3252460847,US -3252460848,3252461055,LT +3252460848,3252460863,LT +3252460864,3252460927,IQ +3252460928,3252461055,LT 3252461056,3252461567,NO 3252461568,3252464383,LT 3252464384,3252465663,NO @@ -87996,7 +90287,9 @@ 3252616704,3252616959,ES 3252616960,3252617215,CH 3252617216,3252617471,PL -3252617472,3252636671,CH +3252617472,3252634623,CH +3252634624,3252634879,RU +3252634880,3252636671,CH 3252636672,3252636927,TR 3252636928,3252637183,DE 3252637184,3252637695,GB @@ -88052,6 +90345,7 @@ 3252912896,3252913151,PL 3252913152,3252913407,ES 3252913408,3252913663,FR +3252913664,3252913919,RU 3252913920,3252914175,NO 3252914176,3252916223,FR 3252916224,3252920319,DE @@ -88129,11 +90423,13 @@ 3253403648,3253403903,PL 3253403904,3253409791,SE 3253409792,3253410047,GB -3253410048,3253412351,SE +3253410048,3253411327,SE +3253411328,3253411583,NO +3253411584,3253412351,SE 3253412352,3253412607,US 3253412608,3253416447,SE -3253416448,3253416703,GB -3253416704,3253428223,SE +3253416448,3253416959,GB +3253416960,3253428223,SE 3253428224,3253428479,DE 3253428480,3253429759,SE 3253429760,3253430015,ES @@ -88150,9 +90446,16 @@ 3253453312,3253453567,NO 3253453568,3253454079,SE 3253454080,3253454335,GB -3253454336,3253460735,SE +3253454336,3253455615,SE +3253455616,3253455871,US +3253455872,3253456383,SE +3253456384,3253456639,US +3253456640,3253460735,SE 3253460736,3253460991,IT -3253460992,3253469183,SE +3253460992,3253461247,US +3253461248,3253463039,SE +3253463040,3253464063,GB +3253464064,3253469183,SE 3253469184,3253471231,AO 3253471232,3253534719,PT 3253534720,3253600255,GB @@ -88244,7 +90547,6 @@ 3253697536,3253698559,PL 3253698560,3253699071,UA 3253699072,3253699583,RO -3253699584,3253700095,UA 3253700096,3253700607,RO 3253700608,3253701119,PL 3253701120,3253702143,RO @@ -88313,6 +90615,7 @@ 3253888256,3253888511,BE 3253888512,3253888767,GB 3253888768,3253889023,SE +3253889024,3253889279,RO 3253889280,3253889535,CH 3253889536,3253889791,DE 3253889792,3253890047,DK @@ -88355,6 +90658,7 @@ 3253968896,3253969407,DE 3253969408,3253969919,AT 3253969920,3253970431,NL +3253970432,3253970687,RU 3253970688,3253970943,UA 3253970944,3253971967,RS 3253971968,3253972991,RU @@ -88554,6 +90858,7 @@ 3254708224,3254708735,UA 3254708736,3254709247,RO 3254709248,3254709759,DE +3254709760,3254710271,PL 3254710272,3254710783,IT 3254710784,3254711295,RO 3254711296,3254711807,FR @@ -88586,6 +90891,8 @@ 3254787072,3254788095,NL 3254788096,3254788351,BG 3254788352,3254789119,ES +3254789120,3254789375,FR +3254789632,3254790655,TK 3254796288,3254797311,SE 3254797312,3254798335,RU 3254798336,3254799359,AT @@ -88597,6 +90904,7 @@ 3254804480,3254806527,PL 3254806528,3254807551,UA 3254807552,3254808575,KZ +3254808576,3254809599,RU 3254809600,3254810623,UA 3254810624,3254811647,RU 3254811648,3254812671,RO @@ -88703,6 +91011,7 @@ 3254840320,3254840575,DK 3254840576,3254840831,UA 3254840832,3254841343,GB +3254841344,3254841599,PL 3254841600,3254841855,IE 3254841856,3254842111,LV 3254842112,3254842367,GB @@ -89116,6 +91425,7 @@ 3255366144,3255367167,DK 3255367168,3255367679,RU 3255367680,3255368191,UA +3255368192,3255368703,FR 3255368704,3255369215,CZ 3255369216,3255369727,GB 3255369728,3255370239,LU @@ -89152,7 +91462,7 @@ 3255385600,3255386111,FR 3255386112,3255386623,KE 3255386624,3255387135,PL -3255387136,3255388159,UA +3255387648,3255388159,UA 3255388160,3255388671,DE 3255388672,3255389183,SE 3255389184,3255389695,GB @@ -89179,7 +91489,6 @@ 3255416832,3255417855,FR 3255417856,3255418879,GB 3255418880,3255422975,DE -3255422976,3255426047,GB 3255426048,3255426559,IT 3255426560,3255426815,FR 3255426816,3255427071,PL @@ -89278,9 +91587,7 @@ 3255558144,3255558399,BE 3255558400,3255564031,CH 3255564032,3255564287,RU -3255564288,3255565567,CH -3255565568,3255566079,DE -3255566080,3255566335,CH +3255564288,3255566335,CH 3255566336,3255574527,SE 3255574528,3255578623,CZ 3255578624,3255582719,SE @@ -89293,14 +91600,18 @@ 3255660544,3255666431,NL 3255666432,3255666687,DE 3255666688,3255697407,NL -3255697408,3255710719,SE +3255697408,3255698687,SE +3255698688,3255698943,GB +3255698944,3255710719,SE 3255710720,3255710975,ES 3255710976,3255724543,SE 3255724544,3255725055,US 3255725056,3255725311,ES 3255725312,3255739647,SE 3255739648,3255739903,GB -3255739904,3255743231,SE +3255739904,3255742719,SE +3255742720,3255742975,SG +3255742976,3255743231,SE 3255743232,3255743487,IT 3255743488,3255743743,DE 3255743744,3255745535,SE @@ -89335,7 +91646,11 @@ 3256075008,3256076287,DK 3256076288,3256076799,SE 3256076800,3256082431,DK -3256082432,3256090623,LV +3256082432,3256088063,LV +3256088064,3256088095,RU +3256088096,3256088103,LV +3256088104,3256088319,RU +3256088320,3256090623,LV 3256090624,3256164863,IT 3256164864,3256165375,SE 3256165376,3256187391,IT @@ -89481,7 +91796,7 @@ 3256699392,3256700415,GB 3256700416,3256700671,NL 3256700672,3256700927,FR -3256700928,3256701183,EU +3256700928,3256701183,DE 3256701184,3256701439,BE 3256701440,3256701695,GB 3256701696,3256705279,EU @@ -90490,9 +92805,7 @@ 3257827840,3257829375,GB 3257829376,3257830399,IE 3257830400,3257835519,GB -3257835520,3257844223,IE -3257844224,3257851903,GB -3257851904,3257860095,IE +3257835520,3257860095,IE 3257860096,3257925631,SE 3257925632,3257925887,AT 3257925888,3257926143,SE @@ -90833,17 +93146,27 @@ 3259236864,3259237119,CH 3259237120,3259237887,SE 3259237888,3259238143,FR -3259238144,3259248127,SE +3259238144,3259243519,SE +3259243520,3259244543,US +3259244544,3259248127,SE 3259248128,3259248383,GB 3259248384,3259258623,SE 3259258624,3259258879,ES 3259258880,3259262719,SE 3259262720,3259262975,DK -3259262976,3259269375,SE +3259262976,3259266047,SE +3259266048,3259266303,SG +3259266304,3259269375,SE 3259269376,3259269631,FR 3259269632,3259276287,SE 3259276288,3259276543,ES -3259276544,3259285759,SE +3259276544,3259279615,SE +3259279616,3259279871,JP +3259279872,3259281407,SE +3259281408,3259282431,US +3259282432,3259282687,SE +3259282688,3259282943,JP +3259282944,3259285759,SE 3259285760,3259286015,GB 3259286016,3259290879,SE 3259290880,3259291135,US @@ -90965,7 +93288,9 @@ 3259461376,3259461631,GB 3259461632,3259465215,SE 3259465216,3259465471,KH -3259465472,3259479807,SE +3259465472,3259470847,SE +3259470848,3259471871,US +3259471872,3259479807,SE 3259479808,3259480063,DK 3259480064,3259480831,SE 3259480832,3259481087,ES @@ -91061,7 +93386,9 @@ 3259696640,3259696895,ES 3259696896,3259701759,GB 3259701760,3259702303,DE -3259702304,3259752191,GB +3259702304,3259709999,GB +3259710000,3259710007,JE +3259710008,3259752191,GB 3259752192,3259752447,FR 3259752448,3259760639,GB 3259760640,3259814399,DE @@ -91154,6 +93481,7 @@ 3260587520,3260588031,PL 3260588032,3260596223,DE 3260596224,3260596735,CH +3260596736,3260597247,SK 3260597248,3260597759,CH 3260597760,3260598271,DE 3260598272,3260598783,RU @@ -91210,6 +93538,7 @@ 3260901120,3260903423,DE 3260903424,3260906239,CH 3260906240,3260906495,DE +3260906496,3260907519,PL 3260907520,3260915711,GB 3260915712,3260923903,UA 3260923904,3261071359,DE @@ -91237,7 +93566,13 @@ 3261503936,3261530111,RO 3261530112,3261531903,SE 3261531904,3261532159,GB -3261532160,3261570303,SE +3261532160,3261532671,SE +3261532672,3261532927,US +3261532928,3261533439,SE +3261533440,3261533695,US +3261533696,3261539327,SE +3261539328,3261540351,SG +3261540352,3261570303,SE 3261570304,3261570559,IT 3261570560,3261595647,SE 3261595648,3261661183,NL @@ -91264,8 +93599,7 @@ 3261697024,3261698047,RO 3261698048,3261698559,UA 3261698560,3261699071,DE -3261699072,3261699583,SA -3261699584,3261700095,NL +3261699072,3261700095,NL 3261700096,3261700607,FR 3261700608,3261701119,GB 3261701120,3261701631,RU @@ -91282,7 +93616,6 @@ 3261775872,3261776383,PL 3261776384,3261777407,RU 3261777408,3261777663,IR -3261777664,3261777919,KZ 3261777920,3261778431,PL 3261778432,3261778943,RU 3261778944,3261779455,RO @@ -91571,7 +93904,7 @@ 3262283776,3262284799,RU 3262284800,3262286847,UA 3262286848,3262287871,SE -3262287872,3262289919,PL +3262288896,3262289919,PL 3262289920,3262316543,SE 3262316544,3262348799,DE 3262348800,3262349055,NL @@ -91593,6 +93926,10 @@ 3262423040,3262423551,GB 3262423552,3262424063,UA 3262424064,3262424575,IT +3262424576,3262424831,PL +3262424832,3262425087,GB +3262425088,3262425343,GR +3262425344,3262425599,RU 3262425600,3262426111,UA 3262426112,3262426623,DE 3262426624,3262427135,GB @@ -91637,7 +93974,6 @@ 3262460416,3262460543,UA 3262460544,3262460671,RU 3262460672,3262460927,AE -3262460928,3262461055,HU 3262461056,3262461183,DK 3262461184,3262461311,SN 3262461312,3262461439,NO @@ -92393,7 +94729,7 @@ 3262476656,3262476667,US 3262476668,3262476671,GB 3262476672,3262476675,SE -3262476676,3262476679,AT +3262476676,3262476679,DE 3262476680,3262476683,NL 3262476684,3262476687,IT 3262476688,3262476691,DE @@ -93575,8 +95911,7 @@ 3262479420,3262479420,ES 3262479421,3262479421,DE 3262479422,3262479422,SE -3262479423,3262479423,AT -3262479424,3262479426,DE +3262479423,3262479426,DE 3262479427,3262479427,IT 3262479428,3262479429,FR 3262479430,3262479430,GB @@ -94375,6 +96710,7 @@ 3263072256,3263074303,LB 3263074304,3263074815,CH 3263074816,3263075327,RO +3263075328,3263075839,IT 3263075840,3263076351,SE 3263076352,3263076863,RO 3263076864,3263077375,IT @@ -94422,6 +96758,7 @@ 3263096064,3263096319,PL 3263096320,3263096575,TR 3263096576,3263096831,SA +3263096832,3263097087,PL 3263097088,3263097343,FR 3263097344,3263097599,DK 3263097600,3263097855,NL @@ -94459,12 +96796,20 @@ 3263459584,3263459839,FR 3263459840,3263461631,SE 3263461632,3263461887,AE -3263461888,3263477759,SE +3263461888,3263469567,SE +3263469568,3263470591,SG +3263470592,3263472127,SE +3263472128,3263472383,SG +3263472384,3263475711,SE +3263475712,3263476735,JP +3263476736,3263477759,SE 3263477760,3263478015,JP 3263478016,3263478271,AU 3263478272,3263478527,SE 3263478528,3263478783,ES -3263478784,3263496191,SE +3263478784,3263480831,SE +3263480832,3263481855,JP +3263481856,3263496191,SE 3263496192,3263497983,EU 3263497984,3263498239,GB 3263498240,3263498751,EU @@ -94637,9 +96982,7 @@ 3264092288,3264092295,AX 3264092296,3264099839,FI 3264099840,3264100095,GB -3264100096,3264118595,FI -3264118596,3264118599,AX -3264118600,3264124927,FI +3264100096,3264124927,FI 3264124928,3264125183,DE 3264125184,3264125439,NL 3264125440,3264125695,FI @@ -94697,6 +97040,7 @@ 3264320000,3264320255,DE 3264320256,3264321023,GB 3264321024,3264321535,DE +3264321536,3264321791,GB 3264321792,3264322047,RS 3264322048,3264322303,FR 3264322304,3264322559,RO @@ -94761,7 +97105,7 @@ 3264378880,3264379135,PL 3264379136,3264379391,BE 3264379392,3264379647,RU -3264379648,3264380159,DE +3264379904,3264380159,DE 3264380160,3264380415,RO 3264380416,3264380671,CH 3264380672,3264380927,NL @@ -94846,17 +97190,28 @@ 3264613312,3264613375,GB 3264613376,3264613887,NL 3264613888,3264613895,GB -3264613896,3264613903,NL -3264613904,3264614399,GB +3264613896,3264613919,NL +3264613920,3264614399,GB 3264614400,3264614655,NL 3264614656,3264614911,SE 3264614912,3264615423,GB -3264615424,3264615727,CH -3264615728,3264617215,GB -3264617216,3264617471,DE +3264615424,3264615735,CH +3264615736,3264615743,GB +3264615744,3264615775,CH +3264615776,3264616447,GB +3264616448,3264616463,DE +3264616464,3264616575,GB +3264616576,3264616703,DE +3264616704,3264616959,GB +3264616960,3264617471,DE 3264617472,3264618239,GB 3264618240,3264618495,US -3264618496,3264622847,GB +3264618496,3264618751,PL +3264618752,3264619007,GB +3264619008,3264619263,BE +3264619264,3264620543,GB +3264620544,3264620575,FR +3264620576,3264622847,GB 3264622848,3264623103,FR 3264623104,3264626687,GB 3264626688,3264627711,EE @@ -94877,6 +97232,7 @@ 3264652288,3264652799,RU 3264652800,3264653311,PL 3264653312,3264653823,EU +3264653824,3264654335,PL 3264654336,3264654847,DE 3264654848,3264655359,UA 3264655360,3264655871,GB @@ -94997,7 +97353,7 @@ 3264846592,3264846719,US 3264846720,3264846847,RU 3264846848,3264846911,DK -3264846976,3264847103,GB +3264847040,3264847103,GB 3264847104,3264847135,FR 3264847136,3264847167,ES 3264847168,3264847199,IE @@ -95154,7 +97510,7 @@ 3265603328,3265603583,MD 3265603584,3265603839,DE 3265603840,3265604095,PL -3265604096,3265604351,SA +3265604096,3265604351,NL 3265604352,3265604607,FR 3265604608,3265604863,CH 3265604864,3265605119,RU @@ -95164,6 +97520,7 @@ 3265605888,3265606143,FR 3265606400,3265606655,NL 3265606656,3265606911,AT +3265606912,3265607167,RU 3265607168,3265607423,PL 3265607424,3265607935,DK 3265607936,3265608191,CZ @@ -95712,9 +98069,7 @@ 3267662952,3267662959,GB 3267662960,3267662991,IE 3267662992,3267663007,EU -3267663008,3267663071,IE -3267663072,3267663087,EU -3267663088,3267663103,IE +3267663008,3267663103,IE 3267663104,3267663327,IT 3267663328,3267663359,EU 3267663360,3267663871,GB @@ -96349,7 +98704,7 @@ 3269284864,3269285055,FR 3269285056,3269285087,EU 3269285088,3269285135,DE -3269285136,3269285151,EU +3269285136,3269285151,GB 3269285152,3269285215,DE 3269285216,3269285311,EU 3269285312,3269285327,DE @@ -96670,6 +99025,7 @@ 3270653440,3270653695,NL 3270653696,3270653951,GB 3270653952,3270654207,ES +3270654208,3270654463,RO 3270654464,3270654719,BE 3270654720,3270655231,UA 3270655232,3270655487,IT @@ -96941,10 +99297,14 @@ 3271426304,3271491583,FR 3271491584,3271495679,DK 3271495680,3271495807,SE -3271495808,3271501663,DK +3271495808,3271501567,DK +3271501568,3271501575,SE +3271501576,3271501663,DK 3271501664,3271501679,DE 3271501680,3271501695,SE -3271501696,3271557119,DK +3271501696,3271501783,DK +3271501784,3271501791,SE +3271501792,3271557119,DK 3271557120,3271589887,BE 3271589888,3271688191,NO 3271688192,3271691775,EU @@ -97012,6 +99372,7 @@ 3271805952,3271806975,UA 3271806976,3271807999,EU 3271808000,3271810047,DE +3271810048,3271811071,PL 3271811072,3271812095,UA 3271812096,3271813119,ES 3271813120,3271814143,PL @@ -97040,8 +99401,8 @@ 3271915008,3271915519,SE 3271915520,3271916031,NL 3271916032,3271916543,GB -3271916544,3271917055,UA -3271917568,3271925759,RU +3271916544,3271917311,UA +3271917312,3271925759,RU 3271925760,3271926015,DE 3271926016,3271926271,MD 3271926272,3271926527,RU @@ -97154,7 +99515,7 @@ 3272111872,3272112383,RO 3272112384,3272113151,DE 3272113152,3272113407,FR -3272113664,3272113919,GB +3272113408,3272113919,GB 3272113920,3272114175,AT 3272114176,3272122367,PL 3272122368,3272131071,GB @@ -97349,14 +99710,16 @@ 3272239688,3272239695,IM 3272239696,3272239703,GB 3272239704,3272239711,IM -3272239712,3272239791,GB -3272239792,3272239799,IM +3272239712,3272239775,GB +3272239776,3272239799,IM 3272239800,3272240127,GB 3272240128,3272240367,IM 3272240368,3272240575,GB 3272240576,3272240639,GH 3272240640,3272241215,GB -3272241216,3272241295,IM +3272241216,3272241247,IM +3272241248,3272241279,GB +3272241280,3272241295,IM 3272241296,3272241303,GB 3272241304,3272241311,IM 3272241312,3272241335,GB @@ -97444,8 +99807,8 @@ 3272376320,3272376447,SK 3272376448,3272376479,SR 3272376480,3272376495,SK -3272376496,3272376519,SR -3272376520,3272376535,SK +3272376496,3272376527,SR +3272376528,3272376535,SK 3272376536,3272376543,SR 3272376544,3272376607,SK 3272376608,3272376639,SR @@ -97453,11 +99816,13 @@ 3272376736,3272376751,SR 3272376752,3272376767,SK 3272376768,3272376831,SR -3272376832,3272384511,SK +3272376832,3272378183,SK +3272378184,3272378201,SR +3272378202,3272384511,SK 3272384512,3272392703,LT 3272392704,3272400895,AT -3272400896,3272400903,EU -3272400904,3272400927,GB +3272400896,3272400911,EU +3272400912,3272400927,GB 3272400928,3272401023,EU 3272401024,3272401087,GB 3272401088,3272401279,EU @@ -97750,9 +100115,7 @@ 3272931152,3272933375,DE 3272933376,3272940287,GB 3272940288,3272940543,DE -3272940544,3272964351,GB -3272964352,3272964607,DE -3272964608,3272998911,GB +3272940544,3272998911,GB 3272998912,3273007103,PT 3273007104,3273015295,CZ 3273015296,3273023487,SE @@ -97855,7 +100218,7 @@ 3273264640,3273265151,AT 3273265152,3273266175,UA 3273266176,3273266687,LV -3273266688,3273267711,PL +3273266688,3273267455,PL 3273267712,3273268223,GB 3273268224,3273268735,SE 3273268736,3273269247,RU @@ -97885,7 +100248,8 @@ 3273327424,3273327511,GB 3273327512,3273327519,EU 3273327520,3273327551,IE -3273327552,3273328511,EU +3273327552,3273327583,GB +3273327584,3273328511,EU 3273328512,3273328639,DE 3273328640,3273329199,GB 3273329200,3273329215,DE @@ -98124,14 +100488,13 @@ 3273437184,3273437695,RO 3273437696,3273438207,PL 3273438208,3273438719,IL -3273438720,3273439231,PL 3273439232,3273439743,RO 3273439744,3273440255,DE 3273440256,3273440767,RO 3273440768,3273441279,AT 3273441280,3273443327,GB -3273443328,3273443839,FR -3273443840,3273449471,GB +3273443328,3273444095,FR +3273444096,3273449471,GB 3273449472,3273457663,CH 3273457664,3273523199,HR 3273523200,3273588735,DE @@ -98221,9 +100584,8 @@ 3273878016,3273878271,FR 3273878272,3273878527,LV 3273878528,3273879039,DE -3273879040,3273879551,EU +3273879040,3273879551,BE 3273879552,3273880063,GB -3273880064,3273880575,LV 3273880576,3273881087,RU 3273881088,3273881343,RO 3273881344,3273881599,CH @@ -98280,6 +100642,8 @@ 3274172416,3274172927,UA 3274172928,3274173439,DE 3274173440,3274173951,GR +3274173952,3274174207,GB +3274174208,3274174463,CZ 3274174464,3274175487,UA 3274175488,3274175999,BE 3274176000,3274176511,DE @@ -98359,7 +100723,6 @@ 3274398208,3274399231,RU 3274399232,3274399743,SC 3274399744,3274407935,LU -3274407936,3274408191,ES 3274408192,3274408447,IT 3274408448,3274408703,NL 3274408704,3274408959,SI @@ -98386,6 +100749,7 @@ 3274414336,3274414591,CH 3274414592,3274414847,NL 3274414848,3274415103,IE +3274415104,3274415359,PL 3274415360,3274415615,GB 3274415616,3274415871,NL 3274415872,3274416127,SI @@ -98635,6 +100999,7 @@ 3274701056,3274701311,DE 3274701312,3274701567,TJ 3274701568,3274701823,IT +3274701824,3274702079,IL 3274702080,3274702335,UA 3274702336,3274702591,SE 3274702592,3274702847,KZ @@ -98901,15 +101266,9 @@ 3275423752,3275423775,EU 3275423776,3275423807,GB 3275423808,3275423871,EU -3275423872,3275425067,GB -3275425068,3275425071,EU -3275425072,3275425087,GB -3275425088,3275425791,EU -3275425792,3275427639,GB -3275427640,3275427647,EU -3275427648,3275427759,GB -3275427760,3275427775,EU -3275427776,3275428399,GB +3275423872,3275425159,GB +3275425160,3275425791,EU +3275425792,3275428399,GB 3275428400,3275428415,EU 3275428416,3275428447,GB 3275428448,3275429887,EU @@ -98923,20 +101282,16 @@ 3275430912,3275431935,EU 3275431936,3275432831,GB 3275432832,3275433983,EU -3275433984,3275438647,GB -3275438648,3275438655,EU -3275438656,3275438671,GB -3275438672,3275438687,EU -3275438688,3275439103,GB -3275439104,3275440127,EU +3275433984,3275439423,GB +3275439424,3275440127,EU 3275440128,3275440639,GB 3275440640,3275442175,EU 3275442176,3275442719,GB 3275442720,3275444223,EU 3275444224,3275444735,GB 3275444736,3275446271,EU -3275446272,3275447135,GB -3275447136,3275448319,EU +3275446272,3275447151,GB +3275447152,3275448319,EU 3275448320,3275449519,GB 3275449520,3275449527,FR 3275449528,3275450879,GB @@ -98945,13 +101300,12 @@ 3275451264,3275452415,EU 3275452416,3275454127,GB 3275454128,3275454143,EU -3275454144,3275456383,GB -3275456384,3275456391,EU -3275456392,3275457023,GB +3275454144,3275457023,GB 3275457024,3275457791,FK 3275457792,3275458559,GB 3275458560,3275460095,IE -3275460096,3275460607,EU +3275460096,3275460223,GB +3275460224,3275460607,EU 3275460608,3275460863,HK 3275460864,3275463523,GB 3275463524,3275463527,EU @@ -98965,8 +101319,18 @@ 3275468768,3275468799,IE 3275468800,3275469071,GB 3275469072,3275469087,IE -3275469088,3275473215,GB -3275473216,3275489279,EU +3275469088,3275473519,GB +3275473520,3275473535,EU +3275473536,3275473599,GB +3275473600,3275474943,EU +3275474944,3275474975,GB +3275474976,3275475071,EU +3275475072,3275475199,GB +3275475200,3275476991,EU +3275476992,3275477055,GB +3275477056,3275477503,EU +3275477504,3275477567,GB +3275477568,3275489279,EU 3275489280,3275497471,GB 3275497472,3275505663,DE 3275505664,3275506175,PL @@ -98988,7 +101352,6 @@ 3275510464,3275510527,GB 3275510528,3275510559,PL 3275510560,3275510591,DE -3275510592,3275510623,FR 3275510624,3275510655,EE 3275510656,3275510687,FR 3275510720,3275510751,GB @@ -99010,7 +101373,7 @@ 3275512832,3275512895,SE 3275512896,3275512959,AT 3275512960,3275513023,PL -3275513024,3275513151,UA +3275513024,3275513087,UA 3275513152,3275513215,ES 3275513216,3275513279,CH 3275513280,3275513343,DK @@ -99026,7 +101389,6 @@ 3275530752,3275531263,AT 3275531264,3275531775,GB 3275531776,3275532287,IE -3275532288,3275532799,CH 3275532800,3275533823,GB 3275533824,3275534335,UA 3275534336,3275534847,IL @@ -99043,6 +101405,7 @@ 3275542528,3275543551,DE 3275543552,3275544575,NL 3275544576,3275545599,PL +3275545600,3275546623,RU 3275546624,3275547647,UA 3275548672,3275549695,IL 3275549696,3275550719,SY @@ -99343,6 +101706,7 @@ 3275909888,3275910143,SI 3275910144,3275910399,RU 3275910400,3275910655,DK +3275910656,3275910911,UA 3275910912,3275911167,DE 3275911168,3275911423,FR 3275911424,3275911679,RO @@ -99427,11 +101791,15 @@ 3276014472,3276014495,GB 3276014496,3276014775,FR 3276014776,3276014783,GB -3276014784,3276014887,FR +3276014784,3276014815,FR +3276014816,3276014823,GB +3276014824,3276014887,FR 3276014888,3276014895,IE 3276014896,3276014943,FR 3276014944,3276014951,GB -3276014952,3276015103,FR +3276014952,3276015031,FR +3276015032,3276015039,GB +3276015040,3276015103,FR 3276015104,3276015119,GB 3276015120,3276015199,FR 3276015200,3276015231,GB @@ -99493,8 +101861,8 @@ 3276018240,3276018271,GB 3276018272,3276018375,FR 3276018376,3276018383,GB -3276018384,3276018431,FR -3276018432,3276018447,GB +3276018384,3276018423,FR +3276018424,3276018447,GB 3276018448,3276018495,FR 3276018496,3276018527,GB 3276018528,3276018543,FR @@ -99507,9 +101875,7 @@ 3276019024,3276019071,GB 3276019072,3276019135,FR 3276019136,3276019151,GB -3276019152,3276019463,FR -3276019464,3276019471,GB -3276019472,3276019479,FR +3276019152,3276019479,FR 3276019480,3276019487,GB 3276019488,3276019503,FR 3276019504,3276019511,GB @@ -99549,11 +101915,17 @@ 3276020880,3276020887,GB 3276020888,3276020943,FR 3276020944,3276020991,GB -3276020992,3276021591,FR +3276020992,3276021103,FR +3276021104,3276021111,GB +3276021112,3276021591,FR 3276021592,3276021599,GB 3276021600,3276021815,FR 3276021816,3276021823,GB -3276021824,3276022127,FR +3276021824,3276021847,FR +3276021848,3276021855,GB +3276021856,3276022031,FR +3276022032,3276022039,GB +3276022040,3276022127,FR 3276022128,3276022143,GB 3276022144,3276022215,FR 3276022216,3276022223,GB @@ -99611,9 +101983,7 @@ 3276025248,3276025279,GB 3276025280,3276025295,FR 3276025296,3276025327,GB -3276025328,3276026143,FR -3276026144,3276026159,GB -3276026160,3276026167,FR +3276025328,3276026167,FR 3276026168,3276026175,GB 3276026176,3276026191,FR 3276026192,3276026199,GB @@ -99785,7 +102155,9 @@ 3276036384,3276036415,GB 3276036416,3276036591,FR 3276036592,3276036607,GB -3276036608,3276037127,FR +3276036608,3276036639,FR +3276036640,3276036863,GB +3276036864,3276037127,FR 3276037128,3276037135,GB 3276037136,3276037199,FR 3276037200,3276037215,GB @@ -99827,9 +102199,7 @@ 3276040064,3276040095,GB 3276040096,3276040159,FR 3276040160,3276040175,GB -3276040176,3276040191,FR -3276040192,3276040215,GB -3276040216,3276040231,FR +3276040176,3276040231,FR 3276040232,3276040239,GB 3276040240,3276040319,FR 3276040320,3276040327,GB @@ -99847,8 +102217,8 @@ 3276040640,3276040671,GB 3276040672,3276040879,FR 3276040880,3276040895,GB -3276040896,3276040991,FR -3276040992,3276041007,GB +3276040896,3276040975,FR +3276040976,3276041007,GB 3276041008,3276041071,FR 3276041072,3276041087,GB 3276041088,3276041199,FR @@ -99909,9 +102279,7 @@ 3276044992,3276044999,GB 3276045000,3276045023,FR 3276045024,3276045039,GB -3276045040,3276045063,FR -3276045064,3276045071,GB -3276045072,3276045111,FR +3276045040,3276045111,FR 3276045112,3276045151,GB 3276045152,3276045191,FR 3276045192,3276045199,GB @@ -99968,6 +102336,8 @@ 3276074496,3276075007,GB 3276075008,3276075519,RU 3276075520,3276076031,DE +3276076032,3276076287,NL +3276076288,3276076543,RU 3276076544,3276077055,DE 3276077056,3276077567,UA 3276077568,3276078079,FR @@ -100007,7 +102377,6 @@ 3276127232,3276128255,UZ 3276128256,3276129279,AT 3276129280,3276131327,UA -3276131328,3276132351,DK 3276132352,3276133375,PL 3276133376,3276134399,GB 3276134400,3276135423,RU @@ -100015,6 +102384,7 @@ 3276136448,3276137471,NL 3276137472,3276138495,PL 3276138496,3276139519,NL +3276139520,3276140543,RU 3276140544,3276141567,DE 3276141568,3276143615,UA 3276143616,3276144639,GB @@ -100026,11 +102396,7 @@ 3276185600,3276193791,NO 3276193792,3276201983,RU 3276201984,3276210175,AT -3276210176,3276233791,DE -3276233792,3276233799,RO -3276233800,3276233807,DE -3276233808,3276233823,RO -3276233824,3276234303,DE +3276210176,3276234303,DE 3276234304,3276234367,GB 3276234368,3276241759,DE 3276241760,3276241767,FR @@ -100045,7 +102411,9 @@ 3276250096,3276275711,DE 3276275712,3276283903,SK 3276283904,3276292095,GB -3276292096,3276300287,BE +3276292096,3276294655,BE +3276294656,3276294663,LU +3276294664,3276300287,BE 3276300288,3276304383,DE 3276304384,3276304639,BG 3276304640,3276305407,GB @@ -102146,7 +104514,8 @@ 3276474368,3276474623,EU 3276474624,3276474879,GB 3276474880,3276475015,EU -3276475016,3276475039,IT +3276475016,3276475023,IT +3276475024,3276475039,FR 3276475040,3276475055,EU 3276475056,3276475071,IT 3276475072,3276475903,EU @@ -102451,7 +104820,9 @@ 3276528448,3276528503,BE 3276528504,3276528511,EU 3276528512,3276528519,BE -3276528520,3276528559,EU +3276528520,3276528527,EU +3276528528,3276528543,BE +3276528544,3276528559,EU 3276528560,3276528567,BE 3276528568,3276528575,EU 3276528576,3276528719,BE @@ -102531,8 +104902,8 @@ 3276535344,3276535351,EU 3276535352,3276535359,FI 3276535360,3276535375,EU -3276535376,3276535423,FI -3276535424,3276535551,EU +3276535376,3276535455,FI +3276535456,3276535551,EU 3276535552,3276535807,PK 3276535808,3276536063,FI 3276536064,3276536319,EU @@ -103033,7 +105404,9 @@ 3276872480,3276872511,GB 3276872512,3276872703,DE 3276872704,3276873727,GB -3276873728,3276874559,ES +3276873728,3276874367,ES +3276874368,3276874495,GB +3276874496,3276874559,ES 3276874560,3276874751,GB 3276874752,3276875007,NL 3276875008,3276875263,CH @@ -103062,9 +105435,11 @@ 3276881152,3276881279,GB 3276881280,3276881407,DE 3276881408,3276881919,FR -3276881920,3276883967,IT -3276883968,3276884487,PL -3276884488,3276884735,GB +3276881920,3276883327,IT +3276883328,3276883391,GB +3276883392,3276883967,IT +3276883968,3276884495,PL +3276884496,3276884735,GB 3276884736,3276884991,PL 3276884992,3276886015,GB 3276886016,3276886271,RO @@ -103076,8 +105451,8 @@ 3276887056,3276887071,GB 3276887072,3276888063,DE 3276888064,3276888575,GB -3276888576,3276888831,IT -3276888832,3276890111,GB +3276888576,3276889087,IT +3276889088,3276890111,GB 3276890112,3276890135,US 3276890136,3276890143,GB 3276890144,3276890207,US @@ -103097,13 +105472,17 @@ 3276896896,3276896927,BE 3276896928,3276897023,GB 3276897024,3276897663,BE -3276897664,3276898047,GB -3276898048,3276898303,CZ -3276898304,3276898655,CH +3276897664,3276897919,GB +3276897920,3276898303,CZ +3276898304,3276898399,CH +3276898400,3276898407,GB +3276898408,3276898655,CH 3276898656,3276898671,GB 3276898672,3276898775,CH 3276898776,3276898783,GB -3276898784,3276900039,CH +3276898784,3276899071,CH +3276899072,3276899087,GB +3276899088,3276900039,CH 3276900040,3276900047,GB 3276900048,3276900351,CH 3276900352,3276900607,GB @@ -103115,11 +105494,11 @@ 3276901624,3276901631,GB 3276901632,3276902151,CH 3276902152,3276902159,GB -3276902160,3276902199,CH -3276902200,3276902207,GB -3276902208,3276902335,CH +3276902160,3276902335,CH 3276902336,3276902399,GB -3276902400,3276902583,SE +3276902400,3276902559,SE +3276902560,3276902575,GB +3276902576,3276902583,SE 3276902584,3276902615,GB 3276902616,3276902639,SE 3276902640,3276902655,GB @@ -103127,7 +105506,11 @@ 3276903320,3276903327,GB 3276903328,3276903359,NO 3276903360,3276903935,SE -3276903936,3276904191,GB +3276903936,3276903999,GB +3276904000,3276904079,SE +3276904080,3276904095,GB +3276904096,3276904127,SE +3276904128,3276904191,GB 3276904192,3276904447,SE 3276904448,3276905311,GB 3276905312,3276905319,ES @@ -103145,7 +105528,9 @@ 3276906624,3276906751,GB 3276906752,3276906823,NL 3276906824,3276906831,CH -3276906832,3276907551,NL +3276906832,3276907339,NL +3276907340,3276907343,GB +3276907344,3276907551,NL 3276907552,3276907567,BE 3276907568,3276907643,NL 3276907644,3276907647,GB @@ -103164,7 +105549,9 @@ 3276912624,3276913183,IT 3276913184,3276913215,GB 3276913216,3276913359,IT -3276913360,3276913375,GB +3276913360,3276913360,GB +3276913361,3276913374,IT +3276913375,3276913375,GB 3276913376,3276913919,IT 3276913920,3276913983,US 3276913984,3276914079,IT @@ -103174,7 +105561,8 @@ 3276914160,3276914687,IT 3276914688,3276915567,ES 3276915568,3276915583,NL -3276915584,3276916087,ES +3276915584,3276915711,GB +3276915712,3276916087,ES 3276916088,3276916095,GB 3276916096,3276916175,ES 3276916176,3276916183,GB @@ -103266,6 +105654,7 @@ 3277187072,3277187327,GB 3277187328,3277187583,UA 3277187584,3277188351,RU +3277188352,3277188607,DE 3277188608,3277188863,RU 3277188864,3277189119,RO 3277189120,3277189375,DE @@ -103352,7 +105741,6 @@ 3277359616,3277360127,UA 3277360128,3277360639,BG 3277360640,3277361151,CZ -3277361152,3277361663,UA 3277361664,3277362175,RU 3277362176,3277362687,ES 3277362688,3277363199,IE @@ -103369,7 +105757,6 @@ 3277368320,3277369343,RO 3277369344,3277369855,CY 3277369856,3277370367,RU -3277370368,3277370879,SE 3277370880,3277371391,RO 3277371392,3277371903,RU 3277371904,3277372415,PL @@ -103541,6 +105928,7 @@ 3277822208,3277822463,ES 3277822464,3277822719,PL 3277822720,3277822975,RU +3277822976,3277823231,ES 3277823232,3277823487,UA 3277823488,3277823743,SI 3277823744,3277823999,UA @@ -103580,7 +105968,8 @@ 3277835776,3277836287,UA 3277836288,3277836799,FI 3277836800,3277837311,UA -3277837312,3277838847,RU +3277837312,3277839103,RU +3277839104,3277839359,CH 3277839360,3277839871,DE 3277839872,3277840383,UA 3277840384,3277840895,FR @@ -103599,21 +105988,23 @@ 3277856768,3277864959,DE 3277864960,3277873151,RU 3277873152,3277881343,NL -3277881344,3277884175,IT +3277881344,3277881375,A2 +3277881376,3277881407,IT +3277881408,3277884175,A2 3277884176,3277884191,IR -3277884192,3277885439,IT +3277884192,3277885439,A2 3277885440,3277885695,IQ 3277885696,3277885727,LB -3277885728,3277885951,IT +3277885728,3277885951,A2 3277885952,3277886463,LB 3277886464,3277886719,IQ 3277886720,3277886975,IR 3277886976,3277887487,IQ -3277887488,3277888255,IT +3277887488,3277888255,A2 3277888256,3277888319,LB -3277888320,3277889023,IT +3277888320,3277889023,A2 3277889024,3277889279,IQ -3277889280,3277889535,IT +3277889280,3277889535,A2 3277889536,3277897727,RU 3277897728,3277905919,IT 3277905920,3277914111,BG @@ -105449,7 +107840,7 @@ 3278943912,3278943913,IT 3278943914,3278943914,DE 3278943915,3278943915,PL -3278943916,3278943916,IT +3278943916,3278943916,DE 3278943917,3278943917,FR 3278943918,3278943918,ES 3278943919,3278943920,FR @@ -106171,6 +108562,7 @@ 3279053312,3279053823,DE 3279053824,3279054335,NL 3279054336,3279054847,GB +3279054848,3279055359,RU 3279055360,3279055871,SA 3279055872,3279056383,TR 3279056384,3279056895,GB @@ -106188,7 +108580,8 @@ 3279078656,3279078911,FR 3279078912,3279084543,ES 3279084544,3279085567,IT -3279085568,3279093759,NL +3279085568,3279093503,NL +3279093504,3279093759,DE 3279093760,3279103103,FR 3279103104,3279103135,GB 3279103136,3279119295,FR @@ -106602,7 +108995,9 @@ 3280390720,3280390751,FR 3280390752,3280392703,GB 3280392704,3280392831,FR -3280392832,3280396287,GB +3280392832,3280395263,GB +3280395264,3280395519,FR +3280395520,3280396287,GB 3280396288,3280404479,FI 3280404480,3280437247,IT 3280437248,3280453631,DE @@ -106614,8 +109009,10 @@ 3280458752,3280459775,RU 3280459776,3280460799,DK 3280460800,3280462847,DE +3280462848,3280463871,PL 3280463872,3280466943,RU 3280466944,3280467967,UA +3280467968,3280468991,ES 3280468992,3280470015,CY 3280470016,3280535551,PL 3280535552,3280568319,GB @@ -106663,6 +109060,7 @@ 3280589312,3280590335,DE 3280590336,3280590847,NL 3280590848,3280591359,DE +3280591360,3280591871,UA 3280591872,3280592383,GB 3280592384,3280592895,TR 3280592896,3280593407,DE @@ -107456,7 +109854,9 @@ 3280963312,3280963327,GB 3280963328,3280963343,DE 3280963344,3280963359,GB -3280963360,3280963495,DE +3280963360,3280963423,DE +3280963424,3280963487,GB +3280963488,3280963495,DE 3280963496,3280963511,GB 3280963512,3280963515,DE 3280963516,3280963519,GB @@ -107558,7 +109958,9 @@ 3280976720,3280976831,GB 3280976832,3280976847,DE 3280976848,3280976895,GB -3280976896,3280977119,DE +3280976896,3280977023,DE +3280977024,3280977031,GB +3280977032,3280977119,DE 3280977120,3280977135,GB 3280977136,3280977407,DE 3280977408,3280977439,GB @@ -108233,6 +110635,7 @@ 3281339392,3281339647,PL 3281339648,3281339903,GB 3281339904,3281340159,UA +3281340160,3281340415,BG 3281340416,3281340927,RO 3281340928,3281341183,DE 3281341184,3281341439,AT @@ -108246,7 +110649,7 @@ 3281344000,3281344255,FR 3281344256,3281344511,RU 3281344512,3281344767,UA -3281344768,3281345023,RU +3281344768,3281345279,RU 3281345280,3281345535,SA 3281345536,3281345791,CH 3281345792,3281346047,RU @@ -109341,6 +111744,7 @@ 3284047104,3284047359,DK 3284047360,3284047615,DE 3284047616,3284047871,NL +3284047872,3284048127,UA 3284048128,3284048383,DK 3284048384,3284048639,GB 3284048640,3284049151,FR @@ -109480,7 +111884,6 @@ 3284598784,3284664319,HU 3284664320,3284672511,GB 3284672512,3284680703,DE -3284680704,3284681215,UA 3284681216,3284681727,RO 3284681728,3284682239,FI 3284682240,3284682751,DE @@ -109489,8 +111892,7 @@ 3284683776,3284684287,GB 3284684288,3284684799,FR 3284684800,3284685311,DE -3284685312,3284685823,NL -3284685824,3284686335,US +3284685312,3284686335,NL 3284686336,3284686847,RO 3284686848,3284687359,PL 3284687360,3284687871,UA @@ -109781,8 +112183,8 @@ 3285462952,3285462959,AT 3285462960,3285463007,EU 3285463008,3285463039,AT -3285463040,3285463079,LU -3285463080,3285463103,EU +3285463040,3285463087,LU +3285463088,3285463103,EU 3285463104,3285463135,LU 3285463136,3285463295,EU 3285463296,3285463311,FR @@ -109881,8 +112283,7 @@ 3285472512,3285473327,EU 3285473328,3285473343,DE 3285473344,3285473439,EU -3285473440,3285473567,DE -3285473568,3285473583,EU +3285473440,3285473583,DE 3285473584,3285473591,GB 3285473592,3285473599,DE 3285473600,3285473631,EU @@ -109929,9 +112330,7 @@ 3285476896,3285477023,EU 3285477024,3285477087,AT 3285477088,3285477151,EU -3285477152,3285477319,IT -3285477320,3285477327,EU -3285477328,3285477343,IT +3285477152,3285477343,IT 3285477344,3285477359,EU 3285477360,3285477375,IT 3285477376,3285477631,FR @@ -110831,7 +113230,8 @@ 3285571904,3285571967,SE 3285571968,3285572095,BE 3285572096,3285572223,DE -3285572224,3285572351,FI +3285572224,3285572335,BE +3285572336,3285572351,ES 3285572352,3285572367,IR 3285572368,3285572383,ES 3285572384,3285572447,BE @@ -110986,8 +113386,7 @@ 3285860352,3285868543,FI 3285868544,3285876735,IE 3285876736,3285909503,RU -3285909504,3285910015,GB -3285910016,3285910271,EU +3285909504,3285910271,GB 3285910272,3285910303,ES 3285910304,3285910335,GB 3285910336,3285910399,ES @@ -110999,9 +113398,7 @@ 3285911552,3285912575,EU 3285912576,3285913087,GB 3285913088,3285913215,ES -3285913216,3285913231,GB -3285913232,3285913247,EU -3285913248,3285913279,GB +3285913216,3285913279,GB 3285913280,3285913343,ES 3285913344,3285913599,GB 3285913600,3285915647,EU @@ -111013,8 +113410,8 @@ 3285916704,3285916711,DE 3285916712,3285916719,CY 3285916720,3285916735,ES -3285916736,3285916799,GB -3285916800,3285916927,EU +3285916736,3285916831,GB +3285916832,3285916927,EU 3285916928,3285917183,GB 3285917184,3285917439,ES 3285917440,3285917695,YE @@ -111046,12 +113443,11 @@ 3285926408,3285926415,ES 3285926416,3285926431,GB 3285926432,3285926463,CH -3285926464,3285926511,GB -3285926512,3285926623,EU +3285926464,3285926527,GB +3285926528,3285926623,EU 3285926624,3285926631,US 3285926632,3285926639,EU -3285926640,3285926671,GB -3285926672,3285926687,EU +3285926640,3285926687,GB 3285926688,3285926719,IN 3285926720,3285926783,EU 3285926784,3285926815,GB @@ -111060,19 +113456,19 @@ 3285926912,3285927423,DE 3285927424,3285927679,GB 3285927680,3285927935,IR -3285927936,3285928063,EU +3285927936,3285927951,GB +3285927952,3285928063,EU 3285928064,3285928191,ES 3285928192,3285928207,PL 3285928208,3285928223,GB 3285928224,3285928255,DE 3285928256,3285928271,GB 3285928272,3285928287,DE -3285928288,3285928319,GB -3285928320,3285928447,EU +3285928288,3285928335,GB +3285928336,3285928447,EU 3285928448,3285928959,ES 3285928960,3285929983,EU -3285929984,3285930511,GB -3285930512,3285930559,EU +3285929984,3285930559,GB 3285930560,3285930575,ES 3285930576,3285930623,GB 3285930624,3285930631,BE @@ -111081,9 +113477,7 @@ 3285930656,3285930671,NL 3285930672,3285930679,BE 3285930680,3285930687,DE -3285930688,3285930719,GB -3285930720,3285930751,EU -3285930752,3285931007,GB +3285930688,3285931007,GB 3285931008,3285932031,EU 3285932032,3285932287,NL 3285932288,3285932799,GB @@ -111096,7 +113490,8 @@ 3285934848,3285935615,GB 3285935616,3285938175,EU 3285938176,3285938431,ES -3285938432,3285938559,EU +3285938432,3285938447,GB +3285938448,3285938559,EU 3285938560,3285938607,GB 3285938608,3285938623,FR 3285938624,3285938631,NG @@ -111108,7 +113503,9 @@ 3285938952,3285938959,NL 3285938960,3285938975,US 3285938976,3285939071,ES -3285939072,3285939199,EU +3285939072,3285939087,EU +3285939088,3285939103,FR +3285939104,3285939199,EU 3285939200,3285939711,ES 3285939712,3285940223,EU 3285940224,3285940479,ES @@ -111121,14 +113518,16 @@ 3285943552,3285943567,GB 3285943568,3285943575,ES 3285943576,3285943583,DE -3285943584,3285943631,GB -3285943632,3285943679,EU +3285943584,3285943647,GB +3285943648,3285943679,NG 3285943680,3285943807,GB 3285943808,3285944319,EU 3285944320,3285944831,US 3285944832,3285945343,DK 3285945344,3285945599,ES -3285945600,3285945663,EU +3285945600,3285945615,EU +3285945616,3285945631,GB +3285945632,3285945663,EU 3285945664,3285945695,FR 3285945696,3285945743,GB 3285945744,3285945855,EU @@ -111147,18 +113546,18 @@ 3285949696,3285949823,ES 3285949824,3285949855,EU 3285949856,3285949887,ES -3285949888,3285949903,GB -3285949904,3285949951,EU +3285949888,3285949919,GB +3285949920,3285949951,EU 3285949952,3285950463,ES 3285950464,3285950719,GB 3285950720,3285950783,US -3285950784,3285950799,GB -3285950800,3285950959,EU -3285950960,3285950975,GB +3285950784,3285950815,GB +3285950816,3285950943,EU +3285950944,3285950975,GB 3285950976,3285951231,NL 3285951232,3285951487,IT -3285951488,3285951503,GB -3285951504,3285951615,EU +3285951488,3285951519,GB +3285951520,3285951615,EU 3285951616,3285951647,GB 3285951648,3285951679,ES 3285951680,3285951695,GB @@ -111177,8 +113576,8 @@ 3285957632,3285957887,PL 3285957888,3285958143,GB 3285958144,3285958655,EU -3285958656,3285958671,GB -3285958672,3285958783,EU +3285958656,3285958687,GB +3285958688,3285958783,EU 3285958784,3285958799,GB 3285958800,3285958847,EU 3285958848,3285958895,NL @@ -111202,8 +113601,8 @@ 3285968384,3285968639,ES 3285968640,3285968895,PL 3285968896,3285971007,EU -3285971008,3285971023,GB -3285971024,3285971183,EU +3285971008,3285971039,GB +3285971040,3285971183,EU 3285971184,3285971199,GB 3285971200,3285971455,FR 3285971456,3285971711,DE @@ -111246,9 +113645,7 @@ 3286264880,3286264895,NL 3286264896,3286279423,GB 3286279424,3286279679,US -3286279680,3286289919,GB -3286289920,3286290175,US -3286290176,3286291807,GB +3286279680,3286291807,GB 3286291808,3286291823,US 3286291824,3286302719,GB 3286302720,3286310911,NO @@ -111315,7 +113712,9 @@ 3286367232,3286368255,BG 3286368256,3286376447,CH 3286376448,3286384639,GB -3286384640,3286401023,DE +3286384640,3286397607,DE +3286397608,3286397615,A2 +3286397616,3286401023,DE 3286401024,3286409215,GB 3286409216,3286417407,DE 3286417408,3286417663,UA @@ -111449,74 +113848,7 @@ 3286790912,3286791679,GB 3286791680,3286791935,AT 3286791936,3286794239,GB -3286794240,3286795263,DE -3286795264,3286795519,LR -3286795520,3286795775,DE -3286795776,3286796031,LR -3286796032,3286796287,DE -3286796288,3286796543,LR -3286796544,3286796799,DE -3286796800,3286797055,RO -3286797056,3286797311,DE -3286797312,3286797567,HU -3286797568,3286798847,DE -3286798848,3286799359,IT -3286799360,3286801407,DE -3286801408,3286801663,NL -3286801664,3286802943,DE -3286802944,3286803199,AU -3286803200,3286805503,DE -3286805504,3286806527,GB -3286806528,3286808063,DE -3286808064,3286808575,GR -3286808576,3286809087,EG -3286809088,3286809599,DE -3286809600,3286809855,GB -3286809856,3286810111,PT -3286810112,3286812927,DE -3286812928,3286813183,PT -3286813184,3286813695,EG -3286813696,3286813951,DE -3286813952,3286814207,AU -3286814208,3286814719,HU -3286814720,3286819839,DE -3286819840,3286820863,NZ -3286820864,3286826751,DE -3286826752,3286827007,IT -3286827008,3286827263,DE -3286827264,3286827519,GB -3286827520,3286832127,DE -3286832128,3286832895,GB -3286832896,3286835711,DE -3286835712,3286836223,ES -3286836224,3286836479,IT -3286836480,3286836735,DE -3286836736,3286836991,IT -3286836992,3286837247,DE -3286837248,3286839295,GB -3286839296,3286839807,DE -3286839808,3286840319,ES -3286840320,3286841087,DE -3286841088,3286841343,IT -3286841344,3286842623,DE -3286842624,3286843391,IT -3286843392,3286844415,IE -3286844416,3286844671,IT -3286844672,3286847487,DE -3286847488,3286848511,GB -3286848512,3286849535,DE -3286849536,3286849791,IT -3286849792,3286851583,DE -3286851584,3286852607,IE -3286852608,3286855679,DE -3286855680,3286857727,IE -3286857728,3286864895,DE -3286864896,3286865151,IT -3286865152,3286872063,DE -3286872064,3286879231,IE -3286879232,3286882303,DE -3286882304,3286883327,IE -3286883328,3286888447,DE +3286794240,3286888447,DE 3286888448,3286889471,IE 3286889472,3286892543,DE 3286892544,3286893055,LI @@ -111558,7 +113890,6 @@ 3286907392,3286907647,AT 3286907648,3286907903,ES 3286907904,3286908159,CH -3286908160,3286908415,UA 3286908416,3286908671,FR 3286908672,3286908927,PL 3286908928,3286909951,CH @@ -111745,7 +114076,8 @@ 3287443968,3287444479,BG 3287444480,3287444991,PL 3287444992,3287445503,DE -3287445504,3287446527,UA +3287445504,3287446015,GB +3287446016,3287446527,UA 3287446528,3287447039,PL 3287447040,3287447551,IL 3287447552,3287448063,DK @@ -111820,9 +114152,7 @@ 3287515376,3287515383,CZ 3287515384,3287523303,DE 3287523304,3287523311,US -3287523312,3287526303,DE -3287526304,3287526311,LU -3287526312,3287534807,DE +3287523312,3287534807,DE 3287534808,3287534815,IT 3287534816,3287541087,DE 3287541088,3287541095,CZ @@ -111860,7 +114190,7 @@ 3287632384,3287632895,SE 3287632896,3287633407,RU 3287633408,3287633919,SK -3287633920,3287634431,UA +3287633920,3287634431,GB 3287634432,3287634943,RO 3287634944,3287635455,PL 3287635456,3287635967,DE @@ -111872,7 +114202,6 @@ 3287638528,3287639039,DE 3287639040,3287639551,GB 3287639552,3287640063,RU -3287640064,3287640575,DE 3287640576,3287641087,SI 3287641088,3287641599,A2 3287641600,3287642111,FI @@ -112195,7 +114524,6 @@ 3288444928,3288449023,NG 3288449024,3288465407,SD 3288465408,3288465919,JM -3288465920,3288466175,BW 3288466176,3288466431,MU 3288466432,3288467455,SY 3288467456,3288469503,BI @@ -112374,7 +114702,7 @@ 3290497024,3290955775,ZA 3290955776,3290980351,CR 3290980352,3290984447,ZA -3291000832,3291004927,KE +3290988544,3290992639,KE 3291004928,3291021311,NG 3291021312,3291029503,ZA 3291029504,3291033343,TZ @@ -112413,6 +114741,9 @@ 3291208960,3291209215,TZ 3291209216,3291209471,KE 3291209472,3291209727,AO +3291209728,3291209983,NG +3291209984,3291210239,GH +3291216896,3291217919,MU 3291217920,3291230207,ZA 3291230208,3291234303,GH 3291234304,3291242495,ZA @@ -112437,7 +114768,9 @@ 3291326464,3291330559,ZA 3291330560,3291331583,TZ 3291331584,3291332607,MW -3291332608,3291348991,NG +3291332608,3291332615,ZA +3291332616,3291332863,NG +3291332864,3291348991,ZA 3291348992,3291353087,MZ 3291353088,3291353343,KE 3291353344,3291353599,EG @@ -112594,7 +114927,7 @@ 3302805504,3302809599,MW 3302813696,3302817791,NG 3302817792,3302883327,EG -3302883328,3302948863,MA +3302883328,3302948863,RW 3302948864,3302949119,MU 3302949120,3302949375,AO 3302949376,3302949631,ZM @@ -112617,6 +114950,7 @@ 3302955008,3302955263,LS 3302955264,3302955519,UG 3302955520,3302955775,ZW +3302955776,3302956031,MW 3305111552,3307208703,TN 3307208704,3309305855,EG 3309305856,3312451583,ZA @@ -112628,8 +114962,11 @@ 3314286592,3314548735,DZ 3315335168,3315351551,ZA 3315351552,3315367935,ET +3315367936,3315384319,KE 3315564544,3315568639,GH +3315572736,3315580927,ST 3315580928,3315589119,CI +3315589120,3315597311,CM 3315597312,3316121599,EG 3316121600,3316645887,ZA 3316645888,3317170175,KE @@ -112657,10 +114994,13 @@ 3320709120,3320840191,ZA 3321102336,3321167871,NG 3321167872,3321233407,ZA +3321233408,3321298943,EG +3321298944,3321364479,MA 3321364480,3321430015,KE 3321430016,3321495551,MZ 3321495552,3321561087,TZ 3321561088,3321593855,SD +3321593856,3321626623,GH 3321626624,3321692159,SD 3321692160,3321708543,NG 3321708544,3321724927,GH @@ -112766,7 +115106,11 @@ 3323662336,3323674623,US 3323723776,3324011007,US 3324011008,3324011263,KN -3324011264,3324036351,US +3324011264,3324030463,US +3324030464,3324030719,KN +3324030720,3324035583,US +3324035584,3324035839,KN +3324035840,3324036351,US 3324036352,3324047615,KN 3324047616,3324051455,US 3324051456,3324182527,CA @@ -113035,7 +115379,9 @@ 3328235520,3328241663,CA 3328241664,3328243199,US 3328243200,3328245759,CA -3328245760,3328414719,US +3328245760,3328394239,US +3328394240,3328394495,GB +3328394496,3328414719,US 3328414720,3328414975,CH 3328414976,3328420351,US 3328420352,3328420607,CA @@ -113379,7 +115725,7 @@ 3338916352,3338916479,CN 3338916480,3339075583,US 3339075584,3339076863,GB -3339076864,3339077631,NO +3339076864,3339077631,JP 3339077632,3339077887,SG 3339077888,3339079167,US 3339079168,3339079423,DK @@ -113401,8 +115747,9 @@ 3339146496,3339147007,US 3339147008,3339147775,CA 3339147776,3339148031,MS -3339148032,3339149311,US -3339157504,3339159551,US +3339148032,3339153407,US +3339153408,3339155455,BB +3339155456,3339159551,US 3339159552,3339160575,CA 3339160576,3339164671,US 3339164672,3339165695,CA @@ -113418,10 +115765,15 @@ 3339184128,3339184639,CA 3339184640,3339184895,US 3339184896,3339186175,CA -3339186176,3339669503,US +3339186176,3339327999,US +3339328512,3339329535,CA +3339329536,3339669503,US 3339669504,3339671807,CA -3339672576,3339673599,US -3339681792,3339747327,US +3339672576,3339728895,US +3339728896,3339729919,AG +3339729920,3339743231,US +3339743232,3339744255,CA +3339744256,3339747327,US 3339747328,3339747583,CA 3339747584,3339747839,FR 3339747840,3339748351,CA @@ -113437,14 +115789,19 @@ 3339778480,3339778495,CY 3339778496,3339923455,US 3339923456,3339927551,CA -3339943936,3339952127,US +3339927552,3339934719,US +3339934720,3339935743,CA +3339935744,3339952127,US 3339952128,3339956223,CA 3339956224,3339965439,US 3339965440,3339969311,CA 3339969312,3339969327,AU 3339969328,3339969375,CA -3339969376,3340058623,US -3340075008,3340080127,US +3339969376,3340071007,US +3340071008,3340071055,GB +3340071056,3340071063,US +3340071064,3340071071,ES +3340071072,3340080127,US 3340080128,3340081151,CA 3340081152,3340084223,US 3340084224,3340085247,KN @@ -113457,16 +115814,20 @@ 3340369920,3340386559,US 3340387328,3340388351,CA 3340388352,3340390399,US -3340394496,3340429823,US +3340390400,3340391423,CA +3340391424,3340429823,US 3340429824,3340430079,PA -3340430080,3340451839,US -3340468224,3340481535,US +3340430080,3340460031,US +3340460032,3340462079,PR +3340462080,3340466175,US +3340466176,3340467199,A2 +3340467200,3340481535,US 3340481536,3340482559,CA 3340482560,3340490751,US 3340490752,3340492799,CA 3340492800,3340584703,US 3340584704,3340584959,KW -3340584960,3340648447,US +3340584960,3340664831,US 3340664832,3340665855,CA 3340665856,3340677119,US 3340677120,3340679167,CA @@ -113563,8 +115924,7 @@ 3340926928,3340926935,ES 3340926936,3340926951,US 3340926952,3340926959,BR -3340926960,3341041663,US -3341058048,3341082623,US +3340926960,3341082623,US 3341082624,3341084671,CA 3341084672,3341444863,US 3341444864,3341445631,DE @@ -113771,7 +116131,11 @@ 3345008640,3345010687,US 3345010688,3345011711,CA 3345011712,3345301503,US -3345317888,3345327103,US +3345317888,3345318943,US +3345318944,3345318975,HK +3345318976,3345321471,US +3345321472,3345321727,CA +3345321728,3345327103,US 3345327104,3345328127,CA 3345328128,3345333247,US 3345333248,3345334271,MF @@ -113781,7 +116145,11 @@ 3345383424,3345384447,CA 3345384448,3345390591,US 3345390592,3345391615,CA -3345391616,3345398783,US +3345391616,3345393151,US +3345393152,3345393279,AU +3345393280,3345393407,US +3345393408,3345393535,AU +3345393536,3345398783,US 3345398784,3345399807,BS 3345399808,3345401855,PR 3345401856,3345403903,CA @@ -113834,7 +116202,9 @@ 3345408698,3345408701,GB 3345408702,3345408784,US 3345408785,3345408788,CA -3345408789,3345408903,US +3345408789,3345408888,US +3345408889,3345408892,MX +3345408893,3345408903,US 3345408904,3345408907,GB 3345408908,3345408949,US 3345408950,3345408993,IN @@ -113859,11 +116229,17 @@ 3345409559,3345409562,CA 3345409563,3345409576,US 3345409577,3345409580,GB -3345409581,3345409722,US +3345409581,3345409706,US +3345409707,3345409718,IN +3345409719,3345409722,US 3345409723,3345409727,GB 3345409728,3345409782,US 3345409783,3345409786,SG -3345409787,3345409895,US +3345409787,3345409816,US +3345409817,3345409820,GB +3345409821,3345409887,US +3345409888,3345409891,GB +3345409892,3345409895,US 3345409896,3345409899,PR 3345409900,3345409903,CA 3345409904,3345409911,US @@ -113873,7 +116249,9 @@ 3345409946,3345409949,SG 3345409950,3345409957,US 3345409958,3345409961,CA -3345409962,3345418239,US +3345409962,3345410032,US +3345410033,3345410036,GB +3345410037,3345418239,US 3345418240,3345419519,NL 3345419520,3345422847,US 3345423360,3345424383,TC @@ -113930,7 +116308,8 @@ 3346499584,3346501631,VI 3346501632,3346506039,US 3346506040,3346506055,CA -3346506056,3346506119,US +3346506056,3346506111,US +3346506112,3346506119,JM 3346506120,3346506127,MX 3346506128,3346510271,US 3346510272,3346510335,IL @@ -113940,7 +116319,9 @@ 3346522348,3346522350,BD 3346522351,3346522401,US 3346522402,3346522404,IN -3346522405,3346522691,US +3346522405,3346522411,US +3346522412,3346522413,AE +3346522414,3346522691,US 3346522692,3346522704,PT 3346522705,3346522773,US 3346522774,3346522783,PT @@ -113982,18 +116363,32 @@ 3349608448,3349609215,US 3349609216,3349610495,CA 3349610496,3349614591,US -3349643264,3349644287,CA -3349644288,3349645311,US +3349643264,3349643487,CA +3349643488,3349643503,US +3349643504,3349644287,CA +3349644288,3349644656,US +3349644657,3349644672,GB +3349644673,3349645215,US +3349645216,3349645231,ID +3349645232,3349645311,US 3349645312,3349647359,CA 3349647360,3349649407,US 3349649408,3349653503,CA 3349653504,3349692415,US -3349708800,3349723996,US +3349708800,3349723260,US +3349723261,3349723265,CA +3349723266,3349723360,US +3349723361,3349723367,CA +3349723368,3349723996,US 3349723997,3349724000,LK -3349724001,3349731327,US +3349724001,3349724985,US +3349724986,3349724999,PK +3349725000,3349731327,US 3349731328,3349733375,CA 3349733376,3349739519,US -3349739520,3349740543,CA +3349739520,3349739551,CA +3349739552,3349739559,US +3349739560,3349740543,CA 3349740544,3349987327,US 3349987328,3349996543,BM 3349996544,3349997055,KY @@ -114011,15 +116406,25 @@ 3350470656,3350475775,US 3350475776,3350476799,CA 3350476800,3350478847,US -3350495232,3350495602,US +3350495232,3350495577,US +3350495578,3350495585,GB +3350495586,3350495602,US 3350495603,3350495604,BD -3350495605,3350495873,US +3350495605,3350495645,US +3350495646,3350495652,RO +3350495653,3350495873,US 3350495874,3350495874,IN 3350495875,3350495881,US 3350495882,3350495882,IN -3350495883,3350496532,US +3350495883,3350496305,US +3350496306,3350496317,PT +3350496318,3350496447,US +3350496448,3350496455,PT +3350496456,3350496532,US 3350496533,3350496533,IN -3350496534,3350496721,US +3350496534,3350496659,US +3350496660,3350496675,BR +3350496676,3350496721,US 3350496722,3350496723,IN 3350496724,3350593535,US 3350593536,3350609919,CA @@ -114044,7 +116449,8 @@ 3351035904,3351036927,US 3351036928,3351037951,CA 3351037952,3351043071,US -3351043072,3351044095,CA +3351043072,3351043079,FR +3351043080,3351044095,CA 3351044096,3351068671,US 3351085056,3351086079,US 3351086080,3351087103,CA @@ -114063,9 +116469,16 @@ 3351303168,3351304191,CA 3351304192,3351306239,US 3351306240,3351307263,VC -3351307264,3351308287,US +3351307264,3351307519,US +3351307520,3351307775,CA +3351307776,3351308287,US 3351308288,3351310335,CA -3351310336,3351380223,US +3351310336,3351330815,US +3351347200,3351357439,US +3351357440,3351359487,CA +3351359488,3351372799,US +3351372800,3351373823,BM +3351373824,3351380223,US 3351380224,3351380479,CA 3351380480,3351380735,US 3351380736,3351381759,CA @@ -114171,7 +116584,9 @@ 3351441152,3351441407,CA 3351441408,3351441919,US 3351441920,3351442175,CA -3351442176,3351478271,US +3351442176,3351483391,US +3351483392,3351484415,CA +3351484416,3351485439,US 3351511040,3351524095,US 3351524096,3351524351,GB 3351524352,3351642111,US @@ -114179,7 +116594,9 @@ 3351698432,3351904255,US 3351912448,3351927551,CA 3351927552,3351927807,US -3351927808,3351969791,CA +3351927808,3351959551,CA +3351959552,3351961599,US +3351961600,3351969791,CA 3351969792,3352035327,IL 3352035328,3352036351,CA 3352036352,3352046591,US @@ -114209,7 +116626,37 @@ 3353722624,3353729023,US 3353729024,3353729279,HK 3353729280,3353730047,US -3353739264,3353979647,US +3353739264,3353752581,US +3353752582,3353752585,FR +3353752586,3353752589,BE +3353752590,3353752606,US +3353752607,3353752610,AU +3353752611,3353752630,US +3353752631,3353752634,CA +3353752635,3353752650,US +3353752651,3353752654,AU +3353752655,3353752677,US +3353752678,3353752681,ES +3353752682,3353752716,US +3353752717,3353752720,IT +3353752721,3353752740,US +3353752741,3353752744,CA +3353752745,3353752748,US +3353752749,3353752752,CA +3353752753,3353752769,US +3353752770,3353752773,AU +3353752774,3353752811,US +3353752812,3353752815,CA +3353752816,3353752828,US +3353752829,3353752830,FR +3353752831,3353752936,US +3353752937,3353752940,SE +3353752941,3353752987,US +3353752988,3353752991,GB +3353752992,3353753055,US +3353753056,3353753059,BR +3353753060,3353753067,GB +3353753068,3353979647,US 3353979648,3353979903,CA 3353979904,3353982719,US 3353982720,3353983231,CA @@ -114239,7 +116686,7 @@ 3355260928,3355262719,CA 3355262720,3355310591,US 3355310592,3355311103,CA -3355312128,3355319295,US +3355311104,3355319295,US 3355319296,3355320319,CA 3355320320,3355324415,US 3355324416,3355328511,CA @@ -114709,8 +117156,8 @@ 3356341808,3356341863,SV 3356341864,3356341871,HN 3356341872,3356343295,SV -3356343296,3356343423,HN -3356343424,3356344319,SV +3356343296,3356343551,HN +3356343552,3356344319,SV 3356344320,3356360703,CO 3356360704,3356362751,CL 3356362752,3356364799,VE @@ -114728,7 +117175,7 @@ 3356380928,3356381183,DO 3356381184,3356381439,CL 3356381440,3356381695,PA -3356381696,3356381951,UY +3356381696,3356381951,CL 3356381952,3356382207,EC 3356382208,3356389375,CL 3356389376,3356389887,CO @@ -114902,8 +117349,8 @@ 3358064640,3358130175,UY 3358130176,3358131199,EC 3358131200,3358131391,CO -3358131392,3358131415,GT -3358131416,3358131983,CO +3358131392,3358131407,GT +3358131408,3358131983,CO 3358131984,3358131991,GT 3358131992,3358132223,CO 3358132224,3358132479,AR @@ -114925,7 +117372,9 @@ 3358150656,3358151167,EC 3358151168,3358151423,PY 3358151424,3358151679,CO -3358151680,3358152703,GT +3358151680,3358151935,GT +3358151936,3358152063,PE +3358152064,3358152703,GT 3358152704,3358152735,AR 3358152736,3358152767,VE 3358152768,3358152831,US @@ -115021,8 +117470,7 @@ 3358723328,3358723583,AN 3358723584,3358724095,PR 3358724096,3358725119,DO -3358725120,3358725375,AN -3358725376,3358728191,PR +3358725120,3358728191,PR 3358728192,3358736383,CL 3358736384,3358737111,BB 3358737112,3358737119,CA @@ -115150,7 +117598,9 @@ 3359475520,3359475551,AR 3359475552,3359475615,CO 3359475616,3359475623,AR -3359475624,3359478687,CO +3359475624,3359477247,CO +3359477248,3359477759,AR +3359477760,3359478687,CO 3359478688,3359478719,AR 3359478720,3359479295,CO 3359479296,3359479303,AR @@ -115182,6 +117632,8 @@ 3359501312,3359502335,SR 3359502336,3359505407,AR 3359505408,3359505663,VE +3359505664,3359505919,AN +3359505920,3359506431,AR 3359506432,3359508479,US 3359508480,3359514623,VE 3359514624,3359516671,GT @@ -115247,7 +117699,9 @@ 3360231680,3360234751,CL 3360234752,3360235263,CO 3360235264,3360235271,CL -3360235272,3360235519,CO +3360235272,3360235487,CO +3360235488,3360235495,CL +3360235496,3360235519,CO 3360235520,3360236287,CL 3360236288,3360236303,CO 3360236304,3360236311,CL @@ -115345,7 +117799,9 @@ 3360763904,3360765951,GT 3360765952,3360767999,CO 3360768000,3360770047,PY -3360770048,3360771327,EC +3360770048,3360771071,EC +3360771072,3360771199,AR +3360771200,3360771327,EC 3360771328,3360771839,AR 3360771840,3360772095,EC 3360772096,3360772351,AR @@ -115413,7 +117869,9 @@ 3362328576,3362330623,CO 3362330624,3362332671,MX 3362332672,3362336767,PA -3362336768,3362338815,CO +3362336768,3362337279,CO +3362337280,3362337535,US +3362337536,3362338815,CO 3362338816,3362339839,AR 3362339840,3362341887,CO 3362341888,3362342143,GT @@ -115438,6 +117896,10 @@ 3362430976,3362447359,CO 3362447360,3362451455,SV 3362451456,3362452479,AR +3362452480,3362452991,BO +3362452992,3362453247,HN +3362453248,3362453503,NI +3362453504,3362455551,AR 3362455552,3362471935,EC 3362471936,3362476031,CL 3362476032,3362476287,HN @@ -115545,12 +118007,13 @@ 3363504128,3363512319,PE 3363512320,3363553791,AR 3363553792,3363554047,PE -3363554048,3363557375,AR +3363554048,3363554175,US +3363554176,3363557375,AR 3363561472,3363565567,CO 3363569664,3363577855,PA 3363577856,3363586047,CL 3363586048,3363594239,BZ -3363594240,3363598335,AR +3363594240,3363602431,AR 3363602432,3363610623,AN 3363610624,3363614719,CO 3363618816,3363622911,UY @@ -115562,8 +118025,9 @@ 3363678208,3363680255,NI 3363680256,3363682303,GT 3363682304,3363684351,VE -3363684352,3363700735,EC -3363700736,3363708927,CU +3363684352,3363700991,EC +3363700992,3363701247,CU +3363701248,3363708927,EC 3363708928,3363713023,CL 3363717120,3363733503,CL 3363733504,3363831807,AR @@ -115575,7 +118039,9 @@ 3384410112,3384672255,CL 3384672256,3384688639,HN 3384688640,3384705023,CO -3384705024,3384737791,PA +3384705024,3384721407,PA +3384721408,3384725503,US +3384725504,3384737791,PA 3384737792,3385851903,CR 3385851904,3386114047,VE 3386114048,3386245119,AR @@ -116114,9 +118580,7 @@ 3390414336,3390414847,SG 3390414848,3390418943,JP 3390418944,3390423039,MV -3390423040,3390429439,SG -3390429440,3390429951,HK -3390429952,3390439423,SG +3390423040,3390439423,SG 3390439424,3390441471,NZ 3390441472,3390443519,TH 3390443520,3390447359,NZ @@ -116250,7 +118714,8 @@ 3391879168,3391881215,ID 3391881216,3391895551,TH 3391895552,3391896575,IN -3391896576,3391900415,TH +3391896576,3391897599,NZ +3391897600,3391900415,TH 3391900416,3391901695,AU 3391901696,3391905791,PK 3391905792,3391906047,TH @@ -116409,7 +118874,6 @@ 3392440832,3392441343,BD 3392441344,3392441855,ID 3392441856,3392442111,AU -3392442112,3392442367,IN 3392442368,3392442623,HK 3392442624,3392442879,AU 3392442880,3392443391,ID @@ -117789,19 +120253,7 @@ 3399515648,3399524351,AU 3399524352,3399528447,IN 3399528448,3399532543,CN -3399532544,3399544575,SG -3399544576,3399544831,IN -3399544832,3399546879,SG -3399546880,3399547135,US -3399547136,3399547903,SG -3399547904,3399547911,PK -3399547912,3399547935,SG -3399547936,3399547951,PK -3399547952,3399547967,SG -3399547968,3399547999,PK -3399548000,3399548415,SG -3399548416,3399548671,ID -3399548672,3399548927,SG +3399532544,3399548927,SG 3399548928,3399557119,AU 3399557120,3399565311,SG 3399565312,3399581695,AU @@ -118118,8 +120570,8 @@ 3400438112,3400438143,HK 3400438144,3400438175,BD 3400438176,3400438399,HK -3400438400,3400438591,BD -3400438592,3400438783,HK +3400438400,3400438527,BD +3400438528,3400438783,AF 3400438784,3400438815,KZ 3400438816,3400438831,PK 3400438832,3400438839,AF @@ -118552,7 +121004,7 @@ 3407326464,3407328767,AU 3407328768,3407329023,CN 3407329024,3407329791,AU -3407330048,3407330303,CN +3407329792,3407330303,CN 3407330304,3407360511,AU 3407360512,3407361023,ID 3407361024,3407362047,AU @@ -118745,9 +121197,7 @@ 3409491712,3409491967,SG 3409491968,3409498111,AU 3409498112,3409498879,CN -3409498880,3409503999,AU -3409504000,3409504255,HK -3409504256,3409505023,AU +3409498880,3409505023,AU 3409505024,3409505279,US 3409505280,3409506559,AU 3409506560,3409506815,IN @@ -118769,9 +121219,7 @@ 3409567232,3409567487,CN 3409567488,3409574143,AU 3409574144,3409574399,CN -3409574400,3409802831,AU -3409802832,3409802847,MT -3409802848,3409838335,AU +3409574400,3409838335,AU 3409838336,3409838591,MY 3409838592,3409838847,CN 3409838848,3409876991,AU @@ -119065,6 +121513,7 @@ 3411644928,3411645951,ID 3411645952,3411646207,SG 3411646208,3411647487,IN +3411647488,3411648511,AU 3411648512,3411656703,NZ 3411656704,3411673087,AU 3411673088,3411674111,CN @@ -119423,9 +121872,7 @@ 3413852160,3413868543,AU 3413868544,3413884927,IN 3413884928,3413893119,KR -3413893120,3413899199,ID -3413899200,3413899203,IN -3413899204,3413901311,ID +3413893120,3413901311,ID 3413901312,3413902847,SG 3413902848,3413903359,JP 3413903360,3413905407,HK @@ -120348,10 +122795,7 @@ 3418513408,3418517503,IN 3418517504,3418519551,MN 3418519552,3418521599,CN -3418521600,3418524574,HK -3418524575,3418524606,CN -3418524607,3418524638,TH -3418524639,3418554367,HK +3418521600,3418554367,HK 3418554368,3418570751,VN 3418570752,3418578943,CN 3418578944,3418583039,TH @@ -120466,7 +122910,9 @@ 3419456912,3419456927,JP 3419456928,3419459007,SG 3419459008,3419459071,AF -3419459072,3419471871,SG +3419459072,3419459407,SG +3419459408,3419459423,GB +3419459424,3419471871,SG 3419471872,3419504639,TH 3419504640,3419508735,HK 3419508736,3419512831,JP @@ -120550,7 +122996,7 @@ 3420033024,3420034047,IN 3420034048,3420036095,AU 3420036096,3420037119,JP -3420037120,3420039167,AU +3420037120,3420038143,AU 3420039168,3420040191,KH 3420040192,3420040703,ID 3420040704,3420040959,IN @@ -120674,8 +123120,8 @@ 3420368896,3420368935,HK 3420368936,3420368943,TW 3420368944,3420368991,HK -3420368992,3420369023,AU -3420369024,3420369055,HK +3420368992,3420369007,AU +3420369008,3420369055,HK 3420369056,3420369087,AU 3420369088,3420369139,HK 3420369140,3420369223,CN @@ -121280,9 +123726,7 @@ 3425830816,3425830831,US 3425830832,3425850519,CA 3425850520,3425850527,US -3425850528,3425855231,CA -3425855232,3425855487,US -3425855488,3425864711,CA +3425850528,3425864711,CA 3425864712,3425864719,US 3425864720,3425869167,CA 3425869168,3425869183,US @@ -121301,9 +123745,13 @@ 3425916480,3425916543,DK 3425916544,3426013183,US 3426013184,3426013439,IL -3426013440,3426387967,US +3426013440,3426369023,US +3426369024,3426369535,CA +3426369536,3426387967,US 3426387968,3426388991,MX -3426388992,3426617855,US +3426388992,3426400255,US +3426400256,3426400511,CA +3426400512,3426617855,US 3426618368,3426618687,US 3426618688,3426618703,NZ 3426618704,3426618735,US @@ -121329,9 +123777,11 @@ 3427127552,3427127807,US 3427128064,3427618303,US 3427618304,3427618559,CA -3427618560,3427647743,US +3427618560,3427647999,US 3427648000,3427648511,CA -3427648512,3427729407,US +3427648512,3427651071,US +3427651072,3427651327,CA +3427651328,3427729407,US 3427729408,3427729663,CA 3427729664,3427730431,US 3427730432,3427730687,BE @@ -121486,11 +123936,19 @@ 3428286720,3428286975,CA 3428286976,3428296959,US 3428296960,3428297215,CL -3428297472,3428299519,US +3428297216,3428299519,US 3428299520,3428299775,ZA -3428299776,3428306175,US +3428299776,3428302079,US +3428302080,3428302335,CA +3428302336,3428306175,US 3428306176,3428306431,MX -3428306432,3428437503,US +3428306432,3428318975,US +3428318976,3428319231,CA +3428319232,3428399359,US +3428399360,3428399615,CA +3428400128,3428433919,US +3428433920,3428434175,CA +3428434176,3428437503,US 3428437504,3428437759,MX 3428437760,3428496639,US 3428496640,3428497151,NL @@ -121859,7 +124317,8 @@ 3431752704,3431753215,US 3431753216,3431753471,SG 3431753472,3431755007,CA -3431755008,3431759615,NL +3431755008,3431755775,NL +3431755776,3431759615,CA 3431759616,3431759871,DE 3431759872,3431783431,US 3431783432,3431783435,NL @@ -121943,7 +124402,9 @@ 3434133760,3434133791,IL 3434133792,3434134015,US 3434134016,3434134079,CA -3434134080,3434423295,US +3434134080,3434299391,US +3434299392,3434303487,VE +3434303488,3434423295,US 3434423296,3434423303,CA 3434423304,3434427391,US 3434427392,3434428415,HR @@ -121960,7 +124421,27 @@ 3434584064,3434807551,US 3434807552,3434810111,CA 3434810112,3434810367,US -3434810368,3434831359,CA +3434810368,3434810879,CA +3434810880,3434810895,GB +3434810896,3434810911,US +3434810912,3434810943,CA +3434810944,3434810959,US +3434810960,3434810975,AE +3434810976,3434811007,CA +3434811008,3434811023,US +3434811024,3434811039,ZA +3434811040,3434811071,US +3434811072,3434811135,CA +3434811136,3434811151,US +3434811152,3434811167,CA +3434811168,3434811199,US +3434811200,3434811215,AU +3434811216,3434811311,US +3434811312,3434811327,GB +3434811328,3434811359,US +3434811360,3434811375,CA +3434811376,3434811383,US +3434811384,3434831359,CA 3434831360,3434831615,US 3434831616,3434872575,CA 3434872576,3434907647,US @@ -122346,7 +124827,9 @@ 3438552272,3438552287,US 3438552288,3438559647,CA 3438559648,3438559679,US -3438559680,3438570031,CA +3438559680,3438569215,CA +3438569216,3438569343,US +3438569344,3438570031,CA 3438570032,3438570039,MY 3438570040,3438570495,CA 3438570496,3438570527,US @@ -122522,7 +125005,10 @@ 3448569056,3448569087,MX 3448569088,3448569735,US 3448569736,3448569743,GB -3448569744,3449001245,US +3448569744,3448983807,US +3448983808,3448983871,GB +3448983872,3448985599,US +3448987648,3449001245,US 3449001246,3449001246,MC 3449001247,3449159679,US 3449159680,3449160703,CA @@ -122721,7 +125207,12 @@ 3450272768,3450345231,US 3450345232,3450345247,FR 3450345248,3450345263,IT -3450345264,3450345439,US +3450345264,3450345279,US +3450345280,3450345311,NE +3450345312,3450345343,GE +3450345344,3450345391,US +3450345392,3450345399,BG +3450345400,3450345439,US 3450345440,3450345471,GE 3450345472,3450731519,US 3450731520,3450732543,CA @@ -122746,7 +125237,11 @@ 3451236608,3451371519,US 3451371520,3451371775,GB 3451371776,3451482111,US -3451482112,3451486207,CA +3451482112,3451482439,CA +3451482440,3451482447,AR +3451482448,3451483423,CA +3451483424,3451483431,US +3451483432,3451486207,CA 3451486208,3451506687,US 3451506688,3451507711,BR 3451507712,3451715583,US @@ -122985,8 +125480,8 @@ 3453375144,3453375167,US 3453375168,3453375191,SA 3453375192,3453375215,US -3453375216,3453375239,GB -3453375240,3453375255,US +3453375216,3453375231,GB +3453375232,3453375255,US 3453375256,3453375263,IN 3453375264,3453375279,GB 3453375280,3453375319,TK @@ -123109,8 +125604,12 @@ 3453554880,3453555711,US 3453555712,3453555767,GB 3453555768,3453583615,US -3453583616,3453583679,SG -3453583680,3453599999,US +3453583616,3453583695,SG +3453583696,3453595527,US +3453595528,3453595551,CA +3453595552,3453595583,US +3453595584,3453595623,CA +3453595624,3453599999,US 3453600000,3453600767,GB 3453600768,3453601863,US 3453601864,3453601871,GB @@ -123133,7 +125632,9 @@ 3453615104,3453615359,AG 3453615360,3453615615,KN 3453615616,3453616127,AG -3453616128,3454003013,US +3453616128,3453681943,US +3453681944,3453681951,IN +3453681952,3454003013,US 3454003014,3454003014,ES 3454003015,3454004997,US 3454004998,3454004998,GB @@ -123173,9 +125674,24 @@ 3454703256,3454703263,CA 3454703264,3454703647,US 3454703648,3454703663,CA -3454703664,3454705151,US +3454703664,3454703951,US +3454703952,3454703959,AF +3454703960,3454704007,US +3454704008,3454704015,ID +3454704016,3454704047,US +3454704048,3454704055,CA +3454704056,3454704063,US +3454704064,3454704079,CA +3454704080,3454704087,AE +3454704088,3454704103,US +3454704104,3454704111,GB +3454704112,3454705151,US 3454705152,3454705215,GB -3454705216,3454708927,US +3454705216,3454705439,US +3454705440,3454705447,GB +3454705448,3454705511,US +3454705512,3454705519,CA +3454705520,3454708927,US 3454708928,3454708991,IN 3454708992,3454710551,US 3454710552,3454710559,SO @@ -123342,7 +125858,9 @@ 3455647488,3455647743,IT 3455647744,3455713279,US 3455713280,3455778815,CA -3455778816,3455871999,US +3455778816,3455797375,US +3455797376,3455797407,FR +3455797408,3455871999,US 3455872000,3455872255,ZM 3455872256,3456303103,US 3456303104,3456311295,JP @@ -124292,7 +126810,8 @@ 3464341504,3464341759,US 3464341760,3464341775,JP 3464341776,3464341783,AU -3464341784,3464341807,US +3464341784,3464341799,US +3464341800,3464341807,CA 3464341808,3464341815,JP 3464341816,3464341823,US 3464341824,3464341831,PT @@ -124302,7 +126821,9 @@ 3464341896,3464341903,GB 3464341904,3464341927,US 3464341928,3464341935,CV -3464341936,3464342543,US +3464341936,3464341983,US +3464341984,3464341991,PR +3464341992,3464342543,US 3464342544,3464342559,SE 3464342560,3464342567,US 3464342568,3464342575,PT @@ -124322,43 +126843,16 @@ 3464384512,3464388607,CA 3464388608,3464394751,US 3464394752,3464396799,VC -3464396800,3464548367,US -3464548368,3464548375,AG -3464548376,3464548391,US -3464548392,3464548399,AG -3464548400,3464548415,US -3464548416,3464548431,AG -3464548432,3464548479,US -3464548480,3464548599,AG -3464548600,3464548607,US +3464396800,3464548351,US +3464548352,3464548607,AG 3464548608,3464548863,LC 3464548864,3464549119,KN 3464549120,3464549375,VG -3464549376,3464549391,US -3464549392,3464549399,AG -3464549400,3464549415,US -3464549416,3464549439,AG +3464549376,3464549439,AG 3464549440,3464549503,MS -3464549504,3464549519,AG -3464549520,3464549551,US -3464549552,3464549567,AG -3464549568,3464549639,US -3464549640,3464549679,AG -3464549680,3464549687,US -3464549688,3464549727,AG +3464549504,3464549727,AG 3464549728,3464549759,KN -3464549760,3464549855,AG -3464549856,3464549863,US -3464549864,3464549871,AG -3464549872,3464549919,US -3464549920,3464549927,AG -3464549928,3464549935,US -3464549936,3464549943,AG -3464549944,3464549951,US -3464549952,3464550015,AG -3464550016,3464550047,US -3464550048,3464550127,AG -3464550128,3464550143,US +3464549760,3464550143,AG 3464550144,3464550399,LC 3464550400,3464626175,US 3464626432,3464626687,CA @@ -124409,7 +126903,9 @@ 3465468880,3465468911,SG 3465468912,3465468935,US 3465468936,3465468943,SG -3465468944,3465510911,US +3465468944,3465469183,US +3465469184,3465469215,GB +3465469216,3465510911,US 3465510912,3465543679,JP 3465543680,3465953503,US 3465953504,3465953535,CA @@ -124447,7 +126943,9 @@ 3466286104,3466286111,DE 3466286112,3466290687,US 3466290688,3466290943,CH -3466290944,3466313727,US +3466290944,3466294271,US +3466294272,3466294319,CA +3466294320,3466313727,US 3466313728,3466317823,CA 3466317824,3466489855,US 3466489856,3466490111,CA @@ -125397,9 +127895,19 @@ 3470360688,3470360695,AF 3470360696,3470360799,US 3470360800,3470360807,CA -3470360808,3470361039,US +3470360808,3470360895,US +3470360896,3470360911,CA +3470360912,3470360927,US +3470360928,3470360935,CA +3470360936,3470361039,US 3470361040,3470361055,CA -3470361056,3470361487,US +3470361056,3470361231,US +3470361232,3470361247,IN +3470361248,3470361295,US +3470361296,3470361311,IN +3470361312,3470361471,US +3470361472,3470361479,JP +3470361480,3470361487,US 3470361488,3470361495,SG 3470361496,3470361663,US 3470361664,3470361671,CA @@ -125424,9 +127932,7 @@ 3470362320,3470362335,AF 3470362336,3470362455,US 3470362456,3470362471,CA -3470362472,3470362487,US -3470362488,3470362495,ES -3470362496,3470362543,US +3470362472,3470362543,US 3470362544,3470362559,SE 3470362560,3470362623,CA 3470362624,3470362731,US @@ -125444,7 +127950,11 @@ 3470363544,3470363555,AF 3470363556,3470363559,US 3470363560,3470363567,CA -3470363568,3470363903,US +3470363568,3470363615,US +3470363616,3470363631,ES +3470363632,3470363671,US +3470363672,3470363679,SE +3470363680,3470363903,US 3470363904,3470363919,CA 3470363920,3470363967,US 3470363968,3470363983,CA @@ -125488,7 +127998,9 @@ 3470645744,3470645747,ES 3470645748,3470645751,US 3470645752,3470645759,BR -3470645760,3470646015,US +3470645760,3470645791,US +3470645792,3470645799,CN +3470645800,3470646015,US 3470646016,3470646019,BR 3470646020,3470646035,US 3470646036,3470646039,VI @@ -125899,7 +128411,9 @@ 3476722240,3476722255,SA 3476722256,3476722287,US 3476722288,3476722319,IT -3476722320,3476722527,US +3476722320,3476722495,US +3476722496,3476722511,AU +3476722512,3476722527,US 3476722528,3476722543,AU 3476722544,3476722591,US 3476722592,3476722607,GB @@ -125969,7 +128483,9 @@ 3478261904,3478261935,SG 3478261936,3478262271,US 3478262272,3478262279,SG -3478262280,3478294527,US +3478262280,3478262655,US +3478262656,3478262671,SG +3478262672,3478294527,US 3478294528,3478294543,GB 3478294544,3478323391,US 3478323392,3478323399,CA @@ -126058,7 +128574,9 @@ 3479294224,3479294231,TH 3479294232,3479294419,US 3479294420,3479294423,CA -3479294424,3479294487,US +3479294424,3479294425,US +3479294426,3479294427,CA +3479294428,3479294487,US 3479294488,3479294495,MX 3479294496,3479294527,US 3479294528,3479294543,BD @@ -126068,9 +128586,7 @@ 3479294664,3479294671,AU 3479294672,3479294775,US 3479294776,3479294783,CA -3479294784,3479294911,US -3479294912,3479294919,CA -3479294920,3479295015,US +3479294784,3479295015,US 3479295016,3479295023,MY 3479295024,3479295071,US 3479295072,3479295079,CR @@ -126351,9 +128867,7 @@ 3480907264,3480907775,FR 3480907776,3480968191,US 3480968192,3480968447,AU -3480968448,3481169151,US -3481169152,3481169407,NZ -3481169408,3481182503,US +3480968448,3481182503,US 3481182504,3481182511,CA 3481182512,3481665535,US 3481665536,3481731071,CA @@ -126572,7 +129086,9 @@ 3484777696,3484778495,CA 3484778496,3484884991,US 3484884992,3484893183,CA -3484893184,3485220863,US +3484893184,3484937103,US +3484937104,3484937111,SE +3484937112,3485220863,US 3485220864,3485229055,CA 3485229056,3485290463,US 3485290464,3485290479,GB @@ -126860,7 +129376,9 @@ 3486700440,3486700447,IT 3486700448,3486701311,US 3486701312,3486701567,CA -3486701568,3486711551,US +3486701568,3486707559,US +3486707560,3486707567,HN +3486707568,3486711551,US 3486711552,3486711807,CA 3486711808,3487039487,US 3487039488,3487105023,CA @@ -126884,9 +129402,13 @@ 3487507376,3487507391,CA 3487507392,3487559711,US 3487559712,3487559743,AU -3487559744,3487559855,US -3487559856,3487559871,AU -3487559872,3487766527,US +3487559744,3487559839,US +3487559840,3487559871,AU +3487559872,3487560167,US +3487560168,3487560175,AU +3487560176,3487561471,US +3487561472,3487561727,AU +3487561728,3487766527,US 3487766528,3487768575,CA 3487768576,3487842303,US 3487842304,3487858687,CA @@ -127126,11 +129648,7 @@ 3493081600,3493082623,PY 3493082624,3493089023,US 3493089024,3493089279,A2 -3493089280,3493137151,US -3493137152,3493137215,DE -3493137216,3493137247,US -3493137248,3493137407,DE -3493137408,3493138207,US +3493089280,3493138207,US 3493138208,3493138239,DE 3493138240,3493140223,US 3493140224,3493140479,DE @@ -127157,7 +129675,9 @@ 3493901760,3493901767,AE 3493901768,3493901791,US 3493901792,3493901823,AE -3493901824,3493901951,US +3493901824,3493901847,US +3493901848,3493901851,CA +3493901852,3493901951,US 3493901952,3493901983,CA 3493901984,3493902215,US 3493902216,3493902223,CA @@ -127247,9 +129767,7 @@ 3494122496,3494135807,US 3494135808,3494136831,CA 3494136832,3494139903,US -3494139904,3494141735,CA -3494141736,3494141743,US -3494141744,3494141951,CA +3494139904,3494141951,CA 3494141952,3494143999,US 3494144000,3494145023,CA 3494145024,3494159039,US @@ -127442,8 +129960,7 @@ 3494438144,3494438399,DM 3494438400,3494438655,KN 3494438656,3494438911,DM -3494438912,3494439935,CA -3494439936,3494449287,US +3494438912,3494449287,US 3494449288,3494449311,CA 3494449312,3494449439,US 3494449440,3494449663,CA @@ -127556,8 +130073,8 @@ 3494701056,3494705319,US 3494705320,3494705327,MX 3494705328,3494712319,US -3494712320,3494713343,CA -3494713344,3494727679,US +3494712320,3494712575,CA +3494712576,3494727679,US 3494727680,3494729727,CA 3494729728,3494730751,US 3494730752,3494731775,CA @@ -127573,9 +130090,7 @@ 3494745304,3494745311,AU 3494745312,3494745879,US 3494745880,3494745887,GB -3494745888,3494745919,US -3494745920,3494745927,CN -3494745928,3494745951,US +3494745888,3494745951,US 3494745952,3494745959,GB 3494745960,3494746019,US 3494746020,3494746023,AU @@ -127621,11 +130136,19 @@ 3494852608,3494854655,CA 3494854656,3494861087,US 3494861088,3494861095,CA -3494861096,3494861615,US +3494861096,3494861575,US +3494861576,3494861583,CH +3494861584,3494861615,US 3494861616,3494861623,AU 3494861624,3494861839,US 3494861840,3494861855,AU -3494861856,3494862639,US +3494861856,3494861935,US +3494861936,3494861943,AU +3494861944,3494861999,US +3494862000,3494862007,CA +3494862008,3494862255,US +3494862256,3494862263,CZ +3494862264,3494862639,US 3494862640,3494862647,JP 3494862648,3494862847,US 3494862848,3494863871,DM @@ -127709,21 +130232,24 @@ 3495153664,3495155711,CA 3495155712,3495157039,US 3495157040,3495157047,SE -3495157048,3495159807,US -3495159808,3495159815,ES -3495159816,3495159839,US +3495157048,3495159839,US 3495159840,3495159847,BR 3495159848,3495159871,US 3495159872,3495159879,AE -3495159880,3495159895,US +3495159880,3495159887,BD +3495159888,3495159895,GB 3495159896,3495159903,IN -3495159904,3495160111,US +3495159904,3495159927,US +3495159928,3495159935,IN +3495159936,3495160071,US +3495160072,3495160079,HK +3495160080,3495160111,US 3495160112,3495160119,NZ 3495160120,3495160303,US 3495160304,3495160319,TR -3495160320,3495160367,US -3495160368,3495160383,ZA -3495160384,3495160447,US +3495160320,3495160359,US +3495160360,3495160367,GB +3495160368,3495160447,US 3495160448,3495160455,BR 3495160456,3495160463,US 3495160464,3495160479,TR @@ -127758,9 +130284,7 @@ 3495235904,3495235911,CA 3495235912,3495235975,US 3495235976,3495235983,VN -3495235984,3495235999,US -3495236000,3495236007,HK -3495236008,3495236015,US +3495235984,3495236015,US 3495236016,3495236031,GB 3495236032,3495236247,US 3495236248,3495236255,AZ @@ -127993,7 +130517,9 @@ 3495749736,3495749745,US 3495749746,3495749785,CA 3495749786,3495749829,GB -3495749830,3495749908,CA +3495749830,3495749846,CA +3495749847,3495749856,US +3495749857,3495749908,CA 3495749909,3495749933,GB 3495749934,3495749959,CA 3495749960,3495749990,GB @@ -128493,7 +131019,11 @@ 3500809992,3500809999,CA 3500810000,3500810247,US 3500810248,3500810255,CA -3500810256,3500812175,US +3500810256,3500811567,US +3500811568,3500811583,AU +3500811584,3500811591,US +3500811592,3500811631,AU +3500811632,3500812175,US 3500812176,3500812183,GB 3500812184,3500921279,US 3500921280,3500921311,AU @@ -128590,10 +131120,7 @@ 3503250432,3503250943,PK 3503250944,3503323135,US 3503323136,3503323647,KE -3503323648,3503323903,A2 -3503323904,3503372031,US -3503372032,3503372287,A2 -3503372288,3503386111,US +3503323648,3503386111,US 3503386112,3503386367,CH 3503386368,3503413871,US 3503413872,3503413887,PR @@ -128674,9 +131201,7 @@ 3506135264,3506135295,GB 3506135296,3506161975,US 3506161976,3506161983,AF -3506161984,3506177967,US -3506177968,3506177983,DE -3506177984,3506192639,US +3506161984,3506192639,US 3506192640,3506192895,A2 3506192896,3506194535,US 3506194536,3506194543,AU @@ -129476,7 +132001,9 @@ 3509777450,3509777545,ID 3509777546,3509777584,US 3509777585,3509777648,ID -3509777649,3509778399,US +3509777649,3509778239,US +3509778240,3509778271,IN +3509778272,3509778399,US 3509778400,3509778431,NL 3509778432,3509778703,US 3509778704,3509778711,CA @@ -129556,15 +132083,17 @@ 3510242560,3510245375,CA 3510245376,3510245631,BD 3510245632,3510246735,CA -3510246736,3510246767,US -3510246768,3510249471,CA +3510246736,3510246775,US +3510246776,3510249471,CA 3510249472,3510249983,QA 3510249984,3510251519,CA 3510251520,3510252799,DO 3510252800,3510253311,CA 3510253312,3510253567,NC 3510253568,3510253631,US -3510253632,3510255439,CA +3510253632,3510253759,CA +3510253760,3510253775,US +3510253776,3510255439,CA 3510255440,3510255447,US 3510255448,3510261503,CA 3510261504,3510261759,ZM @@ -130226,7 +132755,9 @@ 3512377232,3512377239,US 3512377240,3512378435,CA 3512378436,3512378436,US -3512378437,3512385535,CA +3512378437,3512378983,CA +3512378984,3512378991,US +3512378992,3512385535,CA 3512385536,3512397823,US 3512397824,3512399375,CA 3512399376,3512399383,US @@ -130750,10 +133281,11 @@ 3515688192,3515695103,CA 3515695104,3515711487,US 3515711488,3515731967,CA -3515731968,3515736063,US -3515744256,3515793351,US +3515731968,3515793351,US 3515793352,3515793359,MO -3515793360,3515867151,US +3515793360,3515860351,US +3515860352,3515860431,IN +3515860432,3515867151,US 3515867152,3515867167,AU 3515867168,3515867391,US 3515867392,3515867519,AU @@ -130784,7 +133316,9 @@ 3516139264,3516153855,US 3516153856,3516162047,CA 3516162048,3516170239,US -3516170240,3516203007,CA +3516170240,3516193943,CA +3516193944,3516193951,US +3516193952,3516203007,CA 3516203008,3516334079,US 3516334080,3516342271,CA 3516342272,3516351055,US @@ -130899,9 +133433,7 @@ 3517396144,3517396175,US 3517396176,3517396911,CA 3517396912,3517396927,US -3517396928,3517396943,CA -3517396944,3517396959,US -3517396960,3517397503,CA +3517396928,3517397503,CA 3517397504,3517397759,US 3517397760,3517398015,CA 3517398016,3517398527,US @@ -131074,8 +133606,8 @@ 3517437000,3517437007,CA 3517437008,3517437015,US 3517437016,3517437039,CA -3517437040,3517437063,US -3517437064,3517437071,CA +3517437040,3517437055,US +3517437056,3517437071,CA 3517437072,3517437079,US 3517437080,3517437087,CA 3517437088,3517437095,NO @@ -131095,9 +133627,7 @@ 3517438880,3517438911,KW 3517438912,3517439487,CA 3517439488,3517439615,US -3517439616,3517440255,CA -3517440256,3517440511,US -3517440512,3517442239,CA +3517439616,3517442239,CA 3517442240,3517442303,US 3517442304,3517442319,CA 3517442320,3517442335,US @@ -131160,7 +133690,9 @@ 3517601280,3517602047,SE 3517602048,3517602303,DE 3517602304,3517602559,US -3517602560,3517602623,SE +3517602560,3517602575,SE +3517602576,3517602591,US +3517602592,3517602623,SE 3517602624,3517602815,US 3517602816,3517603071,SE 3517603072,3517603615,US @@ -131276,11 +133808,7 @@ 3518897120,3518897127,IT 3518897128,3518903191,US 3518903192,3518903199,JP -3518903200,3518903927,US -3518903928,3518903935,RU -3518903936,3518904015,US -3518904016,3518904031,EG -3518904032,3518905599,US +3518903200,3518905599,US 3518905600,3518905855,GB 3518905856,3518911743,US 3518911744,3518911999,GB @@ -131384,7 +133912,10 @@ 3519420768,3519420775,HK 3519420776,3519422495,US 3519422496,3519422527,CA -3519422528,3519475711,US +3519422528,3519466895,US +3519466896,3519466911,SZ +3519466912,3519467519,US +3519469568,3519475711,US 3519475712,3519476223,BH 3519476224,3519477759,A2 3519477760,3519578367,US @@ -131429,8 +133960,7 @@ 3519723520,3519724031,CA 3519724032,3519741951,US 3519741952,3519758335,ZA -3519758336,3519791103,US -3519799296,3519799871,US +3519758336,3519799871,US 3519799872,3519799903,IN 3519799904,3519805119,US 3519805120,3519805183,GB @@ -131722,7 +134252,9 @@ 3520086272,3520086527,CA 3520086528,3520086959,US 3520086960,3520086975,CA -3520086976,3520088447,US +3520086976,3520087327,US +3520087328,3520087359,DE +3520087360,3520088447,US 3520088448,3520088463,ES 3520088464,3520095455,US 3520095456,3520095471,NL @@ -131790,11 +134322,19 @@ 3520999424,3521003519,CA 3521003520,3521003583,US 3521003584,3521003647,IL -3521003648,3521005311,US +3521003648,3521004031,US +3521004032,3521004039,MY +3521004040,3521004063,US +3521004064,3521004071,RO +3521004072,3521004159,US +3521004160,3521004175,FR +3521004176,3521005311,US 3521005312,3521005319,MY 3521005320,3521005327,GB 3521005328,3521005335,DE -3521005336,3521011719,US +3521005336,3521009679,US +3521009680,3521009687,MY +3521009688,3521011719,US 3521011720,3521011727,BR 3521011728,3521011735,AU 3521011736,3521011743,US @@ -131943,8 +134483,8 @@ 3521934769,3521934776,MA 3521934777,3521935310,US 3521935311,3521935318,EG -3521935319,3521935717,US -3521935718,3521935725,IN +3521935319,3521935709,US +3521935710,3521935725,IN 3521935726,3521935993,US 3521935994,3521936025,EG 3521936026,3521936049,US @@ -131959,7 +134499,8 @@ 3521936670,3521936677,PK 3521936678,3521936739,US 3521936740,3521936747,ID -3521936748,3521936766,US +3521936748,3521936758,US +3521936759,3521936766,IN 3521936767,3521936774,PE 3521936775,3521936827,US 3521936828,3521936860,EG @@ -132299,9 +134840,7 @@ 3524781792,3524781823,SG 3524781824,3524788223,PH 3524788224,3524853759,SG -3524853760,3525300739,CN -3525300740,3525300743,US -3525300744,3526361087,CN +3524853760,3526361087,CN 3526361088,3526393855,NZ 3526393856,3526395903,JP 3526395904,3526397951,KH @@ -132445,9 +134984,7 @@ 3546808320,3547856895,KR 3547856896,3548905471,JP 3548905472,3551002623,CN -3551002624,3554544607,KR -3554544608,3554544639,DE -3554544640,3556769791,KR +3551002624,3556769791,KR 3556769792,3556774399,DE 3556774400,3556786175,EU 3556786176,3556794367,RU @@ -132471,6 +135008,9 @@ 3556868096,3556876287,GB 3556876288,3556884479,NL 3556884480,3556886527,IR +3556886528,3556888575,GB +3556888576,3556890623,US +3556890624,3556892671,GB 3556892672,3556900863,RU 3556900864,3556909055,GB 3556909056,3556925439,DE @@ -132554,25 +135094,28 @@ 3557138432,3557146623,RU 3557146624,3557154815,SK 3557154816,3557171199,RU -3557171200,3557172479,IT +3557171200,3557172479,A2 3557172480,3557172991,IR 3557172992,3557173503,IQ 3557173504,3557173631,IR 3557173632,3557173695,IQ 3557173696,3557173703,AE -3557173704,3557173759,IT +3557173704,3557173759,A2 3557173760,3557174015,IR -3557174016,3557174527,IT +3557174016,3557174527,A2 3557174528,3557174783,IR 3557174784,3557175039,AE 3557175040,3557176063,IR -3557176064,3557176575,IT +3557176064,3557176575,A2 3557176576,3557176619,NE -3557176620,3557176831,IT +3557176620,3557176831,A2 3557176832,3557177023,IQ -3557177024,3557177199,IT +3557177024,3557177199,A2 3557177200,3557177215,IR -3557177216,3557179391,IT +3557177216,3557177343,A2 +3557177344,3557177599,IT +3557177600,3557179135,A2 +3557179136,3557179391,IT 3557179392,3557213351,DE 3557213352,3557213359,US 3557213360,3557228543,DE @@ -132603,16 +135146,16 @@ 3557336192,3557336255,EU 3557336256,3557336319,BE 3557336320,3557336575,EU -3557336576,3557336671,BE -3557336672,3557336703,EU -3557336704,3557336831,BE +3557336576,3557336831,BE 3557336832,3557338111,EU 3557338112,3557338367,BE 3557338368,3557338495,EU -3557338496,3557339175,BE +3557338496,3557338615,BE +3557338616,3557338623,EU +3557338624,3557339175,BE 3557339176,3557339183,EU -3557339184,3557339199,BE -3557339200,3557339215,EU +3557339184,3557339191,BE +3557339192,3557339215,EU 3557339216,3557339223,BE 3557339224,3557339239,EU 3557339240,3557339247,BE @@ -132678,10 +135221,8 @@ 3557361376,3557361391,JE 3557361392,3557361415,GB 3557361416,3557361423,JE -3557361424,3557361455,GB -3557361456,3557361463,JE -3557361464,3557361599,GB -3557361600,3557361615,JE +3557361424,3557361607,GB +3557361608,3557361615,JE 3557361616,3557361663,GB 3557361664,3557361983,JE 3557361984,3557362047,GB @@ -132696,11 +135237,9 @@ 3557363672,3557363679,JE 3557363680,3557364103,GB 3557364104,3557364107,JE -3557364108,3557364147,GB -3557364148,3557364151,JE -3557364152,3557364167,GB -3557364168,3557364223,JE -3557364224,3557364479,GB +3557364108,3557364195,GB +3557364196,3557364199,JE +3557364200,3557364479,GB 3557364480,3557364495,JE 3557364496,3557364527,GB 3557364528,3557364559,JE @@ -132744,17 +135283,9 @@ 3557365912,3557365919,JE 3557365920,3557365935,GB 3557365936,3557366015,JE -3557366016,3557366023,GB -3557366024,3557366031,JE -3557366032,3557366055,GB +3557366016,3557366055,GB 3557366056,3557366063,JE -3557366064,3557366095,GB -3557366096,3557366103,JE -3557366104,3557366111,GB -3557366112,3557366119,JE -3557366120,3557366167,GB -3557366168,3557366175,JE -3557366176,3557366263,GB +3557366064,3557366263,GB 3557366264,3557366271,JE 3557366272,3557366279,GB 3557366280,3557366287,JE @@ -132841,7 +135372,18 @@ 3557860832,3557860847,FI 3557860848,3557860863,SE 3557860864,3557861119,NO -3557861120,3557863887,SE +3557861120,3557862015,SE +3557862016,3557862031,BE +3557862032,3557862399,SE +3557862400,3557862911,FI +3557862912,3557863351,SE +3557863352,3557863359,FI +3557863360,3557863391,SE +3557863392,3557863399,FI +3557863400,3557863487,SE +3557863488,3557863503,NO +3557863504,3557863519,DK +3557863520,3557863887,SE 3557863888,3557863903,NO 3557863904,3557863919,FI 3557863920,3557864287,SE @@ -133041,11 +135583,13 @@ 3558288640,3558288671,BE 3558288672,3558288687,DE 3558288688,3558288895,BE -3558288896,3558289111,FR -3558289112,3558289119,GB +3558288896,3558289103,FR +3558289104,3558289119,GB 3558289120,3558289151,FR 3558289152,3558289407,GB -3558289408,3558289663,NL +3558289408,3558289503,NL +3558289504,3558289535,GB +3558289536,3558289663,NL 3558289664,3558289747,IT 3558289748,3558289751,GB 3558289752,3558289775,IT @@ -133058,8 +135602,8 @@ 3558290592,3558290599,BE 3558290600,3558290615,GB 3558290616,3558290663,BE -3558290664,3558290671,GB -3558290672,3558290687,BE +3558290664,3558290679,GB +3558290680,3558290687,BE 3558290688,3558290871,ES 3558290872,3558290879,GB 3558290880,3558290911,ES @@ -133090,7 +135634,8 @@ 3558292608,3558292735,NL 3558292736,3558292863,GB 3558292864,3558292871,CH -3558292872,3558293119,NL +3558292872,3558292879,GB +3558292880,3558293119,NL 3558293120,3558293143,CH 3558293144,3558293151,GB 3558293152,3558293247,NL @@ -133435,7 +135980,9 @@ 3559088368,3559088371,GB 3559088372,3559088375,BE 3559088376,3559088379,GB -3559088380,3559089023,BE +3559088380,3559088631,BE +3559088632,3559088639,DE +3559088640,3559089023,BE 3559089024,3559089027,GB 3559089028,3559089079,BE 3559089080,3559089087,GB @@ -133447,8 +135994,8 @@ 3559089440,3559089443,GB 3559089444,3559089447,BE 3559089448,3559089451,GB -3559089452,3559089459,BE -3559089460,3559089467,GB +3559089452,3559089463,BE +3559089464,3559089467,GB 3559089468,3559089547,BE 3559089548,3559089551,GB 3559089552,3559089607,BE @@ -133513,11 +136060,17 @@ 3559091632,3559091639,LU 3559091640,3559091815,BE 3559091816,3559091823,GB -3559091824,3559092159,BE +3559091824,3559091887,BE +3559091888,3559091903,GB +3559091904,3559092159,BE 3559092160,3559092160,GB 3559092161,3559092222,BE 3559092223,3559092223,GB -3559092224,3559092735,BE +3559092224,3559092239,BE +3559092240,3559092247,GB +3559092248,3559092359,BE +3559092360,3559092367,GB +3559092368,3559092735,BE 3559092736,3559092739,GB 3559092740,3559092799,BE 3559092800,3559092803,GB @@ -133534,7 +136087,9 @@ 3559093000,3559093007,BE 3559093008,3559093015,GB 3559093016,3559093023,FR -3559093024,3559093047,BE +3559093024,3559093031,BE +3559093032,3559093039,GB +3559093040,3559093047,BE 3559093048,3559093055,GB 3559093056,3559093063,BE 3559093064,3559093071,FR @@ -133846,19 +136401,13 @@ 3559900424,3559900432,EE 3559900433,3559900439,UA 3559900440,3559900447,EE -3559900448,3559900471,UA -3559900472,3559900479,EE -3559900480,3559900483,UA +3559900448,3559900483,UA 3559900484,3559900487,EE 3559900488,3559900492,UA 3559900493,3559900493,EE -3559900494,3559900494,UA -3559900495,3559900495,EE -3559900496,3559900503,UA +3559900494,3559900503,UA 3559900504,3559900511,EE -3559900512,3559900519,UA -3559900520,3559900523,EE -3559900524,3559900611,UA +3559900512,3559900611,UA 3559900612,3559900624,EE 3559900625,3559900927,UA 3559900928,3559900951,EE @@ -133884,17 +136433,13 @@ 3559902240,3559902431,UA 3559902432,3559902463,EE 3559902464,3559902975,UA -3559902976,3559903487,EE -3559903488,3559903551,UA -3559903552,3559903631,EE +3559902976,3559903631,EE 3559903632,3559903679,UA 3559903680,3559904003,EE 3559904004,3559904015,UA 3559904016,3559904043,EE 3559904044,3559904127,UA -3559904128,3559904383,EE -3559904384,3559904511,UA -3559904512,3559904767,EE +3559904128,3559904767,EE 3559904768,3559904799,UA 3559904800,3559904815,EE 3559904816,3559905019,UA @@ -133926,9 +136471,15 @@ 3559905616,3559905631,UA 3559905632,3559905903,EE 3559905904,3559905911,UA -3559905912,3559906257,EE +3559905912,3559906239,EE +3559906240,3559906247,UA +3559906248,3559906257,EE 3559906258,3559906263,UA -3559906264,3559906975,EE +3559906264,3559906267,EE +3559906268,3559906271,UA +3559906272,3559906287,EE +3559906288,3559906303,UA +3559906304,3559906975,EE 3559906976,3559907071,UA 3559907072,3559907327,EE 3559907328,3559915519,FR @@ -133977,7 +136528,9 @@ 3560235008,3560243199,DE 3560243200,3560247295,BE 3560247296,3560251391,NL -3560251392,3560253439,RU +3560251392,3560252351,RU +3560252352,3560252367,CZ +3560252368,3560253439,RU 3560253440,3560253695,CZ 3560253696,3560259583,RU 3560259584,3560267775,GB @@ -134749,9 +137302,7 @@ 3560942952,3560942955,ES 3560942956,3560942959,DE 3560942960,3560942963,GB -3560942964,3560942975,DE -3560942976,3560942979,IT -3560942980,3560942983,DE +3560942964,3560942983,DE 3560942984,3560942987,BE 3560942988,3560942999,IT 3560943000,3560943003,PL @@ -135373,7 +137924,7 @@ 3560943861,3560943865,DE 3560943866,3560943866,BE 3560943867,3560943867,ES -3560943868,3560943868,FR +3560943868,3560943868,DE 3560943869,3560943869,LU 3560943870,3560943871,DE 3560943872,3560943875,BR @@ -136420,7 +138971,9 @@ 3561924720,3561924895,GB 3561924896,3561924903,FR 3561924904,3561924911,GB -3561924912,3561925039,NL +3561924912,3561924927,NL +3561924928,3561924943,GB +3561924944,3561925039,NL 3561925040,3561925087,GB 3561925088,3561925119,NL 3561925120,3561926943,GB @@ -136462,7 +139015,9 @@ 3561939833,3561939835,GB 3561939836,3561940991,IE 3561940992,3561942015,GB -3561942016,3561947135,IE +3561942016,3561942847,IE +3561942848,3561942911,GB +3561942912,3561947135,IE 3561947136,3561963519,DE 3561963520,3561971711,BE 3561971712,3561975807,CZ @@ -136558,6 +139113,10 @@ 3562258432,3562263975,NL 3562263976,3562263983,BE 3562263984,3562283007,NL +3562283008,3562285055,IT +3562285056,3562287103,IE +3562287104,3562289151,IT +3562289152,3562291199,FR 3562291200,3562307583,GB 3562307584,3562315775,NL 3562315776,3562321231,GB @@ -136579,7 +139138,8 @@ 3562373120,3562381311,FR 3562381312,3562389503,SI 3562389504,3562395647,GH -3562395648,3562396159,TZ +3562395648,3562395903,BR +3562395904,3562396159,TZ 3562396160,3562397695,SZ 3562397696,3562405887,GB 3562405888,3562414079,FI @@ -136600,9 +139160,7 @@ 3562545152,3562553343,GB 3562553344,3562561535,DK 3562561536,3562569727,UG -3562569728,3562572143,DE -3562572144,3562572159,LU -3562572160,3562572223,DE +3562569728,3562572223,DE 3562572224,3562572239,US 3562572240,3562572543,DE 3562572544,3562572799,LU @@ -136669,9 +139227,7 @@ 3563005952,3563006463,TR 3563006464,3563006591,DE 3563006592,3563006719,CA -3563006720,3563006847,DE -3563006848,3563006911,US -3563006912,3563007487,DE +3563006720,3563007487,DE 3563007488,3563007999,TR 3563008000,3563008255,DE 3563008256,3563008511,PL @@ -136700,7 +139256,7 @@ 3563068416,3563069183,NG 3563069184,3563069439,GH 3563069440,3563077631,HU -3563077632,3563085823,SE +3563077632,3563085823,KZ 3563085824,3563094015,RU 3563094016,3563096255,DE 3563096256,3563096287,GB @@ -136916,9 +139472,7 @@ 3563850048,3563850111,NL 3563850112,3563850239,ES 3563850240,3563850751,GB -3563850752,3563850767,NL -3563850768,3563850783,ES -3563850784,3563850815,NL +3563850752,3563850815,NL 3563850816,3563850831,ES 3563850832,3563850847,NL 3563850848,3563850879,ES @@ -136944,8 +139498,8 @@ 3563853568,3563854079,ES 3563854080,3563854095,NL 3563854096,3563854103,ES -3563854104,3563854175,NL -3563854176,3563854239,ES +3563854104,3563854191,NL +3563854192,3563854239,ES 3563854240,3563854259,NL 3563854260,3563854591,ES 3563854592,3563854847,NL @@ -137067,9 +139621,7 @@ 3564339992,3564339999,NL 3564340000,3564344031,GB 3564344032,3564344047,NL -3564344048,3564344207,GB -3564344208,3564344215,NL -3564344216,3564345143,GB +3564344048,3564345143,GB 3564345144,3564345151,NL 3564345152,3564349615,GB 3564349616,3564349631,NL @@ -137376,9 +139928,7 @@ 3564881664,3564881727,NL 3564881728,3564881935,GB 3564881936,3564881939,NL -3564881940,3564881983,GB -3564881984,3564881991,NL -3564881992,3564881999,GB +3564881940,3564881999,GB 3564882000,3564882079,NL 3564882080,3564882095,GB 3564882096,3564882119,NL @@ -137386,9 +139936,7 @@ 3564882128,3564882135,NL 3564882136,3564882143,GB 3564882144,3564882239,NL -3564882240,3564882431,GB -3564882432,3564882943,NL -3564882944,3564883007,GB +3564882240,3564883007,GB 3564883008,3564883039,NL 3564883040,3564883071,GB 3564883072,3564883087,NL @@ -137402,8 +139950,8 @@ 3564884336,3564884343,NL 3564884344,3564884359,GB 3564884360,3564884367,NL -3564884368,3564884375,GB -3564884376,3564884399,NL +3564884368,3564884383,GB +3564884384,3564884399,NL 3564884400,3564884407,GB 3564884408,3564884415,NL 3564884416,3564884431,GB @@ -137788,8 +140336,8 @@ 3565038664,3565038687,GB 3565038688,3565038719,IE 3565038720,3565038727,GB -3565038728,3565038775,IE -3565038776,3565039615,GB +3565038728,3565038823,IE +3565038824,3565039615,GB 3565039616,3565042175,IE 3565042176,3565043711,GB 3565043712,3565047807,AT @@ -137957,9 +140505,7 @@ 3565752464,3565752471,EU 3565752472,3565752479,GB 3565752480,3565752487,EU -3565752488,3565752535,GB -3565752536,3565752543,EU -3565752544,3565752839,GB +3565752488,3565752839,GB 3565752840,3565752855,EU 3565752856,3565752879,GB 3565752880,3565752887,EU @@ -138158,9 +140704,7 @@ 3566993408,3567058943,TR 3567058944,3567103047,FR 3567103048,3567103055,IT -3567103056,3567108255,FR -3567108256,3567108263,SE -3567108264,3567124479,FR +3567103056,3567124479,FR 3567124480,3567124991,EU 3567124992,3567125023,GB 3567125024,3567125247,EU @@ -138621,7 +141165,9 @@ 3569068544,3569068671,BG 3569068672,3569068951,GB 3569068952,3569068991,DE -3569068992,3569075711,GB +3569068992,3569074879,GB +3569074880,3569074887,IE +3569074888,3569075711,GB 3569075712,3569075839,FR 3569075840,3569083903,GB 3569083904,3569084159,US @@ -139171,7 +141717,9 @@ 3571415040,3571415295,GB 3571415296,3571415311,DE 3571415312,3571415327,AT -3571415328,3571425695,DE +3571415328,3571423743,DE +3571423744,3571423999,US +3571424000,3571425695,DE 3571425696,3571425727,ES 3571425728,3571426895,DE 3571426896,3571426899,ES @@ -139188,9 +141736,7 @@ 3571485196,3571515391,BE 3571515392,3571548159,GB 3571548160,3571580927,ES -3571580928,3571595727,FI -3571595728,3571595743,AX -3571595744,3571646463,FI +3571580928,3571646463,FI 3571646464,3571655560,DE 3571655561,3571655561,RO 3571655562,3571675679,DE @@ -139442,7 +141988,11 @@ 3575367112,3575367119,DE 3575367120,3575372239,ES 3575372240,3575372247,PT -3575372248,3575382015,ES +3575372248,3575373183,ES +3575373184,3575373191,GB +3575373192,3575374319,ES +3575374320,3575374327,GB +3575374328,3575382015,ES 3575382016,3575412991,FI 3575412992,3575413119,RU 3575413120,3575419903,FI @@ -139718,7 +142268,7 @@ 3575635704,3575635775,BE 3575635776,3575635839,CH 3575635840,3575635847,GB -3575635848,3575635855,FR +3575635848,3575635855,BE 3575635856,3575635871,TR 3575635872,3575635983,BE 3575635984,3575635999,DE @@ -140273,10 +142823,8 @@ 3576238152,3576238159,GB 3576238160,3576238305,FR 3576238306,3576238335,GB -3576238336,3576238511,FR -3576238512,3576238527,GB -3576238528,3576238559,FR -3576238560,3576238575,GB +3576238336,3576238567,FR +3576238568,3576238575,GB 3576238576,3576238863,FR 3576238864,3576238879,GB 3576238880,3576238895,FR @@ -140289,12 +142837,9 @@ 3576239040,3576239071,GB 3576239072,3576239087,FR 3576239088,3576239103,GB -3576239104,3576239615,FR -3576239616,3576239623,GB +3576239104,3576239623,FR 3576239624,3576239631,IT -3576239632,3576239663,FR -3576239664,3576239671,GB -3576239672,3576240039,FR +3576239632,3576240039,FR 3576240040,3576240047,GB 3576240048,3576240111,FR 3576240112,3576240127,GB @@ -140364,7 +142909,9 @@ 3576252416,3576252671,GB 3576252672,3576254543,FR 3576254544,3576254551,GB -3576254552,3576254607,FR +3576254552,3576254567,FR +3576254568,3576254575,GB +3576254576,3576254607,FR 3576254608,3576254615,GB 3576254616,3576254623,FR 3576254624,3576254647,GB @@ -140430,7 +142977,9 @@ 3576256896,3576256959,GB 3576256960,3576256991,FR 3576256992,3576257007,GB -3576257008,3576257135,FR +3576257008,3576257103,FR +3576257104,3576257119,GB +3576257120,3576257135,FR 3576257136,3576257151,GB 3576257152,3576257159,FR 3576257160,3576257167,GB @@ -140476,8 +143025,8 @@ 3576258672,3576258687,GB 3576258688,3576258703,FR 3576258704,3576258783,GB -3576258784,3576258823,FR -3576258824,3576258847,GB +3576258784,3576258831,FR +3576258832,3576258847,GB 3576258848,3576258863,FR 3576258864,3576258895,GB 3576258896,3576258943,FR @@ -140555,9 +143104,7 @@ 3576263528,3576263567,FR 3576263568,3576263575,GB 3576263576,3576263583,FR -3576263584,3576263599,GB -3576263600,3576263615,FR -3576263616,3576263623,GB +3576263584,3576263623,GB 3576263624,3576263679,FR 3576263680,3576263743,GB 3576263744,3576263751,FR @@ -140580,15 +143127,9 @@ 3576264640,3576264687,GB 3576264688,3576265319,FR 3576265320,3576265327,GB -3576265328,3576265359,FR -3576265360,3576265367,GB -3576265368,3576265375,FR -3576265376,3576265383,GB -3576265384,3576265399,FR -3576265400,3576265431,GB -3576265432,3576265439,FR -3576265440,3576265455,GB -3576265456,3576265463,FR +3576265328,3576265423,FR +3576265424,3576265431,GB +3576265432,3576265463,FR 3576265464,3576265471,GB 3576265472,3576265759,FR 3576265760,3576265775,GB @@ -140644,11 +143185,9 @@ 3576987648,3577000959,GB 3577000960,3577001343,NL 3577001344,3577001983,GB -3577001984,3577003647,NL -3577003648,3577003711,GB -3577003712,3577003767,NL -3577003768,3577003771,GB -3577003772,3577004031,NL +3577001984,3577003643,NL +3577003644,3577003711,GB +3577003712,3577004031,NL 3577004032,3577020415,GB 3577020416,3577085951,NL 3577085952,3577151487,DE @@ -140670,8 +143209,8 @@ 3577545984,3577546111,SE 3577546112,3577546239,DE 3577546240,3577546367,US -3577546368,3577547455,DE -3577547456,3577547519,FR +3577546368,3577547487,DE +3577547488,3577547519,FR 3577547520,3577550983,DE 3577550984,3577550991,CH 3577550992,3577551407,DE @@ -140784,8 +143323,8 @@ 3577638960,3577638967,EU 3577638968,3577639239,FR 3577639240,3577639247,EU -3577639248,3577639679,FR -3577639680,3577639767,EU +3577639248,3577639743,FR +3577639744,3577639767,EU 3577639768,3577639783,FR 3577639784,3577639799,EU 3577639800,3577639807,FR @@ -140808,9 +143347,7 @@ 3577642056,3577642063,EU 3577642064,3577642239,GB 3577642240,3577642495,EU -3577642496,3577642623,FR -3577642624,3577642751,EU -3577642752,3577643007,FR +3577642496,3577643007,FR 3577643008,3577643231,NL 3577643232,3577643247,GB 3577643248,3577643263,NL @@ -141214,20 +143751,28 @@ 3580199936,3580200447,EE 3580200448,3580200959,SE 3580200960,3580201983,LT -3580201984,3580203519,SE +3580201984,3580203007,SE +3580203008,3580203135,HR +3580203136,3580203519,SE 3580203520,3580204543,RU 3580204544,3580205055,NL 3580205056,3580207103,HR 3580207104,3580208127,SE 3580208128,3580209151,EE -3580209152,3580213247,SE +3580209152,3580211199,SE +3580211200,3580213247,HR 3580213248,3580214271,CH 3580214272,3580214783,LV -3580214784,3580215295,SE +3580214784,3580215295,HR 3580215296,3580216319,EE 3580216320,3580216831,SE 3580216832,3580217087,EE -3580217088,3580223487,SE +3580217088,3580221439,SE +3580221440,3580221951,HR +3580221952,3580222335,SE +3580222336,3580222719,HR +3580222720,3580222975,SE +3580222976,3580223487,HR 3580223488,3580231679,DE 3580231680,3580231935,LT 3580231936,3580232447,LV @@ -141403,11 +143948,12 @@ 3582077112,3582077439,GB 3582077440,3582077471,DE 3582077472,3582077503,GB -3582077504,3582077695,DE -3582077696,3582078631,GB +3582077504,3582077759,DE +3582077760,3582078631,GB 3582078632,3582078639,DE -3582078640,3582081023,GB -3582081024,3582081535,ES +3582078640,3582081055,GB +3582081056,3582081087,ES +3582081088,3582081535,GB 3582081536,3582081791,DE 3582081792,3582083071,GB 3582083072,3582091263,BG @@ -141450,9 +143996,7 @@ 3582222864,3582222879,NO 3582222880,3582223087,SE 3582223088,3582223095,NL -3582223096,3582223967,SE -3582223968,3582223975,NO -3582223976,3582224375,SE +3582223096,3582224375,SE 3582224376,3582224379,FI 3582224380,3582225719,SE 3582225720,3582225727,FI @@ -141771,7 +144315,9 @@ 3582571488,3582571647,EU 3582571648,3582571687,IE 3582571688,3582571691,EU -3582571692,3582571719,IE +3582571692,3582571695,IE +3582571696,3582571707,EU +3582571708,3582571719,IE 3582571720,3582571751,EU 3582571752,3582571839,IE 3582571840,3582571999,EU @@ -141847,8 +144393,7 @@ 3582722048,3582730239,IT 3582730240,3582736383,ES 3582736384,3582737407,DZ -3582737408,3582737919,MA -3582737920,3582738431,ES +3582737408,3582738431,ES 3582738432,3582746623,DK 3582746624,3582754815,RU 3582754816,3582763007,GR @@ -141936,14 +144481,12 @@ 3583157280,3583157439,GB 3583157440,3583157471,IE 3583157472,3583157487,GB -3583157488,3583157503,IE -3583157504,3583158511,GB +3583157488,3583157759,IE +3583157760,3583158511,GB 3583158512,3583158527,IE 3583158528,3583158783,GB 3583158784,3583159039,DE -3583159040,3583159359,GB -3583159360,3583159375,DE -3583159376,3583160319,GB +3583159040,3583160319,GB 3583160320,3583161343,DE 3583161344,3583162271,GB 3583162272,3583162303,IE @@ -142066,9 +144609,7 @@ 3583706056,3583706063,RU 3583706064,3583706103,UA 3583706104,3583706107,NA -3583706108,3583706151,UA -3583706152,3583706159,NA -3583706160,3583706191,UA +3583706108,3583706191,UA 3583706192,3583706199,NA 3583706200,3583706295,UA 3583706296,3583706319,NA @@ -142086,9 +144627,7 @@ 3583706592,3583706607,NA 3583706608,3583706615,UA 3583706616,3583706623,NA -3583706624,3583706679,UA -3583706680,3583706687,NA -3583706688,3583706695,UA +3583706624,3583706695,UA 3583706696,3583706711,NA 3583706712,3583706743,UA 3583706744,3583706767,NA @@ -142120,13 +144659,9 @@ 3583707216,3583707223,NA 3583707224,3583707519,UA 3583707520,3583707535,NA -3583707536,3583707663,UA -3583707664,3583707671,NA -3583707672,3583707751,UA +3583707536,3583707751,UA 3583707752,3583707759,NA -3583707760,3583707775,UA -3583707776,3583707791,NA -3583707792,3583707807,UA +3583707760,3583707807,UA 3583707808,3583707815,NA 3583707816,3583707839,UA 3583707840,3583707855,NA @@ -142161,8 +144696,7 @@ 3583709768,3583709847,UA 3583709848,3583709863,NA 3583709864,3583709871,RU -3583709872,3583709879,NA -3583709880,3583709887,UA +3583709872,3583709887,UA 3583709888,3583709911,NA 3583709912,3583709927,UA 3583709928,3583709943,NA @@ -142193,8 +144727,7 @@ 3583710744,3583710751,BE 3583710752,3583710887,UA 3583710888,3583710895,NA -3583710896,3583711007,UA -3583711008,3583711015,RU +3583710896,3583711015,UA 3583711016,3583711023,NA 3583711024,3583711247,UA 3583711248,3583711255,NA @@ -142210,9 +144743,7 @@ 3583711784,3583711799,NA 3583711800,3583711815,UA 3583711816,3583711823,NA -3583711824,3583711871,UA -3583711872,3583711879,NA -3583711880,3583712015,UA +3583711824,3583712015,UA 3583712016,3583712023,NA 3583712024,3583712119,UA 3583712120,3583712127,NA @@ -142226,14 +144757,11 @@ 3583712528,3583712535,IN 3583712536,3583712775,UA 3583712776,3583712783,NA -3583712784,3583712927,UA -3583712928,3583712935,IN +3583712784,3583712935,UA 3583712936,3583712943,NA 3583712944,3583713007,UA 3583713008,3583713015,RU -3583713016,3583713079,UA -3583713080,3583713087,IN -3583713088,3583713279,UA +3583713016,3583713279,UA 3583713280,3583721471,CZ 3583721472,3583729663,DE 3583729664,3583737855,TR @@ -142262,8 +144790,7 @@ 3583744104,3583744111,GB 3583744112,3583744287,EU 3583744288,3583744303,GB -3583744304,3583744311,EU -3583744312,3583744319,DE +3583744304,3583744319,EU 3583744320,3583744447,GB 3583744448,3583744511,EU 3583744512,3583744767,GB @@ -142320,8 +144847,10 @@ 3583855248,3583855311,FI 3583855312,3583855327,US 3583855328,3583856383,FI -3583856384,3583856463,SG -3583856464,3583856615,FI +3583856384,3583856510,SG +3583856511,3583856511,FI +3583856512,3583856543,SG +3583856544,3583856615,FI 3583856616,3583856639,SG 3583856640,3583860735,FI 3583860736,3583868927,HU @@ -142534,7 +145063,9 @@ 3584929600,3584929727,DE 3584929728,3584931375,CH 3584931376,3584931391,ES -3584931392,3584933887,CH +3584931392,3584932295,CH +3584932296,3584932303,DE +3584932304,3584933887,CH 3584933888,3584942079,NO 3584942080,3584950271,DK 3584950272,3584958463,UA @@ -142565,9 +145096,7 @@ 3585048576,3585050623,IQ 3585050624,3585056767,GB 3585056768,3585064959,LB -3585064960,3585071405,GB -3585071406,3585071409,IN -3585071410,3585081343,GB +3585064960,3585081343,GB 3585081344,3585114111,IR 3585114112,3585122303,IS 3585122304,3585130495,ES @@ -142942,9 +145471,7 @@ 3586476032,3586476063,TR 3586476064,3586476287,HU 3586476288,3586476295,SK -3586476296,3586476311,HU -3586476312,3586476319,AT -3586476320,3586476351,HU +3586476296,3586476351,HU 3586476352,3586476383,AT 3586476384,3586476407,UA 3586476408,3586476415,BG @@ -142967,11 +145494,21 @@ 3586543760,3586543791,GB 3586543792,3586544703,DE 3586544704,3586544719,AE -3586544720,3586545679,DE +3586544720,3586545119,DE +3586545120,3586545127,GB +3586545128,3586545679,DE 3586545680,3586545703,GB -3586545704,3586546375,DE +3586545704,3586546287,DE +3586546288,3586546303,GB +3586546304,3586546311,DE +3586546312,3586546319,GB +3586546320,3586546375,DE 3586546376,3586546383,GB -3586546384,3586555903,DE +3586546384,3586546415,DE +3586546416,3586546423,GB +3586546424,3586547087,DE +3586547088,3586547095,GB +3586547096,3586555903,DE 3586555904,3586572287,IT 3586572288,3586588671,RS 3586588672,3586596863,IT @@ -143035,6 +145572,7 @@ 3586703360,3586719743,CH 3586719744,3586752511,ES 3586752512,3586785279,NL +3586785280,3586793471,OM 3586793472,3586801663,CH 3586801664,3586804751,HR 3586804752,3586804767,HU @@ -143048,7 +145586,9 @@ 3586883584,3586899967,IT 3586899968,3586900287,DE 3586900288,3586900351,NL -3586900352,3586904831,DE +3586900352,3586901311,DE +3586901312,3586901375,ES +3586901376,3586904831,DE 3586904832,3586904839,VG 3586904840,3586905199,DE 3586905200,3586905215,GB @@ -143153,9 +145693,7 @@ 3587178796,3587178799,US 3587178800,3587179439,AT 3587179440,3587179455,GB -3587179456,3587179463,AT -3587179464,3587179471,CH -3587179472,3587186687,AT +3587179456,3587186687,AT 3587186688,3587186815,DE 3587186816,3587187199,A2 3587187200,3587187455,GB @@ -143213,9 +145751,7 @@ 3587230528,3587230543,NL 3587230544,3587230607,GB 3587230608,3587230623,NL -3587230624,3587230687,GB -3587230688,3587230719,NL -3587230720,3587230791,GB +3587230624,3587230791,GB 3587230792,3587230799,NL 3587230800,3587230847,GB 3587230848,3587230911,NL @@ -143228,7 +145764,9 @@ 3587232536,3587232711,GB 3587232712,3587232719,NL 3587232720,3587232767,GB -3587232768,3587233103,NL +3587232768,3587232911,NL +3587232912,3587232927,GB +3587232928,3587233103,NL 3587233104,3587233119,GB 3587233120,3587233295,NL 3587233296,3587233319,GB @@ -143252,12 +145790,14 @@ 3587234000,3587234047,GB 3587234048,3587234079,NL 3587234080,3587234095,GB -3587234096,3587234143,NL +3587234096,3587234111,NL +3587234112,3587234127,GB +3587234128,3587234143,NL 3587234144,3587234159,GB 3587234160,3587234207,NL 3587234208,3587234815,GB -3587234816,3587236367,NL -3587236368,3587236383,GB +3587234816,3587236351,NL +3587236352,3587236383,GB 3587236384,3587236447,NL 3587236448,3587236479,GB 3587236480,3587236511,NL @@ -143284,11 +145824,17 @@ 3587238568,3587238583,GB 3587238584,3587238607,NL 3587238608,3587238911,GB -3587238912,3587239303,NL +3587238912,3587239279,NL +3587239280,3587239287,GB +3587239288,3587239303,NL 3587239304,3587239311,GB -3587239312,3587239911,NL +3587239312,3587239359,NL +3587239360,3587239423,GB +3587239424,3587239911,NL 3587239912,3587239919,GB -3587239920,3587240063,NL +3587239920,3587239999,NL +3587240000,3587240007,GB +3587240008,3587240063,NL 3587240064,3587240071,BE 3587240072,3587240103,NL 3587240104,3587240107,GB @@ -143296,13 +145842,17 @@ 3587240272,3587240279,GB 3587240280,3587240359,NL 3587240360,3587240367,GB -3587240368,3587240439,NL -3587240440,3587240447,GB -3587240448,3587240511,NL -3587240512,3587240575,GB -3587240576,3587240615,NL -3587240616,3587240623,GB -3587240624,3587241071,NL +3587240368,3587240519,NL +3587240520,3587240527,GB +3587240528,3587240543,NL +3587240544,3587240559,IE +3587240560,3587240567,BE +3587240568,3587240575,GB +3587240576,3587240607,NL +3587240608,3587240623,GB +3587240624,3587241039,NL +3587241040,3587241047,GB +3587241048,3587241071,NL 3587241072,3587241087,GB 3587241088,3587241143,NL 3587241144,3587241151,GB @@ -143312,13 +145862,17 @@ 3587241264,3587241271,GB 3587241272,3587241343,NL 3587241344,3587241471,GB -3587241472,3587242095,NL +3587241472,3587242047,NL +3587242048,3587242055,GB +3587242056,3587242071,NL +3587242072,3587242079,IE +3587242080,3587242095,NL 3587242096,3587242111,GB 3587242112,3587242271,NL 3587242272,3587242287,GB 3587242288,3587242463,NL -3587242464,3587242471,GB -3587242472,3587243407,NL +3587242464,3587242495,GB +3587242496,3587243407,NL 3587243408,3587243415,GB 3587243416,3587243935,NL 3587243936,3587243951,GB @@ -143326,7 +145880,8 @@ 3587243968,3587243975,GB 3587243976,3587243983,NL 3587243984,3587243991,GB -3587243992,3587244031,NL +3587243992,3587244023,NL +3587244024,3587244031,GB 3587244032,3587260415,IT 3587260416,3587284991,DE 3587284992,3587285135,A2 @@ -143458,7 +146013,7 @@ 3587391488,3587407871,KZ 3587407872,3587408383,NL 3587408384,3587408895,BE -3587408896,3587409407,NL +3587408896,3587409407,RU 3587409408,3587410431,BE 3587410432,3587410687,NL 3587410688,3587412223,BE @@ -143496,7 +146051,9 @@ 3587699560,3587699567,GB 3587699568,3587700031,IT 3587700032,3587700039,GB -3587700040,3587701295,IT +3587700040,3587701271,IT +3587701272,3587701279,DE +3587701280,3587701295,IT 3587701296,3587701303,FR 3587701304,3587702783,IT 3587702784,3587710975,DE @@ -143571,9 +146128,7 @@ 3588521984,3588538367,PT 3588538368,3588544383,GB 3588544384,3588544391,IE -3588544392,3588550447,GB -3588550448,3588550463,IE -3588550464,3588553983,GB +3588544392,3588553983,GB 3588553984,3588554239,IE 3588554240,3588554687,GB 3588554688,3588554751,IE @@ -143778,7 +146333,9 @@ 3589582656,3589583359,NL 3589583360,3589583647,GB 3589583648,3589583663,NL -3589583664,3589584255,GB +3589583664,3589583743,GB +3589583744,3589583871,NL +3589583872,3589584255,GB 3589584256,3589584271,NL 3589584272,3589584639,GB 3589584640,3589585279,NL @@ -144031,9 +146588,7 @@ 3589891616,3589891631,BE 3589891632,3589931007,GB 3589931008,3589947391,SI -3589947392,3589951863,FI -3589951864,3589951871,AX -3589951872,3589963775,FI +3589947392,3589963775,FI 3589963776,3589971231,ES 3589971232,3589971247,CA 3589971248,3589980159,ES @@ -144089,8 +146644,8 @@ 3590157568,3590157631,SI 3590157632,3590157679,RS 3590157680,3590157687,SI -3590157688,3590157711,RS -3590157712,3590157743,SI +3590157688,3590157719,RS +3590157720,3590157743,SI 3590157744,3590157751,RS 3590157752,3590157759,SI 3590157760,3590157767,RS @@ -144106,10 +146661,10 @@ 3590158360,3590158367,RS 3590158368,3590158407,SI 3590158408,3590158415,RS -3590158416,3590158431,SI +3590158416,3590158431,ME 3590158432,3590158439,RS -3590158440,3590158455,SI -3590158456,3590158479,RS +3590158440,3590158447,SI +3590158448,3590158479,RS 3590158480,3590158527,SI 3590158528,3590158535,RS 3590158536,3590158591,SI @@ -144125,11 +146680,13 @@ 3590225920,3590234111,TR 3590234112,3590242303,GB 3590242304,3590244351,US -3590244352,3590244863,DE +3590244352,3590244607,DE +3590244608,3590244863,IT 3590244864,3590245119,FR -3590245120,3590245183,BE -3590245184,3590245279,FR -3590245280,3590245311,BE +3590245120,3590245135,BE +3590245136,3590245143,FR +3590245144,3590245183,BE +3590245184,3590245311,FR 3590245312,3590245439,US 3590245440,3590245503,FR 3590245504,3590245567,GB @@ -144166,10 +146723,9 @@ 3590251520,3590251583,FR 3590251584,3590251647,US 3590251648,3590251775,NL -3590251776,3590251839,FR -3590251840,3590251903,ES -3590251904,3590251967,FR -3590251968,3590252543,ES +3590251776,3590251967,FR +3590251968,3590252287,ES +3590252288,3590252543,FR 3590252544,3590253055,GB 3590253056,3590253311,DE 3590253312,3590253375,FR @@ -144182,17 +146738,14 @@ 3590254144,3590254271,US 3590254272,3590254463,FR 3590254464,3590254591,ES -3590254592,3590254847,FR -3590254848,3590254879,ES -3590254880,3590254911,FR +3590254592,3590254911,FR 3590254912,3590254975,ES 3590254976,3590255039,DE 3590255040,3590255047,FR 3590255048,3590255071,ES 3590255072,3590255103,FR 3590255104,3590255359,ES -3590255360,3590255615,FR -3590255616,3590255871,BE +3590255360,3590255871,FR 3590255872,3590256127,US 3590256128,3590256383,ES 3590256384,3590256639,FR @@ -144217,10 +146770,13 @@ 3590307904,3590307935,UA 3590307936,3590307951,A2 3590307952,3590307967,NG -3590307968,3590308031,A2 +3590307968,3590307991,A2 +3590307992,3590307995,SO +3590307996,3590308031,A2 3590308032,3590308047,UG 3590308048,3590308055,NG -3590308056,3590308071,A2 +3590308056,3590308063,A2 +3590308064,3590308071,SO 3590308072,3590308079,RW 3590308080,3590308087,IQ 3590308088,3590308095,A2 @@ -144237,9 +146793,11 @@ 3590308248,3590308287,IQ 3590308288,3590308303,A2 3590308304,3590308311,SO -3590308312,3590308343,IQ -3590308344,3590308359,A2 -3590308360,3590308367,IQ +3590308312,3590308319,IQ +3590308320,3590308327,A2 +3590308328,3590308343,IQ +3590308344,3590308351,A2 +3590308352,3590308367,IQ 3590308368,3590308375,A2 3590308376,3590308391,IQ 3590308392,3590308399,A2 @@ -144260,14 +146818,17 @@ 3590308568,3590308583,IQ 3590308584,3590308607,A2 3590308608,3590308735,NG -3590308736,3590308767,A2 +3590308736,3590308743,A2 +3590308744,3590308747,SO +3590308748,3590308767,A2 3590308768,3590308775,RW 3590308776,3590308783,ZA 3590308784,3590308799,ZW 3590308800,3590308807,GB 3590308808,3590308815,ZM 3590308816,3590308823,KE -3590308824,3590308855,A2 +3590308824,3590308831,SO +3590308832,3590308855,A2 3590308856,3590308863,NG 3590308864,3590308951,A2 3590308952,3590308959,GH @@ -144280,7 +146841,9 @@ 3590309072,3590309079,MW 3590309080,3590309103,NG 3590309104,3590309111,ZW -3590309112,3590309511,A2 +3590309112,3590309251,A2 +3590309252,3590309255,SO +3590309256,3590309511,A2 3590309512,3590309519,AO 3590309520,3590309527,NG 3590309528,3590309535,CM @@ -144311,7 +146874,8 @@ 3590309888,3590310143,A2 3590310144,3590310175,IQ 3590310176,3590310183,LR -3590310184,3590310215,IQ +3590310184,3590310191,A2 +3590310192,3590310215,IQ 3590310216,3590310223,A2 3590310224,3590310255,IQ 3590310256,3590310271,A2 @@ -144333,16 +146897,14 @@ 3590310952,3590310959,IQ 3590310960,3590310967,A2 3590310968,3590311007,IQ -3590311008,3590311015,A2 -3590311016,3590311023,IQ -3590311024,3590311031,A2 +3590311008,3590311031,A2 3590311032,3590311039,IQ 3590311040,3590311055,A2 3590311056,3590311063,IQ 3590311064,3590311079,A2 3590311080,3590311087,IQ -3590311088,3590311095,A2 -3590311096,3590311111,IQ +3590311088,3590311103,A2 +3590311104,3590311111,IQ 3590311112,3590311119,A2 3590311120,3590311135,IQ 3590311136,3590311143,A2 @@ -144352,7 +146914,7 @@ 3590311184,3590311199,A2 3590311200,3590311207,SD 3590311208,3590311215,CD -3590311216,3590311223,AO +3590311216,3590311223,A2 3590311224,3590311231,CD 3590311232,3590311255,A2 3590311256,3590311263,ZW @@ -144441,9 +147003,7 @@ 3590317496,3590317503,LB 3590317504,3590317527,A2 3590317528,3590317543,IQ -3590317544,3590317567,A2 -3590317568,3590317695,IQ -3590317696,3590317951,A2 +3590317544,3590317951,A2 3590317952,3590318047,UA 3590318048,3590319167,A2 3590319168,3590319231,AE @@ -144743,7 +147303,47 @@ 3624549616,3624550143,A2 3624550144,3624587263,US 3624587264,3624591359,JM -3624591360,3624730623,US +3624591360,3624714239,US +3624714240,3624714623,SG +3624714624,3624714639,US +3624714640,3624714655,SG +3624714656,3624714679,US +3624714680,3624714687,SG +3624714688,3624714719,US +3624714720,3624714743,SG +3624714744,3624714751,US +3624714752,3624715023,SG +3624715024,3624715071,US +3624715072,3624715103,SG +3624715104,3624715167,US +3624715168,3624715183,SG +3624715184,3624715263,US +3624715264,3624715647,SG +3624715648,3624715655,US +3624715656,3624715743,SG +3624715744,3624715775,US +3624715776,3624716031,SG +3624716032,3624716223,US +3624716224,3624716255,AU +3624716256,3624718335,US +3624718336,3624718591,SG +3624718592,3624718863,US +3624718864,3624718879,AU +3624718880,3624718951,US +3624718952,3624718959,SG +3624718960,3624719103,US +3624719104,3624719359,SG +3624719360,3624719535,US +3624719536,3624719543,AU +3624719544,3624719615,US +3624719616,3624719743,SG +3624719744,3624719751,US +3624719752,3624719871,SG +3624719872,3624720895,US +3624720896,3624721151,SG +3624721152,3624721727,US +3624721728,3624721759,SG +3624721760,3624730623,US 3624730624,3624796159,CA 3624796160,3624817679,US 3624817680,3624817687,CA @@ -144917,7 +147517,9 @@ 3624912680,3624912687,IN 3624912688,3624912727,US 3624912728,3624912735,TT -3624912736,3624912959,US +3624912736,3624912759,US +3624912760,3624912767,MY +3624912768,3624912959,US 3624912960,3624913087,IN 3624913088,3624913247,US 3624913248,3624913279,CA @@ -145009,7 +147611,8 @@ 3624924896,3624924927,CA 3624924928,3624925054,US 3624925055,3624925695,CA -3624925696,3624926463,US +3624925696,3624926335,US +3624926336,3624926463,TZ 3624926464,3624926527,CA 3624926528,3624926591,US 3624926592,3624926655,IN @@ -145178,8 +147781,8 @@ 3625512960,3625528541,US 3625528542,3625528551,AU 3625528552,3625574399,US -3625574400,3625578495,A2 -3625578496,3625581631,US +3625574400,3625578239,A2 +3625578240,3625581631,US 3625581632,3625581647,NL 3625581648,3625631743,US 3625631744,3625639935,CA @@ -145530,7 +148133,9 @@ 3626383299,3626383375,US 3626383376,3626383383,RU 3626383384,3626383391,CA -3626383392,3626383423,US +3626383392,3626383399,US +3626383400,3626383407,IN +3626383408,3626383423,US 3626383424,3626383431,GB 3626383432,3626383439,AU 3626383440,3626383447,GR @@ -145543,8 +148148,7 @@ 3626383544,3626383551,GB 3626383552,3626383583,US 3626383584,3626383599,CA -3626383600,3626383607,GB -3626383608,3626383615,IN +3626383600,3626383615,IN 3626383616,3626383647,US 3626383648,3626383679,CH 3626383680,3626383727,US @@ -145583,7 +148187,9 @@ 3626385038,3626385041,US 3626385042,3626385045,MX 3626385046,3626385049,CA -3626385050,3626385073,US +3626385050,3626385057,US +3626385058,3626385061,IN +3626385062,3626385073,US 3626385074,3626385077,IE 3626385078,3626385097,US 3626385098,3626385101,IN @@ -145592,7 +148198,7 @@ 3626385118,3626385121,US 3626385122,3626385125,IN 3626385126,3626385129,ID -3626385130,3626385133,GR +3626385130,3626385133,IN 3626385134,3626385137,CA 3626385138,3626385141,GB 3626385142,3626385145,IN @@ -145616,13 +148222,15 @@ 3626385250,3626385253,CN 3626385254,3626385261,US 3626385262,3626385265,GR -3626385266,3626385321,US +3626385266,3626385285,US +3626385286,3626385289,IN +3626385290,3626385321,US 3626385322,3626385325,FR 3626385326,3626385329,CA 3626385330,3626385333,US 3626385334,3626385337,CA 3626385338,3626385349,US -3626385350,3626385353,CA +3626385350,3626385353,IN 3626385354,3626385357,MX 3626385358,3626385361,CA 3626385362,3626385365,US @@ -145787,8 +148395,7 @@ 3626896184,3626905599,CA 3626905600,3626926079,US 3626926080,3626934271,CA -3626934272,3626942463,US -3626950656,3627044863,US +3626934272,3627044863,US 3627044864,3627048959,CA 3627048960,3627065343,US 3627065344,3627069439,CA @@ -145796,7 +148403,9 @@ 3627288576,3627288607,GB 3627288608,3627309455,US 3627309456,3627309471,IL -3627309472,3627310471,US +3627309472,3627309695,US +3627309696,3627309823,AE +3627309824,3627310471,US 3627310472,3627310479,BM 3627310480,3627317087,US 3627317088,3627317119,GB @@ -145857,9 +148466,7 @@ 3627746400,3627746431,CA 3627746432,3627747159,US 3627747160,3627747167,IN -3627747168,3627747583,US -3627747584,3627747615,FR -3627747616,3627753471,US +3627747168,3627753471,US 3627753472,3627753727,AR 3627753728,3627755007,US 3627755008,3627755135,IE @@ -146105,14 +148712,14 @@ 3629202016,3629202047,CA 3629202048,3629202175,US 3629202176,3629202203,CA -3629202204,3629202219,US -3629202220,3629202239,CA +3629202204,3629202223,US +3629202224,3629202239,CA 3629202240,3629202263,US 3629202264,3629202271,CA -3629202272,3629202311,US -3629202312,3629202367,CA -3629202368,3629202427,US -3629202428,3629203199,CA +3629202272,3629202319,US +3629202320,3629202367,CA +3629202368,3629202431,US +3629202432,3629203199,CA 3629203200,3629318143,US 3629318144,3629326335,CA 3629326336,3629327527,US @@ -146853,9 +149460,9 @@ 3632480496,3632480503,US 3632480504,3632480511,RU 3632480512,3632480543,TK -3632480544,3632480567,US -3632480568,3632480575,GB -3632480576,3632480599,US +3632480544,3632480559,US +3632480560,3632480567,DE +3632480568,3632480599,US 3632480600,3632480607,CA 3632480608,3632480615,GB 3632480616,3632480647,US @@ -146871,9 +149478,7 @@ 3632481280,3632481287,GB 3632481288,3632481295,US 3632481296,3632481311,TH -3632481312,3632481391,US -3632481392,3632481399,GB -3632481400,3632481415,US +3632481312,3632481415,US 3632481416,3632481423,TH 3632481424,3632481431,US 3632481432,3632481439,CA @@ -146893,11 +149498,10 @@ 3632481768,3632481775,US 3632481776,3632481783,CA 3632481784,3632481791,GB -3632481792,3632481815,US -3632481816,3632481823,GB -3632481824,3632481999,US +3632481792,3632481999,US 3632482000,3632482007,BZ -3632482008,3632482039,US +3632482008,3632482015,CA +3632482016,3632482039,US 3632482040,3632482047,TK 3632482048,3632482239,US 3632482240,3632482247,GB @@ -146911,8 +149515,7 @@ 3632483152,3632483159,GB 3632483160,3632483327,US 3632483328,3632483335,CA -3632483336,3632483351,US -3632483352,3632483359,CN +3632483336,3632483359,US 3632483360,3632483367,NL 3632483368,3632483375,GI 3632483376,3632483391,GB @@ -146925,9 +149528,7 @@ 3632483584,3632483599,US 3632483600,3632483607,AU 3632483608,3632483615,PL -3632483616,3632483623,GB -3632483624,3632483663,US -3632483664,3632483671,PH +3632483616,3632483671,US 3632483672,3632483679,CA 3632483680,3632483759,US 3632483760,3632483775,TH @@ -146969,8 +149570,7 @@ 3632484816,3632484823,US 3632484824,3632484831,CA 3632484832,3632484839,HK -3632484840,3632484847,BZ -3632484848,3632484855,US +3632484840,3632484855,US 3632484856,3632484863,GB 3632484864,3632485055,US 3632485056,3632485087,TW @@ -146989,15 +149589,16 @@ 3632485280,3632485311,TH 3632485312,3632485391,US 3632485392,3632485399,SR -3632485400,3632485431,US +3632485400,3632485407,US +3632485408,3632485415,CA +3632485416,3632485431,US 3632485432,3632485439,CA 3632485440,3632485471,US 3632485472,3632485487,NC -3632485488,3632485551,US +3632485488,3632485535,US +3632485536,3632485551,CA 3632485552,3632485559,GB -3632485560,3632485567,US -3632485568,3632485575,GB -3632485576,3632485615,US +3632485560,3632485615,US 3632485616,3632485623,TH 3632485624,3632485631,CA 3632485632,3632485639,US @@ -147011,7 +149612,7 @@ 3632485728,3632485735,CA 3632485736,3632485751,US 3632485752,3632485759,CA -3632485760,3632485767,CZ +3632485760,3632485767,US 3632485768,3632485775,KW 3632485776,3632485847,US 3632485848,3632485855,CA @@ -147027,7 +149628,9 @@ 3632486112,3632486143,US 3632486144,3632486151,TK 3632486152,3632486159,GB -3632486160,3632486263,US +3632486160,3632486191,US +3632486192,3632486199,GB +3632486200,3632486263,US 3632486264,3632486271,GB 3632486272,3632486287,FR 3632486288,3632486319,US @@ -147037,11 +149640,10 @@ 3632486344,3632486351,FR 3632486352,3632486407,US 3632486408,3632486415,TH -3632486416,3632486423,US -3632486424,3632486431,CA -3632486432,3632486479,US +3632486416,3632486479,US 3632486480,3632486495,GB -3632486496,3632486519,US +3632486496,3632486511,US +3632486512,3632486519,HU 3632486520,3632486527,GB 3632486528,3632486543,US 3632486544,3632486551,DE @@ -147058,8 +149660,7 @@ 3632486784,3632486815,DE 3632486816,3632486879,US 3632486880,3632486895,TH -3632486896,3632486903,GB -3632486904,3632487023,US +3632486896,3632487023,US 3632487024,3632487031,TH 3632487032,3632487039,CZ 3632487040,3632487135,US @@ -147073,8 +149674,9 @@ 3632487816,3632487823,IL 3632487824,3632487855,US 3632487856,3632487863,GB -3632487864,3632487871,CA -3632487872,3632489087,US +3632487864,3632487895,US +3632487896,3632487903,GB +3632487904,3632489087,US 3632489088,3632489119,SR 3632489120,3632489127,US 3632489128,3632489135,AU @@ -147170,7 +149772,8 @@ 3632493088,3632493119,IO 3632493120,3632493151,US 3632493152,3632493159,GR -3632493160,3632493191,US +3632493160,3632493183,US +3632493184,3632493191,BZ 3632493192,3632493199,CA 3632493200,3632493215,US 3632493216,3632493223,DE @@ -147604,7 +150207,27 @@ 3635533000,3635533007,NO 3635533008,3635533535,US 3635533536,3635533551,IN -3635533552,3635650559,US +3635533552,3635643391,US +3635643392,3635643647,JP +3635643648,3635643679,US +3635643680,3635643681,JP +3635643682,3635643710,US +3635643711,3635643903,JP +3635643904,3635644159,US +3635644160,3635644255,JP +3635644256,3635644319,US +3635644320,3635644671,JP +3635644672,3635645439,US +3635645440,3635645696,JP +3635645697,3635645728,US +3635645729,3635645760,JP +3635645761,3635645776,US +3635645777,3635645951,JP +3635645952,3635646335,US +3635646336,3635646367,JP +3635646368,3635648767,US +3635648768,3635649023,JP +3635649024,3635650559,US 3635650560,3635650815,JP 3635650816,3635651071,US 3635651072,3635651327,JP @@ -147639,7 +150262,10 @@ 3635656224,3635656319,US 3635656320,3635656447,JP 3635656448,3635656703,CA -3635656704,3635659263,US +3635656704,3635656967,JP +3635656968,3635657023,US +3635657024,3635657215,JP +3635657216,3635659263,US 3635659264,3635660031,ID 3635660032,3635660287,CN 3635660288,3635660799,US @@ -147669,7 +150295,19 @@ 3636019200,3636021775,CA 3636021776,3636021791,US 3636021792,3636027391,CA -3636027392,3636064255,US +3636027392,3636028415,US +3636028416,3636029951,SG +3636029952,3636030207,US +3636030208,3636031231,SG +3636031232,3636031999,US +3636032000,3636032511,SG +3636032512,3636032767,US +3636032768,3636033535,SG +3636033536,3636033791,US +3636033792,3636034303,SG +3636034304,3636035327,US +3636035328,3636035583,SG +3636035584,3636064255,US 3636064256,3636068351,CA 3636068352,3636150495,US 3636150496,3636150527,CA @@ -147771,7 +150409,8 @@ 3636161872,3636161885,US 3636161886,3636161943,CA 3636161944,3636161951,US -3636161952,3636161983,CN +3636161952,3636161967,CA +3636161968,3636161983,CN 3636161984,3636162015,US 3636162016,3636162559,CA 3636162560,3636163583,US @@ -147821,9 +150460,7 @@ 3636904544,3636904575,IN 3636904576,3636904607,US 3636904608,3636904671,IN -3636904672,3636904703,US -3636904704,3636904959,MY -3636904960,3636905471,US +3636904672,3636905471,US 3636905472,3636905727,CA 3636905728,3636905791,US 3636905792,3636905823,IN @@ -148005,7 +150642,9 @@ 3638198952,3638198959,BM 3638198960,3638198983,US 3638198984,3638198991,ES -3638198992,3638199711,US +3638198992,3638199167,US +3638199168,3638199295,CN +3638199296,3638199711,US 3638199712,3638199743,DE 3638199744,3638199807,US 3638199808,3638199815,CN @@ -148124,7 +150763,11 @@ 3638400000,3638400063,CA 3638400064,3638400271,US 3638400272,3638400279,CA -3638400280,3638509295,US +3638400280,3638400559,US +3638400560,3638400567,PA +3638400568,3638400639,US +3638400640,3638400767,CA +3638400768,3638509295,US 3638509296,3638509311,GB 3638509312,3638509567,US 3638509568,3638526911,CA @@ -148254,12 +150897,15 @@ 3639498768,3639498783,SI 3639498784,3639498791,US 3639498792,3639498799,NL -3639498800,3639533567,US +3639498800,3639513087,US +3639513088,3639513119,AE +3639513120,3639513239,US +3639513240,3639513243,AE +3639513244,3639533567,US 3639533568,3639537663,CA 3639537664,3639558143,US 3639558144,3639566335,CA -3639566336,3639582719,US -3639590912,3639593983,US +3639566336,3639593983,US 3639593984,3639595007,GB 3639595008,3639607295,US 3639607296,3639611391,CA @@ -148523,9 +151169,7 @@ 3641103720,3641103727,HU 3641103728,3641106951,DE 3641106952,3641106959,CH -3641106960,3641134367,DE -3641134368,3641134375,BE -3641134376,3641140671,DE +3641106960,3641140671,DE 3641140672,3641140679,US 3641140680,3641147519,DE 3641147520,3641147527,AT @@ -148600,18 +151244,16 @@ 3641353808,3641353831,GB 3641353832,3641353839,A2 3641353840,3641353855,GB -3641353856,3641353983,A2 +3641353856,3641353879,NG +3641353880,3641353983,A2 3641353984,3641354239,AF -3641354240,3641354255,NG -3641354256,3641354311,A2 +3641354240,3641354311,A2 3641354312,3641354319,GB 3641354320,3641354327,A2 3641354328,3641354335,GB 3641354336,3641354339,A2 3641354340,3641354367,GB -3641354368,3641354383,A2 -3641354384,3641354391,NG -3641354392,3641354495,A2 +3641354368,3641354495,A2 3641354496,3641354751,GB 3641354752,3641355263,NG 3641355264,3641355519,AO @@ -148621,14 +151263,14 @@ 3641355776,3641356031,LB 3641356032,3641356191,A2 3641356192,3641356207,NG -3641356208,3641357855,A2 +3641356208,3641357823,A2 +3641357824,3641357831,NG +3641357832,3641357855,A2 3641357856,3641357879,GB 3641357880,3641357887,A2 3641357888,3641357927,GB 3641357928,3641358335,A2 -3641358336,3641358591,GB -3641358592,3641358847,A2 -3641358848,3641359359,GB +3641358336,3641359359,GB 3641359360,3641359615,IQ 3641359616,3641359639,GB 3641359640,3641359871,A2 @@ -148689,7 +151331,7 @@ 3641565184,3641567343,SE 3641567344,3641567351,FI 3641567352,3641568967,SE -3641568968,3641568975,NO +3641568968,3641568975,DK 3641568976,3641573375,SE 3641573376,3641577471,NO 3641577472,3641581567,RU @@ -149032,8 +151674,7 @@ 3642415652,3642415655,MT 3642415656,3642417151,GB 3642417152,3642419199,DE -3642419200,3642419967,US -3642419968,3642421247,GB +3642419200,3642421247,GB 3642421248,3642423091,A2 3642423092,3642423099,NG 3642423100,3642424151,A2 @@ -149129,8 +151770,7 @@ 3642553472,3642553519,RU 3642553520,3642553523,UA 3642553524,3642553535,RU -3642553536,3642553543,DE -3642553544,3642553547,UA +3642553536,3642553547,UA 3642553548,3642553567,RU 3642553568,3642553571,UA 3642553572,3642553575,RU @@ -149147,11 +151787,17 @@ 3642554120,3642554127,UA 3642554128,3642554159,RU 3642554160,3642554187,UA -3642554188,3642554207,RU +3642554188,3642554193,RU +3642554194,3642554195,UA +3642554196,3642554207,RU 3642554208,3642554219,UA 3642554220,3642554223,RU 3642554224,3642554367,UA -3642554368,3642554573,LT +3642554368,3642554427,LT +3642554428,3642554431,UA +3642554432,3642554447,LT +3642554448,3642554463,UA +3642554464,3642554573,LT 3642554574,3642554575,UA 3642554576,3642554623,LT 3642554624,3642554631,UA @@ -149167,9 +151813,7 @@ 3642554880,3642554911,DE 3642554912,3642554919,NL 3642554920,3642554931,DE -3642554932,3642554951,UA -3642554952,3642554955,GE -3642554956,3642554959,UA +3642554932,3642554959,UA 3642554960,3642554963,DE 3642554964,3642554967,UA 3642554968,3642554971,LV @@ -149193,7 +151837,8 @@ 3642555070,3642555071,DE 3642555072,3642555087,GE 3642555088,3642555103,DE -3642555104,3642555135,UA +3642555104,3642555111,CZ +3642555112,3642555135,UA 3642555136,3642555153,LT 3642555154,3642555167,UA 3642555168,3642555183,LT @@ -149211,9 +151856,7 @@ 3642555440,3642555443,UA 3642555444,3642555463,PL 3642555464,3642555475,UA -3642555476,3642555493,PL -3642555494,3642555495,UA -3642555496,3642555503,PL +3642555476,3642555503,PL 3642555504,3642555647,UA 3642555648,3642555683,SE 3642555684,3642555685,GB @@ -149226,14 +151869,14 @@ 3642555728,3642555735,SE 3642555736,3642555743,GB 3642555744,3642555759,SE -3642555760,3642555767,UA -3642555768,3642555771,GB +3642555760,3642555771,UA 3642555772,3642555775,SE 3642555776,3642555783,UA 3642555784,3642555787,GB 3642555788,3642555789,UA 3642555790,3642555791,SE -3642555792,3642556159,UA +3642555792,3642555795,CZ +3642555796,3642556159,UA 3642556160,3642556415,LV 3642556416,3642558975,CZ 3642558976,3642559487,HR @@ -149414,8 +152057,8 @@ 3645183744,3645183871,GB 3645183872,3645183903,FR 3645183904,3645183935,IE -3645183936,3645184256,FR -3645184257,3645184447,GB +3645183936,3645184255,FR +3645184256,3645184447,GB 3645184448,3645186047,FR 3645186048,3645190143,GB 3645190144,3645194239,FI @@ -149508,7 +152151,9 @@ 3645435904,3645439999,GB 3645440000,3645444095,SE 3645444096,3645448191,SK -3645448192,3645455487,DE +3645448192,3645454335,DE +3645454336,3645455359,RU +3645455360,3645455487,DE 3645455488,3645456383,RU 3645456384,3645460479,GB 3645460480,3645464575,UA @@ -149530,6 +152175,8 @@ 3645507596,3645507599,DE 3645507600,3645507607,AT 3645507608,3645509631,DE +3645509632,3645511679,NL +3645511680,3645513727,TR 3645513728,3645517823,RU 3645517824,3645521919,IE 3645521920,3645526015,PL @@ -149571,7 +152218,8 @@ 3645601508,3645601759,SE 3645601760,3645601775,FR 3645601776,3645601779,GB -3645601780,3645601799,SE +3645601780,3645601783,US +3645601784,3645601799,SE 3645601800,3645601803,GB 3645601804,3645603839,SE 3645603840,3645612031,BG @@ -149995,9 +152643,7 @@ 3645764087,3645764087,CH 3645764088,3645764091,DE 3645764092,3645764092,FR -3645764093,3645764093,DE -3645764094,3645764094,IT -3645764095,3645764097,DE +3645764093,3645764097,DE 3645764098,3645764098,IT 3645764099,3645764099,DE 3645764100,3645764100,BE @@ -150540,9 +153186,7 @@ 3645889920,3645890559,DE 3645890560,3645894655,RU 3645894656,3645898751,NL -3645898752,3646501711,DE -3646501712,3646501719,US -3646501720,3646513103,DE +3645898752,3646513103,DE 3646513104,3646513111,CA 3646513112,3646947327,DE 3646947328,3647209471,PL @@ -150622,8 +153266,8 @@ 3647965296,3647965303,DE 3647965304,3647965311,ES 3647965312,3647965319,DE -3647965320,3647965423,ES -3647965424,3647965439,DE +3647965320,3647965431,ES +3647965432,3647965439,DE 3647965440,3647965695,ES 3647965696,3647966207,CH 3647966208,3647966575,GB @@ -150649,15 +153293,14 @@ 3647973736,3647973743,DE 3647973744,3647973783,IT 3647973784,3647973791,DE -3647973792,3647973951,IT -3647973952,3647973959,DE -3647973960,3647973967,IT +3647973792,3647973967,IT 3647973968,3647973975,DE 3647973976,3647974047,IT 3647974048,3647974055,DE 3647974056,3647974399,IT 3647974400,3647976447,ES -3647976448,3647976559,BE +3647976448,3647976463,DE +3647976464,3647976559,BE 3647976560,3647976575,FR 3647976576,3647976647,BE 3647976648,3647976663,DE @@ -150688,13 +153331,13 @@ 3647978912,3647979007,NL 3647979008,3647979136,IT 3647979137,3647979519,DE -3647979520,3647980215,FR +3647979520,3647979983,FR +3647979984,3647979991,DE +3647979992,3647980215,FR 3647980216,3647980223,DE 3647980224,3647980239,FR 3647980240,3647980247,DE -3647980248,3647980255,FR -3647980256,3647980271,DE -3647980272,3647980471,FR +3647980248,3647980471,FR 3647980472,3647980479,DE 3647980480,3647980495,FR 3647980496,3647980503,DE @@ -150723,15 +153366,17 @@ 3647987184,3647987191,DE 3647987192,3647987199,ES 3647987200,3647987455,DE -3647987456,3647987527,ES +3647987456,3647987487,ES +3647987488,3647987495,DE +3647987496,3647987527,ES 3647987528,3647987535,GB 3647987536,3647987543,DE 3647987544,3647987711,ES 3647987712,3647988735,IT 3647988736,3647988991,DE -3647988992,3647989495,BE -3647989496,3647989503,DE -3647989504,3647989759,BE +3647988992,3647989263,BE +3647989264,3647989375,DE +3647989376,3647989759,BE 3647989760,3647990271,DE 3647990272,3647990527,ES 3647990528,3647995903,DE @@ -150784,8 +153429,7 @@ 3648078496,3648078527,BE 3648078528,3648078591,BF 3648078592,3648078847,CG -3648078848,3648079103,BE -3648079104,3648080383,UG +3648078848,3648080383,BE 3648080384,3648080511,TZ 3648080512,3648080543,BF 3648080544,3648080639,TZ @@ -150806,7 +153450,7 @@ 3648082432,3648082479,ZM 3648082480,3648084991,BE 3648084992,3648085759,GB -3648085760,3648086015,LR +3648085760,3648086015,ZM 3648086016,3648090111,AT 3648090112,3648094207,RU 3648094208,3648102399,PL @@ -150890,7 +153534,9 @@ 3648184320,3648192511,RU 3648192512,3648196607,DE 3648196608,3648200703,IT -3648200704,3648208895,SE +3648200704,3648208479,SE +3648208480,3648208511,DK +3648208512,3648208895,SE 3648208896,3648212991,DE 3648212992,3648217087,RU 3648217088,3648221183,UA @@ -150967,12 +153613,9 @@ 3648417856,3648417919,GB 3648417920,3648418047,AT 3648418048,3648418079,GB -3648418080,3648418135,ES -3648418136,3648418143,GB -3648418144,3648418247,ES +3648418080,3648418247,ES 3648418248,3648418255,CH -3648418256,3648418263,ES -3648418264,3648418271,GB +3648418256,3648418271,GB 3648418272,3648418303,ES 3648418304,3648419327,GB 3648419328,3648419455,FR @@ -150981,8 +153624,8 @@ 3648419584,3648419839,GB 3648419840,3648419901,BE 3648419902,3648419903,GB -3648419904,3648419935,BE -3648419936,3648420095,GB +3648419904,3648419967,BE +3648419968,3648420095,GB 3648420096,3648420351,NL 3648420352,3648420863,GB 3648420864,3648421119,US @@ -151010,9 +153653,7 @@ 3648465272,3648465823,FI 3648465824,3648465855,AX 3648465856,3648466943,FI -3648466944,3648469263,DE -3648469264,3648469271,NL -3648469272,3648469295,DE +3648466944,3648469295,DE 3648469296,3648469311,AT 3648469312,3648471039,DE 3648471040,3648475135,PL @@ -151058,8 +153699,15 @@ 3649709824,3649765375,GB 3649765376,3649830911,EG 3649830912,3649835007,NL -3649835008,3649839103,ES -3649839104,3649847295,GB +3649835008,3649838079,ES +3649838080,3649839103,NL +3649839104,3649840127,GB +3649840128,3649840383,NL +3649840384,3649843199,GB +3649843200,3649845247,NL +3649845248,3649845759,GB +3649845760,3649847039,NL +3649847040,3649847295,GB 3649847296,3649855487,DE 3649855488,3649856511,GB 3649856512,3649857023,US @@ -151206,7 +153854,8 @@ 3650367488,3650371583,RU 3650371584,3650375679,ES 3650375680,3650379775,NL -3650379776,3650387967,IT +3650379776,3650381823,DE +3650381824,3650387967,IT 3650387968,3650392063,DE 3650392064,3650396159,NO 3650396160,3650404351,NL @@ -151215,7 +153864,9 @@ 3650416640,3650420735,BE 3650420736,3650424831,ES 3650424832,3650428927,RU -3650428928,3650433023,NL +3650428928,3650432431,NL +3650432432,3650432447,DE +3650432448,3650433023,NL 3650433024,3650437119,FI 3650437120,3650441215,NL 3650441216,3650445311,IT @@ -151325,7 +153976,9 @@ 3651087872,3651088127,DE 3651088128,3651088383,IE 3651088384,3651088639,GR -3651088640,3651090919,DE +3651088640,3651090767,DE +3651090768,3651090775,GB +3651090776,3651090919,DE 3651090920,3651090959,IE 3651090960,3651098111,DE 3651098112,3651098367,IE @@ -151380,8 +154033,8 @@ 3651204352,3651204607,PL 3651204608,3651205119,ES 3651205120,3651205375,GB -3651205376,3651205631,ES -3651205632,3651206143,DE +3651205376,3651205887,ES +3651205888,3651206143,DE 3651206144,3651206399,PL 3651206400,3651207167,DE 3651207168,3651207199,GB @@ -151831,7 +154484,9 @@ 3653407072,3653407103,A2 3653407104,3653407111,UG 3653407112,3653407119,ZM -3653407120,3653407167,A2 +3653407120,3653407135,A2 +3653407136,3653407151,MZ +3653407152,3653407167,A2 3653407168,3653407231,NG 3653407232,3653407391,A2 3653407392,3653407399,NG @@ -151940,11 +154595,7 @@ 3653472592,3653472767,AF 3653472768,3653472775,NL 3653472776,3653472791,AF -3653472792,3653472799,NL -3653472800,3653472807,AF -3653472808,3653472815,NL -3653472816,3653472823,AF -3653472824,3653472831,NL +3653472792,3653472831,NL 3653472832,3653472871,AF 3653472872,3653472879,NL 3653472880,3653472915,AF @@ -152029,12 +154680,11 @@ 3653664768,3653664895,DE 3653664896,3653664911,FR 3653664912,3653665023,NL -3653665024,3653665071,DE -3653665072,3653665151,NL +3653665024,3653665087,DE +3653665088,3653665151,NL 3653665152,3653665279,DE -3653665280,3653666815,NL -3653666816,3653667327,DE -3653667328,3653668863,NL +3653665280,3653665791,NL +3653665792,3653668863,DE 3653668864,3653672959,SE 3653672960,3653681151,RU 3653681152,3653685247,ES @@ -152231,9 +154881,7 @@ 3673817088,3673882623,HK 3673882624,3673948159,JP 3673948160,3674210303,HK -3674210304,3674431743,JP -3674431744,3674431999,UA -3674432000,3678404607,JP +3674210304,3678404607,JP 3678404608,3678535679,IN 3678535680,3678666751,JP 3678666752,3678928895,TW @@ -152475,8 +155123,8 @@ 3745513472,3749838847,CN 3749838848,3749839871,SG 3749839872,3749840895,IN -3749840896,3749841919,PH -3749841920,3749846015,AU +3749841920,3749842943,AU +3749843968,3749846015,AU 3749846016,3749847039,IN 3749847040,3749855231,HK 3749855232,3749969919,KR diff --git a/src/or/Makefile.am b/src/or/Makefile.am index a9ac3cdee1..a5682081ae 100644 --- a/src/or/Makefile.am +++ b/src/or/Makefile.am @@ -7,7 +7,7 @@ else tor_platform_source= endif -EXTRA_DIST=ntmain.c or_sha1.i +EXTRA_DIST=ntmain.c or_sha1.i Makefile.nmake if USE_EXTERNAL_EVDNS evdns_source= @@ -15,16 +15,46 @@ else evdns_source=eventdns.c endif -libtor_a_SOURCES = buffers.c circuitbuild.c circuitlist.c \ - circuituse.c command.c config.c \ - connection.c connection_edge.c connection_or.c control.c \ - cpuworker.c directory.c dirserv.c dirvote.c \ - dns.c dnsserv.c geoip.c hibernate.c main.c $(tor_platform_source) \ - microdesc.c \ - networkstatus.c onion.c policies.c \ - reasons.c relay.c rendcommon.c rendclient.c rendmid.c \ - rendservice.c rephist.c router.c routerlist.c routerparse.c \ - $(evdns_source) config_codedigest.c +libtor_a_SOURCES = \ + buffers.c \ + circuitbuild.c \ + circuitlist.c \ + circuituse.c \ + command.c \ + config.c \ + connection.c \ + connection_edge.c \ + connection_or.c \ + control.c \ + cpuworker.c \ + directory.c \ + dirserv.c \ + dirvote.c \ + dns.c \ + dnsserv.c \ + geoip.c \ + hibernate.c \ + main.c \ + microdesc.c \ + networkstatus.c \ + nodelist.c \ + onion.c \ + transports.c \ + policies.c \ + reasons.c \ + relay.c \ + rendclient.c \ + rendcommon.c \ + rendmid.c \ + rendservice.c \ + rephist.c \ + router.c \ + routerlist.c \ + routerparse.c \ + status.c \ + $(evdns_source) \ + $(tor_platform_source) \ + config_codedigest.c #libtor_a_LIBADD = ../common/libor.a ../common/libor-crypto.a \ # ../common/libor-event.a @@ -40,18 +70,55 @@ AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ # This seems to matter nowhere but on windows, but I assure you that it # matters a lot there, and is quite hard to debug if you forget to do it. + tor_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@ tor_LDADD = ./libtor.a ../common/libor.a ../common/libor-crypto.a \ ../common/libor-event.a \ - @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ - -noinst_HEADERS = buffers.h circuitbuild.h circuitlist.h circuituse.h \ - command.h config.h connection_edge.h connection.h connection_or.h \ - control.h cpuworker.h directory.h dirserv.h dirvote.h dns.h \ - dnsserv.h geoip.h hibernate.h main.h microdesc.h networkstatus.h \ - ntmain.h onion.h policies.h reasons.h relay.h rendclient.h \ - rendcommon.h rendmid.h rendservice.h rephist.h router.h routerlist.h \ - routerparse.h or.h eventdns.h eventdns_tor.h micro-revision.i + @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ + @TOR_LIB_WS32@ @TOR_LIB_GDI@ + +noinst_HEADERS = \ + buffers.h \ + circuitbuild.h \ + circuitlist.h \ + circuituse.h \ + command.h \ + config.h \ + connection.h \ + connection_edge.h \ + connection_or.h \ + control.h \ + cpuworker.h \ + directory.h \ + dirserv.h \ + dirvote.h \ + dns.h \ + dnsserv.h \ + eventdns.h \ + eventdns_tor.h \ + geoip.h \ + hibernate.h \ + main.h \ + microdesc.h \ + networkstatus.h \ + nodelist.h \ + ntmain.h \ + onion.h \ + or.h \ + transports.h \ + policies.h \ + reasons.h \ + relay.h \ + rendclient.h \ + rendcommon.h \ + rendmid.h \ + rendservice.h \ + rephist.h \ + router.h \ + routerlist.h \ + routerparse.h \ + status.h \ + micro-revision.i config_codedigest.o: or_sha1.i @@ -59,8 +126,9 @@ tor_main.o: micro-revision.i micro-revision.i: FORCE @rm -f micro-revision.tmp; \ - if test -d ../../.git && test -x "`which git 2>&1;true`"; then \ - HASH="`git rev-parse --short=16 HEAD`"; \ + if test -d "$(top_srcdir)/.git" && \ + test -x "`which git 2>&1;true`"; then \ + HASH="`cd "$(top_srcdir)" && git rev-parse --short=16 HEAD`"; \ echo \"$$HASH\" > micro-revision.tmp; \ fi; \ if test ! -f micro-revision.tmp ; then \ @@ -72,11 +140,13 @@ micro-revision.i: FORCE mv micro-revision.tmp micro-revision.i; \ fi; true -or_sha1.i: $(tor_SOURCES) +or_sha1.i: $(tor_SOURCES) $(libtor_a_SOURCES) if test "@SHA1SUM@" != none; then \ - @SHA1SUM@ $(tor_SOURCES) | @SED@ -n 's/^\(.*\)$$/"\1\\n"/p' > or_sha1.i; \ + (cd "$(srcdir)" && @SHA1SUM@ $(tor_SOURCES) $(libtor_a_SOURCES)) | \ + @SED@ -n 's/^\(.*\)$$/"\1\\n"/p' > or_sha1.i; \ elif test "@OPENSSL@" != none; then \ - @OPENSSL@ sha1 $(tor_SOURCES) | @SED@ -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > or_sha1.i; \ + (cd "$(srcdir)" && @OPENSSL@ sha1 $(tor_SOURCES) $(libtor_a_SOURCES)) | \ + @SED@ -n 's/SHA1(\(.*\))= \(.*\)/"\2 \1\\n"/p' > or_sha1.i; \ else \ rm or_sha1.i; \ touch or_sha1.i; \ diff --git a/src/or/Makefile.nmake b/src/or/Makefile.nmake new file mode 100644 index 0000000000..919edbbf22 --- /dev/null +++ b/src/or/Makefile.nmake @@ -0,0 +1,28 @@ +all: tor.exe
+
+CFLAGS = /I ..\win32 /I ..\..\..\build-alpha\include /I ..\common
+
+LIBS = ..\..\..\build-alpha\lib\libevent.a \
+ ..\..\..\build-alpha\lib\libcrypto.a \
+ ..\..\..\build-alpha\lib\libssl.a \
+ ..\..\..\build-alpha\lib\libz.a \
+ ws2_32.lib advapi32.lib shell32.lib
+
+LIBTOR_OBJECTS = buffers.obj circuitbuild.obj circuitlist.obj circuituse.obj \
+ command.obj config.obj connection.obj connection_edge.obj \
+ connection_or.obj control.obj cpuworker.obj directory.obj \
+ dirserv.obj dirvote.obj dns.obj dnsserv.obj geoip.obj \
+ hibernate.obj main.obj microdesc.obj networkstatus.obj \
+ nodelist.obj onion.obj policies.obj reasons.obj relay.obj \
+ rendclient.obj rendcommon.obj rendmid.obj rendservice.obj \
+ rephist.obj router.obj routerlist.obj routerparse.obj status.obj \
+ config_codedigest.obj ntmain.obj
+
+libtor.lib: $(LIBTOR_OBJECTS)
+ lib $(LIBTOR_OBJECTS) /out:libtor.lib
+
+tor.exe: libtor.lib tor_main.obj
+ $(CC) $(CFLAGS) $(LIBS) libtor.lib ..\common\*.lib tor_main.obj
+
+clean:
+ del $(LIBTOR_OBJECTS) *.lib tor.exe
diff --git a/src/or/buffers.c b/src/or/buffers.c index 05163637f2..f4aac0f0e4 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -23,9 +23,6 @@ #ifdef HAVE_UNISTD_H #include <unistd.h> #endif -#ifdef HAVE_SYS_UIO_H -#include <sys/uio.h> -#endif //#define PARANOIA @@ -56,6 +53,13 @@ * forever. */ +static int parse_socks(const char *data, size_t datalen, socks_request_t *req, + int log_sockstype, int safe_socks, ssize_t *drain_out, + size_t *want_length_out); +static int parse_socks_client(const uint8_t *data, size_t datalen, + int state, char **reason, + ssize_t *drain_out); + /* Chunk manipulation functions */ /** A single chunk on a buffer or in a freelist. */ @@ -64,8 +68,8 @@ typedef struct chunk_t { size_t datalen; /**< The number of bytes stored in this chunk */ size_t memlen; /**< The number of usable bytes of storage in <b>mem</b>. */ char *data; /**< A pointer to the first byte of data stored in <b>mem</b>. */ - char mem[1]; /**< The actual memory used for storage in this chunk. May be - * more than one byte long. */ + char mem[FLEXIBLE_ARRAY_MEMBER]; /**< The actual memory used for storage in + * this chunk. */ } chunk_t; #define CHUNK_HEADER_LEN STRUCT_OFFSET(chunk_t, mem[0]) @@ -547,11 +551,45 @@ buf_free(buf_t *buf) { if (!buf) return; + buf_clear(buf); buf->magic = 0xdeadbeef; tor_free(buf); } +/** Return a new copy of <b>in_chunk</b> */ +static chunk_t * +chunk_copy(const chunk_t *in_chunk) +{ + chunk_t *newch = tor_memdup(in_chunk, CHUNK_ALLOC_SIZE(in_chunk->memlen)); + newch->next = NULL; + if (in_chunk->data) { + off_t offset = in_chunk->data - in_chunk->mem; + newch->data = newch->mem + offset; + } + return newch; +} + +/** Return a new copy of <b>buf</b> */ +buf_t * +buf_copy(const buf_t *buf) +{ + chunk_t *ch; + buf_t *out = buf_new(); + out->default_chunk_size = buf->default_chunk_size; + for (ch = buf->head; ch; ch = ch->next) { + chunk_t *newch = chunk_copy(ch); + if (out->tail) { + out->tail->next = newch; + out->tail = newch; + } else { + out->head = out->tail = newch; + } + } + out->datalen = buf->datalen; + return out; +} + /** Append a new chunk with enough capacity to hold <b>capacity</b> bytes to * the tail of <b>buf</b>. If <b>capped</b>, don't allocate a chunk bigger * than MAX_CHUNK_ALLOC. */ @@ -578,10 +616,6 @@ buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped) return chunk; } -/** If we're using readv and writev, how many chunks are we willing to - * read/write at a time? */ -#define N_IOV 3 - /** Read up to <b>at_most</b> bytes from the socket <b>fd</b> into * <b>chunk</b> (which must be on <b>buf</b>). If we get an EOF, set * *<b>reached_eof</b> to 1. Return -1 on error, 0 on eof or blocking, @@ -591,25 +625,9 @@ read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most, int *reached_eof, int *socket_error) { ssize_t read_result; -#if 0 && defined(HAVE_READV) && !defined(WIN32) - struct iovec iov[N_IOV]; - int i; - size_t remaining = at_most; - for (i=0; chunk && i < N_IOV && remaining; ++i) { - iov[i].iov_base = CHUNK_WRITE_PTR(chunk); - if (remaining > CHUNK_REMAINING_CAPACITY(chunk)) - iov[i].iov_len = CHUNK_REMAINING_CAPACITY(chunk); - else - iov[i].iov_len = remaining; - remaining -= iov[i].iov_len; - chunk = chunk->next; - } - read_result = readv(fd, iov, i); -#else if (at_most > CHUNK_REMAINING_CAPACITY(chunk)) at_most = CHUNK_REMAINING_CAPACITY(chunk); read_result = tor_socket_recv(fd, CHUNK_WRITE_PTR(chunk), at_most, 0); -#endif if (read_result < 0) { int e = tor_socket_errno(fd); @@ -628,14 +646,6 @@ read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most, return 0; } else { /* actually got bytes. */ buf->datalen += read_result; -#if 0 && defined(HAVE_READV) && !defined(WIN32) - while ((size_t)read_result > CHUNK_REMAINING_CAPACITY(chunk)) { - chunk->datalen += CHUNK_REMAINING_CAPACITY(chunk); - read_result -= CHUNK_REMAINING_CAPACITY(chunk); - chunk = chunk->next; - tor_assert(chunk); - } -#endif chunk->datalen += read_result; log_debug(LD_NET,"Read %ld bytes. %d on inbuf.", (long)read_result, (int)buf->datalen); @@ -771,25 +781,10 @@ flush_chunk(tor_socket_t s, buf_t *buf, chunk_t *chunk, size_t sz, size_t *buf_flushlen) { ssize_t write_result; -#if 0 && defined(HAVE_WRITEV) && !defined(WIN32) - struct iovec iov[N_IOV]; - int i; - size_t remaining = sz; - for (i=0; chunk && i < N_IOV && remaining; ++i) { - iov[i].iov_base = chunk->data; - if (remaining > chunk->datalen) - iov[i].iov_len = chunk->datalen; - else - iov[i].iov_len = remaining; - remaining -= iov[i].iov_len; - chunk = chunk->next; - } - write_result = writev(s, iov, i); -#else + if (sz > chunk->datalen) sz = chunk->datalen; write_result = tor_socket_send(s, chunk->data, sz, 0); -#endif if (write_result < 0) { int e = tor_socket_errno(s); @@ -1010,6 +1005,33 @@ fetch_from_buf(char *string, size_t string_len, buf_t *buf) return (int)buf->datalen; } +/** True iff the cell command <b>command</b> is one that implies a + * variable-length cell in Tor link protocol <b>linkproto</b>. */ +static inline int +cell_command_is_var_length(uint8_t command, int linkproto) +{ + /* If linkproto is v2 (2), CELL_VERSIONS is the only variable-length cells + * work as implemented here. If it's 1, there are no variable-length cells. + * Tor does not support other versions right now, and so can't negotiate + * them. + */ + switch (linkproto) { + case 1: + /* Link protocol version 1 has no variable-length cells. */ + return 0; + case 2: + /* In link protocol version 2, VERSIONS is the only variable-length cell */ + return command == CELL_VERSIONS; + case 0: + case 3: + default: + /* In link protocol version 3 and later, and in version "unknown", + * commands 128 and higher indicate variable-length. VERSIONS is + * grandfathered in. */ + return command == CELL_VERSIONS || command >= 128; + } +} + /** Check <b>buf</b> for a variable-length cell according to the rules of link * protocol version <b>linkproto</b>. If one is found, pull it off the buffer * and assign a newly allocated var_cell_t to *<b>out</b>, and return 1. @@ -1024,12 +1046,6 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto) var_cell_t *result; uint8_t command; uint16_t length; - /* If linkproto is unknown (0) or v2 (2), variable-length cells work as - * implemented here. If it's 1, there are no variable-length cells. Tor - * does not support other versions right now, and so can't negotiate them. - */ - if (linkproto == 1) - return 0; check(); *out = NULL; if (buf->datalen < VAR_CELL_HEADER_SIZE) @@ -1037,7 +1053,7 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto) peek_from_buf(hdr, sizeof(hdr), buf); command = get_uint8(hdr+2); - if (!(CELL_COMMAND_IS_VAR_LENGTH(command))) + if (!(cell_command_is_var_length(command, linkproto))) return 0; length = ntohs(get_uint16(hdr+3)); @@ -1056,6 +1072,91 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto) return 1; } +#ifdef USE_BUFFEREVENTS +/** Try to read <b>n</b> bytes from <b>buf</b> at <b>pos</b> (which may be + * NULL for the start of the buffer), copying the data only if necessary. Set + * *<b>data_out</b> to a pointer to the desired bytes. Set <b>free_out</b> + * to 1 if we needed to malloc *<b>data</b> because the original bytes were + * noncontiguous; 0 otherwise. Return the number of bytes actually available + * at *<b>data_out</b>. + */ +static ssize_t +inspect_evbuffer(struct evbuffer *buf, char **data_out, size_t n, + int *free_out, struct evbuffer_ptr *pos) +{ + int n_vecs, i; + + if (evbuffer_get_length(buf) < n) + n = evbuffer_get_length(buf); + if (n == 0) + return 0; + n_vecs = evbuffer_peek(buf, n, pos, NULL, 0); + tor_assert(n_vecs > 0); + if (n_vecs == 1) { + struct evbuffer_iovec v; + i = evbuffer_peek(buf, n, pos, &v, 1); + tor_assert(i == 1); + *data_out = v.iov_base; + *free_out = 0; + return v.iov_len; + } else { + ev_ssize_t copied; + *data_out = tor_malloc(n); + *free_out = 1; + copied = evbuffer_copyout(buf, *data_out, n); + tor_assert(copied >= 0 && (size_t)copied == n); + return copied; + } +} + +/** As fetch_var_cell_from_buf, buf works on an evbuffer. */ +int +fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out, + int linkproto) +{ + char *hdr = NULL; + int free_hdr = 0; + size_t n; + size_t buf_len; + uint8_t command; + uint16_t cell_length; + var_cell_t *cell; + int result = 0; + + *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, linkproto))) { + 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 +1164,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 +1399,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 +1501,7 @@ log_unsafe_socks_warning(int socks_protocol, const char *address, { static ratelim_t socks_ratelim = RATELIM_INIT(SOCKS_WARN_INTERVAL); - or_options_t *options = get_options(); + const or_options_t *options = get_options(); char *m = NULL; if (! options->WarnUnsafeSocks) return; @@ -1340,6 +1528,31 @@ log_unsafe_socks_warning(int socks_protocol, const char *address, * actually significantly higher than the longest possible socks message. */ #define MAX_SOCKS_MESSAGE_LEN 512 +/** Return a new socks_request_t. */ +socks_request_t * +socks_request_new(void) +{ + return tor_malloc_zero(sizeof(socks_request_t)); +} + +/** Free all storage held in the socks_request_t <b>req</b>. */ +void +socks_request_free(socks_request_t *req) +{ + if (!req) + return; + if (req->username) { + memset(req->username, 0x10, req->usernamelen); + tor_free(req->username); + } + if (req->password) { + memset(req->password, 0x04, req->passwordlen); + tor_free(req->password); + } + memset(req, 0xCC, sizeof(socks_request_t)); + tor_free(req); +} + /** There is a (possibly incomplete) socks handshake on <b>buf</b>, of one * of the forms * - socks4: "socksheader username\\0" @@ -1369,59 +1582,241 @@ int fetch_from_buf_socks(buf_t *buf, socks_request_t *req, int log_sockstype, int safe_socks) { + int res; + ssize_t n_drain; + size_t want_length = 128; + + if (buf->datalen < 2) /* version and another byte */ + return 0; + + do { + n_drain = 0; + buf_pullup(buf, want_length, 0); + tor_assert(buf->head && buf->head->datalen >= 2); + want_length = 0; + + res = parse_socks(buf->head->data, buf->head->datalen, req, log_sockstype, + safe_socks, &n_drain, &want_length); + + if (n_drain < 0) + buf_clear(buf); + else if (n_drain > 0) + buf_remove_from_front(buf, n_drain); + + } while (res == 0 && buf->head && want_length < buf->datalen && + buf->datalen >= 2); + + return res; +} + +#ifdef USE_BUFFEREVENTS +/* As fetch_from_buf_socks(), but targets an evbuffer instead. */ +int +fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req, + int log_sockstype, int safe_socks) +{ + char *data; + ssize_t n_drain; + size_t datalen, buflen, want_length; + int res; + + buflen = evbuffer_get_length(buf); + if (buflen < 2) + return 0; + + { + /* See if we can find the socks request in the first chunk of the buffer. + */ + struct evbuffer_iovec v; + int i; + n_drain = 0; + i = evbuffer_peek(buf, -1, NULL, &v, 1); + tor_assert(i == 1); + data = v.iov_base; + datalen = v.iov_len; + want_length = 0; + + res = parse_socks(data, datalen, req, log_sockstype, + safe_socks, &n_drain, &want_length); + + if (n_drain < 0) + evbuffer_drain(buf, evbuffer_get_length(buf)); + else if (n_drain > 0) + evbuffer_drain(buf, n_drain); + + if (res) + return res; + } + + /* Okay, the first chunk of the buffer didn't have a complete socks request. + * That means that either we don't have a whole socks request at all, or + * it's gotten split up. We're going to try passing parse_socks() bigger + * and bigger chunks until either it says "Okay, I got it", or it says it + * will need more data than we currently have. */ + + /* Loop while we have more data that we haven't given parse_socks() yet. */ + do { + int free_data = 0; + const size_t last_wanted = want_length; + n_drain = 0; + data = NULL; + datalen = inspect_evbuffer(buf, &data, want_length, &free_data, NULL); + + want_length = 0; + res = parse_socks(data, datalen, req, log_sockstype, + safe_socks, &n_drain, &want_length); + + if (free_data) + tor_free(data); + + if (n_drain < 0) + evbuffer_drain(buf, evbuffer_get_length(buf)); + else if (n_drain > 0) + evbuffer_drain(buf, n_drain); + + if (res == 0 && n_drain == 0 && want_length <= last_wanted) { + /* If we drained nothing, and we didn't ask for more than last time, + * then we probably wanted more data than the buffer actually had, + * and we're finding out that we're not satisified with it. It's + * time to break until we have more data. */ + break; + } + + buflen = evbuffer_get_length(buf); + } while (res == 0 && want_length <= buflen && buflen >= 2); + + return res; +} +#endif + +/** Implementation helper to implement fetch_from_*_socks. Instead of looking + * at a buffer's contents, we look at the <b>datalen</b> bytes of data in + * <b>data</b>. Instead of removing data from the buffer, we set + * <b>drain_out</b> to the amount of data that should be removed (or -1 if the + * buffer should be cleared). Instead of pulling more data into the first + * chunk of the buffer, we set *<b>want_length_out</b> to the number of bytes + * we'd like to see in the input buffer, if they're available. */ +static int +parse_socks(const char *data, size_t datalen, socks_request_t *req, + int log_sockstype, int safe_socks, ssize_t *drain_out, + size_t *want_length_out) +{ unsigned int len; char tmpbuf[TOR_ADDR_BUF_LEN+1]; tor_addr_t destaddr; uint32_t destip; uint8_t socksver; - enum {socks4, socks4a} socks4_prot = socks4a; char *next, *startaddr; + unsigned char usernamelen, passlen; struct in_addr in; - if (buf->datalen < 2) /* version and another byte */ + if (datalen < 2) { + /* We always need at least 2 bytes. */ + *want_length_out = 2; return 0; + } - buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN, 0); - tor_assert(buf->head && buf->head->datalen >= 2); + if (req->socks_version == 5 && !req->got_auth) { + /* See if we have received authentication. Strictly speaking, we should + also check whether we actually negotiated username/password + authentication. But some broken clients will send us authentication + even if we negotiated SOCKS_NO_AUTH. */ + if (*data == 1) { /* username/pass version 1 */ + /* Format is: authversion [1 byte] == 1 + usernamelen [1 byte] + username [usernamelen bytes] + passlen [1 byte] + password [passlen bytes] */ + usernamelen = (unsigned char)*(data + 1); + if (datalen < 2u + usernamelen + 1u) { + *want_length_out = 2u + usernamelen + 1u; + return 0; + } + passlen = (unsigned char)*(data + 2u + usernamelen); + if (datalen < 2u + usernamelen + 1u + passlen) { + *want_length_out = 2u + usernamelen + 1u + passlen; + return 0; + } + req->replylen = 2; /* 2 bytes of response */ + req->reply[0] = 5; + req->reply[1] = 0; /* authentication successful */ + log_debug(LD_APP, + "socks5: Accepted username/password without checking."); + if (usernamelen) { + req->username = tor_memdup(data+2u, usernamelen); + req->usernamelen = usernamelen; + } + if (passlen) { + req->password = tor_memdup(data+3u+usernamelen, passlen); + req->passwordlen = passlen; + } + *drain_out = 2u + usernamelen + 1u + passlen; + req->got_auth = 1; + *want_length_out = 7; /* Minimal socks5 sommand. */ + return 0; + } else if (req->auth_type == SOCKS_USER_PASS) { + /* unknown version byte */ + log_warn(LD_APP, "Socks5 username/password version %d not recognized; " + "rejecting.", (int)*data); + return -1; + } + } - socksver = *buf->head->data; + socksver = *data; switch (socksver) { /* which version of socks? */ - case 5: /* socks5 */ if (req->socks_version != 5) { /* we need to negotiate a method */ - unsigned char nummethods = (unsigned char)*(buf->head->data+1); + unsigned char nummethods = (unsigned char)*(data+1); + int r=0; tor_assert(!req->socks_version); - if (buf->datalen < 2u+nummethods) + if (datalen < 2u+nummethods) { + *want_length_out = 2u+nummethods; return 0; - buf_pullup(buf, 2u+nummethods, 0); - if (!nummethods || !memchr(buf->head->data+2, 0, nummethods)) { + } + if (!nummethods) + return -1; + req->replylen = 2; /* 2 bytes of response */ + req->reply[0] = 5; /* socks5 reply */ + if (memchr(data+2, SOCKS_NO_AUTH, nummethods)) { + req->reply[1] = SOCKS_NO_AUTH; /* tell client to use "none" auth + method */ + req->socks_version = 5; /* remember we've already negotiated auth */ + log_debug(LD_APP,"socks5: accepted method 0 (no authentication)"); + r=0; + } else if (memchr(data+2, SOCKS_USER_PASS, nummethods)) { + req->auth_type = SOCKS_USER_PASS; + req->reply[1] = SOCKS_USER_PASS; /* tell client to use "user/pass" + auth method */ + req->socks_version = 5; /* remember we've already negotiated auth */ + log_debug(LD_APP,"socks5: accepted method 2 (username/password)"); + r=0; + } else { log_warn(LD_APP, - "socks5: offered methods don't include 'no auth'. " - "Rejecting."); - req->replylen = 2; /* 2 bytes of response */ - req->reply[0] = 5; + "socks5: offered methods don't include 'no auth' or " + "username/password. Rejecting."); req->reply[1] = '\xFF'; /* reject all methods */ - return -1; + r=-1; } - /* remove packet from buf. also remove any other extraneous - * bytes, to support broken socks clients. */ - buf_clear(buf); + /* Remove packet from buf. Some SOCKS clients will have sent extra + * junk at this point; let's hope it's an authentication message. */ + *drain_out = 2u + nummethods; - req->replylen = 2; /* 2 bytes of response */ - req->reply[0] = 5; /* socks5 reply */ - req->reply[1] = 0; /* tell client to use "none" auth method */ - req->socks_version = 5; /* remember we've already negotiated auth */ - log_debug(LD_APP,"socks5: accepted method 0"); - return 0; + return r; + } + if (req->auth_type != SOCKS_NO_AUTH && !req->got_auth) { + log_warn(LD_APP, + "socks5: negotiated authentication, but none provided"); + return -1; } /* we know the method; read in the request */ log_debug(LD_APP,"socks5: checking request"); - if (buf->datalen < 8) /* basic info plus >=2 for addr plus 2 for port */ + if (datalen < 7) {/* basic info plus >=1 for addr plus 2 for port */ + *want_length_out = 7; return 0; /* not yet */ - tor_assert(buf->head->datalen >= 8); - req->command = (unsigned char) *(buf->head->data+1); + } + req->command = (unsigned char) *(data+1); if (req->command != SOCKS_COMMAND_CONNECT && req->command != SOCKS_COMMAND_RESOLVE && req->command != SOCKS_COMMAND_RESOLVE_PTR) { @@ -1430,19 +1825,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 +1851,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 +1868,21 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, "hostname type. Rejecting."); return -1; } - len = (unsigned char)*(buf->head->data+4); - if (buf->datalen < 7+len) /* addr/port there? */ + len = (unsigned char)*(data+4); + if (datalen < 7+len) { /* addr/port there? */ + *want_length_out = 7+len; return 0; /* not yet */ - buf_pullup(buf, 7+len, 0); - tor_assert(buf->head->datalen >= 7+len); + } if (len+1 > MAX_SOCKS_ADDR_LEN) { log_warn(LD_APP, "socks5 hostname is %d bytes, which doesn't fit in " "%d. Rejecting.", len+1,MAX_SOCKS_ADDR_LEN); return -1; } - memcpy(req->address,buf->head->data+5,len); + memcpy(req->address,data+5,len); req->address[len] = 0; - req->port = ntohs(get_uint16(buf->head->data+5+len)); - buf_remove_from_front(buf, 5+len+2); + req->port = ntohs(get_uint16(data+5+len)); + *drain_out = 5+len+2; if (!tor_strisprint(req->address) || strchr(req->address,'\"')) { log_warn(LD_PROTOCOL, "Your application (using socks5 to port %d) gave Tor " @@ -1495,25 +1892,29 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, } if (log_sockstype) log_notice(LD_APP, - "Your application (using socks5 to port %d) gave " - "Tor a hostname, which means Tor will do the DNS resolve " - "for you. This is good.", req->port); + "Your application (using socks5 to port %d) instructed " + "Tor to take care of the DNS resolution itself if " + "necessary. This is good.", req->port); return 1; default: /* unsupported */ log_warn(LD_APP,"socks5: unsupported address type %d. Rejecting.", - (int) *(buf->head->data+3)); + (int) *(data+3)); return -1; } tor_assert(0); - case 4: /* socks4 */ - /* http://archive.socks.permeo.com/protocol/socks4.protocol */ - /* http://archive.socks.permeo.com/protocol/socks4a.protocol */ + case 4: { /* socks4 */ + enum {socks4, socks4a} socks4_prot = socks4a; + const char *authstart, *authend; + /* http://ss5.sourceforge.net/socks4.protocol.txt */ + /* http://ss5.sourceforge.net/socks4A.protocol.txt */ req->socks_version = 4; - if (buf->datalen < SOCKS4_NETWORK_LEN) /* basic info available? */ + if (datalen < SOCKS4_NETWORK_LEN) {/* basic info available? */ + *want_length_out = SOCKS4_NETWORK_LEN; return 0; /* not yet */ - buf_pullup(buf, 1280, 0); - req->command = (unsigned char) *(buf->head->data+1); + } + // buf_pullup(buf, 1280, 0); + req->command = (unsigned char) *(data+1); if (req->command != SOCKS_COMMAND_CONNECT && req->command != SOCKS_COMMAND_RESOLVE) { /* not a connect or resolve? we don't support it. (No resolve_ptr with @@ -1523,8 +1924,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 +1945,20 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, socks4_prot = socks4; } - next = memchr(buf->head->data+SOCKS4_NETWORK_LEN, 0, - buf->head->datalen-SOCKS4_NETWORK_LEN); + authstart = data + SOCKS4_NETWORK_LEN; + next = memchr(authstart, 0, + datalen-SOCKS4_NETWORK_LEN); if (!next) { - if (buf->head->datalen >= 1024) { + if (datalen >= 1024) { log_debug(LD_APP, "Socks4 user name too long; rejecting."); return -1; } log_debug(LD_APP,"socks4: Username not here yet."); + *want_length_out = datalen+1024; /* More than we need, but safe */ return 0; } - tor_assert(next < CHUNK_WRITE_PTR(buf->head)); + authend = next; + tor_assert(next < data+datalen); startaddr = NULL; if (socks4_prot != socks4a && @@ -1565,18 +1969,20 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, return -1; } if (socks4_prot == socks4a) { - if (next+1 == CHUNK_WRITE_PTR(buf->head)) { + if (next+1 == data+datalen) { log_debug(LD_APP,"socks4: No part of destaddr here yet."); + *want_length_out = datalen + 1024; /* More than we need, but safe */ return 0; } startaddr = next+1; - next = memchr(startaddr, 0, CHUNK_WRITE_PTR(buf->head)-startaddr); + next = memchr(startaddr, 0, data + datalen - startaddr); if (!next) { - if (buf->head->datalen >= 1024) { + if (datalen >= 1024) { log_debug(LD_APP,"socks4: Destaddr too long."); return -1; } log_debug(LD_APP,"socks4: Destaddr not all here yet."); + *want_length_out = datalen + 1024; /* More than we need, but safe */ return 0; } if (MAX_SOCKS_ADDR_LEN <= next-startaddr) { @@ -1587,9 +1993,9 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, if (log_sockstype) log_notice(LD_APP, - "Your application (using socks4a to port %d) gave " - "Tor a hostname, which means Tor will do the DNS resolve " - "for you. This is good.", req->port); + "Your application (using socks4a to port %d) instructed " + "Tor to take care of the DNS resolution itself if " + "necessary. This is good.", req->port); } log_debug(LD_APP,"socks4: Everything is here. Success."); strlcpy(req->address, startaddr ? startaddr : tmpbuf, @@ -1601,15 +2007,20 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, req->port, escaped(req->address)); return -1; } + if (authend != authstart) { + req->got_auth = 1; + req->usernamelen = authend - authstart; + req->username = tor_memdup(authstart, authend - authstart); + } /* next points to the final \0 on inbuf */ - buf_remove_from_front(buf, next - buf->head->data + 1); + *drain_out = next - data + 1; return 1; - + } case 'G': /* get */ case 'H': /* head */ case 'P': /* put/post */ case 'C': /* connect */ - strlcpy(req->reply, + strlcpy((char*)req->reply, "HTTP/1.0 501 Tor is not an HTTP Proxy\r\n" "Content-Type: text/html; charset=iso-8859-1\r\n\r\n" "<html>\n" @@ -1635,14 +2046,15 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req, "</body>\n" "</html>\n" , MAX_SOCKS_REPLY_LEN); - req->replylen = strlen(req->reply)+1; + req->replylen = strlen((char*)req->reply)+1; /* fall through */ default: /* version is not socks4 or socks5 */ log_warn(LD_APP, "Socks version %d not recognized. (Tor is not an http proxy.)", - *(buf->head->data)); + *(data)); { - char *tmp = tor_strndup(buf->head->data, 8); /*XXXX what if longer?*/ + /* Tell the controller the first 8 bytes. */ + char *tmp = tor_strndup(data, datalen < 8 ? datalen : 8); control_event_client_status(LOG_WARN, "SOCKS_UNKNOWN_PROTOCOL DATA=\"%s\"", escaped(tmp)); @@ -1664,21 +2076,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 +2145,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 +2157,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 +2167,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 +2188,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 +2197,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 +2208,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 +2218,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 +2226,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 +2252,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 +2290,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 +2369,96 @@ write_to_buf_zlib(buf_t *buf, tor_zlib_state_t *state, return 0; } +#ifdef USE_BUFFEREVENTS +int +write_to_evbuffer_zlib(struct evbuffer *buf, tor_zlib_state_t *state, + const char *data, size_t data_len, + int done) +{ + char *next; + size_t old_avail, avail; + int over = 0, n; + struct evbuffer_iovec vec[1]; + do { + { + size_t cap = data_len / 4; + if (cap < 128) + cap = 128; + /* XXXX NM this strategy is fragmentation-prone. We should really have + * two iovecs, and write first into the one, and then into the + * second if the first gets full. */ + n = evbuffer_reserve_space(buf, cap, vec, 1); + tor_assert(n == 1); + } + + next = vec[0].iov_base; + avail = old_avail = vec[0].iov_len; + + switch (tor_zlib_process(state, &next, &avail, &data, &data_len, done)) { + case TOR_ZLIB_DONE: + over = 1; + break; + case TOR_ZLIB_ERR: + return -1; + case TOR_ZLIB_OK: + if (data_len == 0) + over = 1; + break; + case TOR_ZLIB_BUF_FULL: + if (avail) { + /* Zlib says we need more room (ZLIB_BUF_FULL). Start a new chunk + * automatically, whether were going to or not. */ + } + break; + } + + /* XXXX possible infinite loop on BUF_FULL. */ + vec[0].iov_len = old_avail - avail; + evbuffer_commit_space(buf, vec, 1); + + } while (!over); + check(); + return 0; +} +#endif + +/** Set *<b>output</b> to contain a copy of the data in *<b>input</b> */ +int +generic_buffer_set_to_copy(generic_buffer_t **output, + const generic_buffer_t *input) +{ +#ifdef USE_BUFFEREVENTS + struct evbuffer_ptr ptr; + size_t remaining = evbuffer_get_length(input); + if (*output) { + evbuffer_drain(*output, evbuffer_get_length(*output)); + } else { + if (!(*output = evbuffer_new())) + return -1; + } + evbuffer_ptr_set((struct evbuffer*)input, &ptr, 0, EVBUFFER_PTR_SET); + while (remaining) { + struct evbuffer_iovec v[4]; + int n_used, i; + n_used = evbuffer_peek((struct evbuffer*)input, -1, &ptr, v, 4); + if (n_used < 0) + return -1; + for (i=0;i<n_used;++i) { + evbuffer_add(*output, v[i].iov_base, v[i].iov_len); + tor_assert(v[i].iov_len <= remaining); + remaining -= v[i].iov_len; + evbuffer_ptr_set((struct evbuffer*)input, + &ptr, v[i].iov_len, EVBUFFER_PTR_ADD); + } + } +#else + if (*output) + buf_free(*output); + *output = buf_copy(input); +#endif + return 0; +} + /** Log an error and exit if <b>buf</b> is corrupted. */ void diff --git a/src/or/buffers.h b/src/or/buffers.h index 63fab4957a..7b2a2acc3c 100644 --- a/src/or/buffers.h +++ b/src/or/buffers.h @@ -16,6 +16,7 @@ buf_t *buf_new(void); buf_t *buf_new_with_capacity(size_t size); void buf_free(buf_t *buf); void buf_clear(buf_t *buf); +buf_t *buf_copy(const buf_t *buf); void buf_shrink(buf_t *buf); void buf_shrink_freelists(int free_all); void buf_dump_freelist_sizes(int severity); @@ -41,6 +42,8 @@ int fetch_from_buf_http(buf_t *buf, char **headers_out, size_t max_headerlen, char **body_out, size_t *body_used, size_t max_bodylen, int force_complete); +socks_request_t *socks_request_new(void); +void socks_request_free(socks_request_t *req); int fetch_from_buf_socks(buf_t *buf, socks_request_t *req, int log_sockstype, int safe_socks); int fetch_from_buf_socks_client(buf_t *buf, int state, char **reason); @@ -48,6 +51,41 @@ int fetch_from_buf_line(buf_t *buf, char *data_out, size_t *data_len); int peek_buf_has_control0_command(buf_t *buf); +#ifdef USE_BUFFEREVENTS +int fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out, + int linkproto); +int fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req, + int log_sockstype, int safe_socks); +int fetch_from_evbuffer_socks_client(struct evbuffer *buf, int state, + char **reason); +int fetch_from_evbuffer_http(struct evbuffer *buf, + char **headers_out, size_t max_headerlen, + char **body_out, size_t *body_used, size_t max_bodylen, + int force_complete); +int peek_evbuffer_has_control0_command(struct evbuffer *buf); +int write_to_evbuffer_zlib(struct evbuffer *buf, tor_zlib_state_t *state, + const char *data, size_t data_len, + int done); +#endif + +#ifdef USE_BUFFEREVENTS +#define generic_buffer_new() evbuffer_new() +#define generic_buffer_len(b) evbuffer_get_length((b)) +#define generic_buffer_add(b,dat,len) evbuffer_add((b),(dat),(len)) +#define generic_buffer_get(b,buf,buflen) evbuffer_remove((b),(buf),(buflen)) +#define generic_buffer_clear(b) evbuffer_drain((b), evbuffer_get_length((b))) +#define generic_buffer_free(b) evbuffer_free((b)) +#else +#define generic_buffer_new() buf_new() +#define generic_buffer_len(b) buf_datalen((b)) +#define generic_buffer_add(b,dat,len) write_to_buf((dat),(len),(b)) +#define generic_buffer_get(b,buf,buflen) fetch_from_buf((buf),(buflen),(b)) +#define generic_buffer_clear(b) buf_clear((b)) +#define generic_buffer_free(b) buf_free((b)) +#endif +int generic_buffer_set_to_copy(generic_buffer_t **output, + const generic_buffer_t *input); + void assert_buf_ok(buf_t *buf); #ifdef BUFFERS_PRIVATE diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index c6be46d858..b04bd10120 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -23,8 +23,10 @@ #include "directory.h" #include "main.h" #include "networkstatus.h" +#include "nodelist.h" #include "onion.h" #include "policies.h" +#include "transports.h" #include "relay.h" #include "rephist.h" #include "router.h" @@ -55,8 +57,8 @@ extern circuit_t *global_circuitlist; /** An entry_guard_t represents our information about a chosen long-term * first hop, known as a "helper" node in the literature. We can't just - * use a routerinfo_t, since we want to remember these even when we - * don't have a directory. */ + * use a node_t, since we want to remember these even when we + * don't have any directory info. */ typedef struct { char nickname[MAX_NICKNAME_LEN+1]; char identity[DIGEST_LEN]; @@ -78,6 +80,28 @@ typedef struct { * at which we last failed to connect to it. */ } entry_guard_t; +/** Information about a configured bridge. Currently this just matches the + * ones in the torrc file, but one day we may be able to learn about new + * bridges on our own, and remember them in the state file. */ +typedef struct { + /** Address of the bridge. */ + tor_addr_t addr; + /** TLS port for the bridge. */ + uint16_t port; + /** Boolean: We are re-parsing our bridge list, and we are going to remove + * this one if we don't find it in the list of configured bridges. */ + unsigned marked_for_removal : 1; + /** Expected identity digest, or all zero bytes if we don't know what the + * digest should be. */ + char identity[DIGEST_LEN]; + + /** Name of pluggable transport protocol taken from its config line. */ + char *transport_name; + + /** When should we next try to fetch a descriptor for this bridge? */ + download_status_t fetch_status; +} bridge_info_t; + /** A list of our chosen entry guards. */ static smartlist_t *entry_guards = NULL; /** A value of 1 means that the entry_guards list has changed @@ -95,11 +119,13 @@ static int circuit_deliver_create_cell(circuit_t *circ, static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit); static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath); static int onion_extend_cpath(origin_circuit_t *circ); -static int count_acceptable_routers(smartlist_t *routers); +static int count_acceptable_nodes(smartlist_t *routers); static int onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice); static void entry_guards_changed(void); +static void bridge_free(bridge_info_t *bridge); + /** * This function decides if CBT learning should be disabled. It returns * true if one or more of the following four conditions are met: @@ -1381,7 +1407,7 @@ circuit_build_times_set_timeout_worker(circuit_build_times_t *cbt) cbt->close_ms = MAX(cbt->close_ms, circuit_build_times_initial_timeout()); if (cbt->timeout_ms > max_time) { - log_notice(LD_CIRC, + log_info(LD_CIRC, "Circuit build timeout of %dms is beyond the maximum build " "time we have ever observed. Capping it to %dms.", (int)cbt->timeout_ms, max_time); @@ -1429,7 +1455,7 @@ circuit_build_times_set_timeout(circuit_build_times_t *cbt) timeout_rate = circuit_build_times_timeout_rate(cbt); if (prev_timeout > tor_lround(cbt->timeout_ms/1000)) { - log_notice(LD_CIRC, + log_info(LD_CIRC, "Based on %d circuit times, it looks like we don't need to " "wait so long for circuits to finish. We will now assume a " "circuit is too slow to use after waiting %ld seconds.", @@ -1440,7 +1466,7 @@ circuit_build_times_set_timeout(circuit_build_times_t *cbt) cbt->timeout_ms, cbt->close_ms, cbt->Xm, cbt->alpha, timeout_rate); } else if (prev_timeout < tor_lround(cbt->timeout_ms/1000)) { - log_notice(LD_CIRC, + log_info(LD_CIRC, "Based on %d circuit times, it looks like we need to wait " "longer for circuits to finish. We will now assume a " "circuit is too slow to use after waiting %ld seconds.", @@ -1532,10 +1558,9 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names) hop = circ->cpath; do { - routerinfo_t *ri; - routerstatus_t *rs; char *elt; const char *id; + const node_t *node; if (!hop) break; if (!verbose && hop->state != CPATH_STATE_OPEN) @@ -1545,10 +1570,8 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names) id = hop->extend_info->identity_digest; if (verbose_names) { elt = tor_malloc(MAX_VERBOSE_NICKNAME_LEN+1); - if ((ri = router_get_by_digest(id))) { - router_get_verbose_nickname(elt, ri); - } else if ((rs = router_get_consensus_status_by_id(id))) { - routerstatus_get_verbose_nickname(elt, rs); + if ((node = node_get_by_id(id))) { + node_get_verbose_nickname(node, elt); } else if (is_legal_nickname(hop->extend_info->nickname)) { elt[0] = '$'; base16_encode(elt+1, HEX_DIGEST_LEN+1, id, DIGEST_LEN); @@ -1560,9 +1583,9 @@ circuit_list_path_impl(origin_circuit_t *circ, int verbose, int verbose_names) base16_encode(elt+1, HEX_DIGEST_LEN+1, id, DIGEST_LEN); } } else { /* ! verbose_names */ - if ((ri = router_get_by_digest(id)) && - ri->is_named) { - elt = tor_strdup(hop->extend_info->nickname); + node = node_get_by_id(id); + if (node && node_is_named(node)) { + elt = tor_strdup(node_get_nickname(node)); } else { elt = tor_malloc(HEX_DIGEST_LEN+2); elt[0] = '$'; @@ -1631,31 +1654,28 @@ void circuit_rep_hist_note_result(origin_circuit_t *circ) { crypt_path_t *hop; - char *prev_digest = NULL; - routerinfo_t *router; + const char *prev_digest = NULL; hop = circ->cpath; if (!hop) /* circuit hasn't started building yet. */ return; if (server_mode(get_options())) { - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); if (!me) return; prev_digest = me->cache_info.identity_digest; } do { - router = router_get_by_digest(hop->extend_info->identity_digest); - if (router) { + const node_t *node = node_get_by_id(hop->extend_info->identity_digest); + if (node) { /* Why do we check this? We know the identity. -NM XXXX */ if (prev_digest) { if (hop->state == CPATH_STATE_OPEN) - rep_hist_note_extend_succeeded(prev_digest, - router->cache_info.identity_digest); + rep_hist_note_extend_succeeded(prev_digest, node->identity); else { - rep_hist_note_extend_failed(prev_digest, - router->cache_info.identity_digest); + rep_hist_note_extend_failed(prev_digest, node->identity); break; } } - prev_digest = router->cache_info.identity_digest; + prev_digest = node->identity; } else { prev_digest = NULL; } @@ -1924,7 +1944,7 @@ int inform_testing_reachability(void) { char dirbuf[128]; - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); if (!me) return 0; control_event_server_status(LOG_NOTICE, @@ -1953,7 +1973,7 @@ inform_testing_reachability(void) static INLINE int should_use_create_fast_for_circuit(origin_circuit_t *circ) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); tor_assert(circ->cpath); tor_assert(circ->cpath->extend_info); @@ -1961,9 +1981,10 @@ should_use_create_fast_for_circuit(origin_circuit_t *circ) return 1; /* our hand is forced: only a create_fast will work. */ if (!options->FastFirstHopPK) return 0; /* we prefer to avoid create_fast */ - if (server_mode(options)) { + if (public_server_mode(options)) { /* We're a server, and we know an onion key. We can choose. - * Prefer to blend in. */ + * Prefer to blend our circuit into the other circuits we are + * creating on behalf of others. */ return 0; } @@ -1996,7 +2017,7 @@ int circuit_send_next_onion_skin(origin_circuit_t *circ) { crypt_path_t *hop; - routerinfo_t *router; + const node_t *node; char payload[2+4+DIGEST_LEN+ONIONSKIN_CHALLENGE_LEN]; char *onionskin; size_t payload_len; @@ -2012,7 +2033,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) else control_event_bootstrap(BOOTSTRAP_STATUS_CIRCUIT_CREATE, 0); - router = router_get_by_digest(circ->_base.n_conn->identity_digest); + node = node_get_by_id(circ->_base.n_conn->identity_digest); fast = should_use_create_fast_for_circuit(circ); if (!fast) { /* We are an OR and we know the right onion key: we should @@ -2046,7 +2067,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_BUILDING); log_info(LD_CIRC,"First hop: finished sending %s cell to '%s'", fast ? "CREATE_FAST" : "CREATE", - router ? router_describe(router) : "<unnamed>"); + node ? node_describe(node) : "<unnamed>"); } else { tor_assert(circ->cpath->state == CPATH_STATE_OPEN); tor_assert(circ->_base.state == CIRCUIT_STATE_BUILDING); @@ -2088,7 +2109,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) if (circ->build_state->onehop_tunnel) control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_STATUS, 0); if (!can_complete_circuit && !circ->build_state->onehop_tunnel) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); can_complete_circuit=1; /* FFFF Log a count of known routers here */ log_notice(LD_GENERAL, @@ -2096,6 +2117,7 @@ circuit_send_next_onion_skin(origin_circuit_t *circ) "Looks like client functionality is working."); control_event_bootstrap(BOOTSTRAP_STATUS_DONE, 0); control_event_client_status(LOG_NOTICE, "CIRCUIT_ESTABLISHED"); + clear_broken_connection_map(1); if (server_mode(options) && !check_whether_orport_reachable()) { inform_testing_reachability(); consider_testing_reachability(1, 1); @@ -2523,12 +2545,12 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload, */ static int new_route_len(uint8_t purpose, extend_info_t *exit, - smartlist_t *routers) + smartlist_t *nodes) { int num_acceptable_routers; int routelen; - tor_assert(routers); + tor_assert(nodes); routelen = DEFAULT_ROUTE_LEN; if (exit && @@ -2536,10 +2558,10 @@ new_route_len(uint8_t purpose, extend_info_t *exit, purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO) routelen++; - num_acceptable_routers = count_acceptable_routers(routers); + num_acceptable_routers = count_acceptable_nodes(nodes); log_debug(LD_CIRC,"Chosen route length %d (%d/%d routers suitable).", - routelen, num_acceptable_routers, smartlist_len(routers)); + routelen, num_acceptable_routers, smartlist_len(nodes)); if (num_acceptable_routers < 2) { log_info(LD_CIRC, @@ -2557,24 +2579,12 @@ new_route_len(uint8_t purpose, extend_info_t *exit, return routelen; } -/** Fetch the list of predicted ports, dup it into a smartlist of - * uint16_t's, remove the ones that are already handled by an - * existing circuit, and return it. - */ +/** Return a newly allocated list of uint16_t * for each predicted port not + * handled by a current circuit. */ static smartlist_t * circuit_get_unhandled_ports(time_t now) { - smartlist_t *source = rep_hist_get_predicted_ports(now); - smartlist_t *dest = smartlist_create(); - uint16_t *tmp; - int i; - - for (i = 0; i < smartlist_len(source); ++i) { - tmp = tor_malloc(sizeof(uint16_t)); - memcpy(tmp, smartlist_get(source, i), sizeof(uint16_t)); - smartlist_add(dest, tmp); - } - + smartlist_t *dest = rep_hist_get_predicted_ports(now); circuit_remove_handled_ports(dest); return dest; } @@ -2608,12 +2618,12 @@ circuit_all_predicted_ports_handled(time_t now, int *need_uptime, return enough; } -/** Return 1 if <b>router</b> can handle one or more of the ports in +/** Return 1 if <b>node</b> can handle one or more of the ports in * <b>needed_ports</b>, else return 0. */ static int -router_handles_some_port(routerinfo_t *router, smartlist_t *needed_ports) -{ +node_handles_some_port(const node_t *node, smartlist_t *needed_ports) +{ /* XXXX MOVE */ int i; uint16_t port; @@ -2623,7 +2633,10 @@ router_handles_some_port(routerinfo_t *router, smartlist_t *needed_ports) needed_ports is explicitly a smartlist of uint16_t's */ port = *(uint16_t *)smartlist_get(needed_ports, i); tor_assert(port); - r = compare_addr_to_addr_policy(0, port, router->exit_policy); + if (node) + r = compare_tor_addr_to_node_policy(NULL, port, node); + else + continue; if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED) return 1; } @@ -2635,14 +2648,18 @@ router_handles_some_port(routerinfo_t *router, smartlist_t *needed_ports) static int ap_stream_wants_exit_attention(connection_t *conn) { - if (conn->type == CONN_TYPE_AP && - conn->state == AP_CONN_STATE_CIRCUIT_WAIT && + entry_connection_t *entry; + if (conn->type != CONN_TYPE_AP) + return 0; + entry = TO_ENTRY_CONN(conn); + + if (conn->state == AP_CONN_STATE_CIRCUIT_WAIT && !conn->marked_for_close && - !(TO_EDGE_CONN(conn)->want_onehop) && /* ignore one-hop streams */ - !(TO_EDGE_CONN(conn)->use_begindir) && /* ignore targeted dir fetches */ - !(TO_EDGE_CONN(conn)->chosen_exit_name) && /* ignore defined streams */ + !(entry->want_onehop) && /* ignore one-hop streams */ + !(entry->use_begindir) && /* ignore targeted dir fetches */ + !(entry->chosen_exit_name) && /* ignore defined streams */ !connection_edge_is_rendezvous_stream(TO_EDGE_CONN(conn)) && - !circuit_stream_is_being_handled(TO_EDGE_CONN(conn), 0, + !circuit_stream_is_being_handled(TO_ENTRY_CONN(conn), 0, MIN_CIRCUITS_HANDLING_STREAM)) return 1; return 0; @@ -2656,18 +2673,17 @@ ap_stream_wants_exit_attention(connection_t *conn) * * Return NULL if we can't find any suitable routers. */ -static routerinfo_t * -choose_good_exit_server_general(routerlist_t *dir, int need_uptime, - int need_capacity) +static const node_t * +choose_good_exit_server_general(int need_uptime, int need_capacity) { int *n_supported; - int i; int n_pending_connections = 0; smartlist_t *connections; int best_support = -1; int n_best_support=0; - routerinfo_t *router; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); + const smartlist_t *the_nodes; + const node_t *node=NULL; connections = get_connection_array(); @@ -2688,10 +2704,11 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, * * -1 means "Don't use this router at all." */ - n_supported = tor_malloc(sizeof(int)*smartlist_len(dir->routers)); - for (i = 0; i < smartlist_len(dir->routers); ++i) {/* iterate over routers */ - router = smartlist_get(dir->routers, i); - if (router_is_me(router)) { + the_nodes = nodelist_get_list(); + n_supported = tor_malloc(sizeof(int)*smartlist_len(the_nodes)); + SMARTLIST_FOREACH_BEGIN(the_nodes, const node_t *, node) { + const int i = node_sl_idx; + if (router_digest_is_me(node->identity)) { n_supported[i] = -1; // log_fn(LOG_DEBUG,"Skipping node %s -- it's me.", router->nickname); /* XXX there's probably a reverse predecessor attack here, but @@ -2699,41 +2716,44 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, */ continue; } - if (!router->is_running || router->is_bad_exit) { + if (!node_has_descriptor(node)) { + n_supported[i] = -1; + continue; + } + if (!node->is_running || node->is_bad_exit) { n_supported[i] = -1; continue; /* skip routers that are known to be down or bad exits */ } - - if (options->_ExcludeExitNodesUnion && - routerset_contains_router(options->_ExcludeExitNodesUnion, router)) { + if (routerset_contains_node(options->_ExcludeExitNodesUnion, node)) { n_supported[i] = -1; continue; /* user asked us not to use it, no matter what */ } if (options->ExitNodes && - !routerset_contains_router(options->ExitNodes, router)) { + !routerset_contains_node(options->ExitNodes, node)) { n_supported[i] = -1; continue; /* not one of our chosen exit nodes */ } - if (router_is_unreliable(router, need_uptime, need_capacity, 0)) { + if (node_is_unreliable(node, need_uptime, need_capacity, 0)) { n_supported[i] = -1; continue; /* skip routers that are not suitable. Don't worry if * this makes us reject all the possible routers: if so, * we'll retry later in this function with need_update and * need_capacity set to 0. */ } - if (!(router->is_valid || options->_AllowInvalid & ALLOW_INVALID_EXIT)) { + if (!(node->is_valid || options->_AllowInvalid & ALLOW_INVALID_EXIT)) { /* if it's invalid and we don't want it */ n_supported[i] = -1; // log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- invalid router.", // router->nickname, i); continue; /* skip invalid routers */ } - if (options->ExcludeSingleHopRelays && router->allow_single_hop_exits) { + if (options->ExcludeSingleHopRelays && + node_allows_single_hop_exits(node)) { n_supported[i] = -1; continue; } - if (router_exit_policy_rejects_all(router)) { + if (node_exit_policy_rejects_all(node)) { n_supported[i] = -1; // log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- it rejects all.", // router->nickname, i); @@ -2741,11 +2761,10 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, } n_supported[i] = 0; /* iterate over connections */ - SMARTLIST_FOREACH(connections, connection_t *, conn, - { + SMARTLIST_FOREACH_BEGIN(connections, connection_t *, conn) { if (!ap_stream_wants_exit_attention(conn)) continue; /* Skip everything but APs in CIRCUIT_WAIT */ - if (connection_ap_can_use_exit(TO_EDGE_CONN(conn), router)) { + if (connection_ap_can_use_exit(TO_ENTRY_CONN(conn), node)) { ++n_supported[i]; // log_fn(LOG_DEBUG,"%s is supported. n_supported[%d] now %d.", // router->nickname, i, n_supported[i]); @@ -2753,7 +2772,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, // log_fn(LOG_DEBUG,"%s (index %d) would reject this stream.", // router->nickname, i); } - }); /* End looping over connections. */ + } SMARTLIST_FOREACH_END(conn); if (n_pending_connections > 0 && n_supported[i] == 0) { /* Leave best_support at -1 if that's where it is, so we can * distinguish it later. */ @@ -2770,7 +2789,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, * count of equally good routers.*/ ++n_best_support; } - } + } SMARTLIST_FOREACH_END(node); log_info(LD_CIRC, "Found %d servers that might support %d/%d pending connections.", n_best_support, best_support >= 0 ? best_support : 0, @@ -2781,11 +2800,12 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, if (best_support > 0) { smartlist_t *supporting = smartlist_create(); - for (i = 0; i < smartlist_len(dir->routers); i++) - if (n_supported[i] == best_support) - smartlist_add(supporting, smartlist_get(dir->routers, i)); + SMARTLIST_FOREACH(the_nodes, const node_t *, node, { + if (n_supported[node_sl_idx] == best_support) + smartlist_add(supporting, (void*)node); + }); - router = routerlist_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT); + node = node_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT); smartlist_free(supporting); } else { /* Either there are no pending connections, or no routers even seem to @@ -2803,7 +2823,7 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, need_capacity?", fast":"", need_uptime?", stable":""); tor_free(n_supported); - return choose_good_exit_server_general(dir, 0, 0); + return choose_good_exit_server_general(0, 0); } log_notice(LD_CIRC, "All routers are down or won't exit%s -- " "choosing a doomed exit at random.", @@ -2814,18 +2834,17 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, for (attempt = 0; attempt < 2; attempt++) { /* try once to pick only from routers that satisfy a needed port, * then if there are none, pick from any that support exiting. */ - for (i = 0; i < smartlist_len(dir->routers); i++) { - router = smartlist_get(dir->routers, i); - if (n_supported[i] != -1 && - (attempt || router_handles_some_port(router, needed_ports))) { + SMARTLIST_FOREACH_BEGIN(the_nodes, const node_t *, node) { + if (n_supported[node_sl_idx] != -1 && + (attempt || node_handles_some_port(node, needed_ports))) { // log_fn(LOG_DEBUG,"Try %d: '%s' is a possibility.", // try, router->nickname); - smartlist_add(supporting, router); + smartlist_add(supporting, (void*)node); } - } + } SMARTLIST_FOREACH_END(node); - router = routerlist_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT); - if (router) + node = node_sl_choose_by_bandwidth(supporting, WEIGHT_FOR_EXIT); + if (node) break; smartlist_clear(supporting); } @@ -2835,9 +2854,9 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, } tor_free(n_supported); - if (router) { - log_info(LD_CIRC, "Chose exit server '%s'", router_describe(router)); - return router; + if (node) { + log_info(LD_CIRC, "Chose exit server '%s'", node_describe(node)); + return node; } if (options->ExitNodes) { log_warn(LD_CIRC, @@ -2858,12 +2877,12 @@ choose_good_exit_server_general(routerlist_t *dir, int need_uptime, * For client-side rendezvous circuits, choose a random node, weighted * toward the preferences in 'options'. */ -static routerinfo_t * -choose_good_exit_server(uint8_t purpose, routerlist_t *dir, +static const node_t * +choose_good_exit_server(uint8_t purpose, int need_uptime, int need_capacity, int is_internal) { - or_options_t *options = get_options(); - router_crn_flags_t flags = 0; + const or_options_t *options = get_options(); + router_crn_flags_t flags = CRN_NEED_DESC; if (need_uptime) flags |= CRN_NEED_UPTIME; if (need_capacity) @@ -2876,7 +2895,7 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir, if (is_internal) /* pick it like a middle hop */ return router_choose_random_node(NULL, options->ExcludeNodes, flags); else - return choose_good_exit_server_general(dir,need_uptime,need_capacity); + return choose_good_exit_server_general(need_uptime,need_capacity); case CIRCUIT_PURPOSE_C_ESTABLISH_REND: if (options->_AllowInvalid & ALLOW_INVALID_RENDEZVOUS) flags |= CRN_ALLOW_INVALID; @@ -2892,7 +2911,7 @@ choose_good_exit_server(uint8_t purpose, routerlist_t *dir, static void warn_if_last_router_excluded(origin_circuit_t *circ, const extend_info_t *exit) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); routerset_t *rs = options->ExcludeNodes; const char *description; uint8_t purpose = circ->_base.purpose; @@ -2969,13 +2988,12 @@ static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit) { cpath_build_state_t *state = circ->build_state; - routerlist_t *rl = router_get_routerlist(); if (state->onehop_tunnel) { log_debug(LD_CIRC, "Launching a one-hop circuit for dir tunnel."); state->desired_path_len = 1; } else { - int r = new_route_len(circ->_base.purpose, exit, rl->routers); + int r = new_route_len(circ->_base.purpose, exit, nodelist_get_list()); if (r < 1) /* must be at least 1 */ return -1; state->desired_path_len = r; @@ -2987,14 +3005,15 @@ onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit) extend_info_describe(exit)); exit = extend_info_dup(exit); } else { /* we have to decide one */ - routerinfo_t *router = - choose_good_exit_server(circ->_base.purpose, rl, state->need_uptime, + const node_t *node = + choose_good_exit_server(circ->_base.purpose, state->need_uptime, state->need_capacity, state->is_internal); - if (!router) { + if (!node) { log_warn(LD_CIRC,"failed to choose an exit server"); return -1; } - exit = extend_info_from_router(router); + exit = extend_info_from_node(node); + tor_assert(exit); } state->chosen_exit = exit; return 0; @@ -3045,35 +3064,30 @@ circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *exit) * and available for building circuits through. */ static int -count_acceptable_routers(smartlist_t *routers) +count_acceptable_nodes(smartlist_t *nodes) { - int i, n; int num=0; - routerinfo_t *r; - n = smartlist_len(routers); - for (i=0;i<n;i++) { - r = smartlist_get(routers, i); -// log_debug(LD_CIRC, + SMARTLIST_FOREACH_BEGIN(nodes, const node_t *, node) { + // log_debug(LD_CIRC, // "Contemplating whether router %d (%s) is a new option.", // i, r->nickname); - if (r->is_running == 0) { + if (! node->is_running) // log_debug(LD_CIRC,"Nope, the directory says %d is not running.",i); - goto next_i_loop; - } - if (r->is_valid == 0) { + continue; + if (! node->is_valid) // log_debug(LD_CIRC,"Nope, the directory says %d is not valid.",i); - goto next_i_loop; + continue; + if (! node_has_descriptor(node)) + continue; /* XXX This clause makes us count incorrectly: if AllowInvalidRouters * allows this node in some places, then we're getting an inaccurate * count. For now, be conservative and don't count it. But later we * should try to be smarter. */ - } - num++; + ++num; + } SMARTLIST_FOREACH_END(node); + // log_debug(LD_CIRC,"I like %d. num_acceptable_routers now %d.",i, num); - next_i_loop: - ; /* C requires an explicit statement after the label */ - } return num; } @@ -3101,31 +3115,29 @@ onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop) * circuit. In particular, make sure we don't pick the exit node or its * family, and make sure we don't duplicate any previous nodes or their * families. */ -static routerinfo_t * +static const node_t * choose_good_middle_server(uint8_t purpose, cpath_build_state_t *state, crypt_path_t *head, int cur_len) { int i; - routerinfo_t *r, *choice; + const node_t *r, *choice; crypt_path_t *cpath; smartlist_t *excluded; - or_options_t *options = get_options(); - router_crn_flags_t flags = 0; + const or_options_t *options = get_options(); + router_crn_flags_t flags = CRN_NEED_DESC; tor_assert(_CIRCUIT_PURPOSE_MIN <= purpose && purpose <= _CIRCUIT_PURPOSE_MAX); log_debug(LD_CIRC, "Contemplating intermediate hop: random choice."); excluded = smartlist_create(); - if ((r = build_state_get_exit_router(state))) { - smartlist_add(excluded, r); - routerlist_add_family(excluded, r); + if ((r = build_state_get_exit_node(state))) { + nodelist_add_node_and_family(excluded, r); } for (i = 0, cpath = head; i < cur_len; ++i, cpath=cpath->next) { - if ((r = router_get_by_digest(cpath->extend_info->identity_digest))) { - smartlist_add(excluded, r); - routerlist_add_family(excluded, r); + if ((r = node_get_by_id(cpath->extend_info->identity_digest))) { + nodelist_add_node_and_family(excluded, r); } } @@ -3148,44 +3160,43 @@ choose_good_middle_server(uint8_t purpose, * If <b>state</b> is NULL, we're choosing a router to serve as an entry * guard, not for any particular circuit. */ -static routerinfo_t * +static const node_t * choose_good_entry_server(uint8_t purpose, cpath_build_state_t *state) { - routerinfo_t *r, *choice; + const node_t *choice; smartlist_t *excluded; - or_options_t *options = get_options(); - router_crn_flags_t flags = CRN_NEED_GUARD; + const or_options_t *options = get_options(); + router_crn_flags_t flags = CRN_NEED_GUARD|CRN_NEED_DESC; + const node_t *node; if (state && options->UseEntryGuards && (purpose != CIRCUIT_PURPOSE_TESTING || options->BridgeRelay)) { + /* This is request for an entry server to use for a regular circuit, + * and we use entry guard nodes. Just return one of the guard nodes. */ return choose_random_entry(state); } excluded = smartlist_create(); - if (state && (r = build_state_get_exit_router(state))) { - smartlist_add(excluded, r); - routerlist_add_family(excluded, r); + if (state && (node = build_state_get_exit_node(state))) { + /* Exclude the exit node from the state, if we have one. Also exclude its + * family. */ + nodelist_add_node_and_family(excluded, node); } if (firewall_is_fascist_or()) { - /*XXXX This could slow things down a lot; use a smarter implementation */ - /* exclude all ORs that listen on the wrong port, if anybody notices. */ - routerlist_t *rl = router_get_routerlist(); - int i; - - for (i=0; i < smartlist_len(rl->routers); i++) { - r = smartlist_get(rl->routers, i); - if (!fascist_firewall_allows_or(r)) - smartlist_add(excluded, r); - } + /* Exclude all ORs that we can't reach through our firewall */ + smartlist_t *nodes = nodelist_get_list(); + SMARTLIST_FOREACH(nodes, const node_t *, node, { + if (!fascist_firewall_allows_node(node)) + smartlist_add(excluded, (void*)node); + }); } - /* and exclude current entry guards, if applicable */ + /* and exclude current entry guards and their families, if applicable */ if (options->UseEntryGuards && entry_guards) { SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry, { - if ((r = router_get_by_digest(entry->identity))) { - smartlist_add(excluded, r); - routerlist_add_family(excluded, r); + if ((node = node_get_by_id(entry->identity))) { + nodelist_add_node_and_family(excluded, node); } }); } @@ -3241,14 +3252,18 @@ onion_extend_cpath(origin_circuit_t *circ) if (cur_len == state->desired_path_len - 1) { /* Picking last node */ info = extend_info_dup(state->chosen_exit); } else if (cur_len == 0) { /* picking first node */ - routerinfo_t *r = choose_good_entry_server(purpose, state); - if (r) - info = extend_info_from_router(r); + const node_t *r = choose_good_entry_server(purpose, state); + if (r) { + info = extend_info_from_node(r); + tor_assert(info); + } } else { - routerinfo_t *r = + const node_t *r = choose_good_middle_server(purpose, state, circ->cpath, cur_len); - if (r) - info = extend_info_from_router(r); + if (r) { + info = extend_info_from_node(r); + tor_assert(info); + } } if (!info) { @@ -3308,7 +3323,7 @@ extend_info_alloc(const char *nickname, const char *digest, /** Allocate and return a new extend_info_t that can be used to build a * circuit to or through the router <b>r</b>. */ extend_info_t * -extend_info_from_router(routerinfo_t *r) +extend_info_from_router(const routerinfo_t *r) { tor_addr_t addr; tor_assert(r); @@ -3317,6 +3332,29 @@ extend_info_from_router(routerinfo_t *r) r->onion_pkey, &addr, r->or_port); } +/** Allocate and return a new extend_info that can be used to build a ircuit + * to or through the node <b>node</b>. May return NULL if there is not + * enough info about <b>node</b> to extend to it--for example, if there + * is no routerinfo_t or microdesc_t. + **/ +extend_info_t * +extend_info_from_node(const node_t *node) +{ + if (node->ri) { + return extend_info_from_router(node->ri); + } else if (node->rs && node->md) { + tor_addr_t addr; + tor_addr_from_ipv4h(&addr, node->rs->addr); + return extend_info_alloc(node->rs->nickname, + node->identity, + node->md->onion_pkey, + &addr, + node->rs->or_port); + } else { + return NULL; + } +} + /** Release storage held by an extend_info_t struct. */ void extend_info_free(extend_info_t *info) @@ -3347,12 +3385,12 @@ extend_info_dup(extend_info_t *info) * If there is no chosen exit, or if we don't know the routerinfo_t for * the chosen exit, return NULL. */ -routerinfo_t * -build_state_get_exit_router(cpath_build_state_t *state) +const node_t * +build_state_get_exit_node(cpath_build_state_t *state) { if (!state || !state->chosen_exit) return NULL; - return router_get_by_digest(state->chosen_exit->identity_digest); + return node_get_by_id(state->chosen_exit->identity_digest); } /** Return the nickname for the chosen exit router in <b>state</b>. If @@ -3374,10 +3412,10 @@ build_state_get_exit_nickname(cpath_build_state_t *state) * * If it's not usable, set *<b>reason</b> to a static string explaining why. */ -/*XXXX take a routerstatus, not a routerinfo. */ static int -entry_guard_set_status(entry_guard_t *e, routerinfo_t *ri, - time_t now, or_options_t *options, const char **reason) +entry_guard_set_status(entry_guard_t *e, const node_t *node, + time_t now, const or_options_t *options, + const char **reason) { char buf[HEX_DIGEST_LEN+1]; int changed = 0; @@ -3385,18 +3423,19 @@ entry_guard_set_status(entry_guard_t *e, routerinfo_t *ri, *reason = NULL; /* Do we want to mark this guard as bad? */ - if (!ri) + if (!node) *reason = "unlisted"; - else if (!ri->is_running) + else if (!node->is_running) *reason = "down"; - else if (options->UseBridges && ri->purpose != ROUTER_PURPOSE_BRIDGE) + else if (options->UseBridges && (!node->ri || + node->ri->purpose != ROUTER_PURPOSE_BRIDGE)) *reason = "not a bridge"; - else if (options->UseBridges && !routerinfo_is_a_configured_bridge(ri)) + else if (options->UseBridges && !node_is_a_configured_bridge(node)) *reason = "not a configured bridge"; - else if (!options->UseBridges && !ri->is_possible_guard && - !routerset_contains_router(options->EntryNodes,ri)) + else if (!options->UseBridges && !node->is_possible_guard && + !routerset_contains_node(options->EntryNodes,node)) *reason = "not recommended as a guard"; - else if (routerset_contains_router(options->ExcludeNodes, ri)) + else if (routerset_contains_node(options->ExcludeNodes, node)) *reason = "excluded"; if (*reason && ! e->bad_since) { @@ -3440,7 +3479,7 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now) return now > (e->last_attempted + 36*60*60); } -/** Return the router corresponding to <b>e</b>, if <b>e</b> is +/** Return the node corresponding to <b>e</b>, if <b>e</b> is * working well enough that we are willing to use it as an entry * right now. (Else return NULL.) In particular, it must be * - Listed as either up or never yet contacted; @@ -3454,12 +3493,12 @@ entry_is_time_to_retry(entry_guard_t *e, time_t now) * * If the answer is no, set *<b>msg</b> to an explanation of why. */ -static INLINE routerinfo_t * +static INLINE const node_t * entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity, int assume_reachable, const char **msg) { - routerinfo_t *r; - or_options_t *options = get_options(); + const node_t *node; + const or_options_t *options = get_options(); tor_assert(msg); if (e->bad_since) { @@ -3472,38 +3511,39 @@ entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity, *msg = "unreachable"; return NULL; } - r = router_get_by_digest(e->identity); - if (!r) { + node = node_get_by_id(e->identity); + if (!node || !node_has_descriptor(node)) { *msg = "no descriptor"; return NULL; } - if (options->UseBridges) { - if (r->purpose != ROUTER_PURPOSE_BRIDGE) { + if (get_options()->UseBridges) { + if (node_get_purpose(node) != ROUTER_PURPOSE_BRIDGE) { *msg = "not a bridge"; return NULL; } - if (!routerinfo_is_a_configured_bridge(r)) { + if (!node_is_a_configured_bridge(node)) { *msg = "not a configured bridge"; return NULL; } - } else if (r->purpose != ROUTER_PURPOSE_GENERAL) { - *msg = "not general-purpose"; - return NULL; + } else { /* !get_options()->UseBridges */ + if (node_get_purpose(node) != ROUTER_PURPOSE_GENERAL) { + *msg = "not general-purpose"; + return NULL; + } } - if (options->EntryNodes && - routerset_contains_router(options->EntryNodes, r)) { + if (routerset_contains_node(options->EntryNodes, node)) { /* they asked for it, they get it */ need_uptime = need_capacity = 0; } - if (router_is_unreliable(r, need_uptime, need_capacity, 0)) { + if (node_is_unreliable(node, need_uptime, need_capacity, 0)) { *msg = "not fast/stable"; return NULL; } - if (!fascist_firewall_allows_or(r)) { + if (!fascist_firewall_allows_node(node)) { *msg = "unreachable by config"; return NULL; } - return r; + return node; } /** Return the number of entry guards that we think are usable. */ @@ -3583,7 +3623,7 @@ control_event_guard_deferred(void) #if 0 int n = 0; const char *msg; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); if (!entry_guards) return; SMARTLIST_FOREACH(entry_guards, entry_guard_t *, entry, @@ -3605,15 +3645,15 @@ control_event_guard_deferred(void) * If <b>chosen</b> is defined, use that one, and if it's not * already in our entry_guards list, put it at the *beginning*. * Else, put the one we pick at the end of the list. */ -static routerinfo_t * -add_an_entry_guard(routerinfo_t *chosen, int reset_status) +static const node_t * +add_an_entry_guard(const node_t *chosen, int reset_status, int prepend) { - routerinfo_t *router; + const node_t *node; entry_guard_t *entry; if (chosen) { - router = chosen; - entry = is_an_entry_guard(router->cache_info.identity_digest); + node = chosen; + entry = is_an_entry_guard(node->identity); if (entry) { if (reset_status) { entry->bad_since = 0; @@ -3622,15 +3662,15 @@ add_an_entry_guard(routerinfo_t *chosen, int reset_status) return NULL; } } else { - router = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL); - if (!router) + node = choose_good_entry_server(CIRCUIT_PURPOSE_C_GENERAL, NULL); + if (!node) return NULL; } entry = tor_malloc_zero(sizeof(entry_guard_t)); - log_info(LD_CIRC, "Chose '%s' as new entry guard.", - router_describe(router)); - strlcpy(entry->nickname, router->nickname, sizeof(entry->nickname)); - memcpy(entry->identity, router->cache_info.identity_digest, DIGEST_LEN); + log_info(LD_CIRC, "Chose %s as new entry guard.", + node_describe(node)); + strlcpy(entry->nickname, node_get_nickname(node), sizeof(entry->nickname)); + memcpy(entry->identity, node->identity, DIGEST_LEN); /* Choose expiry time smudged over the past month. The goal here * is to a) spread out when Tor clients rotate their guards, so they * don't all select them on the same day, and b) avoid leaving a @@ -3638,27 +3678,27 @@ add_an_entry_guard(routerinfo_t *chosen, int reset_status) * this guard. For details, see the Jan 2010 or-dev thread. */ entry->chosen_on_date = time(NULL) - crypto_rand_int(3600*24*30); entry->chosen_by_version = tor_strdup(VERSION); - if (chosen) /* prepend */ + if (prepend) smartlist_insert(entry_guards, 0, entry); - else /* append */ + else smartlist_add(entry_guards, entry); control_event_guard(entry->nickname, entry->identity, "NEW"); control_event_guard_deferred(); log_entry_guards(LOG_INFO); - return router; + return node; } /** If the use of entry guards is configured, choose more entry guards * until we have enough in the list. */ static void -pick_entry_guards(or_options_t *options) +pick_entry_guards(const or_options_t *options) { int changed = 0; tor_assert(entry_guards); while (num_live_entry_guards() < options->NumEntryGuards) { - if (!add_an_entry_guard(NULL, 0)) + if (!add_an_entry_guard(NULL, 0, 0)) break; changed = 1; } @@ -3784,7 +3824,7 @@ remove_dead_entry_guards(time_t now) * think that things are unlisted. */ void -entry_guards_compute_status(or_options_t *options, time_t now) +entry_guards_compute_status(const or_options_t *options, time_t now) { int changed = 0; digestmap_t *reasons; @@ -3798,7 +3838,7 @@ entry_guards_compute_status(or_options_t *options, time_t now) reasons = digestmap_new(); SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { - routerinfo_t *r = router_get_by_digest(entry->identity); + const node_t *r = node_get_by_id(entry->identity); const char *reason = NULL; if (entry_guard_set_status(entry, r, now, options, &reason)) changed = 1; @@ -3817,7 +3857,7 @@ entry_guards_compute_status(or_options_t *options, time_t now) SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { const char *reason = digestmap_get(reasons, entry->identity); const char *live_msg = ""; - routerinfo_t *r = entry_is_live(entry, 0, 1, 0, &live_msg); + const node_t *r = entry_is_live(entry, 0, 1, 0, &live_msg); log_info(LD_CIRC, "Summary: Entry %s [%s] is %s, %s%s%s, and %s%s.", entry->nickname, hex_str(entry->identity, DIGEST_LEN), @@ -3935,7 +3975,7 @@ entry_guard_register_connect_status(const char *digest, int succeeded, break; if (e->made_contact) { const char *msg; - routerinfo_t *r = entry_is_live(e, 0, 1, 1, &msg); + const node_t *r = entry_is_live(e, 0, 1, 1, &msg); if (r && e->unreachable_since) { refuse_conn = 1; e->can_retry = 1; @@ -3971,12 +4011,12 @@ entry_nodes_should_be_added(void) should_add_entry_nodes = 1; } -/** Add all nodes in EntryNodes that aren't currently guard nodes to the list - * of guard nodes, at the front. */ +/** Adjust the entry guards list so that it only contains entries from + * EntryNodes, adding new entries from EntryNodes to the list as needed. */ static void -entry_guards_prepend_from_config(or_options_t *options) +entry_guards_set_from_config(const or_options_t *options) { - smartlist_t *entry_routers, *entry_fps; + smartlist_t *entry_nodes, *worse_entry_nodes, *entry_fps; smartlist_t *old_entry_guards_on_list, *old_entry_guards_not_on_list; tor_assert(entry_guards); @@ -3996,23 +4036,19 @@ entry_guards_prepend_from_config(or_options_t *options) tor_free(string); } - entry_routers = smartlist_create(); + entry_nodes = smartlist_create(); + worse_entry_nodes = smartlist_create(); entry_fps = smartlist_create(); old_entry_guards_on_list = smartlist_create(); old_entry_guards_not_on_list = smartlist_create(); /* Split entry guards into those on the list and those not. */ - /* XXXX023 Now that we allow countries and IP ranges in EntryNodes, this is - * potentially an enormous list. For now, we disable such values for - * EntryNodes in options_validate(); really, this wants a better solution. - * Perhaps we should do this calculation once whenever the list of routers - * changes or the entrynodes setting changes. - */ - routerset_get_all_routers(entry_routers, options->EntryNodes, - options->ExcludeNodes, 0); - SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri, - smartlist_add(entry_fps,ri->cache_info.identity_digest)); + routerset_get_all_nodes(entry_nodes, options->EntryNodes, + options->ExcludeNodes, 0); + SMARTLIST_FOREACH(entry_nodes, const node_t *,node, + smartlist_add(entry_fps, (void*)node->identity)); + SMARTLIST_FOREACH(entry_guards, entry_guard_t *, e, { if (smartlist_digest_isin(entry_fps, e->identity)) smartlist_add(old_entry_guards_on_list, e); @@ -4020,27 +4056,47 @@ entry_guards_prepend_from_config(or_options_t *options) smartlist_add(old_entry_guards_not_on_list, e); }); - /* Remove all currently configured entry guards from entry_routers. */ - SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri, { - if (is_an_entry_guard(ri->cache_info.identity_digest)) { - SMARTLIST_DEL_CURRENT(entry_routers, ri); + /* Remove all currently configured guard nodes, excluded nodes, unreachable + * nodes, or non-Guard nodes from entry_nodes. */ + SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) { + if (is_an_entry_guard(node->identity)) { + SMARTLIST_DEL_CURRENT(entry_nodes, node); + continue; + } else if (routerset_contains_node(options->ExcludeNodes, node)) { + SMARTLIST_DEL_CURRENT(entry_nodes, node); + continue; + } else if (!fascist_firewall_allows_node(node)) { + SMARTLIST_DEL_CURRENT(entry_nodes, node); + continue; + } else if (! node->is_possible_guard) { + smartlist_add(worse_entry_nodes, (node_t*)node); + SMARTLIST_DEL_CURRENT(entry_nodes, node); } - }); + } SMARTLIST_FOREACH_END(node); /* Now build the new entry_guards list. */ smartlist_clear(entry_guards); /* First, the previously configured guards that are in EntryNodes. */ smartlist_add_all(entry_guards, old_entry_guards_on_list); + /* Next, scramble the rest of EntryNodes, putting the guards first. */ + smartlist_shuffle(entry_nodes); + smartlist_shuffle(worse_entry_nodes); + smartlist_add_all(entry_nodes, worse_entry_nodes); + /* Next, the rest of EntryNodes */ - SMARTLIST_FOREACH(entry_routers, routerinfo_t *, ri, { - add_an_entry_guard(ri, 0); - }); + SMARTLIST_FOREACH_BEGIN(entry_nodes, const node_t *, node) { + add_an_entry_guard(node, 0, 0); + if (smartlist_len(entry_guards) > options->NumEntryGuards * 10) + break; + } SMARTLIST_FOREACH_END(node); + log_notice(LD_GENERAL, "%d entries in guards", smartlist_len(entry_guards)); /* Finally, free the remaining previously configured guards that are not in * EntryNodes. */ SMARTLIST_FOREACH(old_entry_guards_not_on_list, entry_guard_t *, e, entry_guard_free(e)); - smartlist_free(entry_routers); + smartlist_free(entry_nodes); + smartlist_free(worse_entry_nodes); smartlist_free(entry_fps); smartlist_free(old_entry_guards_on_list); smartlist_free(old_entry_guards_not_on_list); @@ -4052,7 +4108,7 @@ entry_guards_prepend_from_config(or_options_t *options) * list already and we must stick to it. */ int -entry_list_is_constrained(or_options_t *options) +entry_list_is_constrained(const or_options_t *options) { if (options->EntryNodes) return 1; @@ -4066,20 +4122,21 @@ entry_list_is_constrained(or_options_t *options) * make sure not to pick this circuit's exit or any node in the * exit's family. If <b>state</b> is NULL, we're looking for a random * guard (likely a bridge). */ -routerinfo_t * +const node_t * choose_random_entry(cpath_build_state_t *state) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); smartlist_t *live_entry_guards = smartlist_create(); smartlist_t *exit_family = smartlist_create(); - routerinfo_t *chosen_exit = state?build_state_get_exit_router(state) : NULL; - routerinfo_t *r = NULL; + const node_t *chosen_exit = + state?build_state_get_exit_node(state) : NULL; + const node_t *node = NULL; int need_uptime = state ? state->need_uptime : 0; int need_capacity = state ? state->need_capacity : 0; int preferred_min, consider_exit_family = 0; if (chosen_exit) { - routerlist_add_family(exit_family, chosen_exit); + nodelist_add_node_and_family(exit_family, chosen_exit); consider_exit_family = 1; } @@ -4087,7 +4144,7 @@ choose_random_entry(cpath_build_state_t *state) entry_guards = smartlist_create(); if (should_add_entry_nodes) - entry_guards_prepend_from_config(options); + entry_guards_set_from_config(options); if (!entry_list_is_constrained(options) && smartlist_len(entry_guards) < options->NumEntryGuards) @@ -4095,25 +4152,24 @@ choose_random_entry(cpath_build_state_t *state) retry: smartlist_clear(live_entry_guards); - SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) - { + SMARTLIST_FOREACH_BEGIN(entry_guards, entry_guard_t *, entry) { const char *msg; - r = entry_is_live(entry, need_uptime, need_capacity, 0, &msg); - if (!r) + node = entry_is_live(entry, need_uptime, need_capacity, 0, &msg); + if (!node) continue; /* down, no point */ - if (r == chosen_exit) + if (node == chosen_exit) continue; /* don't pick the same node for entry and exit */ - if (consider_exit_family && smartlist_isin(exit_family, r)) + if (consider_exit_family && smartlist_isin(exit_family, node)) continue; /* avoid relays that are family members of our exit */ #if 0 /* since EntryNodes is always strict now, this clause is moot */ if (options->EntryNodes && - !routerset_contains_router(options->EntryNodes, r)) { + !routerset_contains_node(options->EntryNodes, node)) { /* We've come to the end of our preferred entry nodes. */ if (smartlist_len(live_entry_guards)) goto choose_and_finish; /* only choose from the ones we like */ if (options->StrictNodes) { /* in theory this case should never happen, since - * entry_guards_prepend_from_config() drops unwanted relays */ + * entry_guards_set_from_config() drops unwanted relays */ tor_fragile_assert(); } else { log_info(LD_CIRC, @@ -4121,7 +4177,7 @@ choose_random_entry(cpath_build_state_t *state) } } #endif - smartlist_add(live_entry_guards, r); + smartlist_add(live_entry_guards, (void*)node); if (!entry->made_contact) { /* Always start with the first not-yet-contacted entry * guard. Otherwise we might add several new ones, pick @@ -4130,9 +4186,8 @@ choose_random_entry(cpath_build_state_t *state) goto choose_and_finish; } if (smartlist_len(live_entry_guards) >= options->NumEntryGuards) - break; /* we have enough */ - } - SMARTLIST_FOREACH_END(entry); + goto choose_and_finish; /* we have enough */ + } SMARTLIST_FOREACH_END(entry); if (entry_list_is_constrained(options)) { /* If we prefer the entry nodes we've got, and we have at least @@ -4152,8 +4207,8 @@ choose_random_entry(cpath_build_state_t *state) /* XXX if guard doesn't imply fast and stable, then we need * to tell add_an_entry_guard below what we want, or it might * be a long time til we get it. -RD */ - r = add_an_entry_guard(NULL, 0); - if (r) { + node = add_an_entry_guard(NULL, 0, 0); + if (node) { entry_guards_changed(); /* XXX we start over here in case the new node we added shares * a family with our exit node. There's a chance that we'll just @@ -4163,11 +4218,11 @@ choose_random_entry(cpath_build_state_t *state) goto retry; } } - if (!r && need_uptime) { + if (!node && need_uptime) { need_uptime = 0; /* try without that requirement */ goto retry; } - if (!r && need_capacity) { + if (!node && need_capacity) { /* still no? last attempt, try without requiring capacity */ need_capacity = 0; goto retry; @@ -4176,10 +4231,10 @@ choose_random_entry(cpath_build_state_t *state) /* Removing this retry logic: if we only allow one exit, and it is in the same family as all our entries, then we are just plain not going to win here. */ - if (!r && entry_list_is_constrained(options) && consider_exit_family) { - /* still no? if we're using bridges, - * and our chosen exit is in the same family as all our - * bridges, then be flexible about families. */ + if (!node && entry_list_is_constrained(options) && consider_exit_family) { + /* still no? if we're using bridges or have strictentrynodes + * set, and our chosen exit is in the same family as all our + * bridges/entry guards, then be flexible about families. */ consider_exit_family = 0; goto retry; } @@ -4191,16 +4246,16 @@ choose_random_entry(cpath_build_state_t *state) if (entry_list_is_constrained(options)) { /* We need to weight by bandwidth, because our bridges or entryguards * were not already selected proportional to their bandwidth. */ - r = routerlist_sl_choose_by_bandwidth(live_entry_guards, WEIGHT_FOR_GUARD); + node = node_sl_choose_by_bandwidth(live_entry_guards, WEIGHT_FOR_GUARD); } else { /* We choose uniformly at random here, because choose_good_entry_server() * already weights its choices by bandwidth, so we don't want to * *double*-weight our guard selection. */ - r = smartlist_choose(live_entry_guards); + node = smartlist_choose(live_entry_guards); } smartlist_free(live_entry_guards); smartlist_free(exit_family); - return r; + return node; } /** Parse <b>state</b> and learn about the entry guards it describes. @@ -4447,7 +4502,7 @@ getinfo_helper_entry_guards(control_connection_t *conn, char *c = tor_malloc(len); const char *status = NULL; time_t when = 0; - routerinfo_t *ri; + const node_t *node; if (!e->made_contact) { status = "never-connected"; @@ -4458,9 +4513,9 @@ getinfo_helper_entry_guards(control_connection_t *conn, status = "up"; } - ri = router_get_by_digest(e->identity); - if (ri) { - router_get_verbose_nickname(nbuf, ri); + node = node_get_by_id(e->identity); + if (node) { + node_get_verbose_nickname(node, nbuf); } else { nbuf[0] = '$'; base16_encode(nbuf+1, sizeof(nbuf)-1, e->identity, DIGEST_LEN); @@ -4483,24 +4538,6 @@ getinfo_helper_entry_guards(control_connection_t *conn, return 0; } -/** Information about a configured bridge. Currently this just matches the - * ones in the torrc file, but one day we may be able to learn about new - * bridges on our own, and remember them in the state file. */ -typedef struct { - /** Address of the bridge. */ - tor_addr_t addr; - /** TLS port for the bridge. */ - uint16_t port; - /** Boolean: We are re-parsing our bridge list, and we are going to remove - * this one if we don't find it in the list of configured bridges. */ - unsigned marked_for_removal : 1; - /** Expected identity digest, or all zero bytes if we don't know what the - * digest should be. */ - char identity[DIGEST_LEN]; - /** When should we next try to fetch a descriptor for this bridge? */ - download_status_t fetch_status; -} bridge_info_t; - /** A list of configured bridges. Whenever we actually get a descriptor * for one, we add it as an entry guard. Note that the order of bridges * in this list does not necessarily correspond to the order of bridges @@ -4528,7 +4565,7 @@ sweep_bridge_list(void) SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) { if (b->marked_for_removal) { SMARTLIST_DEL_CURRENT(bridge_list, b); - tor_free(b); + bridge_free(b); } } SMARTLIST_FOREACH_END(b); } @@ -4539,10 +4576,243 @@ clear_bridge_list(void) { if (!bridge_list) bridge_list = smartlist_create(); - SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b, tor_free(b)); + SMARTLIST_FOREACH(bridge_list, bridge_info_t *, b, bridge_free(b)); smartlist_clear(bridge_list); } +/** Free the bridge <b>bridge</b>. */ +static void +bridge_free(bridge_info_t *bridge) +{ + if (!bridge) + return; + + tor_free(bridge->transport_name); + tor_free(bridge); +} + +/** A list of pluggable transports found in torrc. */ +static smartlist_t *transport_list = NULL; + +/** Mark every entry of the transport list to be removed on our next call to + * sweep_transport_list unless it has first been un-marked. */ +void +mark_transport_list(void) +{ + if (!transport_list) + transport_list = smartlist_create(); + SMARTLIST_FOREACH(transport_list, transport_t *, t, + t->marked_for_removal = 1); +} + +/** Remove every entry of the transport list that was marked with + * mark_transport_list if it has not subsequently been un-marked. */ +void +sweep_transport_list(void) +{ + if (!transport_list) + transport_list = smartlist_create(); + SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, t) { + if (t->marked_for_removal) { + SMARTLIST_DEL_CURRENT(transport_list, t); + transport_free(t); + } + } SMARTLIST_FOREACH_END(t); +} + +/** Initialize the pluggable transports list to empty, creating it if + * needed. */ +void +clear_transport_list(void) +{ + if (!transport_list) + transport_list = smartlist_create(); + SMARTLIST_FOREACH(transport_list, transport_t *, t, transport_free(t)); + smartlist_clear(transport_list); +} + +/** Free the pluggable transport struct <b>transport</b>. */ +void +transport_free(transport_t *transport) +{ + if (!transport) + return; + + tor_free(transport->name); + tor_free(transport); +} + +/** Returns the transport in our transport list that has the name <b>name</b>. + * Else returns NULL. */ +transport_t * +transport_get_by_name(const char *name) +{ + tor_assert(name); + + if (!transport_list) + return NULL; + + SMARTLIST_FOREACH_BEGIN(transport_list, transport_t *, transport) { + if (!strcmp(transport->name, name)) + return transport; + } SMARTLIST_FOREACH_END(transport); + + return NULL; +} + +/** Returns a transport_t struct for a transport proxy supporting the + protocol <b>name</b> listening at <b>addr</b>:<b>port</b> using + SOCKS version <b>socks_ver</b>. */ +transport_t * +transport_create(const tor_addr_t *addr, uint16_t port, + const char *name, int socks_ver) +{ + transport_t *t = tor_malloc_zero(sizeof(transport_t)); + + tor_addr_copy(&t->addr, addr); + t->port = port; + t->name = tor_strdup(name); + t->socks_version = socks_ver; + + return t; +} + +/** Resolve any conflicts that the insertion of transport <b>t</b> + * might cause. + * Return 0 if <b>t</b> is OK and should be registered, 1 if there is + * a transport identical to <b>t</b> already registered and -1 if + * <b>t</b> cannot be added due to conflicts. */ +static int +transport_resolve_conflicts(transport_t *t) +{ + /* This is how we resolve transport conflicts: + + If there is already a transport with the same name and addrport, + we either have duplicate torrc lines OR we are here post-HUP and + this transport was here pre-HUP as well. In any case, mark the + old transport so that it doesn't get removed and ignore the new + one. Our caller has to free the new transport so we return '1' to + signify this. + + If there is already a transport with the same name but different + addrport: + * if it's marked for removal, it means that it either has a lower + priority than 't' in torrc (otherwise the mark would have been + cleared by the paragraph above), or it doesn't exist at all in + the post-HUP torrc. We destroy the old transport and register 't'. + * if it's *not* marked for removal, it means that it was newly + added in the post-HUP torrc or that it's of higher priority, in + this case we ignore 't'. */ + transport_t *t_tmp = transport_get_by_name(t->name); + if (t_tmp) { /* same name */ + if (tor_addr_eq(&t->addr, &t_tmp->addr) && (t->port == t_tmp->port)) { + /* same name *and* addrport */ + t_tmp->marked_for_removal = 0; + return 1; + } else { /* same name but different addrport */ + if (t_tmp->marked_for_removal) { /* marked for removal */ + log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' " + "but there was already a transport marked for deletion at " + "'%s:%u'. We deleted the old transport and registered the " + "new one.", t->name, fmt_addr(&t->addr), t->port, + fmt_addr(&t_tmp->addr), t_tmp->port); + smartlist_remove(transport_list, t_tmp); + transport_free(t_tmp); + } else { /* *not* marked for removal */ + log_notice(LD_GENERAL, "You tried to add transport '%s' at '%s:%u' " + "but the same transport already exists at '%s:%u'. " + "Skipping.", t->name, fmt_addr(&t->addr), t->port, + fmt_addr(&t_tmp->addr), t_tmp->port); + return -1; + } + } + } + + return 0; +} + +/** Add transport <b>t</b> to the internal list of pluggable + * transports. + * Returns 0 if the transport was added correctly, 1 if the same + * transport was already registered (in this case the caller must + * free the transport) and -1 if there was an error. */ +int +transport_add(transport_t *t) +{ + int r; + tor_assert(t); + + r = transport_resolve_conflicts(t); + + switch (r) { + case 0: /* should register transport */ + if (!transport_list) + transport_list = smartlist_create(); + smartlist_add(transport_list, t); + return 0; + default: /* let our caller know the return code */ + return r; + } +} + +/** Remember a new pluggable transport proxy at <b>addr</b>:<b>port</b>. + * <b>name</b> is set to the name of the protocol this proxy uses. + * <b>socks_ver</b> is set to the SOCKS version of the proxy. */ +int +transport_add_from_config(const tor_addr_t *addr, uint16_t port, + const char *name, int socks_ver) +{ + transport_t *t = transport_create(addr, port, name, socks_ver); + + int r = transport_add(t); + + switch (r) { + case -1: + default: + log_notice(LD_GENERAL, "Could not add transport %s at %s:%u. Skipping.", + t->name, fmt_addr(&t->addr), t->port); + transport_free(t); + return -1; + case 1: + log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.", + t->name, fmt_addr(&t->addr), t->port); + transport_free(t); /* falling */ + return 0; + case 0: + log_info(LD_GENERAL, "Succesfully registered transport %s at %s:%u.", + t->name, fmt_addr(&t->addr), t->port); + return 0; + } +} + +/** Warn the user of possible pluggable transport misconfiguration. + * Return 0 if the validation happened, -1 if we should postpone the + * validation. */ +int +validate_pluggable_transports_config(void) +{ + /* Don't validate if managed proxies are not yet fully configured. */ + if (bridge_list && !pt_proxies_configuration_pending()) { + SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, b) { + /* Skip bridges without transports. */ + if (!b->transport_name) + continue; + /* See if the user has Bridges that specify nonexistent + pluggable transports. We should warn the user in such case, + since it's probably misconfiguration. */ + if (!transport_get_by_name(b->transport_name)) + log_warn(LD_CONFIG, "You have a Bridge line using the %s " + "pluggable transport, but there doesn't seem to be a " + "corresponding ClientTransportPlugin line.", + b->transport_name); + } SMARTLIST_FOREACH_END(b); + + return 0; + } else { + return -1; + } +} + /** Return a bridge pointer if <b>ri</b> is one of our known bridges * (either by comparing keys if possible, else by comparing addr/port). * Else return NULL. */ @@ -4569,7 +4839,7 @@ get_configured_bridge_by_addr_port_digest(const tor_addr_t *addr, /** Wrapper around get_configured_bridge_by_addr_port_digest() to look * it up via router descriptor <b>ri</b>. */ static bridge_info_t * -get_configured_bridge_by_routerinfo(routerinfo_t *ri) +get_configured_bridge_by_routerinfo(const routerinfo_t *ri) { tor_addr_t addr; tor_addr_from_ipv4h(&addr, ri->addr); @@ -4579,11 +4849,29 @@ get_configured_bridge_by_routerinfo(routerinfo_t *ri) /** Return 1 if <b>ri</b> is one of our known bridges, else 0. */ int -routerinfo_is_a_configured_bridge(routerinfo_t *ri) +routerinfo_is_a_configured_bridge(const routerinfo_t *ri) { return get_configured_bridge_by_routerinfo(ri) ? 1 : 0; } +/** Return 1 if <b>node</b> is one of our configured bridges, else 0. */ +int +node_is_a_configured_bridge(const node_t *node) +{ + tor_addr_t addr; + uint16_t orport; + if (!node) + return 0; + if (node_get_addr(node, &addr) < 0) + return 0; + orport = node_get_orport(node); + if (orport == 0) + return 0; + + return get_configured_bridge_by_addr_port_digest( + &addr, orport, node->identity) != NULL; +} + /** We made a connection to a router at <b>addr</b>:<b>port</b> * without knowing its digest. Its digest turned out to be <b>digest</b>. * If it was a bridge, and we still don't know its digest, record it. @@ -4603,10 +4891,12 @@ learned_router_identity(const tor_addr_t *addr, uint16_t port, /** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b> * is set, it tells us the identity key too. If we already had the - * bridge in our list, unmark it, and don't actually add anything new. */ + * bridge in our list, unmark it, and don't actually add anything new. + * If <b>transport_name</b> is non-NULL - the bridge is associated with a + * pluggable transport - we assign the transport to the bridge. */ void bridge_add_from_config(const tor_addr_t *addr, uint16_t port, - const char *digest) + const char *digest, const char *transport_name) { bridge_info_t *b; @@ -4620,6 +4910,8 @@ bridge_add_from_config(const tor_addr_t *addr, uint16_t port, b->port = port; if (digest) memcpy(b->identity, digest, DIGEST_LEN); + if (transport_name) + b->transport_name = tor_strdup(transport_name); b->fetch_status.schedule = DL_SCHED_BRIDGE; if (!bridge_list) bridge_list = smartlist_create(); @@ -4657,19 +4949,54 @@ find_bridge_by_digest(const char *digest) return NULL; } +/** If <b>addr</b> and <b>port</b> match the address and port of a + * bridge of ours that uses pluggable transports, place its transport + * in <b>transport</b>. + * + * Return 0 on success (found a transport, or found a bridge with no + * transport, or found no bridge); return -1 if we should be using a + * transport, but the transport could not be found. + */ +int +find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port, + const transport_t **transport) +{ + *transport = NULL; + if (!bridge_list) + return 0; + + SMARTLIST_FOREACH_BEGIN(bridge_list, const bridge_info_t *, bridge) { + if (tor_addr_eq(&bridge->addr, addr) && + (bridge->port == port)) { /* bridge matched */ + if (bridge->transport_name) { /* it also uses pluggable transports */ + *transport = transport_get_by_name(bridge->transport_name); + if (*transport == NULL) { /* it uses pluggable transports, but + the transport could not be found! */ + return -1; + } + return 0; + } else { /* bridge matched, but it doesn't use transports. */ + break; + } + } + } SMARTLIST_FOREACH_END(bridge); + + *transport = NULL; + return 0; +} + /** We need to ask <b>bridge</b> for its server descriptor. */ static void launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge) { char *address; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); if (connection_get_by_type_addr_port_purpose( CONN_TYPE_DIR, &bridge->addr, bridge->port, DIR_PURPOSE_FETCH_SERVERDESC)) return; /* it's already on the way */ - address = tor_dup_addr(&bridge->addr); if (routerset_contains_bridge(options->ExcludeNodes, bridge)) { download_status_mark_impossible(&bridge->fetch_status); log_warn(LD_APP, "Not using bridge at %s: it is in ExcludeNodes.", @@ -4677,6 +5004,8 @@ launch_direct_bridge_descriptor_fetch(bridge_info_t *bridge) return; } + address = tor_dup_addr(&bridge->addr); + directory_initiate_command(address, &bridge->addr, bridge->port, 0, 0, /* does not matter */ @@ -4703,15 +5032,20 @@ retry_bridge_descriptor_fetch_directly(const char *digest) * descriptor, fetch a new copy of its descriptor -- either directly * from the bridge or via a bridge authority. */ void -fetch_bridge_descriptors(or_options_t *options, time_t now) +fetch_bridge_descriptors(const or_options_t *options, time_t now) { - int num_bridge_auths = get_n_authorities(BRIDGE_AUTHORITY); + int num_bridge_auths = get_n_authorities(BRIDGE_DIRINFO); int ask_bridge_directly; int can_use_bridge_authority; if (!bridge_list) return; + /* If we still have unconfigured managed proxies, don't go and + connect to a bridge. */ + if (pt_proxies_configuration_pending()) + return; + SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge) { if (!download_status_is_ready(&bridge->fetch_status, now, @@ -4770,26 +5104,55 @@ fetch_bridge_descriptors(or_options_t *options, time_t now) } /** If our <b>bridge</b> is configured to be a different address than - * the bridge gives in its routerinfo <b>ri</b>, rewrite the routerinfo + * the bridge gives in <b>node</b>, rewrite the routerinfo * we received to use the address we meant to use. Now we handle * multihomed bridges better. */ static void -rewrite_routerinfo_address_for_bridge(bridge_info_t *bridge, routerinfo_t *ri) +rewrite_node_address_for_bridge(const bridge_info_t *bridge, node_t *node) { + /* XXXX move this function. */ + /* XXXX overridden addresses should really live in the node_t, so that the + * routerinfo_t and the microdesc_t can be immutable. But we can only + * do that safely if we know that no function that connects to an OR + * does so through an address from any source other than node_get_addr(). + */ tor_addr_t addr; - tor_addr_from_ipv4h(&addr, ri->addr); - if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) && - bridge->port == ri->or_port) - return; /* they match, so no need to do anything */ + if (node->ri) { + routerinfo_t *ri = node->ri; + tor_addr_from_ipv4h(&addr, ri->addr); + + if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) && + bridge->port == ri->or_port) { + /* they match, so no need to do anything */ + } else { + ri->addr = tor_addr_to_ipv4h(&bridge->addr); + tor_free(ri->address); + ri->address = tor_dup_ip(ri->addr); + ri->or_port = bridge->port; + log_info(LD_DIR, + "Adjusted bridge routerinfo for '%s' to match configured " + "address %s:%d.", + ri->nickname, ri->address, ri->or_port); + } + } + if (node->rs) { + routerstatus_t *rs = node->rs; + tor_addr_from_ipv4h(&addr, rs->addr); - ri->addr = tor_addr_to_ipv4h(&bridge->addr); - tor_free(ri->address); - ri->address = tor_dup_ip(ri->addr); - ri->or_port = bridge->port; - log_info(LD_DIR, "Adjusted bridge '%s' to match configured address %s:%d.", - ri->nickname, ri->address, ri->or_port); + if (!tor_addr_compare(&bridge->addr, &addr, CMP_EXACT) && + bridge->port == rs->or_port) { + /* they match, so no need to do anything */ + } else { + rs->addr = tor_addr_to_ipv4h(&bridge->addr); + rs->or_port = bridge->port; + log_info(LD_DIR, + "Adjusted bridge routerstatus for '%s' to match " + "configured address %s:%d.", + rs->nickname, fmt_addr(&bridge->addr), rs->or_port); + } + } } /** We just learned a descriptor for a bridge. See if that @@ -4803,16 +5166,19 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache) int first = !any_bridge_descriptors_known(); bridge_info_t *bridge = get_configured_bridge_by_routerinfo(ri); time_t now = time(NULL); - ri->is_running = 1; + router_set_status(ri->cache_info.identity_digest, 1); if (bridge) { /* if we actually want to use this one */ + node_t *node; /* it's here; schedule its re-fetch for a long time from now. */ if (!from_cache) download_status_reset(&bridge->fetch_status); - rewrite_routerinfo_address_for_bridge(bridge, ri); + node = node_get_mutable_by_id(ri->cache_info.identity_digest); + tor_assert(node); + rewrite_node_address_for_bridge(bridge, node); + add_an_entry_guard(node, 1, 1); - add_an_entry_guard(ri, 1); log_notice(LD_DIR, "new bridge descriptor '%s' (%s)", ri->nickname, from_cache ? "cached" : "fresh"); /* set entry->made_contact so if it goes down we don't drop it from @@ -4865,21 +5231,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 @@ -4888,15 +5253,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; @@ -4905,7 +5270,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); @@ -4913,7 +5278,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); @@ -4931,7 +5296,10 @@ entry_guards_free_all(void) entry_guards = NULL; } clear_bridge_list(); + clear_transport_list(); smartlist_free(bridge_list); + smartlist_free(transport_list); bridge_list = NULL; + transport_list = NULL; } diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h index 0e673e1c05..1052db6153 100644 --- a/src/or/circuitbuild.h +++ b/src/or/circuitbuild.h @@ -12,6 +12,21 @@ #ifndef _TOR_CIRCUITBUILD_H #define _TOR_CIRCUITBUILD_H +/** Represents a pluggable transport proxy used by a bridge. */ +typedef struct { + /** SOCKS version: One of PROXY_SOCKS4, PROXY_SOCKS5. */ + int socks_version; + /** Name of pluggable transport protocol */ + char *name; + /** Address of proxy */ + tor_addr_t addr; + /** Port of proxy */ + uint16_t port; + /** Boolean: We are re-parsing our transport list, and we are going to remove + * this one if we don't find it in the list of configured transports. */ + unsigned marked_for_removal : 1; +} transport_t; + char *circuit_list_path(origin_circuit_t *circ, int verbose); char *circuit_list_path_for_controller(origin_circuit_t *circ); void circuit_log_path(int severity, unsigned int domain, @@ -44,18 +59,19 @@ void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop); extend_info_t *extend_info_alloc(const char *nickname, const char *digest, crypto_pk_env_t *onion_key, const tor_addr_t *addr, uint16_t port); -extend_info_t *extend_info_from_router(routerinfo_t *r); +extend_info_t *extend_info_from_router(const routerinfo_t *r); +extend_info_t *extend_info_from_node(const node_t *node); extend_info_t *extend_info_dup(extend_info_t *info); void extend_info_free(extend_info_t *info); -routerinfo_t *build_state_get_exit_router(cpath_build_state_t *state); +const node_t *build_state_get_exit_node(cpath_build_state_t *state); const char *build_state_get_exit_nickname(cpath_build_state_t *state); -void entry_guards_compute_status(or_options_t *options, time_t now); +void entry_guards_compute_status(const or_options_t *options, time_t now); int entry_guard_register_connect_status(const char *digest, int succeeded, int mark_relay_status, time_t now); void entry_nodes_should_be_added(void); -int entry_list_is_constrained(or_options_t *options); -routerinfo_t *choose_random_entry(cpath_build_state_t *state); +int entry_list_is_constrained(const or_options_t *options); +const node_t *choose_random_entry(cpath_build_state_t *state); int entry_guards_parse_state(or_state_t *state, int set, char **msg); void entry_guards_update_state(or_state_t *state); int getinfo_helper_entry_guards(control_connection_t *conn, @@ -64,18 +80,23 @@ int getinfo_helper_entry_guards(control_connection_t *conn, void mark_bridge_list(void); void sweep_bridge_list(void); -int routerinfo_is_a_configured_bridge(routerinfo_t *ri); +void mark_transport_list(void); +void sweep_transport_list(void); + +int routerinfo_is_a_configured_bridge(const routerinfo_t *ri); +int node_is_a_configured_bridge(const node_t *node); void learned_router_identity(const tor_addr_t *addr, uint16_t port, const char *digest); void bridge_add_from_config(const tor_addr_t *addr, uint16_t port, - const char *digest); + const char *digest, + const char *transport_name); void retry_bridge_descriptor_fetch_directly(const char *digest); -void fetch_bridge_descriptors(or_options_t *options, time_t now); +void fetch_bridge_descriptors(const or_options_t *options, time_t now); void learned_bridge_descriptor(routerinfo_t *ri, int from_cache); int any_bridge_descriptors_known(void); int any_pending_bridge_descriptor_fetches(void); -int entries_known_but_down(or_options_t *options); -void entries_retry_all(or_options_t *options); +int entries_known_but_down(const or_options_t *options); +void entries_retry_all(const or_options_t *options); void entry_guards_free_all(void); @@ -124,5 +145,19 @@ void circuit_build_times_network_circ_success(circuit_build_times_t *cbt); int circuit_build_times_get_bw_scale(networkstatus_t *ns); +void clear_transport_list(void); +int transport_add_from_config(const tor_addr_t *addr, uint16_t port, + const char *name, int socks_ver); +int transport_add(transport_t *t); +void transport_free(transport_t *transport); +transport_t *transport_create(const tor_addr_t *addr, uint16_t port, + const char *name, int socks_ver); + +int find_transport_by_bridge_addrport(const tor_addr_t *addr, uint16_t port, + const transport_t **transport); +transport_t *transport_get_by_name(const char *name); + +int validate_pluggable_transports_config(void); + #endif diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index b25a71e6bd..25b80f11f3 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -19,6 +19,7 @@ #include "connection_or.h" #include "control.h" #include "networkstatus.h" +#include "nodelist.h" #include "onion.h" #include "relay.h" #include "rendclient.h" @@ -86,10 +87,7 @@ orconn_circid_circuit_map_t *_last_circid_orconn_ent = NULL; /** Implementation helper for circuit_set_{p,n}_circid_orconn: A circuit ID * and/or or_connection for circ has just changed from <b>old_conn, old_id</b> * to <b>conn, id</b>. Adjust the conn,circid map as appropriate, removing - * the old entry (if any) and adding a new one. If <b>active</b> is true, - * remove the circuit from the list of active circuits on old_conn and add it - * to the list of active circuits on conn. - * XXX "active" isn't an arg anymore */ + * the old entry (if any) and adding a new one. */ static void circuit_set_circid_orconn_helper(circuit_t *circ, int direction, circid_t id, @@ -552,6 +550,16 @@ circuit_free(circuit_t *circ) crypto_free_pk_env(ocirc->intro_key); rend_data_free(ocirc->rend_data); + + tor_free(ocirc->dest_address); + if (ocirc->socks_username) { + memset(ocirc->socks_username, 0x12, ocirc->socks_username_len); + tor_free(ocirc->socks_username); + } + if (ocirc->socks_password) { + memset(ocirc->socks_password, 0x06, ocirc->socks_password_len); + tor_free(ocirc->socks_password); + } } else { or_circuit_t *ocirc = TO_OR_CIRCUIT(circ); /* Remember cell statistics for this circuit before deallocating. */ @@ -981,7 +989,7 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, int need_uptime = (flags & CIRCLAUNCH_NEED_UPTIME) != 0; int need_capacity = (flags & CIRCLAUNCH_NEED_CAPACITY) != 0; int internal = (flags & CIRCLAUNCH_IS_INTERNAL) != 0; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); /* Make sure we're not trying to create a onehop circ by * cannibalization. */ @@ -1003,19 +1011,20 @@ circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, (!need_capacity || circ->build_state->need_capacity) && (internal == circ->build_state->is_internal) && circ->remaining_relay_early_cells && - !circ->build_state->onehop_tunnel) { + !circ->build_state->onehop_tunnel && + !circ->isolation_values_set) { if (info) { /* need to make sure we don't duplicate hops */ crypt_path_t *hop = circ->cpath; - routerinfo_t *ri1 = router_get_by_digest(info->identity_digest); + const node_t *ri1 = node_get_by_id(info->identity_digest); do { - routerinfo_t *ri2; + const node_t *ri2; if (tor_memeq(hop->extend_info->identity_digest, info->identity_digest, DIGEST_LEN)) goto next; if (ri1 && - (ri2 = router_get_by_digest(hop->extend_info->identity_digest)) - && routers_in_same_family(ri1, ri2)) + (ri2 = node_get_by_id(hop->extend_info->identity_digest)) + && nodes_in_same_family(ri1, ri2)) goto next; hop=hop->next; } while (hop!=circ->cpath); @@ -1100,7 +1109,7 @@ void circuit_expire_all_dirty_circs(void) { circuit_t *circ; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); for (circ=global_circuitlist; circ; circ = circ->next) { if (CIRCUIT_IS_ORIGIN(circ) && @@ -1192,7 +1201,7 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line, } if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); - int timed_out = (reason == END_STREAM_REASON_TIMEOUT); + int timed_out = (reason == END_CIRC_REASON_TIMEOUT); tor_assert(circ->state == CIRCUIT_STATE_OPEN); tor_assert(ocirc->build_state->chosen_exit); tor_assert(ocirc->rend_data); @@ -1207,7 +1216,7 @@ _circuit_mark_for_close(circuit_t *circ, int reason, int line, INTRO_POINT_FAILURE_TIMEOUT : INTRO_POINT_FAILURE_GENERIC); } else if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCING && - reason != END_STREAM_REASON_TIMEOUT) { + reason != END_CIRC_REASON_TIMEOUT) { origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); tor_assert(ocirc->build_state->chosen_exit); tor_assert(ocirc->rend_data); diff --git a/src/or/circuituse.c b/src/or/circuituse.c index f2fd6fe3b4..23efe05348 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -17,6 +17,8 @@ #include "connection.h" #include "connection_edge.h" #include "control.h" +#include "nodelist.h" +#include "networkstatus.h" #include "policies.h" #include "rendclient.h" #include "rendcommon.h" @@ -38,19 +40,19 @@ static void circuit_increment_failure_count(void); * Else return 0. */ static int -circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn, +circuit_is_acceptable(const origin_circuit_t *origin_circ, + const entry_connection_t *conn, int must_be_open, uint8_t purpose, int need_uptime, int need_internal, time_t now) { - routerinfo_t *exitrouter; + const circuit_t *circ = TO_CIRCUIT(origin_circ); + const node_t *exitnode; cpath_build_state_t *build_state; tor_assert(circ); tor_assert(conn); tor_assert(conn->socks_request); - if (!CIRCUIT_IS_ORIGIN(circ)) - return 0; /* this circ doesn't start at us */ if (must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_conn)) return 0; /* ignore non-open circs */ if (circ->marked_for_close) @@ -85,8 +87,8 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn, * circuit, it's the magical extra bob hop. so just check the nickname * of the one we meant to finish at. */ - build_state = TO_ORIGIN_CIRCUIT(circ)->build_state; - exitrouter = build_state_get_exit_router(build_state); + build_state = origin_circ->build_state; + exitnode = build_state_get_exit_node(build_state); if (need_uptime && !build_state->need_uptime) return 0; @@ -94,7 +96,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn, return 0; if (purpose == CIRCUIT_PURPOSE_C_GENERAL) { - if (!exitrouter && !build_state->onehop_tunnel) { + if (!exitnode && !build_state->onehop_tunnel) { log_debug(LD_CIRC,"Not considering circuit with unknown router."); return 0; /* this circuit is screwed and doesn't know it yet, * or is a rendezvous circuit. */ @@ -115,7 +117,7 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn, if (tor_digest_is_zero(digest)) { /* we don't know the digest; have to compare addr:port */ tor_addr_t addr; - int r = tor_addr_from_str(&addr, conn->socks_request->address); + int r = tor_addr_parse(&addr, conn->socks_request->address); if (r < 0 || !tor_addr_eq(&build_state->chosen_exit->addr, &addr) || build_state->chosen_exit->port != conn->socks_request->port) @@ -128,30 +130,43 @@ circuit_is_acceptable(circuit_t *circ, edge_connection_t *conn, return 0; } } - if (exitrouter && !connection_ap_can_use_exit(conn, exitrouter)) { + if (exitnode && !connection_ap_can_use_exit(conn, exitnode)) { /* can't exit from this router */ return 0; } } else { /* not general */ - origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ); - if ((conn->rend_data && !ocirc->rend_data) || - (!conn->rend_data && ocirc->rend_data) || - (conn->rend_data && ocirc->rend_data && - rend_cmp_service_ids(conn->rend_data->onion_address, - ocirc->rend_data->onion_address))) { + const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn); + if ((edge_conn->rend_data && !origin_circ->rend_data) || + (!edge_conn->rend_data && origin_circ->rend_data) || + (edge_conn->rend_data && origin_circ->rend_data && + rend_cmp_service_ids(edge_conn->rend_data->onion_address, + origin_circ->rend_data->onion_address))) { /* this circ is not for this conn */ return 0; } } + + if (!connection_edge_compatible_with_circuit(conn, origin_circ)) { + /* conn needs to be isolated from other conns that have already used + * origin_circ */ + return 0; + } + return 1; } /** Return 1 if circuit <b>a</b> is better than circuit <b>b</b> for - * <b>purpose</b>, and return 0 otherwise. Used by circuit_get_best. + * <b>conn</b>, and return 0 otherwise. Used by circuit_get_best. */ static int -circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose) +circuit_is_better(const origin_circuit_t *oa, const origin_circuit_t *ob, + const entry_connection_t *conn) { + const circuit_t *a = TO_CIRCUIT(oa); + const circuit_t *b = TO_CIRCUIT(ob); + const uint8_t purpose = ENTRY_TO_CONN(conn)->purpose; + int a_bits, b_bits; + switch (purpose) { case CIRCUIT_PURPOSE_C_GENERAL: /* if it's used but less dirty it's best; @@ -165,8 +180,7 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose) if (a->timestamp_dirty || timercmp(&a->timestamp_created, &b->timestamp_created, >)) return 1; - if (CIRCUIT_IS_ORIGIN(b) && - TO_ORIGIN_CIRCUIT(b)->build_state->is_internal) + if (ob->build_state->is_internal) /* XXX023 what the heck is this internal thing doing here. I * think we can get rid of it. circuit_is_acceptable() already * makes sure that is_internal is exactly what we need it to @@ -185,6 +199,29 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose) return 1; break; } + + /* XXXX023 Maybe this check should get a higher priority to avoid + * using up circuits too rapidly. */ + + a_bits = connection_edge_update_circuit_isolation(conn, + (origin_circuit_t*)oa, 1); + b_bits = connection_edge_update_circuit_isolation(conn, + (origin_circuit_t*)ob, 1); + /* if x_bits < 0, then we have not used x for anything; better not to dirty + * a connection if we can help it. */ + if (a_bits < 0) { + return 0; + } else if (b_bits < 0) { + return 1; + } + a_bits &= ~ oa->isolation_flags_mixed; + a_bits &= ~ ob->isolation_flags_mixed; + if (n_bits_set_u8(a_bits) < n_bits_set_u8(b_bits)) { + /* The fewer new restrictions we need to make on a circuit for stream + * isolation, the better. */ + return 1; + } + return 0; } @@ -205,10 +242,12 @@ circuit_is_better(circuit_t *a, circuit_t *b, uint8_t purpose) * closest introduce-purposed circuit that you can find. */ static origin_circuit_t * -circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose, +circuit_get_best(const entry_connection_t *conn, + int must_be_open, uint8_t purpose, int need_uptime, int need_internal) { - circuit_t *circ, *best=NULL; + circuit_t *circ; + origin_circuit_t *best=NULL; struct timeval now; int intro_going_on_but_too_old = 0; @@ -221,7 +260,11 @@ circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose, tor_gettimeofday(&now); for (circ=global_circuitlist;circ;circ = circ->next) { - if (!circuit_is_acceptable(circ,conn,must_be_open,purpose, + origin_circuit_t *origin_circ; + if (!CIRCUIT_IS_ORIGIN(circ)) + continue; + origin_circ = TO_ORIGIN_CIRCUIT(circ); + if (!circuit_is_acceptable(origin_circ,conn,must_be_open,purpose, need_uptime,need_internal,now.tv_sec)) continue; @@ -235,8 +278,8 @@ circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose, /* now this is an acceptable circ to hand back. but that doesn't * mean it's the *best* circ to hand back. try to decide. */ - if (!best || circuit_is_better(circ,best,purpose)) - best = circ; + if (!best || circuit_is_better(origin_circ,best,conn)) + best = origin_circ; } if (!best && intro_going_on_but_too_old) @@ -244,7 +287,28 @@ circuit_get_best(edge_connection_t *conn, int must_be_open, uint8_t purpose, "right now, but it has already taken quite a while. Starting " "one in parallel."); - return best ? TO_ORIGIN_CIRCUIT(best) : NULL; + return best; +} + +/** Return the number of not-yet-open general-purpose origin circuits. */ +static int +count_pending_general_client_circuits(void) +{ + const circuit_t *circ; + + int count = 0; + + for (circ = global_circuitlist; circ; circ = circ->next) { + if (circ->marked_for_close || + circ->state == CIRCUIT_STATE_OPEN || + circ->purpose != CIRCUIT_PURPOSE_C_GENERAL || + !CIRCUIT_IS_ORIGIN(circ)) + continue; + + ++count; + } + + return count; } #if 0 @@ -481,11 +545,11 @@ circuit_remove_handled_ports(smartlist_t *needed_ports) * Else return 0. */ int -circuit_stream_is_being_handled(edge_connection_t *conn, +circuit_stream_is_being_handled(entry_connection_t *conn, uint16_t port, int min) { circuit_t *circ; - routerinfo_t *exitrouter; + const node_t *exitnode; int num=0; time_t now = time(NULL); int need_uptime = smartlist_string_num_isin(get_options()->LongLivedPorts, @@ -501,14 +565,14 @@ circuit_stream_is_being_handled(edge_connection_t *conn, if (build_state->is_internal || build_state->onehop_tunnel) continue; - exitrouter = build_state_get_exit_router(build_state); - if (exitrouter && (!need_uptime || build_state->need_uptime)) { + exitnode = build_state_get_exit_node(build_state); + if (exitnode && (!need_uptime || build_state->need_uptime)) { int ok; if (conn) { - ok = connection_ap_can_use_exit(conn, exitrouter); + ok = connection_ap_can_use_exit(conn, exitnode); } else { - addr_policy_result_t r = compare_addr_to_addr_policy( - 0, port, exitrouter->exit_policy); + addr_policy_result_t r; + r = compare_tor_addr_to_node_policy(NULL, port, exitnode); ok = r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED; } if (ok) { @@ -575,7 +639,7 @@ circuit_predict_and_launch_new(void) log_info(LD_CIRC, "Have %d clean circs (%d internal), need another exit circ.", num, num_internal); - circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags); + circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags); return; } @@ -587,7 +651,7 @@ circuit_predict_and_launch_new(void) "Have %d clean circs (%d internal), need another internal " "circ for my hidden service.", num, num_internal); - circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags); + circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags); return; } @@ -605,7 +669,7 @@ circuit_predict_and_launch_new(void) "Have %d clean circs (%d uptime-internal, %d internal), need" " another hidden service circ.", num, num_uptime_internal, num_internal); - circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags); + circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags); return; } @@ -618,7 +682,7 @@ circuit_predict_and_launch_new(void) flags = CIRCLAUNCH_NEED_CAPACITY; log_info(LD_CIRC, "Have %d clean circs need another buildtime test circ.", num); - circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, flags); + circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, flags); return; } } @@ -635,7 +699,7 @@ void circuit_build_needed_circs(time_t now) { static time_t time_to_new_circuit = 0; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); /* launch a new circ for any pending streams that need one */ connection_ap_attach_pending(); @@ -654,9 +718,9 @@ circuit_build_needed_circs(time_t now) circ = circuit_get_youngest_clean_open(CIRCUIT_PURPOSE_C_GENERAL); if (get_options()->RunTesting && circ && - circ->timestamp_created + TESTING_CIRCUIT_INTERVAL < now) { + circ->timestamp_created.tv_sec + TESTING_CIRCUIT_INTERVAL < now) { log_fn(LOG_INFO,"Creating a new testing circuit."); - circuit_launch_by_router(CIRCUIT_PURPOSE_C_GENERAL, NULL, 0); + circuit_launch(CIRCUIT_PURPOSE_C_GENERAL, 0); } #endif } @@ -675,7 +739,11 @@ circuit_detach_stream(circuit_t *circ, edge_connection_t *conn) tor_assert(circ); tor_assert(conn); - conn->cpath_layer = NULL; /* make sure we don't keep a stale pointer */ + if (conn->_base.type == CONN_TYPE_AP) { + entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn); + entry_conn->may_use_optimistic_data = 0; + } + conn->cpath_layer = NULL; /* don't keep a stale pointer */ conn->on_circuit = NULL; if (CIRCUIT_IS_ORIGIN(circ)) { @@ -936,6 +1004,7 @@ circuit_testing_failed(origin_circuit_t *circ, int at_last_hop) void circuit_has_opened(origin_circuit_t *circ) { + int can_try_clearing_isolation = 0, tried_clearing_isolation = 0; control_event_circuit_status(circ, CIRC_EVENT_BUILT, 0); /* Remember that this circuit has finished building. Now if we start @@ -943,9 +1012,12 @@ circuit_has_opened(origin_circuit_t *circ) * to consider its build time. */ circ->has_opened = 1; + again: + switch (TO_CIRCUIT(circ)->purpose) { case CIRCUIT_PURPOSE_C_ESTABLISH_REND: rend_client_rendcirc_has_opened(circ); + can_try_clearing_isolation = 1; connection_ap_attach_pending(); break; case CIRCUIT_PURPOSE_C_INTRODUCING: @@ -954,6 +1026,7 @@ circuit_has_opened(origin_circuit_t *circ) case CIRCUIT_PURPOSE_C_GENERAL: /* Tell any AP connections that have been waiting for a new * circuit that one is ready. */ + can_try_clearing_isolation = 1; connection_ap_attach_pending(); break; case CIRCUIT_PURPOSE_S_ESTABLISH_INTRO: @@ -971,6 +1044,24 @@ circuit_has_opened(origin_circuit_t *circ) * This won't happen in normal operation, but might happen if the * controller did it. Just let it slide. */ } + + if (/* The circuit may have become non-open if it was cannibalized.*/ + circ->_base.state == CIRCUIT_STATE_OPEN && + /* Only if the purpose is clearable, and only if we haven't tried + * to clear isolation yet, do we try. */ + can_try_clearing_isolation && !tried_clearing_isolation && + /* If !isolation_values_set, there is nothing to clear. */ + circ->isolation_values_set && + /* It's not legal to clear a circuit's isolation info if it's ever had + * streams attached */ + !circ->isolation_any_streams_attached) { + /* If we have any isolation information set on this circuit, and + * we didn't manage to attach any streams to it, then we can + * and should clear it and try again. */ + circuit_clear_isolation(circ); + tried_clearing_isolation = 1; + goto again; + } } /** Called whenever a circuit could not be successfully built. @@ -1091,17 +1182,9 @@ static int did_circs_fail_last_period = 0; /** Launch a new circuit; see circuit_launch_by_extend_info() for * details on arguments. */ origin_circuit_t * -circuit_launch_by_router(uint8_t purpose, - routerinfo_t *exit, int flags) +circuit_launch(uint8_t purpose, int flags) { - origin_circuit_t *circ; - extend_info_t *info = NULL; - if (exit) - info = extend_info_from_router(exit); - circ = circuit_launch_by_extend_info(purpose, info, flags); - - extend_info_free(info); - return circ; + return circuit_launch_by_extend_info(purpose, NULL, flags); } /** Launch a new circuit with purpose <b>purpose</b> and exit node @@ -1207,7 +1290,7 @@ circuit_reset_failure_count(int timeout) * Write the found or in-progress or launched circ into *circp. */ static int -circuit_get_open_circ_or_launch(edge_connection_t *conn, +circuit_get_open_circ_or_launch(entry_connection_t *conn, uint8_t desired_circuit_purpose, origin_circuit_t **circp) { @@ -1215,15 +1298,15 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, int check_exit_policy; int need_uptime, need_internal; int want_onehop; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); tor_assert(conn); tor_assert(circp); - tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT); + tor_assert(ENTRY_TO_CONN(conn)->state == AP_CONN_STATE_CIRCUIT_WAIT); check_exit_policy = conn->socks_request->command == SOCKS_COMMAND_CONNECT && !conn->use_begindir && - !connection_edge_is_rendezvous_stream(conn); + !connection_edge_is_rendezvous_stream(ENTRY_TO_EDGE_CONN(conn)); want_onehop = conn->want_onehop; need_uptime = !conn->want_onehop && !conn->use_begindir && @@ -1269,12 +1352,14 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, if (check_exit_policy) { if (!conn->chosen_exit_name) { struct in_addr in; - uint32_t addr = 0; - if (tor_inet_aton(conn->socks_request->address, &in)) - addr = ntohl(in.s_addr); - if (router_exit_policy_all_routers_reject(addr, - conn->socks_request->port, - need_uptime)) { + tor_addr_t addr, *addrp=NULL; + if (tor_inet_aton(conn->socks_request->address, &in)) { + tor_addr_from_in(&addr, &in); + addrp = &addr; + } + if (router_exit_policy_all_nodes_reject(addrp, + conn->socks_request->port, + need_uptime)) { log_notice(LD_APP, "No Tor server allows exit to %s:%d. Rejecting.", safe_str_client(conn->socks_request->address), @@ -1284,9 +1369,9 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, } else { /* XXXX023 Duplicates checks in connection_ap_handshake_attach_circuit: * refactor into a single function? */ - routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1); + const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1); int opt = conn->chosen_exit_optional; - if (router && !connection_ap_can_use_exit(conn, router)) { + if (node && !connection_ap_can_use_exit(conn, node)) { log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP, "Requested exit point '%s' is excluded or " "would refuse request. %s.", @@ -1312,22 +1397,37 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, if (!circ) { extend_info_t *extend_info=NULL; uint8_t new_circ_purpose; + const int n_pending = count_pending_general_client_circuits(); + + if (n_pending >= options->MaxClientCircuitsPending) { + static ratelim_t delay_limit = RATELIM_INIT(10*60); + char *m; + if ((m = rate_limit_log(&delay_limit, approx_time()))) { + log_notice(LD_APP, "We'd like to launch a circuit to handle a " + "connection, but we already have %d general-purpose client " + "circuits pending. Waiting until some finish.", + n_pending); + tor_free(m); + } + return 0; + } if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) { /* need to pick an intro point */ - tor_assert(conn->rend_data); - extend_info = rend_client_get_random_intro(conn->rend_data); + rend_data_t *rend_data = ENTRY_TO_EDGE_CONN(conn)->rend_data; + tor_assert(rend_data); + extend_info = rend_client_get_random_intro(rend_data); if (!extend_info) { log_info(LD_REND, "No intro points for '%s': re-fetching service descriptor.", - safe_str_client(conn->rend_data->onion_address)); - rend_client_refetch_v2_renddesc(conn->rend_data); - conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT; + safe_str_client(rend_data->onion_address)); + rend_client_refetch_v2_renddesc(rend_data); + ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_RENDDESC_WAIT; return 0; } log_info(LD_REND,"Chose %s as intro point for '%s'.", extend_info_describe(extend_info), - safe_str_client(conn->rend_data->onion_address)); + safe_str_client(rend_data->onion_address)); } /* If we have specified a particular exit node for our @@ -1335,11 +1435,11 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, */ if (desired_circuit_purpose == CIRCUIT_PURPOSE_C_GENERAL) { if (conn->chosen_exit_name) { - routerinfo_t *r; + const node_t *r; int opt = conn->chosen_exit_optional; - r = router_get_by_nickname(conn->chosen_exit_name, 1); - if (r) { - extend_info = extend_info_from_router(r); + r = node_get_by_nickname(conn->chosen_exit_name, 1); + if (r && node_has_descriptor(r)) { + extend_info = extend_info_from_node(r); } else { log_debug(LD_DIR, "considering %d, %s", want_onehop, conn->chosen_exit_name); @@ -1354,7 +1454,7 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, log_info(LD_DIR, "Broken exit digest on tunnel conn. Closing."); return -1; } - if (tor_addr_from_str(&addr, conn->socks_request->address) < 0) { + if (tor_addr_parse(&addr, conn->socks_request->address) < 0) { log_info(LD_DIR, "Broken address %s on tunnel conn. Closing.", escaped_safe_str_client(conn->socks_request->address)); return -1; @@ -1416,18 +1516,26 @@ circuit_get_open_circ_or_launch(edge_connection_t *conn, rep_hist_note_used_internal(time(NULL), need_uptime, 1); if (circ) { /* write the service_id into circ */ - circ->rend_data = rend_data_dup(conn->rend_data); + circ->rend_data = rend_data_dup(ENTRY_TO_EDGE_CONN(conn)->rend_data); if (circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND && circ->_base.state == CIRCUIT_STATE_OPEN) rend_client_rendcirc_has_opened(circ); } } - } - if (!circ) + } /* endif (!circ) */ + if (circ) { + /* Mark the circuit with the isolation fields for this connection. + * When the circuit arrives, we'll clear these flags: this is + * just some internal bookkeeping to make sure that we have + * launched enough circuits. + */ + connection_edge_update_circuit_isolation(conn, circ, 0); + } else { log_info(LD_APP, "No safe circuit (purpose %d) ready for edge " "connection; delaying.", desired_circuit_purpose); + } *circp = circ; return 0; } @@ -1446,46 +1554,86 @@ cpath_is_on_circuit(origin_circuit_t *circ, crypt_path_t *crypt_path) return 0; } +/** Return true iff client-side optimistic data is supported. */ +static int +optimistic_data_enabled(void) +{ + const or_options_t *options = get_options(); + if (options->OptimisticData < 0) { + /* XXX023 consider having auto default to 1 rather than 0 before + * the 0.2.3 branch goes stable. See bug 3617. -RD */ + const int32_t enabled = + networkstatus_get_param(NULL, "UseOptimisticData", 0, 0, 1); + return (int)enabled; + } + return options->OptimisticData; +} + /** Attach the AP stream <b>apconn</b> to circ's linked list of * p_streams. Also set apconn's cpath_layer to <b>cpath</b>, or to the last * hop in circ's cpath if <b>cpath</b> is NULL. */ static void -link_apconn_to_circ(edge_connection_t *apconn, origin_circuit_t *circ, +link_apconn_to_circ(entry_connection_t *apconn, origin_circuit_t *circ, crypt_path_t *cpath) { + const node_t *exitnode; + /* add it into the linked list of streams on this circuit */ log_debug(LD_APP|LD_CIRC, "attaching new conn to circ. n_circ_id %d.", circ->_base.n_circ_id); /* reset it, so we can measure circ timeouts */ - apconn->_base.timestamp_lastread = time(NULL); - apconn->next_stream = circ->p_streams; - apconn->on_circuit = TO_CIRCUIT(circ); + ENTRY_TO_CONN(apconn)->timestamp_lastread = time(NULL); + ENTRY_TO_EDGE_CONN(apconn)->next_stream = circ->p_streams; + ENTRY_TO_EDGE_CONN(apconn)->on_circuit = TO_CIRCUIT(circ); /* assert_connection_ok(conn, time(NULL)); */ - circ->p_streams = apconn; + circ->p_streams = ENTRY_TO_EDGE_CONN(apconn); - if (connection_edge_is_rendezvous_stream(apconn)) { + if (connection_edge_is_rendezvous_stream(ENTRY_TO_EDGE_CONN(apconn))) { /* We are attaching a stream to a rendezvous circuit. That means * that an attempt to connect to a hidden service just * succeeded. Tell rendclient.c. */ - rend_client_note_connection_attempt_ended(apconn->rend_data->onion_address); + rend_client_note_connection_attempt_ended( + ENTRY_TO_EDGE_CONN(apconn)->rend_data->onion_address); } if (cpath) { /* we were given one; use it */ tor_assert(cpath_is_on_circuit(circ, cpath)); - apconn->cpath_layer = cpath; - } else { /* use the last hop in the circuit */ + } else { + /* use the last hop in the circuit */ tor_assert(circ->cpath); tor_assert(circ->cpath->prev); tor_assert(circ->cpath->prev->state == CPATH_STATE_OPEN); - apconn->cpath_layer = circ->cpath->prev; + cpath = circ->cpath->prev; + } + ENTRY_TO_EDGE_CONN(apconn)->cpath_layer = cpath; + + circ->isolation_any_streams_attached = 1; + connection_edge_update_circuit_isolation(apconn, circ, 0); + + /* See if we can use optimistic data on this circuit */ + if (cpath->extend_info && + (exitnode = node_get_by_id(cpath->extend_info->identity_digest)) && + exitnode->rs) { + /* Okay; we know what exit node this is. */ + if (optimistic_data_enabled() && + circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL && + exitnode->rs->version_supports_optimistic_data) + apconn->may_use_optimistic_data = 1; + else + apconn->may_use_optimistic_data = 0; + log_info(LD_APP, "Looks like completed circuit to %s %s allow " + "optimistic data for connection to %s", + safe_str_client(node_describe(exitnode)), + apconn->may_use_optimistic_data ? "does" : "doesn't", + safe_str_client(apconn->socks_request->address)); } } /** Return true iff <b>address</b> is matched by one of the entries in * TrackHostExits. */ int -hostname_in_track_host_exits(or_options_t *options, const char *address) +hostname_in_track_host_exits(const or_options_t *options, const char *address) { if (!options->TrackHostExits) return 0; @@ -1507,9 +1655,10 @@ hostname_in_track_host_exits(or_options_t *options, const char *address) * <b>conn</b>'s destination. */ static void -consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ) +consider_recording_trackhost(const entry_connection_t *conn, + const origin_circuit_t *circ) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); char *new_address = NULL; char fp[HEX_DIGEST_LEN+1]; @@ -1544,18 +1693,19 @@ consider_recording_trackhost(edge_connection_t *conn, origin_circuit_t *circ) * indicated by <b>cpath</b>, or from the last hop in circ's cpath if * <b>cpath</b> is NULL. */ int -connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn, +connection_ap_handshake_attach_chosen_circuit(entry_connection_t *conn, origin_circuit_t *circ, crypt_path_t *cpath) { + connection_t *base_conn = ENTRY_TO_CONN(conn); tor_assert(conn); - tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT || - conn->_base.state == AP_CONN_STATE_CONTROLLER_WAIT); + tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT || + base_conn->state == AP_CONN_STATE_CONTROLLER_WAIT); tor_assert(conn->socks_request); tor_assert(circ); tor_assert(circ->_base.state == CIRCUIT_STATE_OPEN); - conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT; + base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT; if (!circ->_base.timestamp_dirty) circ->_base.timestamp_dirty = time(NULL); @@ -1585,21 +1735,22 @@ connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn, /* XXXX this function should mark for close whenever it returns -1; * its callers shouldn't have to worry about that. */ int -connection_ap_handshake_attach_circuit(edge_connection_t *conn) +connection_ap_handshake_attach_circuit(entry_connection_t *conn) { + connection_t *base_conn = ENTRY_TO_CONN(conn); int retval; int conn_age; int want_onehop; tor_assert(conn); - tor_assert(conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT); + tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT); tor_assert(conn->socks_request); want_onehop = conn->want_onehop; - conn_age = (int)(time(NULL) - conn->_base.timestamp_created); + conn_age = (int)(time(NULL) - base_conn->timestamp_created); if (conn_age >= get_options()->SocksTimeout) { - int severity = (tor_addr_is_null(&conn->_base.addr) && !conn->_base.port) ? + int severity = (tor_addr_is_null(&base_conn->addr) && !base_conn->port) ? LOG_INFO : LOG_NOTICE; log_fn(severity, LD_APP, "Tried for %d seconds to get a connection to %s:%d. Giving up.", @@ -1608,13 +1759,14 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn) return -1; } - if (!connection_edge_is_rendezvous_stream(conn)) { /* we're a general conn */ + if (!connection_edge_is_rendezvous_stream(ENTRY_TO_EDGE_CONN(conn))) { + /* we're a general conn */ origin_circuit_t *circ=NULL; if (conn->chosen_exit_name) { - routerinfo_t *router = router_get_by_nickname(conn->chosen_exit_name, 1); + const node_t *node = node_get_by_nickname(conn->chosen_exit_name, 1); int opt = conn->chosen_exit_optional; - if (!router && !want_onehop) { + if (!node && !want_onehop) { /* We ran into this warning when trying to extend a circuit to a * hidden service directory for which we didn't have a router * descriptor. See flyspray task 767 for more details. We should @@ -1630,7 +1782,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn) } return -1; } - if (router && !connection_ap_can_use_exit(conn, router)) { + if (node && !connection_ap_can_use_exit(conn, node)) { log_fn(opt ? LOG_INFO : LOG_WARN, LD_APP, "Requested exit point '%s' is excluded or " "would refuse request. %s.", @@ -1663,7 +1815,7 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn) } else { /* we're a rendezvous conn */ origin_circuit_t *rendcirc=NULL, *introcirc=NULL; - tor_assert(!conn->cpath_layer); + tor_assert(!ENTRY_TO_EDGE_CONN(conn)->cpath_layer); /* start by finding a rendezvous circuit for us */ @@ -1719,8 +1871,9 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn) !c->marked_for_close && CIRCUIT_IS_ORIGIN(c)) { origin_circuit_t *oc = TO_ORIGIN_CIRCUIT(c); if (oc->rend_data && - !rend_cmp_service_ids(conn->rend_data->onion_address, - oc->rend_data->onion_address)) { + !rend_cmp_service_ids( + ENTRY_TO_EDGE_CONN(conn)->rend_data->onion_address, + oc->rend_data->onion_address)) { log_info(LD_REND|LD_CIRC, "Closing introduction circuit that we " "built in parallel."); circuit_mark_for_close(c, END_CIRC_REASON_TIMEOUT); diff --git a/src/or/circuituse.h b/src/or/circuituse.h index bfeaea20dc..9867fd8205 100644 --- a/src/or/circuituse.h +++ b/src/or/circuituse.h @@ -14,7 +14,7 @@ void circuit_expire_building(void); void circuit_remove_handled_ports(smartlist_t *needed_ports); -int circuit_stream_is_being_handled(edge_connection_t *conn, uint16_t port, +int circuit_stream_is_being_handled(entry_connection_t *conn, uint16_t port, int min); #if 0 int circuit_conforms_to_options(const origin_circuit_t *circ, @@ -43,15 +43,15 @@ void circuit_build_failed(origin_circuit_t *circ); origin_circuit_t *circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *info, int flags); -origin_circuit_t *circuit_launch_by_router(uint8_t purpose, - routerinfo_t *exit, int flags); +origin_circuit_t *circuit_launch(uint8_t purpose, int flags); void circuit_reset_failure_count(int timeout); -int connection_ap_handshake_attach_chosen_circuit(edge_connection_t *conn, +int connection_ap_handshake_attach_chosen_circuit(entry_connection_t *conn, origin_circuit_t *circ, crypt_path_t *cpath); -int connection_ap_handshake_attach_circuit(edge_connection_t *conn); +int connection_ap_handshake_attach_circuit(entry_connection_t *conn); -int hostname_in_track_host_exits(or_options_t *options, const char *address); +int hostname_in_track_host_exits(const or_options_t *options, + const char *address); #endif diff --git a/src/or/command.c b/src/or/command.c index 12b4c30f5c..023f2bead5 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" @@ -45,6 +46,15 @@ uint64_t stats_n_versions_cells_processed = 0; /** How many CELL_NETINFO cells have we received, ever? */ uint64_t stats_n_netinfo_cells_processed = 0; +/** How many CELL_VPADDING cells have we received, ever? */ +uint64_t stats_n_vpadding_cells_processed = 0; +/** How many CELL_CERTS cells have we received, ever? */ +uint64_t stats_n_certs_cells_processed = 0; +/** How many CELL_AUTH_CHALLENGE cells have we received, ever? */ +uint64_t stats_n_auth_challenge_cells_processed = 0; +/** How many CELL_AUTHENTICATE cells have we received, ever? */ +uint64_t stats_n_authenticate_cells_processed = 0; + /* These are the main functions for processing cells */ static void command_process_create_cell(cell_t *cell, or_connection_t *conn); static void command_process_created_cell(cell_t *cell, or_connection_t *conn); @@ -53,6 +63,12 @@ static void command_process_destroy_cell(cell_t *cell, or_connection_t *conn); static void command_process_versions_cell(var_cell_t *cell, or_connection_t *conn); static void command_process_netinfo_cell(cell_t *cell, or_connection_t *conn); +static void command_process_certs_cell(var_cell_t *cell, + or_connection_t *conn); +static void command_process_auth_challenge_cell(var_cell_t *cell, + or_connection_t *conn); +static void command_process_authenticate_cell(var_cell_t *cell, + or_connection_t *conn); #ifdef KEEP_TIMING_STATS /** This is a wrapper function around the actual function that processes the @@ -92,7 +108,7 @@ command_time_process_cell(cell_t *cell, or_connection_t *conn, int *time, void command_process_cell(cell_t *cell, or_connection_t *conn) { - int handshaking = (conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING); + int handshaking = (conn->_base.state != OR_CONN_STATE_OPEN); #ifdef KEEP_TIMING_STATS /* how many of each cell have we seen so far this second? needs better * name. */ @@ -132,10 +148,22 @@ command_process_cell(cell_t *cell, or_connection_t *conn) #define PROCESS_CELL(tp, cl, cn) command_process_ ## tp ## _cell(cl, cn) #endif + if (conn->_base.marked_for_close) + return; + /* Reject all but VERSIONS and NETINFO when handshaking. */ + /* (VERSIONS should actually be impossible; it's variable-length.) */ if (handshaking && cell->command != CELL_VERSIONS && - cell->command != CELL_NETINFO) + cell->command != CELL_NETINFO) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Received unexpected cell command %d in state %s; ignoring it.", + (int)cell->command, + conn_state_to_string(CONN_TYPE_OR,conn->_base.state)); return; + } + + if (conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3) + or_handshake_state_record_cell(conn->handshake_state, cell, 1); switch (cell->command) { case CELL_PADDING: @@ -186,39 +214,101 @@ command_process_var_cell(var_cell_t *cell, or_connection_t *conn) #ifdef KEEP_TIMING_STATS /* how many of each cell have we seen so far this second? needs better * name. */ - static int num_versions=0, num_cert=0; + static int num_versions=0, num_certs=0; time_t now = time(NULL); if (now > current_second) { /* the second has rolled over */ /* print stats */ log_info(LD_OR, - "At end of second: %d versions (%d ms), %d cert (%d ms)", + "At end of second: %d versions (%d ms), %d certs (%d ms)", num_versions, versions_time/1000, - cert, cert_time/1000); + num_certs, certs_time/1000); - num_versions = num_cert = 0; - versions_time = cert_time = 0; + num_versions = num_certs = 0; + versions_time = certs_time = 0; /* remember which second it is, for next time */ current_second = now; } #endif - /* reject all when not handshaking. */ - if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING) + if (conn->_base.marked_for_close) return; + switch (conn->_base.state) + { + case OR_CONN_STATE_OR_HANDSHAKING_V2: + if (cell->command != CELL_VERSIONS) + return; + break; + case OR_CONN_STATE_TLS_HANDSHAKING: + /* If we're using bufferevents, it's entirely possible for us to + * notice "hey, data arrived!" before we notice "hey, the handshake + * finished!" And we need to be accepting both at once to handle both + * the v2 and v3 handshakes. */ + + /* fall through */ + case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING: + if (cell->command != CELL_VERSIONS) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Received a non-VERSIONS cell with command %d in state %s; " + "ignoring it.", + (int)cell->command, + conn_state_to_string(CONN_TYPE_OR,conn->_base.state)); + return; + } + break; + case OR_CONN_STATE_OR_HANDSHAKING_V3: + if (cell->command != CELL_AUTHENTICATE) + or_handshake_state_record_var_cell(conn->handshake_state, cell, 1); + break; /* Everything is allowed */ + case OR_CONN_STATE_OPEN: + if (conn->link_proto < 3) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Received a variable-length cell with command %d in state %s " + "with link protocol %d; ignoring it.", + (int)cell->command, + conn_state_to_string(CONN_TYPE_OR,conn->_base.state), + (int)conn->link_proto); + return; + } + break; + default: + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Received var-length cell with command %d in unexpected state " + "%s [%d]; ignoring it.", + (int)cell->command, + conn_state_to_string(CONN_TYPE_OR,conn->_base.state), + (int)conn->_base.state); + return; + } + switch (cell->command) { case CELL_VERSIONS: ++stats_n_versions_cells_processed; PROCESS_CELL(versions, cell, conn); break; + case CELL_VPADDING: + ++stats_n_vpadding_cells_processed; + /* Do nothing */ + break; + case CELL_CERTS: + ++stats_n_certs_cells_processed; + PROCESS_CELL(certs, cell, conn); + break; + case CELL_AUTH_CHALLENGE: + ++stats_n_auth_challenge_cells_processed; + PROCESS_CELL(auth_challenge, cell, conn); + break; + case CELL_AUTHENTICATE: + ++stats_n_authenticate_cells_processed; + PROCESS_CELL(authenticate, cell, conn); + break; default: - log_warn(LD_BUG, + log_fn(LOG_INFO, LD_PROTOCOL, "Variable-length cell of unknown type (%d) received.", cell->command); - tor_fragile_assert(); break; } } @@ -232,6 +322,7 @@ static void command_process_create_cell(cell_t *cell, or_connection_t *conn) { or_circuit_t *circ; + const or_options_t *options = get_options(); int id_is_high; if (we_are_hibernating()) { @@ -243,9 +334,11 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn) return; } - if (!server_mode(get_options())) { + if (!server_mode(options) || + (!public_server_mode(options) && conn->is_outgoing)) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Received create cell (type %d) from %s:%d, but we're a client. " + "Received create cell (type %d) from %s:%d, but we're connected " + "to it as a client. " "Sending back a destroy.", (int)cell->command, conn->_base.address, conn->_base.port); connection_or_send_destroy(cell->circ_id, conn, @@ -267,15 +360,18 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn) } if (circuit_id_in_use_on_orconn(cell->circ_id, conn)) { - routerinfo_t *router = router_get_by_digest(conn->identity_digest); + const node_t *node = node_get_by_id(conn->identity_digest); log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Received CREATE cell (circID %d) for known circ. " "Dropping (age %d).", cell->circ_id, (int)(time(NULL) - conn->_base.timestamp_created)); - if (router) + if (node) { + char *p = esc_for_log(node_get_platform(node)); log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Details: router %s, platform %s.", - router_describe(router), escaped(router->platform)); + node_describe(node), p); + tor_free(p); + } return; } @@ -305,7 +401,13 @@ command_process_create_cell(cell_t *cell, or_connection_t *conn) * a CPU worker. */ char keys[CPATH_KEY_MATERIAL_LEN]; char reply[DIGEST_LEN*2]; + tor_assert(cell->command == CELL_CREATE_FAST); + + /* Make sure we never try to use the OR connection on which we + * received this cell to satisfy an EXTEND request, */ + conn->is_connection_with_client = 1; + if (fast_server_handshake(cell->payload, (uint8_t*)reply, (uint8_t*)keys, sizeof(keys))<0) { log_warn(LD_OR,"Failed to generate key material. Closing."); @@ -501,14 +603,40 @@ command_process_versions_cell(var_cell_t *cell, or_connection_t *conn) { int highest_supported_version = 0; const uint8_t *cp, *end; + const int started_here = connection_or_nonopen_was_started_here(conn); if (conn->link_proto != 0 || - conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING || (conn->handshake_state && conn->handshake_state->received_versions)) { log_fn(LOG_PROTOCOL_WARN, LD_OR, "Received a VERSIONS cell on a connection with its version " "already set to %d; dropping", (int) conn->link_proto); return; } + switch (conn->_base.state) + { + case OR_CONN_STATE_OR_HANDSHAKING_V2: + break; + case OR_CONN_STATE_TLS_HANDSHAKING: + case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING: + if (started_here) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Received a versions cell while TLS-handshaking not in " + "OR_HANDSHAKING_V3 on a connection we originated."); + } + conn->_base.state = OR_CONN_STATE_OR_HANDSHAKING_V3; + if (connection_init_or_handshake_state(conn, started_here) < 0) { + connection_mark_for_close(TO_CONN(conn)); + return; + } + or_handshake_state_record_var_cell(conn->handshake_state, cell, 1); + break; + case OR_CONN_STATE_OR_HANDSHAKING_V3: + break; + default: + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "VERSIONS cell while in unexpected state"); + return; + } + tor_assert(conn->handshake_state); end = cell->payload + cell->payload_len; for (cp = cell->payload; cp+1 < end; ++cp) { @@ -530,19 +658,87 @@ command_process_versions_cell(var_cell_t *cell, or_connection_t *conn) "That's crazily non-compliant. Closing connection."); connection_mark_for_close(TO_CONN(conn)); return; + } else if (highest_supported_version < 3 && + conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Negotiated link protocol 2 or lower after doing a v3 TLS " + "handshake. Closing connection."); + connection_mark_for_close(TO_CONN(conn)); + return; } + conn->link_proto = highest_supported_version; conn->handshake_state->received_versions = 1; - log_info(LD_OR, "Negotiated version %d with %s:%d; sending NETINFO.", - highest_supported_version, - safe_str_client(conn->_base.address), - conn->_base.port); - tor_assert(conn->link_proto >= 2); + if (conn->link_proto == 2) { + log_info(LD_OR, "Negotiated version %d with %s:%d; sending NETINFO.", + highest_supported_version, + safe_str_client(conn->_base.address), + conn->_base.port); - if (connection_or_send_netinfo(conn) < 0) { - connection_mark_for_close(TO_CONN(conn)); - return; + if (connection_or_send_netinfo(conn) < 0) { + connection_mark_for_close(TO_CONN(conn)); + return; + } + } else { + const int send_versions = !started_here; + /* If we want to authenticate, send a CERTS cell */ + const int send_certs = !started_here || public_server_mode(get_options()); + /* If we're a relay that got a connection, ask for authentication. */ + const int send_chall = !started_here && public_server_mode(get_options()); + /* If our certs cell will authenticate us, or if we have no intention of + * authenticating, send a netinfo cell right now. */ + const int send_netinfo = + !(started_here && public_server_mode(get_options())); + const int send_any = + send_versions || send_certs || send_chall || send_netinfo; + tor_assert(conn->link_proto >= 3); + + log_info(LD_OR, "Negotiated version %d with %s:%d; %s%s%s%s%s", + highest_supported_version, + safe_str_client(conn->_base.address), + conn->_base.port, + send_any ? "Sending cells:" : "Waiting for CERTS cell", + send_versions ? " VERSIONS" : "", + send_certs ? " CERTS" : "", + send_chall ? " AUTH_CHALLENGE" : "", + send_netinfo ? " NETINFO" : ""); + +#ifdef DISABLE_V3_LINKPROTO_SERVERSIDE + if (1) { + connection_mark_for_close(TO_CONN(conn)); + return; + } +#endif + + if (send_versions) { + if (connection_or_send_versions(conn, 1) < 0) { + log_warn(LD_OR, "Couldn't send versions cell"); + connection_mark_for_close(TO_CONN(conn)); + return; + } + } + if (send_certs) { + if (connection_or_send_certs_cell(conn) < 0) { + log_warn(LD_OR, "Couldn't send certs cell"); + connection_mark_for_close(TO_CONN(conn)); + return; + } + } + if (send_chall) { + if (connection_or_send_auth_challenge_cell(conn) < 0) { + log_warn(LD_OR, "Couldn't send auth_challenge cell"); + connection_mark_for_close(TO_CONN(conn)); + return; + } + } + if (send_netinfo) { + if (connection_or_send_netinfo(conn) < 0) { + log_warn(LD_OR, "Couldn't send netinfo cell"); + connection_mark_for_close(TO_CONN(conn)); + return; + } + } } } @@ -568,13 +764,41 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn) conn->link_proto == 0 ? "non-versioned" : "a v1"); return; } - if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING) { + if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V2 && + conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) { log_fn(LOG_PROTOCOL_WARN, LD_OR, "Received a NETINFO cell on non-handshaking connection; dropping."); return; } tor_assert(conn->handshake_state && conn->handshake_state->received_versions); + + if (conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3) { + tor_assert(conn->link_proto >= 3); + if (conn->handshake_state->started_here) { + if (!conn->handshake_state->authenticated) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got a NETINFO cell from server, " + "but no authentication. Closing the connection."); + connection_mark_for_close(TO_CONN(conn)); + return; + } + } else { + /* we're the server. If the client never authenticated, we have + some housekeeping to do.*/ + if (!conn->handshake_state->authenticated) { + tor_assert(tor_digest_is_zero( + (const char*)conn->handshake_state->authenticated_peer_id)); + connection_or_set_circid_type(conn, NULL); + + connection_or_init_conn_from_address(conn, + &conn->_base.addr, + conn->_base.port, + (const char*)conn->handshake_state->authenticated_peer_id, + 0); + } + } + } + /* Decode the cell. */ timestamp = ntohl(get_uint32(cell->payload)); if (labs(now - conn->handshake_state->sent_versions_at) < 180) { @@ -620,7 +844,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. */ @@ -647,13 +871,409 @@ command_process_netinfo_cell(cell_t *cell, or_connection_t *conn) * trustworthy. */ (void)my_apparent_addr; - if (connection_or_set_state_open(conn)<0) + if (connection_or_set_state_open(conn)<0) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got good NETINFO cell from %s:%d; but " + "was unable to make the OR connection become open.", + safe_str_client(conn->_base.address), + conn->_base.port); connection_mark_for_close(TO_CONN(conn)); - else + } else { log_info(LD_OR, "Got good NETINFO cell from %s:%d; OR connection is now " - "open, using protocol version %d", + "open, using protocol version %d. Its ID digest is %s", safe_str_client(conn->_base.address), - conn->_base.port, (int)conn->link_proto); + conn->_base.port, (int)conn->link_proto, + hex_str(conn->identity_digest, DIGEST_LEN)); + } assert_connection_ok(TO_CONN(conn),time(NULL)); } +/** Process a CERTS cell from an OR connection. + * + * If the other side should not have sent us a CERTS cell, or the cell is + * malformed, or it is supposed to authenticate the TLS key but it doesn't, + * then mark the connection. + * + * If the cell has a good cert chain and we're doing a v3 handshake, then + * store the certificates in or_handshake_state. If this is the client side + * of the connection, we then authenticate the server or mark the connection. + * If it's the server side, wait for an AUTHENTICATE cell. + */ +static void +command_process_certs_cell(var_cell_t *cell, or_connection_t *conn) +{ +#define ERR(s) \ + do { \ + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ + "Received a bad CERTS cell from %s:%d: %s", \ + safe_str(conn->_base.address), conn->_base.port, (s)); \ + connection_mark_for_close(TO_CONN(conn)); \ + goto err; \ + } while (0) + + tor_cert_t *link_cert = NULL; + tor_cert_t *id_cert = NULL; + tor_cert_t *auth_cert = NULL; + + uint8_t *ptr; + int n_certs, i; + + if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) + ERR("We're not doing a v3 handshake!"); + if (conn->link_proto < 3) + ERR("We're not using link protocol >= 3"); + if (conn->handshake_state->received_certs_cell) + ERR("We already got one"); + if (conn->handshake_state->authenticated) { + /* Should be unreachable, but let's make sure. */ + ERR("We're already authenticated!"); + } + if (cell->payload_len < 1) + ERR("It had no body"); + if (cell->circ_id) + ERR("It had a nonzero circuit ID"); + + n_certs = cell->payload[0]; + ptr = cell->payload + 1; + for (i = 0; i < n_certs; ++i) { + uint8_t cert_type; + uint16_t cert_len; + if (ptr + 3 > cell->payload + cell->payload_len) { + goto truncated; + } + cert_type = *ptr; + cert_len = ntohs(get_uint16(ptr+1)); + if (ptr + 3 + cert_len > cell->payload + cell->payload_len) { + goto truncated; + } + if (cert_type == OR_CERT_TYPE_TLS_LINK || + cert_type == OR_CERT_TYPE_ID_1024 || + cert_type == OR_CERT_TYPE_AUTH_1024) { + tor_cert_t *cert = tor_cert_decode(ptr + 3, cert_len); + if (!cert) { + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, + "Received undecodable certificate in CERTS cell from %s:%d", + safe_str(conn->_base.address), conn->_base.port); + } else { + if (cert_type == OR_CERT_TYPE_TLS_LINK) { + if (link_cert) { + tor_cert_free(cert); + ERR("Too many TLS_LINK certificates"); + } + link_cert = cert; + } else if (cert_type == OR_CERT_TYPE_ID_1024) { + if (id_cert) { + tor_cert_free(cert); + ERR("Too many ID_1024 certificates"); + } + id_cert = cert; + } else if (cert_type == OR_CERT_TYPE_AUTH_1024) { + if (auth_cert) { + tor_cert_free(cert); + ERR("Too many AUTH_1024 certificates"); + } + auth_cert = cert; + } else { + tor_cert_free(cert); + } + } + } + ptr += 3 + cert_len; + continue; + + truncated: + ERR("It ends in the middle of a certificate"); + } + + if (conn->handshake_state->started_here) { + int severity; + if (! (id_cert && link_cert)) + ERR("The certs we wanted were missing"); + /* Okay. We should be able to check the certificates now. */ + if (! tor_tls_cert_matches_key(conn->tls, link_cert)) { + ERR("The link certificate didn't match the TLS public key"); + } + /* Note that this warns more loudly about time and validity if we were + * _trying_ to connect to an authority, not necessarily if we _did_ connect + * to one. */ + if (router_digest_is_trusted_dir(conn->identity_digest)) + severity = LOG_WARN; + else + severity = LOG_PROTOCOL_WARN; + + if (! tor_tls_cert_is_valid(severity, link_cert, id_cert, 0)) + ERR("The link certificate was not valid"); + if (! tor_tls_cert_is_valid(severity, id_cert, id_cert, 1)) + ERR("The ID certificate was not valid"); + + conn->handshake_state->authenticated = 1; + { + const digests_t *id_digests = tor_cert_get_id_digests(id_cert); + crypto_pk_env_t *identity_rcvd; + if (!id_digests) + ERR("Couldn't compute digests for key in ID cert"); + + identity_rcvd = tor_tls_cert_get_key(id_cert); + if (!identity_rcvd) + ERR("Internal error: Couldn't get RSA key from ID cert."); + memcpy(conn->handshake_state->authenticated_peer_id, + id_digests->d[DIGEST_SHA1], DIGEST_LEN); + connection_or_set_circid_type(conn, identity_rcvd); + crypto_free_pk_env(identity_rcvd); + } + + if (connection_or_client_learned_peer_id(conn, + conn->handshake_state->authenticated_peer_id) < 0) + ERR("Problem setting or checking peer id"); + + log_info(LD_OR, "Got some good certificates from %s:%d: Authenticated it.", + safe_str(conn->_base.address), conn->_base.port); + + conn->handshake_state->id_cert = id_cert; + id_cert = NULL; + } else { + if (! (id_cert && auth_cert)) + ERR("The certs we wanted were missing"); + + /* Remember these certificates so we can check an AUTHENTICATE cell */ + if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, auth_cert, id_cert, 1)) + ERR("The authentication certificate was not valid"); + if (! tor_tls_cert_is_valid(LOG_PROTOCOL_WARN, id_cert, id_cert, 1)) + ERR("The ID certificate was not valid"); + + log_info(LD_OR, "Got some good certificates from %s:%d: " + "Waiting for AUTHENTICATE.", + safe_str(conn->_base.address), conn->_base.port); + /* XXXX check more stuff? */ + + conn->handshake_state->id_cert = id_cert; + conn->handshake_state->auth_cert = auth_cert; + id_cert = auth_cert = NULL; + } + + conn->handshake_state->received_certs_cell = 1; + err: + tor_cert_free(id_cert); + tor_cert_free(link_cert); + tor_cert_free(auth_cert); +#undef ERR +} + +/** Process an AUTH_CHALLENGE cell from an OR connection. + * + * If we weren't supposed to get one (for example, because we're not the + * originator of the connection), or it's ill-formed, or we aren't doing a v3 + * handshake, mark the connection. If the cell is well-formed but we don't + * want to authenticate, just drop it. If the cell is well-formed *and* we + * want to authenticate, send an AUTHENTICATE cell and then a NETINFO cell. */ +static void +command_process_auth_challenge_cell(var_cell_t *cell, or_connection_t *conn) +{ + int n_types, i, use_type = -1; + uint8_t *cp; + +#define ERR(s) \ + do { \ + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ + "Received a bad AUTH_CHALLENGE cell from %s:%d: %s", \ + safe_str(conn->_base.address), conn->_base.port, (s)); \ + connection_mark_for_close(TO_CONN(conn)); \ + return; \ + } while (0) + + if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) + ERR("We're not currently doing a v3 handshake"); + if (conn->link_proto < 3) + ERR("We're not using link protocol >= 3"); + if (! conn->handshake_state->started_here) + ERR("We didn't originate this connection"); + if (conn->handshake_state->received_auth_challenge) + ERR("We already received one"); + if (! conn->handshake_state->received_certs_cell) + ERR("We haven't gotten a CERTS cell yet"); + if (cell->payload_len < OR_AUTH_CHALLENGE_LEN + 2) + ERR("It was too short"); + if (cell->circ_id) + ERR("It had a nonzero circuit ID"); + + n_types = ntohs(get_uint16(cell->payload + OR_AUTH_CHALLENGE_LEN)); + if (cell->payload_len < OR_AUTH_CHALLENGE_LEN + 2 + 2*n_types) + ERR("It looks truncated"); + + /* Now see if there is an authentication type we can use */ + cp=cell->payload+OR_AUTH_CHALLENGE_LEN+2; + for (i=0; i < n_types; ++i, cp += 2) { + uint16_t authtype = ntohs(get_uint16(cp)); + if (authtype == AUTHTYPE_RSA_SHA256_TLSSECRET) + use_type = authtype; + } + + conn->handshake_state->received_auth_challenge = 1; + + if (! public_server_mode(get_options())) { + /* If we're not a public server then we don't want to authenticate on a + connection we originated, and we already sent a NETINFO cell when we + got the CERTS cell. We have nothing more to do. */ + return; + } + + if (use_type >= 0) { + log_info(LD_OR, "Got an AUTH_CHALLENGE cell from %s:%d: Sending " + "authentication", + safe_str(conn->_base.address), conn->_base.port); + + if (connection_or_send_authenticate_cell(conn, use_type) < 0) { + log_warn(LD_OR, "Couldn't send authenticate cell"); + connection_mark_for_close(TO_CONN(conn)); + return; + } + } else { + log_info(LD_OR, "Got an AUTH_CHALLENGE cell from %s:%d, but we don't " + "know any of its authentication types. Not authenticating.", + safe_str(conn->_base.address), conn->_base.port); + } + + if (connection_or_send_netinfo(conn) < 0) { + log_warn(LD_OR, "Couldn't send netinfo cell"); + connection_mark_for_close(TO_CONN(conn)); + return; + } + +#undef ERR +} + +/** Process an AUTHENTICATE cell from an OR connection. + * + * If it's ill-formed or we weren't supposed to get one or we're not doing a + * v3 handshake, then mark the connection. If it does not authenticate the + * other side of the connection successfully (because it isn't signed right, + * we didn't get a CERTS cell, etc) mark the connection. Otherwise, accept + * the identity of the router on the other side of the connection. + */ +static void +command_process_authenticate_cell(var_cell_t *cell, or_connection_t *conn) +{ + uint8_t expected[V3_AUTH_FIXED_PART_LEN]; + const uint8_t *auth; + int authlen; + +#define ERR(s) \ + do { \ + log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, \ + "Received a bad AUTHENTICATE cell from %s:%d: %s", \ + safe_str(conn->_base.address), conn->_base.port, (s)); \ + connection_mark_for_close(TO_CONN(conn)); \ + return; \ + } while (0) + + if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) + ERR("We're not doing a v3 handshake"); + if (conn->link_proto < 3) + ERR("We're not using link protocol >= 3"); + if (conn->handshake_state->started_here) + ERR("We originated this connection"); + if (conn->handshake_state->received_authenticate) + ERR("We already got one!"); + if (conn->handshake_state->authenticated) { + /* Should be impossible given other checks */ + ERR("The peer is already authenticated"); + } + if (! conn->handshake_state->received_certs_cell) + ERR("We never got a certs cell"); + if (conn->handshake_state->auth_cert == NULL) + ERR("We never got an authentication certificate"); + if (conn->handshake_state->id_cert == NULL) + ERR("We never got an identity certificate"); + if (cell->payload_len < 4) + ERR("Cell was way too short"); + + auth = cell->payload; + { + uint16_t type = ntohs(get_uint16(auth)); + uint16_t len = ntohs(get_uint16(auth+2)); + if (4 + len > cell->payload_len) + ERR("Authenticator was truncated"); + + if (type != AUTHTYPE_RSA_SHA256_TLSSECRET) + ERR("Authenticator type was not recognized"); + + auth += 4; + authlen = len; + } + + if (authlen < V3_AUTH_BODY_LEN + 1) + ERR("Authenticator was too short"); + + if (connection_or_compute_authenticate_cell_body( + conn, expected, sizeof(expected), NULL, 1) < 0) + ERR("Couldn't compute expected AUTHENTICATE cell body"); + + if (tor_memneq(expected, auth, sizeof(expected))) + ERR("Some field in the AUTHENTICATE cell body was not as expected"); + + { + crypto_pk_env_t *pk = tor_tls_cert_get_key( + conn->handshake_state->auth_cert); + char d[DIGEST256_LEN]; + char *signed_data; + size_t keysize; + int signed_len; + + if (!pk) + ERR("Internal error: couldn't get RSA key from AUTH cert."); + crypto_digest256(d, (char*)auth, V3_AUTH_BODY_LEN, DIGEST_SHA256); + + keysize = crypto_pk_keysize(pk); + signed_data = tor_malloc(keysize); + signed_len = crypto_pk_public_checksig(pk, signed_data, keysize, + (char*)auth + V3_AUTH_BODY_LEN, + authlen - V3_AUTH_BODY_LEN); + crypto_free_pk_env(pk); + if (signed_len < 0) { + tor_free(signed_data); + ERR("Signature wasn't valid"); + } + if (signed_len < DIGEST256_LEN) { + tor_free(signed_data); + ERR("Not enough data was signed"); + } + /* Note that we deliberately allow *more* than DIGEST256_LEN bytes here, + * in case they're later used to hold a SHA3 digest or something. */ + if (tor_memneq(signed_data, d, DIGEST256_LEN)) { + tor_free(signed_data); + ERR("Signature did not match data to be signed."); + } + tor_free(signed_data); + } + + /* Okay, we are authenticated. */ + conn->handshake_state->received_authenticate = 1; + conn->handshake_state->authenticated = 1; + conn->handshake_state->digest_received_data = 0; + { + crypto_pk_env_t *identity_rcvd = + tor_tls_cert_get_key(conn->handshake_state->id_cert); + const digests_t *id_digests = + tor_cert_get_id_digests(conn->handshake_state->id_cert); + + /* This must exist; we checked key type when reading the cert. */ + tor_assert(id_digests); + + memcpy(conn->handshake_state->authenticated_peer_id, + id_digests->d[DIGEST_SHA1], DIGEST_LEN); + + connection_or_set_circid_type(conn, identity_rcvd); + crypto_free_pk_env(identity_rcvd); + + connection_or_init_conn_from_address(conn, + &conn->_base.addr, + conn->_base.port, + (const char*)conn->handshake_state->authenticated_peer_id, + 0); + + log_info(LD_OR, "Got an AUTHENTICATE cell from %s:%d: Looks good.", + safe_str(conn->_base.address), conn->_base.port); + } + +#undef ERR +} + diff --git a/src/or/config.c b/src/or/config.c index 8972506477..a0cf3c80ad 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -33,13 +33,18 @@ #include "rendservice.h" #include "rephist.h" #include "router.h" +#include "util.h" #include "routerlist.h" +#include "transports.h" #ifdef MS_WINDOWS #include <shlobj.h> #endif #include "procmon.h" +/* From main.c */ +extern int quiet_level; + /** Enumeration of types which option values can take */ typedef enum config_type_t { CONFIG_TYPE_STRING = 0, /**< An arbitrary string. */ @@ -48,9 +53,13 @@ typedef enum config_type_t { CONFIG_TYPE_PORT, /**< A port from 1...65535, 0 for "not set", or * "auto". */ CONFIG_TYPE_INTERVAL, /**< A number of seconds, with optional units*/ + CONFIG_TYPE_MSEC_INTERVAL,/**< A number of milliseconds, with optional + * units */ CONFIG_TYPE_MEMUNIT, /**< A number of bytes, with optional units*/ CONFIG_TYPE_DOUBLE, /**< A floating-point value */ CONFIG_TYPE_BOOL, /**< A boolean value, expressed as 0 or 1. */ + CONFIG_TYPE_AUTOBOOL, /**< A boolean+auto value, expressed 0 for false, + * 1 for true, and -1 for auto */ CONFIG_TYPE_ISOTIME, /**< An ISO-formatted time relative to GMT. */ CONFIG_TYPE_CSV, /**< A list of strings, separated by commas and * optional whitespace. */ @@ -175,6 +184,8 @@ static config_var_t _option_vars[] = { V(AuthDirBadDir, LINELIST, NULL), V(AuthDirBadExit, LINELIST, NULL), V(AuthDirInvalid, LINELIST, NULL), + V(AuthDirFastGuarantee, MEMUNIT, "100 KB"), + V(AuthDirGuardBWGuarantee, MEMUNIT, "250 KB"), V(AuthDirReject, LINELIST, NULL), V(AuthDirRejectUnlisted, BOOL, "0"), V(AuthDirListBadDirs, BOOL, "0"), @@ -199,10 +210,12 @@ static config_var_t _option_vars[] = { V(CircuitStreamTimeout, INTERVAL, "0"), V(CircuitPriorityHalflife, DOUBLE, "-100.0"), /*negative:'Use default'*/ V(ClientDNSRejectInternalAddresses, BOOL,"1"), - V(ClientRejectInternalAddresses, BOOL, "1"), V(ClientOnly, BOOL, "0"), + V(ClientRejectInternalAddresses, BOOL, "1"), + V(ClientTransportPlugin, LINELIST, NULL), V(ConsensusParams, STRING, NULL), V(ConnLimit, UINT, "1000"), + V(ConnDirectionStatistics, BOOL, "0"), V(ConstrainedSockets, BOOL, "0"), V(ConstrainedSockSize, MEMUNIT, "8192"), V(ContactInfo, STRING, NULL), @@ -215,8 +228,10 @@ static config_var_t _option_vars[] = { V(CookieAuthentication, BOOL, "0"), V(CookieAuthFileGroupReadable, BOOL, "0"), V(CookieAuthFile, STRING, NULL), + V(CountPrivateBandwidth, BOOL, "0"), V(DataDirectory, FILENAME, NULL), OBSOLETE("DebugLogFile"), + V(DisableNetwork, BOOL, "0"), V(DirAllowPrivateAddresses, BOOL, NULL), V(TestingAuthDirTimeToLearnReachability, INTERVAL, "30 minutes"), V(DirListenAddress, LINELIST, NULL), @@ -229,10 +244,13 @@ static config_var_t _option_vars[] = { OBSOLETE("DirRecordUsageGranularity"), OBSOLETE("DirRecordUsageRetainIPs"), OBSOLETE("DirRecordUsageSaveInterval"), - V(DirReqStatistics, BOOL, "0"), + V(DirReqStatistics, BOOL, "1"), VAR("DirServer", LINELIST, DirServers, NULL), V(DisableAllSwap, BOOL, "0"), - V(DNSPort, PORT, "0"), + V(DisableDebuggerAttachment, BOOL, "1"), + V(DisableIOCP, BOOL, "1"), + V(DynamicDHGroups, BOOL, "1"), + V(DNSPort, LINELIST, NULL), V(DNSListenAddress, LINELIST, NULL), V(DownloadExtraInfo, BOOL, "0"), V(EnforceDistinctSubnets, BOOL, "1"), @@ -246,7 +264,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,8 +287,11 @@ static config_var_t _option_vars[] = { V(GeoIPFile, FILENAME, SHARE_DATADIR PATH_SEPARATOR "tor" PATH_SEPARATOR "geoip"), #endif + V(GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays, + BOOL, "0"), OBSOLETE("Group"), V(HardwareAccel, BOOL, "0"), + V(HeartbeatPeriod, INTERVAL, "6 hours"), V(AccelName, STRING, NULL), V(AccelDir, FILENAME, NULL), V(HashedControlPassword, LINELIST, NULL), @@ -289,6 +310,7 @@ static config_var_t _option_vars[] = { V(HTTPProxyAuthenticator, STRING, NULL), V(HTTPSProxy, STRING, NULL), V(HTTPSProxyAuthenticator, STRING, NULL), + VAR("ServerTransportPlugin", LINELIST, ServerTransportPlugin, NULL), V(Socks4Proxy, STRING, NULL), V(Socks5Proxy, STRING, NULL), V(Socks5ProxyUsername, STRING, NULL), @@ -300,23 +322,25 @@ static config_var_t _option_vars[] = { OBSOLETE("LinkPadding"), OBSOLETE("LogLevel"), OBSOLETE("LogFile"), + V(LogTimeGranularity, MSEC_INTERVAL, "1 second"), V(LongLivedPorts, CSV, - "21,22,706,1863,5050,5190,5222,5223,6667,6697,8300"), + "21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300"), VAR("MapAddress", LINELIST, AddressMap, NULL), V(MaxAdvertisedBandwidth, MEMUNIT, "1 GB"), V(MaxCircuitDirtiness, INTERVAL, "10 minutes"), + V(MaxClientCircuitsPending, UINT, "32"), V(MaxOnionsPending, UINT, "100"), OBSOLETE("MonthlyAccountingStart"), V(MyFamily, STRING, NULL), V(NewCircuitPeriod, INTERVAL, "30 seconds"), VAR("NamingAuthoritativeDirectory",BOOL, NamingAuthoritativeDir, "0"), V(NATDListenAddress, LINELIST, NULL), - V(NATDPort, PORT, "0"), + V(NATDPort, LINELIST, NULL), V(Nickname, STRING, NULL), V(WarnUnsafeSocks, BOOL, "1"), OBSOLETE("NoPublish"), VAR("NodeFamily", LINELIST, NodeFamilies, NULL), - V(NumCPUs, UINT, "1"), + V(NumCPUs, UINT, "0"), V(NumEntryGuards, UINT, "3"), V(ORListenAddress, LINELIST, NULL), V(ORPort, PORT, "0"), @@ -326,6 +350,9 @@ static config_var_t _option_vars[] = { V(PerConnBWRate, MEMUNIT, "0"), V(PidFile, STRING, NULL), V(TestingTorNetwork, BOOL, "0"), + V(OptimisticData, AUTOBOOL, "auto"), + V(PortForwarding, BOOL, "0"), + V(PortForwardingHelper, FILENAME, "tor-fw-helper"), V(PreferTunneledDirConns, BOOL, "1"), V(ProtocolWarnings, BOOL, "0"), V(PublishServerDescriptor, CSV, "1"), @@ -337,7 +364,7 @@ static config_var_t _option_vars[] = { V(RecommendedClientVersions, LINELIST, NULL), V(RecommendedServerVersions, LINELIST, NULL), OBSOLETE("RedirectExit"), - V(RefuseUnknownExits, STRING, "auto"), + V(RefuseUnknownExits, AUTOBOOL, "auto"), V(RejectPlaintextPorts, CSV, ""), V(RelayBandwidthBurst, MEMUNIT, "0"), V(RelayBandwidthRate, MEMUNIT, "0"), @@ -362,23 +389,26 @@ static config_var_t _option_vars[] = { V(ShutdownWaitLength, INTERVAL, "30 seconds"), V(SocksListenAddress, LINELIST, NULL), V(SocksPolicy, LINELIST, NULL), - V(SocksPort, PORT, "9050"), + V(SocksPort, LINELIST, NULL), V(SocksTimeout, INTERVAL, "2 minutes"), OBSOLETE("StatusFetchPeriod"), V(StrictNodes, BOOL, "0"), OBSOLETE("SysLog"), V(TestSocks, BOOL, "0"), OBSOLETE("TestVia"), + V(TokenBucketRefillInterval, MSEC_INTERVAL, "100 msec"), V(TrackHostExits, CSV, NULL), V(TrackHostExitsExpire, INTERVAL, "30 minutes"), OBSOLETE("TrafficShaping"), V(TransListenAddress, LINELIST, NULL), - V(TransPort, PORT, "0"), + V(TransPort, LINELIST, NULL), V(TunnelDirConns, BOOL, "1"), V(UpdateBridgesFromAuthority, BOOL, "0"), V(UseBridges, BOOL, "0"), V(UseEntryGuards, BOOL, "1"), + V(UseMicrodescriptors, AUTOBOOL, "auto"), V(User, STRING, NULL), + V(UserspaceIOCPBuffers, BOOL, "0"), VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"), VAR("V2AuthoritativeDirectory",BOOL, V2AuthoritativeDir, "0"), VAR("V3AuthoritativeDirectory",BOOL, V3AuthoritativeDir, "0"), @@ -394,6 +424,7 @@ static config_var_t _option_vars[] = { VAR("VersioningAuthoritativeDirectory",BOOL,VersioningAuthoritativeDir, "0"), V(VirtualAddrNetwork, STRING, "127.192.0.0/10"), V(WarnPlaintextPorts, CSV, "23,109,110,143"), + V(_UseFilteringSSLBufferevents, BOOL, "0"), VAR("__ReloadTorrcOnSIGHUP", BOOL, ReloadTorrcOnSIGHUP, "1"), VAR("__AllDirActionsPrivate", BOOL, AllDirActionsPrivate, "0"), VAR("__DisablePredictedCircuits",BOOL,DisablePredictedCircuits, "0"), @@ -410,7 +441,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"), @@ -419,6 +450,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"), @@ -430,6 +462,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 @@ -455,6 +488,9 @@ static config_var_t _state_vars[] = { VAR("EntryGuardAddedBy", LINELIST_S, EntryGuards, NULL), V(EntryGuards, LINELIST_V, NULL), + VAR("TransportProxy", LINELIST_S, TransportProxies, NULL), + V(TransportProxies, LINELIST_V, NULL), + V(BWHistoryReadEnds, ISOTIME, NULL), V(BWHistoryReadInterval, UINT, "900"), V(BWHistoryReadValues, CSV, ""), @@ -481,7 +517,6 @@ static config_var_t _state_vars[] = { V(CircuitBuildAbandonedCount, UINT, "0"), VAR("CircuitBuildTimeBin", LINELIST_S, BuildtimeHistogram, NULL), VAR("BuildtimeHistogram", LINELIST_V, BuildtimeHistogram, NULL), - { NULL, CONFIG_TYPE_OBSOLETE, 0, NULL } }; @@ -532,39 +567,48 @@ static char *get_windows_conf_root(void); #endif static void config_line_append(config_line_t **lst, const char *key, const char *val); -static void option_clear(config_format_t *fmt, or_options_t *options, - config_var_t *var); -static void option_reset(config_format_t *fmt, or_options_t *options, - config_var_t *var, int use_defaults); -static void config_free(config_format_t *fmt, void *options); +static void option_clear(const config_format_t *fmt, or_options_t *options, + const config_var_t *var); +static void option_reset(const config_format_t *fmt, or_options_t *options, + const config_var_t *var, int use_defaults); +static void config_free(const config_format_t *fmt, void *options); static int config_lines_eq(config_line_t *a, config_line_t *b); -static int option_is_same(config_format_t *fmt, - or_options_t *o1, or_options_t *o2, +static int option_is_same(const config_format_t *fmt, + const or_options_t *o1, const or_options_t *o2, const char *name); -static or_options_t *options_dup(config_format_t *fmt, or_options_t *old); -static int options_validate(or_options_t *old_options, or_options_t *options, +static or_options_t *options_dup(const config_format_t *fmt, + const or_options_t *old); +static int options_validate(or_options_t *old_options, + or_options_t *options, int from_setconf, char **msg); -static int options_act_reversible(or_options_t *old_options, char **msg); -static int options_act(or_options_t *old_options); -static int options_transition_allowed(or_options_t *old, or_options_t *new, +static int options_act_reversible(const or_options_t *old_options, char **msg); +static int options_act(const or_options_t *old_options); +static int options_transition_allowed(const or_options_t *old, + const or_options_t *new, char **msg); -static int options_transition_affects_workers(or_options_t *old_options, - or_options_t *new_options); -static int options_transition_affects_descriptor(or_options_t *old_options, - or_options_t *new_options); +static int options_transition_affects_workers( + const or_options_t *old_options, const or_options_t *new_options); +static int options_transition_affects_descriptor( + const or_options_t *old_options, const or_options_t *new_options); static int check_nickname_list(const char *lst, const char *name, char **msg); -static void config_register_addressmaps(or_options_t *options); static int parse_bridge_line(const char *line, int validate_only); +static int parse_client_transport_line(const char *line, int validate_only); + +static int parse_server_transport_line(const char *line, int validate_only); static int parse_dir_server_line(const char *line, - authority_type_t required_type, + dirinfo_type_t required_type, int validate_only); +static void port_cfg_free(port_cfg_t *port); +static int parse_client_ports(const or_options_t *options, int validate_only, + char **msg_out, int *n_ports_out); static int validate_data_directory(or_options_t *options); -static int write_configuration_file(const char *fname, or_options_t *options); -static config_line_t *get_assigned_option(config_format_t *fmt, - void *options, const char *key, - int escape_val); -static void config_init(config_format_t *fmt, void *options); +static int write_configuration_file(const char *fname, + const or_options_t *options); +static config_line_t *get_assigned_option(const config_format_t *fmt, + const void *options, const char *key, + int escape_val); +static void config_init(const config_format_t *fmt, void *options); static int or_state_validate(or_state_t *old_options, or_state_t *options, int from_setconf, char **msg); static int or_state_load(void); @@ -574,8 +618,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. */ @@ -602,7 +647,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), @@ -618,14 +663,20 @@ static config_format_t state_format = { /** Command-line and config-file options. */ static or_options_t *global_options = NULL; +/** DOCDOC */ +static or_options_t *global_default_options = NULL; /** Name of most recently read torrc file. */ static char *torrc_fname = NULL; +/** DOCDOC */ +static char *torrc_defaults_fname; /** Persistent serialized state. */ static or_state_t *global_state = NULL; /** Configuration Options set by command line. */ static config_line_t *global_cmdline_options = NULL; /** Contents of most recently read DirPortFrontPage file. */ static char *global_dirfrontpagecontents = NULL; +/** List of port_cfg_t for client-level (SOCKS, DNS, Trans, NATD) ports. */ +static smartlist_t *configured_client_ports = NULL; /** Return the contents of our frontpage string, or NULL if not configured. */ const char * @@ -636,7 +687,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; @@ -646,12 +697,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. @@ -659,6 +717,9 @@ get_options(void) int set_options(or_options_t *new_val, char **msg) { + int i; + smartlist_t *elements; + config_line_t *line; or_options_t *old_options = global_options; global_options = new_val; /* Note that we pass the *old* options below, for comparison. It @@ -673,7 +734,34 @@ set_options(or_options_t *new_val, char **msg) "Acting on config options left us in a broken state. Dying."); exit(1); } - + /* Issues a CONF_CHANGED event to notify controller of the change. If Tor is + * just starting up then the old_options will be undefined. */ + if (old_options) { + elements = smartlist_create(); + for (i=0; options_format.vars[i].name; ++i) { + const config_var_t *var = &options_format.vars[i]; + const char *var_name = var->name; + if (var->type == CONFIG_TYPE_LINELIST_S || + var->type == CONFIG_TYPE_OBSOLETE) { + continue; + } + if (!option_is_same(&options_format, new_val, old_options, var_name)) { + line = get_assigned_option(&options_format, new_val, var_name, 1); + + if (line) { + for (; line; line = line->next) { + smartlist_add(elements, line->key); + smartlist_add(elements, line->value); + } + } else { + smartlist_add(elements, (char*)options_format.vars[i].name); + smartlist_add(elements, NULL); + } + } + } + control_event_conf_changed(elements); + smartlist_free(elements); + } config_free(&options_format, old_options); return 0; @@ -709,6 +797,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); } @@ -719,6 +812,8 @@ config_free_all(void) { or_options_free(global_options); global_options = NULL; + or_options_free(global_default_options); + global_default_options = NULL; config_free(&state_format, global_state); global_state = NULL; @@ -726,7 +821,15 @@ config_free_all(void) config_free_lines(global_cmdline_options); global_cmdline_options = NULL; + if (configured_client_ports) { + SMARTLIST_FOREACH(configured_client_ports, + port_cfg_t *, p, tor_free(p)); + smartlist_free(configured_client_ports); + configured_client_ports = NULL; + } + tor_free(torrc_fname); + tor_free(torrc_defaults_fname); tor_free(_version); tor_free(global_dirfrontpagecontents); } @@ -791,7 +894,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[] = { @@ -865,16 +968,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; } @@ -883,8 +986,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 = @@ -905,27 +1008,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; } @@ -937,12 +1041,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; @@ -971,6 +1075,7 @@ options_act_reversible(or_options_t *old_options, char **msg) #endif if (running_tor) { + int n_client_ports=0; /* We need to set the connection limit before we can open the listeners. */ if (set_max_file_descriptors((unsigned)options->ConnLimit, &options->_ConnLimit) < 0) { @@ -982,18 +1087,37 @@ options_act_reversible(or_options_t *old_options, char **msg) /* Set up libevent. (We need to do this before we can register the * listeners as listeners.) */ if (running_tor && !libevent_initialized) { - init_libevent(); + init_libevent(options); libevent_initialized = 1; } + /* Adjust the client port configuration so we can launch listeners. */ + if (parse_client_ports(options, 0, msg, &n_client_ports)) { + if (!*msg) + *msg = tor_strdup("Unexpected problem parsing client port config"); + goto rollback; + } + + /* Set the hibernation state appropriately.*/ + consider_hibernation(time(NULL)); + /* Launch the listeners. (We do this before we setuid, so we can bind to - * ports under 1024.) We don't want to rebind if we're hibernating. */ + * ports under 1024.) We don't want to rebind if we're hibernating. If + * networking is disabled, this will close all but the control listeners, + * but disable those. */ if (!we_are_hibernating()) { if (retry_all_listeners(replaced_listeners, new_listeners) < 0) { *msg = tor_strdup("Failed to bind one of the listener ports."); goto rollback; } } + if (options->DisableNetwork) { + /* Aggressively close non-controller stuff, NOW */ + log_notice(LD_NET, "DisableNetwork is set. Tor will not make or accept " + "non-control network connections. Shutting down all existing " + "connections."); + connection_mark_all_noncontrol_connections(); + } } #if defined(HAVE_NET_IF_H) && defined(HAVE_NET_PFVAR_H) @@ -1038,7 +1162,7 @@ options_act_reversible(or_options_t *old_options, char **msg) /* Write control ports to disk as appropriate */ control_ports_write_to_file(); - if (directory_caches_v2_dir_info(options)) { + if (directory_caches_v2_dir_info(options)) { size_t len = strlen(options->DataDirectory)+32; char *fn = tor_malloc(len); tor_snprintf(fn, len, "%s"PATH_SEPARATOR"cached-status", @@ -1114,7 +1238,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; @@ -1139,7 +1263,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) @@ -1153,7 +1277,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) @@ -1162,6 +1286,24 @@ get_effective_bwburst(or_options_t *options) return (uint32_t)bw; } +/** Return True if any changes from <b>old_options</b> to + * <b>new_options</b> needs us to refresh our TLS context. */ +static int +options_transition_requires_fresh_tls_context(const or_options_t *old_options, + const or_options_t *new_options) +{ + tor_assert(new_options); + + if (!old_options) + return 0; + + if ((old_options->DynamicDHGroups != new_options->DynamicDHGroups)) { + return 1; + } + + return 0; +} + /** Fetch the active option list, and take actions based on it. All of the * things we do should survive being done repeatedly. If present, * <b>old_options</b> contains the previous value of the options. @@ -1172,15 +1314,23 @@ 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); + /* disable ptrace and later, other basic debugging techniques */ + if (options->DisableDebuggerAttachment) { + tor_disable_debugger_attach(); + } else { + log_notice(LD_CONFIG,"Debugger attachment enabled " + "for unprivileged users."); + } + if (running_tor && !have_lockfile()) { if (try_locking(options, 1) < 0) return -1; @@ -1220,6 +1370,32 @@ options_act(or_options_t *old_options) rep_hist_load_mtbf_data(time(NULL)); } + mark_transport_list(); + pt_prepare_proxy_list_for_config_read(); + if (options->ClientTransportPlugin) { + for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { + if (parse_client_transport_line(cl->value, 0)<0) { + log_warn(LD_BUG, + "Previously validated ClientTransportPlugin line " + "could not be added!"); + return -1; + } + } + } + + if (options->ServerTransportPlugin) { + for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { + if (parse_server_transport_line(cl->value, 0)<0) { + log_warn(LD_BUG, + "Previously validated ServerTransportPlugin line " + "could not be added!"); + return -1; + } + } + } + sweep_transport_list(); + sweep_proxy_list(); + /* Bail out at this point if we're not going to be a client or server: * we want to not fork, and to log stuff to stderr. */ if (!running_tor) @@ -1231,6 +1407,29 @@ options_act(or_options_t *old_options) finish_daemon(options->DataDirectory); } + /* If needed, generate a new TLS DH prime according to the current torrc. */ + if (server_mode(options)) { + if (!old_options) { + if (options->DynamicDHGroups) { + char *fname = get_datadir_fname2("keys", "dynamic_dh_params"); + crypto_set_tls_dh_prime(fname); + tor_free(fname); + } else { + crypto_set_tls_dh_prime(NULL); + } + } else { + if (options->DynamicDHGroups && !old_options->DynamicDHGroups) { + char *fname = get_datadir_fname2("keys", "dynamic_dh_params"); + crypto_set_tls_dh_prime(fname); + tor_free(fname); + } else if (!options->DynamicDHGroups && old_options->DynamicDHGroups) { + crypto_set_tls_dh_prime(NULL); + } + } + } else { /* clients don't need a dynamic DH prime. */ + crypto_set_tls_dh_prime(NULL); + } + /* 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 || @@ -1240,6 +1439,13 @@ options_act(or_options_t *old_options) log_warn(LD_BUG,"Error initializing keys; exiting"); return -1; } + } else if (old_options && + options_transition_requires_fresh_tls_context(old_options, + options)) { + if (router_initialize_tls_context() < 0) { + log_warn(LD_BUG,"Error initializing TLS context."); + return -1; + } } /* Write our PID to the PID file. If we do not have write permissions we @@ -1279,17 +1485,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()); @@ -1408,44 +1613,69 @@ 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 || + options->BridgeAuthoritativeDir) { time_t now = time(NULL); + int print_notice = 0; + + /* If we aren't acting as a server, we can't collect stats anyway. */ + if (!server_mode(options)) { + options->CellStatistics = 0; + options->DirReqStatistics = 0; + options->EntryStatistics = 0; + options->ExitPortStatistics = 0; + } + if ((!old_options || !old_options->CellStatistics) && - options->CellStatistics) + 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 ((!old_options || !old_options->BridgeAuthoritativeDir) && + options->BridgeAuthoritativeDir) { + rep_hist_desc_stats_init(now); + print_notice = 1; + } + 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."); @@ -1463,6 +1693,12 @@ 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(); + if (old_options && old_options->BridgeAuthoritativeDir && + !options->BridgeAuthoritativeDir) + rep_hist_desc_stats_term(); /* Check if we need to parse and add the EntryNodes config option. */ if (options->EntryNodes && @@ -1520,7 +1756,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; @@ -1558,7 +1794,11 @@ config_get_commandlines(int argc, char **argv, config_line_t **result) int i = 1; while (i < argc) { + unsigned command = CONFIG_LINE_NORMAL; + int want_arg = 1; + if (!strcmp(argv[i],"-f") || + !strcmp(argv[i],"--defaults-torrc") || !strcmp(argv[i],"--hash-password")) { i += 2; /* command-line option with argument. ignore them. */ continue; @@ -1575,13 +1815,6 @@ config_get_commandlines(int argc, char **argv, config_line_t **result) continue; } - if (i == argc-1) { - log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.", - argv[i]); - config_free_lines(front); - return -1; - } - *new = tor_malloc_zero(sizeof(config_line_t)); s = argv[i]; @@ -1590,15 +1823,33 @@ config_get_commandlines(int argc, char **argv, config_line_t **result) s++; if (*s == '-') s++; + /* Figure out the command, if any. */ + if (*s == '+') { + s++; + command = CONFIG_LINE_APPEND; + } else if (*s == '/') { + s++; + command = CONFIG_LINE_CLEAR; + /* A 'clear' command has no argument. */ + want_arg = 0; + } + + if (want_arg && i == argc-1) { + log_warn(LD_CONFIG,"Command-line option '%s' with no value. Failing.", + argv[i]); + config_free_lines(front); + return -1; + } (*new)->key = tor_strdup(expand_abbrev(&options_format, s, 1, 1)); - (*new)->value = tor_strdup(argv[i+1]); + (*new)->value = want_arg ? tor_strdup(argv[i+1]) : tor_strdup(""); + (*new)->command = command; (*new)->next = NULL; log(LOG_DEBUG, LD_CONFIG, "command line: parsed keyword '%s', value '%s'", (*new)->key, (*new)->value); new = &((*new)->next); - i += 2; + i += want_arg ? 2 : 1; } *result = front; return 0; @@ -1613,7 +1864,7 @@ config_line_append(config_line_t **lst, { config_line_t *newline; - newline = tor_malloc(sizeof(config_line_t)); + newline = tor_malloc_zero(sizeof(config_line_t)); newline->key = tor_strdup(key); newline->value = tor_strdup(val); newline->next = NULL; @@ -1626,9 +1877,12 @@ config_line_append(config_line_t **lst, /** Helper: parse the config string and strdup into key/value * strings. Set *result to the list, or NULL if parsing the string * failed. Return 0 on success, -1 on failure. Warn and ignore any - * misformatted lines. */ + * misformatted lines. + * + * If <b>extended</b> is set, then treat keys beginning with / and with + as + * indicating "clear" and "append" respectively. */ int -config_get_lines(const char *string, config_line_t **result) +config_get_lines(const char *string, config_line_t **result, int extended) { config_line_t *list = NULL, **next; char *k, *v; @@ -1644,13 +1898,30 @@ config_get_lines(const char *string, config_line_t **result) return -1; } if (k && v) { + unsigned command = CONFIG_LINE_NORMAL; + if (extended) { + if (k[0] == '+') { + char *k_new = tor_strdup(k+1); + tor_free(k); + k = k_new; + command = CONFIG_LINE_APPEND; + } else if (k[0] == '/') { + char *k_new = tor_strdup(k+1); + tor_free(k); + k = k_new; + tor_free(v); + v = tor_strdup(""); + command = CONFIG_LINE_CLEAR; + } + } /* This list can get long, so we keep a pointer to the end of it * rather than using config_line_append over and over and getting * n^2 performance. */ - *next = tor_malloc(sizeof(config_line_t)); + *next = tor_malloc_zero(sizeof(config_line_t)); (*next)->key = k; (*next)->value = v; (*next)->next = NULL; + (*next)->command = command; next = &((*next)->next); } else { tor_free(k); @@ -1680,12 +1951,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); @@ -1710,9 +1978,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) @@ -1730,11 +2009,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); @@ -1777,6 +2056,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) { @@ -1800,6 +2091,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); @@ -1844,7 +2149,19 @@ config_assign_value(config_format_t *fmt, or_options_t *options, case CONFIG_TYPE_LINELIST: case CONFIG_TYPE_LINELIST_S: - config_line_append((config_line_t**)lvalue, c->key, c->value); + { + config_line_t *lastval = *(config_line_t**)lvalue; + if (lastval && lastval->fragile) { + if (c->command != CONFIG_LINE_APPEND) { + config_free_lines(lastval); + *(config_line_t**)lvalue = NULL; + } else { + lastval->fragile = 0; + } + } + + config_line_append((config_line_t**)lvalue, c->key, c->value); + } break; case CONFIG_TYPE_OBSOLETE: log_warn(LD_CONFIG, "Skipping obsolete configuration option '%s'", c->key); @@ -1860,6 +2177,28 @@ config_assign_value(config_format_t *fmt, or_options_t *options, return 0; } +/** Mark every linelist in <b>options<b> "fragile", so that fresh assignments + * to it will replace old ones. */ +static void +config_mark_lists_fragile(const config_format_t *fmt, or_options_t *options) +{ + int i; + tor_assert(fmt); + tor_assert(options); + + for (i = 0; fmt->vars[i].name; ++i) { + const config_var_t *var = &fmt->vars[i]; + config_line_t *list; + if (var->type != CONFIG_TYPE_LINELIST && + var->type != CONFIG_TYPE_LINELIST_V) + continue; + + list = *(config_line_t **)STRUCT_VAR_P(options, var->var_offset); + if (list) + list->fragile = 1; + } +} + /** If <b>c</b> is a syntactically valid configuration line, update * <b>options</b> with its value and return 0. Otherwise return -1 for bad * key, -2 for bad value. @@ -1870,11 +2209,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); @@ -1902,8 +2241,9 @@ config_assign_line(config_format_t *fmt, or_options_t *options, if (!strlen(c->value)) { /* reset or clear it, then return */ if (!clear_first) { - if (var->type == CONFIG_TYPE_LINELIST || - var->type == CONFIG_TYPE_LINELIST_S) { + if ((var->type == CONFIG_TYPE_LINELIST || + var->type == CONFIG_TYPE_LINELIST_S) && + c->command != CONFIG_LINE_CLEAR) { /* We got an empty linelist from the torrc or command line. As a special case, call this an error. Warn and ignore. */ log_warn(LD_CONFIG, @@ -1913,6 +2253,8 @@ config_assign_line(config_format_t *fmt, or_options_t *options, } } return 0; + } else if (c->command == CONFIG_LINE_CLEAR && !clear_first) { + option_reset(fmt, options, var, use_defaults); } if (options_seen && (var->type != CONFIG_TYPE_LINELIST && @@ -1935,10 +2277,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); @@ -1953,7 +2295,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); } @@ -1962,14 +2304,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); } @@ -2007,7 +2349,7 @@ config_lines_dup(const config_line_t *inp) config_line_t *result = NULL; config_line_t **next_out = &result; while (inp) { - *next_out = tor_malloc(sizeof(config_line_t)); + *next_out = tor_malloc_zero(sizeof(config_line_t)); (*next_out)->key = tor_strdup(inp->key); (*next_out)->value = tor_strdup(inp->value); inp = inp->next; @@ -2022,10 +2364,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); @@ -2071,6 +2413,7 @@ get_assigned_option(config_format_t *fmt, void *options, } /* fall through */ case CONFIG_TYPE_INTERVAL: + case CONFIG_TYPE_MSEC_INTERVAL: case CONFIG_TYPE_UINT: /* This means every or_options_t uint or bool element * needs to be an int. Not, say, a uint16_t or char. */ @@ -2086,6 +2429,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. */ @@ -2198,7 +2549,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; @@ -2235,6 +2586,12 @@ config_assign(config_format_t *fmt, void *options, config_line_t *list, list = list->next; } bitarray_free(options_seen); + + /** Now we're done assigning a group of options to the configuration. + * Subsequent group assignments should _replace_ linelists, not extend + * them. */ + config_mark_lists_fragile(fmt, options); + return 0; } @@ -2260,7 +2617,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. */ } @@ -2282,7 +2639,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 */ @@ -2298,11 +2656,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; @@ -2336,8 +2698,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; @@ -2377,7 +2739,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; @@ -2396,7 +2758,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; @@ -2405,7 +2767,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; @@ -2447,48 +2809,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 @@ -2496,7 +2853,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) { @@ -2504,19 +2862,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) { @@ -2535,11 +2894,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; } @@ -2574,7 +2934,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; @@ -2613,8 +2973,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; @@ -2631,7 +2992,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; @@ -2695,7 +3056,7 @@ is_listening_on_low_port(int port_option, return (port_option < 1024); for (l = listen_options; l; l = l->next) { - parse_addr_port(LOG_WARN, l->value, NULL, NULL, &p); + addr_port_lookup(LOG_WARN, l->value, NULL, NULL, &p); if (p<1024) { return 1; } @@ -2707,10 +3068,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) { @@ -2726,24 +3087,30 @@ 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 *default_options, + const void *options, int minimal, int comment_defaults) { smartlist_t *elements; - or_options_t *defaults; + const or_options_t *defaults = default_options; + void *defaults_tmp = NULL; config_line_t *line, *assigned; char *result; int i; char *msg = NULL; - defaults = config_alloc(fmt); - config_init(fmt, defaults); + if (defaults == NULL) { + defaults = defaults_tmp = config_alloc(fmt); + config_init(fmt, defaults_tmp); + } /* XXX use a 1 here so we don't add a new log line while dumping */ - if (fmt->validate_fn(NULL,defaults, 1, &msg) < 0) { - log_err(LD_BUG, "Failed to validate default config."); - tor_free(msg); - tor_assert(0); + if (default_options == NULL) { + if (fmt->validate_fn(NULL, defaults_tmp, 1, &msg) < 0) { + log_err(LD_BUG, "Failed to validate default config."); + tor_free(msg); + tor_assert(0); + } } elements = smartlist_create(); @@ -2785,7 +3152,8 @@ config_dump(config_format_t *fmt, void *options, int minimal, result = smartlist_join_strings(elements, "", 0, NULL); SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp)); smartlist_free(elements); - config_free(fmt, defaults); + if (defaults_tmp) + config_free(fmt, defaults_tmp); return result; } @@ -2794,9 +3162,10 @@ 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); + return config_dump(&options_format, global_default_options, + options, minimal, 0); } /** Return 0 if every element of sl is a string holding a decimal @@ -2853,24 +3222,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 " @@ -2898,6 +3267,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 @@ -2917,6 +3290,7 @@ options_validate(or_options_t *old_options, or_options_t *options, int i; config_line_t *cl; const char *uname = get_uname(); + int n_client_ports=0; #define REJECT(arg) \ STMT_BEGIN *msg = tor_strdup(arg); return -1; STMT_END #define COMPLAIN(arg) STMT_BEGIN log(LOG_WARN, LD_CONFIG, arg); STMT_END @@ -2940,57 +3314,8 @@ options_validate(or_options_t *old_options, or_options_t *options, if (options->DirPort == 0 && options->DirListenAddress != NULL) REJECT("DirPort must be defined if DirListenAddress is defined."); - if (options->DNSPort == 0 && options->DNSListenAddress != NULL) - REJECT("DNSPort must be defined if DNSListenAddress is defined."); - - if (options->ControlPort == 0 && options->ControlListenAddress != NULL) - REJECT("ControlPort must be defined if ControlListenAddress is defined."); - - if (options->TransPort == 0 && options->TransListenAddress != NULL) - REJECT("TransPort must be defined if TransListenAddress is defined."); - - if (options->NATDPort == 0 && options->NATDListenAddress != NULL) - REJECT("NATDPort must be defined if NATDListenAddress is defined."); - - /* Don't gripe about SocksPort 0 with SocksListenAddress set; a standard - * configuration does this. */ - - for (i = 0; i < 3; ++i) { - int is_socks = i==0; - int is_trans = i==1; - config_line_t *line, *opt, *old; - const char *tp; - if (is_socks) { - opt = options->SocksListenAddress; - old = old_options ? old_options->SocksListenAddress : NULL; - tp = "SOCKS proxy"; - } else if (is_trans) { - opt = options->TransListenAddress; - old = old_options ? old_options->TransListenAddress : NULL; - tp = "transparent proxy"; - } else { - opt = options->NATDListenAddress; - old = old_options ? old_options->NATDListenAddress : NULL; - tp = "natd proxy"; - } - - for (line = opt; line; line = line->next) { - char *address = NULL; - uint16_t port; - uint32_t addr; - if (parse_addr_port(LOG_WARN, line->value, &address, &addr, &port)<0) - continue; /* We'll warn about this later. */ - if (!is_internal_IP(addr, 1) && - (!old_options || !config_lines_eq(old, opt))) { - log_warn(LD_CONFIG, - "You specified a public address '%s' for a %s. Other " - "people on the Internet might find your computer and use it as " - "an open %s. Please don't allow this unless you have " - "a good reason.", address, tp, tp); - } - tor_free(address); - } - } + if (parse_client_ports(options, 1, msg, &n_client_ports) < 0) + return -1; if (validate_data_directory(options)<0) REJECT("Invalid DataDirectory"); @@ -3014,8 +3339,12 @@ options_validate(or_options_t *old_options, or_options_t *options, "misconfigured or something else goes wrong."); /* Special case on first boot if no Log options are given. */ - if (!options->Logs && !options->RunAsDaemon && !from_setconf) - config_line_append(&options->Logs, "Log", "notice stdout"); + if (!options->Logs && !options->RunAsDaemon && !from_setconf) { + if (quiet_level == 0) + config_line_append(&options->Logs, "Log", "notice stdout"); + else if (quiet_level == 1) + config_line_append(&options->Logs, "Log", "warn stdout"); + } if (options_init_logs(options, 1)<0) /* Validate the log(s) */ REJECT("Failed to validate Log options. See logs for details."); @@ -3027,20 +3356,12 @@ options_validate(or_options_t *old_options, or_options_t *options, REJECT("Failed to resolve/guess local address. See logs for details."); } - if (strcmp(options->RefuseUnknownExits, "0") && - strcmp(options->RefuseUnknownExits, "1") && - strcmp(options->RefuseUnknownExits, "auto")) { - REJECT("RefuseUnknownExits must be 0, 1, or auto"); - } - #ifndef MS_WINDOWS if (options->RunAsDaemon && torrc_fname && path_is_relative(torrc_fname)) REJECT("Can't use a relative path to torrc when RunAsDaemon is set."); #endif - if (options->SocksPort == 0 && options->TransPort == 0 && - options->NATDPort == 0 && options->ORPort == 0 && - options->DNSPort == 0 && !options->RendConfigLines) + if (n_client_ports == 0 && options->ORPort == 0 && !options->RendConfigLines) log(LOG_WARN, LD_CONFIG, "SocksPort, TransPort, NATDPort, DNSPort, and ORPort are all " "undefined, and there aren't any hidden services configured. " @@ -3051,6 +3372,11 @@ options_validate(or_options_t *old_options, or_options_t *options, REJECT("TransPort and TransListenAddress are disabled in this build."); #endif + if (options->TokenBucketRefillInterval <= 0 + || options->TokenBucketRefillInterval > 1000) { + REJECT("TokenBucketRefillInterval must be between 1 and 1000 inclusive."); + } + if (options->AccountingMax && (is_listening_on_low_port(options->ORPort, options->ORListenAddress) || is_listening_on_low_port(options->DirPort, options->DirListenAddress))) @@ -3070,17 +3396,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"); @@ -3142,6 +3475,15 @@ options_validate(or_options_t *old_options, or_options_t *options, return -1; } + if (options->MaxClientCircuitsPending <= 0 || + options->MaxClientCircuitsPending > MAX_MAX_CLIENT_CIRCUITS_PENDING) { + tor_asprintf(msg, + "MaxClientCircuitsPending must be between 1 and %d, but " + "was set to %d", MAX_MAX_CLIENT_CIRCUITS_PENDING, + options->MaxClientCircuitsPending); + return -1; + } + if (validate_ports_csv(options->FirewallPorts, "FirewallPorts", msg) < 0) return -1; @@ -3290,9 +3632,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."); @@ -3335,6 +3677,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."); @@ -3359,6 +3708,12 @@ options_validate(or_options_t *old_options, or_options_t *options, if (ensure_bandwidth_cap(&options->PerConnBWBurst, "PerConnBWBurst", msg) < 0) return -1; + if (ensure_bandwidth_cap(&options->AuthDirFastGuarantee, + "AuthDirFastGuarantee", msg) < 0) + return -1; + if (ensure_bandwidth_cap(&options->AuthDirGuardBWGuarantee, + "AuthDirGuardBWGuarantee", msg) < 0) + return -1; if (options->RelayBandwidthRate && !options->RelayBandwidthBurst) options->RelayBandwidthBurst = options->RelayBandwidthRate; @@ -3411,7 +3766,7 @@ options_validate(or_options_t *old_options, or_options_t *options, REJECT("Failed to parse accounting options. See logs for details."); if (options->HTTPProxy) { /* parse it now */ - if (tor_addr_port_parse(options->HTTPProxy, + if (tor_addr_port_lookup(options->HTTPProxy, &options->HTTPProxyAddr, &options->HTTPProxyPort) < 0) REJECT("HTTPProxy failed to parse or resolve. Please fix."); if (options->HTTPProxyPort == 0) { /* give it a default */ @@ -3425,7 +3780,7 @@ options_validate(or_options_t *old_options, or_options_t *options, } if (options->HTTPSProxy) { /* parse it now */ - if (tor_addr_port_parse(options->HTTPSProxy, + if (tor_addr_port_lookup(options->HTTPSProxy, &options->HTTPSProxyAddr, &options->HTTPSProxyPort) <0) REJECT("HTTPSProxy failed to parse or resolve. Please fix."); if (options->HTTPSProxyPort == 0) { /* give it a default */ @@ -3439,7 +3794,7 @@ options_validate(or_options_t *old_options, or_options_t *options, } if (options->Socks4Proxy) { /* parse it now */ - if (tor_addr_port_parse(options->Socks4Proxy, + if (tor_addr_port_lookup(options->Socks4Proxy, &options->Socks4ProxyAddr, &options->Socks4ProxyPort) <0) REJECT("Socks4Proxy failed to parse or resolve. Please fix."); @@ -3449,7 +3804,7 @@ options_validate(or_options_t *old_options, or_options_t *options, } if (options->Socks5Proxy) { /* parse it now */ - if (tor_addr_port_parse(options->Socks5Proxy, + if (tor_addr_port_lookup(options->Socks5Proxy, &options->Socks5ProxyAddr, &options->Socks5ProxyPort) <0) REJECT("Socks5Proxy failed to parse or resolve. Please fix."); @@ -3458,8 +3813,11 @@ options_validate(or_options_t *old_options, or_options_t *options, } } - if (options->Socks4Proxy && options->Socks5Proxy) - REJECT("You cannot specify both Socks4Proxy and SOCKS5Proxy"); + /* Check if more than one proxy type has been enabled. */ + if (!!options->Socks4Proxy + !!options->Socks5Proxy + + !!options->HTTPSProxy + !!options->ClientTransportPlugin > 1) + REJECT("You have configured more than one proxy type. " + "(Socks4Proxy|Socks5Proxy|HTTPSProxy|ClientTransportPlugin)"); if (options->Socks5ProxyUsername) { size_t len; @@ -3562,8 +3920,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) @@ -3576,11 +3938,20 @@ options_validate(or_options_t *old_options, or_options_t *options, REJECT("If you set UseBridges, you must specify at least one bridge."); if (options->UseBridges && !options->TunnelDirConns) REJECT("If you set UseBridges, you must set TunnelDirConns."); - if (options->Bridges) { - for (cl = options->Bridges; cl; cl = cl->next) { - if (parse_bridge_line(cl->value, 1)<0) - REJECT("Bridge line did not parse. See logs for details."); - } + + for (cl = options->Bridges; cl; cl = cl->next) { + if (parse_bridge_line(cl->value, 1)<0) + REJECT("Bridge line did not parse. See logs for details."); + } + + for (cl = options->ClientTransportPlugin; cl; cl = cl->next) { + if (parse_client_transport_line(cl->value, 1)<0) + REJECT("Transport line did not parse. See logs for details."); + } + + for (cl = options->ServerTransportPlugin; cl; cl = cl->next) { + if (parse_server_transport_line(cl->value, 1)<0) + REJECT("Server transport line did not parse. See logs for details."); } if (options->ConstrainedSockets) { @@ -3763,17 +4134,13 @@ options_validate(or_options_t *old_options, or_options_t *options, static int opt_streq(const char *s1, const char *s2) { - if (!s1 && !s2) - return 1; - else if (s1 && s2 && !strcmp(s1,s2)) - return 1; - else - return 0; + return 0 == strcmp_opt(s1, s2); } /** Check if any of the previous options have changed but aren't allowed to. */ static int -options_transition_allowed(or_options_t *old, or_options_t *new_val, +options_transition_allowed(const or_options_t *old, + const or_options_t *new_val, char **msg) { if (!old) @@ -3823,14 +4190,26 @@ options_transition_allowed(or_options_t *old, or_options_t *new_val, return -1; } + if (old->TokenBucketRefillInterval != new_val->TokenBucketRefillInterval) { + *msg = tor_strdup("While Tor is running, changing TokenBucketRefill" + "Interval is not allowed"); + return -1; + } + + if (old->DisableIOCP != new_val->DisableIOCP) { + *msg = tor_strdup("While Tor is running, changing DisableIOCP " + "is not allowed."); + return -1; + } + return 0; } /** Return 1 if any change from <b>old_options</b> to <b>new_options</b> * will require us to rotate the CPU and DNS workers; else return 0. */ static int -options_transition_affects_workers(or_options_t *old_options, - or_options_t *new_options) +options_transition_affects_workers(const or_options_t *old_options, + const or_options_t *new_options) { if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) || old_options->NumCPUs != new_options->NumCPUs || @@ -3853,8 +4232,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. */ @@ -3867,6 +4246,7 @@ options_transition_affects_descriptor(or_options_t *old_options, old_options->ORPort != new_options->ORPort || old_options->DirPort != new_options->DirPort || old_options->ClientOnly != new_options->ClientOnly || + old_options->DisableNetwork != new_options->DisableNetwork || old_options->_PublishServerDescriptor != new_options->_PublishServerDescriptor || get_effective_bwrate(old_options) != get_effective_bwrate(new_options) || @@ -3875,7 +4255,8 @@ options_transition_affects_descriptor(or_options_t *old_options, !opt_streq(old_options->ContactInfo, new_options->ContactInfo) || !opt_streq(old_options->MyFamily, new_options->MyFamily) || !opt_streq(old_options->AccountingStart, new_options->AccountingStart) || - old_options->AccountingMax != new_options->AccountingMax) + old_options->AccountingMax != new_options->AccountingMax || + public_server_mode(old_options) != public_server_mode(new_options)) return 1; return 0; @@ -3939,17 +4320,25 @@ get_windows_conf_root(void) } #endif -/** Return the default location for our torrc file. */ +/** Return the default location for our torrc file. + * DOCDOC defaults_file */ static const char * -get_default_conf_file(void) +get_default_conf_file(int defaults_file) { #ifdef MS_WINDOWS - static char path[MAX_PATH+1]; - strlcpy(path, get_windows_conf_root(), MAX_PATH); - strlcat(path,"\\torrc",MAX_PATH); - return path; + if (defaults_file) { + static char defaults_path[MAX_PATH+1]; + tor_snprintf(defaults_path, MAX_PATH, "%s\\torrc-defaults", + get_windows_conf_root()); + return defaults_path; + } else { + static char path[MAX_PATH+1]; + tor_snprintf(path, MAX_PATH, "%s\\torrc", + get_windows_conf_root()); + return path; + } #else - return (CONFDIR "/torrc"); + return defaults_file ? CONFDIR "/torrc-defaults" : CONFDIR "/torrc"; #endif } @@ -3982,37 +4371,46 @@ check_nickname_list(const char *lst, const char *name, char **msg) return r; } -/** Learn config file name from command line arguments, or use the default */ +/** Learn config file name from command line arguments, or use the default, + * DOCDOC defaults_file */ static char * find_torrc_filename(int argc, char **argv, + int defaults_file, int *using_default_torrc, int *ignore_missing_torrc) { char *fname=NULL; int i; + const char *fname_opt = defaults_file ? "--defaults-torrc" : "-f"; + const char *ignore_opt = defaults_file ? NULL : "--ignore-missing-torrc"; + + if (defaults_file) + *ignore_missing_torrc = 1; for (i = 1; i < argc; ++i) { - if (i < argc-1 && !strcmp(argv[i],"-f")) { + if (i < argc-1 && !strcmp(argv[i],fname_opt)) { if (fname) { - log(LOG_WARN, LD_CONFIG, "Duplicate -f options on command line."); + log(LOG_WARN, LD_CONFIG, "Duplicate %s options on command line.", + fname_opt); tor_free(fname); } fname = expand_filename(argv[i+1]); *using_default_torrc = 0; ++i; - } else if (!strcmp(argv[i],"--ignore-missing-torrc")) { + } else if (ignore_opt && !strcmp(argv[i],ignore_opt)) { *ignore_missing_torrc = 1; } } if (*using_default_torrc) { /* didn't find one, try CONFDIR */ - const char *dflt = get_default_conf_file(); + const char *dflt = get_default_conf_file(defaults_file); if (dflt && file_status(dflt) == FN_FILE) { fname = tor_strdup(dflt); } else { #ifndef MS_WINDOWS - char *fn; - fn = expand_filename("~/.torrc"); + char *fn = NULL; + if (!defaults_file) + fn = expand_filename("~/.torrc"); if (fn && file_status(fn) == FN_FILE) { fname = fn; } else { @@ -4027,43 +4425,48 @@ find_torrc_filename(int argc, char **argv, return fname; } -/** Load torrc from disk, setting torrc_fname if successful */ +/** Load torrc from disk, setting torrc_fname if successful. + * DOCDOC defaults_file */ static char * -load_torrc_from_disk(int argc, char **argv) +load_torrc_from_disk(int argc, char **argv, int defaults_file) { char *fname=NULL; char *cf = NULL; int using_default_torrc = 1; int ignore_missing_torrc = 0; + char **fname_var = defaults_file ? &torrc_defaults_fname : &torrc_fname; - fname = find_torrc_filename(argc, argv, + fname = find_torrc_filename(argc, argv, defaults_file, &using_default_torrc, &ignore_missing_torrc); tor_assert(fname); log(LOG_DEBUG, LD_CONFIG, "Opening config file \"%s\"", fname); - tor_free(torrc_fname); - torrc_fname = fname; + tor_free(*fname_var); + *fname_var = fname; /* Open config file */ if (file_status(fname) != FN_FILE || !(cf = read_file_to_str(fname,0,NULL))) { - if (using_default_torrc == 1 || ignore_missing_torrc ) { - log(LOG_NOTICE, LD_CONFIG, "Configuration file \"%s\" not present, " - "using reasonable defaults.", fname); + if (using_default_torrc == 1 || ignore_missing_torrc) { + if (!defaults_file) + log(LOG_NOTICE, LD_CONFIG, "Configuration file \"%s\" not present, " + "using reasonable defaults.", fname); tor_free(fname); /* sets fname to NULL */ - torrc_fname = NULL; + *fname_var = NULL; cf = tor_strdup(""); } else { log(LOG_WARN, LD_CONFIG, "Unable to open configuration file \"%s\".", fname); goto err; } + } else { + log(LOG_NOTICE, LD_CONFIG, "Read configuration file \"%s\".", fname); } return cf; err: tor_free(fname); - torrc_fname = NULL; + *fname_var = NULL; return NULL; } @@ -4074,7 +4477,7 @@ load_torrc_from_disk(int argc, char **argv) int options_init_from_torrc(int argc, char **argv) { - char *cf=NULL; + char *cf=NULL, *cf_defaults=NULL; int i, retval, command; static char **backup_argv; static int backup_argc; @@ -4134,13 +4537,15 @@ options_init_from_torrc(int argc, char **argv) if (command == CMD_HASH_PASSWORD) { cf = tor_strdup(""); } else { - cf = load_torrc_from_disk(argc, argv); + cf_defaults = load_torrc_from_disk(argc, argv, 1); + cf = load_torrc_from_disk(argc, argv, 0); if (!cf) goto err; } - retval = options_init_from_string(cf, command, command_arg, &errmsg); + retval = options_init_from_string(cf_defaults, cf, command, command_arg, &errmsg); tor_free(cf); + tor_free(cf_defaults); if (retval < 0) goto err; @@ -4164,13 +4569,13 @@ options_init_from_torrc(int argc, char **argv) * * -4 for error while setting the new options */ setopt_err_t -options_init_from_string(const char *cf, +options_init_from_string(const char *cf_defaults, const char *cf, int command, const char *command_arg, char **msg) { - or_options_t *oldoptions, *newoptions; + or_options_t *oldoptions, *newoptions, *newdefaultoptions=NULL; config_line_t *cl; - int retval; + int retval, i; setopt_err_t err = SETOPT_ERR_MISC; tor_assert(msg); @@ -4183,17 +4588,24 @@ options_init_from_string(const char *cf, newoptions->command = command; newoptions->command_arg = command_arg; - /* get config lines, assign them */ - retval = config_get_lines(cf, &cl); - if (retval < 0) { - err = SETOPT_ERR_PARSE; - goto err; - } - retval = config_assign(&options_format, newoptions, cl, 0, 0, msg); - config_free_lines(cl); - if (retval < 0) { - err = SETOPT_ERR_PARSE; - goto err; + for (i = 0; i < 2; ++i) { + const char *body = i==0 ? cf_defaults : cf; + if (!body) + continue; + /* get config lines, assign them */ + retval = config_get_lines(body, &cl, 1); + if (retval < 0) { + err = SETOPT_ERR_PARSE; + goto err; + } + retval = config_assign(&options_format, newoptions, cl, 0, 0, msg); + config_free_lines(cl); + if (retval < 0) { + err = SETOPT_ERR_PARSE; + goto err; + } + if (i==0) + newdefaultoptions = options_dup(&options_format, newoptions); } /* Go through command-line variables too */ @@ -4218,9 +4630,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; @@ -4228,6 +4640,8 @@ options_init_from_string(const char *cf, /* Clear newoptions and re-initialize them with new defaults. */ config_free(&options_format, newoptions); + config_free(&options_format, newdefaultoptions); + newdefaultoptions = NULL; newoptions = tor_malloc_zero(sizeof(or_options_t)); newoptions->_magic = OR_OPTIONS_MAGIC; options_init(newoptions); @@ -4235,22 +4649,24 @@ options_init_from_string(const char *cf, newoptions->command_arg = command_arg; /* Assign all options a second time. */ - retval = config_get_lines(cf, &cl); - if (retval < 0) { - err = SETOPT_ERR_PARSE; - goto err; - } - retval = config_assign(&options_format, newoptions, cl, 0, 0, msg); - config_free_lines(cl); - if (retval < 0) { - err = SETOPT_ERR_PARSE; - goto err; - } - retval = config_assign(&options_format, newoptions, - global_cmdline_options, 0, 0, msg); - if (retval < 0) { - err = SETOPT_ERR_PARSE; - goto err; + for (i = 0; i < 2; ++i) { + const char *body = i==0 ? cf_defaults : cf; + if (!body) + continue; + /* get config lines, assign them */ + retval = config_get_lines(body, &cl, 1); + if (retval < 0) { + err = SETOPT_ERR_PARSE; + goto err; + } + retval = config_assign(&options_format, newoptions, cl, 0, 0, msg); + config_free_lines(cl); + if (retval < 0) { + err = SETOPT_ERR_PARSE; + goto err; + } + if (i==0) + newdefaultoptions = options_dup(&options_format, newoptions); } } @@ -4269,11 +4685,14 @@ options_init_from_string(const char *cf, err = SETOPT_ERR_SETTING; goto err; /* frees and replaces old options */ } + config_free(&options_format, global_default_options); + global_default_options = newdefaultoptions; return SETOPT_OK; err: config_free(&options_format, newoptions); + config_free(&options_format, newdefaultoptions); if (*msg) { char *old_msg = *msg; tor_asprintf(msg, "Failed to parse/validate config: %s", old_msg); @@ -4285,19 +4704,21 @@ options_init_from_string(const char *cf, /** Return the location for our configuration file. */ const char * -get_torrc_fname(void) +get_torrc_fname(int defaults_fname) { - if (torrc_fname) - return torrc_fname; + const char *fname = defaults_fname ? torrc_defaults_fname : torrc_fname; + + if (fname) + return fname; else - return get_default_conf_file(); + return get_default_conf_file(defaults_fname); } /** Adjust the address map based on the MapAddress elements in the * configuration <b>options</b> */ -static void -config_register_addressmaps(or_options_t *options) +void +config_register_addressmaps(const or_options_t *options) { smartlist_t *elts; config_line_t *opt; @@ -4346,6 +4767,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(); @@ -4435,6 +4885,8 @@ parse_bridge_line(const char *line, int validate_only) smartlist_t *items = NULL; int r; char *addrport=NULL, *fingerprint=NULL; + char *transport_name=NULL; + char *field1=NULL; tor_addr_t addr; uint16_t port = 0; char digest[DIGEST_LEN]; @@ -4446,9 +4898,25 @@ parse_bridge_line(const char *line, int validate_only) log_warn(LD_CONFIG, "Too few arguments to Bridge line."); goto err; } - addrport = smartlist_get(items, 0); + + /* field1 is either a transport name or addrport */ + field1 = smartlist_get(items, 0); smartlist_del_keeporder(items, 0); - if (tor_addr_port_parse(addrport, &addr, &port)<0) { + + if (!(strstr(field1, ".") || strstr(field1, ":"))) { + /* new-style bridge line */ + transport_name = field1; + if (smartlist_len(items) < 1) { + log_warn(LD_CONFIG, "Too few items to Bridge line."); + goto err; + } + addrport = smartlist_get(items, 0); + smartlist_del_keeporder(items, 0); + } else { + addrport = field1; + } + + if (tor_addr_port_lookup(addrport, &addr, &port)<0) { log_warn(LD_CONFIG, "Error parsing Bridge address '%s'", addrport); goto err; } @@ -4472,26 +4940,282 @@ parse_bridge_line(const char *line, int validate_only) } if (!validate_only) { - log_debug(LD_DIR, "Bridge at %s:%d (%s)", fmt_addr(&addr), - (int)port, + log_debug(LD_DIR, "Bridge at %s:%d (transport: %s) (%s)", + fmt_addr(&addr), (int)port, + transport_name ? transport_name : "no transport", fingerprint ? fingerprint : "no key listed"); - bridge_add_from_config(&addr, port, fingerprint ? digest : NULL); + bridge_add_from_config(&addr, port, + fingerprint ? digest : NULL, transport_name); } r = 0; goto done; - err: + err: r = -1; - done: + done: SMARTLIST_FOREACH(items, char*, s, tor_free(s)); smartlist_free(items); tor_free(addrport); + tor_free(transport_name); tor_free(fingerprint); return r; } +/** Read the contents of a ClientTransportPlugin line from + * <b>line</b>. Return 0 if the line is well-formed, and -1 if it + * isn't. + * + * If <b>validate_only</b> is 0, and the line is well-formed: + * - If it's an external proxy line, add the transport described in the line to + * our internal transport list. + * - If it's a managed proxy line, launch the managed proxy. */ +static int +parse_client_transport_line(const char *line, int validate_only) +{ + smartlist_t *items = NULL; + int r; + char *field2=NULL; + + const char *transports=NULL; + smartlist_t *transport_list=NULL; + char *addrport=NULL; + tor_addr_t addr; + uint16_t port = 0; + int socks_ver=PROXY_NONE; + + /* managed proxy options */ + int is_managed=0; + char **proxy_argv=NULL; + char **tmp=NULL; + int proxy_argc,i; + + int line_length; + + items = smartlist_create(); + smartlist_split_string(items, line, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + + line_length = smartlist_len(items); + if (line_length < 3) { + log_warn(LD_CONFIG, "Too few arguments on ClientTransportPlugin line."); + goto err; + } + + /* Get the first line element, split it to commas into + transport_list (in case it's multiple transports) and validate + the transport names. */ + transports = smartlist_get(items, 0); + transport_list = smartlist_create(); + smartlist_split_string(transport_list, transports, ",", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport_name) { + if (!string_is_C_identifier(transport_name)) { + log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).", + transport_name); + goto err; + } + } SMARTLIST_FOREACH_END(transport_name); + + /* field2 is either a SOCKS version or "exec" */ + field2 = smartlist_get(items, 1); + + if (!strcmp(field2,"socks4")) { + socks_ver = PROXY_SOCKS4; + } else if (!strcmp(field2,"socks5")) { + socks_ver = PROXY_SOCKS5; + } else if (!strcmp(field2,"exec")) { + is_managed=1; + } else { + log_warn(LD_CONFIG, "Strange ClientTransportPlugin field '%s'.", + field2); + goto err; + } + + if (is_managed) { /* managed */ + if (!validate_only) { /* if we are not just validating, use the + rest of the line as the argv of the proxy + to be launched */ + proxy_argc = line_length-2; + tor_assert(proxy_argc > 0); + proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1)); + tmp = proxy_argv; + for (i=0;i<proxy_argc;i++) { /* store arguments */ + *tmp++ = smartlist_get(items, 2); + smartlist_del_keeporder(items, 2); + } + *tmp = NULL; /*terminated with NUL pointer, just like execve() likes it*/ + + /* kickstart the thing */ + pt_kickstart_client_proxy(transport_list, proxy_argv); + } + } else { /* external */ + if (smartlist_len(transport_list) != 1) { + log_warn(LD_CONFIG, "You can't have an external proxy with " + "more than one transports."); + goto err; + } + + addrport = smartlist_get(items, 2); + + if (tor_addr_port_lookup(addrport, &addr, &port)<0) { + log_warn(LD_CONFIG, "Error parsing transport " + "address '%s'", addrport); + goto err; + } + if (!port) { + log_warn(LD_CONFIG, + "Transport address '%s' has no port.", addrport); + goto err; + } + + if (!validate_only) { + transport_add_from_config(&addr, port, smartlist_get(transport_list, 0), + socks_ver); + + log_info(LD_DIR, "Transport '%s' found at %s:%d", + transports, fmt_addr(&addr), (int)port); + } + } + + r = 0; + goto done; + + err: + r = -1; + + done: + SMARTLIST_FOREACH(items, char*, s, tor_free(s)); + smartlist_free(items); + if (transport_list) { + SMARTLIST_FOREACH(transport_list, char*, s, tor_free(s)); + smartlist_free(transport_list); + } + + return r; +} + +/** Read the contents of a ServerTransportPlugin line from + * <b>line</b>. Return 0 if the line is well-formed, and -1 if it + * isn't. + * If <b>validate_only</b> is 0, the line is well-formed, and it's a + * managed proxy line, launch the managed proxy. */ +static int +parse_server_transport_line(const char *line, int validate_only) +{ + smartlist_t *items = NULL; + int r; + const char *transports=NULL; + smartlist_t *transport_list=NULL; + char *type=NULL; + char *addrport=NULL; + tor_addr_t addr; + uint16_t port = 0; + + /* managed proxy options */ + int is_managed=0; + char **proxy_argv=NULL; + char **tmp=NULL; + int proxy_argc,i; + + int line_length; + + items = smartlist_create(); + smartlist_split_string(items, line, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + + line_length = smartlist_len(items); + if (line_length < 3) { + log_warn(LD_CONFIG, "Too few arguments on ServerTransportPlugin line."); + goto err; + } + + /* Get the first line element, split it to commas into + transport_list (in case it's multiple transports) and validate + the transport names. */ + transports = smartlist_get(items, 0); + transport_list = smartlist_create(); + smartlist_split_string(transport_list, transports, ",", + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport_name) { + if (!string_is_C_identifier(transport_name)) { + log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).", + transport_name); + goto err; + } + } SMARTLIST_FOREACH_END(transport_name); + + type = smartlist_get(items, 1); + + if (!strcmp(type, "exec")) { + is_managed=1; + } else if (!strcmp(type, "proxy")) { + is_managed=0; + } else { + log_warn(LD_CONFIG, "Strange ServerTransportPlugin type '%s'", type); + goto err; + } + + if (is_managed) { /* managed */ + if (!validate_only) { + proxy_argc = line_length-2; + tor_assert(proxy_argc > 0); + proxy_argv = tor_malloc_zero(sizeof(char*)*(proxy_argc+1)); + tmp = proxy_argv; + + for (i=0;i<proxy_argc;i++) { /* store arguments */ + *tmp++ = smartlist_get(items, 2); + smartlist_del_keeporder(items, 2); + } + *tmp = NULL; /*terminated with NUL pointer, just like execve() likes it*/ + + /* kickstart the thing */ + pt_kickstart_server_proxy(transport_list, proxy_argv); + } + } else { /* external */ + if (smartlist_len(transport_list) != 1) { + log_warn(LD_CONFIG, "You can't have an external proxy with " + "more than one transports."); + goto err; + } + + addrport = smartlist_get(items, 2); + + if (tor_addr_port_lookup(addrport, &addr, &port)<0) { + log_warn(LD_CONFIG, "Error parsing transport " + "address '%s'", addrport); + goto err; + } + if (!port) { + log_warn(LD_CONFIG, + "Transport address '%s' has no port.", addrport); + goto err; + } + + if (!validate_only) { + log_info(LD_DIR, "Server transport '%s' at %s:%d.", + transports, fmt_addr(&addr), (int)port); + } + } + + r = 0; + goto done; + + err: + r = -1; + + done: + SMARTLIST_FOREACH(items, char*, s, tor_free(s)); + smartlist_free(items); + if (transport_list) { + SMARTLIST_FOREACH(transport_list, char*, s, tor_free(s)); + smartlist_free(transport_list); + } + + return r; +} + /** Read the contents of a DirServer line from <b>line</b>. If * <b>validate_only</b> is 0, and the line is well-formed, and it * shares any bits with <b>required_type</b> or <b>required_type</b> @@ -4499,7 +5223,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; @@ -4508,7 +5232,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(); @@ -4529,13 +5253,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=")) { @@ -4552,7 +5276,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", @@ -4562,9 +5286,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."); @@ -4572,7 +5296,7 @@ parse_dir_server_line(const char *line, authority_type_t required_type, } addrport = smartlist_get(items, 0); smartlist_del_keeporder(items, 0); - if (parse_addr_port(LOG_WARN, addrport, &address, NULL, &dir_port)<0) { + if (addr_port_lookup(LOG_WARN, addrport, &address, NULL, &dir_port)<0) { log_warn(LD_CONFIG, "Error parsing DirServer address '%s'", addrport); goto err; } @@ -4592,7 +5316,7 @@ parse_dir_server_line(const char *line, authority_type_t required_type, * clause once Tor 0.1.2.17 is obsolete. */ log_warn(LD_CONFIG, "Dangerous dirserver line. To correct, erase your " "torrc file (%s), or reinstall Tor and use the default torrc.", - get_torrc_fname()); + get_torrc_fname(0)); goto err; } if (base16_decode(digest, DIGEST_LEN, fingerprint, HEX_DIGEST_LEN)<0) { @@ -4627,6 +5351,374 @@ parse_dir_server_line(const char *line, authority_type_t required_type, return r; } +/** Free all storage held in <b>port</b> */ +static void +port_cfg_free(port_cfg_t *port) +{ + tor_free(port); +} + +/** Warn for every port in <b>ports</b> that is on a publicly routable + * address. */ +static void +warn_nonlocal_client_ports(const smartlist_t *ports, const char *portname) +{ + SMARTLIST_FOREACH_BEGIN(ports, const port_cfg_t *, port) { + if (port->is_unix_addr) { + /* Unix sockets aren't accessible over a network. */ + } else if (!tor_addr_is_internal(&port->addr, 1)) { + log_warn(LD_CONFIG, "You specified a public address for %sPort. " + "Other people on the Internet might find your computer and " + "use it as an open proxy. Please don't allow this unless you " + "have a good reason.", portname); + } else if (!tor_addr_is_loopback(&port->addr)) { + log_notice(LD_CONFIG, "You configured a non-loopback address for " + "%sPort. This allows everybody on your local network to use " + "your machine as a proxy. Make sure this is what you wanted.", + portname); + } + } SMARTLIST_FOREACH_END(port); +} + +#define CL_PORT_NO_OPTIONS (1u<<0) +#define CL_PORT_WARN_NONLOCAL (1u<<1) +#define CL_PORT_ALLOW_EXTRA_LISTENADDR (1u<<2) + +/** + * Parse port configuration for a single client port type. + * + * Read entries of the "FooPort" type from the list <b>ports</b>, and + * entries of the "FooListenAddress" type from the list + * <b>listenaddrs</b>. Two syntaxes are supported: a legacy syntax + * where FooPort is at most a single entry containing a port number and + * where FooListenAddress has any number of address:port combinations; + * and a new syntax where there are no FooListenAddress entries and + * where FooPort can have any number of entries of the format + * "[Address:][Port] IsolationOptions". + * + * In log messages, describe the port type as <b>portname</b>. + * + * If no address is specified, default to <b>defaultaddr</b>. If no + * FooPort is given, default to defaultport (if 0, there is no default). + * + * If CL_PORT_NO_OPTIONS is set in <b>flags</b>, do not allow stream + * isolation options in the FooPort entries. + * + * If CL_PORT_WARN_NONLOCAL is set in <b>flags</b>, warn if any of the + * ports are not on a local address. + * + * Unless CL_PORT_ALLOW_EXTRA_LISTENADDR is set in <b>flags</b>, warn + * if FooListenAddress is set but FooPort is 0. + * + * On success, if <b>out</b> is given, add a new port_cfg_t entry to + * <b>out</b> for every port that the client should listen on. Return 0 + * on success, -1 on failure. + */ +static int +parse_client_port_config(smartlist_t *out, + const config_line_t *ports, + const config_line_t *listenaddrs, + const char *portname, + int listener_type, + const char *defaultaddr, + int defaultport, + unsigned flags) +{ + smartlist_t *elts; + int retval = -1; + const unsigned allow_client_options = !(flags & CL_PORT_NO_OPTIONS); + const unsigned warn_nonlocal = flags & CL_PORT_WARN_NONLOCAL; + const unsigned allow_spurious_listenaddr = + flags & CL_PORT_ALLOW_EXTRA_LISTENADDR; + + /* FooListenAddress is deprecated; let's make it work like it used to work, + * though. */ + if (listenaddrs) { + int mainport = defaultport; + + if (ports && ports->next) { + log_warn(LD_CONFIG, "%sListenAddress can't be used when there are " + "multiple %sPort lines", portname, portname); + return -1; + } else if (ports) { + if (!strcmp(ports->value, "auto")) { + mainport = CFG_AUTO_PORT; + } else { + int ok; + mainport = (int)tor_parse_long(ports->value, 10, 0, 65535, &ok, NULL); + if (!ok) { + log_warn(LD_CONFIG, "%sListenAddress can only be used with a single " + "%sPort with value \"auto\" or 1-65535.", + portname, portname); + return -1; + } + } + } + + if (mainport == 0) { + if (allow_spurious_listenaddr) + return 1; + log_warn(LD_CONFIG, "%sPort must be defined if %sListenAddress is used", + portname, portname); + return -1; + } + + for (; listenaddrs; listenaddrs = listenaddrs->next) { + tor_addr_t addr; + uint16_t port = 0; + if (tor_addr_port_lookup(listenaddrs->value, &addr, &port) < 0) { + log_warn(LD_CONFIG, "Unable to parse %sListenAddress '%s'", + portname, listenaddrs->value); + return -1; + } + if (out) { + port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t)); + cfg->type = listener_type; + cfg->port = port ? port : mainport; + tor_addr_copy(&cfg->addr, &addr); + cfg->session_group = SESSION_GROUP_UNSET; + cfg->isolation_flags = ISO_DEFAULT; + smartlist_add(out, cfg); + } + } + + if (warn_nonlocal && out) + warn_nonlocal_client_ports(out, portname); + return 0; + } /* end if (listenaddrs) */ + + /* No ListenAddress lines. If there's no FooPort, then maybe make a default + * one. */ + if (! ports) { + if (defaultport && out) { + port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t)); + cfg->type = listener_type; + cfg->port = defaultport; + tor_addr_parse(&cfg->addr, defaultaddr); + cfg->session_group = SESSION_GROUP_UNSET; + cfg->isolation_flags = ISO_DEFAULT; + smartlist_add(out, cfg); + } + return 0; + } + + /* At last we can actually parse the FooPort lines. The syntax is: + * [Addr:](Port|auto) [Options].*/ + elts = smartlist_create(); + + for (; ports; ports = ports->next) { + tor_addr_t addr; + int port; + int sessiongroup = SESSION_GROUP_UNSET; + unsigned isolation = ISO_DEFAULT; + + char *addrport; + uint16_t ptmp=0; + int ok; + + smartlist_split_string(elts, ports->value, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + if (smartlist_len(elts) == 0) { + log_warn(LD_CONFIG, "Invalid %sPort line with no value", portname); + goto err; + } + + if (!allow_client_options && smartlist_len(elts) > 1) { + log_warn(LD_CONFIG, "Too many options on %sPort line", portname); + goto err; + } + + /* Now parse the addr/port value */ + addrport = smartlist_get(elts, 0); + if (!strcmp(addrport, "auto")) { + port = CFG_AUTO_PORT; + tor_addr_parse(&addr, defaultaddr); + } else if (!strcasecmpend(addrport, ":auto")) { + char *addrtmp = tor_strndup(addrport, strlen(addrport)-5); + port = CFG_AUTO_PORT; + if (tor_addr_port_lookup(addrtmp, &addr, &ptmp)<0 || ptmp) { + log_warn(LD_CONFIG, "Invalid address '%s' for %sPort", + escaped(addrport), portname); + tor_free(addrtmp); + goto err; + } + } else { + /* Try parsing integer port before address, because, who knows? + "9050" might be a valid address. */ + port = (int) tor_parse_long(addrport, 10, 0, 65535, &ok, NULL); + if (ok) { + tor_addr_parse(&addr, defaultaddr); + } else if (tor_addr_port_lookup(addrport, &addr, &ptmp) == 0) { + if (ptmp == 0) { + log_warn(LD_CONFIG, "%sPort line has address but no port", portname); + goto err; + } + port = ptmp; + } else { + log_warn(LD_CONFIG, "Couldn't parse address '%s' for %sPort", + escaped(addrport), portname); + goto err; + } + } + + /* Now parse the rest of the options, if any. */ + SMARTLIST_FOREACH_BEGIN(elts, char *, elt) { + int no = 0, isoflag = 0; + const char *elt_orig = elt; + if (elt_sl_idx == 0) + continue; /* Skip addr:port */ + if (!strcasecmpstart(elt, "SessionGroup=")) { + int group = (int)tor_parse_long(elt+strlen("SessionGroup="), + 10, 0, INT_MAX, &ok, NULL); + if (!ok) { + log_warn(LD_CONFIG, "Invalid %sPort option '%s'", + portname, escaped(elt)); + goto err; + } + if (sessiongroup >= 0) { + log_warn(LD_CONFIG, "Multiple SessionGroup options on %sPort", + portname); + goto err; + } + sessiongroup = group; + continue; + } + + if (!strcasecmpstart(elt, "No")) { + no = 1; + elt += 2; + } + if (!strcasecmpend(elt, "s")) + elt[strlen(elt)-1] = '\0'; /* kill plurals. */ + + if (!strcasecmp(elt, "IsolateDestPort")) { + isoflag = ISO_DESTPORT; + } else if (!strcasecmp(elt, "IsolateDestAddr")) { + isoflag = ISO_DESTADDR; + } else if (!strcasecmp(elt, "IsolateSOCKSAuth")) { + isoflag = ISO_SOCKSAUTH; + } else if (!strcasecmp(elt, "IsolateClientProtocol")) { + isoflag = ISO_CLIENTPROTO; + } else if (!strcasecmp(elt, "IsolateClientAddr")) { + isoflag = ISO_CLIENTADDR; + } else { + log_warn(LD_CONFIG, "Unrecognized %sPort option '%s'", + portname, escaped(elt_orig)); + } + + if (no) { + isolation &= ~isoflag; + } else { + isolation |= isoflag; + } + } SMARTLIST_FOREACH_END(elt); + + if (out && port) { + port_cfg_t *cfg = tor_malloc_zero(sizeof(port_cfg_t)); + cfg->type = listener_type; + cfg->port = port; + tor_addr_copy(&cfg->addr, &addr); + cfg->session_group = sessiongroup; + cfg->isolation_flags = isolation; + smartlist_add(out, cfg); + } + SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp)); + smartlist_clear(elts); + } + + if (warn_nonlocal && out) + warn_nonlocal_client_ports(out, portname); + + retval = 0; + err: + SMARTLIST_FOREACH(elts, char *, cp, tor_free(cp)); + smartlist_free(elts); + return retval; +} + +/** Parse all client port types (Socks, DNS, Trans, NATD) from + * <b>options</b>. On success, set *<b>n_ports_out</b> to the number of + * ports that are listed and return 0. On failure, set *<b>msg</b> to a + * description of the problem and return -1. + * + * If <b>validate_only</b> is false, set configured_client_ports to the + * new list of ports parsed from <b>options</b>. + **/ +static int +parse_client_ports(const or_options_t *options, int validate_only, + char **msg, int *n_ports_out) +{ + smartlist_t *ports; + int retval = -1; + + ports = smartlist_create(); + + *n_ports_out = 0; + + if (parse_client_port_config(ports, + options->SocksPort, options->SocksListenAddress, + "Socks", CONN_TYPE_AP_LISTENER, + "127.0.0.1", 9050, + CL_PORT_WARN_NONLOCAL|CL_PORT_ALLOW_EXTRA_LISTENADDR) < 0) { + *msg = tor_strdup("Invalid SocksPort/SocksListenAddress configuration"); + goto err; + } + if (parse_client_port_config(ports, + options->DNSPort, options->DNSListenAddress, + "DNS", CONN_TYPE_AP_DNS_LISTENER, + "127.0.0.1", 0, + CL_PORT_WARN_NONLOCAL) < 0) { + *msg = tor_strdup("Invalid DNSPort/DNSListenAddress configuration"); + goto err; + } + if (parse_client_port_config(ports, + options->TransPort, options->TransListenAddress, + "Trans", CONN_TYPE_AP_TRANS_LISTENER, + "127.0.0.1", 0, + CL_PORT_WARN_NONLOCAL) < 0) { + *msg = tor_strdup("Invalid TransPort/TransListenAddress configuration"); + goto err; + } + if (parse_client_port_config(ports, + options->NATDPort, options->NATDListenAddress, + "NATD", CONN_TYPE_AP_NATD_LISTENER, + "127.0.0.1", 0, + CL_PORT_WARN_NONLOCAL) < 0) { + *msg = tor_strdup("Invalid NatdPort/NatdListenAddress configuration"); + goto err; + } + + *n_ports_out = smartlist_len(ports); + + if (!validate_only) { + if (configured_client_ports) { + SMARTLIST_FOREACH(configured_client_ports, + port_cfg_t *, p, port_cfg_free(p)); + smartlist_free(configured_client_ports); + } + configured_client_ports = ports; + ports = NULL; /* prevent free below. */ + } + + retval = 0; + err: + if (ports) { + SMARTLIST_FOREACH(ports, port_cfg_t *, p, port_cfg_free(p)); + smartlist_free(ports); + } + return retval; +} + +/** Return a list of port_cfg_t for client ports parsed from the + * options. */ +const smartlist_t * +get_configured_client_ports(void) +{ + if (!configured_client_ports) + configured_client_ports = smartlist_create(); + return configured_client_ports; +} + /** Adjust the value of options->DataDirectory, or fill it in if it's * absent. Return 0 on success, -1 on failure. */ static int @@ -4698,7 +5790,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; @@ -4783,7 +5875,7 @@ options_save_current(void) * If we try falling back to datadirectory or something, we have a better * chance of saving the configuration, but a better chance of doing * something the user never expected. */ - return write_configuration_file(get_torrc_fname(), get_options()); + return write_configuration_file(get_torrc_fname(0), get_options()); } /** Mapping from a unit name to a multiplier for converting that unit into a @@ -4839,6 +5931,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. @@ -4902,6 +6014,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. @@ -4921,13 +6052,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 @@ -4937,7 +6084,12 @@ init_libevent(void) tor_check_libevent_header_compatibility(); - tor_libevent_initialize(); + memset(&cfg, 0, sizeof(cfg)); + cfg.disable_iocp = options->DisableIOCP; + cfg.num_cpus = get_num_cpus(options); + cfg.msec_per_tick = options->TokenBucketRefillInterval; + + tor_libevent_initialize(&cfg); suppress_libevent_log_msg(NULL); @@ -4976,7 +6128,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) { @@ -5011,6 +6163,69 @@ options_get_datadir_fname2_suffix(or_options_t *options, return fname; } +/** Return true if <b>line</b> is a valid state TransportProxy line. + * Return false otherwise. */ +static int +state_transport_line_is_valid(const char *line) +{ + smartlist_t *items = NULL; + char *addrport=NULL; + tor_addr_t addr; + uint16_t port = 0; + int r; + + items = smartlist_create(); + smartlist_split_string(items, line, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + + if (smartlist_len(items) != 2) { + log_warn(LD_CONFIG, "state: Not enough arguments in TransportProxy line."); + goto err; + } + + addrport = smartlist_get(items, 1); + if (tor_addr_port_lookup(addrport, &addr, &port) < 0) { + log_warn(LD_CONFIG, "state: Could not parse addrport."); + goto err; + } + + if (!port) { + log_warn(LD_CONFIG, "state: Transport line did not contain port."); + goto err; + } + + r = 1; + goto done; + + err: + r = 0; + + done: + SMARTLIST_FOREACH(items, char*, s, tor_free(s)); + smartlist_free(items); + return r; +} + +/** Return 0 if all TransportProxy lines in <b>state</b> are well + * formed. Otherwise, return -1. */ +static int +validate_transports_in_state(or_state_t *state) +{ + int broken = 0; + config_line_t *line; + + for (line = state->TransportProxies ; line ; line = line->next) { + tor_assert(!strcmp(line->key, "TransportProxy")); + if (!state_transport_line_is_valid(line->value)) + broken = 1; + } + + if (broken) + log_warn(LD_CONFIG, "state: State file seems to be broken."); + + return 0; +} + /** Return 0 if every setting in <b>state</b> is reasonable, and a * permissible transition from <b>old_state</b>. Else warn and return -1. * Should have no side effects, except for normalizing the contents of @@ -5029,6 +6244,9 @@ or_state_validate(or_state_t *old_state, or_state_t *state, if (entry_guards_parse_state(state, 0, msg)<0) return -1; + if (validate_transports_in_state(state)<0) + return -1; + return 0; } @@ -5123,7 +6341,7 @@ or_state_load(void) if (contents) { config_line_t *lines=NULL; int assign_retval; - if (config_get_lines(contents, &lines)<0) + if (config_get_lines(contents, &lines, 0)<0) goto done; assign_retval = config_assign(&state_format, new_state, lines, 0, 0, &errmsg); @@ -5227,7 +6445,7 @@ or_state_save(time_t now) tor_free(global_state->TorVersion); tor_asprintf(&global_state->TorVersion, "Tor %s", get_version()); - state = config_dump(&state_format, global_state, 1, 0); + state = config_dump(&state_format, NULL, global_state, 1, 0); format_local_iso_time(tbuf, now); tor_asprintf(&contents, "# Tor state file last generated on %s local time\n" @@ -5261,6 +6479,150 @@ or_state_save(time_t now) return 0; } +/** Return the config line for transport <b>transport</b> in the current state. + * Return NULL if there is no config line for <b>transport</b>. */ +static config_line_t * +get_transport_in_state_by_name(const char *transport) +{ + or_state_t *or_state = get_or_state(); + config_line_t *line; + config_line_t *ret = NULL; + smartlist_t *items = NULL; + + for (line = or_state->TransportProxies ; line ; line = line->next) { + tor_assert(!strcmp(line->key, "TransportProxy")); + + items = smartlist_create(); + smartlist_split_string(items, line->value, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + if (smartlist_len(items) != 2) /* broken state */ + goto done; + + if (!strcmp(smartlist_get(items, 0), transport)) { + ret = line; + goto done; + } + + SMARTLIST_FOREACH(items, char*, s, tor_free(s)); + smartlist_free(items); + items = NULL; + } + + done: + if (items) { + SMARTLIST_FOREACH(items, char*, s, tor_free(s)); + smartlist_free(items); + } + return ret; +} + +/** Return string containing the address:port part of the + * TransportProxy <b>line</b> for transport <b>transport</b>. + * If the line is corrupted, return NULL. */ +static const char * +get_transport_bindaddr(const char *line, const char *transport) +{ + char *line_tmp = NULL; + + if (strlen(line) < strlen(transport) + 2) { + goto broken_state; + } else { + /* line should start with the name of the transport and a space. + (for example, "obfs2 127.0.0.1:47245") */ + tor_asprintf(&line_tmp, "%s ", transport); + if (strcmpstart(line, line_tmp)) + goto broken_state; + + tor_free(line_tmp); + return (line+strlen(transport)+1); + } + + broken_state: + tor_free(line_tmp); + return NULL; +} + +/** Return a static string containing the address:port a proxy + * transport should bind on. */ +const char * +get_bindaddr_for_transport(const char *transport) +{ + static const char default_addrport[] = "127.0.0.1:0"; + const char *bindaddr = NULL; + + config_line_t *line = get_transport_in_state_by_name(transport); + if (!line) + return default_addrport; + + bindaddr = get_transport_bindaddr(line->value, transport); + + return bindaddr ? bindaddr : default_addrport; +} + +/** Save <b>transport</b> listening on <b>addr</b>:<b>port</b> to + state */ +void +save_transport_to_state(const char *transport, + const tor_addr_t *addr, uint16_t port) +{ + or_state_t *state = get_or_state(); + + char *transport_addrport=NULL; + + /** find where to write on the state */ + config_line_t **next, *line; + + /* see if this transport is already stored in state */ + config_line_t *transport_line = + get_transport_in_state_by_name(transport); + + if (transport_line) { /* if transport already exists in state... */ + const char *prev_bindaddr = /* get its addrport... */ + get_transport_bindaddr(transport_line->value, transport); + tor_asprintf(&transport_addrport, "%s:%d", fmt_addr(addr), (int)port); + + /* if transport in state has the same address as this one, life is good */ + if (!strcmp(prev_bindaddr, transport_addrport)) { + log_info(LD_CONFIG, "Transport seems to have spawned on its usual " + "address:port."); + goto done; + } else { /* if addrport in state is different than the one we got */ + log_info(LD_CONFIG, "Transport seems to have spawned on different " + "address:port. Let's update the state file with the new " + "address:port"); + tor_free(transport_line->value); /* free the old line */ + tor_asprintf(&transport_line->value, "%s %s:%d", transport, + fmt_addr(addr), + (int) port); /* replace old addrport line with new line */ + } + } else { /* never seen this one before; save it in state for next time */ + log_info(LD_CONFIG, "It's the first time we see this transport. " + "Let's save its address:port"); + next = &state->TransportProxies; + /* find the last TransportProxy line in the state and point 'next' + right after it */ + line = state->TransportProxies; + while (line) { + next = &(line->next); + line = line->next; + } + + /* allocate space for the new line and fill it in */ + *next = line = tor_malloc_zero(sizeof(config_line_t)); + line->key = tor_strdup("TransportProxy"); + tor_asprintf(&line->value, "%s %s:%d", transport, + fmt_addr(addr), (int) port); + + next = &(line->next); + } + + if (!get_options()->AvoidDiskWrites) + or_state_mark_dirty(state, 0); + + done: + tor_free(transport_addrport); +} + /** Given a file name check to see whether the file exists but has not been * modified for a very long time. If so, remove it. */ void @@ -5293,7 +6655,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) { @@ -5302,9 +6664,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 78a67dddf5..e1fc5cfe9a 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); @@ -22,25 +23,25 @@ const char *escaped_safe_str_client(const char *address); const char *escaped_safe_str(const char *address); const char *get_version(void); -int config_get_lines(const char *string, config_line_t **result); +int config_get_lines(const char *string, config_line_t **result, int extended); 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; +int is_local_addr(const tor_addr_t *addr); 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, +setopt_err_t options_init_from_string(const char *cf_defaults, 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, +const char *get_torrc_fname(int defaults_fname); +char *options_get_datadir_fname2_suffix(const or_options_t *options, const char *sub1, const char *sub2, const char *suffix); #define get_datadir_fname2_suffix(sub1, sub2, suffix) \ @@ -57,23 +58,35 @@ char *options_get_datadir_fname2_suffix(or_options_t *options, #define get_datadir_fname_suffix(sub1, suffix) \ get_datadir_fname2_suffix((sub1), NULL, (suffix)) +int get_num_cpus(const or_options_t *options); + or_state_t *get_or_state(void); int did_last_state_file_write_fail(void); int or_state_save(time_t now); -int options_need_geoip_info(or_options_t *options, const char **reason_out); +const smartlist_t *get_configured_client_ports(void); + +int options_need_geoip_info(const or_options_t *options, + const char **reason_out); + +void save_transport_to_state(const char *transport_name, + const tor_addr_t *addr, uint16_t port); +const char *get_bindaddr_for_transport(const char *transport); + int getinfo_helper_config(control_connection_t *conn, const char *question, char **answer, const char **errmsg); const char *tor_get_digests(void); -uint32_t get_effective_bwrate(or_options_t *options); -uint32_t get_effective_bwburst(or_options_t *options); +uint32_t get_effective_bwrate(const or_options_t *options); +uint32_t get_effective_bwburst(const or_options_t *options); #ifdef CONFIG_PRIVATE /* Used only by config.c and test.c */ or_options_t *options_new(void); #endif +void config_register_addressmaps(const or_options_t *options); + #endif diff --git a/src/or/connection.c b/src/or/connection.c index 2049f4240c..b87f922175 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -36,17 +36,28 @@ #include "router.h" #include "routerparse.h" +#ifdef USE_BUFFEREVENTS +#include <event2/event.h> +#endif + +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif + static connection_t *connection_create_listener( const struct sockaddr *listensockaddr, socklen_t listensocklen, int type, - char* address); + const char *address, + const port_cfg_t *portcfg); static void connection_init(time_t now, connection_t *conn, int type, int socket_family); static int connection_init_accepted_conn(connection_t *conn, - uint8_t listener_type); + const listener_connection_t *listener); static int connection_handle_listener_read(connection_t *conn, int new_type); +#ifndef USE_BUFFEREVENTS static int connection_bucket_should_increase(int bucket, or_connection_t *conn); +#endif static int connection_finished_flushing(connection_t *conn); static int connection_flushed_some(connection_t *conn); static int connection_finished_connecting(connection_t *conn); @@ -60,6 +71,8 @@ static void set_constrained_socket_buffers(tor_socket_t sock, int size); static const char *connection_proxy_state_to_string(int state); static int connection_read_https_proxy_response(connection_t *conn); static void connection_send_socks5_connect(connection_t *conn); +static const char *proxy_type_to_string(int proxy_type); +static int get_proxy_type(void); /** The last IPv4 address that our network interface seemed to have been * binding to, in host order. We use this to detect when our IP changes. */ @@ -68,6 +81,15 @@ static uint32_t last_interface_ip = 0; * Used to detect IP address changes. */ static smartlist_t *outgoing_addrs = NULL; +#define CASE_ANY_LISTENER_TYPE \ + case CONN_TYPE_OR_LISTENER: \ + case CONN_TYPE_AP_LISTENER: \ + case CONN_TYPE_DIR_LISTENER: \ + case CONN_TYPE_CONTROL_LISTENER: \ + case CONN_TYPE_AP_TRANS_LISTENER: \ + case CONN_TYPE_AP_NATD_LISTENER: \ + case CONN_TYPE_AP_DNS_LISTENER + /**************************************************************/ /** @@ -108,13 +130,7 @@ conn_state_to_string(int type, int state) { static char buf[96]; switch (type) { - case CONN_TYPE_OR_LISTENER: - case CONN_TYPE_AP_LISTENER: - case CONN_TYPE_AP_TRANS_LISTENER: - case CONN_TYPE_AP_NATD_LISTENER: - case CONN_TYPE_AP_DNS_LISTENER: - case CONN_TYPE_DIR_LISTENER: - case CONN_TYPE_CONTROL_LISTENER: + CASE_ANY_LISTENER_TYPE: if (state == LISTENER_STATE_READY) return "ready"; break; @@ -124,10 +140,13 @@ conn_state_to_string(int type, int state) case OR_CONN_STATE_PROXY_HANDSHAKING: return "handshaking (proxy)"; case OR_CONN_STATE_TLS_HANDSHAKING: return "handshaking (TLS)"; case OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING: - return "renegotiating (TLS)"; + return "renegotiating (TLS, v2 handshake)"; case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING: - return "waiting for renegotiation (TLS)"; - case OR_CONN_STATE_OR_HANDSHAKING: return "handshaking (Tor)"; + return "waiting for renegotiation or V3 handshake"; + case OR_CONN_STATE_OR_HANDSHAKING_V2: + return "handshaking (Tor, v2 handshake)"; + case OR_CONN_STATE_OR_HANDSHAKING_V3: + return "handshaking (Tor, v3 handshake)"; case OR_CONN_STATE_OPEN: return "open"; } break; @@ -183,6 +202,26 @@ conn_state_to_string(int type, int state) return buf; } +#ifdef USE_BUFFEREVENTS +/** Return true iff the connection's type is one that can use a + bufferevent-based implementation. */ +int +connection_type_uses_bufferevent(connection_t *conn) +{ + switch (conn->type) { + case CONN_TYPE_AP: + case CONN_TYPE_EXIT: + case CONN_TYPE_DIR: + case CONN_TYPE_CONTROL: + case CONN_TYPE_OR: + case CONN_TYPE_CPUWORKER: + return 1; + default: + return 0; + } +} +#endif + /** Allocate and return a new dir_connection_t, initialized as by * connection_init(). */ dir_connection_t * @@ -211,16 +250,26 @@ or_connection_new(int socket_family) return or_conn; } +/** Allocate and return a new entry_connection_t, initialized as by + * connection_init(). */ +entry_connection_t * +entry_connection_new(int type, int socket_family) +{ + entry_connection_t *entry_conn = tor_malloc_zero(sizeof(entry_connection_t)); + tor_assert(type == CONN_TYPE_AP); + connection_init(time(NULL), ENTRY_TO_CONN(entry_conn), type, socket_family); + entry_conn->socks_request = socks_request_new(); + return entry_conn; +} + /** Allocate and return a new edge_connection_t, initialized as by * connection_init(). */ edge_connection_t * edge_connection_new(int type, int socket_family) { edge_connection_t *edge_conn = tor_malloc_zero(sizeof(edge_connection_t)); - tor_assert(type == CONN_TYPE_EXIT || type == CONN_TYPE_AP); + tor_assert(type == CONN_TYPE_EXIT); connection_init(time(NULL), TO_CONN(edge_conn), type, socket_family); - if (type == CONN_TYPE_AP) - edge_conn->socks_request = tor_malloc_zero(sizeof(socks_request_t)); return edge_conn; } @@ -237,6 +286,17 @@ control_connection_new(int socket_family) return control_conn; } +/** Allocate and return a new listener_connection_t, initialized as by + * connection_init(). */ +listener_connection_t * +listener_connection_new(int type, int socket_family) +{ + listener_connection_t *listener_conn = + tor_malloc_zero(sizeof(listener_connection_t)); + connection_init(time(NULL), TO_CONN(listener_conn), type, socket_family); + return listener_conn; +} + /** Allocate, initialize, and return a new connection_t subtype of <b>type</b> * to make or receive connections of address family <b>socket_family</b>. The * type should be one of the CONN_TYPE_* constants. */ @@ -248,15 +308,20 @@ connection_new(int type, int socket_family) return TO_CONN(or_connection_new(socket_family)); case CONN_TYPE_EXIT: - case CONN_TYPE_AP: return TO_CONN(edge_connection_new(type, socket_family)); + case CONN_TYPE_AP: + return ENTRY_TO_CONN(entry_connection_new(type, socket_family)); + case CONN_TYPE_DIR: return TO_CONN(dir_connection_new(socket_family)); case CONN_TYPE_CONTROL: return TO_CONN(control_connection_new(socket_family)); + CASE_ANY_LISTENER_TYPE: + return TO_CONN(listener_connection_new(type, socket_family)); + default: { connection_t *conn = tor_malloc_zero(sizeof(connection_t)); connection_init(time(NULL), conn, type, socket_family); @@ -288,15 +353,20 @@ connection_init(time_t now, connection_t *conn, int type, int socket_family) conn->magic = OR_CONNECTION_MAGIC; break; case CONN_TYPE_EXIT: - case CONN_TYPE_AP: conn->magic = EDGE_CONNECTION_MAGIC; break; + case CONN_TYPE_AP: + conn->magic = ENTRY_CONNECTION_MAGIC; + break; case CONN_TYPE_DIR: conn->magic = DIR_CONNECTION_MAGIC; break; case CONN_TYPE_CONTROL: conn->magic = CONTROL_CONNECTION_MAGIC; break; + CASE_ANY_LISTENER_TYPE: + conn->magic = LISTENER_CONNECTION_MAGIC; + break; default: conn->magic = BASE_CONNECTION_MAGIC; break; @@ -308,10 +378,13 @@ connection_init(time_t now, connection_t *conn, int type, int socket_family) conn->type = type; conn->socket_family = socket_family; - if (!connection_is_listener(conn)) { /* listeners never use their buf */ +#ifndef USE_BUFFEREVENTS + if (!connection_is_listener(conn)) { + /* listeners never use their buf */ conn->inbuf = buf_new(); conn->outbuf = buf_new(); } +#endif conn->timestamp_created = now; conn->timestamp_lastread = now; @@ -350,6 +423,10 @@ _connection_free(connection_t *conn) memlen = sizeof(or_connection_t); break; case CONN_TYPE_AP: + tor_assert(conn->magic == ENTRY_CONNECTION_MAGIC); + mem = TO_ENTRY_CONN(conn); + memlen = sizeof(entry_connection_t); + break; case CONN_TYPE_EXIT: tor_assert(conn->magic == EDGE_CONNECTION_MAGIC); mem = TO_EDGE_CONN(conn); @@ -365,6 +442,11 @@ _connection_free(connection_t *conn) mem = TO_CONTROL_CONN(conn); memlen = sizeof(control_connection_t); break; + CASE_ANY_LISTENER_TYPE: + tor_assert(conn->magic == LISTENER_CONNECTION_MAGIC); + mem = TO_LISTENER_CONN(conn); + memlen = sizeof(listener_connection_t); + break; default: tor_assert(conn->magic == BASE_CONNECTION_MAGIC); mem = conn; @@ -377,7 +459,8 @@ _connection_free(connection_t *conn) "bytes on inbuf, %d on outbuf.", conn_type_to_string(conn->type), conn_state_to_string(conn->type, conn->state), - (int)buf_datalen(conn->inbuf), (int)buf_datalen(conn->outbuf)); + (int)connection_get_inbuf_len(conn), + (int)connection_get_outbuf_len(conn)); } if (!connection_is_listener(conn)) { @@ -407,15 +490,21 @@ _connection_free(connection_t *conn) smartlist_free(or_conn->active_circuit_pqueue); tor_free(or_conn->nickname); } - if (CONN_IS_EDGE(conn)) { - edge_connection_t *edge_conn = TO_EDGE_CONN(conn); - tor_free(edge_conn->chosen_exit_name); - if (edge_conn->socks_request) { - memset(edge_conn->socks_request, 0xcc, sizeof(socks_request_t)); - tor_free(edge_conn->socks_request); + if (conn->type == CONN_TYPE_AP) { + entry_connection_t *entry_conn = TO_ENTRY_CONN(conn); + tor_free(entry_conn->chosen_exit_name); + tor_free(entry_conn->original_dest_address); + if (entry_conn->socks_request) + socks_request_free(entry_conn->socks_request); + if (entry_conn->pending_optimistic_data) { + generic_buffer_free(entry_conn->pending_optimistic_data); + } + if (entry_conn->sending_optimistic_data) { + generic_buffer_free(entry_conn->sending_optimistic_data); } - - rend_data_free(edge_conn->rend_data); + } + if (CONN_IS_EDGE(conn)) { + rend_data_free(TO_EDGE_CONN(conn)->rend_data); } if (conn->type == CONN_TYPE_CONTROL) { control_connection_t *control_conn = TO_CONTROL_CONN(conn); @@ -424,6 +513,15 @@ _connection_free(connection_t *conn) tor_free(conn->read_event); /* Probably already freed by connection_free. */ tor_free(conn->write_event); /* Probably already freed by connection_free. */ + IF_HAS_BUFFEREVENT(conn, { + /* This was a workaround to handle bugs in some old versions of libevent + * where callbacks can occur after calling bufferevent_free(). Setting + * the callbacks to NULL prevented this. It shouldn't be necessary any + * more, but let's not tempt fate for now. */ + bufferevent_setcb(conn->bufev, NULL, NULL, NULL, NULL); + bufferevent_free(conn->bufev); + conn->bufev = NULL; + }); if (conn->type == CONN_TYPE_DIR) { dir_connection_t *dir_conn = TO_DIR_CONN(conn); @@ -450,6 +548,12 @@ _connection_free(connection_t *conn) log_warn(LD_BUG, "called on OR conn with non-zeroed identity_digest"); connection_or_remove_from_identity_map(TO_OR_CONN(conn)); } +#ifdef USE_BUFFEREVENTS + if (conn->type == CONN_TYPE_OR && TO_OR_CONN(conn)->bucket_cfg) { + ev_token_bucket_cfg_free(TO_OR_CONN(conn)->bucket_cfg); + TO_OR_CONN(conn)->bucket_cfg = NULL; + } +#endif memset(mem, 0xCC, memlen); /* poison memory */ tor_free(mem); @@ -485,39 +589,9 @@ connection_free(connection_t *conn) _connection_free(conn); } -/** Call _connection_free() on every connection in our array, and release all - * storage held by connection.c. This is used by cpuworkers and dnsworkers - * when they fork, so they don't keep resources held open (especially - * sockets). - * - * Don't do the checks in connection_free(), because they will - * fail. - */ -void -connection_free_all(void) -{ - smartlist_t *conns = get_connection_array(); - - /* We don't want to log any messages to controllers. */ - SMARTLIST_FOREACH(conns, connection_t *, conn, - if (conn->type == CONN_TYPE_CONTROL) - TO_CONTROL_CONN(conn)->event_mask = 0); - - control_update_global_event_mask(); - - /* Unlink everything from the identity map. */ - connection_or_clear_identity_map(); - - SMARTLIST_FOREACH(conns, connection_t *, conn, _connection_free(conn)); - - if (outgoing_addrs) { - SMARTLIST_FOREACH(outgoing_addrs, void*, addr, tor_free(addr)); - smartlist_free(outgoing_addrs); - outgoing_addrs = NULL; - } -} - -/** Do any cleanup needed: +/** + * Called when we're about to finally unlink and free a connection: + * perform necessary accounting and cleanup * - Directory conns that failed to fetch a rendezvous descriptor * need to inform pending rendezvous streams. * - OR conns need to call rep_hist_note_*() to record status. @@ -530,114 +604,20 @@ connection_free_all(void) void connection_about_to_close_connection(connection_t *conn) { - circuit_t *circ; - dir_connection_t *dir_conn; - or_connection_t *or_conn; - edge_connection_t *edge_conn; - time_t now = time(NULL); - tor_assert(conn->marked_for_close); - if (CONN_IS_EDGE(conn)) { - edge_conn = TO_EDGE_CONN(conn); - if (!edge_conn->edge_has_sent_end) { - log_warn(LD_BUG, "(Harmless.) Edge connection (marked at %s:%d) " - "hasn't sent end yet?", - conn->marked_for_close_file, conn->marked_for_close); - tor_fragile_assert(); - } - } - switch (conn->type) { case CONN_TYPE_DIR: - dir_conn = TO_DIR_CONN(conn); - if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) { - /* It's a directory connection and connecting or fetching - * failed: forget about this router, and maybe try again. */ - connection_dir_request_failed(dir_conn); - } - /* If we were trying to fetch a v2 rend desc and did not succeed, - * retry as needed. (If a fetch is successful, the connection state - * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC to mark that - * refetching is unnecessary.) */ - if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 && - dir_conn->rend_data && - strlen(dir_conn->rend_data->onion_address) == - REND_SERVICE_ID_LEN_BASE32) - rend_client_refetch_v2_renddesc(dir_conn->rend_data); + connection_dir_about_to_close(TO_DIR_CONN(conn)); break; case CONN_TYPE_OR: - or_conn = TO_OR_CONN(conn); - /* Remember why we're closing this connection. */ - if (conn->state != OR_CONN_STATE_OPEN) { - /* Inform any pending (not attached) circs that they should - * give up. */ - circuit_n_conn_done(TO_OR_CONN(conn), 0); - /* now mark things down as needed */ - if (connection_or_nonopen_was_started_here(or_conn)) { - or_options_t *options = get_options(); - rep_hist_note_connect_failed(or_conn->identity_digest, now); - entry_guard_register_connect_status(or_conn->identity_digest,0, - !options->HTTPSProxy, now); - if (conn->state >= OR_CONN_STATE_TLS_HANDSHAKING) { - int reason = tls_error_to_orconn_end_reason(or_conn->tls_error); - control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED, - reason); - if (!authdir_mode_tests_reachability(options)) - control_event_bootstrap_problem( - orconn_end_reason_to_control_string(reason), reason); - } - } - } else if (conn->hold_open_until_flushed) { - /* We only set hold_open_until_flushed when we're intentionally - * closing a connection. */ - rep_hist_note_disconnect(or_conn->identity_digest, now); - control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED, - tls_error_to_orconn_end_reason(or_conn->tls_error)); - } else if (!tor_digest_is_zero(or_conn->identity_digest)) { - rep_hist_note_connection_died(or_conn->identity_digest, now); - control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED, - tls_error_to_orconn_end_reason(or_conn->tls_error)); - } - /* Now close all the attached circuits on it. */ - circuit_unlink_all_from_or_conn(TO_OR_CONN(conn), - END_CIRC_REASON_OR_CONN_CLOSED); + connection_or_about_to_close(TO_OR_CONN(conn)); break; case CONN_TYPE_AP: - edge_conn = TO_EDGE_CONN(conn); - if (edge_conn->socks_request->has_finished == 0) { - /* since conn gets removed right after this function finishes, - * there's no point trying to send back a reply at this point. */ - log_warn(LD_BUG,"Closing stream (marked at %s:%d) without sending" - " back a socks reply.", - conn->marked_for_close_file, conn->marked_for_close); - } - if (!edge_conn->end_reason) { - log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having" - " set end_reason.", - conn->marked_for_close_file, conn->marked_for_close); - } - if (edge_conn->dns_server_request) { - log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having" - " replied to DNS request.", - conn->marked_for_close_file, conn->marked_for_close); - dnsserv_reject_request(edge_conn); - } - control_event_stream_bandwidth(edge_conn); - control_event_stream_status(edge_conn, STREAM_EVENT_CLOSED, - edge_conn->end_reason); - circ = circuit_get_by_edge_conn(edge_conn); - if (circ) - circuit_detach_stream(circ, edge_conn); + connection_ap_about_to_close(TO_ENTRY_CONN(conn)); break; case CONN_TYPE_EXIT: - edge_conn = TO_EDGE_CONN(conn); - circ = circuit_get_by_edge_conn(edge_conn); - if (circ) - circuit_detach_stream(circ, edge_conn); - if (conn->state == EXIT_CONN_STATE_RESOLVING) { - connection_dns_remove(edge_conn); - } + connection_exit_about_to_close(TO_EDGE_CONN(conn)); break; } } @@ -674,10 +654,9 @@ connection_close_immediate(connection_t *conn) conn->s = -1; if (conn->linked) conn->linked_conn_is_closed = 1; - if (!connection_is_listener(conn)) { + if (conn->outbuf) buf_clear(conn->outbuf); - conn->outbuf_flushlen = 0; - } + conn->outbuf_flushlen = 0; } /** Mark <b>conn</b> to be closed next time we loop through @@ -747,48 +726,6 @@ connection_expire_held_open(void) }); } -/** Create an AF_INET listenaddr struct. - * <b>listenaddress</b> provides the host and optionally the port information - * for the new structure. If no port is provided in <b>listenaddress</b> then - * <b>listenport</b> is used. - * - * If not NULL <b>readable_address</b> will contain a copy of the host part of - * <b>listenaddress</b>. - * - * The listenaddr struct has to be freed by the caller. - */ -static struct sockaddr_in * -create_inet_sockaddr(const char *listenaddress, int listenport, - char **readable_address, socklen_t *socklen_out) { - struct sockaddr_in *listenaddr = NULL; - uint32_t addr; - uint16_t usePort = 0; - - if (parse_addr_port(LOG_WARN, - listenaddress, readable_address, &addr, &usePort)<0) { - log_warn(LD_CONFIG, - "Error parsing/resolving ListenAddress %s", listenaddress); - goto err; - } - if (usePort==0) { - if (listenport != CFG_AUTO_PORT) - usePort = listenport; - } - - listenaddr = tor_malloc_zero(sizeof(struct sockaddr_in)); - listenaddr->sin_addr.s_addr = htonl(addr); - listenaddr->sin_family = AF_INET; - listenaddr->sin_port = htons((uint16_t) usePort); - - *socklen_out = sizeof(struct sockaddr_in); - - return listenaddr; - - err: - tor_free(listenaddr); - return NULL; -} - #ifdef HAVE_SYS_UN_H /** Create an AF_UNIX listenaddr struct. * <b>listenaddress</b> provides the path to the Unix socket. @@ -862,7 +799,7 @@ warn_too_many_conns(void) /** Check whether we should be willing to open an AF_UNIX socket in * <b>path</b>. Return 0 if we should go ahead and -1 if we shouldn't. */ static int -check_location_for_unix_socket(or_options_t *options, const char *path) +check_location_for_unix_socket(const or_options_t *options, const char *path) { int r = -1; char *p = tor_strdup(path); @@ -923,12 +860,20 @@ make_socket_reuseable(tor_socket_t sock) static connection_t * connection_create_listener(const struct sockaddr *listensockaddr, socklen_t socklen, - int type, char* address) + int type, const char *address, + const port_cfg_t *port_cfg) { + listener_connection_t *lis_conn; connection_t *conn; tor_socket_t s; /* the socket we're going to make */ + or_options_t const *options = get_options(); +#if defined(HAVE_PWD_H) && defined(HAVE_SYS_UN_H) + struct passwd *pw = NULL; +#endif uint16_t usePort = 0, gotPort = 0; int start_reading = 0; + static int global_next_session_group = SESSION_GROUP_FIRST_AUTO; + tor_addr_t addr; if (get_n_open_sockets() >= get_options()->_ConnLimit-1) { warn_too_many_conns(); @@ -936,7 +881,6 @@ connection_create_listener(const struct sockaddr *listensockaddr, } if (listensockaddr->sa_family == AF_INET) { - tor_addr_t addr; int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER); if (is_tcp) start_reading = 1; @@ -950,7 +894,8 @@ connection_create_listener(const struct sockaddr *listensockaddr, is_tcp ? SOCK_STREAM : SOCK_DGRAM, is_tcp ? IPPROTO_TCP: IPPROTO_UDP); if (!SOCKET_OK(s)) { - log_warn(LD_NET,"Socket creation failed."); + log_warn(LD_NET,"Socket creation failed: %s", + tor_socket_strerror(tor_socket_errno(-1))); goto err; } @@ -998,12 +943,14 @@ connection_create_listener(const struct sockaddr *listensockaddr, * and listeners at the same time */ tor_assert(type == CONN_TYPE_CONTROL_LISTENER); - if (check_location_for_unix_socket(get_options(), address) < 0) + if (check_location_for_unix_socket(options, address) < 0) goto err; log_notice(LD_NET, "Opening %s on %s", conn_type_to_string(type), address); + tor_addr_make_unspec(&addr); + if (unlink(address) < 0 && errno != ENOENT) { log_warn(LD_NET, "Could not unlink %s: %s", address, strerror(errno)); @@ -1020,7 +967,20 @@ connection_create_listener(const struct sockaddr *listensockaddr, tor_socket_strerror(tor_socket_errno(s))); goto err; } - if (get_options()->ControlSocketsGroupWritable) { +#ifdef HAVE_PWD_H + if (options->User) { + pw = getpwnam(options->User); + if (pw == NULL) { + log_warn(LD_NET,"Unable to chown() %s socket: user %s not found.", + address, options->User); + } else if (chown(address, pw->pw_uid, pw->pw_gid) < 0) { + log_warn(LD_NET,"Unable to chown() %s socket: %s.", + address, strerror(errno)); + goto err; + } + } +#endif + if (options->ControlSocketsGroupWritable) { /* We need to use chmod; fchmod doesn't work on sockets on all * platforms. */ if (chmod(address, 0660) < 0) { @@ -1036,6 +996,8 @@ connection_create_listener(const struct sockaddr *listensockaddr, tor_close_socket(s); goto err; } +#else + (void)options; #endif /* HAVE_SYS_UN_H */ } else { log_err(LD_BUG,"Got unexpected address family %d.", @@ -1045,11 +1007,23 @@ connection_create_listener(const struct sockaddr *listensockaddr, set_socket_nonblocking(s); - conn = connection_new(type, listensockaddr->sa_family); + lis_conn = listener_connection_new(type, listensockaddr->sa_family); + conn = TO_CONN(lis_conn); conn->socket_family = listensockaddr->sa_family; conn->s = s; conn->address = tor_strdup(address); conn->port = gotPort; + tor_addr_copy(&conn->addr, &addr); + + if (port_cfg->isolation_flags) { + lis_conn->isolation_flags = port_cfg->isolation_flags; + if (port_cfg->session_group >= 0) { + lis_conn->session_group = port_cfg->session_group; + } else { + /* XXXX023 This can wrap after ~INT_MAX ports are opened. */ + lis_conn->session_group = global_next_session_group--; + } + } if (connection_add(conn) < 0) { /* no space, forget it */ log_warn(LD_NET,"connection_add for listener failed. Giving up."); @@ -1146,7 +1120,7 @@ connection_handle_listener_read(connection_t *conn, int new_type) struct sockaddr *remote = (struct sockaddr*)addrbuf; /* length of the remote address. Must be whatever accept() needs. */ socklen_t remotelen = (socklen_t)sizeof(addrbuf); - or_options_t *options = get_options(); + const or_options_t *options = get_options(); tor_assert((size_t)remotelen >= sizeof(struct sockaddr_in)); memset(addrbuf, 0, sizeof(addrbuf)); @@ -1260,7 +1234,7 @@ connection_handle_listener_read(connection_t *conn, int new_type) return 0; /* no need to tear down the parent */ } - if (connection_init_accepted_conn(newconn, conn->type) < 0) { + if (connection_init_accepted_conn(newconn, TO_LISTENER_CONN(conn)) < 0) { if (! newconn->marked_for_close) connection_mark_for_close(newconn); return 0; @@ -1274,7 +1248,8 @@ connection_handle_listener_read(connection_t *conn, int new_type) * and place it in circuit_wait. */ static int -connection_init_accepted_conn(connection_t *conn, uint8_t listener_type) +connection_init_accepted_conn(connection_t *conn, + const listener_connection_t *listener) { connection_start_reading(conn); @@ -1283,16 +1258,20 @@ connection_init_accepted_conn(connection_t *conn, uint8_t listener_type) control_event_or_conn_status(TO_OR_CONN(conn), OR_CONN_EVENT_NEW, 0); return connection_tls_start_handshake(TO_OR_CONN(conn), 1); case CONN_TYPE_AP: - switch (listener_type) { + TO_ENTRY_CONN(conn)->isolation_flags = listener->isolation_flags; + TO_ENTRY_CONN(conn)->session_group = listener->session_group; + TO_ENTRY_CONN(conn)->nym_epoch = get_signewnym_epoch(); + TO_ENTRY_CONN(conn)->socks_request->listener_type = listener->_base.type; + switch (TO_CONN(listener)->type) { case CONN_TYPE_AP_LISTENER: conn->state = AP_CONN_STATE_SOCKS_WAIT; break; case CONN_TYPE_AP_TRANS_LISTENER: - TO_EDGE_CONN(conn)->is_transparent_ap = 1; + TO_ENTRY_CONN(conn)->is_transparent_ap = 1; conn->state = AP_CONN_STATE_CIRCUIT_WAIT; - return connection_ap_process_transparent(TO_EDGE_CONN(conn)); + return connection_ap_process_transparent(TO_ENTRY_CONN(conn)); case CONN_TYPE_AP_NATD_LISTENER: - TO_EDGE_CONN(conn)->is_transparent_ap = 1; + TO_ENTRY_CONN(conn)->is_transparent_ap = 1; conn->state = AP_CONN_STATE_NATD_WAIT; break; } @@ -1325,8 +1304,8 @@ connection_connect(connection_t *conn, const char *address, int inprogress = 0; char addrbuf[256]; struct sockaddr *dest_addr; - socklen_t dest_addr_len; - or_options_t *options = get_options(); + int dest_addr_len; + const or_options_t *options = get_options(); int protocol_family; if (get_n_open_sockets() >= get_options()->_ConnLimit-1) { @@ -1339,6 +1318,24 @@ connection_connect(connection_t *conn, const char *address, else protocol_family = PF_INET; + if (get_options()->DisableNetwork) { + /* We should never even try to connect anyplace if DisableNetwork is set. + * Warn if we do, and refuse to make the connection. */ + static ratelim_t disablenet_violated = RATELIM_INIT(30*60); + char *m; +#ifdef MS_WINDOWS + *socket_error = WSAENETUNREACH; +#else + *socket_error = ENETUNREACH; +#endif + if ((m = rate_limit_log(&disablenet_violated, approx_time()))) { + log_warn(LD_BUG, "Tried to open a socket with DisableNetwork set.%s", m); + tor_free(m); + } + tor_fragile_assert(); + return -1; + } + s = tor_open_socket(protocol_family,SOCK_STREAM,IPPROTO_TCP); if (s < 0) { *socket_error = tor_socket_errno(-1); @@ -1383,7 +1380,7 @@ connection_connect(connection_t *conn, const char *address, make_socket_reuseable(s); - if (connect(s, dest_addr, dest_addr_len) < 0) { + if (connect(s, dest_addr, (socklen_t)dest_addr_len) < 0) { int e = tor_socket_errno(s); if (!ERRNO_IS_CONN_EINPROGRESS(e)) { /* yuck. kill it. */ @@ -1408,7 +1405,7 @@ connection_connect(connection_t *conn, const char *address, escaped_safe_str_client(address), port, inprogress?"in progress":"established", s); conn->s = s; - if (connection_add(conn) < 0) /* no space, forget it */ + if (connection_add_connecting(conn) < 0) /* no space, forget it */ return -1; return inprogress ? 0 : 1; } @@ -1421,6 +1418,7 @@ connection_proxy_state_to_string(int state) static const char *unknown = "???"; static const char *states[] = { "PROXY_NONE", + "PROXY_INFANT", "PROXY_HTTPS_WANT_CONNECT_OK", "PROXY_SOCKS4_WANT_CONNECT_OK", "PROXY_SOCKS5_WANT_AUTH_METHOD_NONE", @@ -1449,7 +1447,7 @@ connection_proxy_state_to_string(int state) int connection_proxy_connect(connection_t *conn, int type) { - or_options_t *options; + const or_options_t *options; tor_assert(conn); @@ -1641,6 +1639,19 @@ connection_send_socks5_connect(connection_t *conn) conn->proxy_state = PROXY_SOCKS5_WANT_CONNECT_OK; } +/** DOCDOC */ +static int +connection_fetch_from_buf_socks_client(connection_t *conn, + int state, char **reason) +{ + IF_HAS_BUFFEREVENT(conn, { + struct evbuffer *input = bufferevent_get_input(conn->bufev); + return fetch_from_evbuffer_socks_client(input, state, reason); + }) ELSE_IF_NO_BUFFEREVENT { + return fetch_from_buf_socks_client(conn->inbuf, state, reason); + } +} + /** Call this from connection_*_process_inbuf() to advance the proxy * handshake. * @@ -1668,17 +1679,17 @@ connection_read_proxy_handshake(connection_t *conn) break; case PROXY_SOCKS4_WANT_CONNECT_OK: - ret = fetch_from_buf_socks_client(conn->inbuf, - conn->proxy_state, - &reason); + ret = connection_fetch_from_buf_socks_client(conn, + conn->proxy_state, + &reason); if (ret == 1) conn->proxy_state = PROXY_CONNECTED; break; case PROXY_SOCKS5_WANT_AUTH_METHOD_NONE: - ret = fetch_from_buf_socks_client(conn->inbuf, - conn->proxy_state, - &reason); + ret = connection_fetch_from_buf_socks_client(conn, + conn->proxy_state, + &reason); /* no auth needed, do connect */ if (ret == 1) { connection_send_socks5_connect(conn); @@ -1687,9 +1698,9 @@ connection_read_proxy_handshake(connection_t *conn) break; case PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929: - ret = fetch_from_buf_socks_client(conn->inbuf, - conn->proxy_state, - &reason); + ret = connection_fetch_from_buf_socks_client(conn, + conn->proxy_state, + &reason); /* send auth if needed, otherwise do connect */ if (ret == 1) { @@ -1724,9 +1735,9 @@ connection_read_proxy_handshake(connection_t *conn) break; case PROXY_SOCKS5_WANT_AUTH_RFC1929_OK: - ret = fetch_from_buf_socks_client(conn->inbuf, - conn->proxy_state, - &reason); + ret = connection_fetch_from_buf_socks_client(conn, + conn->proxy_state, + &reason); /* send the connect request */ if (ret == 1) { connection_send_socks5_connect(conn); @@ -1735,9 +1746,9 @@ connection_read_proxy_handshake(connection_t *conn) break; case PROXY_SOCKS5_WANT_CONNECT_OK: - ret = fetch_from_buf_socks_client(conn->inbuf, - conn->proxy_state, - &reason); + ret = connection_fetch_from_buf_socks_client(conn, + conn->proxy_state, + &reason); if (ret == 1) conn->proxy_state = PROXY_CONNECTED; break; @@ -1770,6 +1781,113 @@ connection_read_proxy_handshake(connection_t *conn) return ret; } +/** Given a list of listener connections in <b>old_conns</b>, and list of + * port_cfg_t entries in <b>ports</b>, open a new listener for every port in + * <b>ports</b> that does not already have a listener in <b>old_conns</b>. + * + * Remove from <b>old_conns</b> every connection that has a corresponding + * entry in <b>ports</b>. Add to <b>new_conns</b> new every connection we + * launch. + * + * Return 0 on success, -1 on failure. + **/ +static int +retry_listener_ports(smartlist_t *old_conns, + const smartlist_t *ports, + smartlist_t *new_conns) +{ + smartlist_t *launch = smartlist_create(); + int r = 0; + + smartlist_add_all(launch, ports); + + /* Iterate through old_conns, comparing it to launch: remove from both lists + * each pair of elements that corresponds to the same port. */ + SMARTLIST_FOREACH_BEGIN(old_conns, connection_t *, conn) { + const port_cfg_t *found_port = NULL; + + /* Okay, so this is a listener. Is it configured? */ + SMARTLIST_FOREACH_BEGIN(launch, const port_cfg_t *, wanted) { + if (conn->type != wanted->type) + continue; + if ((conn->socket_family != AF_UNIX && wanted->is_unix_addr) || + (conn->socket_family == AF_UNIX && ! wanted->is_unix_addr)) + continue; + + if (wanted->is_unix_addr) { + if (conn->socket_family == AF_UNIX && + !strcmp(wanted->unix_addr, conn->address)) { + found_port = wanted; + break; + } + } else { + int port_matches; + if (wanted->port == CFG_AUTO_PORT) { + port_matches = 1; + } else { + port_matches = (wanted->port == conn->port); + } + if (port_matches && tor_addr_eq(&wanted->addr, &conn->addr)) { + found_port = wanted; + break; + } + } + } SMARTLIST_FOREACH_END(wanted); + + if (found_port) { + /* This listener is already running; we don't need to launch it. */ + //log_debug(LD_NET, "Already have %s on %s:%d", + // conn_type_to_string(found_port->type), conn->address, conn->port); + smartlist_remove(launch, found_port); + /* And we can remove the connection from old_conns too. */ + SMARTLIST_DEL_CURRENT(old_conns, conn); + } + } SMARTLIST_FOREACH_END(conn); + + /* Now open all the listeners that are configured but not opened. */ + SMARTLIST_FOREACH_BEGIN(launch, const port_cfg_t *, port) { + struct sockaddr *listensockaddr; + socklen_t listensocklen = 0; + char *address=NULL; + connection_t *conn; + int real_port = port->port == CFG_AUTO_PORT ? 0 : port->port; + tor_assert(real_port <= UINT16_MAX); + + if (port->is_unix_addr) { + listensockaddr = (struct sockaddr *) + create_unix_sockaddr(port->unix_addr, + &address, &listensocklen); + } else { + listensockaddr = tor_malloc(sizeof(struct sockaddr_storage)); + listensocklen = tor_addr_to_sockaddr(&port->addr, + real_port, + listensockaddr, + sizeof(struct sockaddr_storage)); + address = tor_dup_addr(&port->addr); + } + + if (listensockaddr) { + conn = connection_create_listener(listensockaddr, listensocklen, + port->type, address, port); + tor_free(listensockaddr); + tor_free(address); + } else { + conn = NULL; + } + + if (!conn) { + r = -1; + } else { + if (new_conns) + smartlist_add(new_conns, conn); + } + } SMARTLIST_FOREACH_END(port); + + smartlist_free(launch); + + return r; +} + /** * Launch any configured listener connections of type <b>type</b>. (A * listener is configured if <b>port_option</b> is non-zero. If any @@ -1777,168 +1895,73 @@ connection_read_proxy_handshake(connection_t *conn) * connection binding to each one. Otherwise, create a single * connection binding to the address <b>default_addr</b>.) * - * Only launch the listeners of this type that are not already open, and - * only close listeners that are no longer wanted. Existing listeners - * that are still configured are not touched. - * - * If <b>disable_all_conns</b> is set, then never open new conns, and - * close the existing ones. + * We assume that we're starting with a list of existing listener connection_t + * pointers in <b>old_conns</b>: we do not launch listeners that are already + * in that list. Instead, we just remove them from the list. * - * Add all old conns that should be closed to <b>replaced_conns</b>. - * Add all new connections to <b>new_conns</b>. + * All new connections we launch are added to <b>new_conns</b>. */ static int -retry_listeners(int type, config_line_t *cfg, +retry_listeners(smartlist_t *old_conns, + int type, const config_line_t *cfg, int port_option, const char *default_addr, - smartlist_t *replaced_conns, smartlist_t *new_conns, - int disable_all_conns, - int socket_family) + int is_sockaddr_un) { - smartlist_t *launch = smartlist_create(), *conns; - int free_launch_elts = 1; - int r; - config_line_t *c; - connection_t *conn; - config_line_t *line; - - tor_assert(socket_family == AF_INET || socket_family == AF_UNIX); + smartlist_t *ports = smartlist_create(); + tor_addr_t dflt_addr; + int retval = 0; - if (cfg && port_option) { - for (c = cfg; c; c = c->next) { - smartlist_add(launch, c); - } - free_launch_elts = 0; - } else if (port_option) { - line = tor_malloc_zero(sizeof(config_line_t)); - line->key = tor_strdup(""); - line->value = tor_strdup(default_addr); - smartlist_add(launch, line); + if (default_addr) { + tor_addr_parse(&dflt_addr, default_addr); + } else { + tor_addr_make_unspec(&dflt_addr); } - /* - SMARTLIST_FOREACH(launch, config_line_t *, l, - log_fn(LOG_NOTICE, "#%s#%s", l->key, l->value)); - */ - - conns = get_connection_array(); - SMARTLIST_FOREACH(conns, connection_t *, conn, - { - if (conn->type != type || - conn->socket_family != socket_family || - conn->marked_for_close) - continue; - /* Okay, so this is a listener. Is it configured? */ - line = NULL; - SMARTLIST_FOREACH(launch, config_line_t *, wanted, - { - char *address=NULL; - uint16_t port; - switch (socket_family) { - case AF_INET: - if (!parse_addr_port(LOG_WARN, - wanted->value, &address, NULL, &port)) { - int addr_matches = !strcasecmp(address, conn->address); - int port_matches; - tor_free(address); - if (port) { - /* The Listener line has a port */ - port_matches = (port == conn->port); - } else if (port_option == CFG_AUTO_PORT) { - /* The Listener line has no port, and the Port line is "auto". - * "auto" matches anything; transitions from any port to - * "auto" succeed. */ - port_matches = 1; - } else { - /* The Listener line has no port, and the Port line is "auto". - * "auto" matches anything; transitions from any port to - * "auto" succeed. */ - port_matches = (port_option == conn->port); - } - if (port_matches && addr_matches) { - line = wanted; - break; - } - } - break; - case AF_UNIX: - if (!strcasecmp(wanted->value, conn->address)) { - line = wanted; - break; - } - break; - default: - tor_assert(0); - } - }); - if (!line || disable_all_conns) { - /* This one isn't configured. Close it. */ - log_notice(LD_NET, "Closing no-longer-configured %s on %s:%d", - conn_type_to_string(type), conn->address, conn->port); - if (replaced_conns) { - smartlist_add(replaced_conns, conn); - } else { - connection_close_immediate(conn); - connection_mark_for_close(conn); - } + if (port_option) { + if (!cfg) { + port_cfg_t *port = tor_malloc_zero(sizeof(port_cfg_t)); + tor_addr_copy(&port->addr, &dflt_addr); + port->port = port_option; + port->type = type; + smartlist_add(ports, port); } else { - /* It's configured; we don't need to launch it. */ -// log_debug(LD_NET, "Already have %s on %s:%d", -// conn_type_to_string(type), conn->address, conn->port); - smartlist_remove(launch, line); - if (free_launch_elts) - config_free_lines(line); - } - }); - - /* Now open all the listeners that are configured but not opened. */ - r = 0; - if (!disable_all_conns) { - SMARTLIST_FOREACH_BEGIN(launch, config_line_t *, cfg_line) { - char *address = NULL; - struct sockaddr *listensockaddr; - socklen_t listensocklen = 0; - - switch (socket_family) { - case AF_INET: - listensockaddr = (struct sockaddr *) - create_inet_sockaddr(cfg_line->value, - port_option, - &address, &listensocklen); - break; - case AF_UNIX: - listensockaddr = (struct sockaddr *) - create_unix_sockaddr(cfg_line->value, - &address, &listensocklen); - break; - default: - tor_assert(0); - } - - if (listensockaddr) { - conn = connection_create_listener(listensockaddr, listensocklen, - type, address); - tor_free(listensockaddr); - tor_free(address); - } else - conn = NULL; - - if (!conn) { - r = -1; + const config_line_t *c; + for (c = cfg; c; c = c->next) { + port_cfg_t *port; + tor_addr_t addr; + uint16_t portval = 0; + if (is_sockaddr_un) { + size_t len = strlen(c->value); + port = tor_malloc_zero(sizeof(port_cfg_t) + len + 1); + port->is_unix_addr = 1; + memcpy(port->unix_addr, c->value, len+1); } else { - if (new_conns) - smartlist_add(new_conns, conn); + if (tor_addr_port_lookup(c->value, &addr, &portval) < 0) { + log_warn(LD_CONFIG, "Can't parse/resolve %s %s", + c->key, c->value); + retval = -1; + continue; + } + port = tor_malloc_zero(sizeof(port_cfg_t)); + tor_addr_copy(&port->addr, &addr); } - } SMARTLIST_FOREACH_END(cfg_line); + port->type = type; + port->port = portval ? portval : port_option; + smartlist_add(ports, port); + } + } } - if (free_launch_elts) { - SMARTLIST_FOREACH(launch, config_line_t *, cfg_line, - config_free_lines(cfg_line)); - } - smartlist_free(launch); + if (retval == -1) + goto cleanup; - return r; + retval = retry_listener_ports(old_conns, ports, new_conns); + + cleanup: + SMARTLIST_FOREACH(ports, port_cfg_t *, p, tor_free(p)); + smartlist_free(ports); + return retval; } /** Launch listeners for each port you should have open. Only launch @@ -1952,53 +1975,64 @@ int retry_all_listeners(smartlist_t *replaced_conns, smartlist_t *new_conns) { - or_options_t *options = get_options(); + smartlist_t *listeners = smartlist_create(); + const or_options_t *options = get_options(); int retval = 0; const uint16_t old_or_port = router_get_advertised_or_port(options); const uint16_t old_dir_port = router_get_advertised_dir_port(options, 0); - if (retry_listeners(CONN_TYPE_OR_LISTENER, options->ORListenAddress, - options->ORPort, "0.0.0.0", - replaced_conns, new_conns, options->ClientOnly, - AF_INET)<0) - retval = -1; - if (retry_listeners(CONN_TYPE_DIR_LISTENER, options->DirListenAddress, - options->DirPort, "0.0.0.0", - replaced_conns, new_conns, options->ClientOnly, - AF_INET)<0) - retval = -1; - if (retry_listeners(CONN_TYPE_AP_LISTENER, options->SocksListenAddress, - options->SocksPort, "127.0.0.1", - replaced_conns, new_conns, 0, - AF_INET)<0) - retval = -1; - if (retry_listeners(CONN_TYPE_AP_TRANS_LISTENER, options->TransListenAddress, - options->TransPort, "127.0.0.1", - replaced_conns, new_conns, 0, - AF_INET)<0) - retval = -1; - if (retry_listeners(CONN_TYPE_AP_NATD_LISTENER, options->NATDListenAddress, - options->NATDPort, "127.0.0.1", - replaced_conns, new_conns, 0, - AF_INET)<0) - retval = -1; - if (retry_listeners(CONN_TYPE_AP_DNS_LISTENER, options->DNSListenAddress, - options->DNSPort, "127.0.0.1", - replaced_conns, new_conns, 0, - AF_INET)<0) - retval = -1; - if (retry_listeners(CONN_TYPE_CONTROL_LISTENER, + SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) { + if (connection_is_listener(conn) && !conn->marked_for_close) + smartlist_add(listeners, conn); + } SMARTLIST_FOREACH_END(conn); + + if (! options->ClientOnly && ! options->DisableNetwork) { + if (retry_listeners(listeners, + CONN_TYPE_OR_LISTENER, options->ORListenAddress, + options->ORPort, "0.0.0.0", + new_conns, 0) < 0) + retval = -1; + if (retry_listeners(listeners, + CONN_TYPE_DIR_LISTENER, options->DirListenAddress, + options->DirPort, "0.0.0.0", + new_conns, 0) < 0) + retval = -1; + } + + if (!options->DisableNetwork) { + if (retry_listener_ports(listeners, + get_configured_client_ports(), + new_conns) < 0) + retval = -1; + } + + if (retry_listeners(listeners, + CONN_TYPE_CONTROL_LISTENER, options->ControlListenAddress, options->ControlPort, "127.0.0.1", - replaced_conns, new_conns, 0, - AF_INET)<0) - return -1; - if (retry_listeners(CONN_TYPE_CONTROL_LISTENER, + new_conns, 0) < 0) + retval = -1; + if (retry_listeners(listeners, + CONN_TYPE_CONTROL_LISTENER, options->ControlSocket, options->ControlSocket ? 1 : 0, NULL, - replaced_conns, new_conns, 0, - AF_UNIX)<0) - return -1; + new_conns, 1) < 0) + retval = -1; + + /* Any members that were still in 'listeners' don't correspond to + * any configured port. Kill 'em. */ + SMARTLIST_FOREACH_BEGIN(listeners, connection_t *, conn) { + log_notice(LD_NET, "Closing no-longer-configured %s on %s:%d", + conn_type_to_string(conn->type), conn->address, conn->port); + if (replaced_conns) { + smartlist_add(replaced_conns, conn); + } else { + connection_close_immediate(conn); + connection_mark_for_close(conn); + } + } SMARTLIST_FOREACH_END(conn); + + smartlist_free(listeners); if (old_or_port != router_get_advertised_or_port(options) || old_dir_port != router_get_advertised_dir_port(options, 0)) { @@ -2012,20 +2046,66 @@ retry_all_listeners(smartlist_t *replaced_conns, return retval; } -/** Return 1 if we should apply rate limiting to <b>conn</b>, - * and 0 otherwise. Right now this just checks if it's an internal - * IP address or an internal connection. */ +/** Mark every listener of type other than CONTROL_LISTENER to be closed. */ +void +connection_mark_all_noncontrol_listeners(void) +{ + SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) { + if (conn->marked_for_close) + continue; + if (conn->type == CONN_TYPE_CONTROL_LISTENER) + continue; + if (connection_is_listener(conn)) + connection_mark_for_close(conn); + } SMARTLIST_FOREACH_END(conn); +} + +/** Mark every external conection not used for controllers for close. */ +void +connection_mark_all_noncontrol_connections(void) +{ + SMARTLIST_FOREACH_BEGIN(get_connection_array(), connection_t *, conn) { + if (conn->marked_for_close) + continue; + switch (conn->type) { + case CONN_TYPE_CPUWORKER: + case CONN_TYPE_CONTROL_LISTENER: + case CONN_TYPE_CONTROL: + break; + case CONN_TYPE_AP: + connection_mark_unattached_ap(TO_ENTRY_CONN(conn), + END_STREAM_REASON_HIBERNATING); + break; + default: + connection_mark_for_close(conn); + break; + } + } SMARTLIST_FOREACH_END(conn); +} + +/** Return 1 if we should apply rate limiting to <b>conn</b>, and 0 + * otherwise. + * Right now this just checks if it's an internal IP address or an + * internal connection. We also check if the connection uses pluggable + * transports, since we should then limit it even if it comes from an + * internal IP address. */ static int connection_is_rate_limited(connection_t *conn) { - if (conn->linked || /* internal connection */ - tor_addr_family(&conn->addr) == AF_UNSPEC || /* no address */ - tor_addr_is_internal(&conn->addr, 0)) /* internal address */ - return 0; + const or_options_t *options = get_options(); + if (conn->linked) + return 0; /* Internal connection */ + else if (! options->CountPrivateBandwidth && + (tor_addr_family(&conn->addr) == AF_UNSPEC || /* no address */ + tor_addr_is_internal(&conn->addr, 0))) + return 0; /* Internal address */ else return 1; } +#ifdef USE_BUFFEREVENTS +static struct bufferevent_rate_limit_group *global_rate_limit = NULL; +#else extern int global_read_bucket, global_write_bucket; extern int global_relayed_read_bucket, global_relayed_write_bucket; @@ -2033,11 +2113,13 @@ extern int global_relayed_read_bucket, global_relayed_write_bucket; * we are likely to run dry again this second, so be stingy with the * tokens we just put in. */ static int write_buckets_empty_last_second = 0; +#endif /** How many seconds of no active local circuits will make the * connection revert to the "relayed" bandwidth class? */ #define CLIENT_IDLE_TIME_FOR_PRIORITY 30 +#ifndef USE_BUFFEREVENTS /** Return 1 if <b>conn</b> should use tokens from the "relayed" * bandwidth rates, else 0. Currently, only OR conns with bandwidth * class 1, and directory conns that are serving data out, count. @@ -2148,6 +2230,20 @@ connection_bucket_write_limit(connection_t *conn, time_t now) return connection_bucket_round_robin(base, priority, global_bucket, conn_bucket); } +#else +static ssize_t +connection_bucket_read_limit(connection_t *conn, time_t now) +{ + (void) now; + return bufferevent_get_max_to_read(conn->bufev); +} +ssize_t +connection_bucket_write_limit(connection_t *conn, time_t now) +{ + (void) now; + return bufferevent_get_max_to_write(conn->bufev); +} +#endif /** Return 1 if the global write buckets are low enough that we * shouldn't send <b>attempt</b> bytes of low-priority directory stuff @@ -2172,8 +2268,12 @@ connection_bucket_write_limit(connection_t *conn, time_t now) int global_write_bucket_low(connection_t *conn, size_t attempt, int priority) { +#ifdef USE_BUFFEREVENTS + ssize_t smaller_bucket = bufferevent_get_max_to_write(conn->bufev); +#else int smaller_bucket = global_write_bucket < global_relayed_write_bucket ? global_write_bucket : global_relayed_write_bucket; +#endif if (authdir_mode(get_options()) && priority>1) return 0; /* there's always room to answer v2 if we're an auth dir */ @@ -2183,12 +2283,14 @@ global_write_bucket_low(connection_t *conn, size_t attempt, int priority) if (smaller_bucket < (int)attempt) return 1; /* not enough space no matter the priority */ +#ifndef USE_BUFFEREVENTS if (write_buckets_empty_last_second) return 1; /* we're already hitting our limits, no more please */ +#endif if (priority == 1) { /* old-style v1 query */ /* Could we handle *two* of these requests within the next two seconds? */ - or_options_t *options = get_options(); + const or_options_t *options = get_options(); int64_t can_write = (int64_t)smaller_bucket + 2*(options->RelayBandwidthRate ? options->RelayBandwidthRate : options->BandwidthRate); @@ -2200,23 +2302,11 @@ global_write_bucket_low(connection_t *conn, size_t attempt, int priority) return 0; } -/** We just read <b>num_read</b> and wrote <b>num_written</b> bytes - * onto <b>conn</b>. Decrement buckets appropriately. */ +/** DOCDOC */ static void -connection_buckets_decrement(connection_t *conn, time_t now, - size_t num_read, size_t num_written) +record_num_bytes_transferred_impl(connection_t *conn, + time_t now, size_t num_read, size_t num_written) { - if (num_written >= INT_MAX || num_read >= INT_MAX) { - log_err(LD_BUG, "Value out of range. num_read=%lu, num_written=%lu, " - "connection type=%s, state=%s", - (unsigned long)num_read, (unsigned long)num_written, - conn_type_to_string(conn->type), - conn_state_to_string(conn->type, conn->state)); - if (num_written >= INT_MAX) num_written = 1; - if (num_read >= INT_MAX) num_read = 1; - tor_fragile_assert(); - } - /* Count bytes of answering direct and tunneled directory requests */ if (conn->type == CONN_TYPE_DIR && conn->purpose == DIR_PURPOSE_SERVER) { if (num_read > 0) @@ -2227,6 +2317,11 @@ connection_buckets_decrement(connection_t *conn, time_t now, if (!connection_is_rate_limited(conn)) return; /* local IPs are free */ + + if (conn->type == CONN_TYPE_OR) + rep_hist_note_or_conn_bytes(conn->global_identifier, num_read, + num_written, now); + if (num_read > 0) { rep_hist_note_bytes_read(num_read, now); } @@ -2235,6 +2330,52 @@ connection_buckets_decrement(connection_t *conn, time_t now, } if (conn->type == CONN_TYPE_EXIT) rep_hist_note_exit_bytes(conn->port, num_written, num_read); +} + +#ifdef USE_BUFFEREVENTS +/** DOCDOC */ +static void +record_num_bytes_transferred(connection_t *conn, + time_t now, size_t num_read, size_t num_written) +{ + /* XXX023 check if this is necessary */ + if (num_written >= INT_MAX || num_read >= INT_MAX) { + log_err(LD_BUG, "Value out of range. num_read=%lu, num_written=%lu, " + "connection type=%s, state=%s", + (unsigned long)num_read, (unsigned long)num_written, + conn_type_to_string(conn->type), + conn_state_to_string(conn->type, conn->state)); + if (num_written >= INT_MAX) num_written = 1; + if (num_read >= INT_MAX) num_read = 1; + tor_fragile_assert(); + } + + record_num_bytes_transferred_impl(conn,now,num_read,num_written); +} +#endif + +#ifndef USE_BUFFEREVENTS +/** We just read <b>num_read</b> and wrote <b>num_written</b> bytes + * onto <b>conn</b>. Decrement buckets appropriately. */ +static void +connection_buckets_decrement(connection_t *conn, time_t now, + size_t num_read, size_t num_written) +{ + if (num_written >= INT_MAX || num_read >= INT_MAX) { + log_err(LD_BUG, "Value out of range. num_read=%lu, num_written=%lu, " + "connection type=%s, state=%s", + (unsigned long)num_read, (unsigned long)num_written, + conn_type_to_string(conn->type), + conn_state_to_string(conn->type, conn->state)); + if (num_written >= INT_MAX) num_written = 1; + if (num_read >= INT_MAX) num_read = 1; + tor_fragile_assert(); + } + + record_num_bytes_transferred_impl(conn, now, num_read, num_written); + + if (!connection_is_rate_limited(conn)) + return; /* local IPs are free */ if (connection_counts_as_relayed_traffic(conn, now)) { global_relayed_read_bucket -= (int)num_read; @@ -2300,7 +2441,7 @@ connection_consider_empty_write_buckets(connection_t *conn) void connection_bucket_init(void) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); /* start it at max traffic */ global_read_bucket = (int)options->BandwidthBurst; global_write_bucket = (int)options->BandwidthBurst; @@ -2313,22 +2454,23 @@ connection_bucket_init(void) } } -/** Refill a single <b>bucket</b> called <b>name</b> with bandwidth rate - * <b>rate</b> and bandwidth burst <b>burst</b>, assuming that - * <b>seconds_elapsed</b> seconds have passed since the last call. - **/ +/** Refill a single <b>bucket</b> called <b>name</b> with bandwidth rate per + * second <b>rate</b> and bandwidth burst <b>burst</b>, assuming that + * <b>milliseconds_elapsed</b> milliseconds have passed since the last + * call. */ static void connection_bucket_refill_helper(int *bucket, int rate, int burst, - int seconds_elapsed, const char *name) + int milliseconds_elapsed, + const char *name) { int starting_bucket = *bucket; - if (starting_bucket < burst && seconds_elapsed) { - if (((burst - starting_bucket)/seconds_elapsed) < rate) { + if (starting_bucket < burst && milliseconds_elapsed > 0) { + int64_t incr = (((int64_t)rate) * milliseconds_elapsed) / 1000; + if ((burst - starting_bucket) < incr) { *bucket = burst; /* We would overflow the bucket; just set it to * the maximum. */ } else { - int incr = rate*seconds_elapsed; - *bucket += incr; + *bucket += (int)incr; if (*bucket > burst || *bucket < starting_bucket) { /* If we overflow the burst, or underflow our starting bucket, * cap the bucket value to burst. */ @@ -2341,41 +2483,46 @@ connection_bucket_refill_helper(int *bucket, int rate, int burst, } } -/** A second has rolled over; increment buckets appropriately. */ +/** Time has passed; increment buckets appropriately. */ void -connection_bucket_refill(int seconds_elapsed, time_t now) +connection_bucket_refill(int milliseconds_elapsed, time_t now) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); smartlist_t *conns = get_connection_array(); - int relayrate, relayburst; + int bandwidthrate, bandwidthburst, relayrate, relayburst; + + bandwidthrate = (int)options->BandwidthRate; + bandwidthburst = (int)options->BandwidthBurst; if (options->RelayBandwidthRate) { relayrate = (int)options->RelayBandwidthRate; relayburst = (int)options->RelayBandwidthBurst; } else { - relayrate = (int)options->BandwidthRate; - relayburst = (int)options->BandwidthBurst; + relayrate = bandwidthrate; + relayburst = bandwidthburst; } - tor_assert(seconds_elapsed >= 0); + tor_assert(milliseconds_elapsed >= 0); write_buckets_empty_last_second = global_relayed_write_bucket <= 0 || global_write_bucket <= 0; /* refill the global buckets */ connection_bucket_refill_helper(&global_read_bucket, - (int)options->BandwidthRate, - (int)options->BandwidthBurst, - seconds_elapsed, "global_read_bucket"); + bandwidthrate, bandwidthburst, + milliseconds_elapsed, + "global_read_bucket"); connection_bucket_refill_helper(&global_write_bucket, - (int)options->BandwidthRate, - (int)options->BandwidthBurst, - seconds_elapsed, "global_write_bucket"); + bandwidthrate, bandwidthburst, + milliseconds_elapsed, + "global_write_bucket"); connection_bucket_refill_helper(&global_relayed_read_bucket, - relayrate, relayburst, seconds_elapsed, + relayrate, relayburst, + milliseconds_elapsed, "global_relayed_read_bucket"); connection_bucket_refill_helper(&global_relayed_write_bucket, - relayrate, relayburst, seconds_elapsed, + relayrate, relayburst, + milliseconds_elapsed, "global_relayed_write_bucket"); /* refill the per-connection buckets */ @@ -2383,18 +2530,20 @@ connection_bucket_refill(int seconds_elapsed, time_t now) { if (connection_speaks_cells(conn)) { or_connection_t *or_conn = TO_OR_CONN(conn); + int orbandwidthrate = or_conn->bandwidthrate; + int orbandwidthburst = or_conn->bandwidthburst; if (connection_bucket_should_increase(or_conn->read_bucket, or_conn)) { connection_bucket_refill_helper(&or_conn->read_bucket, - or_conn->bandwidthrate, - or_conn->bandwidthburst, - seconds_elapsed, + orbandwidthrate, + orbandwidthburst, + milliseconds_elapsed, "or_conn->read_bucket"); } if (connection_bucket_should_increase(or_conn->write_bucket, or_conn)) { connection_bucket_refill_helper(&or_conn->write_bucket, - or_conn->bandwidthrate, - or_conn->bandwidthburst, - seconds_elapsed, + orbandwidthrate, + orbandwidthburst, + milliseconds_elapsed, "or_conn->write_bucket"); } } @@ -2443,6 +2592,91 @@ connection_bucket_should_increase(int bucket, or_connection_t *conn) return 1; } +#else +static void +connection_buckets_decrement(connection_t *conn, time_t now, + size_t num_read, size_t num_written) +{ + (void) conn; + (void) now; + (void) num_read; + (void) num_written; + /* Libevent does this for us. */ +} + +void +connection_bucket_refill(int seconds_elapsed, time_t now) +{ + (void) seconds_elapsed; + (void) now; + /* Libevent does this for us. */ +} +void +connection_bucket_init(void) +{ + const or_options_t *options = get_options(); + const struct timeval *tick = tor_libevent_get_one_tick_timeout(); + struct ev_token_bucket_cfg *bucket_cfg; + + uint64_t rate, burst; + if (options->RelayBandwidthRate) { + rate = options->RelayBandwidthRate; + burst = options->RelayBandwidthBurst; + } else { + rate = options->BandwidthRate; + burst = options->BandwidthBurst; + } + + /* This can't overflow, since TokenBucketRefillInterval <= 1000, + * and rate started out less than INT32_MAX. */ + rate = (rate * options->TokenBucketRefillInterval) / 1000; + + bucket_cfg = ev_token_bucket_cfg_new((uint32_t)rate, (uint32_t)burst, + (uint32_t)rate, (uint32_t)burst, + tick); + + if (!global_rate_limit) { + global_rate_limit = + bufferevent_rate_limit_group_new(tor_libevent_get_base(), bucket_cfg); + } else { + bufferevent_rate_limit_group_set_cfg(global_rate_limit, bucket_cfg); + } + ev_token_bucket_cfg_free(bucket_cfg); +} + +void +connection_get_rate_limit_totals(uint64_t *read_out, uint64_t *written_out) +{ + if (global_rate_limit == NULL) { + *read_out = *written_out = 0; + } else { + bufferevent_rate_limit_group_get_totals( + global_rate_limit, read_out, written_out); + } +} + +/** DOCDOC */ +void +connection_enable_rate_limiting(connection_t *conn) +{ + if (conn->bufev) { + if (!global_rate_limit) + connection_bucket_init(); + tor_add_bufferevent_to_rate_limit_group(conn->bufev, global_rate_limit); + } +} + +static void +connection_consider_empty_write_buckets(connection_t *conn) +{ + (void) conn; +} +static void +connection_consider_empty_read_buckets(connection_t *conn) +{ + (void) conn; +} +#endif /** Read bytes from conn-\>s and process them. * @@ -2501,8 +2735,10 @@ connection_handle_read_impl(connection_t *conn) if (CONN_IS_EDGE(conn)) { edge_connection_t *edge_conn = TO_EDGE_CONN(conn); connection_edge_end_errno(edge_conn); - if (edge_conn->socks_request) /* broken, don't send a socks reply back */ - edge_conn->socks_request->has_finished = 1; + if (conn->type == CONN_TYPE_AP && TO_ENTRY_CONN(conn)->socks_request) { + /* broken, don't send a socks reply back */ + TO_ENTRY_CONN(conn)->socks_request->has_finished = 1; + } } connection_close_immediate(conn); /* Don't flush; connection is dead. */ connection_mark_for_close(conn); @@ -2697,7 +2933,7 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read, } if (n_read > 0) { - /* change *max_to_read */ + /* change *max_to_read */ *max_to_read = at_most - n_read; /* Update edge_conn->n_read */ @@ -2729,11 +2965,212 @@ connection_read_to_buf(connection_t *conn, ssize_t *max_to_read, return 0; } +#ifdef USE_BUFFEREVENTS +/* XXXX These generic versions could be simplified by making them + type-specific */ + +/** Callback: Invoked whenever bytes are added to or drained from an input + * evbuffer. Used to track the number of bytes read. */ +static void +evbuffer_inbuf_callback(struct evbuffer *buf, + const struct evbuffer_cb_info *info, void *arg) +{ + connection_t *conn = arg; + (void) buf; + /* XXXX These need to get real counts on the non-nested TLS case. - NM */ + if (info->n_added) { + time_t now = approx_time(); + conn->timestamp_lastread = now; + record_num_bytes_transferred(conn, now, info->n_added, 0); + connection_consider_empty_read_buckets(conn); + if (conn->type == CONN_TYPE_AP) { + edge_connection_t *edge_conn = TO_EDGE_CONN(conn); + /*XXXX022 check for overflow*/ + edge_conn->n_read += (int)info->n_added; + } + } +} + +/** Callback: Invoked whenever bytes are added to or drained from an output + * evbuffer. Used to track the number of bytes written. */ +static void +evbuffer_outbuf_callback(struct evbuffer *buf, + const struct evbuffer_cb_info *info, void *arg) +{ + connection_t *conn = arg; + (void)buf; + if (info->n_deleted) { + time_t now = approx_time(); + conn->timestamp_lastwritten = now; + record_num_bytes_transferred(conn, now, 0, info->n_deleted); + connection_consider_empty_write_buckets(conn); + if (conn->type == CONN_TYPE_AP) { + edge_connection_t *edge_conn = TO_EDGE_CONN(conn); + /*XXXX022 check for overflow*/ + edge_conn->n_written += (int)info->n_deleted; + } + } +} + +/** Callback: invoked whenever a bufferevent has read data. */ +void +connection_handle_read_cb(struct bufferevent *bufev, void *arg) +{ + connection_t *conn = arg; + (void) bufev; + if (!conn->marked_for_close) { + if (connection_process_inbuf(conn, 1)<0) /* XXXX Always 1? */ + if (!conn->marked_for_close) + connection_mark_for_close(conn); + } +} + +/** Callback: invoked whenever a bufferevent has written data. */ +void +connection_handle_write_cb(struct bufferevent *bufev, void *arg) +{ + connection_t *conn = arg; + struct evbuffer *output; + if (connection_flushed_some(conn)<0) { + if (!conn->marked_for_close) + connection_mark_for_close(conn); + return; + } + + output = bufferevent_get_output(bufev); + if (!evbuffer_get_length(output)) { + connection_finished_flushing(conn); + if (conn->marked_for_close && conn->hold_open_until_flushed) { + conn->hold_open_until_flushed = 0; + if (conn->linked) { + /* send eof */ + bufferevent_flush(conn->bufev, EV_WRITE, BEV_FINISHED); + } + } + } +} + +/** Callback: invoked whenever a bufferevent has had an event (like a + * connection, or an eof, or an error) occur. */ +void +connection_handle_event_cb(struct bufferevent *bufev, short event, void *arg) +{ + connection_t *conn = arg; + (void) bufev; + if (event & BEV_EVENT_CONNECTED) { + tor_assert(connection_state_is_connecting(conn)); + if (connection_finished_connecting(conn)<0) + return; + } + if (event & BEV_EVENT_EOF) { + if (!conn->marked_for_close) { + conn->inbuf_reached_eof = 1; + if (connection_reached_eof(conn)<0) + return; + } + } + if (event & BEV_EVENT_ERROR) { + int socket_error = evutil_socket_geterror(conn->s); + if (conn->type == CONN_TYPE_OR && + conn->state == OR_CONN_STATE_CONNECTING) { + connection_or_connect_failed(TO_OR_CONN(conn), + errno_to_orconn_end_reason(socket_error), + tor_socket_strerror(socket_error)); + } else if (CONN_IS_EDGE(conn)) { + edge_connection_t *edge_conn = TO_EDGE_CONN(conn); + if (!edge_conn->edge_has_sent_end) + connection_edge_end_errno(edge_conn); + if (conn->type == CONN_TYPE_AP && TO_ENTRY_CONN(conn)->socks_request) { + /* broken, don't send a socks reply back */ + TO_ENTRY_CONN(conn)->socks_request->has_finished = 1; + } + } + connection_close_immediate(conn); /* Connection is dead. */ + if (!conn->marked_for_close) + connection_mark_for_close(conn); + } +} + +/** Set up the generic callbacks for the bufferevent on <b>conn</b>. */ +void +connection_configure_bufferevent_callbacks(connection_t *conn) +{ + struct bufferevent *bufev; + struct evbuffer *input, *output; + tor_assert(conn->bufev); + bufev = conn->bufev; + bufferevent_setcb(bufev, + connection_handle_read_cb, + connection_handle_write_cb, + connection_handle_event_cb, + conn); + /* Set a fairly high write low-watermark so that we get the write callback + called whenever data is written to bring us under 128K. Leave the + high-watermark at 0. + */ + bufferevent_setwatermark(bufev, EV_WRITE, 128*1024, 0); + + input = bufferevent_get_input(bufev); + output = bufferevent_get_output(bufev); + evbuffer_add_cb(input, evbuffer_inbuf_callback, conn); + evbuffer_add_cb(output, evbuffer_outbuf_callback, conn); +} +#endif + /** A pass-through to fetch_from_buf. */ int connection_fetch_from_buf(char *string, size_t len, connection_t *conn) { - return fetch_from_buf(string, len, conn->inbuf); + IF_HAS_BUFFEREVENT(conn, { + /* XXX overflow -seb */ + return (int)bufferevent_read(conn->bufev, string, len); + }) ELSE_IF_NO_BUFFEREVENT { + return fetch_from_buf(string, len, conn->inbuf); + } +} + +/** As fetch_from_buf_line(), but read from a connection's input buffer. */ +int +connection_fetch_from_buf_line(connection_t *conn, char *data, + size_t *data_len) +{ + IF_HAS_BUFFEREVENT(conn, { + int r; + size_t eol_len=0; + struct evbuffer *input = bufferevent_get_input(conn->bufev); + struct evbuffer_ptr ptr = + evbuffer_search_eol(input, NULL, &eol_len, EVBUFFER_EOL_LF); + if (ptr.pos == -1) + return 0; /* No EOL found. */ + if ((size_t)ptr.pos+eol_len >= *data_len) { + return -1; /* Too long */ + } + *data_len = ptr.pos+eol_len; + r = evbuffer_remove(input, data, ptr.pos+eol_len); + tor_assert(r >= 0); + data[ptr.pos+eol_len] = '\0'; + return 1; + }) ELSE_IF_NO_BUFFEREVENT { + return fetch_from_buf_line(conn->inbuf, data, data_len); + } +} + +/** As fetch_from_buf_http, but fetches from a conncetion's input buffer_t or + * its bufferevent as appropriate. */ +int +connection_fetch_from_buf_http(connection_t *conn, + char **headers_out, size_t max_headerlen, + char **body_out, size_t *body_used, + size_t max_bodylen, int force_complete) +{ + IF_HAS_BUFFEREVENT(conn, { + struct evbuffer *input = bufferevent_get_input(conn->bufev); + return fetch_from_evbuffer_http(input, headers_out, max_headerlen, + body_out, body_used, max_bodylen, force_complete); + }) ELSE_IF_NO_BUFFEREVENT { + return fetch_from_buf_http(conn->inbuf, headers_out, max_headerlen, + body_out, body_used, max_bodylen, force_complete); + } } /** Return conn-\>outbuf_flushlen: how many bytes conn wants to flush @@ -2854,6 +3291,7 @@ connection_handle_write_impl(connection_t *conn, int force) /* If we just flushed the last bytes, check if this tunneled dir * request is done. */ + /* XXXX move this to flushed_some or finished_flushing -NM */ if (buf_datalen(conn->outbuf) == 0 && conn->dirreq_id) geoip_change_dirreq_state(conn->dirreq_id, DIRREQ_TUNNELED, DIRREQ_OR_CONN_BUFFER_FLUSHED); @@ -2909,6 +3347,7 @@ connection_handle_write_impl(connection_t *conn, int force) if (n_written && conn->type == CONN_TYPE_AP) { edge_connection_t *edge_conn = TO_EDGE_CONN(conn); + /* Check for overflow: */ if (PREDICT_LIKELY(UINT32_MAX - edge_conn->n_written > n_written)) edge_conn->n_written += (int)n_written; @@ -2952,6 +3391,25 @@ connection_handle_write(connection_t *conn, int force) return res; } +/** + * Try to flush data that's waiting for a write on <b>conn</b>. Return + * -1 on failure, 0 on success. + * + * Don't use this function for regular writing; the buffers/bufferevents + * system should be good enough at scheduling writes there. Instead, this + * function is for cases when we're about to exit or something and we want + * to report it right away. + */ +int +connection_flush(connection_t *conn) +{ + IF_HAS_BUFFEREVENT(conn, { + int r = bufferevent_flush(conn->bufev, EV_WRITE, BEV_FLUSH); + return (r < 0) ? -1 : 0; + }); + return connection_handle_write(conn, 1); +} + /** OpenSSL TLS record size is 16383; this is close. The goal here is to * push data out as soon as we know there's enough for a TLS record, so * during periods of high load we won't read entire megabytes from @@ -2985,6 +3443,22 @@ _connection_write_to_buf_impl(const char *string, size_t len, if (conn->marked_for_close && !conn->hold_open_until_flushed) return; + IF_HAS_BUFFEREVENT(conn, { + if (zlib) { + int done = zlib < 0; + r = write_to_evbuffer_zlib(bufferevent_get_output(conn->bufev), + TO_DIR_CONN(conn)->zlib_state, + string, len, done); + } else { + r = bufferevent_write(conn->bufev, string, len); + } + if (r < 0) { + /* XXXX mark for close? */ + log_warn(LD_NET, "bufferevent_write failed! That shouldn't happen."); + } + return; + }); + old_datalen = buf_datalen(conn->outbuf); if (zlib) { dir_connection_t *dir_conn = TO_DIR_CONN(conn); @@ -3012,7 +3486,13 @@ _connection_write_to_buf_impl(const char *string, size_t len, return; } - connection_start_writing(conn); + /* If we receive optimistic data in the EXIT_CONN_STATE_RESOLVING + * state, we don't want to try to write it right away, since + * conn->write_event won't be set yet. Otherwise, write data from + * this conn as the socket is available. */ + if (conn->write_event) { + connection_start_writing(conn); + } if (zlib) { conn->outbuf_flushlen += buf_datalen(conn->outbuf) - old_datalen; } else { @@ -3138,8 +3618,7 @@ connection_get_by_type_state_rendquery(int type, int state, type == CONN_TYPE_AP || type == CONN_TYPE_EXIT); tor_assert(rendquery); - SMARTLIST_FOREACH(conns, connection_t *, conn, - { + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { if (conn->type == type && !conn->marked_for_close && (!state || state == conn->state)) { @@ -3154,7 +3633,33 @@ connection_get_by_type_state_rendquery(int type, int state, TO_EDGE_CONN(conn)->rend_data->onion_address)) return conn; } - }); + } SMARTLIST_FOREACH_END(conn); + return NULL; +} + +/** Return a directory connection (if any one exists) that is fetching + * the item described by <b>state</b>/<b>resource</b> */ +dir_connection_t * +connection_dir_get_by_purpose_and_resource(int purpose, + const char *resource) +{ + smartlist_t *conns = get_connection_array(); + + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { + dir_connection_t *dirconn; + if (conn->type != CONN_TYPE_DIR || conn->marked_for_close || + conn->purpose != purpose) + continue; + dirconn = TO_DIR_CONN(conn); + if (dirconn->requested_resource == NULL) { + if (resource == NULL) + return dirconn; + } else if (resource) { + if (0 == strcmp(resource, dirconn->requested_resource)) + return dirconn; + } + } SMARTLIST_FOREACH_END(conn); + return NULL; } @@ -3408,6 +3913,9 @@ connection_finished_flushing(connection_t *conn) // log_fn(LOG_DEBUG,"entered. Socket %u.", conn->s); + IF_HAS_NO_BUFFEREVENT(conn) + connection_stop_writing(conn); + switch (conn->type) { case CONN_TYPE_OR: return connection_or_finished_flushing(TO_OR_CONN(conn)); @@ -3533,11 +4041,23 @@ assert_connection_ok(connection_t *conn, time_t now) tor_assert(conn); tor_assert(conn->type >= _CONN_TYPE_MIN); tor_assert(conn->type <= _CONN_TYPE_MAX); + +#ifdef USE_BUFFEREVENTS + if (conn->bufev) { + tor_assert(conn->read_event == NULL); + tor_assert(conn->write_event == NULL); + tor_assert(conn->inbuf == NULL); + tor_assert(conn->outbuf == NULL); + } +#endif + switch (conn->type) { case CONN_TYPE_OR: tor_assert(conn->magic == OR_CONNECTION_MAGIC); break; case CONN_TYPE_AP: + tor_assert(conn->magic == ENTRY_CONNECTION_MAGIC); + break; case CONN_TYPE_EXIT: tor_assert(conn->magic == EDGE_CONNECTION_MAGIC); break; @@ -3547,6 +4067,9 @@ assert_connection_ok(connection_t *conn, time_t now) case CONN_TYPE_CONTROL: tor_assert(conn->magic == CONTROL_CONNECTION_MAGIC); break; + CASE_ANY_LISTENER_TYPE: + tor_assert(conn->magic == LISTENER_CONNECTION_MAGIC); + break; default: tor_assert(conn->magic == BASE_CONNECTION_MAGIC); break; @@ -3560,8 +4083,15 @@ assert_connection_ok(connection_t *conn, time_t now) tor_assert(!SOCKET_OK(conn->s)); if (conn->outbuf_flushlen > 0) { - tor_assert(connection_is_writing(conn) || conn->write_blocked_on_bw || - (CONN_IS_EDGE(conn) && TO_EDGE_CONN(conn)->edge_blocked_on_circ)); + /* With optimistic data, we may have queued data in + * EXIT_CONN_STATE_RESOLVING while the conn is not yet marked to writing. + * */ + tor_assert((conn->type == CONN_TYPE_EXIT && + conn->state == EXIT_CONN_STATE_RESOLVING) || + connection_is_writing(conn) || + conn->write_blocked_on_bw || + (CONN_IS_EDGE(conn) && + TO_EDGE_CONN(conn)->edge_blocked_on_circ)); } if (conn->hold_open_until_flushed) @@ -3571,10 +4101,10 @@ assert_connection_ok(connection_t *conn, time_t now) * marked_for_close. */ /* buffers */ - if (!connection_is_listener(conn)) { + if (conn->inbuf) assert_buf_ok(conn->inbuf); + if (conn->outbuf) assert_buf_ok(conn->outbuf); - } if (conn->type == CONN_TYPE_OR) { or_connection_t *or_conn = TO_OR_CONN(conn); @@ -3594,21 +4124,18 @@ assert_connection_ok(connection_t *conn, time_t now) } if (CONN_IS_EDGE(conn)) { - edge_connection_t *edge_conn = TO_EDGE_CONN(conn); - if (edge_conn->chosen_exit_optional || edge_conn->chosen_exit_retries) { - tor_assert(conn->type == CONN_TYPE_AP); - tor_assert(edge_conn->chosen_exit_name); - } - /* XXX unchecked: package window, deliver window. */ if (conn->type == CONN_TYPE_AP) { + entry_connection_t *entry_conn = TO_ENTRY_CONN(conn); + if (entry_conn->chosen_exit_optional || entry_conn->chosen_exit_retries) + tor_assert(entry_conn->chosen_exit_name); - tor_assert(edge_conn->socks_request); + tor_assert(entry_conn->socks_request); if (conn->state == AP_CONN_STATE_OPEN) { - tor_assert(edge_conn->socks_request->has_finished); + tor_assert(entry_conn->socks_request->has_finished); if (!conn->marked_for_close) { - tor_assert(edge_conn->cpath_layer); - assert_cpath_layer_ok(edge_conn->cpath_layer); + tor_assert(ENTRY_TO_EDGE_CONN(entry_conn)->cpath_layer); + assert_cpath_layer_ok(ENTRY_TO_EDGE_CONN(entry_conn)->cpath_layer); } } } @@ -3624,13 +4151,7 @@ assert_connection_ok(connection_t *conn, time_t now) switch (conn->type) { - case CONN_TYPE_OR_LISTENER: - case CONN_TYPE_AP_LISTENER: - case CONN_TYPE_AP_TRANS_LISTENER: - case CONN_TYPE_AP_NATD_LISTENER: - case CONN_TYPE_DIR_LISTENER: - case CONN_TYPE_CONTROL_LISTENER: - case CONN_TYPE_AP_DNS_LISTENER: + CASE_ANY_LISTENER_TYPE: tor_assert(conn->state == LISTENER_STATE_READY); break; case CONN_TYPE_OR: @@ -3647,7 +4168,7 @@ assert_connection_ok(connection_t *conn, time_t now) case CONN_TYPE_AP: tor_assert(conn->state >= _AP_CONN_STATE_MIN); tor_assert(conn->state <= _AP_CONN_STATE_MAX); - tor_assert(TO_EDGE_CONN(conn)->socks_request); + tor_assert(TO_ENTRY_CONN(conn)->socks_request); break; case CONN_TYPE_DIR: tor_assert(conn->state >= _DIR_CONN_STATE_MIN); @@ -3668,3 +4189,141 @@ assert_connection_ok(connection_t *conn, time_t now) } } +/** Fills <b>addr</b> and <b>port</b> with the details of the global + * proxy server we are using. + * <b>conn</b> contains the connection we are using the proxy for. + * + * Return 0 on success, -1 on failure. + */ +int +get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type, + const connection_t *conn) +{ + const or_options_t *options = get_options(); + + if (options->HTTPSProxy) { + tor_addr_copy(addr, &options->HTTPSProxyAddr); + *port = options->HTTPSProxyPort; + *proxy_type = PROXY_CONNECT; + return 0; + } else if (options->Socks4Proxy) { + tor_addr_copy(addr, &options->Socks4ProxyAddr); + *port = options->Socks4ProxyPort; + *proxy_type = PROXY_SOCKS4; + return 0; + } else if (options->Socks5Proxy) { + tor_addr_copy(addr, &options->Socks5ProxyAddr); + *port = options->Socks5ProxyPort; + *proxy_type = PROXY_SOCKS5; + return 0; + } else if (options->ClientTransportPlugin || + options->Bridges) { + const transport_t *transport = NULL; + int r; + r = find_transport_by_bridge_addrport(&conn->addr, conn->port, &transport); + if (r<0) + return -1; + if (transport) { /* transport found */ + tor_addr_copy(addr, &transport->addr); + *port = transport->port; + *proxy_type = transport->socks_version; + return 0; + } + } + + *proxy_type = PROXY_NONE; + return 0; +} + +/** Returns the global proxy type used by tor. */ +static int +get_proxy_type(void) +{ + const or_options_t *options = get_options(); + + if (options->HTTPSProxy) + return PROXY_CONNECT; + else if (options->Socks4Proxy) + return PROXY_SOCKS4; + else if (options->Socks5Proxy) + return PROXY_SOCKS5; + else if (options->ClientTransportPlugin) + return PROXY_PLUGGABLE; + else + return PROXY_NONE; +} + +/** Log a failed connection to a proxy server. + * <b>conn</b> is the connection we use the proxy server for. */ +void +log_failed_proxy_connection(connection_t *conn) +{ + tor_addr_t proxy_addr; + uint16_t proxy_port; + int proxy_type; + + if (get_proxy_addrport(&proxy_addr, &proxy_port, &proxy_type, conn) != 0) + return; /* if we have no proxy set up, leave this function. */ + + log_warn(LD_NET, + "The connection to the %s proxy server at %s:%u just failed. " + "Make sure that the proxy server is up and running.", + proxy_type_to_string(get_proxy_type()), fmt_addr(&proxy_addr), + proxy_port); +} + +/** Return string representation of <b>proxy_type</b>. */ +static const char * +proxy_type_to_string(int proxy_type) +{ + switch (proxy_type) { + case PROXY_CONNECT: return "HTTP"; + case PROXY_SOCKS4: return "SOCKS4"; + case PROXY_SOCKS5: return "SOCKS5"; + case PROXY_PLUGGABLE: return "pluggable transports SOCKS"; + case PROXY_NONE: return "NULL"; + default: tor_assert(0); + } + return NULL; /*Unreached*/ +} + +/** Call _connection_free() on every connection in our array, and release all + * storage held by connection.c. This is used by cpuworkers and dnsworkers + * when they fork, so they don't keep resources held open (especially + * sockets). + * + * Don't do the checks in connection_free(), because they will + * fail. + */ +void +connection_free_all(void) +{ + smartlist_t *conns = get_connection_array(); + + /* We don't want to log any messages to controllers. */ + SMARTLIST_FOREACH(conns, connection_t *, conn, + if (conn->type == CONN_TYPE_CONTROL) + TO_CONTROL_CONN(conn)->event_mask = 0); + + control_update_global_event_mask(); + + /* Unlink everything from the identity map. */ + connection_or_clear_identity_map(); + + /* Clear out our list of broken connections */ + clear_broken_connection_map(0); + + SMARTLIST_FOREACH(conns, connection_t *, conn, _connection_free(conn)); + + if (outgoing_addrs) { + SMARTLIST_FOREACH(outgoing_addrs, void*, addr, tor_free(addr)); + smartlist_free(outgoing_addrs); + outgoing_addrs = NULL; + } + +#ifdef USE_BUFFEREVENTS + if (global_rate_limit) + bufferevent_rate_limit_group_free(global_rate_limit); +#endif +} + diff --git a/src/or/connection.h b/src/or/connection.h index 576d3a63e1..c4b8bf8abe 100644 --- a/src/or/connection.h +++ b/src/or/connection.h @@ -12,13 +12,18 @@ #ifndef _TOR_CONNECTION_H #define _TOR_CONNECTION_H +/* XXXX For buf_datalen in inline function */ +#include "buffers.h" + const char *conn_type_to_string(int type); const char *conn_state_to_string(int type, int state); dir_connection_t *dir_connection_new(int socket_family); or_connection_t *or_connection_new(int socket_family); edge_connection_t *edge_connection_new(int type, int socket_family); +entry_connection_t *entry_connection_new(int type, int socket_family); control_connection_t *control_connection_new(int socket_family); +listener_connection_t *listener_connection_new(int type, int socket_family); connection_t *connection_new(int type, int socket_family); void connection_link_connections(connection_t *conn_a, connection_t *conn_b); @@ -31,6 +36,21 @@ void _connection_mark_for_close(connection_t *conn,int line, const char *file); #define connection_mark_for_close(c) \ _connection_mark_for_close((c), __LINE__, _SHORT_FILE_) +/** + * Mark 'c' for close, but try to hold it open until all the data is written. + */ +#define _connection_mark_and_flush(c,line,file) \ + do { \ + connection_t *tmp_conn_ = (c); \ + _connection_mark_for_close(tmp_conn_, (line), (file)); \ + tmp_conn_->hold_open_until_flushed = 1; \ + IF_HAS_BUFFEREVENT(tmp_conn_, \ + connection_start_writing(tmp_conn_)); \ + } while (0) + +#define connection_mark_and_flush(c) \ + _connection_mark_and_flush((c), __LINE__, _SHORT_FILE_) + void connection_expire_held_open(void); int connection_connect(connection_t *conn, const char *address, @@ -39,10 +59,16 @@ int connection_connect(connection_t *conn, const char *address, int connection_proxy_connect(connection_t *conn, int type); int connection_read_proxy_handshake(connection_t *conn); +void log_failed_proxy_connection(connection_t *conn); +int get_proxy_addrport(tor_addr_t *addr, uint16_t *port, int *proxy_type, + const connection_t *conn); int retry_all_listeners(smartlist_t *replaced_conns, smartlist_t *new_conns); +void connection_mark_all_noncontrol_listeners(void); +void connection_mark_all_noncontrol_connections(void); + ssize_t connection_bucket_write_limit(connection_t *conn, time_t now); int global_write_bucket_low(connection_t *conn, size_t attempt, int priority); void connection_bucket_init(void); @@ -51,10 +77,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 +107,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 +140,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 +155,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 0c5ebdee64..efaad79b6a 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -23,6 +23,7 @@ #include "dirserv.h" #include "hibernate.h" #include "main.h" +#include "nodelist.h" #include "policies.h" #include "reasons.h" #include "relay.h" @@ -50,23 +51,26 @@ #define SOCKS4_GRANTED 90 #define SOCKS4_REJECT 91 -static int connection_ap_handshake_process_socks(edge_connection_t *conn); -static int connection_ap_process_natd(edge_connection_t *conn); +static int connection_ap_handshake_process_socks(entry_connection_t *conn); +static int connection_ap_process_natd(entry_connection_t *conn); static int connection_exit_connect_dir(edge_connection_t *exitconn); static int address_is_in_virtual_range(const char *addr); -static int consider_plaintext_ports(edge_connection_t *conn, uint16_t port); +static int consider_plaintext_ports(entry_connection_t *conn, uint16_t port); static void clear_trackexithost_mappings(const char *exitname); +static int connection_ap_supports_optimistic_data(const entry_connection_t *); /** An AP stream has failed/finished. If it hasn't already sent back * a socks reply, send one now (based on endreason). Also set * has_sent_end to 1, and mark the conn. */ void -_connection_mark_unattached_ap(edge_connection_t *conn, int endreason, +_connection_mark_unattached_ap(entry_connection_t *conn, int endreason, int line, const char *file) { - tor_assert(conn->_base.type == CONN_TYPE_AP); - conn->edge_has_sent_end = 1; /* no circ yet */ + connection_t *base_conn = ENTRY_TO_CONN(conn); + edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn); + tor_assert(base_conn->type == CONN_TYPE_AP); + ENTRY_TO_EDGE_CONN(conn)->edge_has_sent_end = 1; /* no circ yet */ /* If this is a rendezvous stream and it is failing without ever * being attached to a circuit, assume that an attempt to connect to @@ -75,14 +79,15 @@ _connection_mark_unattached_ap(edge_connection_t *conn, int endreason, * XXX023 This condition doesn't limit to only streams failing * without ever being attached. That sloppiness should be harmless, * but we should fix it someday anyway. */ - if ((conn->on_circuit != NULL || conn->edge_has_sent_end) && - connection_edge_is_rendezvous_stream(conn)) { - rend_client_note_connection_attempt_ended(conn->rend_data->onion_address); + if ((edge_conn->on_circuit != NULL || edge_conn->edge_has_sent_end) && + connection_edge_is_rendezvous_stream(edge_conn)) { + rend_client_note_connection_attempt_ended( + edge_conn->rend_data->onion_address); } - if (conn->_base.marked_for_close) { + if (base_conn->marked_for_close) { /* This call will warn as appropriate. */ - _connection_mark_for_close(TO_CONN(conn), line, file); + _connection_mark_for_close(base_conn, line, file); return; } @@ -102,9 +107,9 @@ _connection_mark_unattached_ap(edge_connection_t *conn, int endreason, conn->socks_request->has_finished = 1; } - _connection_mark_for_close(TO_CONN(conn), line, file); - conn->_base.hold_open_until_flushed = 1; - conn->end_reason = endreason; + _connection_mark_and_flush(base_conn, line, file); + + ENTRY_TO_EDGE_CONN(conn)->end_reason = endreason; } /** There was an EOF. Send an end and mark the connection for close. @@ -112,7 +117,7 @@ _connection_mark_unattached_ap(edge_connection_t *conn, int endreason, int connection_edge_reached_eof(edge_connection_t *conn) { - if (buf_datalen(conn->_base.inbuf) && + if (connection_get_inbuf_len(TO_CONN(conn)) && connection_state_is_open(TO_CONN(conn))) { /* it still has stuff to process. don't let it die yet. */ return 0; @@ -122,8 +127,11 @@ connection_edge_reached_eof(edge_connection_t *conn) /* only mark it if not already marked. it's possible to * get the 'end' right around when the client hangs up on us. */ connection_edge_end(conn, END_STREAM_REASON_DONE); - if (conn->socks_request) /* eof, so don't send a socks reply back */ - conn->socks_request->has_finished = 1; + if (conn->_base.type == CONN_TYPE_AP) { + /* eof, so don't send a socks reply back */ + if (EDGE_TO_ENTRY_CONN(conn)->socks_request) + EDGE_TO_ENTRY_CONN(conn)->socks_request->has_finished = 1; + } connection_mark_for_close(TO_CONN(conn)); } return 0; @@ -146,13 +154,13 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial) switch (conn->_base.state) { case AP_CONN_STATE_SOCKS_WAIT: - if (connection_ap_handshake_process_socks(conn) < 0) { + if (connection_ap_handshake_process_socks(EDGE_TO_ENTRY_CONN(conn)) <0) { /* already marked */ return -1; } return 0; case AP_CONN_STATE_NATD_WAIT: - if (connection_ap_process_natd(conn) < 0) { + if (connection_ap_process_natd(EDGE_TO_ENTRY_CONN(conn)) < 0) { /* already marked */ return -1; } @@ -165,10 +173,26 @@ connection_edge_process_inbuf(edge_connection_t *conn, int package_partial) return -1; } return 0; + case AP_CONN_STATE_CONNECT_WAIT: + if (connection_ap_supports_optimistic_data(EDGE_TO_ENTRY_CONN(conn))) { + log_info(LD_EDGE, + "data from edge while in '%s' state. Sending it anyway. " + "package_partial=%d, buflen=%ld", + conn_state_to_string(conn->_base.type, conn->_base.state), + package_partial, + (long)connection_get_inbuf_len(TO_CONN(conn))); + if (connection_edge_package_raw_inbuf(conn, package_partial, NULL)<0) { + /* (We already sent an end cell if possible) */ + connection_mark_for_close(TO_CONN(conn)); + return -1; + } + return 0; + } + /* Fall through if the connection is on a circuit without optimistic + * data support. */ case EXIT_CONN_STATE_CONNECTING: case AP_CONN_STATE_RENDDESC_WAIT: case AP_CONN_STATE_CIRCUIT_WAIT: - case AP_CONN_STATE_CONNECT_WAIT: case AP_CONN_STATE_RESOLVE_WAIT: case AP_CONN_STATE_CONTROLLER_WAIT: log_info(LD_EDGE, @@ -193,9 +217,10 @@ connection_edge_destroy(circid_t circ_id, edge_connection_t *conn) log_info(LD_EDGE, "CircID %d: At an edge. Marking connection for close.", circ_id); if (conn->_base.type == CONN_TYPE_AP) { - connection_mark_unattached_ap(conn, END_STREAM_REASON_DESTROY); + entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn); + connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_DESTROY); control_event_stream_bandwidth(conn); - control_event_stream_status(conn, STREAM_EVENT_CLOSED, + control_event_stream_status(entry_conn, STREAM_EVENT_CLOSED, END_STREAM_REASON_DESTROY); conn->end_reason |= END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED; } else { @@ -203,8 +228,7 @@ connection_edge_destroy(circid_t circ_id, edge_connection_t *conn) conn->edge_has_sent_end = 1; conn->end_reason = END_STREAM_REASON_DESTROY; conn->end_reason |= END_STREAM_REASON_FLAG_ALREADY_SENT_CLOSED; - connection_mark_for_close(TO_CONN(conn)); - conn->_base.hold_open_until_flushed = 1; + connection_mark_and_flush(TO_CONN(conn)); } } conn->cpath_layer = NULL; @@ -348,7 +372,6 @@ connection_edge_finished_flushing(edge_connection_t *conn) switch (conn->_base.state) { case AP_CONN_STATE_OPEN: case EXIT_CONN_STATE_OPEN: - connection_stop_writing(TO_CONN(conn)); connection_edge_consider_sending_sendme(conn); return 0; case AP_CONN_STATE_SOCKS_WAIT: @@ -357,7 +380,7 @@ connection_edge_finished_flushing(edge_connection_t *conn) case AP_CONN_STATE_CIRCUIT_WAIT: case AP_CONN_STATE_CONNECT_WAIT: case AP_CONN_STATE_CONTROLLER_WAIT: - connection_stop_writing(TO_CONN(conn)); + case AP_CONN_STATE_RESOLVE_WAIT: return 0; default: log_warn(LD_BUG, "Called in unexpected state %d.",conn->_base.state); @@ -387,8 +410,9 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn) rep_hist_note_exit_stream_opened(conn->port); conn->state = EXIT_CONN_STATE_OPEN; - connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */ - if (connection_wants_to_flush(conn)) /* in case there are any queued relay + IF_HAS_NO_BUFFEREVENT(conn) + connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */ + if (connection_get_outbuf_len(conn)) /* in case there are any queued relay * cells */ connection_start_writing(conn); /* deliver a 'connected' relay cell back through the circuit. */ @@ -420,13 +444,79 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn) return connection_edge_process_inbuf(edge_conn, 1); } +/** Common code to connection_(ap|exit)_about_to_close. */ +static void +connection_edge_about_to_close(edge_connection_t *edge_conn) +{ + if (!edge_conn->edge_has_sent_end) { + connection_t *conn = TO_CONN(edge_conn); + log_warn(LD_BUG, "(Harmless.) Edge connection (marked at %s:%d) " + "hasn't sent end yet?", + conn->marked_for_close_file, conn->marked_for_close); + tor_fragile_assert(); + } +} + +/* Called when we're about to finally unlink and free an AP (client) + * connection: perform necessary accounting and cleanup */ +void +connection_ap_about_to_close(entry_connection_t *entry_conn) +{ + circuit_t *circ; + edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(entry_conn); + connection_t *conn = ENTRY_TO_CONN(entry_conn); + + if (entry_conn->socks_request->has_finished == 0) { + /* since conn gets removed right after this function finishes, + * there's no point trying to send back a reply at this point. */ + log_warn(LD_BUG,"Closing stream (marked at %s:%d) without sending" + " back a socks reply.", + conn->marked_for_close_file, conn->marked_for_close); + } + if (!edge_conn->end_reason) { + log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having" + " set end_reason.", + conn->marked_for_close_file, conn->marked_for_close); + } + if (entry_conn->dns_server_request) { + log_warn(LD_BUG,"Closing stream (marked at %s:%d) without having" + " replied to DNS request.", + conn->marked_for_close_file, conn->marked_for_close); + dnsserv_reject_request(entry_conn); + } + control_event_stream_bandwidth(edge_conn); + control_event_stream_status(entry_conn, STREAM_EVENT_CLOSED, + edge_conn->end_reason); + circ = circuit_get_by_edge_conn(edge_conn); + if (circ) + circuit_detach_stream(circ, edge_conn); +} + +/* Called when we're about to finally unlink and free an exit + * connection: perform necessary accounting and cleanup */ +void +connection_exit_about_to_close(edge_connection_t *edge_conn) +{ + circuit_t *circ; + connection_t *conn = TO_CONN(edge_conn); + + connection_edge_about_to_close(edge_conn); + + circ = circuit_get_by_edge_conn(edge_conn); + if (circ) + circuit_detach_stream(circ, edge_conn); + if (conn->state == EXIT_CONN_STATE_RESOLVING) { + connection_dns_remove(edge_conn); + } +} + /** Define a schedule for how long to wait between retrying * application connections. Rather than waiting a fixed amount of * time between each retry, we wait 10 seconds each for the first * two tries, and 15 seconds for each retry after * that. Hopefully this will improve the expected user experience. */ static int -compute_retry_timeout(edge_connection_t *conn) +compute_retry_timeout(entry_connection_t *conn) { int timeout = get_options()->CircuitStreamTimeout; if (timeout) /* if our config options override the default, use them */ @@ -449,41 +539,43 @@ void connection_ap_expire_beginning(void) { edge_connection_t *conn; + entry_connection_t *entry_conn; circuit_t *circ; time_t now = time(NULL); - or_options_t *options = get_options(); + const or_options_t *options = get_options(); int severity; int cutoff; int seconds_idle, seconds_since_born; smartlist_t *conns = get_connection_array(); - SMARTLIST_FOREACH_BEGIN(conns, connection_t *, c) { - if (c->type != CONN_TYPE_AP || c->marked_for_close) + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) { + if (base_conn->type != CONN_TYPE_AP || base_conn->marked_for_close) continue; - conn = TO_EDGE_CONN(c); + entry_conn = TO_ENTRY_CONN(base_conn); + conn = ENTRY_TO_EDGE_CONN(entry_conn); /* if it's an internal linked connection, don't yell its status. */ - severity = (tor_addr_is_null(&conn->_base.addr) && !conn->_base.port) + severity = (tor_addr_is_null(&base_conn->addr) && !base_conn->port) ? LOG_INFO : LOG_NOTICE; - seconds_idle = (int)( now - conn->_base.timestamp_lastread ); - seconds_since_born = (int)( now - conn->_base.timestamp_created ); + seconds_idle = (int)( now - base_conn->timestamp_lastread ); + seconds_since_born = (int)( now - base_conn->timestamp_created ); - if (conn->_base.state == AP_CONN_STATE_OPEN) + if (base_conn->state == AP_CONN_STATE_OPEN) continue; /* We already consider SocksTimeout in * connection_ap_handshake_attach_circuit(), but we need to consider * it here too because controllers that put streams in controller_wait * state never ask Tor to attach the circuit. */ - if (AP_CONN_STATE_IS_UNATTACHED(conn->_base.state)) { + if (AP_CONN_STATE_IS_UNATTACHED(base_conn->state)) { if (seconds_since_born >= options->SocksTimeout) { log_fn(severity, LD_APP, "Tried for %d seconds to get a connection to %s:%d. " "Giving up. (%s)", seconds_since_born, - safe_str_client(conn->socks_request->address), - conn->socks_request->port, - conn_state_to_string(CONN_TYPE_AP, conn->_base.state)); - connection_mark_unattached_ap(conn, END_STREAM_REASON_TIMEOUT); + safe_str_client(entry_conn->socks_request->address), + entry_conn->socks_request->port, + conn_state_to_string(CONN_TYPE_AP, base_conn->state)); + connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT); } continue; } @@ -491,14 +583,14 @@ connection_ap_expire_beginning(void) /* We're in state connect_wait or resolve_wait now -- waiting for a * reply to our relay cell. See if we want to retry/give up. */ - cutoff = compute_retry_timeout(conn); + cutoff = compute_retry_timeout(entry_conn); if (seconds_idle < cutoff) continue; circ = circuit_get_by_edge_conn(conn); if (!circ) { /* it's vanished? */ log_info(LD_APP,"Conn is waiting (address %s), but lost its circ.", - safe_str_client(conn->socks_request->address)); - connection_mark_unattached_ap(conn, END_STREAM_REASON_TIMEOUT); + safe_str_client(entry_conn->socks_request->address)); + connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT); continue; } if (circ->purpose == CIRCUIT_PURPOSE_C_REND_JOINED) { @@ -507,9 +599,9 @@ connection_ap_expire_beginning(void) "Rend stream is %d seconds late. Giving up on address" " '%s.onion'.", seconds_idle, - safe_str_client(conn->socks_request->address)); + safe_str_client(entry_conn->socks_request->address)); connection_edge_end(conn, END_STREAM_REASON_TIMEOUT); - connection_mark_unattached_ap(conn, END_STREAM_REASON_TIMEOUT); + connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT); } continue; } @@ -518,9 +610,10 @@ connection_ap_expire_beginning(void) "We tried for %d seconds to connect to '%s' using exit %s." " Retrying on a new circuit.", seconds_idle, - safe_str_client(conn->socks_request->address), + safe_str_client(entry_conn->socks_request->address), conn->cpath_layer ? - extend_info_describe(conn->cpath_layer->extend_info): "*unnamed*"); + extend_info_describe(conn->cpath_layer->extend_info): + "*unnamed*"); /* send an end down the circuit */ connection_edge_end(conn, END_STREAM_REASON_TIMEOUT); /* un-mark it as ending, since we're going to reuse it */ @@ -534,15 +627,16 @@ connection_ap_expire_beginning(void) circ->timestamp_dirty -= options->MaxCircuitDirtiness; /* give our stream another 'cutoff' seconds to try */ conn->_base.timestamp_lastread += cutoff; - if (conn->num_socks_retries < 250) /* avoid overflow */ - conn->num_socks_retries++; + if (entry_conn->num_socks_retries < 250) /* avoid overflow */ + entry_conn->num_socks_retries++; /* move it back into 'pending' state, and try to attach. */ - if (connection_ap_detach_retriable(conn, TO_ORIGIN_CIRCUIT(circ), + if (connection_ap_detach_retriable(entry_conn, TO_ORIGIN_CIRCUIT(circ), END_STREAM_REASON_TIMEOUT)<0) { - if (!conn->_base.marked_for_close) - connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH); + if (!base_conn->marked_for_close) + connection_mark_unattached_ap(entry_conn, + END_STREAM_REASON_CANT_ATTACH); } - } SMARTLIST_FOREACH_END(conn); + } SMARTLIST_FOREACH_END(base_conn); } /** Tell any AP streams that are waiting for a new circuit to try again, @@ -551,7 +645,7 @@ connection_ap_expire_beginning(void) void connection_ap_attach_pending(void) { - edge_connection_t *edge_conn; + entry_connection_t *entry_conn; smartlist_t *conns = get_connection_array(); SMARTLIST_FOREACH(conns, connection_t *, conn, { @@ -559,10 +653,10 @@ connection_ap_attach_pending(void) conn->type != CONN_TYPE_AP || conn->state != AP_CONN_STATE_CIRCUIT_WAIT) continue; - edge_conn = TO_EDGE_CONN(conn); - if (connection_ap_handshake_attach_circuit(edge_conn) < 0) { - if (!edge_conn->_base.marked_for_close) - connection_mark_unattached_ap(edge_conn, + entry_conn = TO_ENTRY_CONN(conn); + if (connection_ap_handshake_attach_circuit(entry_conn) < 0) { + if (!conn->marked_for_close) + connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_CANT_ATTACH); } }); @@ -577,7 +671,7 @@ void connection_ap_fail_onehop(const char *failed_digest, cpath_build_state_t *build_state) { - edge_connection_t *edge_conn; + entry_connection_t *entry_conn; char digest[DIGEST_LEN]; smartlist_t *conns = get_connection_array(); SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { @@ -585,27 +679,27 @@ connection_ap_fail_onehop(const char *failed_digest, conn->type != CONN_TYPE_AP || conn->state != AP_CONN_STATE_CIRCUIT_WAIT) continue; - edge_conn = TO_EDGE_CONN(conn); - if (!edge_conn->want_onehop) + entry_conn = TO_ENTRY_CONN(conn); + if (!entry_conn->want_onehop) continue; - if (hexdigest_to_digest(edge_conn->chosen_exit_name, digest) < 0 || + if (hexdigest_to_digest(entry_conn->chosen_exit_name, digest) < 0 || tor_memneq(digest, failed_digest, DIGEST_LEN)) continue; if (tor_digest_is_zero(digest)) { /* we don't know the digest; have to compare addr:port */ tor_addr_t addr; if (!build_state || !build_state->chosen_exit || - !edge_conn->socks_request || !edge_conn->socks_request->address) + !entry_conn->socks_request || !entry_conn->socks_request->address) continue; - if (tor_addr_from_str(&addr, edge_conn->socks_request->address)<0 || + if (tor_addr_parse(&addr, entry_conn->socks_request->address)<0 || !tor_addr_eq(&build_state->chosen_exit->addr, &addr) || - build_state->chosen_exit->port != edge_conn->socks_request->port) + build_state->chosen_exit->port != entry_conn->socks_request->port) continue; } log_info(LD_APP, "Closing one-hop stream to '%s/%s' because the OR conn " - "just failed.", edge_conn->chosen_exit_name, - edge_conn->socks_request->address); - connection_mark_unattached_ap(edge_conn, END_STREAM_REASON_TIMEOUT); + "just failed.", entry_conn->chosen_exit_name, + entry_conn->socks_request->address); + connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TIMEOUT); } SMARTLIST_FOREACH_END(conn); } @@ -616,8 +710,8 @@ connection_ap_fail_onehop(const char *failed_digest, void circuit_discard_optional_exit_enclaves(extend_info_t *info) { - edge_connection_t *edge_conn; - routerinfo_t *r1, *r2; + entry_connection_t *entry_conn; + const node_t *r1, *r2; smartlist_t *conns = get_connection_array(); SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { @@ -625,32 +719,32 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info) conn->type != CONN_TYPE_AP || conn->state != AP_CONN_STATE_CIRCUIT_WAIT) continue; - edge_conn = TO_EDGE_CONN(conn); - if (!edge_conn->chosen_exit_optional && - !edge_conn->chosen_exit_retries) + entry_conn = TO_ENTRY_CONN(conn); + if (!entry_conn->chosen_exit_optional && + !entry_conn->chosen_exit_retries) continue; - r1 = router_get_by_nickname(edge_conn->chosen_exit_name, 0); - r2 = router_get_by_digest(info->identity_digest); + r1 = node_get_by_nickname(entry_conn->chosen_exit_name, 0); + r2 = node_get_by_id(info->identity_digest); if (!r1 || !r2 || r1 != r2) continue; - tor_assert(edge_conn->socks_request); - if (edge_conn->chosen_exit_optional) { + tor_assert(entry_conn->socks_request); + if (entry_conn->chosen_exit_optional) { log_info(LD_APP, "Giving up on enclave exit '%s' for destination %s.", - safe_str_client(edge_conn->chosen_exit_name), - escaped_safe_str_client(edge_conn->socks_request->address)); - edge_conn->chosen_exit_optional = 0; - tor_free(edge_conn->chosen_exit_name); /* clears it */ + safe_str_client(entry_conn->chosen_exit_name), + escaped_safe_str_client(entry_conn->socks_request->address)); + entry_conn->chosen_exit_optional = 0; + tor_free(entry_conn->chosen_exit_name); /* clears it */ /* if this port is dangerous, warn or reject it now that we don't * think it'll be using an enclave. */ - consider_plaintext_ports(edge_conn, edge_conn->socks_request->port); + consider_plaintext_ports(entry_conn, entry_conn->socks_request->port); } - if (edge_conn->chosen_exit_retries) { - if (--edge_conn->chosen_exit_retries == 0) { /* give up! */ - clear_trackexithost_mappings(edge_conn->chosen_exit_name); - tor_free(edge_conn->chosen_exit_name); /* clears it */ + if (entry_conn->chosen_exit_retries) { + if (--entry_conn->chosen_exit_retries == 0) { /* give up! */ + clear_trackexithost_mappings(entry_conn->chosen_exit_name); + tor_free(entry_conn->chosen_exit_name); /* clears it */ /* if this port is dangerous, warn or reject it now that we don't * think it'll be using an enclave. */ - consider_plaintext_ports(edge_conn, edge_conn->socks_request->port); + consider_plaintext_ports(entry_conn, entry_conn->socks_request->port); } } } SMARTLIST_FOREACH_END(conn); @@ -664,20 +758,27 @@ circuit_discard_optional_exit_enclaves(extend_info_t *info) * Returns -1 on err, 1 on success, 0 on not-yet-sure. */ int -connection_ap_detach_retriable(edge_connection_t *conn, origin_circuit_t *circ, +connection_ap_detach_retriable(entry_connection_t *conn, + origin_circuit_t *circ, int reason) { control_event_stream_status(conn, STREAM_EVENT_FAILED_RETRIABLE, reason); - conn->_base.timestamp_lastread = time(NULL); + ENTRY_TO_CONN(conn)->timestamp_lastread = time(NULL); + + if (conn->pending_optimistic_data) { + generic_buffer_set_to_copy(&conn->sending_optimistic_data, + conn->pending_optimistic_data); + } + if (!get_options()->LeaveStreamsUnattached || conn->use_begindir) { /* If we're attaching streams ourself, or if this connection is * a tunneled directory connection, then just attach it. */ - conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT; - circuit_detach_stream(TO_CIRCUIT(circ),conn); + ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CIRCUIT_WAIT; + circuit_detach_stream(TO_CIRCUIT(circ),ENTRY_TO_EDGE_CONN(conn)); return connection_ap_handshake_attach_circuit(conn); } else { - conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT; - circuit_detach_stream(TO_CIRCUIT(circ),conn); + ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CONTROLLER_WAIT; + circuit_detach_stream(TO_CIRCUIT(circ),ENTRY_TO_EDGE_CONN(conn)); return 0; } } @@ -825,7 +926,7 @@ clear_trackexithost_mappings(const char *exitname) * host is unknown or no longer allowed, or for which the source address * is no longer in trackexithosts. */ void -addressmap_clear_excluded_trackexithosts(or_options_t *options) +addressmap_clear_excluded_trackexithosts(const or_options_t *options) { const routerset_t *allow_nodes = options->ExitNodes; const routerset_t *exclude_nodes = options->_ExcludeExitNodesUnion; @@ -841,9 +942,12 @@ 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")) { + if (!target) { + /* DNS resolving in progress */ + continue; + } else if (strcmpend(target, ".exit")) { /* Not a .exit mapping */ continue; } else if (ent->source != ADDRMAPSRC_TRACKEXIT) { @@ -854,15 +958,15 @@ addressmap_clear_excluded_trackexithosts(or_options_t *options) if (len < 6) continue; /* malformed. */ dot = target + len - 6; /* dot now points to just before .exit */ - while(dot > target && *dot != '.') - dot--; + while (dot > target && *dot != '.') + dot--; if (*dot == '.') dot++; nodename = tor_strndup(dot, len-5-(dot-target));; - 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); @@ -876,7 +980,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; @@ -1323,7 +1427,6 @@ static char * addressmap_get_virtual_address(int type) { char buf[64]; - struct in_addr in; tor_assert(addressmap); if (type == RESOLVED_TYPE_HOSTNAME) { @@ -1337,6 +1440,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. */ @@ -1528,9 +1632,9 @@ addressmap_get_mappings(smartlist_t *sl, time_t min_expires, /** Check if <b>conn</b> is using a dangerous port. Then warn and/or * reject depending on our config options. */ static int -consider_plaintext_ports(edge_connection_t *conn, uint16_t port) +consider_plaintext_ports(entry_connection_t *conn, uint16_t port) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); int reject = smartlist_string_num_isin(options->RejectPlaintextPorts, port); if (smartlist_string_num_isin(options->WarnPlaintextPorts, port)) { @@ -1563,14 +1667,14 @@ consider_plaintext_ports(edge_connection_t *conn, uint16_t port) * documentation for arguments and return value. */ int -connection_ap_rewrite_and_attach_if_allowed(edge_connection_t *conn, +connection_ap_rewrite_and_attach_if_allowed(entry_connection_t *conn, origin_circuit_t *circ, crypt_path_t *cpath) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); if (options->LeaveStreamsUnattached) { - conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT; + ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CONTROLLER_WAIT; return 0; } return connection_ap_handshake_rewrite_and_attach(conn, circ, cpath); @@ -1592,13 +1696,13 @@ connection_ap_rewrite_and_attach_if_allowed(edge_connection_t *conn, * <b>cpath</b> is NULL. */ int -connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, +connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, origin_circuit_t *circ, crypt_path_t *cpath) { socks_request_t *socks = conn->socks_request; hostname_type_t addresstype; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); struct in_addr addr_tmp; /* We set this to true if this is an address we should automatically * remap to a local address in VirtualAddrNetwork */ @@ -1609,6 +1713,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, address, and we remap it to one because of an entry in the addressmap. */ int remapped_to_exit = 0; time_t now = time(NULL); + connection_t *base_conn = ENTRY_TO_CONN(conn); tor_strlower(socks->address); /* normalize it */ strlcpy(orig_address, socks->address, sizeof(orig_address)); @@ -1616,6 +1721,9 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, safe_str_client(socks->address), socks->port); + if (! conn->original_dest_address) + conn->original_dest_address = tor_strdup(conn->socks_request->address); + if (socks->command == SOCKS_COMMAND_RESOLVE && !tor_inet_aton(socks->address, &addr_tmp) && options->AutomapHostsOnResolve && options->AutomapHostsSuffixes) { @@ -1661,7 +1769,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, /* Don't let people try to do a reverse lookup on 10.0.0.1. */ tor_addr_t addr; int ok; - ok = tor_addr_parse_reverse_lookup_name( + ok = tor_addr_parse_PTR_name( &addr, socks->address, AF_UNSPEC, 1); if (ok == 1 && tor_addr_is_internal(&addr, 0)) { connection_ap_handshake_socks_resolved(conn, RESOLVED_TYPE_ERROR, @@ -1721,15 +1829,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; @@ -1744,15 +1851,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)); @@ -1760,7 +1868,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)); @@ -1813,7 +1921,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, if (options->ClientRejectInternalAddresses && !conn->use_begindir && !conn->chosen_exit_name && !circ) { tor_addr_t addr; - if (tor_addr_from_str(&addr, socks->address) >= 0 && + if (tor_addr_parse(&addr, socks->address) >= 0 && tor_addr_is_internal(&addr, 0)) { /* If this is an explicit private address with no chosen exit node, * then we really don't want to try to connect to it. That's @@ -1835,17 +1943,16 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, if (!conn->use_begindir && !conn->chosen_exit_name && !circ) { /* see if we can find a suitable enclave exit */ - routerinfo_t *r = + const node_t *r = router_find_exact_exit_enclave(socks->address, socks->port); if (r) { log_info(LD_APP, "Redirecting address %s to exit at enclave router %s", - safe_str_client(socks->address), - router_describe(r)); + safe_str_client(socks->address), node_describe(r)); /* use the hex digest, not nickname, in case there are two routers with this nickname */ conn->chosen_exit_name = - tor_strdup(hex_str(r->cache_info.identity_digest, DIGEST_LEN)); + tor_strdup(hex_str(r->identity, DIGEST_LEN)); conn->chosen_exit_optional = 1; } } @@ -1865,12 +1972,12 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, } else { tor_fragile_assert(); } - conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT; + base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT; if ((circ && connection_ap_handshake_attach_chosen_circuit( conn, circ, cpath) < 0) || (!circ && connection_ap_handshake_attach_circuit(conn) < 0)) { - if (!conn->_base.marked_for_close) + if (!base_conn->marked_for_close) connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH); return -1; } @@ -1880,6 +1987,7 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, rend_cache_entry_t *entry; int r; rend_service_authorization_t *client_auth; + rend_data_t *rend_data; tor_assert(!automap); if (SOCKS_COMMAND_IS_RESOLVE(socks->command)) { /* if it's a resolve request, fail it right now, rather than @@ -1901,16 +2009,17 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, return -1; } - conn->rend_data = tor_malloc_zero(sizeof(rend_data_t)); - strlcpy(conn->rend_data->onion_address, socks->address, - sizeof(conn->rend_data->onion_address)); + ENTRY_TO_EDGE_CONN(conn)->rend_data = rend_data = + tor_malloc_zero(sizeof(rend_data_t)); + strlcpy(rend_data->onion_address, socks->address, + sizeof(rend_data->onion_address)); log_info(LD_REND,"Got a hidden service request for ID '%s'", - safe_str_client(conn->rend_data->onion_address)); + safe_str_client(rend_data->onion_address)); /* see if we already have it cached */ - r = rend_cache_lookup_entry(conn->rend_data->onion_address, -1, &entry); + r = rend_cache_lookup_entry(rend_data->onion_address, -1, &entry); if (r<0) { log_warn(LD_BUG,"Invalid service name '%s'", - safe_str_client(conn->rend_data->onion_address)); + safe_str_client(rend_data->onion_address)); connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); return -1; } @@ -1921,24 +2030,24 @@ connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, /* Look up if we have client authorization for it. */ client_auth = rend_client_lookup_service_authorization( - conn->rend_data->onion_address); + rend_data->onion_address); if (client_auth) { log_info(LD_REND, "Using previously configured client authorization " "for hidden service request."); - memcpy(conn->rend_data->descriptor_cookie, + memcpy(rend_data->descriptor_cookie, client_auth->descriptor_cookie, REND_DESC_COOKIE_LEN); - conn->rend_data->auth_type = client_auth->auth_type; + rend_data->auth_type = client_auth->auth_type; } if (r==0) { - conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT; + base_conn->state = AP_CONN_STATE_RENDDESC_WAIT; log_info(LD_REND, "Unknown descriptor %s. Fetching.", - safe_str_client(conn->rend_data->onion_address)); - rend_client_refetch_v2_renddesc(conn->rend_data); + safe_str_client(rend_data->onion_address)); + rend_client_refetch_v2_renddesc(rend_data); } else { /* r > 0 */ - conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT; + base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT; log_info(LD_REND, "Descriptor is here. Great."); if (connection_ap_handshake_attach_circuit(conn) < 0) { - if (!conn->_base.marked_for_close) + if (!base_conn->marked_for_close) connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH); return -1; } @@ -1960,10 +2069,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) { @@ -1984,7 +2093,7 @@ get_pf_socket(void) * else return 0. */ static int -connection_ap_get_original_destination(edge_connection_t *conn, +connection_ap_get_original_destination(entry_connection_t *conn, socks_request_t *req) { #ifdef TRANS_NETFILTER @@ -1993,9 +2102,9 @@ connection_ap_get_original_destination(edge_connection_t *conn, socklen_t orig_dst_len = sizeof(orig_dst); tor_addr_t addr; - if (getsockopt(conn->_base.s, SOL_IP, SO_ORIGINAL_DST, + if (getsockopt(ENTRY_TO_CONN(conn)->s, SOL_IP, SO_ORIGINAL_DST, (struct sockaddr*)&orig_dst, &orig_dst_len) < 0) { - int e = tor_socket_errno(conn->_base.s); + int e = tor_socket_errno(ENTRY_TO_CONN(conn)->s); log_warn(LD_NET, "getsockopt() failed: %s", tor_socket_strerror(e)); return -1; } @@ -2012,9 +2121,9 @@ connection_ap_get_original_destination(edge_connection_t *conn, tor_addr_t addr; int pf = -1; - if (getsockname(conn->_base.s, (struct sockaddr*)&proxy_addr, + if (getsockname(ENTRY_TO_CONN(conn)->s, (struct sockaddr*)&proxy_addr, &proxy_addr_len) < 0) { - int e = tor_socket_errno(conn->_base.s); + int e = tor_socket_errno(ENTRY_TO_CONN(conn)->s); log_warn(LD_NET, "getsockname() to determine transocks destination " "failed: %s", tor_socket_strerror(e)); return -1; @@ -2026,16 +2135,16 @@ connection_ap_get_original_destination(edge_connection_t *conn, if (proxy_sa->sa_family == AF_INET) { struct sockaddr_in *sin = (struct sockaddr_in *)proxy_sa; pnl.af = AF_INET; - pnl.saddr.v4.s_addr = tor_addr_to_ipv4n(&conn->_base.addr); - pnl.sport = htons(conn->_base.port); + pnl.saddr.v4.s_addr = tor_addr_to_ipv4n(&ENTRY_TO_CONN(conn)->addr); + pnl.sport = htons(ENTRY_TO_CONN(conn)->port); pnl.daddr.v4.s_addr = sin->sin_addr.s_addr; pnl.dport = sin->sin_port; } else if (proxy_sa->sa_family == AF_INET6) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)proxy_sa; pnl.af = AF_INET6; - memcpy(&pnl.saddr.v6, tor_addr_to_in6(&conn->_base.addr), + memcpy(&pnl.saddr.v6, tor_addr_to_in6(&ENTRY_TO_CONN(conn)->addr), sizeof(struct in6_addr)); - pnl.sport = htons(conn->_base.port); + pnl.sport = htons(ENTRY_TO_CONN(conn)->port); memcpy(&pnl.daddr.v6, &sin6->sin6_addr, sizeof(struct in6_addr)); pnl.dport = sin6->sin6_port; } else { @@ -2086,38 +2195,43 @@ connection_ap_get_original_destination(edge_connection_t *conn, * else return 0. */ static int -connection_ap_handshake_process_socks(edge_connection_t *conn) +connection_ap_handshake_process_socks(entry_connection_t *conn) { socks_request_t *socks; int sockshere; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); + int had_reply = 0; + connection_t *base_conn = ENTRY_TO_CONN(conn); tor_assert(conn); - tor_assert(conn->_base.type == CONN_TYPE_AP); - tor_assert(conn->_base.state == AP_CONN_STATE_SOCKS_WAIT); + tor_assert(base_conn->type == CONN_TYPE_AP); + tor_assert(base_conn->state == AP_CONN_STATE_SOCKS_WAIT); tor_assert(conn->socks_request); socks = conn->socks_request; log_debug(LD_APP,"entered."); - sockshere = fetch_from_buf_socks(conn->_base.inbuf, socks, - options->TestSocks, options->SafeSocks); + IF_HAS_BUFFEREVENT(base_conn, { + struct evbuffer *input = bufferevent_get_input(base_conn->bufev); + sockshere = fetch_from_evbuffer_socks(input, socks, + options->TestSocks, options->SafeSocks); + }) ELSE_IF_NO_BUFFEREVENT { + sockshere = fetch_from_buf_socks(base_conn->inbuf, socks, + options->TestSocks, options->SafeSocks); + }; + + if (socks->replylen) { + had_reply = 1; + connection_write_to_buf((const char*)socks->reply, socks->replylen, + base_conn); + socks->replylen = 0; + } + if (sockshere == 0) { - if (socks->replylen) { - connection_write_to_buf(socks->reply, socks->replylen, TO_CONN(conn)); - /* zero it out so we can do another round of negotiation */ - socks->replylen = 0; - } else { - log_debug(LD_APP,"socks handshake not all here yet."); - } + log_debug(LD_APP,"socks handshake not all here yet."); return 0; } else if (sockshere == -1) { - if (socks->replylen) { /* we should send reply back */ - log_debug(LD_APP,"reply is already set for us. Using it."); - connection_ap_handshake_socks_reply(conn, socks->reply, socks->replylen, - END_STREAM_REASON_SOCKSPROTOCOL); - - } else { + if (!had_reply) { log_warn(LD_APP,"Fetching socks handshake failed. Closing."); connection_ap_handshake_socks_reply(conn, NULL, 0, END_STREAM_REASON_SOCKSPROTOCOL); @@ -2144,12 +2258,11 @@ connection_ap_handshake_process_socks(edge_connection_t *conn) * for close), else return 0. */ int -connection_ap_process_transparent(edge_connection_t *conn) +connection_ap_process_transparent(entry_connection_t *conn) { socks_request_t *socks; tor_assert(conn); - tor_assert(conn->_base.type == CONN_TYPE_AP); tor_assert(conn->socks_request); socks = conn->socks_request; @@ -2185,7 +2298,7 @@ connection_ap_process_transparent(edge_connection_t *conn) * for close), else return 0. */ static int -connection_ap_process_natd(edge_connection_t *conn) +connection_ap_process_natd(entry_connection_t *conn) { char tmp_buf[36], *tbuf, *daddr; size_t tlen = 30; @@ -2193,8 +2306,7 @@ connection_ap_process_natd(edge_connection_t *conn) socks_request_t *socks; tor_assert(conn); - tor_assert(conn->_base.type == CONN_TYPE_AP); - tor_assert(conn->_base.state == AP_CONN_STATE_NATD_WAIT); + tor_assert(ENTRY_TO_CONN(conn)->state == AP_CONN_STATE_NATD_WAIT); tor_assert(conn->socks_request); socks = conn->socks_request; @@ -2202,7 +2314,7 @@ connection_ap_process_natd(edge_connection_t *conn) /* look for LF-terminated "[DEST ip_addr port]" * where ip_addr is a dotted-quad and port is in string form */ - err = fetch_from_buf_line(conn->_base.inbuf, tmp_buf, &tlen); + err = connection_fetch_from_buf_line(ENTRY_TO_CONN(conn), tmp_buf, &tlen); if (err == 0) return 0; if (err < 0) { @@ -2246,7 +2358,7 @@ connection_ap_process_natd(edge_connection_t *conn) control_event_stream_status(conn, STREAM_EVENT_NEW, 0); - conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT; + ENTRY_TO_CONN(conn)->state = AP_CONN_STATE_CIRCUIT_WAIT; return connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL); } @@ -2276,28 +2388,46 @@ get_unique_stream_id_by_circ(origin_circuit_t *circ) return test_stream_id; } +/** Return true iff <b>conn</b> is linked to a circuit and configured to use + * an exit that supports optimistic data. */ +static int +connection_ap_supports_optimistic_data(const entry_connection_t *conn) +{ + const edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn); + /* We can only send optimistic data if we're connected to an open + general circuit. */ + if (edge_conn->on_circuit == NULL || + edge_conn->on_circuit->state != CIRCUIT_STATE_OPEN || + edge_conn->on_circuit->purpose != CIRCUIT_PURPOSE_C_GENERAL) + return 0; + + return conn->may_use_optimistic_data; +} + /** Write a relay begin cell, using destaddr and destport from ap_conn's * socks_request field, and send it down circ. * * If ap_conn is broken, mark it for close and return -1. Else return 0. */ int -connection_ap_handshake_send_begin(edge_connection_t *ap_conn) +connection_ap_handshake_send_begin(entry_connection_t *ap_conn) { char payload[CELL_PAYLOAD_SIZE]; int payload_len; int begin_type; origin_circuit_t *circ; - tor_assert(ap_conn->on_circuit); - circ = TO_ORIGIN_CIRCUIT(ap_conn->on_circuit); + edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(ap_conn); + connection_t *base_conn = TO_CONN(edge_conn); + tor_assert(edge_conn->on_circuit); + circ = TO_ORIGIN_CIRCUIT(edge_conn->on_circuit); - tor_assert(ap_conn->_base.type == CONN_TYPE_AP); - tor_assert(ap_conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT); + tor_assert(base_conn->type == CONN_TYPE_AP); + tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT); tor_assert(ap_conn->socks_request); tor_assert(SOCKS_COMMAND_IS_CONNECT(ap_conn->socks_request->command)); - ap_conn->stream_id = get_unique_stream_id_by_circ(circ); - if (ap_conn->stream_id==0) { + edge_conn->stream_id = get_unique_stream_id_by_circ(circ); + if (edge_conn->stream_id==0) { /* XXXX023 Instead of closing this stream, we should make it get * retried on another circuit. */ connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL); @@ -2315,8 +2445,10 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn) ap_conn->socks_request->port); payload_len = (int)strlen(payload)+1; - log_debug(LD_APP, - "Sending relay cell to begin stream %d.", ap_conn->stream_id); + log_info(LD_APP, + "Sending relay cell %d to begin stream %d.", + (int)ap_conn->use_begindir, + edge_conn->stream_id); begin_type = ap_conn->use_begindir ? RELAY_COMMAND_BEGIN_DIR : RELAY_COMMAND_BEGIN; @@ -2324,17 +2456,31 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn) tor_assert(circ->build_state->onehop_tunnel == 0); } - if (connection_edge_send_command(ap_conn, begin_type, + if (connection_edge_send_command(edge_conn, begin_type, begin_type == RELAY_COMMAND_BEGIN ? payload : NULL, begin_type == RELAY_COMMAND_BEGIN ? payload_len : 0) < 0) return -1; /* circuit is closed, don't continue */ - ap_conn->package_window = STREAMWINDOW_START; - ap_conn->deliver_window = STREAMWINDOW_START; - ap_conn->_base.state = AP_CONN_STATE_CONNECT_WAIT; + edge_conn->package_window = STREAMWINDOW_START; + edge_conn->deliver_window = STREAMWINDOW_START; + base_conn->state = AP_CONN_STATE_CONNECT_WAIT; log_info(LD_APP,"Address/port sent, ap socket %d, n_circ_id %d", - ap_conn->_base.s, circ->_base.n_circ_id); + base_conn->s, circ->_base.n_circ_id); control_event_stream_status(ap_conn, STREAM_EVENT_SENT_CONNECT, 0); + + /* If there's queued-up data, send it now */ + if ((connection_get_inbuf_len(base_conn) || + ap_conn->sending_optimistic_data) && + connection_ap_supports_optimistic_data(ap_conn)) { + log_info(LD_APP, "Sending up to %ld + %ld bytes of queued-up data", + (long)connection_get_inbuf_len(base_conn), + ap_conn->sending_optimistic_data ? + (long)generic_buffer_len(ap_conn->sending_optimistic_data) : 0); + if (connection_edge_package_raw_inbuf(edge_conn, 1, NULL) < 0) { + connection_mark_for_close(base_conn); + } + } + return 0; } @@ -2344,25 +2490,27 @@ connection_ap_handshake_send_begin(edge_connection_t *ap_conn) * If ap_conn is broken, mark it for close and return -1. Else return 0. */ int -connection_ap_handshake_send_resolve(edge_connection_t *ap_conn) +connection_ap_handshake_send_resolve(entry_connection_t *ap_conn) { int payload_len, command; const char *string_addr; char inaddr_buf[REVERSE_LOOKUP_NAME_BUF_LEN]; origin_circuit_t *circ; - tor_assert(ap_conn->on_circuit); - circ = TO_ORIGIN_CIRCUIT(ap_conn->on_circuit); + edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(ap_conn); + connection_t *base_conn = TO_CONN(edge_conn); + tor_assert(edge_conn->on_circuit); + circ = TO_ORIGIN_CIRCUIT(edge_conn->on_circuit); - tor_assert(ap_conn->_base.type == CONN_TYPE_AP); - tor_assert(ap_conn->_base.state == AP_CONN_STATE_CIRCUIT_WAIT); + tor_assert(base_conn->type == CONN_TYPE_AP); + tor_assert(base_conn->state == AP_CONN_STATE_CIRCUIT_WAIT); tor_assert(ap_conn->socks_request); tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_C_GENERAL); command = ap_conn->socks_request->command; tor_assert(SOCKS_COMMAND_IS_RESOLVE(command)); - ap_conn->stream_id = get_unique_stream_id_by_circ(circ); - if (ap_conn->stream_id==0) { + edge_conn->stream_id = get_unique_stream_id_by_circ(circ); + if (edge_conn->stream_id==0) { /* XXXX023 Instead of closing this stream, we should make it get * retried on another circuit. */ connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL); @@ -2385,7 +2533,7 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn) /* We're doing a reverse lookup. The input could be an IP address, or * could be an .in-addr.arpa or .ip6.arpa address */ - r = tor_addr_parse_reverse_lookup_name(&addr, a, AF_INET, 1); + r = tor_addr_parse_PTR_name(&addr, a, AF_INET, 1); if (r <= 0) { log_warn(LD_APP, "Rejecting ill-formed reverse lookup of %s", safe_str_client(a)); @@ -2393,7 +2541,7 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn) return -1; } - r = tor_addr_to_reverse_lookup_name(inaddr_buf, sizeof(inaddr_buf), &addr); + r = tor_addr_to_PTR_name(inaddr_buf, sizeof(inaddr_buf), &addr); if (r < 0) { log_warn(LD_BUG, "Couldn't generate reverse lookup hostname of %s", safe_str_client(a)); @@ -2407,18 +2555,18 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn) } log_debug(LD_APP, - "Sending relay cell to begin stream %d.", ap_conn->stream_id); + "Sending relay cell to begin stream %d.", edge_conn->stream_id); - if (connection_edge_send_command(ap_conn, + if (connection_edge_send_command(edge_conn, RELAY_COMMAND_RESOLVE, string_addr, payload_len) < 0) return -1; /* circuit is closed, don't continue */ - tor_free(ap_conn->_base.address); /* Maybe already set by dnsserv. */ - ap_conn->_base.address = tor_strdup("(Tor_internal)"); - ap_conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT; + tor_free(base_conn->address); /* Maybe already set by dnsserv. */ + base_conn->address = tor_strdup("(Tor_internal)"); + base_conn->state = AP_CONN_STATE_RESOLVE_WAIT; log_info(LD_APP,"Address sent for resolve, ap socket %d, n_circ_id %d", - ap_conn->_base.s, circ->_base.n_circ_id); + base_conn->s, circ->_base.n_circ_id); control_event_stream_status(ap_conn, STREAM_EVENT_NEW, 0); control_event_stream_status(ap_conn, STREAM_EVENT_SENT_RESOLVE, 0); return 0; @@ -2429,19 +2577,25 @@ connection_ap_handshake_send_resolve(edge_connection_t *ap_conn) * and call connection_ap_handshake_attach_circuit(conn) on it. * * Return the other end of the linked connection pair, or -1 if error. + * DOCDOC partner. */ -edge_connection_t * -connection_ap_make_link(char *address, uint16_t port, - const char *digest, int use_begindir, int want_onehop) +entry_connection_t * +connection_ap_make_link(connection_t *partner, + char *address, uint16_t port, + const char *digest, + int session_group, int isolation_flags, + int use_begindir, int want_onehop) { - edge_connection_t *conn; + entry_connection_t *conn; + connection_t *base_conn; log_info(LD_APP,"Making internal %s tunnel to %s:%d ...", want_onehop ? "direct" : "anonymized", safe_str_client(address), port); - conn = edge_connection_new(CONN_TYPE_AP, AF_INET); - conn->_base.linked = 1; /* so that we can add it safely below. */ + conn = entry_connection_new(CONN_TYPE_AP, AF_INET); + base_conn = ENTRY_TO_CONN(conn); + base_conn->linked = 1; /* so that we can add it safely below. */ /* populate conn->socks_request */ @@ -2462,22 +2616,30 @@ connection_ap_make_link(char *address, uint16_t port, digest, DIGEST_LEN); } - conn->_base.address = tor_strdup("(Tor_internal)"); - tor_addr_make_unspec(&conn->_base.addr); - conn->_base.port = 0; + /* Populate isolation fields. */ + conn->socks_request->listener_type = CONN_TYPE_DIR_LISTENER; + conn->original_dest_address = tor_strdup(address); + conn->session_group = session_group; + conn->isolation_flags = isolation_flags; - if (connection_add(TO_CONN(conn)) < 0) { /* no space, forget it */ - connection_free(TO_CONN(conn)); + base_conn->address = tor_strdup("(Tor_internal)"); + tor_addr_make_unspec(&base_conn->addr); + base_conn->port = 0; + + connection_link_connections(partner, base_conn); + + if (connection_add(base_conn) < 0) { /* no space, forget it */ + connection_free(base_conn); return NULL; } - conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT; + base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT; control_event_stream_status(conn, STREAM_EVENT_NEW, 0); /* attaching to a dirty circuit is fine */ if (connection_ap_handshake_attach_circuit(conn) < 0) { - if (!conn->_base.marked_for_close) + if (!base_conn->marked_for_close) connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH); return NULL; } @@ -2490,7 +2652,7 @@ connection_ap_make_link(char *address, uint16_t port, * or resolve error. Takes the same arguments as does * connection_ap_handshake_socks_resolved(). */ static void -tell_controller_about_resolved_result(edge_connection_t *conn, +tell_controller_about_resolved_result(entry_connection_t *conn, int answer_type, size_t answer_len, const char *answer, @@ -2502,13 +2664,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); @@ -2531,7 +2691,7 @@ tell_controller_about_resolved_result(edge_connection_t *conn, /* XXXX023 the use of the ttl and expires fields is nutty. Let's make this * interface and those that use it less ugly. */ void -connection_ap_handshake_socks_resolved(edge_connection_t *conn, +connection_ap_handshake_socks_resolved(entry_connection_t *conn, int answer_type, size_t answer_len, const uint8_t *answer, @@ -2556,7 +2716,7 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn, } } - if (conn->is_dns_request) { + if (ENTRY_TO_EDGE_CONN(conn)->is_dns_request) { if (conn->dns_server_request) { /* We had a request on our DNS port: answer it. */ dnsserv_resolved(conn, answer_type, answer_len, (char*)answer, ttl); @@ -2636,7 +2796,7 @@ connection_ap_handshake_socks_resolved(edge_connection_t *conn, * be 0 or REASON_DONE. Send endreason to the controller, if appropriate. */ void -connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply, +connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply, size_t replylen, int endreason) { char buf[256]; @@ -2655,7 +2815,7 @@ connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply, return; } if (replylen) { /* we already have a reply in mind */ - connection_write_to_buf(reply, replylen, TO_CONN(conn)); + connection_write_to_buf(reply, replylen, ENTRY_TO_CONN(conn)); conn->socks_request->has_finished = 1; return; } @@ -2663,7 +2823,7 @@ connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply, memset(buf,0,SOCKS4_NETWORK_LEN); buf[1] = (status==SOCKS5_SUCCEEDED ? SOCKS4_GRANTED : SOCKS4_REJECT); /* leave version, destport, destip zero */ - connection_write_to_buf(buf, SOCKS4_NETWORK_LEN, TO_CONN(conn)); + connection_write_to_buf(buf, SOCKS4_NETWORK_LEN, ENTRY_TO_CONN(conn)); } else if (conn->socks_request->socks_version == 5) { buf[0] = 5; /* version 5 */ buf[1] = (char)status; @@ -2671,7 +2831,7 @@ connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply, buf[3] = 1; /* ipv4 addr */ memset(buf+4,0,6); /* Set external addr/port to 0. The spec doesn't seem to say what to do here. -RD */ - connection_write_to_buf(buf,10,TO_CONN(conn)); + connection_write_to_buf(buf,10,ENTRY_TO_CONN(conn)); } /* If socks_version isn't 4 or 5, don't send anything. * This can happen in the case of AP bridges. */ @@ -2705,7 +2865,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)) @@ -2737,9 +2897,9 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) END_STREAM_REASON_TORPROTOCOL, NULL); return 0; } - if (parse_addr_port(LOG_PROTOCOL_WARN, - (char*)(cell->payload+RELAY_HEADER_SIZE), - &address,NULL,&port)<0) { + if (tor_addr_port_split(LOG_PROTOCOL_WARN, + (char*)(cell->payload+RELAY_HEADER_SIZE), + &address,&port)<0) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Unable to parse addr:port in relay begin cell. Closing."); relay_send_end_cell_from_edge(rh.stream_id, circ, @@ -2988,12 +3148,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)) { @@ -3103,12 +3264,11 @@ connection_edge_is_rendezvous_stream(edge_connection_t *conn) * resolved.) */ int -connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit) +connection_ap_can_use_exit(const entry_connection_t *conn, const node_t *exit) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); tor_assert(conn); - tor_assert(conn->_base.type == CONN_TYPE_AP); tor_assert(conn->socks_request); tor_assert(exit); @@ -3116,10 +3276,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); @@ -3130,12 +3290,13 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit) if (conn->socks_request->command == SOCKS_COMMAND_CONNECT && !conn->use_begindir) { struct in_addr in; - uint32_t addr = 0; + tor_addr_t addr, *addrp = NULL; addr_policy_result_t r; - if (tor_inet_aton(conn->socks_request->address, &in)) - addr = ntohl(in.s_addr); - r = compare_addr_to_addr_policy(addr, conn->socks_request->port, - exit->exit_policy); + if (tor_inet_aton(conn->socks_request->address, &in)) { + tor_addr_from_in(&addr, &in); + addrp = &addr; + } + r = compare_tor_addr_to_node_policy(addrp, conn->socks_request->port,exit); if (r == ADDR_POLICY_REJECTED) return 0; /* We know the address, and the exit policy rejects it. */ if (r == ADDR_POLICY_PROBABLY_REJECTED && !conn->chosen_exit_name) @@ -3143,17 +3304,11 @@ connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit) * addresses with this port. Since the user didn't ask for * this node, err on the side of caution. */ } else if (SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)) { - /* Can't support reverse lookups without eventdns. */ - if (conn->socks_request->command == SOCKS_COMMAND_RESOLVE_PTR && - exit->has_old_dnsworkers) - return 0; - /* Don't send DNS requests to non-exit servers by default. */ - if (!conn->chosen_exit_name && policy_is_reject_star(exit->exit_policy)) + if (!conn->chosen_exit_name && node_exit_policy_rejects_all(exit)) return 0; } - if (options->_ExcludeExitNodesUnion && - routerset_contains_router(options->_ExcludeExitNodesUnion, exit)) { + if (routerset_contains_node(options->_ExcludeExitNodesUnion, exit)) { /* Not a suitable exit. Refuse it. */ return 0; } @@ -3208,3 +3363,205 @@ parse_extended_hostname(char *address, int allowdotexit) return BAD_HOSTNAME; } +/** Return true iff the (possibly NULL) <b>alen</b>-byte chunk of memory at + * <b>a</b> is equal to the (possibly NULL) <b>blen</b>-byte chunk of memory + * at <b>b</b>. */ +static int +memeq_opt(const char *a, size_t alen, const char *b, size_t blen) +{ + if (a == NULL) { + return (b == NULL); + } else if (b == NULL) { + return 0; + } else if (alen != blen) { + return 0; + } else { + return tor_memeq(a, b, alen); + } +} + +/** + * Return true iff none of the isolation flags and fields in <b>conn</b> + * should prevent it from being attached to <b>circ</b>. + */ +int +connection_edge_compatible_with_circuit(const entry_connection_t *conn, + const origin_circuit_t *circ) +{ + const uint8_t iso = conn->isolation_flags; + const socks_request_t *sr = conn->socks_request; + + /* If circ has never been used for an isolated connection, we can + * totally use it for this one. */ + if (!circ->isolation_values_set) + return 1; + + /* If circ has been used for connections having more than one value + * for some field f, it will have the corresponding bit set in + * isolation_flags_mixed. If isolation_flags_mixed has any bits + * in common with iso, then conn must be isolated from at least + * one stream that has been attached to circ. */ + if ((iso & circ->isolation_flags_mixed) != 0) { + /* For at least one field where conn is isolated, the circuit + * already has mixed streams. */ + return 0; + } + + if (! conn->original_dest_address) { + log_warn(LD_BUG, "Reached connection_edge_compatible_with_circuit without " + "having set conn->original_dest_address"); + ((entry_connection_t*)conn)->original_dest_address = + tor_strdup(conn->socks_request->address); + } + + if ((iso & ISO_STREAM) && + (circ->associated_isolated_stream_global_id != + ENTRY_TO_CONN(conn)->global_identifier)) + return 0; + + if ((iso & ISO_DESTPORT) && conn->socks_request->port != circ->dest_port) + return 0; + if ((iso & ISO_DESTADDR) && + strcasecmp(conn->original_dest_address, circ->dest_address)) + return 0; + if ((iso & ISO_SOCKSAUTH) && + (! memeq_opt(sr->username, sr->usernamelen, + circ->socks_username, circ->socks_username_len) || + ! memeq_opt(sr->password, sr->passwordlen, + circ->socks_password, circ->socks_password_len))) + return 0; + if ((iso & ISO_CLIENTPROTO) && + (conn->socks_request->listener_type != circ->client_proto_type || + conn->socks_request->socks_version != circ->client_proto_socksver)) + return 0; + if ((iso & ISO_CLIENTADDR) && + !tor_addr_eq(&ENTRY_TO_CONN(conn)->addr, &circ->client_addr)) + return 0; + if ((iso & ISO_SESSIONGRP) && conn->session_group != circ->session_group) + return 0; + if ((iso & ISO_NYM_EPOCH) && conn->nym_epoch != circ->nym_epoch) + return 0; + + return 1; +} + +/** + * If <b>dry_run</b> is false, update <b>circ</b>'s isolation flags and fields + * to reflect having had <b>conn</b> attached to it, and return 0. Otherwise, + * if <b>dry_run</b> is true, then make no changes to <b>circ</b>, and return + * a bitfield of isolation flags that we would have to set in + * isolation_flags_mixed to add <b>conn</b> to <b>circ</b>, or -1 if + * <b>circ</b> has had no streams attached to it. + */ +int +connection_edge_update_circuit_isolation(const entry_connection_t *conn, + origin_circuit_t *circ, + int dry_run) +{ + const socks_request_t *sr = conn->socks_request; + if (! conn->original_dest_address) { + log_warn(LD_BUG, "Reached connection_update_circuit_isolation without " + "having set conn->original_dest_address"); + ((entry_connection_t*)conn)->original_dest_address = + tor_strdup(conn->socks_request->address); + } + + if (!circ->isolation_values_set) { + if (dry_run) + return -1; + circ->associated_isolated_stream_global_id = + ENTRY_TO_CONN(conn)->global_identifier; + circ->dest_port = conn->socks_request->port; + circ->dest_address = tor_strdup(conn->original_dest_address); + circ->client_proto_type = conn->socks_request->listener_type; + circ->client_proto_socksver = conn->socks_request->socks_version; + tor_addr_copy(&circ->client_addr, &ENTRY_TO_CONN(conn)->addr); + circ->session_group = conn->session_group; + circ->nym_epoch = conn->nym_epoch; + circ->socks_username = sr->username ? + tor_memdup(sr->username, sr->usernamelen) : NULL; + circ->socks_password = sr->password ? + tor_memdup(sr->password, sr->passwordlen) : NULL; + circ->socks_username_len = sr->usernamelen; + circ->socks_password_len = sr->passwordlen; + + circ->isolation_values_set = 1; + return 0; + } else { + uint8_t mixed = 0; + if (conn->socks_request->port != circ->dest_port) + mixed |= ISO_DESTPORT; + if (strcasecmp(conn->original_dest_address, circ->dest_address)) + mixed |= ISO_DESTADDR; + if (!memeq_opt(sr->username, sr->usernamelen, + circ->socks_username, circ->socks_username_len) || + !memeq_opt(sr->password, sr->passwordlen, + circ->socks_password, circ->socks_password_len)) + mixed |= ISO_SOCKSAUTH; + if ((conn->socks_request->listener_type != circ->client_proto_type || + conn->socks_request->socks_version != circ->client_proto_socksver)) + mixed |= ISO_CLIENTPROTO; + if (!tor_addr_eq(&ENTRY_TO_CONN(conn)->addr, &circ->client_addr)) + mixed |= ISO_CLIENTADDR; + if (conn->session_group != circ->session_group) + mixed |= ISO_SESSIONGRP; + if (conn->nym_epoch != circ->nym_epoch) + mixed |= ISO_NYM_EPOCH; + + if (dry_run) + return mixed; + + if ((mixed & conn->isolation_flags) != 0) { + log_warn(LD_BUG, "Updating a circuit with seemingly incompatible " + "isolation flags."); + } + circ->isolation_flags_mixed |= mixed; + return 0; + } +} + +/** + * Clear the isolation settings on <b>circ</b>. + * + * This only works on an open circuit that has never had a stream attached to + * it, and whose isolation settings are hypothetical. (We set hypothetical + * isolation settings on circuits as we're launching them, so that we + * know whether they can handle more streams or whether we need to launch + * even more circuits. Once the circuit is open, if it turns out that + * we no longer have any streams to attach to it, we clear the isolation flags + * and data so that other streams can have a chance.) + */ +void +circuit_clear_isolation(origin_circuit_t *circ) +{ + if (circ->isolation_any_streams_attached) { + log_warn(LD_BUG, "Tried to clear the isolation status of a dirty circuit"); + return; + } + if (TO_CIRCUIT(circ)->state != CIRCUIT_STATE_OPEN) { + log_warn(LD_BUG, "Tried to clear the isolation status of a non-open " + "circuit"); + return; + } + + circ->isolation_values_set = 0; + circ->isolation_flags_mixed = 0; + circ->associated_isolated_stream_global_id = 0; + circ->client_proto_type = 0; + circ->client_proto_socksver = 0; + circ->dest_port = 0; + tor_addr_make_unspec(&circ->client_addr); + tor_free(circ->dest_address); + circ->session_group = -1; + circ->nym_epoch = 0; + if (circ->socks_username) { + memset(circ->socks_username, 0x11, circ->socks_username_len); + tor_free(circ->socks_username); + } + if (circ->socks_password) { + memset(circ->socks_password, 0x05, circ->socks_password_len); + tor_free(circ->socks_password); + } + circ->socks_username_len = circ->socks_password_len = 0; +} + diff --git a/src/or/connection_edge.h b/src/or/connection_edge.h index 8ba2fafd08..830667e601 100644 --- a/src/or/connection_edge.h +++ b/src/or/connection_edge.h @@ -15,7 +15,7 @@ #define connection_mark_unattached_ap(conn, endreason) \ _connection_mark_unattached_ap((conn), (endreason), __LINE__, _SHORT_FILE_) -void _connection_mark_unattached_ap(edge_connection_t *conn, int endreason, +void _connection_mark_unattached_ap(entry_connection_t *conn, int endreason, int line, const char *file); int connection_edge_reached_eof(edge_connection_t *conn); int connection_edge_process_inbuf(edge_connection_t *conn, @@ -27,16 +27,22 @@ int connection_edge_flushed_some(edge_connection_t *conn); int connection_edge_finished_flushing(edge_connection_t *conn); int connection_edge_finished_connecting(edge_connection_t *conn); -int connection_ap_handshake_send_begin(edge_connection_t *ap_conn); -int connection_ap_handshake_send_resolve(edge_connection_t *ap_conn); +void connection_ap_about_to_close(entry_connection_t *edge_conn); +void connection_exit_about_to_close(edge_connection_t *edge_conn); -edge_connection_t *connection_ap_make_link(char *address, uint16_t port, +int connection_ap_handshake_send_begin(entry_connection_t *ap_conn); +int connection_ap_handshake_send_resolve(entry_connection_t *ap_conn); + +entry_connection_t *connection_ap_make_link(connection_t *partner, + char *address, uint16_t port, const char *digest, + int session_group, + int isolation_flags, int use_begindir, int want_onehop); -void connection_ap_handshake_socks_reply(edge_connection_t *conn, char *reply, +void connection_ap_handshake_socks_reply(entry_connection_t *conn, char *reply, size_t replylen, int endreason); -void connection_ap_handshake_socks_resolved(edge_connection_t *conn, +void connection_ap_handshake_socks_resolved(entry_connection_t *conn, int answer_type, size_t answer_len, const uint8_t *answer, @@ -47,22 +53,23 @@ int connection_exit_begin_conn(cell_t *cell, circuit_t *circ); int connection_exit_begin_resolve(cell_t *cell, or_circuit_t *circ); void connection_exit_connect(edge_connection_t *conn); int connection_edge_is_rendezvous_stream(edge_connection_t *conn); -int connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit); +int connection_ap_can_use_exit(const entry_connection_t *conn, + const node_t *exit); void connection_ap_expire_beginning(void); void connection_ap_attach_pending(void); void connection_ap_fail_onehop(const char *failed_digest, cpath_build_state_t *build_state); void circuit_discard_optional_exit_enclaves(extend_info_t *info); -int connection_ap_detach_retriable(edge_connection_t *conn, +int connection_ap_detach_retriable(entry_connection_t *conn, origin_circuit_t *circ, int reason); -int connection_ap_process_transparent(edge_connection_t *conn); +int connection_ap_process_transparent(entry_connection_t *conn); int address_is_invalid_destination(const char *address, int client); void addressmap_init(void); -void addressmap_clear_excluded_trackexithosts(or_options_t *options); -void addressmap_clear_invalid_automaps(or_options_t *options); +void addressmap_clear_excluded_trackexithosts(const or_options_t *options); +void addressmap_clear_invalid_automaps(const or_options_t *options); void addressmap_clean(time_t now); void addressmap_clear_configured(void); void addressmap_clear_transient(void); @@ -81,10 +88,10 @@ void client_dns_set_addressmap(const char *address, uint32_t val, const char *addressmap_register_virtual_address(int type, char *new_address); void addressmap_get_mappings(smartlist_t *sl, time_t min_expires, time_t max_expires, int want_expiry); -int connection_ap_rewrite_and_attach_if_allowed(edge_connection_t *conn, +int connection_ap_rewrite_and_attach_if_allowed(entry_connection_t *conn, origin_circuit_t *circ, crypt_path_t *cpath); -int connection_ap_handshake_rewrite_and_attach(edge_connection_t *conn, +int connection_ap_handshake_rewrite_and_attach(entry_connection_t *conn, origin_circuit_t *circ, crypt_path_t *cpath); @@ -98,5 +105,12 @@ hostname_type_t parse_extended_hostname(char *address, int allowdotexit); int get_pf_socket(void); #endif +int connection_edge_compatible_with_circuit(const entry_connection_t *conn, + const origin_circuit_t *circ); +int connection_edge_update_circuit_isolation(const entry_connection_t *conn, + origin_circuit_t *circ, + int dry_run); +void circuit_clear_isolation(origin_circuit_t *circ); + #endif diff --git a/src/or/connection_or.c b/src/or/connection_or.c index c019f6592b..e178f3a8c0 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -13,6 +13,7 @@ #include "or.h" #include "buffers.h" #include "circuitbuild.h" +#include "circuitlist.h" #include "command.h" #include "config.h" #include "connection.h" @@ -22,21 +23,33 @@ #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_launch_v3_or_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); -static int connection_init_or_handshake_state(or_connection_t *conn, - int started_here); 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); +static void connection_or_close_connection_cb(void *_conn); + +#ifdef USE_BUFFEREVENTS +static void connection_or_handle_event_cb(struct bufferevent *bufev, + short event, void *arg); +#include <event2/buffer.h>/*XXXX REMOVE */ +#endif + /**************************************************************/ /** Map from identity digest of connected OR or desired OR to a connection_t @@ -136,6 +149,142 @@ connection_or_set_identity_digest(or_connection_t *conn, const char *digest) #endif } +/**************************************************************/ + +/** Map from a string describing what a non-open OR connection was doing when + * failed, to an intptr_t describing the count of connections that failed that + * way. Note that the count is stored _as_ the pointer. + */ +static strmap_t *broken_connection_counts; + +/** If true, do not record information in <b>broken_connection_counts</b>. */ +static int disable_broken_connection_counts = 0; + +/** Record that an OR connection failed in <b>state</b>. */ +static void +note_broken_connection(const char *state) +{ + void *ptr; + intptr_t val; + if (disable_broken_connection_counts) + return; + + if (!broken_connection_counts) + broken_connection_counts = strmap_new(); + + ptr = strmap_get(broken_connection_counts, state); + val = (intptr_t)ptr; + val++; + ptr = (void*)val; + strmap_set(broken_connection_counts, state, ptr); +} + +/** Forget all recorded states for failed connections. If + * <b>stop_recording</b> is true, don't record any more. */ +void +clear_broken_connection_map(int stop_recording) +{ + if (broken_connection_counts) + strmap_free(broken_connection_counts, NULL); + broken_connection_counts = NULL; + if (stop_recording) + disable_broken_connection_counts = 1; +} + +/** Write a detailed description the state of <b>orconn</b> into the + * <b>buflen</b>-byte buffer at <b>buf</b>. This description includes not + * only the OR-conn level state but also the TLS state. It's useful for + * diagnosing broken handshakes. */ +static void +connection_or_get_state_description(or_connection_t *orconn, + char *buf, size_t buflen) +{ + connection_t *conn = TO_CONN(orconn); + const char *conn_state; + char tls_state[256]; + + tor_assert(conn->type == CONN_TYPE_OR); + + conn_state = conn_state_to_string(conn->type, conn->state); + tor_tls_get_state_description(orconn->tls, tls_state, sizeof(tls_state)); + + tor_snprintf(buf, buflen, "%s with SSL state %s", conn_state, tls_state); +} + +/** Record the current state of <b>orconn</b> as the state of a broken + * connection. */ +static void +connection_or_note_state_when_broken(or_connection_t *orconn) +{ + char buf[256]; + if (disable_broken_connection_counts) + return; + connection_or_get_state_description(orconn, buf, sizeof(buf)); + log_info(LD_HANDSHAKE,"Connection died in state '%s'", buf); + note_broken_connection(buf); +} + +/** Helper type used to sort connection states and find the most frequent. */ +typedef struct broken_state_count_t { + intptr_t count; + const char *state; +} broken_state_count_t; + +/** Helper function used to sort broken_state_count_t by frequency. */ +static int +broken_state_count_compare(const void **a_ptr, const void **b_ptr) +{ + const broken_state_count_t *a = *a_ptr, *b = *b_ptr; + if (b->count < a->count) + return -1; + else if (b->count == a->count) + return 0; + else + return 1; +} + +/** Upper limit on the number of different states to report for connection + * failure. */ +#define MAX_REASONS_TO_REPORT 10 + +/** Report a list of the top states for failed OR connections at log level + * <b>severity</b>, in log domain <b>domain</b>. */ +void +connection_or_report_broken_states(int severity, int domain) +{ + int total = 0; + smartlist_t *items; + + if (!broken_connection_counts || disable_broken_connection_counts) + return; + + items = smartlist_create(); + STRMAP_FOREACH(broken_connection_counts, state, void *, countptr) { + broken_state_count_t *c = tor_malloc(sizeof(broken_state_count_t)); + c->count = (intptr_t)countptr; + total += (int)c->count; + c->state = state; + smartlist_add(items, c); + } STRMAP_FOREACH_END; + + smartlist_sort(items, broken_state_count_compare); + + log(severity, domain, "%d connections have failed%s", total, + smartlist_len(items) > MAX_REASONS_TO_REPORT ? ". Top reasons:" : ":"); + + SMARTLIST_FOREACH_BEGIN(items, const broken_state_count_t *, c) { + if (c_sl_idx > MAX_REASONS_TO_REPORT) + break; + log(severity, domain, + " %d connections died in state %s", (int)c->count, c->state); + } SMARTLIST_FOREACH_END(c); + + SMARTLIST_FOREACH(items, broken_state_count_t *, c, tor_free(c)); + smartlist_free(items); +} + +/**************************************************************/ + /** Pack the cell_t host-order structure <b>src</b> into network-order * in the buffer <b>dest</b>. See tor-spec.txt for details about the * wire format. @@ -178,7 +327,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,8 +377,17 @@ connection_or_process_inbuf(or_connection_t *conn) } return ret; + case OR_CONN_STATE_TLS_SERVER_RENEGOTIATING: +#ifdef USE_BUFFEREVENTS + 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: + case OR_CONN_STATE_OR_HANDSHAKING_V2: + case OR_CONN_STATE_OR_HANDSHAKING_V3: return connection_or_process_cells_from_inbuf(conn); default: return 0; /* don't do anything */ @@ -248,7 +407,7 @@ connection_or_process_inbuf(or_connection_t *conn) int connection_or_flushed_some(or_connection_t *conn) { - size_t datalen = buf_datalen(conn->_base.outbuf); + size_t datalen = connection_get_outbuf_len(TO_CONN(conn)); /* If we're under the low water mark, add cells until we're just over the * high water mark. */ if (datalen < OR_CONN_LOWWATER) { @@ -280,8 +439,8 @@ connection_or_finished_flushing(or_connection_t *conn) switch (conn->_base.state) { case OR_CONN_STATE_PROXY_HANDSHAKING: case OR_CONN_STATE_OPEN: - case OR_CONN_STATE_OR_HANDSHAKING: - connection_stop_writing(TO_CONN(conn)); + case OR_CONN_STATE_OR_HANDSHAKING_V2: + case OR_CONN_STATE_OR_HANDSHAKING_V3: break; default: log_err(LD_BUG,"Called in unexpected state %d.", conn->_base.state); @@ -296,7 +455,7 @@ connection_or_finished_flushing(or_connection_t *conn) int connection_or_finished_connecting(or_connection_t *or_conn) { - int proxy_type; + const int proxy_type = or_conn->proxy_type; connection_t *conn; tor_assert(or_conn); conn = TO_CONN(or_conn); @@ -306,15 +465,6 @@ connection_or_finished_connecting(or_connection_t *or_conn) conn->address,conn->port); control_event_bootstrap(BOOTSTRAP_STATUS_HANDSHAKE, 0); - proxy_type = PROXY_NONE; - - if (get_options()->HTTPSProxy) - proxy_type = PROXY_CONNECT; - else if (get_options()->Socks4Proxy) - proxy_type = PROXY_SOCKS4; - else if (get_options()->Socks5Proxy) - proxy_type = PROXY_SOCKS5; - if (proxy_type != PROXY_NONE) { /* start proxy handshake */ if (connection_proxy_connect(conn, proxy_type) < 0) { @@ -335,6 +485,54 @@ connection_or_finished_connecting(or_connection_t *or_conn) return 0; } +/* Called when we're about to finally unlink and free an OR connection: + * perform necessary accounting and cleanup */ +void +connection_or_about_to_close(or_connection_t *or_conn) +{ + time_t now = time(NULL); + connection_t *conn = TO_CONN(or_conn); + + if (or_conn->pending_action) + tor_cancel_libevent_action(or_conn->pending_action); + + /* Remember why we're closing this connection. */ + if (conn->state != OR_CONN_STATE_OPEN) { + /* Inform any pending (not attached) circs that they should + * give up. */ + circuit_n_conn_done(TO_OR_CONN(conn), 0); + /* now mark things down as needed */ + if (connection_or_nonopen_was_started_here(or_conn)) { + const or_options_t *options = get_options(); + connection_or_note_state_when_broken(or_conn); + rep_hist_note_connect_failed(or_conn->identity_digest, now); + entry_guard_register_connect_status(or_conn->identity_digest,0, + !options->HTTPSProxy, now); + if (conn->state >= OR_CONN_STATE_TLS_HANDSHAKING) { + int reason = tls_error_to_orconn_end_reason(or_conn->tls_error); + control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED, + reason); + if (!authdir_mode_tests_reachability(options)) + control_event_bootstrap_problem( + orconn_end_reason_to_control_string(reason), reason); + } + } + } else if (conn->hold_open_until_flushed) { + /* We only set hold_open_until_flushed when we're intentionally + * closing a connection. */ + rep_hist_note_disconnect(or_conn->identity_digest, now); + control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED, + tls_error_to_orconn_end_reason(or_conn->tls_error)); + } else if (!tor_digest_is_zero(or_conn->identity_digest)) { + rep_hist_note_connection_died(or_conn->identity_digest, now); + control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED, + tls_error_to_orconn_end_reason(or_conn->tls_error)); + } + /* Now close all the attached circuits on it. */ + circuit_unlink_all_from_or_conn(TO_OR_CONN(conn), + END_CIRC_REASON_OR_CONN_CLOSED); +} + /** Return 1 if identity digest <b>id_digest</b> is known to be a * currently or recently running relay. Otherwise return 0. */ int @@ -342,7 +540,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 +557,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 +580,27 @@ connection_or_update_token_buckets_helper(or_connection_t *conn, int reset, conn->bandwidthrate = rate; conn->bandwidthburst = burst; +#ifdef USE_BUFFEREVENTS + { + const struct timeval *tick = tor_libevent_get_one_tick_timeout(); + struct ev_token_bucket_cfg *cfg, *old_cfg; + int64_t rate64 = (((int64_t)rate) * options->TokenBucketRefillInterval) + / 1000; + /* This can't overflow, since TokenBucketRefillInterval <= 1000, + * and rate started out less than INT_MAX. */ + int rate_per_tick = (int) rate64; + + cfg = ev_token_bucket_cfg_new(rate_per_tick, burst, rate_per_tick, + burst, tick); + old_cfg = conn->bucket_cfg; + if (conn->_base.bufev) + tor_set_bufferevent_rate_limit(conn->_base.bufev, cfg); + if (old_cfg) + ev_token_bucket_cfg_free(old_cfg); + conn->bucket_cfg = cfg; + (void) reset; /* No way to do this with libevent yet. */ + } +#else if (reset) { /* set up the token buckets to be full */ conn->read_bucket = conn->write_bucket = burst; return; @@ -392,13 +611,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, { @@ -410,13 +631,13 @@ connection_or_update_token_buckets(smartlist_t *conns, or_options_t *options) /** If we don't necessarily know the router we're connecting to, but we * have an addr/port/id_digest, then fill in as much as we can. Start * by checking to see if this describes a router we know. */ -static void +void connection_or_init_conn_from_address(or_connection_t *conn, const tor_addr_t *addr, uint16_t port, 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 +645,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 +661,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 @@ -548,6 +771,11 @@ connection_or_get_for_extend(const char *digest, tor_assert(tor_memeq(conn->identity_digest, digest, DIGEST_LEN)); if (conn->_base.marked_for_close) continue; + /* Never return a connection on which the other end appears to be + * a client. */ + if (conn->is_connection_with_client) { + continue; + } /* Never return a non-open connection. */ if (conn->_base.state != OR_CONN_STATE_OPEN) { /* If the address matches, don't launch a new connection for this @@ -787,11 +1015,15 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port, const char *id_digest) { or_connection_t *conn; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); int socket_error = 0; - int using_proxy = 0; tor_addr_t addr; + int r; + tor_addr_t proxy_addr; + uint16_t proxy_port; + int proxy_type; + tor_assert(_addr); tor_assert(id_digest); tor_addr_copy(&addr, _addr); @@ -808,19 +1040,22 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port, conn->_base.state = OR_CONN_STATE_CONNECTING; control_event_or_conn_status(conn, OR_CONN_EVENT_LAUNCHED, 0); - /* use a proxy server if available */ - if (options->HTTPSProxy) { - using_proxy = 1; - tor_addr_copy(&addr, &options->HTTPSProxyAddr); - port = options->HTTPSProxyPort; - } else if (options->Socks4Proxy) { - using_proxy = 1; - tor_addr_copy(&addr, &options->Socks4ProxyAddr); - port = options->Socks4ProxyPort; - } else if (options->Socks5Proxy) { - using_proxy = 1; - tor_addr_copy(&addr, &options->Socks5ProxyAddr); - port = options->Socks5ProxyPort; + conn->is_outgoing = 1; + + /* If we are using a proxy server, find it and use it. */ + r = get_proxy_addrport(&proxy_addr, &proxy_port, &proxy_type, TO_CONN(conn)); + if (r == 0) { + conn->proxy_type = proxy_type; + if (proxy_type != PROXY_NONE) { + tor_addr_copy(&addr, &proxy_addr); + port = proxy_port; + conn->_base.proxy_state = PROXY_INFANT; + } + } else { + log_warn(LD_GENERAL, "Tried to connect through proxy, but proxy address " + "could not be found."); + connection_free(TO_CONN(conn)); + return NULL; } switch (connection_connect(TO_CONN(conn), conn->_base.address, @@ -828,7 +1063,7 @@ connection_or_connect(const tor_addr_t *_addr, uint16_t port, case -1: /* If the connection failed immediately, and we're using * a proxy, our proxy is down. Don't blame the Tor server. */ - if (!using_proxy) + if (conn->_base.proxy_state == PROXY_INFANT) entry_guard_register_connect_status(conn->identity_digest, 0, 1, time(NULL)); connection_or_connect_failed(conn, @@ -863,19 +1098,50 @@ 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)); if (!conn->tls) { log_warn(LD_BUG,"tor_tls_new failed. Closing."); return -1; } + tor_tls_set_logged_address(conn->tls, // XXX client and relay? + escaped_safe_str(conn->_base.address)); + tor_tls_set_renegotiate_callbacks(conn->tls, + connection_or_tls_renegotiated_cb, + connection_or_close_connection_cb, + conn); +#ifdef USE_BUFFEREVENTS + if (connection_type_uses_bufferevent(TO_CONN(conn))) { + const int filtering = get_options()->_UseFilteringSSLBufferevents; + struct bufferevent *b = + tor_tls_init_bufferevent(conn->tls, conn->_base.bufev, conn->_base.s, + receiving, filtering); + if (!b) { + log_warn(LD_BUG,"tor_tls_init_bufferevent failed. Closing."); + return -1; + } + conn->_base.bufev = b; + if (conn->bucket_cfg) + tor_set_bufferevent_rate_limit(conn->_base.bufev, conn->bucket_cfg); + connection_enable_rate_limiting(TO_CONN(conn)); + + connection_configure_bufferevent_callbacks(TO_CONN(conn)); + bufferevent_setcb(b, + connection_handle_read_cb, + connection_handle_write_cb, + connection_or_handle_event_cb,/* overriding this one*/ + TO_CONN(conn)); + } +#endif connection_start_reading(TO_CONN(conn)); log_debug(LD_HANDSHAKE,"starting TLS handshake on fd %d", conn->_base.s); note_crypto_pk_op(receiving ? TLS_HANDSHAKE_S : TLS_HANDSHAKE_C); - if (connection_tls_continue_handshake(conn) < 0) { - return -1; + IF_HAS_BUFFEREVENT(TO_CONN(conn), { + /* ???? */; + }) ELSE_IF_NO_BUFFEREVENT { + if (connection_tls_continue_handshake(conn) < 0) + return -1; } return 0; } @@ -888,10 +1154,6 @@ connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn) or_connection_t *conn = _conn; (void)tls; - /* Don't invoke this again. */ - tor_tls_set_renegotiate_callback(tls, NULL, NULL); - tor_tls_block_renegotiation(tls); - if (connection_tls_finish_handshake(conn) < 0) { /* XXXX_TLS double-check that it's ok to do this from inside read. */ /* XXXX_TLS double-check that this verifies certificates. */ @@ -899,6 +1161,34 @@ connection_or_tls_renegotiated_cb(tor_tls_t *tls, void *_conn) } } +/*DOCDOC*/ +static void +close_connection_libevent_cb(void *_conn) +{ + or_connection_t *or_conn = _conn; + connection_t *conn = TO_CONN(or_conn); + + or_conn->pending_action = NULL; + + connection_stop_reading(conn); + if (!conn->marked_for_close) + connection_mark_for_close(conn); +} + +/* DOCDOC */ +static void +connection_or_close_connection_cb(void *_conn) +{ + /* We can't close their connection from in here since it's an OpenSSL + callback, so we set a libevent event that triggers in the next event + loop and closes the connection. */ + or_connection_t *or_conn = _conn; + if (or_conn->_base.marked_for_close || or_conn->pending_action) + return; + or_conn->pending_action = + tor_run_in_libevent_loop(close_connection_libevent_cb, or_conn); +} + /** Move forward with the tls handshake. If it finishes, hand * <b>conn</b> to connection_tls_finish_handshake(). * @@ -929,19 +1219,22 @@ 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_debug(LD_OR, "Done with initial SSL handshake (client-side). " - "Requesting renegotiation."); - conn->_base.state = OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING; - goto again; + if (tor_tls_received_v3_certificate(conn->tls)) { + log_info(LD_OR, "Client got a v3 cert! Moving on to v3 " + "handshake."); + return connection_or_launch_v3_or_handshake(conn); + } else { + 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. */ + /* v2/v3 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); + "Expecting renegotiation or VERSIONS cell"); conn->_base.state = OR_CONN_STATE_TLS_SERVER_RENEGOTIATING; connection_stop_writing(TO_CONN(conn)); connection_start_reading(TO_CONN(conn)); @@ -963,6 +1256,82 @@ 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) { + if (tor_tls_received_v3_certificate(conn->tls)) { + log_info(LD_OR, "Client got a v3 cert!"); + if (connection_or_launch_v3_or_handshake(conn) < 0) + connection_mark_for_close(TO_CONN(conn)); + return; + } else { + 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) { + /* v2 or v3 handshake, as a server. Only got one handshake, so + * wait for the next one. */ + 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) { + /* v2 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. */ @@ -977,6 +1346,29 @@ connection_or_nonopen_was_started_here(or_connection_t *conn) return !tor_tls_is_server(conn->tls); } +/** Set the circid_type field of <b>conn</b> (which determines which part of + * the circuit ID space we're willing to use) based on comparing our ID to + * <b>identity_rcvd</b> */ +void +connection_or_set_circid_type(or_connection_t *conn, + crypto_pk_env_t *identity_rcvd) +{ + const int started_here = connection_or_nonopen_was_started_here(conn); + crypto_pk_env_t *our_identity = + started_here ? get_tlsclient_identity_key() : + get_server_identity_key(); + + if (identity_rcvd) { + if (crypto_pk_cmp_keys(our_identity, identity_rcvd)<0) { + conn->circ_id_type = CIRC_ID_TYPE_LOWER; + } else { + conn->circ_id_type = CIRC_ID_TYPE_HIGHER; + } + } else { + conn->circ_id_type = CIRC_ID_TYPE_NEITHER; + } +} + /** <b>Conn</b> just completed its handshake. Return 0 if all is well, and * return -1 if he is lying, broken, or otherwise something is wrong. * @@ -1008,16 +1400,13 @@ 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 : safe_str_client(conn->_base.address); const char *conn_type = started_here ? "outgoing" : "incoming"; - crypto_pk_env_t *our_identity = - started_here ? get_tlsclient_identity_key() : - get_server_identity_key(); - int has_cert = 0, has_identity=0; + int has_cert = 0; check_no_tls_errors(); has_cert = tor_tls_peer_has_cert(conn->tls); @@ -1052,21 +1441,46 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, } if (identity_rcvd) { - has_identity = 1; crypto_pk_get_digest(identity_rcvd, digest_rcvd_out); - if (crypto_pk_cmp_keys(our_identity, identity_rcvd)<0) { - conn->circ_id_type = CIRC_ID_TYPE_LOWER; - } else { - conn->circ_id_type = CIRC_ID_TYPE_HIGHER; - } - crypto_free_pk_env(identity_rcvd); } else { memset(digest_rcvd_out, 0, DIGEST_LEN); - conn->circ_id_type = CIRC_ID_TYPE_NEITHER; } - if (started_here && tor_digest_is_zero(conn->identity_digest)) { - connection_or_set_identity_digest(conn, digest_rcvd_out); + connection_or_set_circid_type(conn, identity_rcvd); + crypto_free_pk_env(identity_rcvd); + + if (started_here) + return connection_or_client_learned_peer_id(conn, + (const uint8_t*)digest_rcvd_out); + + return 0; +} + +/** Called when we (as a connection initiator) have definitively, + * authenticatedly, learned that ID of the Tor instance on the other + * side of <b>conn</b> is <b>peer_id</b>. For v1 and v2 handshakes, + * this is right after we get a certificate chain in a TLS handshake + * or renegotiation. For v3 handshakes, this is right after we get a + * certificate chain in a CERTS cell. + * + * If we want any particular ID before, record the one we got. + * + * If we wanted an ID, but we didn't get it, log a warning and return -1. + * + * If we're testing reachability, remember what we learned. + * + * Return 0 on success, -1 on failure. + */ +int +connection_or_client_learned_peer_id(or_connection_t *conn, + const uint8_t *peer_id) +{ + int as_expected = 1; + const or_options_t *options = get_options(); + int severity = server_mode(options) ? LOG_PROTOCOL_WARN : LOG_WARN; + + if (tor_digest_is_zero(conn->identity_digest)) { + connection_or_set_identity_digest(conn, (const char*)peer_id); tor_free(conn->nickname); conn->nickname = tor_malloc(HEX_DIGEST_LEN+2); conn->nickname[0] = '$'; @@ -1078,43 +1492,39 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, /* if it's a bridge and we didn't know its identity fingerprint, now * we do -- remember it for future attempts. */ learned_router_identity(&conn->_base.addr, conn->_base.port, - digest_rcvd_out); + (const char*)peer_id); } - if (started_here) { - int as_advertised = 1; - tor_assert(has_cert); - tor_assert(has_identity); - if (tor_memneq(digest_rcvd_out, conn->identity_digest, DIGEST_LEN)) { - /* I was aiming for a particular digest. I didn't get it! */ - char seen[HEX_DIGEST_LEN+1]; - char expected[HEX_DIGEST_LEN+1]; - base16_encode(seen, sizeof(seen), digest_rcvd_out, DIGEST_LEN); - base16_encode(expected, sizeof(expected), conn->identity_digest, - DIGEST_LEN); - log_fn(severity, LD_HANDSHAKE, - "Tried connecting to router at %s:%d, but identity key was not " - "as expected: wanted %s but got %s.", - conn->_base.address, conn->_base.port, expected, seen); - entry_guard_register_connect_status(conn->identity_digest, 0, 1, - time(NULL)); - control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED, - END_OR_CONN_REASON_OR_IDENTITY); - if (!authdir_mode_tests_reachability(options)) - control_event_bootstrap_problem("foo", END_OR_CONN_REASON_OR_IDENTITY); - as_advertised = 0; - } - if (authdir_mode_tests_reachability(options)) { - dirserv_orconn_tls_done(conn->_base.address, conn->_base.port, - digest_rcvd_out, as_advertised); - } - if (!as_advertised) - return -1; + if (tor_memneq(peer_id, conn->identity_digest, DIGEST_LEN)) { + /* I was aiming for a particular digest. I didn't get it! */ + char seen[HEX_DIGEST_LEN+1]; + char expected[HEX_DIGEST_LEN+1]; + base16_encode(seen, sizeof(seen), (const char*)peer_id, DIGEST_LEN); + base16_encode(expected, sizeof(expected), conn->identity_digest, + DIGEST_LEN); + log_fn(severity, LD_HANDSHAKE, + "Tried connecting to router at %s:%d, but identity key was not " + "as expected: wanted %s but got %s.", + conn->_base.address, conn->_base.port, expected, seen); + entry_guard_register_connect_status(conn->identity_digest, 0, 1, + time(NULL)); + control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED, + END_OR_CONN_REASON_OR_IDENTITY); + if (!authdir_mode_tests_reachability(options)) + control_event_bootstrap_problem("foo", END_OR_CONN_REASON_OR_IDENTITY); + as_expected = 0; + } + if (authdir_mode_tests_reachability(options)) { + dirserv_orconn_tls_done(conn->_base.address, conn->_base.port, + (const char*)peer_id, as_expected); } + if (!as_expected) + return -1; + return 0; } -/** The tls handshake is finished. +/** The v1/v2 TLS handshake is finished. * * Make sure we are happy with the person we just handshaked with. * @@ -1124,6 +1534,8 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn, * If all is successful, call circuit_n_conn_done() to handle events * that have been pending on the <tls handshake completion. Also set the * directory to be dirty (only matters if I'm an authdirserver). + * + * If this is a v2 TLS handshake, send a versions cell. */ static int connection_tls_finish_handshake(or_connection_t *conn) @@ -1131,7 +1543,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(); @@ -1148,28 +1562,50 @@ connection_tls_finish_handshake(or_connection_t *conn) connection_or_init_conn_from_address(conn, &conn->_base.addr, conn->_base.port, digest_rcvd, 0); } - tor_tls_block_renegotiation(conn->tls); return connection_or_set_state_open(conn); } else { - conn->_base.state = OR_CONN_STATE_OR_HANDSHAKING; + conn->_base.state = OR_CONN_STATE_OR_HANDSHAKING_V2; if (connection_init_or_handshake_state(conn, started_here) < 0) return -1; if (!started_here) { connection_or_init_conn_from_address(conn, &conn->_base.addr, conn->_base.port, digest_rcvd, 0); } - return connection_or_send_versions(conn); + return connection_or_send_versions(conn, 0); } } +/** + * Called as client when initial TLS handshake is done, and we notice + * that we got a v3-handshake signalling certificate from the server. + * Set up structures, do bookkeeping, and send the versions cell. + * Return 0 on success and -1 on failure. + */ +static int +connection_or_launch_v3_or_handshake(or_connection_t *conn) +{ + tor_assert(connection_or_nonopen_was_started_here(conn)); + tor_assert(tor_tls_received_v3_certificate(conn->tls)); + + circuit_build_times_network_is_live(&circ_times); + + conn->_base.state = OR_CONN_STATE_OR_HANDSHAKING_V3; + if (connection_init_or_handshake_state(conn, 1) < 0) + return -1; + + return connection_or_send_versions(conn, 1); +} + /** Allocate a new connection handshake state for the connection * <b>conn</b>. Return 0 on success, -1 on failure. */ -static int +int connection_init_or_handshake_state(or_connection_t *conn, int started_here) { or_handshake_state_t *s; s = conn->handshake_state = tor_malloc_zero(sizeof(or_handshake_state_t)); s->started_here = started_here ? 1 : 0; + s->digest_sent_data = 1; + s->digest_received_data = 1; return 0; } @@ -1179,10 +1615,89 @@ or_handshake_state_free(or_handshake_state_t *state) { if (!state) return; + crypto_free_digest_env(state->digest_sent); + crypto_free_digest_env(state->digest_received); + tor_cert_free(state->auth_cert); + tor_cert_free(state->id_cert); memset(state, 0xBE, sizeof(or_handshake_state_t)); tor_free(state); } +/** + * Remember that <b>cell</b> has been transmitted (if <b>incoming</b> is + * false) or received (if <b>incoming is true) during a V3 handshake using + * <b>state</b>. + * + * (We don't record the cell, but we keep a digest of everything sent or + * received during the v3 handshake, and the client signs it in an + * authenticate cell.) + */ +void +or_handshake_state_record_cell(or_handshake_state_t *state, + const cell_t *cell, + int incoming) +{ + crypto_digest_env_t *d, **dptr; + packed_cell_t packed; + if (incoming) { + if (!state->digest_received_data) + return; + } else { + if (!state->digest_sent_data) + return; + } + if (!incoming) { + log_warn(LD_BUG, "We shouldn't be sending any non-variable-length cells " + "while making a handshake digest. But we think we are sending " + "one with type %d.", (int)cell->command); + } + dptr = incoming ? &state->digest_received : &state->digest_sent; + if (! *dptr) + *dptr = crypto_new_digest256_env(DIGEST_SHA256); + + d = *dptr; + /* Re-packing like this is a little inefficient, but we don't have to do + this very often at all. */ + cell_pack(&packed, cell); + crypto_digest_add_bytes(d, packed.body, sizeof(packed.body)); + memset(&packed, 0, sizeof(packed)); +} + +/** Remember that a variable-length <b>cell</b> has been transmitted (if + * <b>incoming</b> is false) or received (if <b>incoming is true) during a V3 + * handshake using <b>state</b>. + * + * (We don't record the cell, but we keep a digest of everything sent or + * received during the v3 handshake, and the client signs it in an + * authenticate cell.) + */ +void +or_handshake_state_record_var_cell(or_handshake_state_t *state, + const var_cell_t *cell, + int incoming) +{ + crypto_digest_env_t *d, **dptr; + char buf[VAR_CELL_HEADER_SIZE]; + if (incoming) { + if (!state->digest_received_data) + return; + } else { + if (!state->digest_sent_data) + return; + } + dptr = incoming ? &state->digest_received : &state->digest_sent; + if (! *dptr) + *dptr = crypto_new_digest256_env(DIGEST_SHA256); + + d = *dptr; + + var_cell_pack_header(cell, buf); + crypto_digest_add_bytes(d, buf, sizeof(buf)); + crypto_digest_add_bytes(d, (const char *)cell->payload, cell->payload_len); + + memset(buf, 0, sizeof(buf)); +} + /** Set <b>conn</b>'s state to OR_CONN_STATE_OPEN, and tell other subsystems * as appropriate. Called when we are done with all TLS and OR handshaking. */ @@ -1212,7 +1727,7 @@ connection_or_set_state_open(or_connection_t *conn) router_set_status(conn->identity_digest, 1); } else { /* only report it to the geoip module if it's not a known router */ - if (!router_get_by_digest(conn->identity_digest)) { + if (!router_get_by_id_digest(conn->identity_digest)) { if (tor_addr_family(&TO_CONN(conn)->addr) == AF_INET) { /*XXXX IP6 support ipv6 geoip.*/ uint32_t a = tor_addr_to_ipv4h(&TO_CONN(conn)->addr); @@ -1223,8 +1738,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; @@ -1246,6 +1765,9 @@ connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn) connection_write_to_buf(networkcell.body, CELL_NETWORK_SIZE, TO_CONN(conn)); + if (conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3) + or_handshake_state_record_cell(conn->handshake_state, cell, 0); + if (cell->command != CELL_PADDING) conn->timestamp_last_added_nonpadding = approx_time(); } @@ -1265,16 +1787,24 @@ connection_or_write_var_cell_to_buf(const var_cell_t *cell, connection_write_to_buf(hdr, sizeof(hdr), TO_CONN(conn)); connection_write_to_buf((char*)cell->payload, cell->payload_len, TO_CONN(conn)); + if (conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3) + or_handshake_state_record_var_cell(conn->handshake_state, cell, 0); if (cell->command != CELL_PADDING) conn->timestamp_last_added_nonpadding = approx_time(); } -/** See whether there's a variable-length cell waiting on <b>conn</b>'s +/** See whether there's a variable-length cell waiting on <b>or_conn</b>'s * inbuf. Return values as for fetch_var_cell_from_buf(). */ static int -connection_fetch_var_cell_from_buf(or_connection_t *conn, var_cell_t **out) +connection_fetch_var_cell_from_buf(or_connection_t *or_conn, var_cell_t **out) { - return fetch_var_cell_from_buf(conn->_base.inbuf, out, conn->link_proto); + connection_t *conn = TO_CONN(or_conn); + IF_HAS_BUFFEREVENT(conn, { + struct evbuffer *input = bufferevent_get_input(conn->bufev); + return fetch_var_cell_from_evbuffer(input, out, or_conn->link_proto); + }) ELSE_IF_NO_BUFFEREVENT { + return fetch_var_cell_from_buf(conn->inbuf, out, or_conn->link_proto); + } } /** Process cells from <b>conn</b>'s inbuf. @@ -1292,7 +1822,7 @@ connection_or_process_cells_from_inbuf(or_connection_t *conn) while (1) { log_debug(LD_OR, "%d: starting, inbuf_datalen %d (%d pending in tls object).", - conn->_base.s,(int)buf_datalen(conn->_base.inbuf), + conn->_base.s,(int)connection_get_inbuf_len(TO_CONN(conn)), tor_tls_get_pending_bytes(conn->tls)); if (connection_fetch_var_cell_from_buf(conn, &var_cell)) { if (!var_cell) @@ -1303,8 +1833,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); @@ -1343,7 +1873,7 @@ connection_or_send_destroy(circid_t circ_id, or_connection_t *conn, int reason) } /** Array of recognized link protocol versions. */ -static const uint16_t or_protocol_versions[] = { 1, 2 }; +static const uint16_t or_protocol_versions[] = { 1, 2, 3 }; /** Number of versions in <b>or_protocol_versions</b>. */ static const int n_or_protocol_versions = (int)( sizeof(or_protocol_versions)/sizeof(uint16_t) ); @@ -1362,20 +1892,33 @@ is_or_protocol_version_known(uint16_t v) } /** Send a VERSIONS cell on <b>conn</b>, telling the other host about the - * link protocol versions that this Tor can support. */ -static int -connection_or_send_versions(or_connection_t *conn) + * link protocol versions that this Tor can support. + * + * If <b>v3_plus</b>, this is part of a V3 protocol handshake, so only + * allow protocol version v3 or later. If not <b>v3_plus</b>, this is + * not part of a v3 protocol handshake, so don't allow protocol v3 or + * later. + **/ +int +connection_or_send_versions(or_connection_t *conn, int v3_plus) { var_cell_t *cell; int i; + int n_versions = 0; + const int min_version = v3_plus ? 3 : 0; + const int max_version = v3_plus ? UINT16_MAX : 2; tor_assert(conn->handshake_state && !conn->handshake_state->sent_versions_at); cell = var_cell_new(n_or_protocol_versions * 2); cell->command = CELL_VERSIONS; for (i = 0; i < n_or_protocol_versions; ++i) { uint16_t v = or_protocol_versions[i]; - set_uint16(cell->payload+(2*i), htons(v)); + if (v < min_version || v > max_version) + continue; + set_uint16(cell->payload+(2*n_versions), htons(v)); + ++n_versions; } + cell->payload_len = n_versions * 2; connection_or_write_var_cell_to_buf(cell, conn); conn->handshake_state->sent_versions_at = time(NULL); @@ -1391,10 +1934,12 @@ 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; + tor_assert(conn->handshake_state); + memset(&cell, 0, sizeof(cell_t)); cell.command = CELL_NETINFO; @@ -1403,13 +1948,20 @@ connection_or_send_netinfo(or_connection_t *conn) /* Their address. */ out = cell.payload + 4; - len = append_address_to_payload(out, &conn->_base.addr); + /* We use &conn->real_addr below, unless it hasn't yet been set. If it + * hasn't yet been set, we know that _base.addr hasn't been tampered with + * yet either. */ + len = append_address_to_payload(out, !tor_addr_is_null(&conn->real_addr) + ? &conn->real_addr : &conn->_base.addr); if (len<0) return -1; out += len; - /* My address. */ - if ((me = router_get_my_routerinfo())) { + /* My address -- only include it if I'm a public relay, or if I'm a + * bridge and this is an incoming connection. If I'm a bridge and this + * is an outgoing connection, act like a normal client and omit it. */ + if ((public_server_mode(get_options()) || !conn->is_outgoing) && + (me = router_get_my_routerinfo())) { tor_addr_t my_addr; *out++ = 1; /* only one address is supported. */ @@ -1421,8 +1973,285 @@ connection_or_send_netinfo(or_connection_t *conn) *out = 0; } + conn->handshake_state->digest_sent_data = 0; connection_or_write_cell_to_buf(&cell, conn); return 0; } +/** Send a CERTS cell on the connection <b>conn</b>. Return 0 on success, -1 + * on failure. */ +int +connection_or_send_certs_cell(or_connection_t *conn) +{ + const tor_cert_t *link_cert = NULL, *id_cert = NULL; + const uint8_t *link_encoded = NULL, *id_encoded = NULL; + size_t link_len, id_len; + var_cell_t *cell; + size_t cell_len; + ssize_t pos; + int server_mode; + + tor_assert(conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3); + + if (! conn->handshake_state) + return -1; + server_mode = ! conn->handshake_state->started_here; + if (tor_tls_get_my_certs(server_mode, &link_cert, &id_cert) < 0) + return -1; + tor_cert_get_der(link_cert, &link_encoded, &link_len); + tor_cert_get_der(id_cert, &id_encoded, &id_len); + + cell_len = 1 /* 1 byte: num certs in cell */ + + 2 * ( 1 + 2 ) /* For each cert: 1 byte for type, 2 for length */ + + link_len + id_len; + cell = var_cell_new(cell_len); + cell->command = CELL_CERTS; + cell->payload[0] = 2; + pos = 1; + + if (server_mode) + cell->payload[pos] = OR_CERT_TYPE_TLS_LINK; /* Link cert */ + else + cell->payload[pos] = OR_CERT_TYPE_AUTH_1024; /* client authentication */ + set_uint16(&cell->payload[pos+1], htons(link_len)); + memcpy(&cell->payload[pos+3], link_encoded, link_len); + pos += 3 + link_len; + + cell->payload[pos] = OR_CERT_TYPE_ID_1024; /* ID cert */ + set_uint16(&cell->payload[pos+1], htons(id_len)); + memcpy(&cell->payload[pos+3], id_encoded, id_len); + pos += 3 + id_len; + + tor_assert(pos == (int)cell_len); /* Otherwise we just smashed the heap */ + + connection_or_write_var_cell_to_buf(cell, conn); + var_cell_free(cell); + + return 0; +} + +/** Send an AUTH_CHALLENGE cell on the connection <b>conn</b>. Return 0 + * on success, -1 on failure. */ +int +connection_or_send_auth_challenge_cell(or_connection_t *conn) +{ + var_cell_t *cell; + uint8_t *cp; + uint8_t challenge[OR_AUTH_CHALLENGE_LEN]; + tor_assert(conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3); + + if (! conn->handshake_state) + return -1; + + if (crypto_rand((char*)challenge, OR_AUTH_CHALLENGE_LEN) < 0) + return -1; + cell = var_cell_new(OR_AUTH_CHALLENGE_LEN + 4); + cell->command = CELL_AUTH_CHALLENGE; + memcpy(cell->payload, challenge, OR_AUTH_CHALLENGE_LEN); + cp = cell->payload + OR_AUTH_CHALLENGE_LEN; + set_uint16(cp, htons(1)); /* We recognize one authentication type. */ + set_uint16(cp+2, htons(AUTHTYPE_RSA_SHA256_TLSSECRET)); + + connection_or_write_var_cell_to_buf(cell, conn); + var_cell_free(cell); + memset(challenge, 0, sizeof(challenge)); + + return 0; +} + +/** Compute the main body of an AUTHENTICATE cell that a client can use + * to authenticate itself on a v3 handshake for <b>conn</b>. Write it to the + * <b>outlen</b>-byte buffer at <b>out</b>. + * + * If <b>server</b> is true, only calculate the first + * V3_AUTH_FIXED_PART_LEN bytes -- the part of the authenticator that's + * determined by the rest of the handshake, and which match the provided value + * exactly. + * + * If <b>server</b> is false and <b>signing_key</b> is NULL, calculate the + * first V3_AUTH_BODY_LEN bytes of the authenticator (that is, everything + * that should be signed), but don't actually sign it. + * + * If <b>server</b> is false and <b>signing_key</b> is provided, calculate the + * entire authenticator, signed with <b>signing_key</b>. + * DOCDOC return value + */ +int +connection_or_compute_authenticate_cell_body(or_connection_t *conn, + uint8_t *out, size_t outlen, + crypto_pk_env_t *signing_key, + int server) +{ + uint8_t *ptr; + + /* assert state is reasonable XXXX */ + + if (outlen < V3_AUTH_FIXED_PART_LEN || + (!server && outlen < V3_AUTH_BODY_LEN)) + return -1; + + ptr = out; + + /* Type: 8 bytes. */ + memcpy(ptr, "AUTH0001", 8); + ptr += 8; + + { + const tor_cert_t *id_cert=NULL, *link_cert=NULL; + const digests_t *my_digests, *their_digests; + const uint8_t *my_id, *their_id, *client_id, *server_id; + if (tor_tls_get_my_certs(0, &link_cert, &id_cert)) + return -1; + my_digests = tor_cert_get_id_digests(id_cert); + their_digests = tor_cert_get_id_digests(conn->handshake_state->id_cert); + tor_assert(my_digests); + tor_assert(their_digests); + my_id = (uint8_t*)my_digests->d[DIGEST_SHA256]; + their_id = (uint8_t*)their_digests->d[DIGEST_SHA256]; + + client_id = server ? their_id : my_id; + server_id = server ? my_id : their_id; + + /* Client ID digest: 32 octets. */ + memcpy(ptr, client_id, 32); + ptr += 32; + + /* Server ID digest: 32 octets. */ + memcpy(ptr, server_id, 32); + ptr += 32; + } + + { + crypto_digest_env_t *server_d, *client_d; + if (server) { + server_d = conn->handshake_state->digest_sent; + client_d = conn->handshake_state->digest_received; + } else { + client_d = conn->handshake_state->digest_sent; + server_d = conn->handshake_state->digest_received; + } + + /* Server log digest : 32 octets */ + crypto_digest_get_digest(server_d, (char*)ptr, 32); + ptr += 32; + + /* Client log digest : 32 octets */ + crypto_digest_get_digest(client_d, (char*)ptr, 32); + ptr += 32; + } + + { + /* Digest of cert used on TLS link : 32 octets. */ + const tor_cert_t *cert = NULL; + tor_cert_t *freecert = NULL; + if (server) { + tor_tls_get_my_certs(1, &cert, NULL); + } else { + freecert = tor_tls_get_peer_cert(conn->tls); + cert = freecert; + } + if (!cert) + return -1; + memcpy(ptr, tor_cert_get_cert_digests(cert)->d[DIGEST_SHA256], 32); + + if (freecert) + tor_cert_free(freecert); + ptr += 32; + } + + /* HMAC of clientrandom and serverrandom using master key : 32 octets */ + tor_tls_get_tlssecrets(conn->tls, ptr); + ptr += 32; + + tor_assert(ptr - out == V3_AUTH_FIXED_PART_LEN); + + if (server) + return V3_AUTH_FIXED_PART_LEN; // ptr-out + + /* Time: 8 octets. */ + { + uint64_t now = time(NULL); + if ((time_t)now < 0) + return -1; + set_uint32(ptr, htonl((uint32_t)(now>>32))); + set_uint32(ptr+4, htonl((uint32_t)now)); + ptr += 8; + } + + /* Nonce: 16 octets. */ + crypto_rand((char*)ptr, 16); + ptr += 16; + + tor_assert(ptr - out == V3_AUTH_BODY_LEN); + + if (!signing_key) + return V3_AUTH_BODY_LEN; // ptr - out + + { + int siglen; + char d[32]; + crypto_digest256(d, (char*)out, ptr-out, DIGEST_SHA256); + siglen = crypto_pk_private_sign(signing_key, + (char*)ptr, outlen - (ptr-out), + d, 32); + if (siglen < 0) + return -1; + + ptr += siglen; + tor_assert(ptr <= out+outlen); + return (int)(ptr - out); + } +} + +/** Send an AUTHENTICATE cell on the connection <b>conn</b>. Return 0 on + * success, -1 on failure */ +int +connection_or_send_authenticate_cell(or_connection_t *conn, int authtype) +{ + var_cell_t *cell; + crypto_pk_env_t *pk = tor_tls_get_my_client_auth_key(); + int authlen; + size_t cell_maxlen; + /* XXXX make sure we're actually supposed to send this! */ + + if (!pk) { + log_warn(LD_BUG, "Can't compute authenticate cell: no client auth key"); + return -1; + } + if (authtype != AUTHTYPE_RSA_SHA256_TLSSECRET) { + log_warn(LD_BUG, "Tried to send authenticate cell with unknown " + "authentication type %d", authtype); + return -1; + } + + cell_maxlen = 4 + /* overhead */ + V3_AUTH_BODY_LEN + /* Authentication body */ + crypto_pk_keysize(pk) + /* Max signature length */ + 16 /* add a few extra bytes just in case. */; + + cell = var_cell_new(cell_maxlen); + cell->command = CELL_AUTHENTICATE; + set_uint16(cell->payload, htons(AUTHTYPE_RSA_SHA256_TLSSECRET)); + /* skip over length ; we don't know that yet. */ + + authlen = connection_or_compute_authenticate_cell_body(conn, + cell->payload+4, + cell_maxlen-4, + pk, + 0 /* not server */); + if (authlen < 0) { + log_warn(LD_BUG, "Unable to compute authenticate cell!"); + var_cell_free(cell); + return -1; + } + tor_assert(authlen + 4 <= cell->payload_len); + set_uint16(cell->payload+2, htons(authlen)); + cell->payload_len = authlen + 4; + + connection_or_write_var_cell_to_buf(cell, conn); + var_cell_free(cell); + + return 0; +} + diff --git a/src/or/connection_or.h b/src/or/connection_or.h index 70ef96a335..62a15b1cf2 100644 --- a/src/or/connection_or.h +++ b/src/or/connection_or.h @@ -14,6 +14,7 @@ void connection_or_remove_from_identity_map(or_connection_t *conn); void connection_or_clear_identity_map(void); +void clear_broken_connection_map(int disable); or_connection_t *connection_or_get_for_extend(const char *digest, const tor_addr_t *target_addr, const char **msg_out, @@ -25,19 +26,40 @@ int connection_or_process_inbuf(or_connection_t *conn); int connection_or_flushed_some(or_connection_t *conn); int connection_or_finished_flushing(or_connection_t *conn); int connection_or_finished_connecting(or_connection_t *conn); +void connection_or_about_to_close(or_connection_t *conn); int connection_or_digest_is_known_relay(const char *id_digest); void connection_or_update_token_buckets(smartlist_t *conns, - or_options_t *options); + const or_options_t *options); void connection_or_connect_failed(or_connection_t *conn, int reason, const char *msg); or_connection_t *connection_or_connect(const tor_addr_t *addr, uint16_t port, const char *id_digest); +void connection_or_report_broken_states(int severity, int domain); + int connection_tls_start_handshake(or_connection_t *conn, int receiving); int connection_tls_continue_handshake(or_connection_t *conn); +int connection_init_or_handshake_state(or_connection_t *conn, + int started_here); +void connection_or_init_conn_from_address(or_connection_t *conn, + const tor_addr_t *addr, + uint16_t port, + const char *id_digest, + int started_here); +int connection_or_client_learned_peer_id(or_connection_t *conn, + const uint8_t *peer_id); +void connection_or_set_circid_type(or_connection_t *conn, + crypto_pk_env_t *identity_rcvd); void or_handshake_state_free(or_handshake_state_t *state); +void or_handshake_state_record_cell(or_handshake_state_t *state, + const cell_t *cell, + int incoming); +void or_handshake_state_record_var_cell(or_handshake_state_t *state, + const var_cell_t *cell, + int incoming); + int connection_or_set_state_open(or_connection_t *conn); void connection_or_write_cell_to_buf(const cell_t *cell, or_connection_t *conn); @@ -45,7 +67,16 @@ void connection_or_write_var_cell_to_buf(const var_cell_t *cell, or_connection_t *conn); int connection_or_send_destroy(circid_t circ_id, or_connection_t *conn, int reason); +int connection_or_send_versions(or_connection_t *conn, int v3_plus); int connection_or_send_netinfo(or_connection_t *conn); +int connection_or_send_certs_cell(or_connection_t *conn); +int connection_or_send_auth_challenge_cell(or_connection_t *conn); +int connection_or_compute_authenticate_cell_body(or_connection_t *conn, + uint8_t *out, size_t outlen, + crypto_pk_env_t *signing_key, + int server); +int connection_or_send_authenticate_cell(or_connection_t *conn, int type); + int is_or_protocol_version_known(uint16_t version); void cell_pack(packed_cell_t *dest, const cell_t *src); diff --git a/src/or/control.c b/src/or/control.c index 1e411ec9c1..e2d0eece02 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -18,6 +18,7 @@ #include "config.h" #include "connection.h" #include "connection_edge.h" +#include "connection_or.h" #include "control.h" #include "directory.h" #include "dirserv.h" @@ -26,12 +27,18 @@ #include "hibernate.h" #include "main.h" #include "networkstatus.h" +#include "nodelist.h" #include "policies.h" #include "reasons.h" #include "router.h" #include "routerlist.h" #include "routerparse.h" +#ifndef MS_WINDOWS +#include <pwd.h> +#include <sys/resource.h> +#endif + #include "procmon.h" /** Yield true iff <b>s</b> is the state of a control_connection_t that has @@ -66,7 +73,9 @@ #define EVENT_CLIENTS_SEEN 0x0015 #define EVENT_NEWCONSENSUS 0x0016 #define EVENT_BUILDTIMEOUT_SET 0x0017 -#define _EVENT_MAX 0x0017 +#define EVENT_SIGNAL 0x0018 +#define EVENT_CONF_CHANGED 0x0019 +#define _EVENT_MAX 0x0019 /* If _EVENT_MAX ever hits 0x0020, we need to make the mask wider. */ /** Bitfield: The bit 1<<e is set if <b>any</b> open control @@ -168,7 +177,7 @@ static int handle_control_resolve(control_connection_t *conn, uint32_t len, static int handle_control_usefeature(control_connection_t *conn, uint32_t len, const char *body); -static int write_stream_target_to_buf(edge_connection_t *conn, char *buf, +static int write_stream_target_to_buf(entry_connection_t *conn, char *buf, size_t len); static void orconn_target_get_name(char *buf, size_t len, or_connection_t *conn); @@ -494,8 +503,8 @@ connection_printf_to_buf(control_connection_t *conn, const char *format, ...) va_end(ap); if (len < 0) { - log_warn(LD_BUG, "Unable to format string for controller."); - return; + log_err(LD_BUG, "Unable to format string for controller."); + tor_assert(0); } connection_write_to_buf(buf, (size_t)len, TO_CONN(conn)); @@ -509,7 +518,7 @@ control_ports_write_to_file(void) { smartlist_t *lines; char *joined = NULL; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); if (!options->ControlPortWriteToFile) return; @@ -593,7 +602,7 @@ send_control_event_string(uint16_t event, event_format_t which, else if (event == EVENT_STATUS_SERVER) is_err = !strcmpstart(msg, "STATUS_SERVER ERR "); if (is_err) - connection_handle_write(TO_CONN(control_conn), 1); + connection_flush(TO_CONN(control_conn)); } } } SMARTLIST_FOREACH_END(conn); @@ -647,7 +656,7 @@ get_circ(const char *id) } /** Given a text stream <b>id</b>, return the corresponding AP connection. */ -static edge_connection_t * +static entry_connection_t * get_stream(const char *id) { uint64_t n_id; @@ -659,7 +668,7 @@ get_stream(const char *id) conn = connection_get_by_global_id(n_id); if (!conn || conn->type != CONN_TYPE_AP || conn->marked_for_close) return NULL; - return TO_EDGE_CONN(conn); + return TO_ENTRY_CONN(conn); } /** Helper for setconf and resetconf. Acts like setconf, except @@ -728,7 +737,7 @@ control_setconf_helper(control_connection_t *conn, uint32_t len, char *body, SMARTLIST_FOREACH(entries, char *, cp, tor_free(cp)); smartlist_free(entries); - if (config_get_lines(config, &lines) < 0) { + if (config_get_lines(config, &lines, 0) < 0) { log_warn(LD_CONTROL,"Controller gave us config lines we can't parse."); connection_write_str_to_buf("551 Couldn't parse configuration\r\n", conn); @@ -798,7 +807,7 @@ handle_control_getconf(control_connection_t *conn, uint32_t body_len, smartlist_t *unrecognized = smartlist_create(); char *msg = NULL; size_t msg_len; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); int i, len; (void) body_len; /* body is NUL-terminated; so we can ignore len. */ @@ -874,7 +883,7 @@ handle_control_loadconf(control_connection_t *conn, uint32_t len, const char *msg = NULL; (void) len; - retval = options_init_from_string(body, CMD_RUN_TOR, NULL, &errstring); + retval = options_init_from_string(NULL, body, CMD_RUN_TOR, NULL, &errstring); if (retval != SETOPT_OK) log_warn(LD_CONTROL, @@ -910,13 +919,45 @@ handle_control_loadconf(control_connection_t *conn, uint32_t len, return 0; } +struct control_event_t { + uint16_t event_code; + const char *event_name; +}; +static const struct control_event_t control_event_table[] = { + { EVENT_CIRCUIT_STATUS, "CIRC" }, + { EVENT_STREAM_STATUS, "STREAM" }, + { EVENT_OR_CONN_STATUS, "ORCONN" }, + { EVENT_BANDWIDTH_USED, "BW" }, + { EVENT_DEBUG_MSG, "DEBUG" }, + { EVENT_INFO_MSG, "INFO" }, + { EVENT_NOTICE_MSG, "NOTICE" }, + { EVENT_WARN_MSG, "WARN" }, + { EVENT_ERR_MSG, "ERR" }, + { EVENT_NEW_DESC, "NEWDESC" }, + { EVENT_ADDRMAP, "ADDRMAP" }, + { EVENT_AUTHDIR_NEWDESCS, "AUTHDIR_NEWDESCS" }, + { EVENT_DESCCHANGED, "DESCCHANGED" }, + { EVENT_NS, "NS" }, + { EVENT_STATUS_GENERAL, "STATUS_GENERAL" }, + { EVENT_STATUS_CLIENT, "STATUS_CLIENT" }, + { EVENT_STATUS_SERVER, "STATUS_SERVER" }, + { EVENT_GUARD, "GUARD" }, + { EVENT_STREAM_BANDWIDTH_USED, "STREAM_BW" }, + { EVENT_CLIENTS_SEEN, "CLIENTS_SEEN" }, + { EVENT_NEWCONSENSUS, "NEWCONSENSUS" }, + { EVENT_BUILDTIMEOUT_SET, "BUILDTIMEOUT_SET" }, + { EVENT_SIGNAL, "SIGNAL" }, + { EVENT_CONF_CHANGED, "CONF_CHANGED"}, + { 0, NULL }, +}; + /** Called when we get a SETEVENTS message: update conn->event_mask, * and reply with DONE or ERROR. */ static int handle_control_setevents(control_connection_t *conn, uint32_t len, const char *body) { - uint16_t event_code; + int event_code = -1; uint32_t event_mask = 0; smartlist_t *events = smartlist_create(); @@ -928,56 +969,22 @@ handle_control_setevents(control_connection_t *conn, uint32_t len, { if (!strcasecmp(ev, "EXTENDED")) { continue; - } else if (!strcasecmp(ev, "CIRC")) - event_code = EVENT_CIRCUIT_STATUS; - else if (!strcasecmp(ev, "STREAM")) - event_code = EVENT_STREAM_STATUS; - else if (!strcasecmp(ev, "ORCONN")) - event_code = EVENT_OR_CONN_STATUS; - else if (!strcasecmp(ev, "BW")) - event_code = EVENT_BANDWIDTH_USED; - else if (!strcasecmp(ev, "DEBUG")) - event_code = EVENT_DEBUG_MSG; - else if (!strcasecmp(ev, "INFO")) - event_code = EVENT_INFO_MSG; - else if (!strcasecmp(ev, "NOTICE")) - event_code = EVENT_NOTICE_MSG; - else if (!strcasecmp(ev, "WARN")) - event_code = EVENT_WARN_MSG; - else if (!strcasecmp(ev, "ERR")) - event_code = EVENT_ERR_MSG; - else if (!strcasecmp(ev, "NEWDESC")) - event_code = EVENT_NEW_DESC; - else if (!strcasecmp(ev, "ADDRMAP")) - event_code = EVENT_ADDRMAP; - else if (!strcasecmp(ev, "AUTHDIR_NEWDESCS")) - event_code = EVENT_AUTHDIR_NEWDESCS; - else if (!strcasecmp(ev, "DESCCHANGED")) - event_code = EVENT_DESCCHANGED; - else if (!strcasecmp(ev, "NS")) - event_code = EVENT_NS; - else if (!strcasecmp(ev, "STATUS_GENERAL")) - event_code = EVENT_STATUS_GENERAL; - else if (!strcasecmp(ev, "STATUS_CLIENT")) - event_code = EVENT_STATUS_CLIENT; - else if (!strcasecmp(ev, "STATUS_SERVER")) - event_code = EVENT_STATUS_SERVER; - else if (!strcasecmp(ev, "GUARD")) - event_code = EVENT_GUARD; - else if (!strcasecmp(ev, "STREAM_BW")) - event_code = EVENT_STREAM_BANDWIDTH_USED; - else if (!strcasecmp(ev, "CLIENTS_SEEN")) - event_code = EVENT_CLIENTS_SEEN; - else if (!strcasecmp(ev, "NEWCONSENSUS")) - event_code = EVENT_NEWCONSENSUS; - else if (!strcasecmp(ev, "BUILDTIMEOUT_SET")) - event_code = EVENT_BUILDTIMEOUT_SET; - else { - connection_printf_to_buf(conn, "552 Unrecognized event \"%s\"\r\n", - ev); - SMARTLIST_FOREACH(events, char *, e, tor_free(e)); - smartlist_free(events); - return 0; + } else { + int i; + for (i = 0; control_event_table[i].event_name != NULL; ++i) { + if (!strcasecmp(ev, control_event_table[i].event_name)) { + event_code = control_event_table[i].event_code; + break; + } + } + + if (event_code == -1) { + connection_printf_to_buf(conn, "552 Unrecognized event \"%s\"\r\n", + ev); + SMARTLIST_FOREACH(events, char *, e, tor_free(e)); + smartlist_free(events); + return 0; + } } event_mask |= (1 << event_code); } @@ -1039,7 +1046,7 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len, const char *body) { int used_quoted_string = 0; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); const char *errstr = NULL; char *password; size_t password_len; @@ -1048,7 +1055,10 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len, int bad_cookie=0, bad_password=0; smartlist_t *sl = NULL; - if (TOR_ISXDIGIT(body[0])) { + if (!len) { + password = tor_strdup(""); + password_len = 0; + } else if (TOR_ISXDIGIT(body[0])) { cp = body; while (TOR_ISXDIGIT(*cp)) ++cp; @@ -1065,9 +1075,6 @@ handle_control_authenticate(control_connection_t *conn, uint32_t len, tor_free(password); return 0; } - } else if (TOR_ISSPACE(body[0])) { - password = tor_strdup(""); - password_len = 0; } else { if (!decode_escaped_string(body, len, &password, &password_len)) { connection_write_str_to_buf("551 Invalid quoted string. You need " @@ -1248,7 +1255,7 @@ handle_control_signal(control_connection_t *conn, uint32_t len, send_control_done(conn); /* Flush the "done" first if the signal might make us shut down. */ if (sig == SIGTERM || sig == SIGINT) - connection_handle_write(TO_CONN(conn), 1); + connection_flush(TO_CONN(conn)); process_signal(sig); @@ -1371,17 +1378,24 @@ getinfo_helper_misc(control_connection_t *conn, const char *question, if (!strcmp(question, "version")) { *answer = tor_strdup(get_version()); } else if (!strcmp(question, "config-file")) { - *answer = tor_strdup(get_torrc_fname()); + *answer = tor_strdup(get_torrc_fname(0)); + } else if (!strcmp(question, "config-defaults-file")) { + *answer = tor_strdup(get_torrc_fname(1)); } else if (!strcmp(question, "config-text")) { *answer = options_dump(get_options(), 1); } else if (!strcmp(question, "info/names")) { *answer = list_getinfo_options(); } else if (!strcmp(question, "events/names")) { - *answer = tor_strdup("CIRC STREAM ORCONN BW DEBUG INFO NOTICE WARN ERR " - "NEWDESC ADDRMAP AUTHDIR_NEWDESCS DESCCHANGED " - "NS STATUS_GENERAL STATUS_CLIENT STATUS_SERVER " - "GUARD STREAM_BW CLIENTS_SEEN NEWCONSENSUS " - "BUILDTIMEOUT_SET"); + int i; + smartlist_t *event_names = smartlist_create(); + + for (i = 0; control_event_table[i].event_name != NULL; ++i) { + smartlist_add(event_names, (char *)control_event_table[i].event_name); + } + + *answer = smartlist_join_strings(event_names, " ", 0, NULL); + + smartlist_free(event_names); } else if (!strcmp(question, "features/names")) { *answer = tor_strdup("VERBOSE_NAMES EXTENDED_EVENTS"); } else if (!strcmp(question, "address")) { @@ -1391,6 +1405,61 @@ getinfo_helper_misc(control_connection_t *conn, const char *question, return -1; } *answer = tor_dup_ip(addr); + } else if (!strcmp(question, "traffic/read")) { + tor_asprintf(answer, U64_FORMAT, U64_PRINTF_ARG(get_bytes_read())); + } else if (!strcmp(question, "traffic/written")) { + tor_asprintf(answer, U64_FORMAT, U64_PRINTF_ARG(get_bytes_written())); + } else if (!strcmp(question, "process/pid")) { + int myPid = -1; + + #ifdef MS_WINDOWS + myPid = _getpid(); + #else + myPid = getpid(); + #endif + + tor_asprintf(answer, "%d", myPid); + } else if (!strcmp(question, "process/uid")) { + #ifdef MS_WINDOWS + *answer = tor_strdup("-1"); + #else + int myUid = geteuid(); + tor_asprintf(answer, "%d", myUid); + #endif + } else if (!strcmp(question, "process/user")) { + #ifdef MS_WINDOWS + *answer = tor_strdup(""); + #else + int myUid = geteuid(); + struct passwd *myPwEntry = getpwuid(myUid); + + if (myPwEntry) { + *answer = tor_strdup(myPwEntry->pw_name); + } else { + *answer = tor_strdup(""); + } + #endif + } else if (!strcmp(question, "process/descriptor-limit")) { + /** platform specifc limits are from the set_max_file_descriptors function + * of src/common/compat.c */ + /* XXXX023 This is duplicated code from compat.c; it should turn into a + * function. */ + #ifdef HAVE_GETRLIMIT + struct rlimit descriptorLimit; + + if (getrlimit(RLIMIT_NOFILE, &descriptorLimit) == 0) { + tor_asprintf(answer, U64_FORMAT, + U64_PRINTF_ARG(descriptorLimit.rlim_max)); + } else { + *answer = tor_strdup("-1"); + } + #elif defined(CYGWIN) || defined(__CYGWIN__) + *answer = tor_strdup("3200"); + #elif defined(MS_WINDOWS) + *answer = tor_strdup("15000"); + #else + *answer = tor_strdup("15000"); + #endif } else if (!strcmp(question, "dir-usage")) { *answer = directory_dump_request_log(); } else if (!strcmp(question, "fingerprint")) { @@ -1416,8 +1485,9 @@ getinfo_helper_misc(control_connection_t *conn, const char *question, * NOTE: <b>ri_body</b> is as returned by signed_descriptor_get_body: it might * not be NUL-terminated. */ static char * -munge_extrainfo_into_routerinfo(const char *ri_body, signed_descriptor_t *ri, - signed_descriptor_t *ei) +munge_extrainfo_into_routerinfo(const char *ri_body, + const signed_descriptor_t *ri, + const signed_descriptor_t *ei) { char *out = NULL, *outp; int i; @@ -1519,16 +1589,19 @@ 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); + /* XXX023 Setting 'warn_if_unnamed' here is a bit silly -- the + * warning goes to the user, not to the controller. */ + ri = router_get_by_nickname(question+strlen("desc/name/"),1); if (ri) { const char *body = signed_descriptor_get_body(&ri->cache_info); if (body) @@ -1538,7 +1611,7 @@ getinfo_helper_dir(control_connection_t *control_conn, routerlist_t *routerlist = router_get_routerlist(); smartlist_t *sl = smartlist_create(); if (routerlist && routerlist->routers) { - SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri, + SMARTLIST_FOREACH(routerlist->routers, const routerinfo_t *, ri, { const char *body = signed_descriptor_get_body(&ri->cache_info); if (body) @@ -1554,7 +1627,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,9 +1644,28 @@ getinfo_helper_dir(control_connection_t *control_conn, *answer = smartlist_join_strings(sl, "", 0, NULL); SMARTLIST_FOREACH(sl, char *, c, tor_free(c)); smartlist_free(sl); + } else if (!strcmpstart(question, "md/id/")) { + const node_t *node = node_get_by_hex_id(question+strlen("md/id/")); + const microdesc_t *md = NULL; + if (node) md = node->md; + if (md) { + tor_assert(md->body); + *answer = tor_strndup(md->body, md->bodylen); + } + } else if (!strcmpstart(question, "md/name/")) { + /* XXX023 Setting 'warn_if_unnamed' here is a bit silly -- the + * warning goes to the user, not to the controller. */ + const node_t *node = node_get_by_nickname(question+strlen("md/name/"), 1); + /* XXXX duplicated code */ + const microdesc_t *md = NULL; + if (node) md = node->md; + if (md) { + tor_assert(md->body); + *answer = tor_strndup(md->body, md->bodylen); + } } else if (!strcmpstart(question, "desc-annotations/id/")) { - routerinfo_t *ri = router_get_by_hexdigest(question+ - strlen("desc-annotations/id/")); + ri = router_get_by_hexdigest(question+ + strlen("desc-annotations/id/")); if (ri) { const char *annotations = signed_descriptor_get_annotations(&ri->cache_info); @@ -1733,7 +1825,7 @@ getinfo_helper_events(control_connection_t *control_conn, char buf[256]; SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) { const char *state; - edge_connection_t *conn; + entry_connection_t *conn; char *s; size_t slen; circuit_t *circ; @@ -1743,8 +1835,8 @@ getinfo_helper_events(control_connection_t *control_conn, base_conn->state == AP_CONN_STATE_SOCKS_WAIT || base_conn->state == AP_CONN_STATE_NATD_WAIT) continue; - conn = TO_EDGE_CONN(base_conn); - switch (conn->_base.state) + conn = TO_ENTRY_CONN(base_conn); + switch (base_conn->state) { case AP_CONN_STATE_CONTROLLER_WAIT: case AP_CONN_STATE_CIRCUIT_WAIT: @@ -1763,17 +1855,17 @@ getinfo_helper_events(control_connection_t *control_conn, state = "SUCCEEDED"; break; default: log_warn(LD_BUG, "Asked for stream in unknown state %d", - conn->_base.state); + base_conn->state); continue; } - circ = circuit_get_by_edge_conn(conn); + circ = circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn)); if (circ && CIRCUIT_IS_ORIGIN(circ)) origin_circ = TO_ORIGIN_CIRCUIT(circ); write_stream_target_to_buf(conn, buf, sizeof(buf)); slen = strlen(buf)+strlen(state)+32; s = tor_malloc(slen+1); tor_snprintf(s, slen, "%lu %s %lu %s", - (unsigned long) conn->_base.global_identifier,state, + (unsigned long) base_conn->global_identifier,state, origin_circ? (unsigned long)origin_circ->global_identifier : 0ul, buf); @@ -1886,7 +1978,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); @@ -1934,6 +2026,7 @@ typedef struct getinfo_item_t { static const getinfo_item_t getinfo_items[] = { ITEM("version", misc, "The current version of Tor."), ITEM("config-file", misc, "Current location of the \"torrc\" file."), + ITEM("config-defaults-file", misc, "Current location of the defaults file."), ITEM("config-text", misc, "Return the string that would be written by a saveconf command."), ITEM("accounting/bytes", accounting, @@ -1965,6 +2058,8 @@ static const getinfo_item_t getinfo_items[] = { ITEM("desc/all-recent", dir, "All non-expired, non-superseded router descriptors."), ITEM("desc/all-recent-extrainfo-hack", dir, NULL), /* Hack. */ + PREFIX("md/id/", dir, "Microdescriptors by ID"), + PREFIX("md/name/", dir, "Microdescriptors by name"), PREFIX("extra-info/digest/", dir, "Extra-info documents by digest."), PREFIX("net/listeners/", listeners, "Bound addresses by type"), ITEM("ns/all", networkstatus, @@ -2004,6 +2099,14 @@ static const getinfo_item_t getinfo_items[] = { "Number of versioning authorities agreeing on the status of the " "current version"), ITEM("address", misc, "IP address of this Tor host, if we can guess it."), + ITEM("traffic/read", misc,"Bytes read since the process was started."), + ITEM("traffic/written", misc, + "Bytes written since the process was started."), + ITEM("process/pid", misc, "Process id belonging to the main tor process."), + ITEM("process/uid", misc, "User id running the tor process."), + ITEM("process/user", misc, + "Username under which the tor process is running."), + ITEM("process/descriptor-limit", misc, "File descriptor limit."), ITEM("dir-usage", misc, "Breakdown of bytes transferred over DirPort."), PREFIX("desc-annotations/id/", dir, "Router annotations by hexdigest."), PREFIX("dir/server/", dir,"Router descriptors as retrieved from a DirPort."), @@ -2213,7 +2316,7 @@ static int handle_control_extendcircuit(control_connection_t *conn, uint32_t len, const char *body) { - smartlist_t *router_nicknames=NULL, *routers=NULL; + smartlist_t *router_nicknames=NULL, *nodes=NULL; origin_circuit_t *circ = NULL; int zero_circ; uint8_t intended_purpose = CIRCUIT_PURPOSE_C_GENERAL; @@ -2244,8 +2347,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len, if ((smartlist_len(args) == 1) || (smartlist_len(args) >= 2 && is_keyval_pair(smartlist_get(args, 1)))) { // "EXTENDCIRCUIT 0" || EXTENDCIRCUIT 0 foo=bar" - circ = circuit_launch_by_router(intended_purpose, NULL, - CIRCLAUNCH_NEED_CAPACITY); + circ = circuit_launch(intended_purpose, CIRCLAUNCH_NEED_CAPACITY); if (!circ) { connection_write_str_to_buf("551 Couldn't start circuit\r\n", conn); } else { @@ -2273,17 +2375,21 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len, SMARTLIST_FOREACH(args, char *, cp, tor_free(cp)); smartlist_free(args); - routers = smartlist_create(); + nodes = smartlist_create(); SMARTLIST_FOREACH(router_nicknames, const char *, n, { - routerinfo_t *r = router_get_by_nickname(n, 1); - if (!r) { + const node_t *node = node_get_by_nickname(n, 1); + if (!node) { connection_printf_to_buf(conn, "552 No such router \"%s\"\r\n", n); goto done; } - smartlist_add(routers, r); + if (!node_has_descriptor(node)) { + connection_printf_to_buf(conn, "552 descriptor for \"%s\"\r\n", n); + goto done; + } + smartlist_add(nodes, (void*)node); }); - if (!smartlist_len(routers)) { + if (!smartlist_len(nodes)) { connection_write_str_to_buf("512 No router names provided\r\n", conn); goto done; } @@ -2294,9 +2400,10 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len, } /* now circ refers to something that is ready to be extended */ - SMARTLIST_FOREACH(routers, routerinfo_t *, r, + SMARTLIST_FOREACH(nodes, const node_t *, node, { - extend_info_t *info = extend_info_from_router(r); + extend_info_t *info = extend_info_from_node(node); + tor_assert(info); /* True, since node_has_descriptor(node) == true */ circuit_append_new_exit(circ, info); extend_info_free(info); }); @@ -2330,7 +2437,7 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len, done: SMARTLIST_FOREACH(router_nicknames, char *, n, tor_free(n)); smartlist_free(router_nicknames); - smartlist_free(routers); + smartlist_free(nodes); return 0; } @@ -2381,7 +2488,7 @@ static int handle_control_attachstream(control_connection_t *conn, uint32_t len, const char *body) { - edge_connection_t *ap_conn = NULL; + entry_connection_t *ap_conn = NULL; origin_circuit_t *circ = NULL; int zero_circ; smartlist_t *args; @@ -2417,9 +2524,9 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len, if (!ap_conn || (!zero_circ && !circ) || !hop_line_ok) return 0; - if (ap_conn->_base.state != AP_CONN_STATE_CONTROLLER_WAIT && - ap_conn->_base.state != AP_CONN_STATE_CONNECT_WAIT && - ap_conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT) { + if (ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_CONTROLLER_WAIT && + ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_CONNECT_WAIT && + ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_RESOLVE_WAIT) { connection_write_str_to_buf( "555 Connection is not managed by controller.\r\n", conn); @@ -2427,15 +2534,16 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len, } /* Do we need to detach it first? */ - if (ap_conn->_base.state != AP_CONN_STATE_CONTROLLER_WAIT) { - circuit_t *tmpcirc = circuit_get_by_edge_conn(ap_conn); - connection_edge_end(ap_conn, END_STREAM_REASON_TIMEOUT); + if (ENTRY_TO_CONN(ap_conn)->state != AP_CONN_STATE_CONTROLLER_WAIT) { + edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(ap_conn); + circuit_t *tmpcirc = circuit_get_by_edge_conn(edge_conn); + connection_edge_end(edge_conn, END_STREAM_REASON_TIMEOUT); /* Un-mark it as ending, since we're going to reuse it. */ - ap_conn->edge_has_sent_end = 0; - ap_conn->end_reason = 0; + edge_conn->edge_has_sent_end = 0; + edge_conn->end_reason = 0; if (tmpcirc) - circuit_detach_stream(tmpcirc,ap_conn); - ap_conn->_base.state = AP_CONN_STATE_CONTROLLER_WAIT; + circuit_detach_stream(tmpcirc, edge_conn); + TO_CONN(edge_conn)->state = AP_CONN_STATE_CONTROLLER_WAIT; } if (circ && (circ->_base.state != CIRCUIT_STATE_OPEN)) { @@ -2446,16 +2554,17 @@ handle_control_attachstream(control_connection_t *conn, uint32_t len, } /* Is this a single hop circuit? */ if (circ && (circuit_get_cpath_len(circ)<2 || hop==1)) { - routerinfo_t *r = NULL; - char* exit_digest; + const node_t *node = NULL; + char *exit_digest; if (circ->build_state && circ->build_state->chosen_exit && !tor_digest_is_zero(circ->build_state->chosen_exit->identity_digest)) { exit_digest = circ->build_state->chosen_exit->identity_digest; - r = router_get_by_digest(exit_digest); + node = node_get_by_id(exit_digest); } /* Do both the client and relay allow one-hop exit circuits? */ - if (!r || !r->allow_single_hop_exits || + if (!node || + !node_allows_single_hop_exits(node) || !get_options()->AllowSingleHopCircuits) { connection_write_str_to_buf( "551 Can't attach stream to this one-hop circuit.\r\n", conn); @@ -2556,7 +2665,7 @@ static int handle_control_redirectstream(control_connection_t *conn, uint32_t len, const char *body) { - edge_connection_t *ap_conn = NULL; + entry_connection_t *ap_conn = NULL; char *new_addr = NULL; uint16_t new_port = 0; smartlist_t *args; @@ -2604,7 +2713,7 @@ static int handle_control_closestream(control_connection_t *conn, uint32_t len, const char *body) { - edge_connection_t *ap_conn=NULL; + entry_connection_t *ap_conn=NULL; uint8_t reason=0; smartlist_t *args; int ok; @@ -2749,7 +2858,7 @@ handle_control_protocolinfo(control_connection_t *conn, uint32_t len, connection_mark_for_close(TO_CONN(conn)); goto done; } else { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); int cookies = options->CookieAuthentication; char *cfile = get_cookie_file(); char *esc_cfile = esc_for_log(cfile); @@ -2827,8 +2936,6 @@ int connection_control_finished_flushing(control_connection_t *conn) { tor_assert(conn); - - connection_stop_writing(TO_CONN(conn)); return 0; } @@ -2900,6 +3007,17 @@ is_valid_initial_command(control_connection_t *conn, const char *cmd) * interfaces is broken. */ #define MAX_COMMAND_LINE_LENGTH (1024*1024) +static int +peek_connection_has_control0_command(connection_t *conn) +{ + IF_HAS_BUFFEREVENT(conn, { + struct evbuffer *input = bufferevent_get_input(conn->bufev); + return peek_evbuffer_has_control0_command(input); + }) ELSE_IF_NO_BUFFEREVENT { + return peek_buf_has_control0_command(conn->inbuf); + } +} + /** Called when data has arrived on a v1 control connection: Try to fetch * commands from conn->inbuf, and execute them. */ @@ -2922,7 +3040,7 @@ connection_control_process_inbuf(control_connection_t *conn) } if (conn->_base.state == CONTROL_CONN_STATE_NEEDAUTH && - peek_buf_has_control0_command(conn->_base.inbuf)) { + peek_connection_has_control0_command(TO_CONN(conn))) { /* Detect v0 commands and send a "no more v0" message. */ size_t body_len; char buf[128]; @@ -2934,8 +3052,8 @@ connection_control_process_inbuf(control_connection_t *conn) body_len = 2+strlen(buf+6)+2; /* code, msg, nul. */ set_uint16(buf+0, htons(body_len)); connection_write_to_buf(buf, 4+body_len, TO_CONN(conn)); - connection_mark_for_close(TO_CONN(conn)); - conn->_base.hold_open_until_flushed = 1; + + connection_mark_and_flush(TO_CONN(conn)); return 0; } @@ -2946,7 +3064,7 @@ connection_control_process_inbuf(control_connection_t *conn) /* First, fetch a line. */ do { data_len = conn->incoming_cmd_len - conn->incoming_cmd_cur_len; - r = fetch_from_buf_line(conn->_base.inbuf, + r = connection_fetch_from_buf_line(TO_CONN(conn), conn->incoming_cmd+conn->incoming_cmd_cur_len, &data_len); if (r == 0) @@ -2956,8 +3074,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; @@ -3004,7 +3121,7 @@ connection_control_process_inbuf(control_connection_t *conn) args = conn->incoming_cmd+cmd_len+1; tor_assert(data_len>(size_t)cmd_len); data_len -= (cmd_len+1); /* skip the command and NUL we added after it */ - while (*args == ' ' || *args == '\t') { + while (TOR_ISSPACE(*args)) { ++args; --data_len; } @@ -3017,8 +3134,7 @@ connection_control_process_inbuf(control_connection_t *conn) /* Otherwise, Quit is always valid. */ if (!strcasecmp(conn->incoming_cmd, "QUIT")) { connection_write_str_to_buf("250 closing connection\r\n", conn); - connection_mark_for_close(TO_CONN(conn)); - conn->_base.hold_open_until_flushed = 1; + connection_mark_and_flush(TO_CONN(conn)); return 0; } @@ -3177,7 +3293,7 @@ control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t tp, * <b>conn</b>, and write it to <b>buf</b>. Return 0 on success, -1 on * failure. */ static int -write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len) +write_stream_target_to_buf(entry_connection_t *conn, char *buf, size_t len) { char buf2[256]; if (conn->chosen_exit_name) @@ -3188,8 +3304,8 @@ write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len) if (tor_snprintf(buf, len, "%s%s%s:%d", conn->socks_request->address, conn->chosen_exit_name ? buf2 : "", - !conn->chosen_exit_name && - connection_edge_is_rendezvous_stream(conn) ? ".onion" : "", + !conn->chosen_exit_name && connection_edge_is_rendezvous_stream( + ENTRY_TO_EDGE_CONN(conn)) ? ".onion" : "", conn->socks_request->port)<0) return -1; return 0; @@ -3198,7 +3314,7 @@ write_stream_target_to_buf(edge_connection_t *conn, char *buf, size_t len) /** Something has happened to the stream associated with AP connection * <b>conn</b>: tell any interested control connections. */ int -control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp, +control_event_stream_status(entry_connection_t *conn, stream_status_event_t tp, int reason_code) { char reason_buf[64]; @@ -3270,7 +3386,7 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp, if (tp == STREAM_EVENT_NEW) { tor_snprintf(addrport_buf,sizeof(addrport_buf), " SOURCE_ADDR=%s:%d", - TO_CONN(conn)->address, TO_CONN(conn)->port ); + ENTRY_TO_CONN(conn)->address, ENTRY_TO_CONN(conn)->port); } else { addrport_buf[0] = '\0'; } @@ -3278,12 +3394,12 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp, if (tp == STREAM_EVENT_NEW_RESOLVE) { purpose = " PURPOSE=DNS_REQUEST"; } else if (tp == STREAM_EVENT_NEW) { - if (conn->is_dns_request || + if (ENTRY_TO_EDGE_CONN(conn)->is_dns_request || (conn->socks_request && SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command))) purpose = " PURPOSE=DNS_REQUEST"; else if (conn->use_begindir) { - connection_t *linked = TO_CONN(conn)->linked_conn; + connection_t *linked = ENTRY_TO_CONN(conn)->linked_conn; int linked_dir_purpose = -1; if (linked && linked->type == CONN_TYPE_DIR) linked_dir_purpose = linked->purpose; @@ -3295,12 +3411,13 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp, purpose = " PURPOSE=USER"; } - circ = circuit_get_by_edge_conn(conn); + circ = circuit_get_by_edge_conn(ENTRY_TO_EDGE_CONN(conn)); if (circ && CIRCUIT_IS_ORIGIN(circ)) origin_circ = TO_ORIGIN_CIRCUIT(circ); send_control_event(EVENT_STREAM_STATUS, ALL_FORMATS, "650 STREAM "U64_FORMAT" %s %lu %s%s%s%s\r\n", - U64_PRINTF_ARG(conn->_base.global_identifier), status, + U64_PRINTF_ARG(ENTRY_TO_CONN(conn)->global_identifier), + status, origin_circ? (unsigned long)origin_circ->global_identifier : 0ul, buf, reason_buf, addrport_buf, purpose); @@ -3316,10 +3433,10 @@ control_event_stream_status(edge_connection_t *conn, stream_status_event_t tp, static void orconn_target_get_name(char *name, size_t len, or_connection_t *conn) { - routerinfo_t *ri = router_get_by_digest(conn->identity_digest); - if (ri) { + const node_t *node = node_get_by_id(conn->identity_digest); + if (node) { tor_assert(len > MAX_VERBOSE_NICKNAME_LEN); - router_get_verbose_nickname(name, ri); + node_get_verbose_nickname(node, name); } else if (! tor_digest_is_zero(conn->identity_digest)) { name[0] = '$'; base16_encode(name+1, len-1, conn->identity_digest, @@ -3636,7 +3753,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; @@ -3724,10 +3841,46 @@ control_event_buildtimeout_set(const circuit_build_times_t *cbt, return 0; } +/** Called when a signal has been processed from signal_callback */ +int +control_event_signal(uintptr_t signal) +{ + const char *signal_string = NULL; + + if (!control_event_is_interesting(EVENT_SIGNAL)) + return 0; + + switch (signal) { + case SIGHUP: + signal_string = "RELOAD"; + break; + case SIGUSR1: + signal_string = "DUMP"; + break; + case SIGUSR2: + signal_string = "DEBUG"; + break; + case SIGNEWNYM: + signal_string = "NEWNYM"; + break; + case SIGCLEARDNSCACHE: + signal_string = "CLEARDNSCACHE"; + break; + default: + log_warn(LD_BUG, "Unrecognized signal %lu in control_event_signal", + (unsigned long)signal); + return -1; + } + + send_control_event(EVENT_SIGNAL, ALL_FORMATS, "650 SIGNAL %s\r\n", + signal_string); + return 0; +} + /** Called when a single local_routerstatus_t has changed: Sends an NS event * to any controller that cares. */ int -control_event_networkstatus_changed_single(routerstatus_t *rs) +control_event_networkstatus_changed_single(const routerstatus_t *rs) { smartlist_t *statuses; int r; @@ -3736,7 +3889,7 @@ control_event_networkstatus_changed_single(routerstatus_t *rs) return 0; statuses = smartlist_create(); - smartlist_add(statuses, rs); + smartlist_add(statuses, (void*)rs); r = control_event_networkstatus_changed(statuses); smartlist_free(statuses); return r; @@ -3861,9 +4014,9 @@ control_event_guard(const char *nickname, const char *digest, { char buf[MAX_VERBOSE_NICKNAME_LEN+1]; - routerinfo_t *ri = router_get_by_digest(digest); - if (ri) { - router_get_verbose_nickname(buf, ri); + const node_t *node = node_get_by_id(digest); + if (node) { + node_get_verbose_nickname(node, buf); } else { tor_snprintf(buf, sizeof(buf), "$%s~%s", hbuf, nickname); } @@ -3873,12 +4026,45 @@ control_event_guard(const char *nickname, const char *digest, return 0; } +/** Called when a configuration option changes. This is generally triggered + * by SETCONF requests and RELOAD/SIGHUP signals. The <b>elements</b> is + * a smartlist_t containing (key, value, ...) pairs in sequence. + * <b>value</b> can be NULL. */ +int +control_event_conf_changed(smartlist_t *elements) +{ + int i; + char *result; + smartlist_t *lines; + if (!EVENT_IS_INTERESTING(EVENT_CONF_CHANGED) || + smartlist_len(elements) == 0) { + return 0; + } + lines = smartlist_create(); + for (i = 0; i < smartlist_len(elements); i += 2) { + char *k = smartlist_get(elements, i); + char *v = smartlist_get(elements, i+1); + if (v == NULL) { + smartlist_asprintf_add(lines, "650-%s", k); + } else { + smartlist_asprintf_add(lines, "650-%s=%s", k, v); + } + } + result = smartlist_join_strings(lines, "\r\n", 0, NULL); + send_control_event(EVENT_CONF_CHANGED, 0, + "650-CONF_CHANGED\r\n%s\r\n650 OK\r\n", result); + tor_free(result); + SMARTLIST_FOREACH(lines, char *, cp, tor_free(cp)); + smartlist_free(lines); + return 0; +} + /** Helper: Return a newly allocated string containing a path to the * file where we store our authentication cookie. */ static char * get_cookie_file(void) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); if (options->CookieAuthFile && strlen(options->CookieAuthFile)) { return tor_strdup(options->CookieAuthFile); } else { @@ -4146,6 +4332,7 @@ control_event_bootstrap_problem(const char *warn, int reason) const char *tag, *summary; char buf[BOOTSTRAP_MSG_LEN]; const char *recommendation = "ignore"; + int severity; /* bootstrap_percent must not be in "undefined" state here. */ tor_assert(status >= 0); @@ -4170,12 +4357,17 @@ control_event_bootstrap_problem(const char *warn, int reason) status--; /* find a recognized status string based on current progress */ status = bootstrap_percent; /* set status back to the actual number */ - log_fn(!strcmp(recommendation, "warn") ? LOG_WARN : LOG_INFO, + severity = !strcmp(recommendation, "warn") ? LOG_WARN : LOG_INFO; + + log_fn(severity, LD_CONTROL, "Problem bootstrapping. Stuck at %d%%: %s. (%s; %s; " "count %d; recommendation %s)", status, summary, warn, orconn_end_reason_to_control_string(reason), bootstrap_problems, recommendation); + + connection_or_report_broken_states(severity, LD_HANDSHAKE); + tor_snprintf(buf, sizeof(buf), "BOOTSTRAP PROGRESS=%d TAG=%s SUMMARY=\"%s\" WARNING=\"%s\" REASON=%s " "COUNT=%d RECOMMENDATION=%s", diff --git a/src/or/control.h b/src/or/control.h index ddea4cd548..0d9acd26ef 100644 --- a/src/or/control.h +++ b/src/or/control.h @@ -37,7 +37,7 @@ int control_event_is_interesting(int event); int control_event_circuit_status(origin_circuit_t *circ, circuit_status_event_t e, int reason); -int control_event_stream_status(edge_connection_t *conn, +int control_event_stream_status(entry_connection_t *conn, stream_status_event_t e, int reason); int control_event_or_conn_status(or_connection_t *conn, @@ -57,7 +57,7 @@ int control_event_my_descriptor_changed(void); int control_event_networkstatus_changed(smartlist_t *statuses); int control_event_newconsensus(const networkstatus_t *consensus); -int control_event_networkstatus_changed_single(routerstatus_t *rs); +int control_event_networkstatus_changed_single(const routerstatus_t *rs); int control_event_general_status(int severity, const char *format, ...) CHECK_PRINTF(2,3); int control_event_client_status(int severity, const char *format, ...) @@ -66,8 +66,10 @@ int control_event_server_status(int severity, const char *format, ...) CHECK_PRINTF(2,3); int control_event_guard(const char *nickname, const char *digest, const char *status); +int control_event_conf_changed(smartlist_t *elements); int control_event_buildtimeout_set(const circuit_build_times_t *cbt, buildtimeout_set_event_t type); +int control_event_signal(uintptr_t signal); int init_cookie_authentication(int enabled); smartlist_t *decode_hashed_passwords(config_line_t *passwords); diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index c5e4863f7f..914003790a 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -62,7 +62,6 @@ connection_cpu_finished_flushing(connection_t *conn) { tor_assert(conn); tor_assert(conn->type == CONN_TYPE_CPUWORKER); - connection_stop_writing(conn); return 0; } @@ -141,13 +140,13 @@ connection_cpu_process_inbuf(connection_t *conn) tor_assert(conn); tor_assert(conn->type == CONN_TYPE_CPUWORKER); - if (!buf_datalen(conn->inbuf)) + if (!connection_get_inbuf_len(conn)) return 0; if (conn->state == CPUWORKER_STATE_BUSY_ONION) { - if (buf_datalen(conn->inbuf) < LEN_ONION_RESPONSE) /* answer available? */ + if (connection_get_inbuf_len(conn) < LEN_ONION_RESPONSE) return 0; /* not yet */ - tor_assert(buf_datalen(conn->inbuf) == LEN_ONION_RESPONSE); + tor_assert(connection_get_inbuf_len(conn) == LEN_ONION_RESPONSE); connection_fetch_from_buf(&success,1,conn); connection_fetch_from_buf(buf,LEN_ONION_RESPONSE-1,conn); @@ -367,7 +366,7 @@ spawn_cpuworker(void) static void spawn_enough_cpuworkers(void) { - int num_cpuworkers_needed = get_options()->NumCPUs; + int num_cpuworkers_needed = get_num_cpus(get_options()); if (num_cpuworkers_needed < MIN_CPUWORKERS) num_cpuworkers_needed = MIN_CPUWORKERS; @@ -446,9 +445,19 @@ assign_onionskin_to_cpuworker(connection_t *cpuworker, { char qbuf[1]; char tag[TAG_LEN]; + time_t now = approx_time(); + static time_t last_culled_cpuworkers = 0; - cull_wedged_cpuworkers(); - spawn_enough_cpuworkers(); + /* Checking for wedged cpuworkers requires a linear search over all + * connections, so let's do it only once a minute. + */ +#define CULL_CPUWORKERS_INTERVAL 60 + + if (last_culled_cpuworkers + CULL_CPUWORKERS_INTERVAL <= now) { + cull_wedged_cpuworkers(); + spawn_enough_cpuworkers(); + last_culled_cpuworkers = now; + } if (1) { if (num_cpuworkers_busy == num_cpuworkers) { diff --git a/src/or/directory.c b/src/or/directory.c index 52fec6b61a..776b7a25f9 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -15,7 +15,9 @@ #include "dirvote.h" #include "geoip.h" #include "main.h" +#include "microdesc.h" #include "networkstatus.h" +#include "nodelist.h" #include "policies.h" #include "rendclient.h" #include "rendcommon.h" @@ -78,6 +80,8 @@ static void dir_routerdesc_download_failed(smartlist_t *failed, int router_purpose, int was_extrainfo, int was_descriptor_digests); +static void dir_microdesc_download_failed(smartlist_t *failed, + int status_code); static void note_client_request(int purpose, int compressed, size_t bytes); static int client_likes_consensus(networkstatus_t *v, const char *want_url); @@ -137,26 +141,28 @@ purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose) dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS || dir_purpose == DIR_PURPOSE_FETCH_CERTIFICATE || dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC || - dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO) + dir_purpose == DIR_PURPOSE_FETCH_EXTRAINFO || + dir_purpose == DIR_PURPOSE_FETCH_MICRODESC) return 0; return 1; } -/** Return a newly allocated string describing <b>auth</b>. */ -char * -authority_type_to_string(authority_type_t auth) +/** Return a newly allocated string describing <b>auth</b>. Only describes + * authority features. */ +static char * +authdir_type_to_string(dirinfo_type_t auth) { char *result; smartlist_t *lst = smartlist_create(); - if (auth & V1_AUTHORITY) + if (auth & V1_DIRINFO) smartlist_add(lst, (void*)"V1"); - if (auth & V2_AUTHORITY) + if (auth & V2_DIRINFO) smartlist_add(lst, (void*)"V2"); - if (auth & V3_AUTHORITY) + if (auth & V3_DIRINFO) smartlist_add(lst, (void*)"V3"); - if (auth & BRIDGE_AUTHORITY) + if (auth & BRIDGE_DIRINFO) smartlist_add(lst, (void*)"Bridge"); - if (auth & HIDSERV_AUTHORITY) + if (auth & HIDSERV_DIRINFO) smartlist_add(lst, (void*)"Hidden service"); if (smartlist_len(lst)) { result = smartlist_join_strings(lst, ", ", 0, NULL); @@ -201,6 +207,8 @@ dir_conn_purpose_to_string(int purpose) return "hidden-service v2 descriptor fetch"; case DIR_PURPOSE_UPLOAD_RENDDESC_V2: return "hidden-service v2 descriptor upload"; + case DIR_PURPOSE_FETCH_MICRODESC: + return "microdescriptor fetch"; } log_warn(LD_BUG, "Called with unknown purpose %d", purpose); @@ -213,17 +221,19 @@ dir_conn_purpose_to_string(int purpose) int router_supports_extrainfo(const char *identity_digest, int is_authority) { - routerinfo_t *ri = router_get_by_digest(identity_digest); + const node_t *node = node_get_by_id(identity_digest); - if (ri) { - if (ri->caches_extra_info) + if (node && node->ri) { + if (node->ri->caches_extra_info) return 1; - if (is_authority && ri->platform && - tor_version_as_new_as(ri->platform, "Tor 0.2.0.0-alpha-dev (r10070)")) + if (is_authority && node->ri->platform && + tor_version_as_new_as(node->ri->platform, + "Tor 0.2.0.0-alpha-dev (r10070)")) return 1; } if (is_authority) { - routerstatus_t *rs = router_get_consensus_status_by_id(identity_digest); + const routerstatus_t *rs = + router_get_consensus_status_by_id(identity_digest); if (rs && rs->version_supports_extrainfo_upload) return 1; } @@ -242,7 +252,7 @@ int directories_have_accepted_server_descriptor(void) { smartlist_t *servers = router_get_trusted_dir_servers(); - or_options_t *options = get_options(); + const or_options_t *options = get_options(); SMARTLIST_FOREACH(servers, trusted_dir_server_t *, d, { if ((d->type & options->_PublishServerDescriptor) && d->has_accepted_serverdesc) { @@ -271,11 +281,11 @@ directories_have_accepted_server_descriptor(void) */ void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, - authority_type_t type, + dirinfo_type_t type, const char *payload, size_t payload_len, size_t extrainfo_len) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); int post_via_tor; smartlist_t *dirservers = router_get_trusted_dir_servers(); int found = 0; @@ -296,8 +306,8 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, if (exclude_self && router_digest_is_me(ds->digest)) continue; - if (options->ExcludeNodes && options->StrictNodes && - routerset_contains_routerstatus(options->ExcludeNodes, rs)) { + if (options->StrictNodes && + routerset_contains_routerstatus(options->ExcludeNodes, rs, -1)) { log_warn(LD_DIR, "Wanted to contact authority '%s' for %s, but " "it's in our ExcludedNodes list and StrictNodes is set. " "Skipping.", @@ -324,7 +334,7 @@ directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, NULL, payload, upload_len, 0); } SMARTLIST_FOREACH_END(ds); if (!found) { - char *s = authority_type_to_string(type); + char *s = authdir_type_to_string(type); log_warn(LD_DIR, "Publishing server descriptor to directory authorities " "of type '%s', but no authorities of that type listed!", s); tor_free(s); @@ -341,39 +351,44 @@ void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, const char *resource, int pds_flags) { - routerstatus_t *rs = NULL; - or_options_t *options = get_options(); + const routerstatus_t *rs = NULL; + const or_options_t *options = get_options(); int prefer_authority = directory_fetches_from_authorities(options); int get_via_tor = purpose_needs_anonymity(dir_purpose, router_purpose); - authority_type_t type; + dirinfo_type_t type; time_t if_modified_since = 0; /* FFFF we could break this switch into its own function, and call * it elsewhere in directory.c. -RD */ switch (dir_purpose) { case DIR_PURPOSE_FETCH_EXTRAINFO: - type = EXTRAINFO_CACHE | - (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY : - V3_AUTHORITY); + type = EXTRAINFO_DIRINFO | + (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO : + V3_DIRINFO); break; case DIR_PURPOSE_FETCH_V2_NETWORKSTATUS: - type = V2_AUTHORITY; + type = V2_DIRINFO; prefer_authority = 1; /* Only v2 authorities have these anyway. */ break; case DIR_PURPOSE_FETCH_SERVERDESC: - type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_AUTHORITY : - V3_AUTHORITY); + type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO : + V3_DIRINFO); break; case DIR_PURPOSE_FETCH_RENDDESC: - type = HIDSERV_AUTHORITY; + type = HIDSERV_DIRINFO; break; case DIR_PURPOSE_FETCH_STATUS_VOTE: case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES: - type = V3_AUTHORITY; + case DIR_PURPOSE_FETCH_CERTIFICATE: + type = V3_DIRINFO; break; case DIR_PURPOSE_FETCH_CONSENSUS: - case DIR_PURPOSE_FETCH_CERTIFICATE: - type = V3_AUTHORITY; + type = V3_DIRINFO; + if (resource && !strcmp(resource,"microdesc")) + type |= MICRODESC_DIRINFO; + break; + case DIR_PURPOSE_FETCH_MICRODESC: + type = MICRODESC_DIRINFO; break; default: log_warn(LD_BUG, "Unexpected purpose %d", (int)dir_purpose); @@ -381,25 +396,42 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, } if (dir_purpose == DIR_PURPOSE_FETCH_CONSENSUS) { - networkstatus_t *v = networkstatus_get_latest_consensus(); - if (v) - if_modified_since = v->valid_after + 180; + int flav = FLAV_NS; + networkstatus_t *v; + if (resource) + flav = networkstatus_parse_flavor_name(resource); + + if (flav != -1) { + /* IF we have a parsed consensus of this type, we can do an + * if-modified-time based on it. */ + v = networkstatus_get_latest_consensus_by_flavor(flav); + if (v) + if_modified_since = v->valid_after + 180; + } else { + /* Otherwise it might be a consensus we don't parse, but which we + * do cache. Look at the cached copy, perhaps. */ + cached_dir_t *cd = dirserv_get_consensus(resource ? resource : "ns"); + if (cd) + if_modified_since = cd->published + 180; + } } - if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY) + if (!options->FetchServerDescriptors && type != HIDSERV_DIRINFO) return; if (!get_via_tor) { - if (options->UseBridges && type != BRIDGE_AUTHORITY) { + if (options->UseBridges && type != BRIDGE_DIRINFO) { /* want to ask a running bridge for which we have a descriptor. */ /* XXX023 we assume that all of our bridges can answer any * possible directory question. This won't be true forever. -RD */ /* It certainly is not true with conditional consensus downloading, * so, for now, never assume the server supports that. */ - routerinfo_t *ri = choose_random_entry(NULL); - if (ri) { + const node_t *node = choose_random_entry(NULL); + if (node && node->ri) { + /* every bridge has a routerinfo. */ tor_addr_t addr; - tor_addr_from_ipv4h(&addr, ri->addr); + routerinfo_t *ri = node->ri; + node_get_addr(node, &addr); directory_initiate_command(ri->address, &addr, ri->or_port, 0, 0, /* don't use conditional consensus url */ @@ -412,10 +444,11 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, "nodes are available yet."); return; } else { - if (prefer_authority || type == BRIDGE_AUTHORITY) { + if (prefer_authority || type == BRIDGE_DIRINFO) { /* only ask authdirservers, and don't ask myself */ rs = router_pick_trusteddirserver(type, pds_flags); - if (rs == NULL && (pds_flags & PDS_NO_EXISTING_SERVERDESC_FETCH)) { + if (rs == NULL && (pds_flags & (PDS_NO_EXISTING_SERVERDESC_FETCH| + PDS_NO_EXISTING_MICRODESC_FETCH))) { /* We don't want to fetch from any authorities that we're currently * fetching server descriptors from, and we got no match. Did we * get no match because all the authorities have connections @@ -423,7 +456,8 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, * return,) or because all the authorities are down or on fire or * unreachable or something (in which case we should go on with * our fallback code)? */ - pds_flags &= ~PDS_NO_EXISTING_SERVERDESC_FETCH; + pds_flags &= ~(PDS_NO_EXISTING_SERVERDESC_FETCH| + PDS_NO_EXISTING_MICRODESC_FETCH); rs = router_pick_trusteddirserver(type, pds_flags); if (rs) { log_debug(LD_DIR, "Deferring serverdesc fetch: all authorities " @@ -432,7 +466,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, } } } - if (!rs && type != BRIDGE_AUTHORITY) { + if (!rs && type != BRIDGE_DIRINFO) { /* anybody with a non-zero dirport will do */ rs = router_pick_directory_server(type, pds_flags); if (!rs) { @@ -449,7 +483,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) { /* only ask hidserv authorities, any of them will do */ pds_flags |= PDS_IGNORE_FASCISTFIREWALL|PDS_ALLOW_SELF; - rs = router_pick_trusteddirserver(HIDSERV_AUTHORITY, pds_flags); + rs = router_pick_trusteddirserver(HIDSERV_DIRINFO, pds_flags); } else { /* anybody with a non-zero dirport will do. Disregard firewalls. */ pds_flags |= PDS_IGNORE_FASCISTFIREWALL; @@ -495,7 +529,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose, routerstatus_t *rs; if (router_digest_is_me(ds->digest)) continue; - if (!(ds->type & V3_AUTHORITY)) + if (!(ds->type & V3_DIRINFO)) continue; rs = &ds->fake_status; directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose, @@ -506,7 +540,7 @@ directory_get_from_all_authorities(uint8_t dir_purpose, /** Same as directory_initiate_command_routerstatus(), but accepts * rendezvous data to fetch a hidden service descriptor. */ void -directory_initiate_command_routerstatus_rend(routerstatus_t *status, +directory_initiate_command_routerstatus_rend(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, int anonymized_connection, @@ -516,21 +550,22 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status, time_t if_modified_since, const rend_data_t *rend_query) { - or_options_t *options = get_options(); - routerinfo_t *router; + const or_options_t *options = get_options(); + const node_t *node; char address_buf[INET_NTOA_BUF_LEN+1]; struct in_addr in; const char *address; tor_addr_t addr; - router = router_get_by_digest(status->identity_digest); + node = node_get_by_id(status->identity_digest); - if (!router && anonymized_connection) { - log_info(LD_DIR, "Not sending anonymized request to directory %s; we " + if (!node && anonymized_connection) { + log_info(LD_DIR, "Not sending anonymized request to directory '%s'; we " "don't have its router descriptor.", routerstatus_describe(status)); return; - } else if (router) { - address = router->address; + } else if (node) { + node_get_address_string(node, address_buf, sizeof(address_buf)); + address = address_buf; } else { in.s_addr = htonl(status->addr); tor_inet_ntoa(&in, address_buf, sizeof(address_buf)); @@ -539,7 +574,7 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status, tor_addr_from_ipv4h(&addr, status->addr); if (options->ExcludeNodes && options->StrictNodes && - routerset_contains_routerstatus(options->ExcludeNodes, status)) { + routerset_contains_routerstatus(options->ExcludeNodes, status, -1)) { log_warn(LD_DIR, "Wanted to contact directory mirror %s for %s, but " "it's in our ExcludedNodes list and StrictNodes is set. " "Skipping. This choice might make your Tor not work.", @@ -574,7 +609,7 @@ directory_initiate_command_routerstatus_rend(routerstatus_t *status, * want to fetch. */ void -directory_initiate_command_routerstatus(routerstatus_t *status, +directory_initiate_command_routerstatus(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, int anonymized_connection, @@ -598,7 +633,7 @@ directory_conn_is_self_reachability_test(dir_connection_t *conn) { if (conn->requested_resource && !strcmpstart(conn->requested_resource,"authority")) { - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); if (me && router_digest_is_me(conn->identity_digest) && tor_addr_eq_ipv4h(&conn->_base.addr, me->addr) && /*XXXX prop 118*/ @@ -612,7 +647,7 @@ directory_conn_is_self_reachability_test(dir_connection_t *conn) * server due to a network error: Mark the router as down and try again if * possible. */ -void +static void connection_dir_request_failed(dir_connection_t *conn) { if (directory_conn_is_self_reachability_test(conn)) { @@ -626,15 +661,18 @@ connection_dir_request_failed(dir_connection_t *conn) connection_dir_download_v2_networkstatus_failed(conn, -1); } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC || conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO) { - log_info(LD_DIR, "Giving up on directory server at '%s'; retrying", + log_info(LD_DIR, "Giving up on serverdesc/extrainfo fetch from " + "directory server at '%s'; retrying", conn->_base.address); if (conn->router_purpose == ROUTER_PURPOSE_BRIDGE) connection_dir_bridge_routerdesc_failed(conn); connection_dir_download_routerdesc_failed(conn); } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) { - networkstatus_consensus_download_failed(0); + if (conn->requested_resource) + networkstatus_consensus_download_failed(0, conn->requested_resource); } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) { - log_info(LD_DIR, "Giving up on directory server at '%s'; retrying", + log_info(LD_DIR, "Giving up on certificate fetch from directory server " + "at '%s'; retrying", conn->_base.address); connection_dir_download_cert_failed(conn, 0); } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) { @@ -643,6 +681,10 @@ connection_dir_request_failed(dir_connection_t *conn) } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) { log_info(LD_DIR, "Giving up downloading votes from '%s'", conn->_base.address); + } else if (conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC) { + log_info(LD_DIR, "Giving up on downloading microdescriptors from " + " directory server at '%s'; will retry", conn->_base.address); + connection_dir_download_routerdesc_failed(conn); } } @@ -713,7 +755,8 @@ connection_dir_download_routerdesc_failed(dir_connection_t *conn) /* No need to relaunch descriptor downloads here: we already do it * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */ tor_assert(conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC || - conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO); + conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO || + conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC); (void) conn; } @@ -776,7 +819,7 @@ connection_dir_download_cert_failed(dir_connection_t *conn, int status) * 3) Else yes. */ static int -directory_command_should_use_begindir(or_options_t *options, +directory_command_should_use_begindir(const or_options_t *options, const tor_addr_t *addr, int or_port, uint8_t router_purpose, int anonymized_connection) @@ -785,8 +828,7 @@ directory_command_should_use_begindir(or_options_t *options, return 0; /* We don't know an ORPort -- no chance. */ if (!anonymized_connection) if (!fascist_firewall_allows_address_or(addr, or_port) || - directory_fetches_from_authorities(options) || - (server_mode(options) && !options->Address)) + directory_fetches_from_authorities(options)) return 0; /* We're firewalled or are acting like a relay -- also no. */ if (!options->TunnelDirConns && router_purpose != ROUTER_PURPOSE_BRIDGE) @@ -817,6 +859,20 @@ directory_initiate_command(const char *address, const tor_addr_t *_addr, if_modified_since, NULL); } +/** Return non-zero iff a directory connection with purpose + * <b>dir_purpose</b> reveals sensitive information about a Tor + * instance's client activities. (Such connections must be performed + * through normal three-hop Tor circuits.) */ +static int +is_sensitive_dir_purpose(uint8_t dir_purpose) +{ + return ((dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) || + (dir_purpose == DIR_PURPOSE_HAS_FETCHED_RENDDESC) || + (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC) || + (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) || + (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC_V2)); +} + /** Same as directory_initiate_command(), but accepts rendezvous data to * fetch a hidden service descriptor. */ static void @@ -832,7 +888,7 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, const rend_data_t *rend_query) { dir_connection_t *conn; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); int socket_error = 0; int use_begindir = supports_begindir && directory_command_should_use_begindir(options, _addr, @@ -851,6 +907,9 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, log_debug(LD_DIR, "Initiating %s", dir_conn_purpose_to_string(dir_purpose)); + tor_assert(!(is_sensitive_dir_purpose(dir_purpose) && + !anonymized_connection)); + /* ensure that we don't make direct connections when a SOCKS server is * configured. */ if (!anonymized_connection && !use_begindir && !options->HTTPProxy && @@ -912,7 +971,11 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, error indicates broken link in windowsland. */ } } else { /* we want to connect via a tor connection */ - edge_connection_t *linked_conn; + entry_connection_t *linked_conn; + /* Anonymized tunneled connections can never share a circuit. + * One-hop directory connections can share circuits with each other + * but nothing else. */ + int iso_flags = anonymized_connection ? ISO_STREAM : ISO_SESSIONGRP; /* If it's an anonymized connection, remember the fact that we * wanted it for later: maybe we'll want it again soon. */ @@ -926,14 +989,16 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, * hook up both sides */ linked_conn = - connection_ap_make_link(conn->_base.address, conn->_base.port, - digest, use_begindir, conn->dirconn_direct); + connection_ap_make_link(TO_CONN(conn), + conn->_base.address, conn->_base.port, + digest, + SESSION_GROUP_DIRCONN, iso_flags, + use_begindir, conn->dirconn_direct); if (!linked_conn) { log_warn(LD_NET,"Making tunnel to dirserver failed."); connection_mark_for_close(TO_CONN(conn)); return; } - connection_link_connections(TO_CONN(conn), TO_CONN(linked_conn)); if (connection_add(TO_CONN(conn)) < 0) { log_warn(LD_NET,"Unable to add connection for link to dirserver."); @@ -946,8 +1011,13 @@ directory_initiate_command_rend(const char *address, const tor_addr_t *_addr, payload, payload_len, supports_conditional_consensus, if_modified_since); + connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT); - connection_start_reading(TO_CONN(linked_conn)); + IF_HAS_BUFFEREVENT(ENTRY_TO_CONN(linked_conn), { + connection_watch_events(ENTRY_TO_CONN(linked_conn), + READ_EVENT|WRITE_EVENT); + }) ELSE_IF_NO_BUFFEREVENT + connection_start_reading(ENTRY_TO_CONN(linked_conn)); } } @@ -985,12 +1055,22 @@ _compare_strs(const void **a, const void **b) * This url depends on whether or not the server we go to * is sufficiently new to support conditional consensus downloading, * i.e. GET .../consensus/<b>fpr</b>+<b>fpr</b>+<b>fpr</b> + * + * If 'resource' is provided, it is the name of a consensus flavor to request. */ static char * -directory_get_consensus_url(int supports_conditional_consensus) +directory_get_consensus_url(int supports_conditional_consensus, + const char *resource) { - char *url; - size_t len; + char *url = NULL; + const char *hyphen, *flavor; + if (resource==NULL || strcmp(resource, "ns")==0) { + flavor = ""; /* Request ns consensuses as "", so older servers will work*/ + hyphen = ""; + } else { + flavor = resource; + hyphen = "-"; + } if (supports_conditional_consensus) { char *authority_id_list; @@ -1000,7 +1080,7 @@ directory_get_consensus_url(int supports_conditional_consensus) trusted_dir_server_t *, ds, { char *hex; - if (!(ds->type & V3_AUTHORITY)) + if (!(ds->type & V3_DIRINFO)) continue; hex = tor_malloc(2*CONDITIONAL_CONSENSUS_FPR_LEN+1); @@ -1012,16 +1092,15 @@ directory_get_consensus_url(int supports_conditional_consensus) authority_id_list = smartlist_join_strings(authority_digests, "+", 0, NULL); - len = strlen(authority_id_list)+64; - url = tor_malloc(len); - tor_snprintf(url, len, "/tor/status-vote/current/consensus/%s.z", - authority_id_list); + tor_asprintf(&url, "/tor/status-vote/current/consensus%s%s/%s.z", + hyphen, flavor, authority_id_list); SMARTLIST_FOREACH(authority_digests, char *, cp, tor_free(cp)); smartlist_free(authority_digests); tor_free(authority_id_list); } else { - url = tor_strdup("/tor/status-vote/current/consensus.z"); + tor_asprintf(&url, "/tor/status-vote/current/consensus%s%s.z", + hyphen, flavor); } return url; } @@ -1037,11 +1116,11 @@ directory_send_command(dir_connection_t *conn, time_t if_modified_since) { char proxystring[256]; - char proxyauthstring[256]; char hoststring[128]; - char imsstring[RFC1123_TIME_LEN+32]; + smartlist_t *headers = smartlist_create(); char *url; char request[8192]; + char *header; const char *httpcommand = NULL; size_t len; @@ -1061,12 +1140,11 @@ directory_send_command(dir_connection_t *conn, } /* Format if-modified-since */ - if (!if_modified_since) { - imsstring[0] = '\0'; - } else { + if (if_modified_since) { char b[RFC1123_TIME_LEN+1]; format_rfc1123_time(b, if_modified_since); - tor_snprintf(imsstring, sizeof(imsstring), "\r\nIf-Modified-Since: %s", b); + tor_asprintf(&header, "If-Modified-Since: %s\r\n", b); + smartlist_add(headers, header); } /* come up with some proxy lines, if we're using one. */ @@ -1081,16 +1159,14 @@ directory_send_command(dir_connection_t *conn, log_warn(LD_BUG, "Encoding http authenticator failed"); } if (base64_authenticator) { - tor_snprintf(proxyauthstring, sizeof(proxyauthstring), - "\r\nProxy-Authorization: Basic %s", + tor_asprintf(&header, + "Proxy-Authorization: Basic %s\r\n", base64_authenticator); tor_free(base64_authenticator); - } else { - proxyauthstring[0] = 0; + smartlist_add(headers, header); } } else { proxystring[0] = 0; - proxyauthstring[0] = 0; } switch (purpose) { @@ -1102,10 +1178,11 @@ directory_send_command(dir_connection_t *conn, tor_snprintf(url, len, "/tor/status/%s", resource); break; case DIR_PURPOSE_FETCH_CONSENSUS: - tor_assert(!resource); + /* resource is optional. If present, it's a flavor name */ tor_assert(!payload); httpcommand = "GET"; - url = directory_get_consensus_url(supports_conditional_consensus); + url = directory_get_consensus_url(supports_conditional_consensus, + resource); log_info(LD_DIR, "Downloading consensus from %s using %s", hoststring, url); break; @@ -1145,12 +1222,23 @@ directory_send_command(dir_connection_t *conn, url = tor_malloc(len); tor_snprintf(url, len, "/tor/extra/%s", resource); break; - case DIR_PURPOSE_UPLOAD_DIR: + case DIR_PURPOSE_FETCH_MICRODESC: + tor_assert(resource); + httpcommand = "GET"; + tor_asprintf(&url, "/tor/micro/%s", resource); + break; + case DIR_PURPOSE_UPLOAD_DIR: { + const char *why = router_get_descriptor_gen_reason(); tor_assert(!resource); tor_assert(payload); httpcommand = "POST"; url = tor_strdup("/tor/"); + if (why) { + tor_asprintf(&header, "X-Desc-Gen-Reason: %s\r\n", why); + smartlist_add(headers, header); + } break; + } case DIR_PURPOSE_UPLOAD_VOTE: tor_assert(!resource); tor_assert(payload); @@ -1201,26 +1289,26 @@ directory_send_command(dir_connection_t *conn, connection_write_to_buf(url, strlen(url), TO_CONN(conn)); tor_free(url); - if (!strcmp(httpcommand, "GET") && !payload) { - tor_snprintf(request, sizeof(request), - " HTTP/1.0\r\nHost: %s%s%s\r\n\r\n", - hoststring, - imsstring, - proxyauthstring); - } else { - tor_snprintf(request, sizeof(request), - " HTTP/1.0\r\nContent-Length: %lu\r\nHost: %s%s%s\r\n\r\n", - payload ? (unsigned long)payload_len : 0, - hoststring, - imsstring, - proxyauthstring); + if (!strcmp(httpcommand, "POST") || payload) { + tor_asprintf(&header, "Content-Length: %lu\r\n", + payload ? (unsigned long)payload_len : 0); + smartlist_add(headers, header); } + + header = smartlist_join_strings(headers, "", 0, NULL); + tor_snprintf(request, sizeof(request), " HTTP/1.0\r\nHost: %s\r\n%s\r\n", + hoststring, header); + tor_free(header); + connection_write_to_buf(request, strlen(request), TO_CONN(conn)); if (payload) { /* then send the payload afterwards too */ connection_write_to_buf(payload, payload_len, TO_CONN(conn)); } + + SMARTLIST_FOREACH(headers, char *, h, tor_free(h)); + smartlist_free(headers); } /** Parse an HTTP request string <b>headers</b> of the form @@ -1420,6 +1508,9 @@ body_is_plausible(const char *body, size_t len, int purpose) return 1; /* empty bodies don't need decompression */ if (len < 32) return 0; + if (purpose == DIR_PURPOSE_FETCH_MICRODESC) { + return (!strcmpstart(body,"onion-key")); + } if (purpose != DIR_PURPOSE_FETCH_RENDDESC) { if (!strcmpstart(body,"router") || !strcmpstart(body,"signed-directory") || @@ -1496,11 +1587,12 @@ connection_dir_client_reached_eof(dir_connection_t *conn) int plausible; int skewed=0; int allow_partial = (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC || - conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO); + conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO || + conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC); int was_compressed=0; time_t now = time(NULL); - switch (fetch_from_buf_http(conn->_base.inbuf, + switch (connection_fetch_from_buf_http(TO_CONN(conn), &headers, MAX_HEADERS_SIZE, &body, &body_len, MAX_DIR_DL_SIZE, allow_partial)) { @@ -1575,13 +1667,14 @@ connection_dir_client_reached_eof(dir_connection_t *conn) if (status_code == 503) { routerstatus_t *rs; trusted_dir_server_t *ds; + const char *id_digest = conn->identity_digest; log_info(LD_DIR,"Received http status code %d (%s) from server " "'%s:%d'. I'll try again soon.", status_code, escaped(reason), conn->_base.address, conn->_base.port); - if ((rs = router_get_consensus_status_by_id(conn->identity_digest))) + if ((rs = router_get_mutable_consensus_status_by_id(id_digest))) rs->last_dir_503_at = now; - if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest))) + if ((ds = router_get_trusteddirserver_by_digest(id_digest))) ds->fake_status.last_dir_503_at = now; tor_free(body); tor_free(headers); tor_free(reason); @@ -1720,6 +1813,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn) if (conn->_base.purpose == DIR_PURPOSE_FETCH_CONSENSUS) { int r; + const char *flavname = conn->requested_resource; if (status_code != 200) { int severity = (status_code == 304) ? LOG_INFO : LOG_WARN; log(severity, LD_DIR, @@ -1728,22 +1822,24 @@ connection_dir_client_reached_eof(dir_connection_t *conn) status_code, escaped(reason), conn->_base.address, conn->_base.port); tor_free(body); tor_free(headers); tor_free(reason); - networkstatus_consensus_download_failed(status_code); + networkstatus_consensus_download_failed(status_code, flavname); return -1; } log_info(LD_DIR,"Received consensus directory (size %d) from server " "'%s:%d'", (int)body_len, conn->_base.address, conn->_base.port); - if ((r=networkstatus_set_current_consensus(body, "ns", 0))<0) { + if ((r=networkstatus_set_current_consensus(body, flavname, 0))<0) { log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR, - "Unable to load consensus directory downloaded from " + "Unable to load %s consensus directory downloaded from " "server '%s:%d'. I'll try again soon.", - conn->_base.address, conn->_base.port); + flavname, conn->_base.address, conn->_base.port); tor_free(body); tor_free(headers); tor_free(reason); - networkstatus_consensus_download_failed(0); + networkstatus_consensus_download_failed(0, flavname); return -1; } /* launches router downloads as needed */ routers_update_all_from_networkstatus(now, 3); + update_microdescs_from_networkstatus(now); + update_microdesc_downloads(now); directory_info_has_arrived(now, 0); log_info(LD_DIR, "Successfully loaded consensus."); } @@ -1893,6 +1989,43 @@ connection_dir_client_reached_eof(dir_connection_t *conn) if (directory_conn_is_self_reachability_test(conn)) router_dirport_found_reachable(); } + if (conn->_base.purpose == DIR_PURPOSE_FETCH_MICRODESC) { + smartlist_t *which = NULL; + log_info(LD_DIR,"Received answer to microdescriptor request (status %d, " + "size %d) from server '%s:%d'", + status_code, (int)body_len, conn->_base.address, + conn->_base.port); + tor_assert(conn->requested_resource && + !strcmpstart(conn->requested_resource, "d/")); + which = smartlist_create(); + dir_split_resource_into_fingerprints(conn->requested_resource+2, + which, NULL, + DSR_DIGEST256|DSR_BASE64); + if (status_code != 200) { + log_info(LD_DIR, "Received status code %d (%s) from server " + "'%s:%d' while fetching \"/tor/micro/%s\". I'll try again " + "soon.", + status_code, escaped(reason), conn->_base.address, + (int)conn->_base.port, conn->requested_resource); + dir_microdesc_download_failed(which, status_code); + SMARTLIST_FOREACH(which, char *, cp, tor_free(cp)); + smartlist_free(which); + tor_free(body); tor_free(headers); tor_free(reason); + return 0; + } else { + smartlist_t *mds; + mds = microdescs_add_to_cache(get_microdesc_cache(), + body, body+body_len, SAVED_NOWHERE, 0, + now, which); + if (smartlist_len(which)) { + /* Mark remaining ones as failed. */ + dir_microdesc_download_failed(which, status_code); + } + SMARTLIST_FOREACH(which, char *, cp, tor_free(cp)); + smartlist_free(which); + smartlist_free(mds); + } + } if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_DIR) { switch (status_code) { @@ -2167,7 +2300,7 @@ connection_dir_process_inbuf(dir_connection_t *conn) return 0; } - if (buf_datalen(conn->_base.inbuf) > MAX_DIRECTORY_OBJECT_SIZE) { + if (connection_get_inbuf_len(TO_CONN(conn)) > MAX_DIRECTORY_OBJECT_SIZE) { log_warn(LD_HTTP, "Too much data received from directory connection: " "denial of service attempt, or you need to upgrade?"); connection_mark_for_close(TO_CONN(conn)); @@ -2179,6 +2312,28 @@ connection_dir_process_inbuf(dir_connection_t *conn) return 0; } +/** Called when we're about to finally unlink and free a directory connection: + * perform necessary accounting and cleanup */ +void +connection_dir_about_to_close(dir_connection_t *dir_conn) +{ + connection_t *conn = TO_CONN(dir_conn); + + if (conn->state < DIR_CONN_STATE_CLIENT_FINISHED) { + /* It's a directory connection and connecting or fetching + * failed: forget about this router, and maybe try again. */ + connection_dir_request_failed(dir_conn); + } + /* If we were trying to fetch a v2 rend desc and did not succeed, + * retry as needed. (If a fetch is successful, the connection state + * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC to mark that + * refetching is unnecessary.) */ + if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 && + dir_conn->rend_data && + strlen(dir_conn->rend_data->onion_address) == REND_SERVICE_ID_LEN_BASE32) + rend_client_refetch_v2_renddesc(dir_conn->rend_data); +} + /** Create an http response for the client <b>conn</b> out of * <b>status</b> and <b>reason_phrase</b>. Write it to <b>conn</b>. */ @@ -2470,18 +2625,18 @@ client_likes_consensus(networkstatus_t *v, const char *want_url) * Always return 0. */ static int directory_handle_command_get(dir_connection_t *conn, const char *headers, - const char *body, size_t body_len) + const char *req_body, size_t req_body_len) { size_t dlen; char *url, *url_mem, *header; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); time_t if_modified_since = 0; int compressed; size_t url_len; /* We ignore the body of a GET request. */ - (void)body; - (void)body_len; + (void)req_body; + (void)req_body_len; log_debug(LD_DIRSERV,"Received GET command."); @@ -3190,7 +3345,7 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers, const char *body, size_t body_len) { char *url = NULL; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); log_debug(LD_DIRSERV,"Received POST command."); @@ -3334,7 +3489,7 @@ directory_handle_command(dir_connection_t *conn) tor_assert(conn); tor_assert(conn->_base.type == CONN_TYPE_DIR); - switch (fetch_from_buf_http(conn->_base.inbuf, + switch (connection_fetch_from_buf_http(TO_CONN(conn), &headers, MAX_HEADERS_SIZE, &body, &body_len, MAX_DIR_UL_SIZE, 0)) { case -1: /* overflow */ @@ -3387,14 +3542,27 @@ connection_dir_finished_flushing(dir_connection_t *conn) DIRREQ_DIRECT, DIRREQ_FLUSHING_DIR_CONN_FINISHED); switch (conn->_base.state) { + case DIR_CONN_STATE_CONNECTING: case DIR_CONN_STATE_CLIENT_SENDING: log_debug(LD_DIR,"client finished sending command."); conn->_base.state = DIR_CONN_STATE_CLIENT_READING; - connection_stop_writing(TO_CONN(conn)); return 0; case DIR_CONN_STATE_SERVER_WRITING: - log_debug(LD_DIRSERV,"Finished writing server response. Closing."); - connection_mark_for_close(TO_CONN(conn)); + if (conn->dir_spool_src != DIR_SPOOL_NONE) { +#ifdef USE_BUFFEREVENTS + /* This can happen with paired bufferevents, since a paired connection + * can flush immediately when you write to it, making the subsequent + * check in connection_handle_write_cb() decide that the connection + * is flushed. */ + log_debug(LD_DIRSERV, "Emptied a dirserv buffer, but still spooling."); +#else + log_warn(LD_BUG, "Emptied a dirserv buffer, but it's still spooling!"); + connection_mark_for_close(TO_CONN(conn)); +#endif + } else { + log_debug(LD_DIRSERV, "Finished writing server response. Closing."); + connection_mark_for_close(TO_CONN(conn)); + } return 0; default: log_warn(LD_BUG,"called in unexpected state %d.", @@ -3620,6 +3788,36 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code, * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */ } +/* DOCDOC NM */ +static void +dir_microdesc_download_failed(smartlist_t *failed, + int status_code) +{ + networkstatus_t *consensus + = networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC); + routerstatus_t *rs; + download_status_t *dls; + time_t now = time(NULL); + int server = directory_fetches_from_authorities(get_options()); + + if (! consensus) + return; + SMARTLIST_FOREACH_BEGIN(failed, const char *, d) { + rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus,d); + if (!rs) + continue; + dls = &rs->dl_status; + if (dls->n_download_failures >= MAX_MICRODESC_DOWNLOAD_FAILURES) + continue; + { + char buf[BASE64_DIGEST256_LEN+1]; + digest256_to_base64(buf, d); + download_status_increment_failure(dls, status_code, buf, + server, now); + } + } SMARTLIST_FOREACH_END(d); +} + /** Helper. Compare two fp_pair_t objects, and return negative, 0, or * positive as appropriate. */ static int diff --git a/src/or/directory.h b/src/or/directory.h index 94dfb17644..8c63bb5dfd 100644 --- a/src/or/directory.h +++ b/src/or/directory.h @@ -13,9 +13,8 @@ #define _TOR_DIRECTORY_H int directories_have_accepted_server_descriptor(void); -char *authority_type_to_string(authority_type_t auth); void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose, - authority_type_t type, const char *payload, + dirinfo_type_t type, const char *payload, size_t payload_len, size_t extrainfo_len); void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, const char *resource, @@ -23,7 +22,7 @@ void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose, void directory_get_from_all_authorities(uint8_t dir_purpose, uint8_t router_purpose, const char *resource); -void directory_initiate_command_routerstatus(routerstatus_t *status, +void directory_initiate_command_routerstatus(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, int anonymized_connection, @@ -31,7 +30,7 @@ void directory_initiate_command_routerstatus(routerstatus_t *status, const char *payload, size_t payload_len, time_t if_modified_since); -void directory_initiate_command_routerstatus_rend(routerstatus_t *status, +void directory_initiate_command_routerstatus_rend(const routerstatus_t *status, uint8_t dir_purpose, uint8_t router_purpose, int anonymized_connection, @@ -49,7 +48,7 @@ int connection_dir_reached_eof(dir_connection_t *conn); int connection_dir_process_inbuf(dir_connection_t *conn); int connection_dir_finished_flushing(dir_connection_t *conn); int connection_dir_finished_connecting(dir_connection_t *conn); -void connection_dir_request_failed(dir_connection_t *conn); +void connection_dir_about_to_close(dir_connection_t *dir_conn); void directory_initiate_command(const char *address, const tor_addr_t *addr, uint16_t or_port, uint16_t dir_port, int supports_conditional_consensus, diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 66079018ab..8fe1b18a35 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, @@ -232,7 +232,7 @@ dirserv_load_fingerprint_file(void) } tor_free(fname); - result = config_get_lines(cf, &front); + result = config_get_lines(cf, &front, 0); tor_free(cf); if (result < 0) { log_warn(LD_CONFIG, "Error reading from fingerprint file"); @@ -305,7 +305,7 @@ dirserv_load_fingerprint_file(void) * * If the status is 'FP_REJECT' and <b>msg</b> is provided, set * *<b>msg</b> to an explanation of why. */ -static uint32_t +uint32_t dirserv_router_get_status(const routerinfo_t *router, const char **msg) { char d[DIGEST_LEN]; @@ -327,7 +327,7 @@ dirserv_router_get_status(const routerinfo_t *router, const char **msg) /** Return true if there is no point in downloading the router described by * <b>rs</b> because this directory would reject it. */ int -dirserv_would_reject_router(routerstatus_t *rs) +dirserv_would_reject_router(const routerstatus_t *rs) { uint32_t res; @@ -362,7 +362,7 @@ dirserv_get_name_status(const char *id_digest, const char *nickname) return 0; } -/** Helper: As dirserv_get_router_status, but takes the router fingerprint +/** Helper: As dirserv_router_get_status, but takes the router fingerprint * (hex, no spaces), nickname, address (used for logging only), IP address, OR * port, platform (logging only) and contact info (logging only) as arguments. * @@ -377,7 +377,7 @@ dirserv_get_status_impl(const char *id_digest, const char *nickname, const char **msg, int should_log) { int reject_unlisted = get_options()->AuthDirRejectUnlisted; - uint32_t result = 0; + uint32_t result; router_status_t *status_by_digest; if (!fingerprint_list) @@ -542,7 +542,7 @@ dirserv_router_has_valid_address(routerinfo_t *ri) */ int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, - int complain) + int complain, int *valid_out) { /* Okay. Now check whether the fingerprint is recognized. */ uint32_t status = dirserv_router_get_status(ri, msg); @@ -586,15 +586,24 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, *msg = "Rejected: Address is not an IP, or IP is a private address."; return -1; } - /* Okay, looks like we're willing to accept this one. */ - ri->is_named = (status & FP_NAMED) ? 1 : 0; - ri->is_valid = (status & FP_INVALID) ? 0 : 1; - ri->is_bad_directory = (status & FP_BADDIR) ? 1 : 0; - ri->is_bad_exit = (status & FP_BADEXIT) ? 1 : 0; + + *valid_out = ! (status & FP_INVALID); return 0; } +/** Update the relevant flags of <b>node</b> based on our opinion as a + * directory authority in <b>authstatus</b>, as returned by + * dirserv_router_get_status or equivalent. */ +void +dirserv_set_node_flags_from_authoritative_status(node_t *node, + uint32_t authstatus) +{ + node->is_valid = (authstatus & FP_INVALID) ? 0 : 1; + node->is_bad_directory = (authstatus & FP_BADDIR) ? 1 : 0; + node->is_bad_exit = (authstatus & FP_BADEXIT) ? 1 : 0; +} + /** True iff <b>a</b> is more severe than <b>b</b>. */ static int WRA_MORE_SEVERE(was_router_added_t a, was_router_added_t b) @@ -719,7 +728,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source) * from this server. (We do this here and not in router_add_to_routerlist * because we want to be able to accept the newest router descriptor that * another authority has, so we all converge on the same one.) */ - ri_old = router_get_by_digest(ri->cache_info.identity_digest); + ri_old = router_get_mutable_by_digest(ri->cache_info.identity_digest); if (ri_old && ri_old->cache_info.published_on < ri->cache_info.published_on && router_differences_are_cosmetic(ri_old, ri) && !router_is_me(ri)) { @@ -763,8 +772,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source) routerlist_descriptors_added(changed, 0); smartlist_free(changed); if (!*msg) { - *msg = ri->is_valid ? "Descriptor for valid server accepted" : - "Descriptor for invalid server accepted"; + *msg = "Descriptor accepted"; } log_info(LD_DIRSERV, "Added descriptor from '%s' (source: %s): %s.", @@ -779,12 +787,12 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source) static was_router_added_t dirserv_add_extrainfo(extrainfo_t *ei, const char **msg) { - routerinfo_t *ri; + const routerinfo_t *ri; int r; tor_assert(msg); *msg = NULL; - ri = router_get_by_digest(ei->cache_info.identity_digest); + ri = router_get_by_id_digest(ei->cache_info.identity_digest); if (!ri) { *msg = "No corresponding router descriptor for extra-info descriptor"; extrainfo_free(ei); @@ -819,56 +827,67 @@ dirserv_add_extrainfo(extrainfo_t *ei, const char **msg) static void directory_remove_invalid(void) { - int i; int changed = 0; routerlist_t *rl = router_get_routerlist(); + smartlist_t *nodes = smartlist_create(); + smartlist_add_all(nodes, nodelist_get_list()); - routerlist_assert_ok(rl); - - for (i = 0; i < smartlist_len(rl->routers); ++i) { + SMARTLIST_FOREACH_BEGIN(nodes, node_t *, node) { const char *msg; - routerinfo_t *ent = smartlist_get(rl->routers, i); + routerinfo_t *ent = node->ri; char description[NODE_DESC_BUF_LEN]; - uint32_t r = dirserv_router_get_status(ent, &msg); + uint32_t r; + if (!ent) + continue; + r = dirserv_router_get_status(ent, &msg); router_get_description(description, ent); if (r & FP_REJECT) { log_info(LD_DIRSERV, "Router %s is now rejected: %s", description, msg?msg:""); routerlist_remove(rl, ent, 0, time(NULL)); - i--; changed = 1; continue; } - if (bool_neq((r & FP_NAMED), ent->is_named)) { +#if 0 + if (bool_neq((r & FP_NAMED), ent->auth_says_is_named)) { log_info(LD_DIRSERV, "Router %s is now %snamed.", description, (r&FP_NAMED)?"":"un"); ent->is_named = (r&FP_NAMED)?1:0; changed = 1; } - if (bool_neq((r & FP_INVALID), !ent->is_valid)) { + if (bool_neq((r & FP_UNNAMED), ent->auth_says_is_unnamed)) { + log_info(LD_DIRSERV, + "Router '%s' is now %snamed. (FP_UNNAMED)", description, + (r&FP_NAMED)?"":"un"); + ent->is_named = (r&FP_NUNAMED)?0:1; + changed = 1; + } +#endif + if (bool_neq((r & FP_INVALID), !node->is_valid)) { log_info(LD_DIRSERV, "Router '%s' is now %svalid.", description, (r&FP_INVALID) ? "in" : ""); - ent->is_valid = (r&FP_INVALID)?0:1; + node->is_valid = (r&FP_INVALID)?0:1; changed = 1; } - if (bool_neq((r & FP_BADDIR), ent->is_bad_directory)) { + if (bool_neq((r & FP_BADDIR), node->is_bad_directory)) { log_info(LD_DIRSERV, "Router '%s' is now a %s directory", description, (r & FP_BADDIR) ? "bad" : "good"); - ent->is_bad_directory = (r&FP_BADDIR) ? 1: 0; + node->is_bad_directory = (r&FP_BADDIR) ? 1: 0; changed = 1; } - if (bool_neq((r & FP_BADEXIT), ent->is_bad_exit)) { + if (bool_neq((r & FP_BADEXIT), node->is_bad_exit)) { log_info(LD_DIRSERV, "Router '%s' is now a %s exit", description, (r & FP_BADEXIT) ? "bad" : "good"); - ent->is_bad_exit = (r&FP_BADEXIT) ? 1: 0; + node->is_bad_exit = (r&FP_BADEXIT) ? 1: 0; changed = 1; } - } + } SMARTLIST_FOREACH_END(node); if (changed) directory_set_dirty(); routerlist_assert_ok(rl); + smartlist_free(nodes); } /** Mark the directory as <b>dirty</b> -- when we're next asked for a @@ -907,10 +926,11 @@ directory_set_dirty(void) * as running iff <b>is_live</b> is true. */ static char * -list_single_server_status(routerinfo_t *desc, int is_live) +list_single_server_status(const routerinfo_t *desc, int is_live) { char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */ char *cp; + const node_t *node; tor_assert(desc); @@ -918,7 +938,8 @@ list_single_server_status(routerinfo_t *desc, int is_live) if (!is_live) { *cp++ = '!'; } - if (desc->is_valid) { + node = node_get_by_id(desc->cache_info.identity_digest); + if (node && node->is_valid) { strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf)); cp += strlen(cp); *cp++ = '='; @@ -957,6 +978,8 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now) unreachable. */ int answer; + node_t *node = node_get_mutable_by_id(router->cache_info.identity_digest); + tor_assert(node); if (router_is_me(router)) { /* We always know if we are down ourselves. */ @@ -991,7 +1014,7 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now) rep_hist_note_router_unreachable(router->cache_info.identity_digest, when); } - router->is_running = answer; + node->is_running = answer; } /** Based on the routerinfo_ts in <b>routers</b>, allocate the @@ -1009,7 +1032,7 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out, smartlist_t *rs_entries; time_t now = time(NULL); time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); /* We include v2 dir auths here too, because they need to answer * controllers. Eventually we'll deprecate this whole function; * see also networkstatus_getinfo_by_purpose(). */ @@ -1019,6 +1042,8 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out, rs_entries = smartlist_create(); SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) { + const node_t *node = node_get_by_id(ri->cache_info.identity_digest); + tor_assert(node); if (authdir) { /* Update router status in routerinfo_t. */ dirserv_set_router_is_running(ri, now); @@ -1026,12 +1051,13 @@ list_server_status_v1(smartlist_t *routers, char **router_status_out, if (for_controller) { char name_buf[MAX_VERBOSE_NICKNAME_LEN+2]; char *cp = name_buf; - if (!ri->is_running) + if (!node->is_running) *cp++ = '!'; router_get_verbose_nickname(cp, ri); smartlist_add(rs_entries, tor_strdup(name_buf)); } else if (ri->cache_info.published_on >= cutoff) { - smartlist_add(rs_entries, list_single_server_status(ri, ri->is_running)); + smartlist_add(rs_entries, list_single_server_status(ri, + node->is_running)); } } SMARTLIST_FOREACH_END(ri); @@ -1069,12 +1095,12 @@ format_versions_list(config_line_t *ln) * not hibernating, and not too old. Else return 0. */ static int -router_is_active(routerinfo_t *ri, time_t now) +router_is_active(const routerinfo_t *ri, const node_t *node, time_t now) { time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH; if (ri->cache_info.published_on < cutoff) return 0; - if (!ri->is_running || !ri->is_valid || ri->is_hibernating) + if (!node->is_running || !node->is_valid || ri->is_hibernating) return 0; return 1; } @@ -1173,9 +1199,9 @@ dirserv_dump_directory_to_string(char **dir_out, /** Return 1 if we fetch our directory material directly from the * authorities, rather than from a mirror. */ int -directory_fetches_from_authorities(or_options_t *options) +directory_fetches_from_authorities(const or_options_t *options) { - routerinfo_t *me; + const routerinfo_t *me; uint32_t addr; int refuseunknown; if (options->FetchDirInfoEarly) @@ -1200,7 +1226,7 @@ directory_fetches_from_authorities(or_options_t *options) * on the "mirror" schedule rather than the "client" schedule. */ int -directory_fetches_dir_info_early(or_options_t *options) +directory_fetches_dir_info_early(const or_options_t *options) { return directory_fetches_from_authorities(options); } @@ -1212,7 +1238,7 @@ directory_fetches_dir_info_early(or_options_t *options) * client as a directory guard. */ int -directory_fetches_dir_info_later(or_options_t *options) +directory_fetches_dir_info_later(const or_options_t *options) { return options->UseBridges != 0; } @@ -1220,7 +1246,7 @@ directory_fetches_dir_info_later(or_options_t *options) /** Return 1 if we want to cache v2 dir info (each status file). */ int -directory_caches_v2_dir_info(or_options_t *options) +directory_caches_v2_dir_info(const or_options_t *options) { return options->DirPort != 0; } @@ -1229,7 +1255,7 @@ directory_caches_v2_dir_info(or_options_t *options) * and we're willing to serve them to others. Else return 0. */ int -directory_caches_dir_info(or_options_t *options) +directory_caches_dir_info(const or_options_t *options) { if (options->BridgeRelay || options->DirPort) return 1; @@ -1245,7 +1271,7 @@ directory_caches_dir_info(or_options_t *options) * requests via the "begin_dir" interface, which doesn't require * having any separate port open. */ int -directory_permits_begindir_requests(or_options_t *options) +directory_permits_begindir_requests(const or_options_t *options) { return options->BridgeRelay != 0 || options->DirPort != 0; } @@ -1254,7 +1280,7 @@ directory_permits_begindir_requests(or_options_t *options) * requests via the controller interface, which doesn't require * having any separate port open. */ int -directory_permits_controller_requests(or_options_t *options) +directory_permits_controller_requests(const or_options_t *options) { return options->DirPort != 0; } @@ -1264,7 +1290,8 @@ directory_permits_controller_requests(or_options_t *options) * lately. */ int -directory_too_idle_to_fetch_descriptors(or_options_t *options, time_t now) +directory_too_idle_to_fetch_descriptors(const or_options_t *options, + time_t now) { return !directory_caches_dir_info(options) && !options->FetchUselessDescriptors && @@ -1287,7 +1314,8 @@ static cached_dir_t cached_runningrouters; * cached_dir_t. */ static digestmap_t *cached_v2_networkstatus = NULL; -/** Map from flavor name to the v3 consensuses that we're currently serving. */ +/** Map from flavor name to the cached_dir_t for the v3 consensuses that we're + * currently serving. */ static strmap_t *cached_consensuses = NULL; /** Possibly replace the contents of <b>d</b> with the value of @@ -1531,11 +1559,11 @@ dirserv_pick_cached_dir_obj(cached_dir_t *cache_src, cached_dir_t *auth_src, time_t dirty, cached_dir_t *(*regenerate)(void), const char *name, - authority_type_t auth_type) + dirinfo_type_t auth_type) { - or_options_t *options = get_options(); - int authority = (auth_type == V1_AUTHORITY && authdir_mode_v1(options)) || - (auth_type == V2_AUTHORITY && authdir_mode_v2(options)); + const or_options_t *options = get_options(); + int authority = (auth_type == V1_DIRINFO && authdir_mode_v1(options)) || + (auth_type == V2_DIRINFO && authdir_mode_v2(options)); if (!authority || authdir_mode_bridge(options)) { return cache_src; @@ -1564,7 +1592,7 @@ dirserv_get_directory(void) return dirserv_pick_cached_dir_obj(cached_directory, the_directory, the_directory_is_dirty, dirserv_regenerate_directory, - "v1 server directory", V1_AUTHORITY); + "v1 server directory", V1_DIRINFO); } /** Only called by v1 auth dirservers. @@ -1657,7 +1685,7 @@ dirserv_get_runningrouters(void) &cached_runningrouters, &the_runningrouters, runningrouters_is_dirty, generate_runningrouters, - "v1 network status list", V1_AUTHORITY); + "v1 network status list", V1_DIRINFO); } /** Return the latest downloaded consensus networkstatus in encoded, signed, @@ -1692,12 +1720,6 @@ should_generate_v2_networkstatus(void) /** If a router's MTBF is at least this value, then it is always stable. * See above. (Corresponds to about 7 days for current decay rates.) */ #define MTBF_TO_GUARANTEE_STABLE (60*60*24*5) -/** Similarly, we protect sufficiently fast nodes from being pushed - * out of the set of Fast nodes. */ -#define BANDWIDTH_TO_GUARANTEE_FAST ROUTER_REQUIRED_MIN_BANDWIDTH -/** Similarly, every node with sufficient bandwidth can be considered - * for Guard status. */ -#define BANDWIDTH_TO_GUARANTEE_GUARD (250*1024) /** Similarly, every node with at least this much weighted time known can be * considered familiar enough to be a guard. Corresponds to about 20 days for * current decay rates. @@ -1740,7 +1762,7 @@ static uint64_t total_exit_bandwidth = 0; /** Helper: estimate the uptime of a router given its stated uptime and the * amount of time since it last stated its stated uptime. */ static INLINE long -real_uptime(routerinfo_t *router, time_t now) +real_uptime(const routerinfo_t *router, time_t now) { if (now < router->cache_info.published_on) return router->uptime; @@ -1794,7 +1816,8 @@ dirserv_thinks_router_is_unreliable(time_t now, * been set. */ static int -dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now) +dirserv_thinks_router_is_hs_dir(const routerinfo_t *router, + const node_t *node, time_t now) { long uptime; @@ -1822,7 +1845,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 @@ -1841,6 +1864,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl) long *tks; double *mtbfs, *wfus; time_t now = time(NULL); + const or_options_t *options = get_options(); /* initialize these all here, in case there are no routers */ stable_uptime = 0; @@ -1870,19 +1894,22 @@ dirserv_compute_performance_thresholds(routerlist_t *rl) /* Weighted fractional uptime for each active router. */ wfus = tor_malloc(sizeof(double)*smartlist_len(rl->routers)); + nodelist_assert_ok(); + /* Now, fill in the arrays. */ - SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, { - if (router_is_active(ri, now)) { + SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) { + routerinfo_t *ri = node->ri; + if (ri && router_is_active(ri, node, now)) { const char *id = ri->cache_info.identity_digest; uint32_t bw; - ri->is_exit = (!router_exit_policy_rejects_all(ri) && - exit_policy_is_general_exit(ri->exit_policy)); + node->is_exit = (!router_exit_policy_rejects_all(ri) && + exit_policy_is_general_exit(ri->exit_policy)); uptimes[n_active] = (uint32_t)real_uptime(ri, now); mtbfs[n_active] = rep_hist_get_stability(id, now); tks [n_active] = rep_hist_get_weighted_time_known(id, now); bandwidths[n_active] = bw = router_get_advertised_bandwidth(ri); total_bandwidth += bw; - if (ri->is_exit && !ri->is_bad_exit) { + if (node->is_exit && !node->is_bad_exit) { total_exit_bandwidth += bw; } else { bandwidths_excluding_exits[n_active_nonexit] = bw; @@ -1890,7 +1917,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl) } ++n_active; } - }); + } SMARTLIST_FOREACH_END(node); /* Now, compute thresholds. */ if (n_active) { @@ -1910,21 +1937,26 @@ dirserv_compute_performance_thresholds(routerlist_t *rl) if (guard_tk > TIME_KNOWN_TO_GUARANTEE_FAMILIAR) guard_tk = TIME_KNOWN_TO_GUARANTEE_FAMILIAR; - if (fast_bandwidth > BANDWIDTH_TO_GUARANTEE_FAST) - fast_bandwidth = BANDWIDTH_TO_GUARANTEE_FAST; + /* Protect sufficiently fast nodes from being pushed out of the set + * of Fast nodes. */ + if (options->AuthDirFastGuarantee && + fast_bandwidth > options->AuthDirFastGuarantee) + fast_bandwidth = (uint32_t)options->AuthDirFastGuarantee; /* Now that we have a time-known that 7/8 routers are known longer than, * fill wfus with the wfu of every such "familiar" router. */ n_familiar = 0; - SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, { - if (router_is_active(ri, now)) { + + SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) { + routerinfo_t *ri = node->ri; + if (ri && router_is_active(ri, node, now)) { const char *id = ri->cache_info.identity_digest; long tk = rep_hist_get_weighted_time_known(id, now); if (tk < guard_tk) continue; wfus[n_familiar++] = rep_hist_get_weighted_fractional_uptime(id, now); } - }); + } SMARTLIST_FOREACH_END(node); if (n_familiar) guard_wfu = median_double(wfus, n_familiar); if (guard_wfu > WFU_TO_GUARANTEE_GUARD) @@ -1995,24 +2027,20 @@ version_from_platform(const char *platform) */ int routerstatus_format_entry(char *buf, size_t buf_len, - routerstatus_t *rs, const char *version, + const routerstatus_t *rs, const char *version, routerstatus_format_type_t format) { int r; - struct in_addr in; char *cp; char *summary; char published[ISO_TIME_LEN+1]; - char ipaddr[INET_NTOA_BUF_LEN]; char identity64[BASE64_DIGEST_LEN+1]; char digest64[BASE64_DIGEST_LEN+1]; format_iso_time(published, rs->published_on); digest_to_base64(identity64, rs->identity_digest); digest_to_base64(digest64, rs->descriptor_digest); - in.s_addr = htonl(rs->addr); - tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr)); r = tor_snprintf(buf, buf_len, "r %s %s %s%s%s %s %d %d\n", @@ -2021,7 +2049,7 @@ routerstatus_format_entry(char *buf, size_t buf_len, (format==NS_V3_CONSENSUS_MICRODESC)?"":digest64, (format==NS_V3_CONSENSUS_MICRODESC)?"":" ", published, - ipaddr, + fmt_addr32(rs->addr), (int)rs->or_port, (int)rs->dir_port); if (r<0) { @@ -2049,7 +2077,7 @@ routerstatus_format_entry(char *buf, size_t buf_len, rs->is_possible_guard?" Guard":"", rs->is_hs_dir?" HSDir":"", rs->is_named?" Named":"", - rs->is_running?" Running":"", + rs->is_flagged_running?" Running":"", rs->is_stable?" Stable":"", rs->is_unnamed?" Unnamed":"", rs->is_v2_dir?" V2Dir":"", @@ -2071,7 +2099,7 @@ routerstatus_format_entry(char *buf, size_t buf_len, } if (format != NS_V2) { - routerinfo_t* desc = router_get_by_digest(rs->identity_digest); + const routerinfo_t* desc = router_get_by_id_digest(rs->identity_digest); uint32_t bw; if (format != NS_CONTROL_PORT) { @@ -2167,6 +2195,8 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b) routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b; int first_is_auth, second_is_auth; uint32_t bw_first, bw_second; + const node_t *node_first, *node_second; + int first_is_running, second_is_running; /* we return -1 if first should appear before second... that is, * if first is a better router. */ @@ -2189,9 +2219,14 @@ _compare_routerinfo_by_ip_and_bw(const void **a, const void **b) else if (!first_is_auth && second_is_auth) return 1; - else if (first->is_running && !second->is_running) + node_first = node_get_by_id(first->cache_info.identity_digest); + node_second = node_get_by_id(second->cache_info.identity_digest); + first_is_running = node_first && node_first->is_running; + second_is_running = node_second && node_second->is_running; + + if (first_is_running && !second_is_running) return -1; - else if (!first->is_running && second->is_running) + else if (!first_is_running && second_is_running) return 1; bw_first = router_get_advertised_bandwidth(first); @@ -2215,7 +2250,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; @@ -2251,6 +2286,75 @@ get_possible_sybil_list(const smartlist_t *routers) return omit_as_sybil; } +/** Return non-zero iff a relay running the Tor version specified in + * <b>platform</b> is suitable for use as a potential entry guard. */ +static int +is_router_version_good_for_possible_guard(const char *platform) +{ + static int parsed_versions_initialized = 0; + static tor_version_t first_good_0_2_1_guard_version; + static tor_version_t first_good_0_2_2_guard_version; + static tor_version_t first_good_later_guard_version; + + tor_version_t router_version; + + /* XXX023 This block should be extracted into its own function. */ + /* XXXX Begin code copied from tor_version_as_new_as (in routerparse.c) */ + { + char *s, *s2, *start; + char tmp[128]; + + tor_assert(platform); + + /* nonstandard Tor; be safe and say yes */ + if (strcmpstart(platform,"Tor ")) + return 1; + + start = (char *)eat_whitespace(platform+3); + if (!*start) return 0; + s = (char *)find_whitespace(start); /* also finds '\0', which is fine */ + s2 = (char*)eat_whitespace(s); + if (!strcmpstart(s2, "(r") || !strcmpstart(s2, "(git-")) + s = (char*)find_whitespace(s2); + + if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */ + return 0; + strlcpy(tmp, start, s-start+1); + + if (tor_version_parse(tmp, &router_version)<0) { + log_info(LD_DIR,"Router version '%s' unparseable.",tmp); + return 1; /* be safe and say yes */ + } + } + /* XXXX End code copied from tor_version_as_new_as (in routerparse.c) */ + + if (!parsed_versions_initialized) { + /* CVE-2011-2769 was fixed on the relay side in Tor versions + * 0.2.1.31, 0.2.2.34, and 0.2.3.6-alpha. */ + tor_assert(tor_version_parse("0.2.1.31", + &first_good_0_2_1_guard_version)>=0); + tor_assert(tor_version_parse("0.2.2.34", + &first_good_0_2_2_guard_version)>=0); + tor_assert(tor_version_parse("0.2.3.6-alpha", + &first_good_later_guard_version)>=0); + + /* Don't parse these constant version strings once for every relay + * for every vote. */ + parsed_versions_initialized = 1; + } + + return ((tor_version_same_series(&first_good_0_2_1_guard_version, + &router_version) && + tor_version_compare(&first_good_0_2_1_guard_version, + &router_version) <= 0) || + (tor_version_same_series(&first_good_0_2_2_guard_version, + &router_version) && + tor_version_compare(&first_good_0_2_2_guard_version, + &router_version) <= 0) || + (tor_version_compare(&first_good_later_guard_version, + &router_version) <= 0)); +} + /** Extract status information from <b>ri</b> and from other authority * functions and store it in <b>rs</b>>. If <b>naming</b>, consider setting * the named flag in <b>rs</b>. @@ -2260,60 +2364,68 @@ get_possible_sybil_list(const smartlist_t *routers) */ void set_routerstatus_from_routerinfo(routerstatus_t *rs, - routerinfo_t *ri, time_t now, + node_t *node, + routerinfo_t *ri, + time_t now, int naming, int listbadexits, int listbaddirs, int vote_on_hsdirs) { + const or_options_t *options = get_options(); int unstable_version = !tor_version_as_new_as(ri->platform,"0.1.1.16-rc-cvs"); + uint32_t routerbw = router_get_advertised_bandwidth(ri); + memset(rs, 0, sizeof(routerstatus_t)); rs->is_authority = 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 && - (router_get_advertised_bandwidth(ri) >= BANDWIDTH_TO_GUARANTEE_GUARD || - router_get_advertised_bandwidth(ri) >= - MIN(guard_bandwidth_including_exits, - guard_bandwidth_excluding_exits))) { + if (node->is_fast && + ((options->AuthDirGuardBWGuarantee && + routerbw >= options->AuthDirGuardBWGuarantee) || + routerbw >= MIN(guard_bandwidth_including_exits, + guard_bandwidth_excluding_exits)) && + (options->GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays || + is_router_version_good_for_possible_guard(ri->platform))) { long tk = rep_hist_get_weighted_time_known( - ri->cache_info.identity_digest, now); + node->identity, now); double wfu = rep_hist_get_weighted_fractional_uptime( - ri->cache_info.identity_digest, now); + 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 = vote_on_hsdirs && ri->is_hs_dir; + + rs->is_bad_directory = listbaddirs && node->is_bad_directory; + rs->is_bad_exit = listbadexits && node->is_bad_exit; + node->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, node, now); + rs->is_hs_dir = vote_on_hsdirs && node->is_hs_dir; rs->is_v2_dir = ri->dir_port != 0; if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME)) rs->is_named = rs->is_unnamed = 0; rs->published_on = ri->cache_info.published_on; - memcpy(rs->identity_digest, ri->cache_info.identity_digest, DIGEST_LEN); + memcpy(rs->identity_digest, node->identity, DIGEST_LEN); memcpy(rs->descriptor_digest, ri->cache_info.signed_descriptor_digest, DIGEST_LEN); rs->addr = ri->addr; @@ -2330,7 +2442,7 @@ static void clear_status_flags_on_sybil(routerstatus_t *rs) { rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast = - rs->is_running = rs->is_named = rs->is_valid = rs->is_v2_dir = + rs->is_flagged_running = rs->is_named = rs->is_valid = rs->is_v2_dir = rs->is_hs_dir = rs->is_possible_guard = rs->is_bad_exit = rs->is_bad_directory = 0; /* FFFF we might want some mechanism to check later on if we @@ -2338,18 +2450,6 @@ clear_status_flags_on_sybil(routerstatus_t *rs) * forget to add it to this clause. */ } -/** Clear all the status flags in routerinfo <b>router</b>. We put this - * function here because it's eerily similar to - * clear_status_flags_on_sybil() above. One day we should merge them. */ -void -router_clear_status_flags(routerinfo_t *router) -{ - router->is_valid = router->is_running = router->is_hs_dir = - router->is_fast = router->is_stable = - router->is_possible_guard = router->is_exit = - router->is_bad_exit = router->is_bad_directory = 0; -} - /** * Helper function to parse out a line in the measured bandwidth file * into a measured_bw_line_t output structure. Returns -1 on failure @@ -2467,7 +2567,7 @@ dirserv_read_measured_bandwidths(const char *from_file, smartlist_t *routerstatuses) { char line[256]; - FILE *fp = fopen(from_file, "r"); + FILE *fp = tor_fopen_cloexec(from_file, "r"); int applied_lines = 0; time_t file_time; int ok; @@ -2527,7 +2627,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; @@ -2598,10 +2698,13 @@ 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, vote_on_hsdirs); @@ -2609,7 +2712,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, 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); @@ -2743,12 +2846,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(); @@ -2770,8 +2871,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); @@ -2789,7 +2888,7 @@ generate_v2_networkstatus_opinion(void) goto done; } - contact = get_options()->ContactInfo; + contact = options->ContactInfo; if (!contact) contact = "(none)"; @@ -2817,7 +2916,7 @@ generate_v2_networkstatus_opinion(void) "dir-options%s%s%s%s\n" "%s" /* client version line, server version line. */ "dir-signing-key\n%s", - hostname, ipaddr, + hostname, fmt_addr32(addr), (int)router_get_advertised_dir_port(options, 0), fingerprint, contact, @@ -2849,8 +2948,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, vote_on_hsdirs); @@ -2868,7 +2971,7 @@ generate_v2_networkstatus_opinion(void) }); if (tor_snprintf(outp, endp-outp, "directory-signature %s\n", - get_options()->Nickname)<0) { + options->Nickname)<0) { log_warn(LD_BUG, "Unable to write signature line."); goto done; } @@ -2934,7 +3037,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)); @@ -2953,7 +3056,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); @@ -3022,7 +3125,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)); @@ -3042,8 +3145,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) @@ -3054,7 +3157,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)) { @@ -3093,9 +3196,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/"); @@ -3119,17 +3222,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)); @@ -3178,7 +3281,7 @@ dirserv_orconn_tls_done(const char *address, log_info(LD_DIRSERV, "Found router %s to be reachable at %s:%d. Yay.", router_describe(ri), address, ri->or_port); - if (tor_addr_from_str(&addr, ri->address) != -1) + if (tor_addr_parse(&addr, ri->address) != -1) addrp = &addr; else log_warn(LD_BUG, "Couldn't parse IP address \"%s\"", ri->address); @@ -3196,7 +3299,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; @@ -3320,7 +3424,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) { @@ -3330,7 +3434,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) @@ -3398,7 +3502,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%. */ @@ -3452,20 +3556,19 @@ connection_dirserv_finish_spooling(dir_connection_t *conn) static int connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn) { -#ifdef TRACK_SERVED_TIME - time_t now = time(NULL); -#endif int by_fp = (conn->dir_spool_src == DIR_SPOOL_SERVER_BY_FP || conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_FP); int extra = (conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_FP || conn->dir_spool_src == DIR_SPOOL_EXTRA_BY_DIGEST); time_t publish_cutoff = time(NULL)-ROUTER_MAX_AGE_TO_PUBLISH; + const or_options_t *options = get_options(); + 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 { @@ -3482,9 +3585,17 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn) * unknown bridge descriptor has shown up between then and now. */ continue; } -#ifdef TRACK_SERVED_TIME - sd->last_served_at = now; -#endif + + /** If we are the bridge authority and the descriptor is a bridge + * descriptor, remember that we served this descriptor for desc stats. */ + if (options->BridgeAuthoritativeDir && by_fp) { + const routerinfo_t *router = + router_get_by_id_digest(sd->identity_digest); + /* router can be NULL here when the bridge auth is asked for its own + * descriptor. */ + if (router && router->purpose == ROUTER_PURPOSE_BRIDGE) + rep_hist_note_desc_served(sd->identity_digest); + } body = signed_descriptor_get_body(sd); if (conn->zlib_state) { /* XXXX022 This 'last' business should actually happen on the last @@ -3523,7 +3634,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); @@ -3562,7 +3673,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) @@ -3601,7 +3712,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); @@ -3647,7 +3758,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 569abfca2e..d3fd90ceb5 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 c6ce9f6776..01e2358c44 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -50,7 +50,7 @@ static int dirvote_publish_consensus(void); static char *make_consensus_method_list(int low, int high, const char *sep); /** The highest consensus method that we currently support. */ -#define MAX_SUPPORTED_CONSENSUS_METHOD 11 +#define MAX_SUPPORTED_CONSENSUS_METHOD 12 /** Lowest consensus method that contains a 'directory-footer' marker */ #define MIN_METHOD_FOR_FOOTER 9 @@ -64,6 +64,10 @@ static char *make_consensus_method_list(int low, int high, const char *sep); /** Lowest consensus method that generates microdescriptors */ #define MIN_METHOD_FOR_MICRODESC 8 +/** Lowest consensus method that ensures a majority of authorities voted + * for a param. */ +#define MIN_METHOD_FOR_MAJORITY_PARAMS 12 + /* ===== * Voting * =====*/ @@ -83,9 +87,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 +100,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 +186,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"); @@ -611,11 +612,16 @@ compute_consensus_versions_list(smartlist_t *lst, int n_versioning) return result; } +/** Minimum number of directory authorities voting for a parameter to + * include it in the consensus, if consensus method 12 or later is to be + * used. See proposal 178 for details. */ +#define MIN_VOTES_FOR_PARAM 3 + /** Helper: given a list of valid networkstatus_t, return a new string * containing the contents of the consensus network parameter set. */ /* private */ char * -dirvote_compute_params(smartlist_t *votes) +dirvote_compute_params(smartlist_t *votes, int method, int total_authorities) { int i; int32_t *vals; @@ -672,11 +678,17 @@ dirvote_compute_params(smartlist_t *votes) next_param = smartlist_get(param_list, param_sl_idx+1); if (!next_param || strncmp(next_param, param, cur_param_len)) { /* We've reached the end of a series. */ - int32_t median = median_int32(vals, i); - char *out_string = tor_malloc(64+cur_param_len); - memcpy(out_string, param, cur_param_len); - tor_snprintf(out_string+cur_param_len,64, "%ld", (long)median); - smartlist_add(output, out_string); + /* Make sure enough authorities voted on this param, unless the + * the consensus method we use is too old for that. */ + if (method < MIN_METHOD_FOR_MAJORITY_PARAMS || + i > total_authorities/2 || + i >= MIN_VOTES_FOR_PARAM) { + int32_t median = median_int32(vals, i); + char *out_string = tor_malloc(64+cur_param_len); + memcpy(out_string, param, cur_param_len); + tor_snprintf(out_string+cur_param_len,64, "%ld", (long)median); + smartlist_add(output, out_string); + } i = 0; if (next_param) { @@ -1499,7 +1511,8 @@ networkstatus_compute_consensus(smartlist_t *votes, } if (consensus_method >= MIN_METHOD_FOR_PARAMS) { - params = dirvote_compute_params(votes); + params = dirvote_compute_params(votes, consensus_method, + total_authorities); if (params) { smartlist_add(chunks, tor_strdup("params ")); smartlist_add(chunks, params); @@ -1530,8 +1543,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 +1552,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 +1559,7 @@ networkstatus_compute_consensus(smartlist_t *votes, tor_asprintf(&buf, "dir-source %s%s %s %s %s %d %d\n", voter->nickname, e->is_legacy ? "-legacy" : "", - fingerprint, voter->address, ip, + fingerprint, voter->address, fmt_addr32(voter->addr), voter->dir_port, voter->or_port); smartlist_add(chunks, buf); @@ -2511,7 +2520,7 @@ authority_cert_dup(authority_cert_t *cert) void dirvote_get_preferred_voting_intervals(vote_timing_t *timing_out) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); tor_assert(timing_out); @@ -2585,7 +2594,7 @@ static struct { /** Set voting_schedule to hold the timing for the next vote we should be * doing. */ void -dirvote_recalculate_timing(or_options_t *options, time_t now) +dirvote_recalculate_timing(const or_options_t *options, time_t now) { int interval, vote_delay, dist_delay; time_t start; @@ -2636,7 +2645,7 @@ dirvote_recalculate_timing(or_options_t *options, time_t now) /** Entry point: Take whatever voting actions are pending as of <b>now</b>. */ void -dirvote_act(or_options_t *options, time_t now) +dirvote_act(const or_options_t *options, time_t now) { if (!authdir_mode_v3(options)) return; @@ -2751,7 +2760,7 @@ dirvote_perform_vote(void) directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_VOTE, ROUTER_PURPOSE_GENERAL, - V3_AUTHORITY, + V3_DIRINFO, pending_vote->vote_body->dir, pending_vote->vote_body->dir_len, 0); log_notice(LD_DIR, "Vote posted."); @@ -2770,7 +2779,7 @@ dirvote_fetch_missing_votes(void) SMARTLIST_FOREACH(router_get_trusted_dir_servers(), trusted_dir_server_t *, ds, { - if (!(ds->type & V3_AUTHORITY)) + if (!(ds->type & V3_DIRINFO)) continue; if (!dirvote_get_vote(ds->v3_identity_digest, DGV_BY_ID|DGV_INCLUDE_PENDING)) { @@ -2883,7 +2892,7 @@ list_v3_auth_ids(void) char *keys; SMARTLIST_FOREACH(router_get_trusted_dir_servers(), trusted_dir_server_t *, ds, - if ((ds->type & V3_AUTHORITY) && + if ((ds->type & V3_DIRINFO) && !tor_digest_is_zero(ds->v3_identity_digest)) smartlist_add(known_v3_keys, tor_strdup(hex_str(ds->v3_identity_digest, DIGEST_LEN)))); @@ -3078,7 +3087,7 @@ dirvote_compute_consensuses(void) if (!pending_vote_list) pending_vote_list = smartlist_create(); - n_voters = get_n_authorities(V3_AUTHORITY); + n_voters = get_n_authorities(V3_DIRINFO); n_votes = smartlist_len(pending_vote_list); if (n_votes <= n_voters/2) { log_warn(LD_DIR, "We don't have enough votes to generate a consensus: " @@ -3217,7 +3226,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 de11fcf997..1f4dc362b5 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, int vote_on_hsdirs); @@ -83,7 +84,8 @@ document_signature_t *voter_get_sig_by_algorithm( #ifdef DIRVOTE_PRIVATE char *format_networkstatus_vote(crypto_pk_env_t *private_key, networkstatus_t *v3_ns); -char *dirvote_compute_params(smartlist_t *votes); +char *dirvote_compute_params(smartlist_t *votes, int method, + int total_authorities); #endif #endif diff --git a/src/or/dns.c b/src/or/dns.c index 9b6b98afaf..beb110acb2 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; @@ -687,7 +687,7 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, /* first check if exitconn->_base.address is an IP. If so, we already * know the answer. */ - if (tor_addr_from_str(&addr, exitconn->_base.address) >= 0) { + if (tor_addr_parse(&addr, exitconn->_base.address) >= 0) { if (tor_addr_family(&addr) == AF_INET) { tor_addr_copy(&exitconn->_base.addr, &addr); exitconn->address_ttl = DEFAULT_DNS_TTL; @@ -721,7 +721,7 @@ dns_resolve_impl(edge_connection_t *exitconn, int is_resolve, * .in-addr.arpa address but this isn't a resolve request, kill the * connection. */ - if ((r = tor_addr_parse_reverse_lookup_name(&addr, exitconn->_base.address, + if ((r = tor_addr_parse_PTR_name(&addr, exitconn->_base.address, AF_UNSPEC, 0)) != 0) { if (r == 1) { is_reverse = 1; @@ -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; @@ -1198,7 +1198,7 @@ configure_nameservers(int force) #ifdef HAVE_EVDNS_SET_DEFAULT_OUTGOING_BIND_ADDRESS if (options->OutboundBindAddress) { tor_addr_t addr; - if (tor_addr_from_str(&addr, options->OutboundBindAddress) < 0) { + if (tor_addr_parse(&addr, options->OutboundBindAddress) < 0) { log_warn(LD_CONFIG,"Outbound bind address '%s' didn't parse. Ignoring.", options->OutboundBindAddress); } else { @@ -1395,6 +1395,10 @@ launch_resolve(edge_connection_t *exitconn) int r; int options = get_options()->ServerDNSSearchDomains ? 0 : DNS_QUERY_NO_SEARCH; + + if (get_options()->DisableNetwork) + return -1; + /* What? Nameservers not configured? Sounds like a bug. */ if (!nameservers_configured) { log_warn(LD_EXIT, "(Harmless.) Nameservers not configured, but resolve " @@ -1404,7 +1408,7 @@ launch_resolve(edge_connection_t *exitconn) } } - r = tor_addr_parse_reverse_lookup_name( + r = tor_addr_parse_PTR_name( &a, exitconn->_base.address, AF_UNSPEC, 0); tor_assert(the_evdns_base); @@ -1595,12 +1599,15 @@ 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; (void)args; + if (options->DisableNetwork) + return; + log_info(LD_EXIT, "Launching checks to see whether our nameservers like to " "hijack *everything*."); /* This situation is worse than the failure-hijacking situation. When this diff --git a/src/or/dnsserv.c b/src/or/dnsserv.c index f2c473dfc5..7f519398fa 100644 --- a/src/or/dnsserv.c +++ b/src/or/dnsserv.c @@ -29,8 +29,10 @@ * DNSPort. We need to eventually answer the request <b>req</b>. */ static void -evdns_server_callback(struct evdns_server_request *req, void *_data) +evdns_server_callback(struct evdns_server_request *req, void *data_) { + const listener_connection_t *listener = data_; + entry_connection_t *entry_conn; edge_connection_t *conn; int i = 0; struct evdns_server_question *q = NULL; @@ -43,7 +45,7 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) char *q_name; tor_assert(req); - tor_assert(_data == NULL); + log_info(LD_APP, "Got a new DNS request!"); req->flags |= 0x80; /* set RA */ @@ -114,8 +116,9 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) } /* Make a new dummy AP connection, and attach the request to it. */ - conn = edge_connection_new(CONN_TYPE_AP, AF_INET); - conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT; + entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET); + conn = ENTRY_TO_EDGE_CONN(entry_conn); + TO_CONN(conn)->state = AP_CONN_STATE_RESOLVE_WAIT; conn->is_dns_request = 1; tor_addr_copy(&TO_CONN(conn)->addr, &tor_addr); @@ -123,23 +126,27 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) TO_CONN(conn)->address = tor_dup_addr(&tor_addr); if (q->type == EVDNS_TYPE_A) - conn->socks_request->command = SOCKS_COMMAND_RESOLVE; + entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE; else - conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; + entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; - strlcpy(conn->socks_request->address, q->name, - sizeof(conn->socks_request->address)); + strlcpy(entry_conn->socks_request->address, q->name, + sizeof(entry_conn->socks_request->address)); - conn->dns_server_request = req; + entry_conn->socks_request->listener_type = listener->_base.type; + entry_conn->dns_server_request = req; + entry_conn->isolation_flags = listener->isolation_flags; + entry_conn->session_group = listener->session_group; + entry_conn->nym_epoch = get_signewnym_epoch(); - if (connection_add(TO_CONN(conn)) < 0) { + if (connection_add(ENTRY_TO_CONN(entry_conn)) < 0) { log_warn(LD_APP, "Couldn't register dummy connection for DNS request"); evdns_server_request_respond(req, DNS_ERR_SERVERFAILED); - connection_free(TO_CONN(conn)); + connection_free(ENTRY_TO_CONN(entry_conn)); return; } - control_event_stream_status(conn, STREAM_EVENT_NEW, 0); + control_event_stream_status(entry_conn, STREAM_EVENT_NEW, 0); /* Now, unless a controller asked us to leave streams unattached, * throw the connection over to get rewritten (which will @@ -148,7 +155,7 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) log_info(LD_APP, "Passing request for %s to rewrite_and_attach.", escaped_safe_str_client(q->name)); q_name = tor_strdup(q->name); /* q could be freed in rewrite_and_attach */ - connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL); + connection_ap_rewrite_and_attach_if_allowed(entry_conn, NULL, NULL); /* Now, the connection is marked if it was bad. */ log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.", @@ -164,22 +171,30 @@ evdns_server_callback(struct evdns_server_request *req, void *_data) int dnsserv_launch_request(const char *name, int reverse) { + entry_connection_t *entry_conn; edge_connection_t *conn; char *q_name; /* Make a new dummy AP connection, and attach the request to it. */ - conn = edge_connection_new(CONN_TYPE_AP, AF_INET); + entry_conn = entry_connection_new(CONN_TYPE_AP, AF_INET); + conn = ENTRY_TO_EDGE_CONN(entry_conn); conn->_base.state = AP_CONN_STATE_RESOLVE_WAIT; if (reverse) - conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; + entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE_PTR; else - conn->socks_request->command = SOCKS_COMMAND_RESOLVE; + entry_conn->socks_request->command = SOCKS_COMMAND_RESOLVE; conn->is_dns_request = 1; - strlcpy(conn->socks_request->address, name, - sizeof(conn->socks_request->address)); + strlcpy(entry_conn->socks_request->address, name, + sizeof(entry_conn->socks_request->address)); + + entry_conn->socks_request->listener_type = CONN_TYPE_CONTROL_LISTENER; + entry_conn->original_dest_address = tor_strdup(name); + entry_conn->session_group = SESSION_GROUP_CONTROL_RESOLVE; + entry_conn->nym_epoch = get_signewnym_epoch(); + entry_conn->isolation_flags = ISO_DEFAULT; if (connection_add(TO_CONN(conn))<0) { log_warn(LD_APP, "Couldn't register dummy connection for RESOLVE request"); @@ -194,7 +209,7 @@ dnsserv_launch_request(const char *name, int reverse) log_info(LD_APP, "Passing request for %s to rewrite_and_attach.", escaped_safe_str_client(name)); q_name = tor_strdup(name); /* q could be freed in rewrite_and_attach */ - connection_ap_rewrite_and_attach_if_allowed(conn, NULL, NULL); + connection_ap_rewrite_and_attach_if_allowed(entry_conn, NULL, NULL); /* Now, the connection is marked if it was bad. */ log_info(LD_APP, "Passed request for %s to rewrite_and_attach_if_allowed.", @@ -206,7 +221,7 @@ dnsserv_launch_request(const char *name, int reverse) /** If there is a pending request on <b>conn</b> that's waiting for an answer, * send back an error and free the request. */ void -dnsserv_reject_request(edge_connection_t *conn) +dnsserv_reject_request(entry_connection_t *conn) { if (conn->dns_server_request) { evdns_server_request_respond(conn->dns_server_request, @@ -252,7 +267,7 @@ evdns_get_orig_address(const struct evdns_server_request *req, * <b>answer_len</b>, in <b>answer</b>, with TTL <b>ttl</b>. Doesn't do * any caching; that's handled elsewhere. */ void -dnsserv_resolved(edge_connection_t *conn, +dnsserv_resolved(entry_connection_t *conn, int answer_type, size_t answer_len, const char *answer, @@ -305,12 +320,15 @@ dnsserv_resolved(edge_connection_t *conn, void dnsserv_configure_listener(connection_t *conn) { + listener_connection_t *listener_conn; tor_assert(conn); tor_assert(SOCKET_OK(conn->s)); tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER); - conn->dns_server_port = - tor_evdns_add_server_port(conn->s, 0, evdns_server_callback, NULL); + listener_conn = TO_LISTENER_CONN(conn); + listener_conn->dns_server_port = + tor_evdns_add_server_port(conn->s, 0, evdns_server_callback, + listener_conn); } /** Free the evdns server port for <b>conn</b>, which must be an @@ -318,12 +336,15 @@ dnsserv_configure_listener(connection_t *conn) void dnsserv_close_listener(connection_t *conn) { + listener_connection_t *listener_conn; tor_assert(conn); tor_assert(conn->type == CONN_TYPE_AP_DNS_LISTENER); - if (conn->dns_server_port) { - evdns_close_server_port(conn->dns_server_port); - conn->dns_server_port = NULL; + listener_conn = TO_LISTENER_CONN(conn); + + if (listener_conn->dns_server_port) { + evdns_close_server_port(listener_conn->dns_server_port); + listener_conn->dns_server_port = NULL; } } diff --git a/src/or/dnsserv.h b/src/or/dnsserv.h index fcca868885..73ec365647 100644 --- a/src/or/dnsserv.h +++ b/src/or/dnsserv.h @@ -14,12 +14,12 @@ void dnsserv_configure_listener(connection_t *conn); void dnsserv_close_listener(connection_t *conn); -void dnsserv_resolved(edge_connection_t *conn, +void dnsserv_resolved(entry_connection_t *conn, int answer_type, size_t answer_len, const char *answer, int ttl); -void dnsserv_reject_request(edge_connection_t *conn); +void dnsserv_reject_request(entry_connection_t *conn); int dnsserv_launch_request(const char *name, int is_reverse); #endif diff --git a/src/or/eventdns.c b/src/or/eventdns.c index 42e16aec7a..7cd5d80afb 100644 --- a/src/or/eventdns.c +++ b/src/or/eventdns.c @@ -1,12 +1,18 @@ -/* The original version of this module was written by Adam Langley; for - * a history of modifications, check out the subversion logs. +/* READ THIS COMMENT BEFORE HACKING THIS FILE. * - * When editing this module, try to keep it re-mergeable by Adam. Don't - * reformat the whitespace, add Tor dependencies, or so on. + * This eventdns.c copy has diverged a bit from Libevent's version, and it's + * no longer easy to resynchronize them. Once Tor requires Libevent 2.0, we + * will just dump this file and use Libevent's evdns code. * - * TODO: - * - Replace all externally visible magic numbers with #defined constants. - * - Write documentation for APIs of all external functions. + * Therefore, you probably shouldn't make any change here without making it to + * Libevent as well: it's not good for the implementation to diverge even + * more. Also, we can't shouldn't wantonly the API here (since Libevent APIs + * can't change in ways that break user behavior). Also, we shouldn't bother + * with cosmetic changes: the whole module is slated for demolition, so + * there's no point dusting the linebreaks or re-painting the parser. + * + * (We can't just drop the Libevent 2.0 evdns implementation in here instead, + * since it depends pretty heavily on parts of Libevent 2.0.) */ /* Async DNS Library @@ -75,7 +81,6 @@ #include <stdint.h> #endif #include <stdlib.h> -#include <string.h> #include <errno.h> #include <assert.h> #ifdef HAVE_UNISTD_H @@ -1831,8 +1836,8 @@ evdns_server_request_respond(struct evdns_server_request *_req, int err) r = sendto(port->socket, req->response, req->response_len, 0, (struct sockaddr*) &req->addr, req->addrlen); if (r<0) { - int err = last_error(port->socket); - if (! error_is_eagain(err)) + int error = last_error(port->socket); + if (! error_is_eagain(error)) return -1; if (port->pending_replies) { @@ -2291,7 +2296,7 @@ _evdns_nameserver_add_impl(const struct sockaddr *address, evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns); - ns->socket = socket(address->sa_family, SOCK_DGRAM, 0); + ns->socket = tor_open_socket(address->sa_family, SOCK_DGRAM, 0); if (ns->socket < 0) { err = 1; goto out1; } #ifdef WIN32 { @@ -3040,7 +3045,7 @@ evdns_resolv_conf_parse(int flags, const char *const filename) { log(EVDNS_LOG_DEBUG, "Parsing resolv.conf file %s", filename); - fd = open(filename, O_RDONLY); + fd = tor_open_cloexec(filename, O_RDONLY, 0); if (fd < 0) { evdns_resolv_set_defaults(flags); return 1; @@ -3460,7 +3465,7 @@ main(int c, char **v) { if (servertest) { int sock; struct sockaddr_in my_addr; - sock = socket(PF_INET, SOCK_DGRAM, 0); + sock = tor_open_socket(PF_INET, SOCK_DGRAM, 0); fcntl(sock, F_SETFL, O_NONBLOCK); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(10053); diff --git a/src/or/geoip.c b/src/or/geoip.c index c51142c82e..73194ae9c6 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -44,6 +44,9 @@ static strmap_t *country_idxplus1_by_lc_code = NULL; /** A list of all known geoip_entry_t, sorted by ip_low. */ static smartlist_t *geoip_entries = NULL; +/** SHA1 digest of the GeoIP file to include in extra-info descriptors. */ +static char geoip_digest[DIGEST_LEN]; + /** Return the index of the <b>country</b>'s entry in the GeoIP DB * if it is a valid 2-letter country code, otherwise return -1. */ @@ -113,10 +116,10 @@ geoip_parse_entry(const char *line) ++line; if (*line == '#') return 0; - if (sscanf(line,"%u,%u,%2s", &low, &high, b) == 3) { + if (tor_sscanf(line,"%u,%u,%2s", &low, &high, b) == 3) { geoip_add_entry(low, high, b); return 0; - } else if (sscanf(line,"\"%u\",\"%u\",\"%2s\",", &low, &high, b) == 3) { + } else if (tor_sscanf(line,"\"%u\",\"%u\",\"%2s\",", &low, &high, b) == 3) { geoip_add_entry(low, high, b); return 0; } else { @@ -159,7 +162,7 @@ _geoip_compare_key_to_entry(const void *_key, const void **_member) /** Return 1 if we should collect geoip stats on bridge users, and * include them in our extrainfo descriptor. Else return 0. */ int -should_record_bridge_info(or_options_t *options) +should_record_bridge_info(const or_options_t *options) { return options->BridgeRelay && options->BridgeRecordUsageByCountry; } @@ -196,13 +199,14 @@ init_geoip_countries(void) * with '#' (comments). */ int -geoip_load_file(const char *filename, or_options_t *options) +geoip_load_file(const char *filename, const or_options_t *options) { FILE *f; const char *msg = ""; int severity = options_need_geoip_info(options, &msg) ? LOG_WARN : LOG_INFO; + crypto_digest_env_t *geoip_digest_env = NULL; clear_geoip_db(); - if (!(f = fopen(filename, "r"))) { + if (!(f = tor_fopen_cloexec(filename, "r"))) { log_fn(severity, LD_GENERAL, "Failed to open GEOIP file %s. %s", filename, msg); return -1; @@ -214,11 +218,13 @@ geoip_load_file(const char *filename, or_options_t *options) smartlist_free(geoip_entries); } geoip_entries = smartlist_create(); + geoip_digest_env = crypto_new_digest_env(); log_notice(LD_GENERAL, "Parsing GEOIP file %s.", filename); while (!feof(f)) { char buf[512]; if (fgets(buf, (int)sizeof(buf), f) == NULL) break; + crypto_digest_add_bytes(geoip_digest_env, buf, strlen(buf)); /* FFFF track full country name. */ geoip_parse_entry(buf); } @@ -231,6 +237,11 @@ geoip_load_file(const char *filename, or_options_t *options) * country. */ refresh_all_country_info(); + /* Remember file digest so that we can include it in our extra-info + * descriptors. */ + crypto_digest_get_digest(geoip_digest_env, geoip_digest, DIGEST_LEN); + crypto_free_digest_env(geoip_digest_env); + return 0; } @@ -278,6 +289,15 @@ geoip_is_loaded(void) return geoip_countries != NULL && geoip_entries != NULL; } +/** Return the hex-encoded SHA1 digest of the loaded GeoIP file. The + * result does not need to be deallocated, but will be overwritten by the + * next call of hex_str(). */ +const char * +geoip_db_digest(void) +{ + return hex_str(geoip_digest, DIGEST_LEN); +} + /** Entry in a map from IP address to the last time we've seen an incoming * connection from that IP address. Used by bridges only, to track which * countries have them blocked. */ @@ -404,7 +424,7 @@ void geoip_note_client_seen(geoip_client_action_t action, uint32_t addr, time_t now) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); clientmap_entry_t lookup, *ent; if (action == GEOIP_CLIENT_CONNECT) { /* Only remember statistics as entry guard or as bridge. */ @@ -910,10 +930,9 @@ geoip_dirreq_stats_init(time_t now) start_of_dirreq_stats_interval = now; } -/** Stop collecting directory request stats in a way that we can re-start - * doing so in geoip_dirreq_stats_init(). */ +/** Reset counters for dirreq stats. */ void -geoip_dirreq_stats_term(void) +geoip_reset_dirreq_stats(time_t now) { SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, { c->n_v2_ns_requests = c->n_v3_ns_requests = 0; @@ -945,59 +964,44 @@ geoip_dirreq_stats_term(void) tor_free(this); } } - start_of_dirreq_stats_interval = 0; + start_of_dirreq_stats_interval = now; } -/** Write dirreq statistics to $DATADIR/stats/dirreq-stats and return when - * we would next want to write. */ -time_t -geoip_dirreq_stats_write(time_t now) +/** Stop collecting directory request stats in a way that we can re-start + * doing so in geoip_dirreq_stats_init(). */ +void +geoip_dirreq_stats_term(void) { - char *statsdir = NULL, *filename = NULL; - char *data_v2 = NULL, *data_v3 = NULL; - char written[ISO_TIME_LEN+1]; - open_file_t *open_file = NULL; + geoip_reset_dirreq_stats(0); +} + +/** Return a newly allocated string containing the dirreq statistics + * until <b>now</b>, or NULL if we're not collecting dirreq stats. Caller + * must ensure start_of_dirreq_stats_interval is in the past. */ +char * +geoip_format_dirreq_stats(time_t now) +{ + char t[ISO_TIME_LEN+1]; double v2_share = 0.0, v3_share = 0.0; - FILE *out; int i; + char *v3_ips_string, *v2_ips_string, *v3_reqs_string, *v2_reqs_string, + *v2_share_string = NULL, *v3_share_string = NULL, + *v3_direct_dl_string, *v2_direct_dl_string, + *v3_tunneled_dl_string, *v2_tunneled_dl_string; + char *result; if (!start_of_dirreq_stats_interval) - return 0; /* Not initialized. */ - if (start_of_dirreq_stats_interval + WRITE_STATS_INTERVAL > now) - goto done; /* Not ready to write. */ + return NULL; /* Not initialized. */ - /* Discard all items in the client history that are too old. */ - geoip_remove_old_clients(start_of_dirreq_stats_interval); + tor_assert(now >= start_of_dirreq_stats_interval); - statsdir = get_datadir_fname("stats"); - if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) - goto done; - filename = get_datadir_fname2("stats", "dirreq-stats"); - data_v2 = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS_V2); - data_v3 = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS); - format_iso_time(written, now); - out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND | O_TEXT, - 0600, &open_file); - if (!out) - goto done; - if (fprintf(out, "dirreq-stats-end %s (%d s)\ndirreq-v3-ips %s\n" - "dirreq-v2-ips %s\n", written, - (unsigned) (now - start_of_dirreq_stats_interval), - data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0) - goto done; - tor_free(data_v2); - tor_free(data_v3); + format_iso_time(t, now); + v2_ips_string = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS_V2); + v3_ips_string = geoip_get_client_history(GEOIP_CLIENT_NETWORKSTATUS); + v2_reqs_string = geoip_get_request_history( + GEOIP_CLIENT_NETWORKSTATUS_V2); + v3_reqs_string = geoip_get_request_history(GEOIP_CLIENT_NETWORKSTATUS); - data_v2 = geoip_get_request_history(GEOIP_CLIENT_NETWORKSTATUS_V2); - data_v3 = geoip_get_request_history(GEOIP_CLIENT_NETWORKSTATUS); - if (fprintf(out, "dirreq-v3-reqs %s\ndirreq-v2-reqs %s\n", - data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0) - goto done; - tor_free(data_v2); - tor_free(data_v3); - SMARTLIST_FOREACH(geoip_countries, geoip_country_t *, c, { - c->n_v2_ns_requests = c->n_v3_ns_requests = 0; - }); #define RESPONSE_GRANULARITY 8 for (i = 0; i < GEOIP_NS_RESPONSE_NUM; i++) { ns_v2_responses[i] = round_uint32_to_next_multiple_of( @@ -1006,61 +1010,117 @@ geoip_dirreq_stats_write(time_t now) ns_v3_responses[i], RESPONSE_GRANULARITY); } #undef RESPONSE_GRANULARITY - if (fprintf(out, "dirreq-v3-resp ok=%u,not-enough-sigs=%u,unavailable=%u," - "not-found=%u,not-modified=%u,busy=%u\n", - ns_v3_responses[GEOIP_SUCCESS], - ns_v3_responses[GEOIP_REJECT_NOT_ENOUGH_SIGS], - ns_v3_responses[GEOIP_REJECT_UNAVAILABLE], - ns_v3_responses[GEOIP_REJECT_NOT_FOUND], - ns_v3_responses[GEOIP_REJECT_NOT_MODIFIED], - ns_v3_responses[GEOIP_REJECT_BUSY]) < 0) - goto done; - if (fprintf(out, "dirreq-v2-resp ok=%u,unavailable=%u," - "not-found=%u,not-modified=%u,busy=%u\n", - ns_v2_responses[GEOIP_SUCCESS], - ns_v2_responses[GEOIP_REJECT_UNAVAILABLE], - ns_v2_responses[GEOIP_REJECT_NOT_FOUND], - ns_v2_responses[GEOIP_REJECT_NOT_MODIFIED], - ns_v2_responses[GEOIP_REJECT_BUSY]) < 0) - goto done; - memset(ns_v2_responses, 0, sizeof(ns_v2_responses)); - memset(ns_v3_responses, 0, sizeof(ns_v3_responses)); + if (!geoip_get_mean_shares(now, &v2_share, &v3_share)) { - if (fprintf(out, "dirreq-v2-share %0.2lf%%\n", v2_share*100) < 0) - goto done; - if (fprintf(out, "dirreq-v3-share %0.2lf%%\n", v3_share*100) < 0) - goto done; + tor_asprintf(&v2_share_string, "dirreq-v2-share %0.2lf%%\n", + v2_share*100); + tor_asprintf(&v3_share_string, "dirreq-v3-share %0.2lf%%\n", + v3_share*100); } - data_v2 = geoip_get_dirreq_history(GEOIP_CLIENT_NETWORKSTATUS_V2, - DIRREQ_DIRECT); - data_v3 = geoip_get_dirreq_history(GEOIP_CLIENT_NETWORKSTATUS, - DIRREQ_DIRECT); - if (fprintf(out, "dirreq-v3-direct-dl %s\ndirreq-v2-direct-dl %s\n", - data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0) - goto done; - tor_free(data_v2); - tor_free(data_v3); - data_v2 = geoip_get_dirreq_history(GEOIP_CLIENT_NETWORKSTATUS_V2, - DIRREQ_TUNNELED); - data_v3 = geoip_get_dirreq_history(GEOIP_CLIENT_NETWORKSTATUS, - DIRREQ_TUNNELED); - if (fprintf(out, "dirreq-v3-tunneled-dl %s\ndirreq-v2-tunneled-dl %s\n", - data_v3 ? data_v3 : "", data_v2 ? data_v2 : "") < 0) - goto done; + v2_direct_dl_string = geoip_get_dirreq_history( + GEOIP_CLIENT_NETWORKSTATUS_V2, DIRREQ_DIRECT); + v3_direct_dl_string = geoip_get_dirreq_history( + GEOIP_CLIENT_NETWORKSTATUS, DIRREQ_DIRECT); + + v2_tunneled_dl_string = geoip_get_dirreq_history( + GEOIP_CLIENT_NETWORKSTATUS_V2, DIRREQ_TUNNELED); + v3_tunneled_dl_string = geoip_get_dirreq_history( + GEOIP_CLIENT_NETWORKSTATUS, DIRREQ_TUNNELED); + + /* Put everything together into a single string. */ + tor_asprintf(&result, "dirreq-stats-end %s (%d s)\n" + "dirreq-v3-ips %s\n" + "dirreq-v2-ips %s\n" + "dirreq-v3-reqs %s\n" + "dirreq-v2-reqs %s\n" + "dirreq-v3-resp ok=%u,not-enough-sigs=%u,unavailable=%u," + "not-found=%u,not-modified=%u,busy=%u\n" + "dirreq-v2-resp ok=%u,unavailable=%u," + "not-found=%u,not-modified=%u,busy=%u\n" + "%s" + "%s" + "dirreq-v3-direct-dl %s\n" + "dirreq-v2-direct-dl %s\n" + "dirreq-v3-tunneled-dl %s\n" + "dirreq-v2-tunneled-dl %s\n", + t, + (unsigned) (now - start_of_dirreq_stats_interval), + v3_ips_string ? v3_ips_string : "", + v2_ips_string ? v2_ips_string : "", + v3_reqs_string ? v3_reqs_string : "", + v2_reqs_string ? v2_reqs_string : "", + ns_v3_responses[GEOIP_SUCCESS], + ns_v3_responses[GEOIP_REJECT_NOT_ENOUGH_SIGS], + ns_v3_responses[GEOIP_REJECT_UNAVAILABLE], + ns_v3_responses[GEOIP_REJECT_NOT_FOUND], + ns_v3_responses[GEOIP_REJECT_NOT_MODIFIED], + ns_v3_responses[GEOIP_REJECT_BUSY], + ns_v2_responses[GEOIP_SUCCESS], + ns_v2_responses[GEOIP_REJECT_UNAVAILABLE], + ns_v2_responses[GEOIP_REJECT_NOT_FOUND], + ns_v2_responses[GEOIP_REJECT_NOT_MODIFIED], + ns_v2_responses[GEOIP_REJECT_BUSY], + v2_share_string ? v2_share_string : "", + v3_share_string ? v3_share_string : "", + v3_direct_dl_string ? v3_direct_dl_string : "", + v2_direct_dl_string ? v2_direct_dl_string : "", + v3_tunneled_dl_string ? v3_tunneled_dl_string : "", + v2_tunneled_dl_string ? v2_tunneled_dl_string : ""); + + /* Free partial strings. */ + tor_free(v3_ips_string); + tor_free(v2_ips_string); + tor_free(v3_reqs_string); + tor_free(v2_reqs_string); + tor_free(v2_share_string); + tor_free(v3_share_string); + tor_free(v3_direct_dl_string); + tor_free(v2_direct_dl_string); + tor_free(v3_tunneled_dl_string); + tor_free(v2_tunneled_dl_string); - finish_writing_to_file(open_file); - open_file = NULL; + return result; +} - start_of_dirreq_stats_interval = now; +/** If 24 hours have passed since the beginning of the current dirreq + * stats period, write dirreq stats to $DATADIR/stats/dirreq-stats + * (possibly overwriting an existing file) and reset counters. Return + * when we would next want to write dirreq stats or 0 if we never want to + * write. */ +time_t +geoip_dirreq_stats_write(time_t now) +{ + char *statsdir = NULL, *filename = NULL, *str = NULL; + + if (!start_of_dirreq_stats_interval) + return 0; /* Not initialized. */ + if (start_of_dirreq_stats_interval + WRITE_STATS_INTERVAL > now) + goto done; /* Not ready to write. */ + + /* Discard all items in the client history that are too old. */ + geoip_remove_old_clients(start_of_dirreq_stats_interval); + + /* Generate history string .*/ + str = geoip_format_dirreq_stats(now); + + /* Write dirreq-stats string to disk. */ + statsdir = get_datadir_fname("stats"); + if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) { + log_warn(LD_HIST, "Unable to create stats/ directory!"); + goto done; + } + filename = get_datadir_fname2("stats", "dirreq-stats"); + if (write_str_to_file(filename, str, 0) < 0) + log_warn(LD_HIST, "Unable to write dirreq statistics to disk!"); + + /* Reset measurement interval start. */ + geoip_reset_dirreq_stats(now); done: - if (open_file) - abort_writing_to_file(open_file); - tor_free(filename); tor_free(statsdir); - tor_free(data_v2); - tor_free(data_v3); + tor_free(filename); + tor_free(str); return start_of_dirreq_stats_interval + WRITE_STATS_INTERVAL; } @@ -1140,8 +1200,8 @@ static char *bridge_stats_extrainfo = NULL; /** Return a newly allocated string holding our bridge usage stats by country * in a format suitable for inclusion in an extrainfo document. Return NULL on * failure. */ -static char * -format_bridge_stats_extrainfo(time_t now) +char * +geoip_format_bridge_stats(time_t now) { char *out = NULL, *data = NULL; long duration = now - start_of_bridge_stats_interval; @@ -1149,6 +1209,8 @@ format_bridge_stats_extrainfo(time_t now) if (duration < 0) return NULL; + if (!start_of_bridge_stats_interval) + return NULL; /* Not initialized. */ format_iso_time(written, now); data = geoip_get_client_history(GEOIP_CLIENT_CONNECT); @@ -1198,7 +1260,7 @@ geoip_bridge_stats_write(time_t now) geoip_remove_old_clients(start_of_bridge_stats_interval); /* Generate formatted string */ - val = format_bridge_stats_extrainfo(now); + val = geoip_format_bridge_stats(now); if (val == NULL) goto done; @@ -1275,25 +1337,54 @@ geoip_entry_stats_init(time_t now) start_of_entry_stats_interval = now; } +/** Reset counters for entry stats. */ +void +geoip_reset_entry_stats(time_t now) +{ + client_history_clear(); + start_of_entry_stats_interval = now; +} + /** Stop collecting entry stats in a way that we can re-start doing so in * geoip_entry_stats_init(). */ void geoip_entry_stats_term(void) { - client_history_clear(); - start_of_entry_stats_interval = 0; + geoip_reset_entry_stats(0); } -/** Write entry statistics to $DATADIR/stats/entry-stats and return time - * when we would next want to write. */ +/** Return a newly allocated string containing the entry statistics + * until <b>now</b>, or NULL if we're not collecting entry stats. Caller + * must ensure start_of_entry_stats_interval lies in the past. */ +char * +geoip_format_entry_stats(time_t now) +{ + char t[ISO_TIME_LEN+1]; + char *data = NULL; + char *result; + + if (!start_of_entry_stats_interval) + return NULL; /* Not initialized. */ + + tor_assert(now >= start_of_entry_stats_interval); + + data = geoip_get_client_history(GEOIP_CLIENT_CONNECT); + format_iso_time(t, now); + tor_asprintf(&result, "entry-stats-end %s (%u s)\nentry-ips %s\n", + t, (unsigned) (now - start_of_entry_stats_interval), + data ? data : ""); + tor_free(data); + return result; +} + +/** If 24 hours have passed since the beginning of the current entry stats + * period, write entry stats to $DATADIR/stats/entry-stats (possibly + * overwriting an existing file) and reset counters. Return when we would + * next want to write entry stats or 0 if we never want to write. */ time_t geoip_entry_stats_write(time_t now) { - char *statsdir = NULL, *filename = NULL; - char *data = NULL; - char written[ISO_TIME_LEN+1]; - open_file_t *open_file = NULL; - FILE *out; + char *statsdir = NULL, *filename = NULL, *str = NULL; if (!start_of_entry_stats_interval) return 0; /* Not initialized. */ @@ -1303,31 +1394,26 @@ geoip_entry_stats_write(time_t now) /* Discard all items in the client history that are too old. */ geoip_remove_old_clients(start_of_entry_stats_interval); + /* Generate history string .*/ + str = geoip_format_entry_stats(now); + + /* Write entry-stats string to disk. */ statsdir = get_datadir_fname("stats"); - if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) + if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) { + log_warn(LD_HIST, "Unable to create stats/ directory!"); goto done; + } filename = get_datadir_fname2("stats", "entry-stats"); - data = geoip_get_client_history(GEOIP_CLIENT_CONNECT); - format_iso_time(written, now); - out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND | O_TEXT, - 0600, &open_file); - if (!out) - goto done; - if (fprintf(out, "entry-stats-end %s (%u s)\nentry-ips %s\n", - written, (unsigned) (now - start_of_entry_stats_interval), - data ? data : "") < 0) - goto done; + if (write_str_to_file(filename, str, 0) < 0) + log_warn(LD_HIST, "Unable to write entry statistics to disk!"); - start_of_entry_stats_interval = now; + /* Reset measurement interval start. */ + geoip_reset_entry_stats(now); - finish_writing_to_file(open_file); - open_file = NULL; done: - if (open_file) - abort_writing_to_file(open_file); - tor_free(filename); tor_free(statsdir); - tor_free(data); + tor_free(filename); + tor_free(str); return start_of_entry_stats_interval + WRITE_STATS_INTERVAL; } diff --git a/src/or/geoip.h b/src/or/geoip.h index 24f7c5b931..ce3841967f 100644 --- a/src/or/geoip.h +++ b/src/or/geoip.h @@ -15,12 +15,13 @@ #ifdef GEOIP_PRIVATE int geoip_parse_entry(const char *line); #endif -int should_record_bridge_info(or_options_t *options); -int geoip_load_file(const char *filename, or_options_t *options); +int should_record_bridge_info(const or_options_t *options); +int geoip_load_file(const char *filename, const or_options_t *options); int geoip_get_country_by_ip(uint32_t ipaddr); int geoip_get_n_countries(void); const char *geoip_get_country_name(country_t num); int geoip_is_loaded(void); +const char *geoip_db_digest(void); country_t geoip_get_country(const char *countrycode); void geoip_note_client_seen(geoip_client_action_t action, @@ -42,12 +43,17 @@ void geoip_change_dirreq_state(uint64_t dirreq_id, dirreq_type_t type, dirreq_state_t new_state); void geoip_dirreq_stats_init(time_t now); +void geoip_reset_dirreq_stats(time_t now); +char *geoip_format_dirreq_stats(time_t now); time_t geoip_dirreq_stats_write(time_t now); void geoip_dirreq_stats_term(void); void geoip_entry_stats_init(time_t now); time_t geoip_entry_stats_write(time_t now); void geoip_entry_stats_term(void); +void geoip_reset_entry_stats(time_t now); +char *geoip_format_entry_stats(time_t now); void geoip_bridge_stats_init(time_t now); +char *geoip_format_bridge_stats(time_t now); time_t geoip_bridge_stats_write(time_t now); void geoip_bridge_stats_term(void); const char *geoip_get_bridge_stats_extrainfo(time_t); diff --git a/src/or/hibernate.c b/src/or/hibernate.c index aebce4cc88..ce64581d1c 100644 --- a/src/or/hibernate.c +++ b/src/or/hibernate.c @@ -21,6 +21,7 @@ hibernating, phase 2: - close all OR/AP/exit conns) */ +#define HIBERNATE_PRIVATE #include "or.h" #include "config.h" #include "connection.h" @@ -29,26 +30,11 @@ hibernating, phase 2: #include "main.h" #include "router.h" -/** Possible values of hibernate_state */ -typedef enum { - /** We are running normally. */ - HIBERNATE_STATE_LIVE=1, - /** We're trying to shut down cleanly, and we'll kill all active connections - * at shutdown_time. */ - HIBERNATE_STATE_EXITING=2, - /** We're running low on allocated bandwidth for this period, so we won't - * accept any new connections. */ - HIBERNATE_STATE_LOWBANDWIDTH=3, - /** We are hibernating, and we won't wake up till there's more bandwidth to - * use. */ - HIBERNATE_STATE_DORMANT=4 -} hibernate_state_t; - extern long stats_n_seconds_working; /* published uptime */ /** Are we currently awake, asleep, running out of bandwidth, or shutting * down? */ -static hibernate_state_t hibernate_state = HIBERNATE_STATE_LIVE; +static hibernate_state_t hibernate_state = HIBERNATE_STATE_INITIAL; /** If are hibernating, when do we plan to wake up? Set to 0 if we * aren't hibernating. */ static time_t hibernate_end_time = 0; @@ -134,7 +120,7 @@ static void accounting_set_wakeup_time(void); * options->AccountingStart. Return 0 on success, -1 on failure. If * <b>validate_only</b> is true, do not change the current settings. */ int -accounting_parse_options(or_options_t *options, int validate_only) +accounting_parse_options(const or_options_t *options, int validate_only) { time_unit_t unit; int ok, idx; @@ -249,7 +235,7 @@ accounting_parse_options(or_options_t *options, int validate_only) * hibernate, return 1, else return 0. */ int -accounting_is_enabled(or_options_t *options) +accounting_is_enabled(const or_options_t *options) { if (options->AccountingMax) return 1; @@ -411,7 +397,7 @@ static void update_expected_bandwidth(void) { uint64_t expected; - or_options_t *options= get_options(); + const or_options_t *options= get_options(); uint64_t max_configured = (options->RelayBandwidthRate > 0 ? options->RelayBandwidthRate : options->BandwidthRate) * 60; @@ -749,8 +735,7 @@ hibernate_soft_limit_reached(void) 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) { @@ -770,15 +755,7 @@ hibernate_begin(hibernate_state_t new_state, time_t now) } /* close listeners. leave control listener(s). */ - while ((conn = connection_get_by_type(CONN_TYPE_OR_LISTENER)) || - (conn = connection_get_by_type(CONN_TYPE_AP_LISTENER)) || - (conn = connection_get_by_type(CONN_TYPE_AP_TRANS_LISTENER)) || - (conn = connection_get_by_type(CONN_TYPE_AP_DNS_LISTENER)) || - (conn = connection_get_by_type(CONN_TYPE_AP_NATD_LISTENER)) || - (conn = connection_get_by_type(CONN_TYPE_DIR_LISTENER))) { - log_info(LD_NET,"Closing listener type %d", conn->type); - connection_mark_for_close(conn); - } + connection_mark_all_noncontrol_listeners(); /* XXX kill intro point circs */ /* XXX upload rendezvous service descriptors with no intro points */ @@ -804,10 +781,12 @@ static void hibernate_end(hibernate_state_t new_state) { tor_assert(hibernate_state == HIBERNATE_STATE_LOWBANDWIDTH || - hibernate_state == HIBERNATE_STATE_DORMANT); + hibernate_state == HIBERNATE_STATE_DORMANT || + hibernate_state == HIBERNATE_STATE_INITIAL); /* listeners will be relaunched in run_scheduled_events() in main.c */ - log_notice(LD_ACCT,"Hibernation period ended. Resuming normal activity."); + if (hibernate_state != HIBERNATE_STATE_INITIAL) + log_notice(LD_ACCT,"Hibernation period ended. Resuming normal activity."); hibernate_state = new_state; hibernate_end_time = 0; /* no longer hibernating */ @@ -856,7 +835,7 @@ hibernate_go_dormant(time_t now) connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_HIBERNATING); log_info(LD_NET,"Closing conn type %d", conn->type); if (conn->type == CONN_TYPE_AP) /* send socks failure if needed */ - connection_mark_unattached_ap(TO_EDGE_CONN(conn), + connection_mark_unattached_ap(TO_ENTRY_CONN(conn), END_STREAM_REASON_HIBERNATING); else connection_mark_for_close(conn); @@ -939,11 +918,12 @@ consider_hibernation(time_t now) /* Else, we aren't hibernating. See if it's time to start hibernating, or to * go dormant. */ - if (hibernate_state == HIBERNATE_STATE_LIVE) { + if (hibernate_state == HIBERNATE_STATE_LIVE || + hibernate_state == HIBERNATE_STATE_INITIAL) { if (hibernate_soft_limit_reached()) { log_notice(LD_ACCT, "Bandwidth soft limit reached; commencing hibernation. " - "No new conncetions will be accepted"); + "No new connections will be accepted"); hibernate_begin(HIBERNATE_STATE_LOWBANDWIDTH, now); } else if (accounting_enabled && now < interval_wakeup_time) { format_local_iso_time(buf,interval_wakeup_time); @@ -951,6 +931,8 @@ consider_hibernation(time_t now) "Commencing hibernation. We will wake up at %s local time.", buf); hibernate_go_dormant(now); + } else if (hibernate_state == HIBERNATE_STATE_INITIAL) { + hibernate_end(HIBERNATE_STATE_LIVE); } } @@ -1017,3 +999,13 @@ getinfo_helper_accounting(control_connection_t *conn, return 0; } +/** + * Manually change the hibernation state. Private; used only by the unit + * tests. + */ +void +hibernate_set_state_for_testing_(hibernate_state_t newstate) +{ + hibernate_state = newstate; +} + diff --git a/src/or/hibernate.h b/src/or/hibernate.h index 2aea0fab0c..78e7bb75e9 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); @@ -25,5 +25,27 @@ int getinfo_helper_accounting(control_connection_t *conn, const char *question, char **answer, const char **errmsg); +#ifdef HIBERNATE_PRIVATE +/** Possible values of hibernate_state */ +typedef enum { + /** We are running normally. */ + HIBERNATE_STATE_LIVE=1, + /** We're trying to shut down cleanly, and we'll kill all active connections + * at shutdown_time. */ + HIBERNATE_STATE_EXITING=2, + /** We're running low on allocated bandwidth for this period, so we won't + * accept any new connections. */ + HIBERNATE_STATE_LOWBANDWIDTH=3, + /** We are hibernating, and we won't wake up till there's more bandwidth to + * use. */ + HIBERNATE_STATE_DORMANT=4, + /** We start out in state default, which means we havent decided which state + * we're in. */ + HIBERNATE_STATE_INITIAL=5 +} hibernate_state_t; + +void hibernate_set_state_for_testing_(hibernate_state_t newstate); +#endif + #endif diff --git a/src/or/main.c b/src/or/main.c index 289d805503..da45f5a681 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -33,9 +33,11 @@ #include "main.h" #include "microdesc.h" #include "networkstatus.h" +#include "nodelist.h" #include "ntmain.h" #include "onion.h" #include "policies.h" +#include "transports.h" #include "relay.h" #include "rendclient.h" #include "rendcommon.h" @@ -44,6 +46,7 @@ #include "router.h" #include "routerlist.h" #include "routerparse.h" +#include "status.h" #ifdef USE_DMALLOC #include <dmalloc.h> #include <openssl/crypto.h> @@ -56,6 +59,10 @@ #include <event.h> #endif +#ifdef USE_BUFFEREVENTS +#include <event2/bufferevent.h> +#endif + void evdns_shutdown(int); /********* PROTOTYPES **********/ @@ -71,6 +78,7 @@ static int connection_should_read_from_linked_conn(connection_t *conn); /********* START VARIABLES **********/ +#ifndef USE_BUFFEREVENTS int global_read_bucket; /**< Max number of bytes I can read this second. */ int global_write_bucket; /**< Max number of bytes I can write this second. */ @@ -78,13 +86,17 @@ int global_write_bucket; /**< Max number of bytes I can write this second. */ int global_relayed_read_bucket; /** Max number of relayed (bandwidth class 1) bytes I can write this second. */ int global_relayed_write_bucket; - /** What was the read bucket before the last second_elapsed_callback() call? * (used to determine how many bytes we've read). */ static int stats_prev_global_read_bucket; /** What was the write bucket before the last second_elapsed_callback() call? * (used to determine how many bytes we've written). */ static int stats_prev_global_write_bucket; +#endif + +static uint64_t stats_prev_n_read = 0; +static uint64_t stats_prev_n_written = 0; + /* XXX we might want to keep stats about global_relayed_*_bucket too. Or not.*/ /** How many bytes have we read since we started the process? */ static uint64_t stats_n_bytes_read = 0; @@ -103,6 +115,8 @@ static time_t time_to_check_for_correct_dns = 0; static time_t time_of_last_signewnym = 0; /** Is there a signewnym request we're currently waiting to handle? */ static int signewnym_is_pending = 0; +/** How many times have we called newnym? */ +static unsigned newnym_epoch = 0; /** Smartlist of all open connections. */ static smartlist_t *connection_array = NULL; @@ -141,6 +155,12 @@ int can_complete_circuit=0; * they are obsolete? */ #define TLS_HANDSHAKE_TIMEOUT (60) +/** Decides our behavior when no logs are configured/before any + * logs have been configured. For 0, we log notice to stdout as normal. + * For 1, we log warnings only. For 2, we log nothing. + */ +int quiet_level = 0; + /********* END VARIABLES ************/ /**************************************************************************** @@ -150,12 +170,58 @@ 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 + +#ifdef MS_WINDOWS +/** Remove the kernel-space send and receive buffers for <b>s</b>. For use + * with IOCP only. */ +static int +set_buffer_lengths_to_zero(tor_socket_t s) +{ + int zero = 0; + int r = 0; + if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&zero, sizeof(zero))) { + log_warn(LD_NET, "Unable to clear SO_SNDBUF"); + r = -1; + } + if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&zero, sizeof(zero))) { + log_warn(LD_NET, "Unable to clear SO_RCVBUF"); + r = -1; + } + return r; +} +#endif + /** Add <b>conn</b> to the array of connections that we can poll on. The * connection's socket must be set; the connection starts out * non-reading and non-writing. */ int -connection_add(connection_t *conn) +connection_add_impl(connection_t *conn, int is_connecting) { tor_assert(conn); tor_assert(SOCKET_OK(conn->s) || @@ -167,11 +233,71 @@ connection_add(connection_t *conn) conn->conn_array_index = smartlist_len(connection_array); smartlist_add(connection_array, conn); - if (SOCKET_OK(conn->s) || conn->linked) { +#ifdef USE_BUFFEREVENTS + if (connection_type_uses_bufferevent(conn)) { + if (SOCKET_OK(conn->s) && !conn->linked) { + +#ifdef MS_WINDOWS + if (tor_libevent_using_iocp_bufferevents() && + get_options()->UserspaceIOCPBuffers) { + set_buffer_lengths_to_zero(conn->s); + } +#endif + + conn->bufev = bufferevent_socket_new( + tor_libevent_get_base(), + conn->s, + BEV_OPT_DEFER_CALLBACKS); + if (!conn->bufev) { + log_warn(LD_BUG, "Unable to create socket bufferevent"); + smartlist_del(connection_array, conn->conn_array_index); + conn->conn_array_index = -1; + return -1; + } + if (is_connecting) { + /* Put the bufferevent into a "connecting" state so that we'll get + * a "connected" event callback on successful write. */ + bufferevent_socket_connect(conn->bufev, NULL, 0); + } + connection_configure_bufferevent_callbacks(conn); + } else if (conn->linked && conn->linked_conn && + connection_type_uses_bufferevent(conn->linked_conn)) { + tor_assert(!(SOCKET_OK(conn->s))); + if (!conn->bufev) { + struct bufferevent *pair[2] = { NULL, NULL }; + if (bufferevent_pair_new(tor_libevent_get_base(), + BEV_OPT_DEFER_CALLBACKS, + pair) < 0) { + log_warn(LD_BUG, "Unable to create bufferevent pair"); + smartlist_del(connection_array, conn->conn_array_index); + conn->conn_array_index = -1; + return -1; + } + tor_assert(pair[0]); + conn->bufev = pair[0]; + conn->linked_conn->bufev = pair[1]; + } /* else the other side already was added, and got a bufferevent_pair */ + connection_configure_bufferevent_callbacks(conn); + } else { + tor_assert(!conn->linked); + } + + if (conn->bufev) + tor_assert(conn->inbuf == NULL); + + if (conn->linked_conn && conn->linked_conn->bufev) + tor_assert(conn->linked_conn->inbuf == NULL); + } +#else + (void) is_connecting; +#endif + + if (!HAS_BUFFEREVENT(conn) && (SOCKET_OK(conn->s) || conn->linked)) { conn->read_event = tor_event_new(tor_libevent_get_base(), conn->s, EV_READ|EV_PERSIST, conn_read_callback, conn); conn->write_event = tor_event_new(tor_libevent_get_base(), conn->s, EV_WRITE|EV_PERSIST, conn_write_callback, conn); + /* XXXX CHECK FOR NULL RETURN! */ } log_debug(LD_NET,"new conn type %s, socket %d, address %s, n_conns %d.", @@ -195,7 +321,13 @@ connection_unregister_events(connection_t *conn) log_warn(LD_BUG, "Error removing write event for %d", (int)conn->s); tor_free(conn->write_event); } - if (conn->dns_server_port) { +#ifdef USE_BUFFEREVENTS + if (conn->bufev) { + bufferevent_free(conn->bufev); + conn->bufev = NULL; + } +#endif + if (conn->type == CONN_TYPE_AP_DNS_LISTENER) { dnsserv_close_listener(conn); } } @@ -303,12 +435,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 +483,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 +495,12 @@ void connection_stop_reading(connection_t *conn) { tor_assert(conn); + + IF_HAS_BUFFEREVENT(conn, { + bufferevent_disable(conn->bufev, EV_READ); + return; + }); + tor_assert(conn->read_event); if (conn->linked) { @@ -354,6 +520,12 @@ void connection_start_reading(connection_t *conn) { tor_assert(conn); + + IF_HAS_BUFFEREVENT(conn, { + bufferevent_enable(conn->bufev, EV_READ); + return; + }); + tor_assert(conn->read_event); if (conn->linked) { @@ -375,6 +547,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 +560,12 @@ void connection_stop_writing(connection_t *conn) { tor_assert(conn); + + IF_HAS_BUFFEREVENT(conn, { + bufferevent_disable(conn->bufev, EV_WRITE); + return; + }); + tor_assert(conn->write_event); if (conn->linked) { @@ -404,6 +586,12 @@ void connection_start_writing(connection_t *conn) { tor_assert(conn); + + IF_HAS_BUFFEREVENT(conn, { + bufferevent_enable(conn->bufev, EV_WRITE); + return; + }); + tor_assert(conn->write_event); if (conn->linked) { @@ -590,9 +778,32 @@ conn_close_if_marked(int i) assert_connection_ok(conn, now); /* assert_all_pending_dns_resolves_ok(); */ - log_debug(LD_NET,"Cleaning up connection (fd %d).",(int)conn->s); - if ((SOCKET_OK(conn->s) || conn->linked_conn) - && connection_wants_to_flush(conn)) { +#ifdef USE_BUFFEREVENTS + if (conn->bufev) { + if (conn->hold_open_until_flushed && + evbuffer_get_length(bufferevent_get_output(conn->bufev))) { + /* don't close yet. */ + return 0; + } + if (conn->linked_conn && ! conn->linked_conn->marked_for_close) { + /* We need to do this explicitly so that the linked connection + * notices that there was an EOF. */ + bufferevent_flush(conn->bufev, EV_WRITE, BEV_FINISHED); + } + } +#endif + + log_debug(LD_NET,"Cleaning up connection (fd %d).",conn->s); + + /* If the connection we are about to close was trying to connect to + a proxy server and failed, the client won't be able to use that + proxy. We should warn the user about this. */ + if (conn->proxy_state == PROXY_INFANT) + log_failed_proxy_connection(conn); + + IF_HAS_BUFFEREVENT(conn, goto unlink); + if ((SOCKET_OK(conn->s) || conn->linked_conn) && + connection_wants_to_flush(conn)) { /* s == -1 means it's an incomplete edge connection, or that the socket * has already been closed as unflushable. */ ssize_t sz = connection_bucket_write_limit(conn, now); @@ -614,8 +825,8 @@ conn_close_if_marked(int i) } log_debug(LD_GENERAL, "Flushed last %d bytes from a linked conn; " "%d left; flushlen %d; wants-to-flush==%d", retval, - (int)buf_datalen(conn->outbuf), - (int)conn->outbuf_flushlen, + (int)connection_get_outbuf_len(conn), + (int)conn->outbuf_flushlen, connection_wants_to_flush(conn)); } else if (connection_speaks_cells(conn)) { if (conn->state == OR_CONN_STATE_OPEN) { @@ -652,13 +863,17 @@ conn_close_if_marked(int i) "something is wrong with your network connection, or " "something is wrong with theirs. " "(fd %d, type %s, state %d, marked at %s:%d).", - (int)buf_datalen(conn->outbuf), + (int)connection_get_outbuf_len(conn), escaped_safe_str_client(conn->address), (int)conn->s, conn_type_to_string(conn->type), conn->state, conn->marked_for_close_file, conn->marked_for_close); } } + +#ifdef USE_BUFFEREVENTS + unlink: +#endif connection_unlink(conn); /* unlink, remove, free */ return 1; } @@ -679,13 +894,13 @@ directory_all_unreachable(time_t now) while ((conn = connection_get_by_type_state(CONN_TYPE_AP, AP_CONN_STATE_CIRCUIT_WAIT))) { - edge_connection_t *edge_conn = TO_EDGE_CONN(conn); + entry_connection_t *entry_conn = TO_ENTRY_CONN(conn); log_notice(LD_NET, "Is your network connection down? " "Failing connection to '%s:%d'.", - safe_str_client(edge_conn->socks_request->address), - edge_conn->socks_request->port); - connection_mark_unattached_ap(edge_conn, + safe_str_client(entry_conn->socks_request->address), + entry_conn->socks_request->port); + connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_NET_UNREACHABLE); } control_event_general_status(LOG_ERR, "DIR_ALL_UNREACHABLE"); @@ -696,18 +911,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. */ @@ -718,7 +934,7 @@ directory_info_has_arrived(time_t now, int from_cache) update_extrainfo_downloads(now); } - if (server_mode(options) && !we_are_hibernating() && !from_cache && + if (server_mode(options) && !net_is_disabled() && !from_cache && (can_complete_circuit || !any_predicted_circuits(now))) consider_testing_reachability(1, 1); } @@ -740,12 +956,13 @@ run_connection_housekeeping(int i, time_t now) { cell_t cell; connection_t *conn = smartlist_get(connection_array, i); - or_options_t *options = get_options(); + const or_options_t *options = get_options(); or_connection_t *or_conn; int past_keepalive = now >= conn->timestamp_lastwritten + options->KeepalivePeriod; - if (conn->outbuf && !buf_datalen(conn->outbuf) && conn->type == CONN_TYPE_OR) + if (conn->outbuf && !connection_get_outbuf_len(conn) && + conn->type == CONN_TYPE_OR) TO_OR_CONN(conn)->timestamp_lastempty = now; if (conn->marked_for_close) { @@ -765,7 +982,7 @@ run_connection_housekeeping(int i, time_t now) /* This check is temporary; it's to let us know whether we should consider * parsing partial serverdesc responses. */ if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC && - buf_datalen(conn->inbuf)>=1024) { + connection_get_inbuf_len(conn) >= 1024) { log_info(LD_DIR,"Trying to extract information from wedged server desc " "download."); connection_dir_reached_eof(TO_DIR_CONN(conn)); @@ -782,7 +999,11 @@ run_connection_housekeeping(int i, time_t now) the connection or send a keepalive, depending. */ or_conn = TO_OR_CONN(conn); +#ifdef USE_BUFFEREVENTS + tor_assert(conn->bufev); +#else tor_assert(conn->outbuf); +#endif if (or_conn->is_bad_for_new_circs && !or_conn->n_circuits) { /* It's bad for new circuits, and has no unmarked circuits on it: @@ -794,8 +1015,7 @@ run_connection_housekeeping(int i, time_t now) connection_or_connect_failed(TO_OR_CONN(conn), END_OR_CONN_REASON_TIMEOUT, "Tor gave up on the connection"); - connection_mark_for_close(conn); - conn->hold_open_until_flushed = 1; + connection_mark_and_flush(conn); } else if (!connection_state_is_open(conn)) { if (past_keepalive) { /* We never managed to actually get this connection open and happy. */ @@ -804,13 +1024,12 @@ run_connection_housekeeping(int i, time_t now) connection_mark_for_close(conn); } } else if (we_are_hibernating() && !or_conn->n_circuits && - !buf_datalen(conn->outbuf)) { + !connection_get_outbuf_len(conn)) { /* We're hibernating, there's no circuits, and nothing to flush.*/ log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) " "[Hibernating or exiting].", (int)conn->s,conn->address, conn->port); - connection_mark_for_close(conn); - conn->hold_open_until_flushed = 1; + connection_mark_and_flush(conn); } else if (!or_conn->n_circuits && now >= or_conn->timestamp_last_added_nonpadding + IDLE_OR_CONN_TIMEOUT) { @@ -818,7 +1037,6 @@ run_connection_housekeeping(int i, time_t now) "[idle %d].", (int)conn->s,conn->address, conn->port, (int)(now - or_conn->timestamp_last_added_nonpadding)); connection_mark_for_close(conn); - conn->hold_open_until_flushed = 1; } else if ( now >= or_conn->timestamp_lastempty + options->KeepalivePeriod*10 && now >= conn->timestamp_lastwritten + options->KeepalivePeriod*10) { @@ -826,10 +1044,10 @@ run_connection_housekeeping(int i, time_t now) "Expiring stuck OR connection to fd %d (%s:%d). (%d bytes to " "flush; %d seconds since last write)", (int)conn->s, conn->address, conn->port, - (int)buf_datalen(conn->outbuf), + (int)connection_get_outbuf_len(conn), (int)(now-conn->timestamp_lastwritten)); connection_mark_for_close(conn); - } else if (past_keepalive && !buf_datalen(conn->outbuf)) { + } else if (past_keepalive && !connection_get_outbuf_len(conn)) { /* send a padding cell */ log_fn(LOG_DEBUG,LD_OR,"Sending keepalive to (%s:%d)", conn->address, conn->port); @@ -844,7 +1062,7 @@ run_connection_housekeeping(int i, time_t now) static void signewnym_impl(time_t now) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); if (!proxy_mode(options)) { log_info(LD_CONTROL, "Ignoring SIGNAL NEWNYM because client functionality " "is disabled."); @@ -856,6 +1074,17 @@ signewnym_impl(time_t now) rend_client_purge_state(); time_of_last_signewnym = now; signewnym_is_pending = 0; + + ++newnym_epoch; + + control_event_signal(SIGNEWNYM); +} + +/** Return the number of times that signewnym has been called. */ +unsigned +get_signewnym_epoch(void) +{ + return newnym_epoch; } /** Perform regular maintenance tasks. This function gets run once per @@ -881,10 +1110,14 @@ run_scheduled_events(time_t now) static time_t time_to_check_for_expired_networkstatus = 0; static time_t time_to_write_stats_files = 0; static time_t time_to_write_bridge_stats = 0; + static time_t time_to_check_port_forwarding = 0; static time_t time_to_launch_reachability_tests = 0; static int should_init_bridge_stats = 1; static time_t time_to_retry_dns_init = 0; - or_options_t *options = get_options(); + static time_t time_to_next_heartbeat = 0; + static int has_validated_pt = 0; + const or_options_t *options = get_options(); + int is_server = server_mode(options); int i; int have_dir_info; @@ -895,6 +1128,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 && @@ -918,12 +1161,12 @@ run_scheduled_events(time_t now) if (router_rebuild_descriptor(1)<0) { log_info(LD_CONFIG, "Couldn't rebuild router descriptor"); } - if (advertised_server_mode()) + if (advertised_server_mode() & !options->DisableNetwork) router_upload_dir_desc_to_dirservers(0); } - if (time_to_try_getting_descriptors < now) { - update_router_descriptor_downloads(now); + if (!options->DisableNetwork && time_to_try_getting_descriptors < 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; @@ -946,10 +1189,7 @@ run_scheduled_events(time_t now) last_rotated_x509_certificate = now; if (last_rotated_x509_certificate+MAX_SSL_KEY_LIFETIME_INTERNAL < now) { log_info(LD_GENERAL,"Rotating tls context."); - if (tor_tls_context_init(public_server_mode(options), - get_tlsclient_identity_key(), - is_server ? get_server_identity_key() : NULL, - MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { + if (router_initialize_tls_context() < 0) { log_warn(LD_BUG, "Error reinitializing TLS context"); /* XXX is it a bug here, that we just keep going? -RD */ } @@ -976,7 +1216,7 @@ run_scheduled_events(time_t now) if (time_to_launch_reachability_tests < now && (authdir_mode_tests_reachability(options)) && - !we_are_hibernating()) { + !net_is_disabled()) { time_to_launch_reachability_tests = now + REACHABILITY_TEST_INTERVAL; /* try to determine reachability of the other Tor relays */ dirserv_test_reachability(now); @@ -1048,6 +1288,16 @@ 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; + } + if (options->BridgeAuthoritativeDir) { + time_t next_write = rep_hist_desc_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; } @@ -1076,10 +1326,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; } @@ -1088,7 +1337,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(); } @@ -1103,7 +1352,7 @@ run_scheduled_events(time_t now) /* 2b. Once per minute, regenerate and upload the descriptor if the old * one is inaccurate. */ - if (time_to_check_descriptor < now) { + if (time_to_check_descriptor < now && !options->DisableNetwork) { static int dirport_reachability_count = 0; time_to_check_descriptor = now + CHECK_DESCRIPTOR_INTERVAL; check_descriptor_bandwidth_changed(now); @@ -1111,15 +1360,11 @@ run_scheduled_events(time_t now) time_to_check_ipaddress = now + CHECK_IPADDRESS_INTERVAL; check_descriptor_ipaddress_changed(now); } -/** If our router descriptor ever goes this long without being regenerated - * because something changed, we force an immediate regenerate-and-upload. */ -#define FORCE_REGENERATE_DESCRIPTOR_INTERVAL (18*60*60) - mark_my_descriptor_dirty_if_older_than( - now - FORCE_REGENERATE_DESCRIPTOR_INTERVAL); + mark_my_descriptor_dirty_if_too_old(now); consider_publishable_server(0); /* also, check religiously for reachability, if it's within the first * 20 minutes of our uptime. */ - if (server_mode(options) && + if (is_server && (can_complete_circuit || !any_predicted_circuits(now)) && !we_are_hibernating()) { if (stats_n_seconds_working < TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) { @@ -1130,7 +1375,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) { @@ -1182,7 +1427,7 @@ run_scheduled_events(time_t now) connection_expire_held_open(); /** 3d. And every 60 seconds, we relaunch listeners if any died. */ - if (!we_are_hibernating() && time_to_check_listeners < now) { + if (!net_is_disabled() && time_to_check_listeners < now) { retry_all_listeners(NULL, NULL); time_to_check_listeners = now+60; } @@ -1193,7 +1438,7 @@ run_scheduled_events(time_t now) * and we make a new circ if there are no clean circuits. */ have_dir_info = router_have_minimum_dir_info(); - if (have_dir_info && !we_are_hibernating()) + if (have_dir_info && !net_is_disabled()) circuit_build_needed_circs(now); /* every 10 seconds, but not at the same second as other such events */ @@ -1224,7 +1469,7 @@ run_scheduled_events(time_t now) circuit_close_all_marked(); /** 7. And upload service descriptors if necessary. */ - if (can_complete_circuit && !we_are_hibernating()) { + if (can_complete_circuit && !net_is_disabled()) { rend_consider_services_upload(now); rend_consider_descriptor_republication(); } @@ -1241,7 +1486,8 @@ run_scheduled_events(time_t now) /** 9. and if we're a server, check whether our DNS is telling stories to * us. */ - if (is_server && time_to_check_for_correct_dns < now) { + if (!net_is_disabled() && + public_server_mode(options) && time_to_check_for_correct_dns < now) { if (!time_to_check_for_correct_dns) { time_to_check_for_correct_dns = now + 60 + crypto_rand_int(120); } else { @@ -1251,13 +1497,45 @@ run_scheduled_events(time_t now) } } - /** 10b. write bridge networkstatus file to disk */ + /** 10. write bridge networkstatus file to disk */ if (options->BridgeAuthoritativeDir && time_to_write_bridge_status_file < now) { networkstatus_dump_bridge_status_to_file(now); #define BRIDGE_STATUSFILE_INTERVAL (30*60) time_to_write_bridge_status_file = now+BRIDGE_STATUSFILE_INTERVAL; } + + /** 11. check the port forwarding app */ + if (!net_is_disabled() && + time_to_check_port_forwarding < now && + options->PortForwarding && + is_server) { +#define PORT_FORWARDING_CHECK_INTERVAL 5 + tor_check_port_forwarding(options->PortForwardingHelper, + options->DirPort, + options->ORPort, + now); + time_to_check_port_forwarding = now+PORT_FORWARDING_CHECK_INTERVAL; + } + + /** 11b. check pending unconfigured managed proxies */ + if (!net_is_disabled() && pt_proxies_configuration_pending()) + pt_configure_remaining_proxies(); + + /** 11c. validate pluggable transports configuration if we need to */ + if (!has_validated_pt && + (options->Bridges || options->ClientTransportPlugin)) { + if (validate_pluggable_transports_config() == 0) { + has_validated_pt = 1; + } + } + + /** 12. write the heartbeat message */ + if (options->HeartbeatPeriod && + time_to_next_heartbeat < now) { + log_heartbeat(now); + time_to_next_heartbeat = now+options->HeartbeatPeriod; + } } /** Timer: used to invoke second_elapsed_callback() once per second. */ @@ -1277,7 +1555,7 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg) size_t bytes_written; size_t bytes_read; int seconds_elapsed; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); (void)timer; (void)arg; @@ -1288,30 +1566,39 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg) update_approx_time(now); /* the second has rolled over. check more stuff. */ - bytes_written = stats_prev_global_write_bucket - global_write_bucket; - bytes_read = stats_prev_global_read_bucket - global_read_bucket; seconds_elapsed = current_second ? (int)(now - current_second) : 0; - stats_n_bytes_read += bytes_read; - stats_n_bytes_written += bytes_written; - if (accounting_is_enabled(options) && seconds_elapsed >= 0) - accounting_add_bytes(bytes_read, bytes_written, seconds_elapsed); +#ifdef USE_BUFFEREVENTS + { + uint64_t cur_read,cur_written; + connection_get_rate_limit_totals(&cur_read, &cur_written); + bytes_written = (size_t)(cur_written - stats_prev_n_written); + bytes_read = (size_t)(cur_read - stats_prev_n_read); + stats_n_bytes_read += bytes_read; + stats_n_bytes_written += bytes_written; + if (accounting_is_enabled(options) && seconds_elapsed >= 0) + accounting_add_bytes(bytes_read, bytes_written, seconds_elapsed); + stats_prev_n_written = cur_written; + stats_prev_n_read = cur_read; + } +#else + bytes_read = (size_t)(stats_n_bytes_read - stats_prev_n_read); + bytes_written = (size_t)(stats_n_bytes_written - stats_prev_n_written); + stats_prev_n_read = stats_n_bytes_read; + stats_prev_n_written = stats_n_bytes_written; +#endif + control_event_bandwidth_used((uint32_t)bytes_read,(uint32_t)bytes_written); control_event_stream_bandwidth_used(); - if (seconds_elapsed > 0) - connection_bucket_refill(seconds_elapsed, now); - stats_prev_global_read_bucket = global_read_bucket; - stats_prev_global_write_bucket = global_write_bucket; - if (server_mode(options) && - !we_are_hibernating() && + !net_is_disabled() && seconds_elapsed > 0 && can_complete_circuit && stats_n_seconds_working / TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT != (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, " @@ -1350,6 +1637,57 @@ second_elapsed_callback(periodic_timer_t *timer, void *arg) current_second = now; /* remember which second it is, for next time */ } +#ifndef USE_BUFFEREVENTS +/** Timer: used to invoke refill_callback(). */ +static periodic_timer_t *refill_timer = NULL; + +/** Libevent callback: invoked periodically to refill token buckets + * and count r/w bytes. It is only used when bufferevents are disabled. */ +static void +refill_callback(periodic_timer_t *timer, void *arg) +{ + static struct timeval current_millisecond; + struct timeval now; + + size_t bytes_written; + size_t bytes_read; + int milliseconds_elapsed = 0; + int seconds_rolled_over = 0; + + const or_options_t *options = get_options(); + + (void)timer; + (void)arg; + + tor_gettimeofday(&now); + + /* If this is our first time, no time has passed. */ + if (current_millisecond.tv_sec) { + long mdiff = tv_mdiff(¤t_millisecond, &now); + if (mdiff > INT_MAX) + mdiff = INT_MAX; + milliseconds_elapsed = (int)mdiff; + seconds_rolled_over = (int)(now.tv_sec - current_millisecond.tv_sec); + } + + bytes_written = stats_prev_global_write_bucket - global_write_bucket; + bytes_read = stats_prev_global_read_bucket - global_read_bucket; + + stats_n_bytes_read += bytes_read; + stats_n_bytes_written += bytes_written; + if (accounting_is_enabled(options) && milliseconds_elapsed >= 0) + accounting_add_bytes(bytes_read, bytes_written, seconds_rolled_over); + + if (milliseconds_elapsed > 0) + connection_bucket_refill(milliseconds_elapsed, now.tv_sec); + + stats_prev_global_read_bucket = global_read_bucket; + stats_prev_global_write_bucket = global_write_bucket; + + current_millisecond = now; /* remember what time it is, for next time */ +} +#endif + #ifndef MS_WINDOWS /** Called when a possibly ignorable libevent error occurs; ensures that we * don't get into an infinite loop by ignoring too many errors from @@ -1378,7 +1716,8 @@ ip_address_changed(int at_interface) if (at_interface) { if (! server) { /* Okay, change our keys. */ - init_keys(); + if (init_keys()<0) + log_warn(LD_GENERAL, "Unable to rotate keys after IP change!"); } } else { if (server) { @@ -1409,7 +1748,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(); @@ -1453,7 +1792,8 @@ do_hup(void) /* retry appropriate downloads */ router_reset_status_download_failures(); router_reset_descriptor_download_failures(); - update_networkstatus_downloads(time(NULL)); + if (!options->DisableNetwork) + update_networkstatus_downloads(time(NULL)); /* We'll retry routerstatus downloads in about 10 seconds; no need to * force a retry there. */ @@ -1501,8 +1841,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); @@ -1545,6 +1887,22 @@ do_main_loop(void) tor_assert(second_timer); } +#ifndef USE_BUFFEREVENTS + if (!refill_timer) { + struct timeval refill_interval; + int msecs = get_options()->TokenBucketRefillInterval; + + refill_interval.tv_sec = msecs/1000; + refill_interval.tv_usec = (msecs%1000)*1000; + + refill_timer = periodic_timer_new(tor_libevent_get_base(), + &refill_interval, + refill_callback, + NULL); + tor_assert(refill_timer); + } +#endif + for (;;) { if (nt_service_is_stopping()) return 0; @@ -1633,11 +1991,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) { @@ -1645,6 +2005,7 @@ process_signal(uintptr_t sig) tor_cleanup(); exit(1); } + control_event_signal(sig); break; #ifdef SIGCHLD case SIGCHLD: @@ -1666,10 +2027,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; @@ -1716,13 +2085,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) { @@ -1894,10 +2263,26 @@ tor_init(int argc, char *argv[]) default: add_temp_log(LOG_NOTICE); } + quiet_level = quiet; + + { + const char *version = get_version(); + log_notice(LD_GENERAL, "Tor v%s%s running on %s.", version, +#ifdef USE_BUFFEREVENTS + " (with bufferevents)", +#else + "", +#endif + get_uname()); - log(LOG_NOTICE, LD_GENERAL, "Tor v%s. This is experimental software. " - "Do not rely on it for strong anonymity. (Running on %s)",get_version(), - get_uname()); + log_notice(LD_GENERAL, "WARNING: Tor can't help you if you use it wrong. " + "Learn how to be safe at " + "https://www.torproject.org/download/download#warning"); + + if (strstr(version, "alpha") || strstr(version, "beta")) + log_notice(LD_GENERAL, "This version is not a stable Tor release. " + "Expect more bugs than usual."); + } if (network_init()<0) { log_err(LD_BUG,"Error initializing network; exiting."); @@ -1937,7 +2322,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; @@ -2016,9 +2401,11 @@ tor_free_all(int postfork) clear_pending_onions(); circuit_free_all(); entry_guards_free_all(); + pt_free_all(); connection_free_all(); buf_shrink_freelists(1); memarea_clear_freelist(); + nodelist_free_all(); microdesc_free_all(); if (!postfork) { config_free_all(); @@ -2050,7 +2437,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 0551f7aaf9..c8903642de 100644 --- a/src/or/main.h +++ b/src/or/main.h @@ -14,7 +14,9 @@ extern int can_complete_circuit; -int connection_add(connection_t *conn); +int connection_add_impl(connection_t *conn, int is_connecting); +#define connection_add(conn) connection_add_impl((conn), 0) +#define connection_add_connecting(conn) connection_add_impl((conn), 1) int connection_remove(connection_t *conn); void connection_unregister_events(connection_t *conn); int connection_in_array(connection_t *conn); @@ -22,10 +24,13 @@ void add_connection_to_closeable_list(connection_t *conn); int connection_is_on_closeable_list(connection_t *conn); smartlist_t *get_connection_array(void); +uint64_t get_bytes_read(void); +uint64_t get_bytes_written(void); /** Bitmask for events that we can turn on and off with * connection_watch_events. */ typedef enum watchable_events { + /* Yes, it is intentional that these match Libevent's EV_READ and EV_WRITE */ READ_EVENT=0x02, /**< We want to know when a connection is readable */ WRITE_EVENT=0x04 /**< We want to know when a connection is writable */ } watchable_events_t; @@ -46,10 +51,13 @@ void directory_info_has_arrived(time_t now, int from_cache); void ip_address_changed(int at_interface); void dns_servers_relaunch_checks(void); +long get_uptime(void); +unsigned get_signewnym_epoch(void); + void handle_signals(int is_parent); void process_signal(uintptr_t sig); -int try_locking(or_options_t *options, int err_if_locked); +int try_locking(const or_options_t *options, int err_if_locked); int have_lockfile(void); void release_lockfile(void); diff --git a/src/or/microdesc.c b/src/or/microdesc.c index 7c67d51448..92f5c03585 100644 --- a/src/or/microdesc.c +++ b/src/or/microdesc.c @@ -3,7 +3,14 @@ #include "or.h" #include "config.h" +#include "directory.h" +#include "dirserv.h" #include "microdesc.h" +#include "networkstatus.h" +#include "nodelist.h" +#include "policies.h" +#include "router.h" +#include "routerlist.h" #include "routerparse.h" /** A data structure to hold a bunch of cached microdescriptors. There are @@ -121,15 +128,19 @@ get_microdesc_cache(void) * ending at <b>eos</b>, and store them in <b>cache</b>. If <b>no-save</b>, * mark them as non-writable to disk. If <b>where</b> is SAVED_IN_CACHE, * leave their bodies as pointers to the mmap'd cache. If where is - * <b>SAVED_NOWHERE</b>, do not allow annotations. Return a list of the added - * microdescriptors. */ + * <b>SAVED_NOWHERE</b>, do not allow annotations. If listed_at is positive, + * set the last_listed field of every microdesc to listed_at. If + * requested_digests is non-null, then it contains a list of digests we mean + * to allow, so we should reject any non-requested microdesc with a different + * digest, and alter the list to contain only the digests of those microdescs + * we didn't find. + * Return a newly allocated list of the added microdescriptors, or NULL */ smartlist_t * microdescs_add_to_cache(microdesc_cache_t *cache, const char *s, const char *eos, saved_location_t where, - int no_save) + int no_save, time_t listed_at, + smartlist_t *requested_digests256) { - /*XXXX need an argument that sets last_listed as appropriate. */ - smartlist_t *descriptors, *added; const int allow_annotations = (where != SAVED_NOWHERE); const int copy_body = (where != SAVED_IN_CACHE); @@ -137,6 +148,33 @@ microdescs_add_to_cache(microdesc_cache_t *cache, descriptors = microdescs_parse_from_string(s, eos, allow_annotations, copy_body); + if (listed_at > 0) { + SMARTLIST_FOREACH(descriptors, microdesc_t *, md, + md->last_listed = listed_at); + } + if (requested_digests256) { + digestmap_t *requested; /* XXXX actuqlly we should just use a + digest256map */ + requested = digestmap_new(); + SMARTLIST_FOREACH(requested_digests256, const char *, cp, + digestmap_set(requested, cp, (void*)1)); + SMARTLIST_FOREACH_BEGIN(descriptors, microdesc_t *, md) { + if (digestmap_get(requested, md->digest)) { + digestmap_set(requested, md->digest, (void*)2); + } else { + log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Received non-requested microcdesc"); + microdesc_free(md); + SMARTLIST_DEL_CURRENT(descriptors, md); + } + } SMARTLIST_FOREACH_END(md); + SMARTLIST_FOREACH_BEGIN(requested_digests256, char *, cp) { + if (digestmap_get(requested, cp) == (void*)2) { + tor_free(cp); + SMARTLIST_DEL_CURRENT(requested_digests256, cp); + } + } SMARTLIST_FOREACH_END(cp); + digestmap_free(requested, NULL); + } added = microdescs_add_list_to_cache(cache, descriptors, where, no_save); smartlist_free(descriptors); @@ -144,7 +182,7 @@ microdescs_add_to_cache(microdesc_cache_t *cache, } /* As microdescs_add_to_cache, but takes a list of micrdescriptors instead of - * a string to encode. Frees any members of <b>descriptors</b> that it does + * a string to decode. Frees any members of <b>descriptors</b> that it does * not add. */ smartlist_t * microdescs_add_list_to_cache(microdesc_cache_t *cache, @@ -200,6 +238,7 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache, md->no_save = no_save; HT_INSERT(microdesc_map, &cache->map, md); + md->held_in_map = 1; smartlist_add(added, md); ++cache->n_seen; cache->total_len_seen += md->bodylen; @@ -208,6 +247,15 @@ microdescs_add_list_to_cache(microdesc_cache_t *cache, if (f) finish_writing_to_file(open_file); /*XXX Check me.*/ + { + networkstatus_t *ns = networkstatus_get_latest_consensus(); + if (ns && ns->flavor == FLAV_MICRODESC) + SMARTLIST_FOREACH(added, microdesc_t *, md, nodelist_add_microdesc(md)); + } + + if (smartlist_len(added)) + router_dir_info_changed(); + return added; } @@ -219,6 +267,7 @@ microdesc_cache_clear(microdesc_cache_t *cache) for (entry = HT_START(microdesc_map, &cache->map); entry; entry = next) { microdesc_t *md = *entry; next = HT_NEXT_RMV(microdesc_map, &cache->map, entry); + md->held_in_map = 0; microdesc_free(md); } HT_CLEAR(microdesc_map, &cache->map); @@ -247,7 +296,7 @@ microdesc_cache_reload(microdesc_cache_t *cache) mm = cache->cache_content = tor_mmap_file(cache->cache_fname); if (mm) { added = microdescs_add_to_cache(cache, mm->data, mm->data+mm->size, - SAVED_IN_CACHE, 0); + SAVED_IN_CACHE, 0, -1, NULL); if (added) { total += smartlist_len(added); smartlist_free(added); @@ -260,7 +309,7 @@ microdesc_cache_reload(microdesc_cache_t *cache) cache->journal_len = (size_t) st.st_size; added = microdescs_add_to_cache(cache, journal_content, journal_content+st.st_size, - SAVED_IN_JOURNAL, 0); + SAVED_IN_JOURNAL, 0, -1, NULL); if (added) { total += smartlist_len(added); smartlist_free(added); @@ -293,9 +342,11 @@ microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force) size_t bytes_dropped = 0; time_t now = time(NULL); - (void) force; - /* In 0.2.2, we let this proceed unconditionally: only authorities have - * microdesc caches. */ + /* If we don't know a live consensus, don't believe last_listed values: we + * might be starting up after being down for a while. */ + if (! force && + ! networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC)) + return; if (cutoff <= 0) cutoff = now - TOLERATE_MICRODESC_AGE; @@ -305,6 +356,7 @@ microdesc_cache_clean(microdesc_cache_t *cache, time_t cutoff, int force) ++dropped; victim = *mdp; mdp = HT_NEXT_RMV(microdesc_map, &cache->map, mdp); + victim->held_in_map = 0; bytes_dropped += victim->bodylen; microdesc_free(victim); } else { @@ -390,6 +442,7 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force) /* log? return -1? die? coredump the universe? */ continue; } + tor_assert(((size_t)size) == annotation_len + md->bodylen); md->off = off + annotation_len; off += size; if (md->saved_location != SAVED_IN_CACHE) { @@ -415,7 +468,21 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force) SMARTLIST_FOREACH_BEGIN(wrote, microdesc_t *, md) { tor_assert(md->saved_location == SAVED_IN_CACHE); md->body = (char*)cache->cache_content->data + md->off; - tor_assert(fast_memeq(md->body, "onion-key", 9)); + if (PREDICT_UNLIKELY( + md->bodylen < 9 || fast_memneq(md->body, "onion-key", 9) != 0)) { + /* XXXX023 once bug 2022 is solved, we can kill this block and turn it + * into just the tor_assert(!memcmp) */ + off_t avail = cache->cache_content->size - md->off; + char *bad_str; + tor_assert(avail >= 0); + bad_str = tor_strndup(md->body, MIN(128, (size_t)avail)); + log_err(LD_BUG, "After rebuilding microdesc cache, offsets seem wrong. " + " At offset %d, I expected to find a microdescriptor starting " + " with \"onion-key\". Instead I got %s.", + (int)md->off, escaped(bad_str)); + tor_free(bad_str); + tor_assert(fast_memeq(md->body, "onion-key", 9)); + } } SMARTLIST_FOREACH_END(md); smartlist_free(wrote); @@ -432,6 +499,28 @@ microdesc_cache_rebuild(microdesc_cache_t *cache, int force) return 0; } +/** Make sure that the reference count of every microdescriptor in cache is + * accurate. */ +void +microdesc_check_counts(void) +{ + microdesc_t **mdp; + if (!the_microdesc_cache) + return; + + HT_FOREACH(mdp, microdesc_map, &the_microdesc_cache->map) { + microdesc_t *md = *mdp; + unsigned int found=0; + const smartlist_t *nodes = nodelist_get_list(); + SMARTLIST_FOREACH(nodes, node_t *, node, { + if (node->md == md) { + ++found; + } + }); + tor_assert(found == md->held_by_nodes); + } +} + /** Deallocate a single microdescriptor. Note: the microdescriptor MUST have * previously been removed from the cache if it had ever been inserted. */ void @@ -439,7 +528,43 @@ microdesc_free(microdesc_t *md) { if (!md) return; - /* Must be removed from hash table! */ + + /* Make sure that the microdesc was really removed from the appropriate data + structures. */ + if (md->held_in_map) { + microdesc_cache_t *cache = get_microdesc_cache(); + microdesc_t *md2 = HT_FIND(microdesc_map, &cache->map, md); + if (md2 == md) { + log_warn(LD_BUG, "microdesc_free() called, but md was still in " + "microdesc_map"); + HT_REMOVE(microdesc_map, &cache->map, md); + } else { + log_warn(LD_BUG, "microdesc_free() called with held_in_map set, but " + "microdesc was not in the map."); + } + tor_fragile_assert(); + } + if (md->held_by_nodes) { + int found=0; + const smartlist_t *nodes = nodelist_get_list(); + SMARTLIST_FOREACH(nodes, node_t *, node, { + if (node->md == md) { + ++found; + node->md = NULL; + } + }); + if (found) { + log_warn(LD_BUG, "microdesc_free() called, but md was still referenced " + "%d node(s); held_by_nodes == %u", found, md->held_by_nodes); + } else { + log_warn(LD_BUG, "microdesc_free() called with held_by_nodes set to %u, " + "but md was not referenced by any nodes", md->held_by_nodes); + } + tor_fragile_assert(); + } + //tor_assert(md->held_in_map == 0); + //tor_assert(md->held_by_nodes == 0); + if (md->onion_pkey) crypto_free_pk_env(md->onion_pkey); if (md->body && md->saved_location != SAVED_IN_CACHE) @@ -449,7 +574,7 @@ microdesc_free(microdesc_t *md) SMARTLIST_FOREACH(md->family, char *, cp, tor_free(cp)); smartlist_free(md->family); } - tor_free(md->exitsummary); + short_policy_free(md->exit_policy); tor_free(md); } @@ -491,3 +616,147 @@ microdesc_average_size(microdesc_cache_t *cache) return (size_t)(cache->total_len_seen / cache->n_seen); } +/** Return a smartlist of all the sha256 digest of the microdescriptors that + * are listed in <b>ns</b> but not present in <b>cache</b>. Returns pointers + * to internals of <b>ns</b>; you should not free the members of the resulting + * smartlist. Omit all microdescriptors whose digest appear in <b>skip</b>. */ +smartlist_t * +microdesc_list_missing_digest256(networkstatus_t *ns, microdesc_cache_t *cache, + int downloadable_only, digestmap_t *skip) +{ + smartlist_t *result = smartlist_create(); + time_t now = time(NULL); + tor_assert(ns->flavor == FLAV_MICRODESC); + SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) { + if (microdesc_cache_lookup_by_digest256(cache, rs->descriptor_digest)) + continue; + if (downloadable_only && + !download_status_is_ready(&rs->dl_status, now, + MAX_MICRODESC_DOWNLOAD_FAILURES)) + continue; + if (skip && digestmap_get(skip, rs->descriptor_digest)) + continue; + if (tor_mem_is_zero(rs->descriptor_digest, DIGEST256_LEN)) + continue; /* This indicates a bug somewhere XXXX023*/ + /* XXXX Also skip if we're a noncache and wouldn't use this router. + * XXXX NM Microdesc + */ + smartlist_add(result, rs->descriptor_digest); + } SMARTLIST_FOREACH_END(rs); + return result; +} + +/** Launch download requests for mircodescriptors as appropriate. + * + * Specifically, we should launch download requests if we are configured to + * download mirodescriptors, and there are some microdescriptors listed the + * current microdesc consensus that we don't have, and either we never asked + * for them, or we failed to download them but we're willing to retry. + */ +void +update_microdesc_downloads(time_t now) +{ + const or_options_t *options = get_options(); + networkstatus_t *consensus; + smartlist_t *missing; + digestmap_t *pending; + + if (should_delay_dir_fetches(options)) + return; + if (directory_too_idle_to_fetch_descriptors(options, now)) + return; + + consensus = networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC); + if (!consensus) + return; + + if (!we_fetch_microdescriptors(options)) + return; + + pending = digestmap_new(); + list_pending_microdesc_downloads(pending); + + missing = microdesc_list_missing_digest256(consensus, + get_microdesc_cache(), + 1, + pending); + digestmap_free(pending, NULL); + + launch_descriptor_downloads(DIR_PURPOSE_FETCH_MICRODESC, + missing, NULL, now); + + smartlist_free(missing); +} + +/** For every microdescriptor listed in the current microdecriptor consensus, + * update its last_listed field to be at least as recent as the publication + * time of the current microdescriptor consensus. + */ +void +update_microdescs_from_networkstatus(time_t now) +{ + microdesc_cache_t *cache = get_microdesc_cache(); + microdesc_t *md; + networkstatus_t *ns = + networkstatus_get_reasonably_live_consensus(now, FLAV_MICRODESC); + + if (! ns) + return; + + tor_assert(ns->flavor == FLAV_MICRODESC); + + SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) { + md = microdesc_cache_lookup_by_digest256(cache, rs->descriptor_digest); + if (md && ns->valid_after > md->last_listed) + md->last_listed = ns->valid_after; + } SMARTLIST_FOREACH_END(rs); +} + +/** Return true iff we should prefer to use microdescriptors rather than + * routerdescs for building circuits. */ +int +we_use_microdescriptors_for_circuits(const or_options_t *options) +{ + int ret = options->UseMicrodescriptors; + if (ret == -1) { + /* UseMicrodescriptors is "auto"; we need to decide: */ + /* So we decide that we'll use microdescriptors iff we are not a server, + * and we're not autofetching everything. */ + ret = !server_mode(options) && !options->FetchUselessDescriptors; + } + return ret; +} + +/** Return true iff we should try to download microdescriptors at all. */ +int +we_fetch_microdescriptors(const or_options_t *options) +{ + if (directory_caches_dir_info(options)) + return 1; + if (options->FetchUselessDescriptors) + return 1; + return we_use_microdescriptors_for_circuits(options); +} + +/** Return true iff we should try to download router descriptors at all. */ +int +we_fetch_router_descriptors(const or_options_t *options) +{ + if (directory_caches_dir_info(options)) + return 1; + if (options->FetchUselessDescriptors) + return 1; + return ! we_use_microdescriptors_for_circuits(options); +} + +/** Return the consensus flavor we actually want to use to build circuits. */ +int +usable_consensus_flavor(void) +{ + if (we_use_microdescriptors_for_circuits(get_options())) { + return FLAV_MICRODESC; + } else { + return FLAV_NS; + } +} + diff --git a/src/or/microdesc.h b/src/or/microdesc.h index 77ce8536bc..4564132810 100644 --- a/src/or/microdesc.h +++ b/src/or/microdesc.h @@ -14,9 +14,12 @@ microdesc_cache_t *get_microdesc_cache(void); +void microdesc_check_counts(void); + smartlist_t *microdescs_add_to_cache(microdesc_cache_t *cache, const char *s, const char *eos, saved_location_t where, - int no_save); + int no_save, time_t listed_at, + smartlist_t *requested_digests256); smartlist_t *microdescs_add_list_to_cache(microdesc_cache_t *cache, smartlist_t *descriptors, saved_location_t where, int no_save); @@ -31,8 +34,21 @@ microdesc_t *microdesc_cache_lookup_by_digest256(microdesc_cache_t *cache, size_t microdesc_average_size(microdesc_cache_t *cache); +smartlist_t *microdesc_list_missing_digest256(networkstatus_t *ns, + microdesc_cache_t *cache, + int downloadable_only, + digestmap_t *skip); + void microdesc_free(microdesc_t *md); void microdesc_free_all(void); +void update_microdesc_downloads(time_t now); +void update_microdescs_from_networkstatus(time_t now); + +int usable_consensus_flavor(void); +int we_fetch_microdescriptors(const or_options_t *options); +int we_fetch_router_descriptors(const or_options_t *options); +int we_use_microdescriptors_for_circuits(const or_options_t *options); + #endif diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index b0ef74b02e..7cd9d02c3f 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -20,7 +20,9 @@ #include "dirserv.h" #include "dirvote.h" #include "main.h" +#include "microdesc.h" #include "networkstatus.h" +#include "nodelist.h" #include "relay.h" #include "router.h" #include "routerlist.h" @@ -44,8 +46,21 @@ static strmap_t *named_server_map = NULL; * as unnamed for some server in the consensus. */ static strmap_t *unnamed_server_map = NULL; -/** Most recently received and validated v3 consensus network status. */ -static networkstatus_t *current_consensus = NULL; +/** Most recently received and validated v3 consensus network status, + * of whichever type we are using for our own circuits. This will be the same + * as one of current_ns_consensus or current_md_consensus. + */ +#define current_consensus \ + (we_use_microdescriptors_for_circuits(get_options()) ? \ + current_md_consensus : current_ns_consensus) + +/** Most recently received and validated v3 "ns"-flavored consensus network + * status. */ +static networkstatus_t *current_ns_consensus = NULL; + +/** Most recently received and validated v3 "microdec"-flavored consensus + * network status. */ +static networkstatus_t *current_md_consensus = NULL; /** A v3 consensus networkstatus that we've received, but which we don't * have enough certificates to be happy about. */ @@ -94,9 +109,8 @@ void networkstatus_reset_warnings(void) { if (current_consensus) { - SMARTLIST_FOREACH(current_consensus->routerstatus_list, - routerstatus_t *, rs, - rs->name_lookup_warned = 0); + SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node, + node->name_lookup_warned = 0); } have_warned_about_old_version = 0; @@ -199,7 +213,7 @@ router_reload_consensus_networkstatus(void) char *filename; char *s; struct stat st; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); const unsigned int flags = NSSET_FROM_CACHE | NSSET_DONT_DOWNLOAD_CERTS; int flav; @@ -271,6 +285,7 @@ router_reload_consensus_networkstatus(void) update_certificate_downloads(time(NULL)); routers_update_all_from_networkstatus(time(NULL), 3); + update_microdescs_from_networkstatus(time(NULL)); return 0; } @@ -469,7 +484,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus, int n_bad = 0; int n_unknown = 0; int n_no_signature = 0; - int n_v3_authorities = get_n_authorities(V3_AUTHORITY); + int n_v3_authorities = get_n_authorities(V3_DIRINFO); int n_required = n_v3_authorities/2 + 1; smartlist_t *need_certs_from = smartlist_create(); smartlist_t *unrecognized = smartlist_create(); @@ -540,7 +555,7 @@ networkstatus_check_consensus_signature(networkstatus_t *consensus, SMARTLIST_FOREACH(router_get_trusted_dir_servers(), trusted_dir_server_t *, ds, { - if ((ds->type & V3_AUTHORITY) && + if ((ds->type & V3_DIRINFO) && !networkstatus_get_voter_by_id(consensus, ds->v3_identity_digest)) smartlist_add(missing_authorities, ds); }); @@ -723,7 +738,7 @@ router_set_networkstatus_v2(const char *s, time_t arrived_at, base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN); if (!(trusted_dir = router_get_trusteddirserver_by_digest(ns->identity_digest)) || - !(trusted_dir->type & V2_AUTHORITY)) { + !(trusted_dir->type & V2_DIRINFO)) { log_info(LD_DIR, "Network status was signed, but not by an authoritative " "directory we recognize."); source_desc = fp; @@ -927,10 +942,9 @@ compare_digest_to_routerstatus_entry(const void *_key, const void **_member) return tor_memcmp(key, rs->identity_digest, DIGEST_LEN); } -/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or - * NULL if none was found. */ +/** As networkstatus_v2_find_entry, but do not return a const pointer */ routerstatus_t * -networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest) +networkstatus_v2_find_mutable_entry(networkstatus_v2_t *ns, const char *digest) { return smartlist_bsearch(ns->entries, digest, compare_digest_to_routerstatus_entry); @@ -938,14 +952,29 @@ networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest) /** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or * NULL if none was found. */ +const routerstatus_t * +networkstatus_v2_find_entry(networkstatus_v2_t *ns, const char *digest) +{ + return networkstatus_v2_find_mutable_entry(ns, digest); +} + +/** As networkstatus_find_entry, but do not return a const pointer */ routerstatus_t * -networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest) +networkstatus_vote_find_mutable_entry(networkstatus_t *ns, const char *digest) { return smartlist_bsearch(ns->routerstatus_list, digest, compare_digest_to_routerstatus_entry); } -/*XXXX make this static once functions are moved into this file. */ +/** Return the entry in <b>ns</b> for the identity digest <b>digest</b>, or + * NULL if none was found. */ +const routerstatus_t * +networkstatus_vote_find_entry(networkstatus_t *ns, const char *digest) +{ + return networkstatus_vote_find_mutable_entry(ns, digest); +} + +/*XXXX MOVE make this static once functions are moved into this file. */ /** Search the routerstatuses in <b>ns</b> for one whose identity digest is * <b>digest</b>. Return value and set *<b>found_out</b> as for * smartlist_bsearch_idx(). */ @@ -967,22 +996,37 @@ networkstatus_get_v2_list(void) return networkstatus_v2_list; } -/** Return the consensus view of the status of the router whose current - * <i>descriptor</i> digest is <b>digest</b>, or NULL if no such router is - * known. */ +/* As router_get_consensus_status_by_descriptor_digest, but does not return + * a const pointer */ routerstatus_t * -router_get_consensus_status_by_descriptor_digest(const char *digest) +router_get_mutable_consensus_status_by_descriptor_digest( + networkstatus_t *consensus, + const char *digest) { - if (!current_consensus) return NULL; - if (!current_consensus->desc_digest_map) { - digestmap_t * m = current_consensus->desc_digest_map = digestmap_new(); - SMARTLIST_FOREACH(current_consensus->routerstatus_list, + if (!consensus) + consensus = current_consensus; + if (!consensus) + return NULL; + if (!consensus->desc_digest_map) { + digestmap_t *m = consensus->desc_digest_map = digestmap_new(); + SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs, { digestmap_set(m, rs->descriptor_digest, rs); }); } - return digestmap_get(current_consensus->desc_digest_map, digest); + return digestmap_get(consensus->desc_digest_map, digest); +} + +/** Return the consensus view of the status of the router whose current + * <i>descriptor</i> digest in <b>consensus</b> is <b>digest</b>, or NULL if + * no such router is known. */ +const routerstatus_t * +router_get_consensus_status_by_descriptor_digest(networkstatus_t *consensus, + const char *digest) +{ + return router_get_mutable_consensus_status_by_descriptor_digest( + consensus, digest); } /** Given the digest of a router descriptor, return its current download @@ -991,7 +1035,10 @@ download_status_t * router_get_dl_status_by_descriptor_digest(const char *d) { routerstatus_t *rs; - if ((rs = router_get_consensus_status_by_descriptor_digest(d))) + if (!current_ns_consensus) + return NULL; + if ((rs = router_get_mutable_consensus_status_by_descriptor_digest( + current_ns_consensus, d))) return &rs->dl_status; if (v2_download_status_map) return digestmap_get(v2_download_status_map, d); @@ -999,10 +1046,9 @@ router_get_dl_status_by_descriptor_digest(const char *d) return NULL; } -/** Return the consensus view of the status of the router whose identity - * digest is <b>digest</b>, or NULL if we don't know about any such router. */ +/** As router_get_consensus_status_by_id, but do not return a const pointer */ routerstatus_t * -router_get_consensus_status_by_id(const char *digest) +router_get_mutable_consensus_status_by_id(const char *digest) { if (!current_consensus) return NULL; @@ -1010,100 +1056,27 @@ router_get_consensus_status_by_id(const char *digest) compare_digest_to_routerstatus_entry); } +/** Return the consensus view of the status of the router whose identity + * digest is <b>digest</b>, or NULL if we don't know about any such router. */ +const routerstatus_t * +router_get_consensus_status_by_id(const char *digest) +{ + return router_get_mutable_consensus_status_by_id(digest); +} + /** Given a nickname (possibly verbose, possibly a hexadecimal digest), return * the corresponding routerstatus_t, or NULL if none exists. Warn the * user if <b>warn_if_unnamed</b> is set, and they have specified a router by * nickname, but the Named flag isn't set for that router. */ -routerstatus_t * +const routerstatus_t * router_get_consensus_status_by_nickname(const char *nickname, int warn_if_unnamed) { - char digest[DIGEST_LEN]; - routerstatus_t *best=NULL; - smartlist_t *matches=NULL; - const char *named_id=NULL; - - if (!current_consensus || !nickname) - return NULL; - - /* Is this name really a hexadecimal identity digest? */ - if (nickname[0] == '$') { - if (base16_decode(digest, DIGEST_LEN, nickname+1, strlen(nickname+1))<0) - return NULL; - return networkstatus_vote_find_entry(current_consensus, digest); - } else if (strlen(nickname) == HEX_DIGEST_LEN && - (base16_decode(digest, DIGEST_LEN, nickname, strlen(nickname))==0)) { - return networkstatus_vote_find_entry(current_consensus, digest); - } - - /* Is there a server that is Named with this name? */ - if (named_server_map) - named_id = strmap_get_lc(named_server_map, nickname); - if (named_id) - return networkstatus_vote_find_entry(current_consensus, named_id); - - /* Okay; is this name listed as Unnamed? */ - if (unnamed_server_map && - strmap_get_lc(unnamed_server_map, nickname)) { - log_info(LD_GENERAL, "The name %s is listed as Unnamed; it is not the " - "canonical name of any server we know.", escaped(nickname)); + const node_t *node = node_get_by_nickname(nickname, warn_if_unnamed); + if (node) + return node->rs; + else return NULL; - } - - /* This name is not canonical for any server; go through the list and - * see who it matches. */ - /*XXXX This is inefficient; optimize it if it matters. */ - matches = smartlist_create(); - SMARTLIST_FOREACH(current_consensus->routerstatus_list, - routerstatus_t *, lrs, - { - if (!strcasecmp(lrs->nickname, nickname)) { - if (lrs->is_named) { - tor_fragile_assert() /* This should never happen. */ - smartlist_free(matches); - return lrs; - } else { - if (lrs->is_unnamed) { - tor_fragile_assert(); /* nor should this. */ - smartlist_clear(matches); - best=NULL; - break; - } - smartlist_add(matches, lrs); - best = lrs; - } - } - }); - - if (smartlist_len(matches)>1 && warn_if_unnamed) { - int any_unwarned=0; - SMARTLIST_FOREACH(matches, routerstatus_t *, lrs, - { - if (! lrs->name_lookup_warned) { - lrs->name_lookup_warned=1; - any_unwarned=1; - } - }); - if (any_unwarned) { - log_warn(LD_CONFIG,"There are multiple matches for the nickname \"%s\"," - " but none is listed as named by the directory authorities. " - "Choosing one arbitrarily.", nickname); - } - } else if (warn_if_unnamed && best && !best->name_lookup_warned) { - char fp[HEX_DIGEST_LEN+1]; - base16_encode(fp, sizeof(fp), - best->identity_digest, DIGEST_LEN); - log_warn(LD_CONFIG, - "When looking up a status, you specified a server \"%s\" by name, " - "but the directory authorities do not have any key registered for " - "this nickname -- so it could be used by any server, " - "not just the one you meant. " - "To make sure you get the same server in the future, refer to " - "it by key, as \"$%s\".", nickname, fp); - best->name_lookup_warned = 1; - } - smartlist_free(matches); - return best; } /** Return the identity digest that's mapped to officially by @@ -1159,7 +1132,7 @@ update_v2_networkstatus_cache_downloads(time_t now) { char resource[HEX_DIGEST_LEN+6]; /* fp/hexdigit.z\0 */ tor_addr_t addr; - if (!(ds->type & V2_AUTHORITY)) + if (!(ds->type & V2_DIRINFO)) continue; if (router_digest_is_me(ds->digest)) continue; @@ -1200,6 +1173,29 @@ update_v2_networkstatus_cache_downloads(time_t now) } } +/** DOCDOC */ +static int +we_want_to_fetch_flavor(const or_options_t *options, int flavor) +{ + if (flavor < 0 || flavor > N_CONSENSUS_FLAVORS) { + /* This flavor is crazy; we don't want it */ + /*XXXX handle unrecognized flavors later */ + return 0; + } + if (authdir_mode_v3(options) || directory_caches_dir_info(options)) { + /* We want to serve all flavors to others, regardless if we would use + * it ourselves. */ + return 1; + } + if (options->FetchUselessDescriptors) { + /* In order to get all descriptors, we need to fetch all consensuses. */ + return 1; + } + /* Otherwise, we want the flavor only if we want to use it to build + * circuits. */ + return flavor == usable_consensus_flavor(); +} + /** How many times will we try to fetch a consensus before we give up? */ #define CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES 8 /** How long will we hang onto a possibly live consensus for which we're @@ -1212,48 +1208,65 @@ static void update_consensus_networkstatus_downloads(time_t now) { int i; + const or_options_t *options = get_options(); + if (!networkstatus_get_live_consensus(now)) time_to_download_next_consensus = now; /* No live consensus? Get one now!*/ if (time_to_download_next_consensus > now) return; /* Wait until the current consensus is older. */ - /* XXXXNM Microdescs: may need to download more types. */ - if (!download_status_is_ready(&consensus_dl_status[FLAV_NS], now, - CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES)) - return; /* We failed downloading a consensus too recently. */ - if (connection_get_by_type_purpose(CONN_TYPE_DIR, - DIR_PURPOSE_FETCH_CONSENSUS)) - return; /* There's an in-progress download.*/ for (i=0; i < N_CONSENSUS_FLAVORS; ++i) { - consensus_waiting_for_certs_t *waiting = &consensus_waiting_for_certs[i]; + /* XXXX need some way to download unknown flavors if we are caching. */ + const char *resource; + consensus_waiting_for_certs_t *waiting; + + if (! we_want_to_fetch_flavor(options, i)) + continue; + + resource = networkstatus_get_flavor_name(i); + + if (!download_status_is_ready(&consensus_dl_status[i], now, + CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES)) + continue; /* We failed downloading a consensus too recently. */ + if (connection_dir_get_by_purpose_and_resource( + DIR_PURPOSE_FETCH_CONSENSUS, resource)) + continue; /* There's an in-progress download.*/ + + waiting = &consensus_waiting_for_certs[i]; if (waiting->consensus) { /* XXXX make sure this doesn't delay sane downloads. */ - if (waiting->set_at + DELAY_WHILE_FETCHING_CERTS > now) - return; /* We're still getting certs for this one. */ - else { + if (waiting->set_at + DELAY_WHILE_FETCHING_CERTS > now) { + continue; /* We're still getting certs for this one. */ + } else { if (!waiting->dl_failed) { - download_status_failed(&consensus_dl_status[FLAV_NS], 0); + download_status_failed(&consensus_dl_status[i], 0); waiting->dl_failed=1; } } } - } - log_info(LD_DIR, "Launching networkstatus consensus download."); - directory_get_from_dirserver(DIR_PURPOSE_FETCH_CONSENSUS, - ROUTER_PURPOSE_GENERAL, NULL, - PDS_RETRY_IF_NO_SERVERS); + log_info(LD_DIR, "Launching %s networkstatus consensus download.", + networkstatus_get_flavor_name(i)); + + directory_get_from_dirserver(DIR_PURPOSE_FETCH_CONSENSUS, + ROUTER_PURPOSE_GENERAL, resource, + PDS_RETRY_IF_NO_SERVERS); + } } /** Called when an attempt to download a consensus fails: note that the * failure occurred, and possibly retry. */ void -networkstatus_consensus_download_failed(int status_code) +networkstatus_consensus_download_failed(int status_code, const char *flavname) { - /* XXXXNM Microdescs: may need to handle more types. */ - download_status_failed(&consensus_dl_status[FLAV_NS], status_code); - /* Retry immediately, if appropriate. */ - update_consensus_networkstatus_downloads(time(NULL)); + int flav = networkstatus_parse_flavor_name(flavname); + if (flav >= 0) { + tor_assert(flav < N_CONSENSUS_FLAVORS); + /* XXXX handle unrecognized flavors */ + download_status_failed(&consensus_dl_status[flav], status_code); + /* Retry immediately, if appropriate. */ + update_consensus_networkstatus_downloads(time(NULL)); + } } /** How long do we (as a cache) wait after a consensus becomes non-fresh @@ -1265,7 +1278,7 @@ networkstatus_consensus_download_failed(int status_code) void update_consensus_networkstatus_fetch_time(time_t now) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); networkstatus_t *c = networkstatus_get_live_consensus(now); if (c) { long dl_interval; @@ -1339,7 +1352,7 @@ update_consensus_networkstatus_fetch_time(time_t now) * fetches yet (e.g. we demand bridges and none are yet known). * Else return 0. */ int -should_delay_dir_fetches(or_options_t *options) +should_delay_dir_fetches(const or_options_t *options) { if (options->UseBridges && !any_bridge_descriptors_known()) { log_info(LD_DIR, "delaying dir fetches (no running bridges known)"); @@ -1353,7 +1366,7 @@ should_delay_dir_fetches(or_options_t *options) void update_networkstatus_downloads(time_t now) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); if (should_delay_dir_fetches(options)) return; if (authdir_mode_any_main(options) || options->FetchV2Networkstatus) @@ -1374,7 +1387,10 @@ update_certificate_downloads(time_t now) now); } - authority_certs_fetch_missing(current_consensus, now); + if (current_ns_consensus) + authority_certs_fetch_missing(current_ns_consensus, now); + if (current_md_consensus) + authority_certs_fetch_missing(current_md_consensus, now); } /** Return 1 if we have a consensus but we don't have enough certificates @@ -1382,7 +1398,7 @@ update_certificate_downloads(time_t now) int consensus_is_waiting_for_certs(void) { - return consensus_waiting_for_certs[USABLE_CONSENSUS_FLAVOR].consensus + return consensus_waiting_for_certs[usable_consensus_flavor()].consensus ? 1 : 0; } @@ -1406,6 +1422,18 @@ networkstatus_get_latest_consensus(void) return current_consensus; } +/** DOCDOC */ +networkstatus_t * +networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f) +{ + if (f == FLAV_NS) + return current_ns_consensus; + else if (f == FLAV_MICRODESC) + return current_md_consensus; + else + tor_assert(0); +} + /** Return the most recent consensus that we have downloaded, or NULL if it is * no longer live. */ networkstatus_t * @@ -1425,13 +1453,15 @@ networkstatus_get_live_consensus(time_t now) /** As networkstatus_get_live_consensus(), but is way more tolerant of expired * consensuses. */ networkstatus_t * -networkstatus_get_reasonably_live_consensus(time_t now) +networkstatus_get_reasonably_live_consensus(time_t now, int flavor) { #define REASONABLY_LIVE_TIME (24*60*60) - if (current_consensus && - current_consensus->valid_after <= now && - now <= current_consensus->valid_until+REASONABLY_LIVE_TIME) - return current_consensus; + networkstatus_t *consensus = + networkstatus_get_latest_consensus_by_flavor(flavor); + if (consensus && + consensus->valid_after <= now && + now <= consensus->valid_until+REASONABLY_LIVE_TIME) + return consensus; else return NULL; } @@ -1452,7 +1482,7 @@ routerstatus_has_changed(const routerstatus_t *a, const routerstatus_t *b) a->is_exit != b->is_exit || a->is_stable != b->is_stable || a->is_fast != b->is_fast || - a->is_running != b->is_running || + a->is_flagged_running != b->is_flagged_running || a->is_named != b->is_named || a->is_unnamed != b->is_unnamed || a->is_valid != b->is_valid || @@ -1493,13 +1523,14 @@ notify_control_networkstatus_changed(const networkstatus_t *old_c, } changed = smartlist_create(); - SMARTLIST_FOREACH_JOIN(old_c->routerstatus_list, routerstatus_t *, rs_old, - new_c->routerstatus_list, routerstatus_t *, rs_new, - tor_memcmp(rs_old->identity_digest, - rs_new->identity_digest, DIGEST_LEN), - smartlist_add(changed, rs_new)) { + SMARTLIST_FOREACH_JOIN( + old_c->routerstatus_list, const routerstatus_t *, rs_old, + new_c->routerstatus_list, const routerstatus_t *, rs_new, + tor_memcmp(rs_old->identity_digest, + rs_new->identity_digest, DIGEST_LEN), + smartlist_add(changed, (void*) rs_new)) { if (routerstatus_has_changed(rs_old, rs_new)) - smartlist_add(changed, rs_new); + smartlist_add(changed, (void*)rs_new); } SMARTLIST_FOREACH_JOIN_END(rs_old, rs_new); control_event_networkstatus_changed(changed); @@ -1523,7 +1554,6 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c, rs_new->identity_digest, DIGEST_LEN), STMT_NIL) { /* Okay, so we're looking at the same identity. */ - rs_new->name_lookup_warned = rs_old->name_lookup_warned; rs_new->last_dir_503_at = rs_old->last_dir_503_at; if (tor_memeq(rs_old->descriptor_digest, rs_new->descriptor_digest, @@ -1559,7 +1589,7 @@ networkstatus_set_current_consensus(const char *consensus, networkstatus_t *c=NULL; int r, result = -1; time_t now = time(NULL); - or_options_t *options = get_options(); + const or_options_t *options = get_options(); char *unverified_fname = NULL, *consensus_fname = NULL; int flav = networkstatus_parse_flavor_name(flavor); const unsigned from_cache = flags & NSSET_FROM_CACHE; @@ -1597,7 +1627,7 @@ networkstatus_set_current_consensus(const char *consensus, flavor = networkstatus_get_flavor_name(flav); } - if (flav != USABLE_CONSENSUS_FLAVOR && + if (flav != usable_consensus_flavor() && !directory_caches_dir_info(options)) { /* This consensus is totally boring to us: we won't use it, and we won't * serve it. Drop it. */ @@ -1616,9 +1646,16 @@ networkstatus_set_current_consensus(const char *consensus, if (!strcmp(flavor, "ns")) { consensus_fname = get_datadir_fname("cached-consensus"); unverified_fname = get_datadir_fname("unverified-consensus"); - if (current_consensus) { - current_digests = ¤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 +1732,36 @@ networkstatus_set_current_consensus(const char *consensus, } } - if (!from_cache && flav == USABLE_CONSENSUS_FLAVOR) + if (!from_cache && flav == usable_consensus_flavor()) control_event_client_status(LOG_NOTICE, "CONSENSUS_ARRIVED"); /* Are we missing any certificates at all? */ if (r != 1 && dl_certs) authority_certs_fetch_missing(c, now); - if (flav == USABLE_CONSENSUS_FLAVOR) { + if (flav == usable_consensus_flavor()) { notify_control_networkstatus_changed(current_consensus, c); - - if (current_consensus) { - networkstatus_copy_old_consensus_info(c, current_consensus); - networkstatus_vote_free(current_consensus); + } + if (flav == FLAV_NS) { + if (current_ns_consensus) { + networkstatus_copy_old_consensus_info(c, current_ns_consensus); + networkstatus_vote_free(current_ns_consensus); /* Defensive programming : we should set current_consensus very soon, * but we're about to call some stuff in the meantime, and leaving this * dangling pointer around has proven to be trouble. */ - current_consensus = NULL; + current_ns_consensus = NULL; + } + current_ns_consensus = c; + free_consensus = 0; /* avoid free */ + } else if (flav == FLAV_MICRODESC) { + if (current_md_consensus) { + networkstatus_copy_old_consensus_info(c, current_md_consensus); + networkstatus_vote_free(current_md_consensus); + /* more defensive programming */ + current_md_consensus = NULL; } + current_md_consensus = c; + free_consensus = 0; /* avoid free */ } waiting = &consensus_waiting_for_certs[flav]; @@ -1737,12 +1786,12 @@ networkstatus_set_current_consensus(const char *consensus, download_status_failed(&consensus_dl_status[flav], 0); } - if (flav == USABLE_CONSENSUS_FLAVOR) { - current_consensus = c; - free_consensus = 0; /* Prevent free. */ - - /* XXXXNM Microdescs: needs a non-ns variant. */ + if (flav == usable_consensus_flavor()) { + /* XXXXNM Microdescs: needs a non-ns variant. ???? NM*/ update_consensus_networkstatus_fetch_time(now); + + nodelist_set_consensus(current_consensus); + dirvote_recalculate_timing(options, now); routerstatus_list_update_named_server_map(); cell_ewma_set_scale_factor(options, current_consensus); @@ -1769,11 +1818,11 @@ networkstatus_set_current_consensus(const char *consensus, * valid-after time, declare that our clock is skewed. */ #define EARLY_CONSENSUS_NOTICE_SKEW 60 - if (now < current_consensus->valid_after - EARLY_CONSENSUS_NOTICE_SKEW) { + if (now < c->valid_after - EARLY_CONSENSUS_NOTICE_SKEW) { char tbuf[ISO_TIME_LEN+1]; char dbuf[64]; - long delta = now - current_consensus->valid_after; - format_iso_time(tbuf, current_consensus->valid_after); + long delta = now - c->valid_after; + format_iso_time(tbuf, c->valid_after); format_time_interval(dbuf, sizeof(dbuf), delta); log_warn(LD_GENERAL, "Our clock is %s behind the time published in the " "consensus network status document (%s GMT). Tor needs an " @@ -1824,7 +1873,8 @@ void routers_update_all_from_networkstatus(time_t now, int dir_version) { routerlist_t *rl = router_get_routerlist(); - networkstatus_t *consensus = networkstatus_get_live_consensus(now); + networkstatus_t *consensus = networkstatus_get_reasonably_live_consensus(now, + FLAV_NS); if (networkstatus_v2_list_has_changed) download_status_map_update_from_v2_networkstatus(); @@ -1896,7 +1946,7 @@ download_status_map_update_from_v2_networkstatus(void) dl_status = digestmap_new(); SMARTLIST_FOREACH_BEGIN(networkstatus_v2_list, networkstatus_v2_t *, ns) { - SMARTLIST_FOREACH_BEGIN(ns->entries, routerstatus_t *, rs) { + SMARTLIST_FOREACH_BEGIN(ns->entries, const routerstatus_t *, rs) { const char *d = rs->descriptor_digest; download_status_t *s; if (digestmap_get(dl_status, d)) @@ -1924,7 +1974,8 @@ routerstatus_list_update_named_server_map(void) named_server_map = strmap_new(); strmap_free(unnamed_server_map, NULL); unnamed_server_map = strmap_new(); - SMARTLIST_FOREACH(current_consensus->routerstatus_list, routerstatus_t *, rs, + SMARTLIST_FOREACH(current_consensus->routerstatus_list, + const routerstatus_t *, rs, { if (rs->is_named) { strmap_set_lc(named_server_map, rs->nickname, @@ -1944,9 +1995,8 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, int reset_failures) { trusted_dir_server_t *ds; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); int authdir = authdir_mode_v2(options) || authdir_mode_v3(options); - int namingdir = authdir && options->NamingAuthoritativeDir; networkstatus_t *ns = current_consensus; if (!ns || !smartlist_len(ns->routerstatus_list)) return; @@ -1960,25 +2010,12 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, tor_memcmp(rs->identity_digest, router->cache_info.identity_digest, DIGEST_LEN), { - /* We have no routerstatus for this router. Clear flags and skip it. */ - if (!namingdir) - router->is_named = 0; - if (!authdir) { - if (router->purpose == ROUTER_PURPOSE_GENERAL) - router_clear_status_flags(router); - } }) { /* We have a routerstatus for this router. */ const char *digest = router->cache_info.identity_digest; ds = router_get_trusteddirserver_by_digest(digest); - if (!namingdir) { - if (rs->is_named && !strcasecmp(router->nickname, rs->nickname)) - router->is_named = 1; - else - router->is_named = 0; - } /* Is it the same descriptor, or only the same identity? */ if (tor_memeq(router->cache_info.signed_descriptor_digest, rs->descriptor_digest, DIGEST_LEN)) { @@ -1986,28 +2023,17 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, router->cache_info.last_listed_as_valid_until = ns->valid_until; } - if (!authdir) { - /* If we're not an authdir, believe others. */ - router->is_valid = rs->is_valid; - router->is_running = rs->is_running; - router->is_fast = rs->is_fast; - router->is_stable = rs->is_stable; - router->is_possible_guard = rs->is_possible_guard; - router->is_exit = rs->is_exit; - router->is_bad_directory = rs->is_bad_directory; - router->is_bad_exit = rs->is_bad_exit; - router->is_hs_dir = rs->is_hs_dir; - } else { + if (authdir) { /* If we _are_ an authority, we should check whether this router * is one that will cause us to need a reachability test. */ routerinfo_t *old_router = - router_get_by_digest(router->cache_info.identity_digest); + router_get_mutable_by_digest(router->cache_info.identity_digest); if (old_router != router) { router->needs_retest_if_added = dirserv_should_launch_reachability_test(router, old_router); } } - if (router->is_running && ds) { + if (rs->is_flagged_running && ds) { download_status_reset(&ds->v2_ns_dl_status); } if (reset_failures) { @@ -2016,10 +2042,9 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, } SMARTLIST_FOREACH_JOIN_END(rs, router); /* Now update last_listed_as_valid_until from v2 networkstatuses. */ - /* XXXX If this is slow, we need to rethink the code. */ SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, { time_t live_until = ns->published_on + V2_NETWORKSTATUS_ROUTER_LIFETIME; - SMARTLIST_FOREACH_JOIN(ns->entries, routerstatus_t *, rs, + SMARTLIST_FOREACH_JOIN(ns->entries, const routerstatus_t *, rs, routers, routerinfo_t *, ri, tor_memcmp(rs->identity_digest, ri->cache_info.identity_digest, DIGEST_LEN), @@ -2040,7 +2065,7 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, void signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs) { - networkstatus_t *ns = current_consensus; + networkstatus_t *ns = current_ns_consensus; if (!ns) return; @@ -2048,11 +2073,11 @@ signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs) char dummy[DIGEST_LEN]; /* instantiates the digest map. */ memset(dummy, 0, sizeof(dummy)); - router_get_consensus_status_by_descriptor_digest(dummy); + router_get_consensus_status_by_descriptor_digest(ns, dummy); } SMARTLIST_FOREACH(descs, signed_descriptor_t *, d, { - routerstatus_t *rs = digestmap_get(ns->desc_digest_map, + const routerstatus_t *rs = digestmap_get(ns->desc_digest_map, d->signed_descriptor_digest); if (rs) { if (ns->valid_until > d->last_listed_as_valid_until) @@ -2065,7 +2090,7 @@ signed_descs_update_status_from_consensus_networkstatus(smartlist_t *descs) * return the result in a newly allocated string. Used only by controller * interface (for now.) */ char * -networkstatus_getinfo_helper_single(routerstatus_t *rs) +networkstatus_getinfo_helper_single(const routerstatus_t *rs) { char buf[RS_ENTRY_LEN+1]; routerstatus_format_entry(buf, sizeof(buf), rs, NULL, NS_CONTROL_PORT); @@ -2098,6 +2123,9 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now) statuses = smartlist_create(); SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, { + node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest); + if (!node) + continue; if (ri->cache_info.published_on < cutoff) continue; if (ri->purpose != purpose) @@ -2105,7 +2133,7 @@ networkstatus_getinfo_by_purpose(const char *purpose_string, time_t now) if (bridge_auth && ri->purpose == ROUTER_PURPOSE_BRIDGE) dirserv_set_router_is_running(ri, now); /* then generate and write out status lines for each of them */ - set_routerstatus_from_routerinfo(&rs, ri, now, 0, 0, 0, 0); + set_routerstatus_from_routerinfo(&rs, node, ri, now, 0, 0, 0, 0); smartlist_add(statuses, networkstatus_getinfo_helper_single(&rs)); }); @@ -2120,7 +2148,7 @@ void networkstatus_dump_bridge_status_to_file(time_t now) { char *status = networkstatus_getinfo_by_purpose("bridge", now); - or_options_t *options = get_options(); + const or_options_t *options = get_options(); size_t len = strlen(options->DataDirectory) + 32; char *fname = tor_malloc(len); tor_snprintf(fname, len, "%s"PATH_SEPARATOR"networkstatus-bridges", @@ -2174,7 +2202,7 @@ get_net_param_from_list(smartlist_t *net_params, const char *param_name, * <b>min_val</b> and at most <b>max_val</b> and raise/cap the parsed value * if necessary. */ int32_t -networkstatus_get_param(networkstatus_t *ns, const char *param_name, +networkstatus_get_param(const networkstatus_t *ns, const char *param_name, int32_t default_val, int32_t min_val, int32_t max_val) { if (!ns) /* if they pass in null, go find it ourselves */ @@ -2253,7 +2281,7 @@ getinfo_helper_networkstatus(control_connection_t *conn, const char *question, char **answer, const char **errmsg) { - routerstatus_t *status; + const routerstatus_t *status; (void) conn; if (!current_consensus) { @@ -2264,7 +2292,7 @@ getinfo_helper_networkstatus(control_connection_t *conn, if (!strcmp(question, "ns/all")) { smartlist_t *statuses = smartlist_create(); SMARTLIST_FOREACH(current_consensus->routerstatus_list, - routerstatus_t *, rs, + const routerstatus_t *, rs, { smartlist_add(statuses, networkstatus_getinfo_helper_single(rs)); }); @@ -2308,8 +2336,9 @@ networkstatus_free_all(void) digestmap_free(v2_download_status_map, _tor_free); v2_download_status_map = NULL; - networkstatus_vote_free(current_consensus); - current_consensus = NULL; + networkstatus_vote_free(current_ns_consensus); + networkstatus_vote_free(current_md_consensus); + current_md_consensus = current_ns_consensus = NULL; for (i=0; i < N_CONSENSUS_FLAVORS; ++i) { consensus_waiting_for_certs_t *waiting = &consensus_waiting_for_certs[i]; diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h index ec2e8f884d..1b10f27388 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 0000000000..b93b919c13 --- /dev/null +++ b/src/or/nodelist.c @@ -0,0 +1,758 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2011, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "or.h" +#include "config.h" +#include "dirserv.h" +#include "microdesc.h" +#include "networkstatus.h" +#include "nodelist.h" +#include "policies.h" +#include "router.h" +#include "routerlist.h" + +#include <string.h> + +static void nodelist_drop_node(node_t *node, int remove_from_ht); +static void node_free(node_t *node); + +/** A nodelist_t holds a node_t object for every router we're "willing to use + * for something". Specifically, it should hold a node_t for every node that + * is currently in the routerlist, or currently in the consensus we're using. + */ +typedef struct nodelist_t { + /* A list of all the nodes. */ + smartlist_t *nodes; + /* Hash table to map from node ID digest to node. */ + HT_HEAD(nodelist_map, node_t) nodes_by_id; + +} nodelist_t; + +static INLINE unsigned int +node_id_hash(const node_t *node) +{ +#if SIZEOF_INT == 4 + const uint32_t *p = (const uint32_t*)node->identity; + return p[0] ^ p[1] ^ p[2] ^ p[3] ^ p[4]; +#elif SIZEOF_INT == 8 + const uint64_t *p = (const uint32_t*)node->identity; + const uint32_t *p32 = (const uint32_t*)node->identity; + return p[0] ^ p[1] ^ p32[4]; +#endif +} + +static INLINE unsigned int +node_id_eq(const node_t *node1, const node_t *node2) +{ + return tor_memeq(node1->identity, node2->identity, DIGEST_LEN); +} + +HT_PROTOTYPE(nodelist_map, node_t, ht_ent, node_id_hash, node_id_eq); +HT_GENERATE(nodelist_map, node_t, ht_ent, node_id_hash, node_id_eq, + 0.6, malloc, realloc, free); + +/** The global nodelist. */ +static nodelist_t *the_nodelist=NULL; + +/** Create an empty nodelist if we haven't done so already. */ +static void +init_nodelist(void) +{ + if (PREDICT_UNLIKELY(the_nodelist == NULL)) { + the_nodelist = tor_malloc_zero(sizeof(nodelist_t)); + HT_INIT(nodelist_map, &the_nodelist->nodes_by_id); + the_nodelist->nodes = smartlist_create(); + } +} + +/** As node_get_by_id, but returns a non-const pointer */ +node_t * +node_get_mutable_by_id(const char *identity_digest) +{ + node_t search, *node; + if (PREDICT_UNLIKELY(the_nodelist == NULL)) + return NULL; + + memcpy(&search.identity, identity_digest, DIGEST_LEN); + node = HT_FIND(nodelist_map, &the_nodelist->nodes_by_id, &search); + return node; +} + +/** Return the node_t whose identity is <b>identity_digest</b>, or NULL + * if no such node exists. */ +const node_t * +node_get_by_id(const char *identity_digest) +{ + return node_get_mutable_by_id(identity_digest); +} + +/** Internal: return the node_t whose identity_digest is + * <b>identity_digest</b>. If none exists, create a new one, add it to the + * nodelist, and return it. + * + * Requires that the nodelist be initialized. + */ +static node_t * +node_get_or_create(const char *identity_digest) +{ + node_t *node; + + if ((node = node_get_mutable_by_id(identity_digest))) + return node; + + node = tor_malloc_zero(sizeof(node_t)); + memcpy(node->identity, identity_digest, DIGEST_LEN); + HT_INSERT(nodelist_map, &the_nodelist->nodes_by_id, node); + + smartlist_add(the_nodelist->nodes, node); + node->nodelist_idx = smartlist_len(the_nodelist->nodes) - 1; + + node->country = -1; + + return node; +} + +/** Add <b>ri</b> to the nodelist. */ +node_t * +nodelist_add_routerinfo(routerinfo_t *ri) +{ + node_t *node; + init_nodelist(); + node = node_get_or_create(ri->cache_info.identity_digest); + node->ri = ri; + + if (node->country == -1) + node_set_country(node); + + if (authdir_mode(get_options())) { + const char *discard=NULL; + uint32_t status = dirserv_router_get_status(ri, &discard); + dirserv_set_node_flags_from_authoritative_status(node, status); + } + + return node; +} + +/** Set the appropriate node_t to use <b>md</b> as its microdescriptor. + * + * Called when a new microdesc has arrived and the usable consensus flavor + * is "microdesc". + **/ +node_t * +nodelist_add_microdesc(microdesc_t *md) +{ + networkstatus_t *ns = + networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC); + const routerstatus_t *rs; + node_t *node; + if (ns == NULL) + return NULL; + init_nodelist(); + + /* Microdescriptors don't carry an identity digest, so we need to figure + * it out by looking up the routerstatus. */ + rs = router_get_consensus_status_by_descriptor_digest(ns, md->digest); + if (rs == NULL) + return NULL; + node = node_get_mutable_by_id(rs->identity_digest); + if (node) { + if (node->md) + node->md->held_by_nodes--; + node->md = md; + md->held_by_nodes++; + } + return node; +} + +/** Tell the nodelist that the current usable consensus to <b>ns</b>. + * This makes the nodelist change all of the routerstatus entries for + * the nodes, drop nodes that no longer have enough info to get used, + * and grab microdescriptors into nodes as appropriate. + */ +void +nodelist_set_consensus(networkstatus_t *ns) +{ + const or_options_t *options = get_options(); + int authdir = authdir_mode_v2(options) || authdir_mode_v3(options); + + init_nodelist(); + if (ns->flavor == FLAV_MICRODESC) + (void) get_microdesc_cache(); /* Make sure it exists first. */ + + SMARTLIST_FOREACH(the_nodelist->nodes, node_t *, node, + node->rs = NULL); + + SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) { + node_t *node = node_get_or_create(rs->identity_digest); + node->rs = rs; + if (ns->flavor == FLAV_MICRODESC) { + if (node->md == NULL || + tor_memneq(node->md->digest,rs->descriptor_digest,DIGEST256_LEN)) { + if (node->md) + node->md->held_by_nodes--; + node->md = microdesc_cache_lookup_by_digest256(NULL, + rs->descriptor_digest); + if (node->md) + node->md->held_by_nodes++; + } + } + + node_set_country(node); + + /* If we're not an authdir, believe others. */ + if (!authdir) { + node->is_valid = rs->is_valid; + node->is_running = rs->is_flagged_running; + node->is_fast = rs->is_fast; + node->is_stable = rs->is_stable; + node->is_possible_guard = rs->is_possible_guard; + node->is_exit = rs->is_exit; + node->is_bad_directory = rs->is_bad_directory; + node->is_bad_exit = rs->is_bad_exit; + node->is_hs_dir = rs->is_hs_dir; + } + + } SMARTLIST_FOREACH_END(rs); + + nodelist_purge(); + + if (! authdir) { + SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) { + /* We have no routerstatus for this router. Clear flags so we can skip + * it, maybe.*/ + if (!node->rs) { + tor_assert(node->ri); /* if it had only an md, or nothing, purge + * would have removed it. */ + if (node->ri->purpose == ROUTER_PURPOSE_GENERAL) { + /* Clear all flags. */ + node->is_valid = node->is_running = node->is_hs_dir = + node->is_fast = node->is_stable = + node->is_possible_guard = node->is_exit = + node->is_bad_exit = node->is_bad_directory = 0; + } + } + } SMARTLIST_FOREACH_END(node); + } +} + +/** Helper: return true iff a node has a usable amount of information*/ +static INLINE int +node_is_usable(const node_t *node) +{ + return (node->rs) || (node->ri); +} + +/** Tell the nodelist that <b>md</b> is no longer a microdescriptor for the + * node with <b>identity_digest</b>. */ +void +nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md) +{ + node_t *node = node_get_mutable_by_id(identity_digest); + if (node && node->md == md) { + node->md = NULL; + md->held_by_nodes--; + } +} + +/** Tell the nodelist that <b>ri</b> is no longer in the routerlist. */ +void +nodelist_remove_routerinfo(routerinfo_t *ri) +{ + node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest); + if (node && node->ri == ri) { + node->ri = NULL; + if (! node_is_usable(node)) { + nodelist_drop_node(node, 1); + node_free(node); + } + } +} + +/** Remove <b>node</b> from the nodelist. (Asserts that it was there to begin + * with.) */ +static void +nodelist_drop_node(node_t *node, int remove_from_ht) +{ + node_t *tmp; + int idx; + if (remove_from_ht) { + tmp = HT_REMOVE(nodelist_map, &the_nodelist->nodes_by_id, node); + tor_assert(tmp == node); + } + + idx = node->nodelist_idx; + tor_assert(idx >= 0); + + tor_assert(node == smartlist_get(the_nodelist->nodes, idx)); + smartlist_del(the_nodelist->nodes, idx); + if (idx < smartlist_len(the_nodelist->nodes)) { + tmp = smartlist_get(the_nodelist->nodes, idx); + tmp->nodelist_idx = idx; + } + node->nodelist_idx = -1; +} + +/** Release storage held by <b>node</b> */ +static void +node_free(node_t *node) +{ + if (!node) + return; + if (node->md) + node->md->held_by_nodes--; + tor_assert(node->nodelist_idx == -1); + tor_free(node); +} + +/** Remove all entries from the nodelist that don't have enough info to be + * usable for anything. */ +void +nodelist_purge(void) +{ + node_t **iter; + if (PREDICT_UNLIKELY(the_nodelist == NULL)) + return; + + /* Remove the non-usable nodes. */ + for (iter = HT_START(nodelist_map, &the_nodelist->nodes_by_id); iter; ) { + node_t *node = *iter; + + if (node->md && !node->rs) { + /* An md is only useful if there is an rs. */ + node->md->held_by_nodes--; + node->md = NULL; + } + + if (node_is_usable(node)) { + iter = HT_NEXT(nodelist_map, &the_nodelist->nodes_by_id, iter); + } else { + iter = HT_NEXT_RMV(nodelist_map, &the_nodelist->nodes_by_id, iter); + nodelist_drop_node(node, 0); + node_free(node); + } + } + nodelist_assert_ok(); +} + +/** Release all storage held by the nodelist. */ +void +nodelist_free_all(void) +{ + if (PREDICT_UNLIKELY(the_nodelist == NULL)) + return; + + HT_CLEAR(nodelist_map, &the_nodelist->nodes_by_id); + SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) { + node->nodelist_idx = -1; + node_free(node); + } SMARTLIST_FOREACH_END(node); + + smartlist_free(the_nodelist->nodes); + + tor_free(the_nodelist); +} + +/** Check that the nodelist is internally consistent, and consistent with + * the directory info it's derived from. + */ +void +nodelist_assert_ok(void) +{ + routerlist_t *rl = router_get_routerlist(); + networkstatus_t *ns = networkstatus_get_latest_consensus(); + digestmap_t *dm; + + if (!the_nodelist) + return; + + dm = digestmap_new(); + + /* every routerinfo in rl->routers should be in the nodelist. */ + if (rl) { + SMARTLIST_FOREACH_BEGIN(rl->routers, routerinfo_t *, ri) { + const node_t *node = node_get_by_id(ri->cache_info.identity_digest); + tor_assert(node && node->ri == ri); + tor_assert(fast_memeq(ri->cache_info.identity_digest, + node->identity, DIGEST_LEN)); + tor_assert(! digestmap_get(dm, node->identity)); + digestmap_set(dm, node->identity, (void*)node); + } SMARTLIST_FOREACH_END(ri); + } + + /* every routerstatus in ns should be in the nodelist */ + if (ns) { + SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) { + const node_t *node = node_get_by_id(rs->identity_digest); + tor_assert(node && node->rs == rs); + tor_assert(fast_memeq(rs->identity_digest, node->identity, DIGEST_LEN)); + digestmap_set(dm, node->identity, (void*)node); + if (ns->flavor == FLAV_MICRODESC) { + /* If it's a microdesc consensus, every entry that has a + * microdescriptor should be in the nodelist. + */ + microdesc_t *md = + microdesc_cache_lookup_by_digest256(NULL, rs->descriptor_digest); + tor_assert(md == node->md); + if (md) + tor_assert(md->held_by_nodes >= 1); + } + } SMARTLIST_FOREACH_END(rs); + } + + /* The nodelist should have no other entries, and its entries should be + * well-formed. */ + SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) { + tor_assert(digestmap_get(dm, node->identity) != NULL); + tor_assert(node_sl_idx == node->nodelist_idx); + } SMARTLIST_FOREACH_END(node); + + tor_assert((long)smartlist_len(the_nodelist->nodes) == + (long)HT_SIZE(&the_nodelist->nodes_by_id)); + + digestmap_free(dm, NULL); +} + +/** Return a list of a node_t * for every node we know about. The caller + * MUST NOT modify the list. (You can set and clear flags in the nodes if + * you must, but you must not add or remove nodes.) */ +smartlist_t * +nodelist_get_list(void) +{ + init_nodelist(); + return the_nodelist->nodes; +} + +/** Given a hex-encoded nickname of the format DIGEST, $DIGEST, $DIGEST=name, + * or $DIGEST~name, return the node with the matching identity digest and + * nickname (if any). Return NULL if no such node exists, or if <b>hex_id</b> + * is not well-formed. */ +const node_t * +node_get_by_hex_id(const char *hex_id) +{ + char digest_buf[DIGEST_LEN]; + char nn_buf[MAX_NICKNAME_LEN+1]; + char nn_char='\0'; + + if (hex_digest_nickname_decode(hex_id, digest_buf, &nn_char, nn_buf)==0) { + const node_t *node = node_get_by_id(digest_buf); + if (!node) + return NULL; + if (nn_char) { + const char *real_name = node_get_nickname(node); + if (!real_name || strcasecmp(real_name, nn_buf)) + return NULL; + if (nn_char == '=') { + const char *named_id = + networkstatus_get_router_digest_by_nickname(nn_buf); + if (!named_id || tor_memneq(named_id, digest_buf, DIGEST_LEN)) + return NULL; + } + } + return node; + } + + return NULL; +} + +/** Given a nickname (possibly verbose, possibly a hexadecimal digest), return + * the corresponding node_t, or NULL if none exists. Warn the user if + * <b>warn_if_unnamed</b> is set, and they have specified a router by + * nickname, but the Named flag isn't set for that router. */ +const node_t * +node_get_by_nickname(const char *nickname, int warn_if_unnamed) +{ + const node_t *node; + if (!the_nodelist) + return NULL; + + /* Handle these cases: DIGEST, $DIGEST, $DIGEST=name, $DIGEST~name. */ + if ((node = node_get_by_hex_id(nickname)) != NULL) + return node; + + if (!strcasecmp(nickname, UNNAMED_ROUTER_NICKNAME)) + return NULL; + + /* Okay, so if we get here, the nickname is just a nickname. Is there + * a binding for it in the consensus? */ + { + const char *named_id = + networkstatus_get_router_digest_by_nickname(nickname); + if (named_id) + return node_get_by_id(named_id); + } + + /* Is it marked as owned-by-someone-else? */ + if (networkstatus_nickname_is_unnamed(nickname)) { + log_info(LD_GENERAL, "The name %s is listed as Unnamed: there is some " + "router that holds it, but not one listed in the current " + "consensus.", escaped(nickname)); + return NULL; + } + + /* Okay, so the name is not canonical for anybody. */ + { + smartlist_t *matches = smartlist_create(); + const node_t *choice = NULL; + + SMARTLIST_FOREACH_BEGIN(the_nodelist->nodes, node_t *, node) { + if (!strcasecmp(node_get_nickname(node), nickname)) + smartlist_add(matches, node); + } SMARTLIST_FOREACH_END(node); + + if (smartlist_len(matches)>1 && warn_if_unnamed) { + int any_unwarned = 0; + SMARTLIST_FOREACH_BEGIN(matches, node_t *, node) { + if (!node->name_lookup_warned) { + node->name_lookup_warned = 1; + any_unwarned = 1; + } + } SMARTLIST_FOREACH_END(node); + + if (any_unwarned) { + log_warn(LD_CONFIG, "There are multiple matches for the name %s, " + "but none is listed as Named in the directory consensus. " + "Choosing one arbitrarily.", nickname); + } + } else if (smartlist_len(matches)>1 && warn_if_unnamed) { + char fp[HEX_DIGEST_LEN+1]; + node_t *node = smartlist_get(matches, 0); + if (node->name_lookup_warned) { + base16_encode(fp, sizeof(fp), node->identity, DIGEST_LEN); + log_warn(LD_CONFIG, + "You specified a server \"%s\" by name, but the directory " + "authorities do not have any key registered for this " + "nickname -- so it could be used by any server, not just " + "the one you meant. " + "To make sure you get the same server in the future, refer " + "to it by key, as \"$%s\".", nickname, fp); + node->name_lookup_warned = 1; + } + } + + if (smartlist_len(matches)) + choice = smartlist_get(matches, 0); + + smartlist_free(matches); + return choice; + } +} + +/** Return the nickname of <b>node</b>, or NULL if we can't find one. */ +const char * +node_get_nickname(const node_t *node) +{ + tor_assert(node); + if (node->rs) + return node->rs->nickname; + else if (node->ri) + return node->ri->nickname; + else + return NULL; +} + +/** Return true iff the nickname of <b>node</b> is canonical, based on the + * latest consensus. */ +int +node_is_named(const node_t *node) +{ + const char *named_id; + const char *nickname = node_get_nickname(node); + if (!nickname) + return 0; + named_id = networkstatus_get_router_digest_by_nickname(nickname); + if (!named_id) + return 0; + return tor_memeq(named_id, node->identity, DIGEST_LEN); +} + +/** Return true iff <b>node</b> appears to be a directory authority or + * directory cache */ +int +node_is_dir(const node_t *node) +{ + if (node->rs) + return node->rs->dir_port != 0; + else if (node->ri) + return node->ri->dir_port != 0; + else + return 0; +} + +/** Return true iff <b>node</b> has either kind of usable descriptor -- that + * is, a routerdecriptor or a microdescriptor. */ +int +node_has_descriptor(const node_t *node) +{ + return (node->ri || + (node->rs && node->md)); +} + +/** Return the router_purpose of <b>node</b>. */ +int +node_get_purpose(const node_t *node) +{ + if (node->ri) + return node->ri->purpose; + else + return ROUTER_PURPOSE_GENERAL; +} + +/** Compute the verbose ("extended") nickname of <b>node</b> and store it + * into the MAX_VERBOSE_NICKNAME_LEN+1 character buffer at + * <b>verbose_nickname_out</b> */ +void +node_get_verbose_nickname(const node_t *node, + char *verbose_name_out) +{ + const char *nickname = node_get_nickname(node); + int is_named = node_is_named(node); + verbose_name_out[0] = '$'; + base16_encode(verbose_name_out+1, HEX_DIGEST_LEN+1, node->identity, + DIGEST_LEN); + if (!nickname) + return; + verbose_name_out[1+HEX_DIGEST_LEN] = is_named ? '=' : '~'; + strlcpy(verbose_name_out+1+HEX_DIGEST_LEN+1, nickname, MAX_NICKNAME_LEN+1); +} + +/** Return true iff it seems that <b>node</b> allows circuits to exit + * through it directlry from the client. */ +int +node_allows_single_hop_exits(const node_t *node) +{ + if (node && node->ri) + return node->ri->allow_single_hop_exits; + else + return 0; +} + +/** Return true iff it seems that <b>node</b> has an exit policy that doesn't + * actually permit anything to exit, or we don't know its exit policy */ +int +node_exit_policy_rejects_all(const node_t *node) +{ + if (node->rejects_all) + return 1; + + if (node->ri) + return node->ri->policy_is_reject_star; + else if (node->md) + return node->md->exit_policy == NULL || + short_policy_is_reject_star(node->md->exit_policy); + else + return 1; +} + +/** Copy the address for <b>node</b> into *<b>addr_out</b>. */ +int +node_get_addr(const node_t *node, tor_addr_t *addr_out) +{ + if (node->ri) { + tor_addr_from_ipv4h(addr_out, node->ri->addr); + return 0; + } else if (node->rs) { + tor_addr_from_ipv4h(addr_out, node->rs->addr); + return 0; + } + return -1; +} + +/** Return the host-order IPv4 address for <b>node</b>, or 0 if it doesn't + * seem to have one. */ +uint32_t +node_get_addr_ipv4h(const node_t *node) +{ + if (node->ri) { + return node->ri->addr; + } else if (node->rs) { + return node->rs->addr; + } + return 0; +} + +/** Copy a string representation of the IP address for <b>node</b> into the + * <b>len</b>-byte buffer at <b>buf</b>. + */ +void +node_get_address_string(const node_t *node, char *buf, size_t len) +{ + if (node->ri) { + strlcpy(buf, node->ri->address, len); + } else if (node->rs) { + tor_addr_t addr; + tor_addr_from_ipv4h(&addr, node->rs->addr); + tor_addr_to_str(buf, &addr, len, 0); + } else { + buf[0] = '\0'; + } +} + +/** Return <b>node</b>'s declared uptime, or -1 if it doesn't seem to have + * one. */ +long +node_get_declared_uptime(const node_t *node) +{ + if (node->ri) + return node->ri->uptime; + else + return -1; +} + +/** Return <b>node</b>'s declared or_port */ +uint16_t +node_get_orport(const node_t *node) +{ + if (node->ri) + return node->ri->or_port; + else if (node->rs) + return node->rs->or_port; + else + return 0; +} + +/** Return <b>node</b>'s platform string, or NULL if we don't know it. */ +const char * +node_get_platform(const node_t *node) +{ + /* If we wanted, we could record the version in the routerstatus_t, since + * the consensus lists it. We don't, though, so this function just won't + * work with microdescriptors. */ + if (node->ri) + return node->ri->platform; + else + return NULL; +} + +/** Return <b>node</b>'s time of publication, or 0 if we don't have one. */ +time_t +node_get_published_on(const node_t *node) +{ + if (node->ri) + return node->ri->cache_info.published_on; + else + return 0; +} + +/** Return true iff <b>node</b> is one representing this router. */ +int +node_is_me(const node_t *node) +{ + return router_digest_is_me(node->identity); +} + +/** Return <b>node</b> declared family (as a list of names), or NULL if + * the node didn't declare a family. */ +const smartlist_t * +node_get_declared_family(const node_t *node) +{ + if (node->ri && node->ri->declared_family) + return node->ri->declared_family; + else if (node->md && node->md->family) + return node->md->family; + else + return NULL; +} + diff --git a/src/or/nodelist.h b/src/or/nodelist.h new file mode 100644 index 0000000000..bd2e63953c --- /dev/null +++ b/src/or/nodelist.h @@ -0,0 +1,60 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2011, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file microdesc.h + * \brief Header file for microdesc.c. + **/ + +#ifndef _TOR_NODELIST_H +#define _TOR_NODELIST_H + +node_t *node_get_mutable_by_id(const char *identity_digest); +const node_t *node_get_by_id(const char *identity_digest); +const node_t *node_get_by_hex_id(const char *identity_digest); +node_t *nodelist_add_routerinfo(routerinfo_t *ri); +node_t *nodelist_add_microdesc(microdesc_t *md); +void nodelist_set_consensus(networkstatus_t *ns); + +void nodelist_remove_microdesc(const char *identity_digest, microdesc_t *md); +void nodelist_remove_routerinfo(routerinfo_t *ri); +void nodelist_purge(void); + +void nodelist_free_all(void); +void nodelist_assert_ok(void); + +const node_t *node_get_by_nickname(const char *nickname, int warn_if_unnamed); +void node_get_verbose_nickname(const node_t *node, + char *verbose_name_out); +int node_is_named(const node_t *node); +int node_is_dir(const node_t *node); +int node_has_descriptor(const node_t *node); +int node_get_purpose(const node_t *node); +#define node_is_bridge(node) \ + (node_get_purpose((node)) == ROUTER_PURPOSE_BRIDGE) +int node_is_me(const node_t *node); +int node_exit_policy_rejects_all(const node_t *node); +int node_get_addr(const node_t *node, tor_addr_t *addr_out); +uint32_t node_get_addr_ipv4h(const node_t *node); +int node_allows_single_hop_exits(const node_t *node); +uint16_t node_get_orport(const node_t *node); +const char *node_get_nickname(const node_t *node); +const char *node_get_platform(const node_t *node); +void node_get_address_string(const node_t *node, char *cp, size_t len); +long node_get_declared_uptime(const node_t *node); +time_t node_get_published_on(const node_t *node); +const smartlist_t *node_get_declared_family(const node_t *node); + +smartlist_t *nodelist_get_list(void); + +/* XXXX These need to move out of routerlist.c */ +void nodelist_refresh_countries(void); +void node_set_country(node_t *node); +void nodelist_add_node_and_family(smartlist_t *nodes, const node_t *node); +int nodes_in_same_family(const node_t *node1, const node_t *node2); + +#endif + diff --git a/src/or/ntmain.c b/src/or/ntmain.c index b2fee648cc..8d03ea8087 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. */ @@ -728,6 +727,7 @@ nt_service_parse_options(int argc, char **argv, int *should_exit) if ((argc >= 3) && (!strcmp(argv[1], "-service") || !strcmp(argv[1], "--service"))) { nt_service_loadlibrary(); + *should_exit = 1; if (!strcmp(argv[2], "install")) return nt_service_install(argc, argv); if (!strcmp(argv[2], "remove")) @@ -737,7 +737,6 @@ nt_service_parse_options(int argc, char **argv, int *should_exit) if (!strcmp(argv[2], "stop")) return nt_service_cmd_stop(); printf("Unrecognized service command '%s'\n", argv[2]); - *should_exit = 1; return 1; } if (argc >= 2) { diff --git a/src/or/or.h b/src/or/or.h index 3510ab0421..9d6f605024 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -23,8 +23,12 @@ #endif #ifdef MS_WINDOWS +#ifndef WIN32_WINNT #define WIN32_WINNT 0x400 +#endif +#ifndef _WIN32_WINNT #define _WIN32_WINNT 0x400 +#endif #define WIN32_LEAN_AND_MEAN #endif @@ -83,6 +87,13 @@ #define snprintf _snprintf #endif +#ifdef USE_BUFFEREVENTS +#include <event2/bufferevent.h> +#include <event2/buffer.h> +#include <event2/util.h> +#endif + +#include "crypto.h" #include "tortls.h" #include "../common/torlog.h" #include "container.h" @@ -225,15 +236,30 @@ typedef enum { #define PROXY_CONNECT 1 #define PROXY_SOCKS4 2 #define PROXY_SOCKS5 3 +/* !!!! If there is ever a PROXY_* type over 2, we must grow the proxy_type + * field in or_connection_t */ +/* pluggable transports proxy type */ +#define PROXY_PLUGGABLE 4 /* Proxy client handshake states */ -#define PROXY_HTTPS_WANT_CONNECT_OK 1 -#define PROXY_SOCKS4_WANT_CONNECT_OK 2 -#define PROXY_SOCKS5_WANT_AUTH_METHOD_NONE 3 -#define PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929 4 -#define PROXY_SOCKS5_WANT_AUTH_RFC1929_OK 5 -#define PROXY_SOCKS5_WANT_CONNECT_OK 6 -#define PROXY_CONNECTED 7 +/* We use a proxy but we haven't even connected to it yet. */ +#define PROXY_INFANT 1 +/* We use an HTTP proxy and we've sent the CONNECT command. */ +#define PROXY_HTTPS_WANT_CONNECT_OK 2 +/* We use a SOCKS4 proxy and we've sent the CONNECT command. */ +#define PROXY_SOCKS4_WANT_CONNECT_OK 3 +/* We use a SOCKS5 proxy and we try to negotiate without + any authentication . */ +#define PROXY_SOCKS5_WANT_AUTH_METHOD_NONE 4 +/* We use a SOCKS5 proxy and we try to negotiate with + Username/Password authentication . */ +#define PROXY_SOCKS5_WANT_AUTH_METHOD_RFC1929 5 +/* We use a SOCKS5 proxy and we just sent our credentials. */ +#define PROXY_SOCKS5_WANT_AUTH_RFC1929_OK 6 +/* We use a SOCKS5 proxy and we just sent our CONNECT command. */ +#define PROXY_SOCKS5_WANT_CONNECT_OK 7 +/* We use a proxy and we CONNECTed successfully!. */ +#define PROXY_CONNECTED 8 /** True iff <b>x</b> is an edge connection. */ #define CONN_IS_EDGE(x) \ @@ -257,22 +283,27 @@ typedef enum { #define OR_CONN_STATE_CONNECTING 1 /** State for a connection to an OR: waiting for proxy handshake to complete */ #define OR_CONN_STATE_PROXY_HANDSHAKING 2 -/** State for a connection to an OR or client: SSL is handshaking, not done +/** State for an OR connection client: SSL is handshaking, not done * yet. */ #define OR_CONN_STATE_TLS_HANDSHAKING 3 /** State for a connection to an OR: We're doing a second SSL handshake for - * renegotiation purposes. */ + * renegotiation purposes. (V2 handshake only.) */ #define OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING 4 /** State for a connection at an OR: We're waiting for the client to - * renegotiate. */ + * renegotiate (to indicate a v2 handshake) or send a versions cell (to + * indicate a v3 handshake) */ #define OR_CONN_STATE_TLS_SERVER_RENEGOTIATING 5 -/** State for a connection to an OR: We're done with our SSL handshake, but we - * haven't yet negotiated link protocol versions and sent a netinfo cell. - */ -#define OR_CONN_STATE_OR_HANDSHAKING 6 -/** State for a connection to an OR: Ready to send/receive cells. */ -#define OR_CONN_STATE_OPEN 7 -#define _OR_CONN_STATE_MAX 7 +/** State for an OR connection: We're done with our SSL handshake, we've done + * renegotiation, but we haven't yet negotiated link protocol versions and + * sent a netinfo cell. */ +#define OR_CONN_STATE_OR_HANDSHAKING_V2 6 +/** State for an OR connection: We're done with our SSL handshake, but we + * haven't yet negotiated link protocol versions, done a V3 handshake, and + * sent a netinfo cell. */ +#define OR_CONN_STATE_OR_HANDSHAKING_V3 7 +/** State for an OR connection: Ready to send/receive cells. */ +#define OR_CONN_STATE_OPEN 8 +#define _OR_CONN_STATE_MAX 8 #define _EXIT_CONN_STATE_MIN 1 /** State for an exit connection: waiting for response from DNS farm. */ @@ -386,7 +417,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. */ @@ -792,9 +825,10 @@ typedef enum { #define CELL_NETINFO 8 #define CELL_RELAY_EARLY 9 -/** True iff the cell command <b>x</b> is one that implies a variable-length - * cell. */ -#define CELL_COMMAND_IS_VAR_LENGTH(x) ((x) == CELL_VERSIONS) +#define CELL_VPADDING 128 +#define CELL_CERTS 129 +#define CELL_AUTH_CHALLENGE 130 +#define CELL_AUTHENTICATE 131 /** How long to test reachability before complaining to the user. */ #define TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT (20*60) @@ -807,6 +841,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 @@ -857,7 +894,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. */ @@ -901,14 +938,21 @@ typedef struct { typedef struct buf_t buf_t; typedef struct socks_request_t socks_request_t; +#ifdef USE_BUFFEREVENTS +#define generic_buffer_t struct evbuffer +#else +#define generic_buffer_t buf_t +#endif /* Values for connection_t.magic: used to make sure that downcasts (casts from * connection_t to foo_connection_t) are safe. */ #define BASE_CONNECTION_MAGIC 0x7C3C304Eu #define OR_CONNECTION_MAGIC 0x7D31FF03u #define EDGE_CONNECTION_MAGIC 0xF0374013u +#define ENTRY_CONNECTION_MAGIC 0xbb4a5703 #define DIR_CONNECTION_MAGIC 0x9988ffeeu #define CONTROL_CONNECTION_MAGIC 0x8abc765du +#define LISTENER_CONNECTION_MAGIC 0x1a1ac741u /** Description of a connection to another host or process, and associated * data. @@ -974,6 +1018,7 @@ typedef struct connection_t { /** Our socket; -1 if this connection is closed, or has no socket. */ tor_socket_t s; int conn_array_index; /**< Index into the global connection array. */ + struct event *read_event; /**< Libevent event structure. */ struct event *write_event; /**< Libevent event structure. */ buf_t *inbuf; /**< Buffer holding data read over this connection. */ @@ -984,6 +1029,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 */ @@ -1008,17 +1058,73 @@ typedef struct connection_t { /** Unique identifier for this connection on this Tor instance. */ uint64_t global_identifier; - /* XXXX023 move this field, and all the listener-only fields (just - socket_family, I think), into a new listener_connection_t subtype. */ + /** Unique ID for measuring tunneled network status requests. */ + uint64_t dirreq_id; +} connection_t; + +typedef struct listener_connection_t { + connection_t _base; + /** If the connection is a CONN_TYPE_AP_DNS_LISTENER, this field points * to the evdns_server_port it uses to listen to and answer connections. */ struct evdns_server_port *dns_server_port; - /** Unique ID for measuring tunneled network status requests. */ - uint64_t dirreq_id; -} connection_t; + /** @name Isolation parameters + * + * For an AP listener, these fields describe how to isolate streams that + * arrive on the listener. + * + * @{ + */ + /** The session group for this listener. */ + int session_group; + /** One or more ISO_ flags to describe how to isolate streams. */ + uint8_t isolation_flags; + /**@}*/ + +} listener_connection_t; + +/** Minimum length of the random part of an AUTH_CHALLENGE cell. */ +#define OR_AUTH_CHALLENGE_LEN 32 -/** Stores flags and information related to the portion of a v2 Tor OR +/** + * @name Certificate types for CERTS cells. + * + * These values are defined by the protocol, and affect how an X509 + * certificate in a CERTS cell is interpreted and used. + * + * @{ */ +/** A certificate that authenticates a TLS link key. The subject key + * must match the key used in the TLS handshake; it must be signed by + * the identity key. */ +#define OR_CERT_TYPE_TLS_LINK 1 +/** A self-signed identity certificate. The subject key must be a + * 1024-bit RSA key. */ +#define OR_CERT_TYPE_ID_1024 2 +/** A certificate that authenticates a key used in an AUTHENTICATE cell + * in the v3 handshake. The subject key must be a 1024-bit RSA key; it + * must be signed by the identity key */ +#define OR_CERT_TYPE_AUTH_1024 3 +/**@}*/ + +/** The one currently supported type of AUTHENTICATE cell. It contains + * a bunch of structures signed with an RSA1024 key. The signed + * structures include a HMAC using negotiated TLS secrets, and a digest + * of all cells sent or received before the AUTHENTICATE cell (including + * the random server-generated AUTH_CHALLENGE cell). + */ +#define AUTHTYPE_RSA_SHA256_TLSSECRET 1 + +/** The length of the part of the AUTHENTICATE cell body that the client and + * server can generate independently (when using RSA_SHA256_TLSSECRET). It + * contains everything except the client's timestamp, the client's randomly + * generated nonce, and the signature. */ +#define V3_AUTH_FIXED_PART_LEN (8+(32*6)) +/** The length of the part of the AUTHENTICATE cell body that the client + * signs. */ +#define V3_AUTH_BODY_LEN (V3_AUTH_FIXED_PART_LEN + 8 + 16) + +/** Stores flags and information related to the portion of a v2/v3 Tor OR * connection handshake that happens after the TLS handshake is finished. */ typedef struct or_handshake_state_t { @@ -1029,6 +1135,52 @@ typedef struct or_handshake_state_t { unsigned int started_here : 1; /** True iff we have received and processed a VERSIONS cell. */ unsigned int received_versions : 1; + /** True iff we have received and processed an AUTH_CHALLENGE cell */ + unsigned int received_auth_challenge : 1; + /** True iff we have received and processed a CERTS cell. */ + unsigned int received_certs_cell : 1; + /** True iff we have received and processed an AUTHENTICATE cell */ + unsigned int received_authenticate : 1; + + /* True iff we've received valid authentication to some identity. */ + unsigned int authenticated : 1; + + /** True iff we should feed outgoing cells into digest_sent and + * digest_received respectively. + * + * From the server's side of the v3 handshake, we want to capture everything + * from the VERSIONS cell through and including the AUTH_CHALLENGE cell. + * From the client's, we want to capture everything from the VERSIONS cell + * through but *not* including the AUTHENTICATE cell. + * + * @{ */ + unsigned int digest_sent_data : 1; + unsigned int digest_received_data : 1; + /**@}*/ + + /** Identity digest that we have received and authenticated for our peer + * on this connection. */ + uint8_t authenticated_peer_id[DIGEST_LEN]; + + /** Digests of the cells that we have sent or received as part of a V3 + * handshake. Used for making and checking AUTHENTICATE cells. + * + * @{ + */ + crypto_digest_env_t *digest_sent; + crypto_digest_env_t *digest_received; + /** @} */ + + /** Certificates that a connection initiator sent us in a CERTS cell; we're + * holding on to them until we get an AUTHENTICATE cell. + * + * @{ + */ + /** The cert for the key that's supposed to sign the AUTHENTICATE cell */ + tor_cert_t *auth_cert; + /** A self-signed identity certificate */ + tor_cert_t *id_cert; + /**@}*/ } or_handshake_state_t; /** Subtype of connection_t for an "OR connection" -- that is, one that speaks @@ -1068,6 +1220,13 @@ typedef struct or_connection_t { * router itself has a problem. */ unsigned int is_bad_for_new_circs:1; + /** True iff we have decided that the other end of this connection + * is a client. Connections with this flag set should never be used + * to satisfy an EXTEND request. */ + unsigned int is_connection_with_client:1; + /** True iff this is an outgoing connection. */ + unsigned int is_outgoing:1; + unsigned int proxy_type:2; /**< One of PROXY_NONE...PROXY_SOCKS5 */ uint8_t link_proto; /**< What protocol version are we using? 0 for * "none negotiated yet." */ circid_t next_circ_id; /**< Which circ_id do we try to use next on @@ -1083,10 +1242,16 @@ typedef struct or_connection_t { /* bandwidth* and *_bucket only used by ORs in OPEN state: */ int bandwidthrate; /**< Bytes/s added to the bucket. (OPEN ORs only.) */ int bandwidthburst; /**< Max bucket size for this conn. (OPEN ORs only.) */ +#ifndef USE_BUFFEREVENTS int read_bucket; /**< When this hits 0, stop receiving. Every second we * add 'bandwidthrate' to this, capping it at * bandwidthburst. (OPEN ORs only) */ int write_bucket; /**< When this hits 0, stop writing. Like read_bucket. */ +#else + /** DOCDOC */ + /* XXXX we could share this among all connections. */ + struct ev_token_bucket_cfg *bucket_cfg; +#endif int n_circuits; /**< How many circuits use this connection as p_conn or * n_conn ? */ @@ -1107,29 +1272,31 @@ typedef struct or_connection_t { unsigned active_circuit_pqueue_last_recalibrated; struct or_connection_t *next_with_same_id; /**< Next connection with same * identity digest as this one. */ + + tor_libevent_action_t *pending_action; } or_connection_t; -/** Subtype of connection_t for an "edge connection" -- that is, a socks (ap) +/** Subtype of connection_t for an "edge connection" -- that is, an entry (ap) * connection, or an exit. */ typedef struct edge_connection_t { connection_t _base; struct edge_connection_t *next_stream; /**< Points to the next stream at this * edge, if any */ - struct crypt_path_t *cpath_layer; /**< A pointer to which node in the circ - * this conn exits at. */ int package_window; /**< How many more relay cells can I send into the * circuit? */ int deliver_window; /**< How many more relay cells can end at me? */ - /** Nickname of planned exit node -- used with .exit support. */ - char *chosen_exit_name; - - socks_request_t *socks_request; /**< SOCKS structure describing request (AP - * only.) */ struct circuit_t *on_circuit; /**< The circuit (if any) that this edge * connection is using. */ + /** A pointer to which node in the circ this conn exits at. Set for AP + * connections and for hidden service exit connections. */ + struct crypt_path_t *cpath_layer; + /** What rendezvous service are we querying for (if an AP) or providing (if + * an exit)? */ + rend_data_t *rend_data; + uint32_t address_ttl; /**< TTL for address-to-addr mapping on exit * connection. Exit connections only. */ @@ -1145,14 +1312,62 @@ typedef struct edge_connection_t { /** Bytes written since last call to control_event_stream_bandwidth_used() */ uint32_t n_written; - /** What rendezvous service are we querying for? (AP only) */ - rend_data_t *rend_data; + /** True iff this connection is for a DNS request only. */ + unsigned int is_dns_request:1; + + unsigned int edge_has_sent_end:1; /**< For debugging; only used on edge + * connections. Set once we've set the stream end, + * and check in connection_about_to_close_connection(). + */ + /** True iff we've blocked reading until the circuit has fewer queued + * cells. */ + unsigned int edge_blocked_on_circ:1; + +} edge_connection_t; + +/** Subtype of edge_connection_t for an "entry connection" -- that is, a SOCKS + * connection, a DNS request, a TransPort connection or a NATD connection */ +typedef struct entry_connection_t { + edge_connection_t _edge; + + /** Nickname of planned exit node -- used with .exit support. */ + char *chosen_exit_name; + + socks_request_t *socks_request; /**< SOCKS structure describing request (AP + * only.) */ + + /* === Isolation related, AP only. === */ + /** AP only: based on which factors do we isolate this stream? */ + uint8_t isolation_flags; + /** AP only: what session group is this stream in? */ + int session_group; + /** AP only: The newnym epoch in which we created this connection. */ + unsigned nym_epoch; + /** AP only: The original requested address before we rewrote it. */ + char *original_dest_address; + /* Other fields to isolate on already exist. The ClientAddr is addr. The + ClientProtocol is a combination of type and socks_request-> + socks_version. SocksAuth is socks_request->username/password. + DestAddr is in socks_request->address. */ /** Number of times we've reassigned this application connection to * a new circuit. We keep track because the timeout is longer if we've * already retried several times. */ uint8_t num_socks_retries; + /** For AP connections only: buffer for data that we have sent + * optimistically, which we might need to re-send if we have to + * retry this connection. */ + generic_buffer_t *pending_optimistic_data; + /* For AP connections only: buffer for data that we previously sent + * optimistically which we are currently re-sending as we retry this + * connection. */ + generic_buffer_t *sending_optimistic_data; + + /** If this is a DNSPort connection, this field holds the pending DNS + * request that we're going to try to answer. */ + struct evdns_server_request *dns_server_request; + #define NUM_CIRCUITS_LAUNCHED_THRESHOLD 10 /** Number of times we've launched a circuit to handle this stream. If * it gets too high, that could indicate an inconsistency between our @@ -1160,9 +1375,6 @@ typedef struct edge_connection_t { * stream to one of the available circuits" logic. */ unsigned int num_circuits_launched:4; - /** True iff this connection is for a DNS request only. */ - unsigned int is_dns_request:1; - /** True iff this stream must attach to a one-hop circuit (e.g. for * begin_dir). */ unsigned int want_onehop:1; @@ -1170,13 +1382,6 @@ typedef struct edge_connection_t { * itself rather than BEGIN (either via onehop or via a whole circuit). */ unsigned int use_begindir:1; - unsigned int edge_has_sent_end:1; /**< For debugging; only used on edge - * connections. Set once we've set the stream end, - * and check in connection_about_to_close_connection(). - */ - /** True iff we've blocked reading until the circuit has fewer queued - * cells. */ - unsigned int edge_blocked_on_circ:1; /** For AP connections only. If 1, and we fail to reach the chosen exit, * stop requiring it. */ unsigned int chosen_exit_optional:1; @@ -1190,19 +1395,26 @@ typedef struct edge_connection_t { * NATd connection */ unsigned int is_transparent_ap:1; - /** If this is a DNSPort connection, this field holds the pending DNS - * request that we're going to try to answer. */ - struct evdns_server_request *dns_server_request; + /** For AP connections only: Set if this connection's target exit node + * allows optimistic data (that is, data sent on this stream before + * the exit has sent a CONNECTED cell) and we have chosen to use it. + */ + unsigned int may_use_optimistic_data : 1; -} edge_connection_t; +} entry_connection_t; /** Subtype of connection_t for an "directory connection" -- that is, an HTTP * connection to retrieve or serve directory material. */ typedef struct dir_connection_t { connection_t _base; - char *requested_resource; /**< Which 'resource' did we ask the directory - * for? */ + /** Which 'resource' did we ask the directory for? This is typically the part + * of the URL string that defines, relative to the directory conn purpose, + * what thing we want. For example, in router descriptor downloads by + * descriptor digest, it contains "d/", then one ore more +-separated + * fingerprints. + **/ + char *requested_resource; unsigned int dirconn_direct:1; /**< Is this dirconn direct, or via Tor? */ /* Used only for server sides of some dir connections, to implement @@ -1262,6 +1474,11 @@ typedef struct control_connection_t { /** Helper macro: Given a pointer to to._base, of type from*, return &to. */ #define DOWNCAST(to, ptr) ((to*)SUBTYPE_P(ptr, to, _base)) +/** Cast a entry_connection_t subtype pointer to a edge_connection_t **/ +#define ENTRY_TO_EDGE_CONN(c) (&(((c))->_edge)) +/** Cast a entry_connection_t subtype pointer to a connection_t **/ +#define ENTRY_TO_CONN(c) (TO_CONN(ENTRY_TO_EDGE_CONN(c))) + /** Convert a connection_t* to an or_connection_t*; assert if the cast is * invalid. */ static or_connection_t *TO_OR_CONN(connection_t *); @@ -1271,9 +1488,18 @@ static dir_connection_t *TO_DIR_CONN(connection_t *); /** Convert a connection_t* to an edge_connection_t*; assert if the cast is * invalid. */ static edge_connection_t *TO_EDGE_CONN(connection_t *); +/** Convert a connection_t* to an entry_connection_t*; assert if the cast is + * invalid. */ +static entry_connection_t *TO_ENTRY_CONN(connection_t *); +/** Convert a edge_connection_t* to an entry_connection_t*; assert if the cast + * is invalid. */ +static entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *); /** Convert a connection_t* to an control_connection_t*; assert if the cast is * invalid. */ static control_connection_t *TO_CONTROL_CONN(connection_t *); +/** Convert a connection_t* to an listener_connection_t*; assert if the cast is + * invalid. */ +static listener_connection_t *TO_LISTENER_CONN(connection_t *); static INLINE or_connection_t *TO_OR_CONN(connection_t *c) { @@ -1287,14 +1513,75 @@ static INLINE dir_connection_t *TO_DIR_CONN(connection_t *c) } static INLINE edge_connection_t *TO_EDGE_CONN(connection_t *c) { - tor_assert(c->magic == EDGE_CONNECTION_MAGIC); + tor_assert(c->magic == EDGE_CONNECTION_MAGIC || + c->magic == ENTRY_CONNECTION_MAGIC); return DOWNCAST(edge_connection_t, c); } +static INLINE entry_connection_t *TO_ENTRY_CONN(connection_t *c) +{ + tor_assert(c->magic == ENTRY_CONNECTION_MAGIC); + return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, _edge._base); +} +static INLINE entry_connection_t *EDGE_TO_ENTRY_CONN(edge_connection_t *c) +{ + tor_assert(c->_base.magic == ENTRY_CONNECTION_MAGIC); + return (entry_connection_t*) SUBTYPE_P(c, entry_connection_t, _edge); +} static INLINE control_connection_t *TO_CONTROL_CONN(connection_t *c) { tor_assert(c->magic == CONTROL_CONNECTION_MAGIC); return DOWNCAST(control_connection_t, c); } +static INLINE listener_connection_t *TO_LISTENER_CONN(connection_t *c) +{ + tor_assert(c->magic == LISTENER_CONNECTION_MAGIC); + return DOWNCAST(listener_connection_t, c); +} + +/* Conditional macros to help write code that works whether bufferevents are + disabled or not. + + We can't just write: + if (conn->bufev) { + do bufferevent stuff; + } else { + do other stuff; + } + because the bufferevent stuff won't even compile unless we have a fairly + new version of Libevent. Instead, we say: + IF_HAS_BUFFEREVENT(conn, { do_bufferevent_stuff } ); + or: + IF_HAS_BUFFEREVENT(conn, { + do bufferevent stuff; + }) ELSE_IF_NO_BUFFEREVENT { + do non-bufferevent stuff; + } + If we're compiling with bufferevent support, then the macros expand more or + less to: + if (conn->bufev) { + do_bufferevent_stuff; + } else { + do non-bufferevent stuff; + } + and if we aren't using bufferevents, they expand more or less to: + { do non-bufferevent stuff; } +*/ +#ifdef USE_BUFFEREVENTS +#define HAS_BUFFEREVENT(c) (((c)->bufev) != NULL) +#define IF_HAS_BUFFEREVENT(c, stmt) \ + if ((c)->bufev) do { \ + stmt ; \ + } while (0) +#define ELSE_IF_NO_BUFFEREVENT ; else +#define IF_HAS_NO_BUFFEREVENT(c) \ + if (NULL == (c)->bufev) +#else +#define HAS_BUFFEREVENT(c) (0) +#define IF_HAS_BUFFEREVENT(c, stmt) (void)0 +#define ELSE_IF_NO_BUFFEREVENT ; +#define IF_HAS_NO_BUFFEREVENT(c) \ + if (1) +#endif /** What action type does an address policy indicate: accept or reject? */ typedef enum { @@ -1411,11 +1698,6 @@ typedef struct signed_descriptor_t { * networkstatus that listed it. 0 for "never listed in a consensus or * status, so far as we know." */ time_t last_listed_as_valid_until; -#ifdef TRACK_SERVED_TIME - /** The last time we served anybody this descriptor. Used for internal - * testing to see whether we're holding on to descriptors too long. */ - time_t last_served_at; /*XXXX remove if not useful. */ -#endif /* If true, we do not ever try to save this object in the cache. */ unsigned int do_not_cache : 1; /* If true, this item is meant to represent an extrainfo. */ @@ -1459,59 +1741,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. */ @@ -1537,8 +1809,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. */ @@ -1546,7 +1819,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. */ @@ -1577,6 +1854,12 @@ typedef struct routerstatus_t { /** True iff this router is a version that, if it caches directory info, * we can get v3 downloads from. */ unsigned int version_supports_v3_dir:1; + /** True iff this router is a version that, if it caches directory info, + * we can get microdescriptors from. */ + unsigned int version_supports_microdesc_cache:1; + /** True iff this router is a version that allows DATA cells to arrive on + * a stream before it has sent a CONNECTED cell. */ + unsigned int version_supports_optimistic_data:1; unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */ unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */ @@ -1598,15 +1881,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 @@ -1626,6 +1925,11 @@ typedef struct microdesc_t { saved_location_t saved_location : 3; /** If true, do not attempt to cache this microdescriptor on disk. */ unsigned int no_save : 1; + /** If true, this microdesc has an entry in the microdesc_map */ + unsigned int held_in_map : 1; + /** Reference count: how many node_ts have a reference to this microdesc? */ + unsigned int held_by_nodes; + /** If saved_location == SAVED_IN_CACHE, this field holds the offset of the * microdescriptor in the cache. */ off_t off; @@ -1648,15 +1952,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? */ @@ -1770,9 +2142,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) @@ -1942,24 +2311,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 @@ -2032,15 +2410,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? */ @@ -2138,7 +2516,10 @@ typedef struct circuit_t { * length ONIONSKIN_CHALLENGE_LEN. */ char *n_conn_onionskin; - struct timeval timestamp_created; /**< When was the circuit created? */ + /** When was this circuit created? We keep this timestamp with a higher + * resolution than most so that the circuit-build-time tracking code can + * get millisecond resolution. */ + struct timeval timestamp_created; /** When the circuit was first used, or 0 if the circuit is clean. * * XXXX023 Note that some code will artifically adjust this value backward @@ -2236,6 +2617,55 @@ typedef struct origin_circuit_t { /* XXXX NM This can get re-used after 2**32 circuits. */ uint32_t global_identifier; + /** True if we have associated one stream to this circuit, thereby setting + * the isolation paramaters for this circuit. Note that this doesn't + * necessarily mean that we've <em>attached</em> any streams to the circuit: + * we may only have marked up this circuit during the launch process. + */ + unsigned int isolation_values_set : 1; + /** True iff any stream has <em>ever</em> been attached to this circuit. + * + * In a better world we could use timestamp_dirty for this, but + * timestamp_dirty is far too overloaded at the moment. + */ + unsigned int isolation_any_streams_attached : 1; + + /** A bitfield of ISO_* flags for every isolation field such that this + * circuit has had streams with more than one value for that field + * attached to it. */ + uint8_t isolation_flags_mixed; + + /** @name Isolation parameters + * + * If any streams have been associated with this circ (isolation_values_set + * == 1), and all streams associated with the circuit have had the same + * value for some field ((isolation_flags_mixed & ISO_FOO) == 0), then these + * elements hold the value for that field. + * + * Note again that "associated" is not the same as "attached": we + * preliminarily associate streams with a circuit while the circuit is being + * launched, so that we can tell whether we need to launch more circuits. + * + * @{ + */ + uint8_t client_proto_type; + uint8_t client_proto_socksver; + uint16_t dest_port; + tor_addr_t client_addr; + char *dest_address; + int session_group; + unsigned nym_epoch; + size_t socks_username_len; + uint8_t socks_password_len; + /* Note that the next two values are NOT NUL-terminated; see + socks_username_len and socks_password_len for their lengths. */ + char *socks_username; + char *socks_password; + /** Global identifier for the first stream attached here; used by + * ISO_STREAM. */ + uint64_t associated_isolated_stream_global_id; + /**@}*/ + } origin_circuit_t; /** An or_circuit_t holds information needed to implement a circuit at an @@ -2354,11 +2784,79 @@ typedef enum invalid_router_usage_t { #define MIN_CONSTRAINED_TCP_BUFFER 2048 #define MAX_CONSTRAINED_TCP_BUFFER 262144 /* 256k */ +/** @name Isolation flags + + Ways to isolate client streams + + @{ +*/ +/** Isolate based on destination port */ +#define ISO_DESTPORT (1u<<0) +/** Isolate based on destination address */ +#define ISO_DESTADDR (1u<<1) +/** Isolate based on SOCKS authentication */ +#define ISO_SOCKSAUTH (1u<<2) +/** Isolate based on client protocol choice */ +#define ISO_CLIENTPROTO (1u<<3) +/** Isolate based on client address */ +#define ISO_CLIENTADDR (1u<<4) +/** Isolate based on session group (always on). */ +#define ISO_SESSIONGRP (1u<<5) +/** Isolate based on newnym epoch (always on). */ +#define ISO_NYM_EPOCH (1u<<6) +/** Isolate all streams (Internal only). */ +#define ISO_STREAM (1u<<7) +/**@}*/ + +/** Default isolation level for ports. */ +#define ISO_DEFAULT (ISO_CLIENTADDR|ISO_SOCKSAUTH|ISO_SESSIONGRP|ISO_NYM_EPOCH) + +/** Indicates that we haven't yet set a session group on a port_cfg_t. */ +#define SESSION_GROUP_UNSET -1 +/** Session group reserved for directory connections */ +#define SESSION_GROUP_DIRCONN -2 +/** Session group reserved for resolve requests launched by a controller */ +#define SESSION_GROUP_CONTROL_RESOLVE -3 +/** First automatically allocated session group number */ +#define SESSION_GROUP_FIRST_AUTO -4 + +/** Configuration for a single port that we're listening on. */ +typedef struct port_cfg_t { + tor_addr_t addr; /**< The actual IP to listen on, if !is_unix_addr. */ + int port; /**< The configured port, or CFG_AUTO_PORT to tell Tor to pick its + * own port. */ + uint8_t type; /**< One of CONN_TYPE_*_LISTENER */ + unsigned is_unix_addr : 1; /**< True iff this is an AF_UNIX address. */ + + /* Client port types (socks, dns, trans, natd) only: */ + uint8_t isolation_flags; /**< Zero or more isolation flags */ + int session_group; /**< A session group, or -1 if this port is not in a + * session group. */ + + /* Unix sockets only: */ + /** Path for an AF_UNIX address */ + char unix_addr[FLEXIBLE_ARRAY_MEMBER]; +} port_cfg_t; + +/** Ordinary configuration line. */ +#define CONFIG_LINE_NORMAL 0 +/** Appends to previous configuration for the same option, even if we + * would ordinary replace it. */ +#define CONFIG_LINE_APPEND 1 +/* Removes all previous configuration for an option. */ +#define CONFIG_LINE_CLEAR 2 + /** A linked list of lines in a config file. */ typedef struct config_line_t { char *key; char *value; struct config_line_t *next; + /** What special treatment (if any) does this line require? */ + unsigned int command:2; + /** If true, subsequent assignments to this linelist should replace + * it, not extend it. Set only on the first item in a linelist in an + * or_options_t. */ + unsigned int fragile:1; } config_line_t; typedef struct routerset_t routerset_t; @@ -2380,6 +2878,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? */ @@ -2390,6 +2889,8 @@ typedef struct { char *Address; /**< OR only: configured address for this onion router. */ char *PidFile; /**< Where to store PID of Tor process. */ + int DynamicDHGroups; /**< Dynamic generation of prime moduli for use in DH.*/ + routerset_t *ExitNodes; /**< Structure containing nicknames, digests, * country codes and IP address patterns of ORs to * consider as exits. */ @@ -2448,16 +2949,17 @@ typedef struct { char *User; /**< Name of user to run Tor as. */ char *Group; /**< Name of group to run Tor as. */ int ORPort; /**< Port to listen on for OR connections. */ - int SocksPort; /**< Port to listen on for SOCKS connections. */ - /** Port to listen on for transparent pf/netfilter connections. */ - int TransPort; - int NATDPort; /**< Port to listen on for transparent natd connections. */ + config_line_t *SocksPort; /**< Ports to listen on for SOCKS connections. */ + /** Ports to listen on for transparent pf/netfilter connections. */ + config_line_t *TransPort; + config_line_t *NATDPort; /**< Ports to listen on for transparent natd + * connections. */ int ControlPort; /**< Port to listen on for control connections. */ config_line_t *ControlSocket; /**< List of Unix Domain Sockets to listen on * for control connections. */ int ControlSocketsGroupWritable; /**< Boolean: Are control sockets g+rw? */ int DirPort; /**< Port to listen on for directory connections. */ - int DNSPort; /**< Port to listen on for DNS requests. */ + config_line_t *DNSPort; /**< Port to listen on for DNS requests. */ int AssumeReachable; /**< Whether to publish our descriptor regardless. */ int AuthoritativeDir; /**< Boolean: is this an authoritative directory? */ int V1AuthoritativeDir; /**< Boolean: is this an authoritative directory @@ -2485,6 +2987,12 @@ typedef struct { int UseBridges; /**< Boolean: should we start all circuits with a bridge? */ config_line_t *Bridges; /**< List of bootstrap bridge addresses. */ + config_line_t *ClientTransportPlugin; /**< List of client + transport plugins. */ + + config_line_t *ServerTransportPlugin; /**< List of client + transport plugins. */ + int BridgeRelay; /**< Boolean: are we acting as a bridge relay? We make * this explicit so we can change how we behave in the * future. */ @@ -2499,8 +3007,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? */ @@ -2532,12 +3040,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. */ @@ -2608,6 +3114,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. */ @@ -2645,7 +3154,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 @@ -2666,6 +3176,18 @@ typedef struct { * number of servers per IP address shared * with an authority. */ + /** Should we assign the Guard flag to relays which would allow + * exploitation of CVE-2011-2768 against their clients? */ + int GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays; + + /** If non-zero, always vote the Fast flag for any relay advertising + * this amount of capacity or more. */ + uint64_t AuthDirFastGuarantee; + + /** If non-zero, this advertised capacity or more is always sufficient + * to satisfy the bandwidth requirement for the Guard flag. */ + uint64_t AuthDirGuardBWGuarantee; + char *AccountingStart; /**< How long is the accounting interval, and when * does it start? */ uint64_t AccountingMax; /**< How many bytes do we allow per accounting @@ -2711,6 +3233,8 @@ typedef struct { * log whether it was DNS-leaking or not? */ int HardwareAccel; /**< Boolean: Should we enable OpenSSL hardware * acceleration where available? */ + /** Token Bucket Refill resolution in milliseconds. */ + int TokenBucketRefillInterval; char *AccelName; /**< Optional hardware acceleration engine name. */ char *AccelDir; /**< Optional hardware acceleration engine search dir. */ int UseEntryGuards; /**< Boolean: Do we try to enter from a smallish number @@ -2742,10 +3266,14 @@ typedef struct { disclaimer. This allows a server administrator to show that they're running Tor and anyone visiting their server will know this without any specialized knowledge. */ + int DisableDebuggerAttachment; /**< Currently Linux only specific attempt to + disable ptrace; needs BSD testing. */ /** 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. */ @@ -2755,6 +3283,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. */ @@ -2792,6 +3324,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; @@ -2888,16 +3423,44 @@ typedef struct { */ double CircuitPriorityHalflife; + /** If true, do not enable IOCP on windows with bufferevents, even if + * we think we could. */ + int DisableIOCP; + /** For testing only: will go away in 0.2.3.x. */ + int _UseFilteringSSLBufferevents; + /** Set to true if the TestingTorNetwork configuration option is set. * This is used so that options_validate() has a chance to realize that * the defaults have changed. */ int _UsingTestNetworkDefaults; + /** If 1, we try to use microdescriptors to build circuits. If 0, we don't. + * If -1, Tor decides. */ + int UseMicrodescriptors; + /** File where we should write the ControlPort. */ char *ControlPortWriteToFile; /** Should that file be group-readable? */ int ControlPortFileGroupReadable; +#define MAX_MAX_CLIENT_CIRCUITS_PENDING 1024 + /** Maximum number of non-open general-purpose origin circuits to allow at + * once. */ + int MaxClientCircuitsPending; + + /** If 1, we always send optimistic data when it's supported. If 0, we + * never use it. If -1, we do what the consensus says. */ + int OptimisticData; + + /** If 1, and we are using IOCP, we set the kernel socket SNDBUF and RCVBUF + * to 0 to try to save kernel memory and avoid the dread "Out of buffers" + * issue. */ + int UserspaceIOCPBuffers; + + /** If 1, we accept and launch no external network connections, except on + * control ports. */ + int DisableNetwork; + } or_options_t; /** Persistent state for an onion router, as saved to disk. */ @@ -2924,6 +3487,8 @@ typedef struct { /** A list of Entry Guard-related configuration lines. */ config_line_t *EntryGuards; + config_line_t *TransportProxies; + /** These fields hold information on the history of bandwidth usage for * servers. The "Ends" fields hold the time when we last updated the * bandwidth usage. The "Interval" fields hold the granularity, in seconds, @@ -2976,6 +3541,8 @@ static INLINE void or_state_mark_dirty(or_state_t *state, time_t when) #define MAX_SOCKS_REPLY_LEN 1024 #define MAX_SOCKS_ADDR_LEN 256 +#define SOCKS_NO_AUTH 0x00 +#define SOCKS_USER_PASS 0x02 /** Please open a TCP connection to this addr:port. */ #define SOCKS_COMMAND_CONNECT 0x01 @@ -2995,10 +3562,17 @@ struct socks_request_t { /** Which version of SOCKS did the client use? One of "0, 4, 5" -- where * 0 means that no socks handshake ever took place, and this is just a * stub connection (e.g. see connection_ap_make_link()). */ - char socks_version; - int command; /**< What is this stream's goal? One from the above list. */ + uint8_t socks_version; + /** If using socks5 authentication, which authentication type did we + * negotiate? currently we support 0 (no authentication) and 2 + * (username/password). */ + uint8_t auth_type; + /** What is this stream's goal? One of the SOCKS_COMMAND_* values */ + uint8_t command; + /** Which kind of listener created this stream? */ + uint8_t listener_type; size_t replylen; /**< Length of <b>reply</b>. */ - char reply[MAX_SOCKS_REPLY_LEN]; /**< Write an entry into this string if + uint8_t reply[MAX_SOCKS_REPLY_LEN]; /**< Write an entry into this string if * we want to specify our own socks reply, * rather than using the default socks4 or * socks5 socks reply. We use this for the @@ -3010,10 +3584,21 @@ struct socks_request_t { unsigned int has_finished : 1; /**< Has the SOCKS handshake finished? Used to * make sure we send back a socks reply for * every connection. */ + unsigned int got_auth : 1; /**< Have we received any authentication data? */ + + /** Number of bytes in username; 0 if username is NULL */ + size_t usernamelen; + /** Number of bytes in password; 0 if password is NULL */ + uint8_t passwordlen; + /** The negotiated username value if any (for socks5), or the entire + * authentication string (for socks4). This value is NOT nul-terminated; + * see usernamelen for its length. */ + char *username; + /** The negotiated password value if any (for socks5). This value is NOT + * nul-terminated; see passwordlen for its length. */ + char *password; }; -/* all the function prototypes go here */ - /********************************* circuitbuild.c **********************/ /** How many hops does a general-purpose circuit have by default? */ @@ -3426,7 +4011,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 ***************************/ @@ -3582,7 +4167,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. */ @@ -3628,6 +4213,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 @@ -3645,7 +4232,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 c87036013d..40e5277478 100644 --- a/src/or/policies.c +++ b/src/or/policies.c @@ -11,6 +11,7 @@ #include "or.h" #include "config.h" #include "dirserv.h" +#include "nodelist.h" #include "policies.h" #include "routerparse.h" #include "ht.h" @@ -82,15 +83,15 @@ policy_expand_private(smartlist_t **policy) continue; } for (i = 0; private_nets[i]; ++i) { - addr_policy_t policy; - memcpy(&policy, p, sizeof(addr_policy_t)); - policy.is_private = 0; - policy.is_canonical = 0; - if (tor_addr_parse_mask_ports(private_nets[i], &policy.addr, - &policy.maskbits, &port_min, &port_max)<0) { + addr_policy_t newpolicy; + memcpy(&newpolicy, p, sizeof(addr_policy_t)); + newpolicy.is_private = 0; + newpolicy.is_canonical = 0; + if (tor_addr_parse_mask_ports(private_nets[i], &newpolicy.addr, + &newpolicy.maskbits, &port_min, &port_max)<0) { tor_assert(0); } - smartlist_add(tmp, addr_policy_get_canonical_entry(&policy)); + smartlist_add(tmp, addr_policy_get_canonical_entry(&newpolicy)); } addr_policy_free(p); }); @@ -163,7 +164,7 @@ parse_addr_policy(config_line_t *cfg, smartlist_t **dest, static int parse_reachable_addresses(void) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); int ret = 0; if (options->ReachableDirAddresses && @@ -261,7 +262,7 @@ fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port) /** Return true iff we think our firewall will let us make an OR connection to * <b>ri</b>. */ int -fascist_firewall_allows_or(routerinfo_t *ri) +fascist_firewall_allows_or(const routerinfo_t *ri) { /* XXXX proposal 118 */ tor_addr_t addr; @@ -269,6 +270,22 @@ fascist_firewall_allows_or(routerinfo_t *ri) return fascist_firewall_allows_address_or(&addr, ri->or_port); } +/** Return true iff we think our firewall will let us make an OR connection to + * <b>node</b>. */ +int +fascist_firewall_allows_node(const node_t *node) +{ + if (node->ri) { + return fascist_firewall_allows_or(node->ri); + } else if (node->rs) { + tor_addr_t addr; + tor_addr_from_ipv4h(&addr, node->rs->addr); + return fascist_firewall_allows_address_or(&addr, node->rs->or_port); + } else { + return 1; + } +} + /** Return true iff we think our firewall will let us make a directory * connection to addr:port. */ int @@ -339,7 +356,7 @@ authdir_policy_badexit_address(uint32_t addr, uint16_t port) * options in <b>options</b>, return -1 and set <b>msg</b> to a newly * allocated description of the error. Else return 0. */ int -validate_addr_policies(or_options_t *options, char **msg) +validate_addr_policies(const or_options_t *options, char **msg) { /* XXXX Maybe merge this into parse_policies_from_options, to make sure * that the two can't go out of sync. */ @@ -423,7 +440,7 @@ load_policy_from_option(config_line_t *config, smartlist_t **policy, /** Set all policies based on <b>options</b>, which should have been validated * first by validate_addr_policies. */ int -policies_parse_from_options(or_options_t *options) +policies_parse_from_options(const or_options_t *options) { int ret = 0; if (load_policy_from_option(options->SocksPolicy, &socks_policy, -1) < 0) @@ -553,18 +570,6 @@ addr_policy_get_canonical_entry(addr_policy_t *e) return found->policy; } -/** As compare_tor_addr_to_addr_policy, but instead of a tor_addr_t, takes - * in host order. */ -addr_policy_result_t -compare_addr_to_addr_policy(uint32_t addr, uint16_t port, - const smartlist_t *policy) -{ - /*XXXX deprecate this function when possible. */ - tor_addr_t a; - tor_addr_from_ipv4h(&a, addr); - return compare_tor_addr_to_addr_policy(&a, port, policy); -} - /** Helper for compare_tor_addr_to_addr_policy. Implements the case where * addr and port are both known. */ static addr_policy_result_t @@ -684,7 +689,7 @@ compare_tor_addr_to_addr_policy(const tor_addr_t *addr, uint16_t port, if (!policy) { /* no policy? accept all. */ return ADDR_POLICY_ACCEPTED; - } else if (tor_addr_is_null(addr)) { + } else if (addr == NULL || tor_addr_is_null(addr)) { tor_assert(port != 0); return compare_unknown_tor_addr_to_addr_policy(port, policy); } else if (port == 0) { @@ -866,15 +871,11 @@ policies_exit_policy_append_reject_star(smartlist_t **dest) append_exit_policy_string(dest, "reject *:*"); } -/** Replace the exit policy of <b>r</b> with reject *:*. */ +/** Replace the exit policy of <b>node</b> with reject *:* */ void -policies_set_router_exitpolicy_to_reject_all(routerinfo_t *r) +policies_set_node_exitpolicy_to_reject_all(node_t *node) { - addr_policy_t *item; - addr_policy_list_free(r->exit_policy); - r->exit_policy = smartlist_create(); - item = router_parse_addr_policy_item_from_string("reject *:*", -1); - smartlist_add(r->exit_policy, item); + node->rejects_all = 1; } /** Return 1 if there is at least one /8 subnet in <b>policy</b> that @@ -1085,7 +1086,7 @@ policy_summary_split(smartlist_t *summary, int start_at_index; int i = 0; - /* XXXX Do a binary search if run time matters */ + while (AT(i)->prt_max < prt_min) i++; if (AT(i)->prt_min != prt_min) { @@ -1298,6 +1299,186 @@ policy_summarize(smartlist_t *policy) return result; } +/** Convert a summarized policy string into a short_policy_t. Return NULL + * if the string is not well-formed. */ +short_policy_t * +parse_short_policy(const char *summary) +{ + const char *orig_summary = summary; + short_policy_t *result; + int is_accept; + int n_entries; + short_policy_entry_t entries[MAX_EXITPOLICY_SUMMARY_LEN]; /* overkill */ + const char *next; + + if (!strcmpstart(summary, "accept ")) { + is_accept = 1; + summary += strlen("accept "); + } else if (!strcmpstart(summary, "reject ")) { + is_accept = 0; + summary += strlen("reject "); + } else { + log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Unrecognized policy summary keyword"); + return NULL; + } + + n_entries = 0; + for ( ; *summary; summary = next) { + const char *comma = strchr(summary, ','); + unsigned low, high; + char dummy; + char ent_buf[32]; + + next = comma ? comma+1 : strchr(summary, '\0'); + + if (n_entries == MAX_EXITPOLICY_SUMMARY_LEN) { + log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Impossibly long policy summary %s", + escaped(orig_summary)); + return NULL; + } + + if (! TOR_ISDIGIT(*summary) || next-summary > (int)(sizeof(ent_buf)-1)) { + /* unrecognized entry format. skip it. */ + continue; + } + if (next-summary < 2) { + /* empty; skip it. */ + continue; + } + + memcpy(ent_buf, summary, next-summary-1); + ent_buf[next-summary-1] = '\0'; + + if (tor_sscanf(ent_buf, "%u-%u%c", &low, &high, &dummy) == 2) { + if (low<1 || low>65535 || high<1 || high>65535) { + log_fn(LOG_PROTOCOL_WARN, LD_DIR, + "Found bad entry in policy summary %s", escaped(orig_summary)); + return NULL; + } + } else if (tor_sscanf(ent_buf, "%u%c", &low, &dummy) == 1) { + if (low<1 || low>65535) { + log_fn(LOG_PROTOCOL_WARN, LD_DIR, + "Found bad entry in policy summary %s", escaped(orig_summary)); + return NULL; + } + high = low; + } else { + log_fn(LOG_PROTOCOL_WARN, LD_DIR,"Found bad entry in policy summary %s", + escaped(orig_summary)); + return NULL; + } + + entries[n_entries].min_port = low; + entries[n_entries].max_port = high; + n_entries++; + } + + if (n_entries == 0) { + log_fn(LOG_PROTOCOL_WARN, LD_DIR, + "Found no port-range entries in summary %s", escaped(orig_summary)); + return NULL; + } + + { + size_t size = STRUCT_OFFSET(short_policy_t, entries) + + sizeof(short_policy_entry_t)*(n_entries); + result = tor_malloc_zero(size); + + tor_assert( (char*)&result->entries[n_entries-1] < ((char*)result)+size); + } + + result->is_accept = is_accept; + result->n_entries = n_entries; + memcpy(result->entries, entries, sizeof(short_policy_entry_t)*n_entries); + return result; +} + +/** Release all storage held in <b>policy</b>. */ +void +short_policy_free(short_policy_t *policy) +{ + tor_free(policy); +} + +/** See whether the <b>addr</b>:<b>port</b> address is likely to be accepted + * or rejected by the summarized policy <b>policy</b>. Return values are as + * for compare_tor_addr_to_addr_policy. Unlike the regular addr_policy + * functions, requires the <b>port</b> be specified. */ +addr_policy_result_t +compare_tor_addr_to_short_policy(const tor_addr_t *addr, uint16_t port, + const short_policy_t *policy) +{ + int i; + int found_match = 0; + int accept; + (void)addr; + + tor_assert(port != 0); + + if (addr && tor_addr_is_null(addr)) + addr = NULL; /* Unspec means 'no address at all,' in this context. */ + + if (addr && (tor_addr_is_internal(addr, 0) || + tor_addr_is_loopback(addr))) + return ADDR_POLICY_REJECTED; + + for (i=0; i < policy->n_entries; ++i) { + const short_policy_entry_t *e = &policy->entries[i]; + if (e->min_port <= port && port <= e->max_port) { + found_match = 1; + break; + } + } + + if (found_match) + accept = policy->is_accept; + else + accept = ! policy->is_accept; + + /* ???? are these right? */ + if (accept) + return ADDR_POLICY_PROBABLY_ACCEPTED; + else + return ADDR_POLICY_REJECTED; +} + +/** Return true iff <b>policy</b> seems reject all ports */ +int +short_policy_is_reject_star(const short_policy_t *policy) +{ + /* This doesn't need to be as much on the lookout as policy_is_reject_star, + * since policy summaries are from the consensus or from consensus + * microdescs. + */ + tor_assert(policy); + /* Check for an exact match of "reject 1-65535". */ + return (policy->is_accept == 0 && policy->n_entries == 1 && + policy->entries[0].min_port == 1 && + policy->entries[0].max_port == 65535); +} + +/** Decides whether addr:port is probably or definitely accepted or rejcted by + * <b>node</b>. See compare_tor_addr_to_addr_policy for details on addr/port + * interpretation. */ +addr_policy_result_t +compare_tor_addr_to_node_policy(const tor_addr_t *addr, uint16_t port, + const node_t *node) +{ + if (node->rejects_all) + return ADDR_POLICY_REJECTED; + + if (node->ri) + return compare_tor_addr_to_addr_policy(addr, port, node->ri->exit_policy); + else if (node->md) { + if (node->md->exit_policy == NULL) + return ADDR_POLICY_REJECTED; + else + return compare_tor_addr_to_short_policy(addr, port, + node->md->exit_policy); + } else + return ADDR_POLICY_PROBABLY_REJECTED; +} + /** Implementation for GETINFO control command: knows the answer for questions * about "exit-policy/..." */ int diff --git a/src/or/policies.h b/src/or/policies.h index b2947c67e7..51716ab0a7 100644 --- a/src/or/policies.h +++ b/src/or/policies.h @@ -19,7 +19,8 @@ int firewall_is_fascist_or(void); int fascist_firewall_allows_address_or(const tor_addr_t *addr, uint16_t port); -int fascist_firewall_allows_or(routerinfo_t *ri); +int fascist_firewall_allows_or(const routerinfo_t *ri); +int fascist_firewall_allows_node(const node_t *node); int fascist_firewall_allows_address_dir(const tor_addr_t *addr, uint16_t port); int dir_policy_permits_address(const tor_addr_t *addr); int socks_policy_permits_address(const tor_addr_t *addr); @@ -28,21 +29,23 @@ int authdir_policy_valid_address(uint32_t addr, uint16_t port); int authdir_policy_baddir_address(uint32_t addr, uint16_t port); int authdir_policy_badexit_address(uint32_t addr, uint16_t port); -int validate_addr_policies(or_options_t *options, char **msg); +int validate_addr_policies(const or_options_t *options, char **msg); void policy_expand_private(smartlist_t **policy); -int policies_parse_from_options(or_options_t *options); +int policies_parse_from_options(const or_options_t *options); addr_policy_t *addr_policy_get_canonical_entry(addr_policy_t *ent); int cmp_addr_policies(smartlist_t *a, smartlist_t *b); addr_policy_result_t compare_tor_addr_to_addr_policy(const tor_addr_t *addr, uint16_t port, const smartlist_t *policy); -addr_policy_result_t compare_addr_to_addr_policy(uint32_t addr, - uint16_t port, const smartlist_t *policy); + +addr_policy_result_t compare_tor_addr_to_node_policy(const tor_addr_t *addr, + uint16_t port, const node_t *node); + int policies_parse_exit_policy(config_line_t *cfg, smartlist_t **dest, int rejectprivate, const char *local_address, int add_default_policy); void policies_exit_policy_append_reject_star(smartlist_t **dest); -void policies_set_router_exitpolicy_to_reject_all(routerinfo_t *exitrouter); +void policies_set_node_exitpolicy_to_reject_all(node_t *exitrouter); int exit_policy_is_general_exit(smartlist_t *policy); int policy_is_reject_star(const smartlist_t *policy); int getinfo_helper_policies(control_connection_t *conn, @@ -57,5 +60,12 @@ void policies_free_all(void); char *policy_summarize(smartlist_t *policy); +short_policy_t *parse_short_policy(const char *summary); +void short_policy_free(short_policy_t *policy); +int short_policy_is_reject_star(const short_policy_t *policy); +addr_policy_result_t compare_tor_addr_to_short_policy( + const tor_addr_t *addr, uint16_t port, + const short_policy_t *policy); + #endif diff --git a/src/or/relay.c b/src/or/relay.c index d9b9d0c486..ac3114bda5 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -11,6 +11,7 @@ **/ #include <math.h> +#define RELAY_PRIVATE #include "or.h" #include "buffers.h" #include "circuitbuild.h" @@ -24,6 +25,7 @@ #include "main.h" #include "mempool.h" #include "networkstatus.h" +#include "nodelist.h" #include "policies.h" #include "reasons.h" #include "relay.h" @@ -32,9 +34,6 @@ #include "routerlist.h" #include "routerparse.h" -static int relay_crypt(circuit_t *circ, cell_t *cell, - cell_direction_t cell_direction, - crypt_path_t **layer_hint, char *recognized); static edge_connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction, crypt_path_t *layer_hint); @@ -296,7 +295,7 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, * Return -1 to indicate that we should mark the circuit for close, * else return 0. */ -static int +int relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction, crypt_path_t **layer_hint, char *recognized) { @@ -648,6 +647,7 @@ connection_edge_send_command(edge_connection_t *fromconn, { /* XXXX NM Split this function into a separate versions per circuit type? */ circuit_t *circ; + crypt_path_t *cpath_layer = fromconn->cpath_layer; tor_assert(fromconn); circ = fromconn->on_circuit; @@ -662,7 +662,8 @@ connection_edge_send_command(edge_connection_t *fromconn, if (!circ) { if (fromconn->_base.type == CONN_TYPE_AP) { log_info(LD_APP,"no circ. Closing conn."); - connection_mark_unattached_ap(fromconn, END_STREAM_REASON_INTERNAL); + connection_mark_unattached_ap(EDGE_TO_ENTRY_CONN(fromconn), + END_STREAM_REASON_INTERNAL); } else { log_info(LD_EXIT,"no circ. Closing conn."); fromconn->edge_has_sent_end = 1; /* no circ to send to */ @@ -674,7 +675,7 @@ connection_edge_send_command(edge_connection_t *fromconn, return relay_send_command_from_edge(fromconn->stream_id, circ, relay_command, payload, - payload_len, fromconn->cpath_layer); + payload_len, cpath_layer); } /** How many times will I retry a stream that fails due to DNS @@ -702,22 +703,24 @@ edge_reason_is_retriable(int reason) static int connection_ap_process_end_not_open( relay_header_t *rh, cell_t *cell, origin_circuit_t *circ, - edge_connection_t *conn, crypt_path_t *layer_hint) + entry_connection_t *conn, crypt_path_t *layer_hint) { struct in_addr in; - routerinfo_t *exitrouter; + node_t *exitrouter; int reason = *(cell->payload+RELAY_HEADER_SIZE); int control_reason = reason | END_STREAM_REASON_FLAG_REMOTE; + edge_connection_t *edge_conn = ENTRY_TO_EDGE_CONN(conn); (void) layer_hint; /* unused */ if (rh->length > 0 && edge_reason_is_retriable(reason) && - !connection_edge_is_rendezvous_stream(conn) /* avoid retry if rend */ - ) { + /* avoid retry if rend */ + !connection_edge_is_rendezvous_stream(edge_conn)) { + const char *chosen_exit_digest = + circ->build_state->chosen_exit->identity_digest; log_info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.", safe_str(conn->socks_request->address), stream_end_reason_to_string(reason)); - exitrouter = - router_get_by_digest(circ->build_state->chosen_exit->identity_digest); + exitrouter = node_get_mutable_by_id(chosen_exit_digest); switch (reason) { case END_STREAM_REASON_EXITPOLICY: if (rh->length >= 5) { @@ -752,8 +755,8 @@ connection_ap_process_end_not_open( log_info(LD_APP, "Exitrouter %s seems to be more restrictive than its exit " "policy. Not using this router as exit for now.", - router_describe(exitrouter)); - policies_set_router_exitpolicy_to_reject_all(exitrouter); + node_describe(exitrouter)); + policies_set_node_exitpolicy_to_reject_all(exitrouter); } /* rewrite it to an IP if we learned one. */ if (addressmap_rewrite(conn->socks_request->address, @@ -818,7 +821,7 @@ connection_ap_process_end_not_open( case END_STREAM_REASON_HIBERNATING: case END_STREAM_REASON_RESOURCELIMIT: if (exitrouter) { - policies_set_router_exitpolicy_to_reject_all(exitrouter); + policies_set_node_exitpolicy_to_reject_all(exitrouter); } if (conn->chosen_exit_optional) { /* stop wanting a specific exit */ @@ -838,7 +841,7 @@ connection_ap_process_end_not_open( stream_end_reason_to_string(rh->length > 0 ? reason : -1)); circuit_log_path(LOG_INFO,LD_APP,circ); /* need to test because of detach_retriable */ - if (!conn->_base.marked_for_close) + if (!ENTRY_TO_CONN(conn)->marked_for_close) connection_mark_unattached_ap(conn, control_reason); return 0; } @@ -847,7 +850,7 @@ connection_ap_process_end_not_open( * dotted-quad representation of <b>new_addr</b> (given in host order), * and send an appropriate REMAP event. */ static void -remap_event_helper(edge_connection_t *conn, uint32_t new_addr) +remap_event_helper(entry_connection_t *conn, uint32_t new_addr) { struct in_addr in; @@ -873,7 +876,8 @@ connection_edge_process_relay_cell_not_open( if (rh->command == RELAY_COMMAND_END) { if (CIRCUIT_IS_ORIGIN(circ) && conn->_base.type == CONN_TYPE_AP) { return connection_ap_process_end_not_open(rh, cell, - TO_ORIGIN_CIRCUIT(circ), conn, + TO_ORIGIN_CIRCUIT(circ), + EDGE_TO_ENTRY_CONN(conn), layer_hint); } else { /* we just got an 'end', don't need to send one */ @@ -887,6 +891,7 @@ connection_edge_process_relay_cell_not_open( if (conn->_base.type == CONN_TYPE_AP && rh->command == RELAY_COMMAND_CONNECTED) { + entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn); tor_assert(CIRCUIT_IS_ORIGIN(circ)); if (conn->_base.state != AP_CONN_STATE_CONNECT_WAIT) { log_fn(LOG_PROTOCOL_WARN, LD_APP, @@ -901,29 +906,26 @@ connection_edge_process_relay_cell_not_open( int ttl; if (!addr || (get_options()->ClientDNSRejectInternalAddresses && is_internal_IP(addr, 0))) { - char buf[INET_NTOA_BUF_LEN]; - struct in_addr a; - a.s_addr = htonl(addr); - tor_inet_ntoa(&a, buf, sizeof(buf)); - log_info(LD_APP, - "...but it claims the IP address was %s. Closing.", buf); + log_info(LD_APP, "...but it claims the IP address was %s. Closing.", + fmt_addr32(addr)); connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL); - connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); + connection_mark_unattached_ap(entry_conn, + END_STREAM_REASON_TORPROTOCOL); return 0; } if (rh->length >= 8) ttl = (int)ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+4)); else ttl = -1; - client_dns_set_addressmap(conn->socks_request->address, addr, - conn->chosen_exit_name, ttl); + client_dns_set_addressmap(entry_conn->socks_request->address, addr, + entry_conn->chosen_exit_name, ttl); - remap_event_helper(conn, addr); + remap_event_helper(entry_conn, addr); } circuit_log_path(LOG_INFO,LD_APP,TO_ORIGIN_CIRCUIT(circ)); /* don't send a socks reply to transparent conns */ - if (!conn->socks_request->has_finished) - connection_ap_handshake_socks_reply(conn, NULL, 0, 0); + if (!entry_conn->socks_request->has_finished) + connection_ap_handshake_socks_reply(entry_conn, NULL, 0, 0); /* Was it a linked dir conn? If so, a dir request just started to * fetch something; this could be a bootstrap status milestone. */ @@ -946,6 +948,12 @@ connection_edge_process_relay_cell_not_open( break; } } + /* This is definitely a success, so forget about any pending data we + * had sent. */ + if (entry_conn->pending_optimistic_data) { + generic_buffer_free(entry_conn->pending_optimistic_data); + entry_conn->pending_optimistic_data = NULL; + } /* handle anything that might have queued */ if (connection_edge_package_raw_inbuf(conn, 1, NULL) < 0) { @@ -960,17 +968,18 @@ connection_edge_process_relay_cell_not_open( int ttl; int answer_len; uint8_t answer_type; + entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn); if (conn->_base.state != AP_CONN_STATE_RESOLVE_WAIT) { log_fn(LOG_PROTOCOL_WARN, LD_APP, "Got a 'resolved' cell while " "not in state resolve_wait. Dropping."); return 0; } - tor_assert(SOCKS_COMMAND_IS_RESOLVE(conn->socks_request->command)); + tor_assert(SOCKS_COMMAND_IS_RESOLVE(entry_conn->socks_request->command)); answer_len = cell->payload[RELAY_HEADER_SIZE+1]; if (rh->length < 2 || answer_len+2>rh->length) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Dropping malformed 'resolved' cell"); - connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); + connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_TORPROTOCOL); return 0; } answer_type = cell->payload[RELAY_HEADER_SIZE]; @@ -983,19 +992,17 @@ connection_edge_process_relay_cell_not_open( uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2)); if (get_options()->ClientDNSRejectInternalAddresses && is_internal_IP(addr, 0)) { - char buf[INET_NTOA_BUF_LEN]; - struct in_addr a; - a.s_addr = htonl(addr); - tor_inet_ntoa(&a, buf, sizeof(buf)); - log_info(LD_APP,"Got a resolve with answer %s. Rejecting.", buf); - connection_ap_handshake_socks_resolved(conn, + log_info(LD_APP,"Got a resolve with answer %s. Rejecting.", + fmt_addr32(addr)); + connection_ap_handshake_socks_resolved(entry_conn, RESOLVED_TYPE_ERROR_TRANSIENT, 0, NULL, 0, TIME_MAX); - connection_mark_unattached_ap(conn, END_STREAM_REASON_TORPROTOCOL); + connection_mark_unattached_ap(entry_conn, + END_STREAM_REASON_TORPROTOCOL); return 0; } } - connection_ap_handshake_socks_resolved(conn, + connection_ap_handshake_socks_resolved(entry_conn, answer_type, cell->payload[RELAY_HEADER_SIZE+1], /*answer_len*/ cell->payload+RELAY_HEADER_SIZE+2, /*answer*/ @@ -1003,9 +1010,9 @@ connection_edge_process_relay_cell_not_open( -1); if (answer_type == RESOLVED_TYPE_IPV4 && answer_len == 4) { uint32_t addr = ntohl(get_uint32(cell->payload+RELAY_HEADER_SIZE+2)); - remap_event_helper(conn, addr); + remap_event_helper(entry_conn, addr); } - connection_mark_unattached_ap(conn, + connection_mark_unattached_ap(entry_conn, END_STREAM_REASON_DONE | END_STREAM_REASON_FLAG_ALREADY_SOCKS_REPLIED); return 0; @@ -1039,6 +1046,9 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, relay_header_t rh; unsigned domain = layer_hint?LD_APP:LD_EXIT; int reason; + int optimistic_data = 0; /* Set to 1 if we receive data on a stream + * that's in the EXIT_CONN_STATE_RESOLVING + * or EXIT_CONN_STATE_CONNECTING states. */ tor_assert(cell); tor_assert(circ); @@ -1058,9 +1068,20 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, /* either conn is NULL, in which case we've got a control cell, or else * conn points to the recognized stream. */ - if (conn && !connection_state_is_open(TO_CONN(conn))) - return connection_edge_process_relay_cell_not_open( - &rh, cell, circ, conn, layer_hint); + if (conn && !connection_state_is_open(TO_CONN(conn))) { + if (conn->_base.type == CONN_TYPE_EXIT && + (conn->_base.state == EXIT_CONN_STATE_CONNECTING || + conn->_base.state == EXIT_CONN_STATE_RESOLVING) && + rh.command == RELAY_COMMAND_DATA) { + /* Allow DATA cells to be delivered to an exit node in state + * EXIT_CONN_STATE_CONNECTING or EXIT_CONN_STATE_RESOLVING. + * This speeds up HTTP, for example. */ + optimistic_data = 1; + } else { + return connection_edge_process_relay_cell_not_open( + &rh, cell, circ, conn, layer_hint); + } + } switch (rh.command) { case RELAY_COMMAND_DROP: @@ -1127,7 +1148,14 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, stats_n_data_bytes_received += rh.length; connection_write_to_buf((char*)(cell->payload + RELAY_HEADER_SIZE), rh.length, TO_CONN(conn)); - connection_edge_consider_sending_sendme(conn); + + if (!optimistic_data) { + /* Only send a SENDME if we're not getting optimistic data; otherwise + * a SENDME could arrive before the CONNECTED. + */ + connection_edge_consider_sending_sendme(conn); + } + return 0; case RELAY_COMMAND_END: reason = rh.length > 0 ? @@ -1142,9 +1170,13 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, conn->_base.s, stream_end_reason_to_string(reason), conn->stream_id); - if (conn->socks_request && !conn->socks_request->has_finished) - log_warn(LD_BUG, - "open stream hasn't sent socks answer yet? Closing."); + if (conn->_base.type == CONN_TYPE_AP) { + entry_connection_t *entry_conn = EDGE_TO_ENTRY_CONN(conn); + if (entry_conn->socks_request && + !entry_conn->socks_request->has_finished) + log_warn(LD_BUG, + "open stream hasn't sent socks answer yet? Closing."); + } /* We just *got* an end; no reason to send one. */ conn->edge_has_sent_end = 1; if (!conn->end_reason) @@ -1152,8 +1184,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, if (!conn->_base.marked_for_close) { /* only mark it if not already marked. it's possible to * get the 'end' right around when the client hangs up on us. */ - connection_mark_for_close(TO_CONN(conn)); - conn->_base.hold_open_until_flushed = 1; + connection_mark_and_flush(TO_CONN(conn)); } return 0; case RELAY_COMMAND_EXTEND: @@ -1324,10 +1355,17 @@ int connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial, int *max_cells) { - size_t amount_to_process, length; + size_t bytes_to_process, length; char payload[CELL_PAYLOAD_SIZE]; circuit_t *circ; - unsigned domain = conn->cpath_layer ? LD_APP : LD_EXIT; + const unsigned domain = conn->_base.type == CONN_TYPE_AP ? LD_APP : LD_EXIT; + int sending_from_optimistic = 0; + const int sending_optimistically = + conn->_base.type == CONN_TYPE_AP && + conn->_base.state != AP_CONN_STATE_OPEN; + entry_connection_t *entry_conn = + conn->_base.type == CONN_TYPE_AP ? EDGE_TO_ENTRY_CONN(conn) : NULL; + crypt_path_t *cpath_layer = conn->cpath_layer; tor_assert(conn); @@ -1350,7 +1388,7 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial, return -1; } - if (circuit_consider_stop_edge_reading(circ, conn->cpath_layer)) + if (circuit_consider_stop_edge_reading(circ, cpath_layer)) return 0; if (conn->package_window <= 0) { @@ -1360,44 +1398,75 @@ connection_edge_package_raw_inbuf(edge_connection_t *conn, int package_partial, return 0; } - amount_to_process = buf_datalen(conn->_base.inbuf); + sending_from_optimistic = entry_conn && + entry_conn->sending_optimistic_data != NULL; + + if (PREDICT_UNLIKELY(sending_from_optimistic)) { + bytes_to_process = generic_buffer_len(entry_conn->sending_optimistic_data); + if (PREDICT_UNLIKELY(!bytes_to_process)) { + log_warn(LD_BUG, "sending_optimistic_data was non-NULL but empty"); + bytes_to_process = connection_get_inbuf_len(TO_CONN(conn)); + sending_from_optimistic = 0; + } + } else { + bytes_to_process = connection_get_inbuf_len(TO_CONN(conn)); + } - if (!amount_to_process) + if (!bytes_to_process) return 0; - if (!package_partial && amount_to_process < RELAY_PAYLOAD_SIZE) + if (!package_partial && bytes_to_process < RELAY_PAYLOAD_SIZE) return 0; - if (amount_to_process > RELAY_PAYLOAD_SIZE) { + if (bytes_to_process > RELAY_PAYLOAD_SIZE) { length = RELAY_PAYLOAD_SIZE; } else { - length = amount_to_process; + length = bytes_to_process; } stats_n_data_bytes_packaged += length; stats_n_data_cells_packaged += 1; - connection_fetch_from_buf(payload, length, TO_CONN(conn)); + if (PREDICT_UNLIKELY(sending_from_optimistic)) { + /* XXX023 We could be more efficient here by sometimes packing + * previously-sent optimistic data in the same cell with data + * from the inbuf. */ + generic_buffer_get(entry_conn->sending_optimistic_data, payload, length); + if (!generic_buffer_len(entry_conn->sending_optimistic_data)) { + generic_buffer_free(entry_conn->sending_optimistic_data); + entry_conn->sending_optimistic_data = NULL; + } + } else { + connection_fetch_from_buf(payload, length, TO_CONN(conn)); + } log_debug(domain,"(%d) Packaging %d bytes (%d waiting).", conn->_base.s, - (int)length, (int)buf_datalen(conn->_base.inbuf)); + (int)length, (int)connection_get_inbuf_len(TO_CONN(conn))); + + if (sending_optimistically && !sending_from_optimistic) { + /* This is new optimistic data; remember it in case we need to detach and + retry */ + if (!entry_conn->pending_optimistic_data) + entry_conn->pending_optimistic_data = generic_buffer_new(); + generic_buffer_add(entry_conn->pending_optimistic_data, payload, length); + } if (connection_edge_send_command(conn, RELAY_COMMAND_DATA, payload, length) < 0 ) /* circuit got marked for close, don't continue, don't need to mark conn */ return 0; - if (!conn->cpath_layer) { /* non-rendezvous exit */ + if (!cpath_layer) { /* non-rendezvous exit */ tor_assert(circ->package_window > 0); circ->package_window--; } else { /* we're an AP, or an exit on a rendezvous circ */ - tor_assert(conn->cpath_layer->package_window > 0); - conn->cpath_layer->package_window--; + tor_assert(cpath_layer->package_window > 0); + cpath_layer->package_window--; } if (--conn->package_window <= 0) { /* is it 0 after decrement? */ connection_stop_reading(TO_CONN(conn)); log_debug(domain,"conn->package_window reached 0."); - circuit_consider_stop_edge_reading(circ, conn->cpath_layer); + circuit_consider_stop_edge_reading(circ, cpath_layer); return 0; /* don't process the inbuf any more */ } log_debug(domain,"conn->package_window is now %d",conn->package_window); @@ -1436,7 +1505,7 @@ connection_edge_consider_sending_sendme(edge_connection_t *conn) } while (conn->deliver_window <= STREAMWINDOW_START - STREAMWINDOW_INCREMENT) { - log_debug(conn->cpath_layer?LD_APP:LD_EXIT, + log_debug(conn->_base.type == CONN_TYPE_AP ?LD_APP:LD_EXIT, "Outbuf %d, Queuing stream sendme.", (int)conn->_base.outbuf_flushlen); conn->deliver_window += STREAMWINDOW_INCREMENT; @@ -1532,7 +1601,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn, if (!layer_hint || conn->cpath_layer == layer_hint) { connection_start_reading(TO_CONN(conn)); - if (buf_datalen(conn->_base.inbuf) > 0) + if (connection_get_inbuf_len(TO_CONN(conn)) > 0) ++n_packaging_streams; } } @@ -1543,7 +1612,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn, if (!layer_hint || conn->cpath_layer == layer_hint) { connection_start_reading(TO_CONN(conn)); - if (buf_datalen(conn->_base.inbuf) > 0) + if (connection_get_inbuf_len(TO_CONN(conn)) > 0) ++n_packaging_streams; } } @@ -1582,7 +1651,7 @@ circuit_resume_edge_reading_helper(edge_connection_t *first_conn, } /* If there's still data to read, we'll be coming back to this stream. */ - if (buf_datalen(conn->_base.inbuf)) + if (connection_get_inbuf_len(TO_CONN(conn))) ++n_streams_left; /* If the circuit won't accept any more data, return without looking @@ -1638,9 +1707,10 @@ circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint) if (layer_hint->package_window <= 0) { log_debug(domain,"yes, at-origin. stopped."); for (conn = TO_ORIGIN_CIRCUIT(circ)->p_streams; conn; - conn=conn->next_stream) + conn=conn->next_stream) { if (conn->cpath_layer == layer_hint) connection_stop_reading(TO_CONN(conn)); + } return 1; } return 0; @@ -1995,7 +2065,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; @@ -2246,7 +2317,7 @@ set_streams_blocked_on_circ(circuit_t *circ, or_connection_t *orconn, edge->edge_blocked_on_circ = block; } - if (!conn->read_event) { + if (!conn->read_event && !HAS_BUFFEREVENT(conn)) { /* This connection is a placeholder for something; probably a DNS * request. It can't actually stop or start reading.*/ continue; @@ -2321,13 +2392,13 @@ connection_or_flush_from_first_active_circuit(or_connection_t *conn, int max, /* Calculate the exact time that this cell has spent in the queue. */ if (get_options()->CellStatistics && !CIRCUIT_IS_ORIGIN(circ)) { - struct timeval now; + struct timeval tvnow; uint32_t flushed; uint32_t cell_waiting_time; insertion_time_queue_t *it_queue = queue->insertion_times; - tor_gettimeofday_cached(&now); - flushed = (uint32_t)((now.tv_sec % SECONDS_IN_A_DAY) * 100L + - (uint32_t)now.tv_usec / (uint32_t)10000L); + tor_gettimeofday_cached(&tvnow); + flushed = (uint32_t)((tvnow.tv_sec % SECONDS_IN_A_DAY) * 100L + + (uint32_t)tvnow.tv_usec / (uint32_t)10000L); if (!it_queue || !it_queue->first) { log_info(LD_GENERAL, "Cannot determine insertion time of cell. " "Looks like the CellStatistics option was " @@ -2447,7 +2518,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 f64752da5d..1cd4008bb9 100644 --- a/src/or/relay.h +++ b/src/or/relay.h @@ -60,11 +60,16 @@ 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); +#ifdef RELAY_PRIVATE +int relay_crypt(circuit_t *circ, cell_t *cell, cell_direction_t cell_direction, + crypt_path_t **layer_hint, char *recognized); +#endif + #endif diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 0a9e2a605f..6a45207e29 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -16,6 +16,7 @@ #include "connection_edge.h" #include "directory.h" #include "main.h" +#include "nodelist.h" #include "relay.h" #include "rendclient.h" #include "rendcommon.h" @@ -80,8 +81,8 @@ rend_client_send_establish_rendezvous(origin_circuit_t *circ) /** Extend the introduction circuit <b>circ</b> to another valid * introduction point for the hidden service it is trying to connect * to, or mark it and launch a new circuit if we can't extend it. - * Return 0 on success. Return -1 and mark the introduction - * circuit on failure. + * Return 0 on success or possible success. Return -1 and mark the + * introduction circuit for close on permanent failure. * * On failure, the caller is responsible for marking the associated * rendezvous circuit for close. */ @@ -106,17 +107,11 @@ rend_client_reextend_intro_circuit(origin_circuit_t *circ) result = circuit_extend_to_new_exit(circ, extend_info); } else { log_info(LD_REND, - "Building a new introduction circuit, this time to %s.", - safe_str_client(extend_info_describe(extend_info))); + "Closing intro circ %d (out of RELAY_EARLY cells).", + circ->_base.n_circ_id); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED); - if (!circuit_launch_by_extend_info(CIRCUIT_PURPOSE_C_INTRODUCING, - extend_info, - CIRCLAUNCH_IS_INTERNAL)) { - log_warn(LD_REND, "Building introduction circuit failed."); - result = -1; - } else { - result = 0; - } + /* connection_ap_handshake_attach_circuit will launch a new intro circ. */ + result = 0; } extend_info_free(extend_info); return result; @@ -144,6 +139,8 @@ rend_client_send_introduction(origin_circuit_t *introcirc, tor_assert(rendcirc->rend_data); tor_assert(!rend_cmp_service_ids(introcirc->rend_data->onion_address, rendcirc->rend_data->onion_address)); + tor_assert(!(introcirc->build_state->onehop_tunnel)); + tor_assert(!(rendcirc->build_state->onehop_tunnel)); if (rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1, &entry) < 1) { @@ -334,6 +331,7 @@ rend_client_introduction_acked(origin_circuit_t *circ, } tor_assert(circ->build_state->chosen_exit); + tor_assert(!(circ->build_state->onehop_tunnel)); tor_assert(circ->rend_data); if (request_len == 0) { @@ -345,6 +343,7 @@ rend_client_introduction_acked(origin_circuit_t *circ, rendcirc = circuit_get_by_rend_query_and_purpose( circ->rend_data->onion_address, CIRCUIT_PURPOSE_C_REND_READY); if (rendcirc) { /* remember the ack */ + tor_assert(!(rendcirc->build_state->onehop_tunnel)); rendcirc->_base.purpose = CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED; /* Set timestamp_dirty, because circuit_expire_building expects * it to specify when a circuit entered the @@ -367,8 +366,8 @@ rend_client_introduction_acked(origin_circuit_t *circ, safe_str_client(circ->rend_data->onion_address), safe_str_client(extend_info_describe(circ->build_state->chosen_exit))); if (rend_client_report_intro_point_failure(circ->build_state->chosen_exit, - circ->rend_data, - INTRO_POINT_FAILURE_GENERIC)>0){ + circ->rend_data, + INTRO_POINT_FAILURE_GENERIC)>0) { /* There are introduction points left. Re-extend the circuit to * another intro point and try again. */ int result = rend_client_reextend_intro_circuit(circ); @@ -385,9 +384,12 @@ rend_client_introduction_acked(origin_circuit_t *circ, #define REND_HID_SERV_DIR_REQUERY_PERIOD (15 * 60) /** Contains the last request times to hidden service directories for - * certain queries; keys are strings consisting of base32-encoded - * hidden service directory identities and base32-encoded descriptor IDs; - * values are pointers to timestamps of the last requests. */ + * certain queries; each key is a string consisting of the + * concatenation of a base32-encoded HS directory identity digest, a + * base32-encoded HS descriptor ID, and a hidden service address + * (without the ".onion" part); each value is a pointer to a time_t + * holding the time of the last request for that descriptor ID to that + * HS directory. */ static strmap_t *last_hid_serv_requests_ = NULL; /** Returns last_hid_serv_requests_, initializing it to a new strmap if @@ -400,23 +402,34 @@ get_last_hid_serv_requests(void) return last_hid_serv_requests_; } +#define LAST_HID_SERV_REQUEST_KEY_LEN (REND_DESC_ID_V2_LEN_BASE32 + \ + REND_DESC_ID_V2_LEN_BASE32 + \ + REND_SERVICE_ID_LEN_BASE32) + /** Look up the last request time to hidden service directory <b>hs_dir</b> - * for descriptor ID <b>desc_id_base32</b>. If <b>set</b> is non-zero, + * for descriptor ID <b>desc_id_base32</b> for the service specified in + * <b>rend_query</b>. If <b>set</b> is non-zero, * assign the current time <b>now</b> and return that. Otherwise, return * the most recent request time, or 0 if no such request has been sent * before. */ static time_t lookup_last_hid_serv_request(routerstatus_t *hs_dir, - const char *desc_id_base32, time_t now, int set) + const char *desc_id_base32, + const rend_data_t *rend_query, + time_t now, int set) { char hsdir_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; - char hsdir_desc_comb_id[2 * REND_DESC_ID_V2_LEN_BASE32 + 1]; + char hsdir_desc_comb_id[LAST_HID_SERV_REQUEST_KEY_LEN + 1]; time_t *last_request_ptr; strmap_t *last_hid_serv_requests = get_last_hid_serv_requests(); base32_encode(hsdir_id_base32, sizeof(hsdir_id_base32), hs_dir->identity_digest, DIGEST_LEN); - tor_snprintf(hsdir_desc_comb_id, sizeof(hsdir_desc_comb_id), "%s%s", - hsdir_id_base32, desc_id_base32); + tor_snprintf(hsdir_desc_comb_id, sizeof(hsdir_desc_comb_id), "%s%s%s", + hsdir_id_base32, + desc_id_base32, + rend_query->onion_address); + /* XXX023 tor_assert(strlen(hsdir_desc_comb_id) == + LAST_HID_SERV_REQUEST_KEY_LEN); */ if (set) { time_t *oldptr; last_request_ptr = tor_malloc_zero(sizeof(time_t)); @@ -434,10 +447,10 @@ lookup_last_hid_serv_request(routerstatus_t *hs_dir, * it does not contain requests older than REND_HID_SERV_DIR_REQUERY_PERIOD * seconds any more. */ static void -directory_clean_last_hid_serv_requests(void) +directory_clean_last_hid_serv_requests(time_t now) { strmap_iter_t *iter; - time_t cutoff = time(NULL) - REND_HID_SERV_DIR_REQUERY_PERIOD; + time_t cutoff = now - REND_HID_SERV_DIR_REQUERY_PERIOD; strmap_t *last_hid_serv_requests = get_last_hid_serv_requests(); for (iter = strmap_iter_init(last_hid_serv_requests); !strmap_iter_done(iter); ) { @@ -455,6 +468,33 @@ directory_clean_last_hid_serv_requests(void) } } +/** Remove all requests related to the hidden service named + * <b>onion_address</b> from the history of times of requests to + * hidden service directories. */ +static void +purge_hid_serv_from_last_hid_serv_requests(const char *onion_address) +{ + strmap_iter_t *iter; + strmap_t *last_hid_serv_requests = get_last_hid_serv_requests(); + /* XXX023 tor_assert(strlen(onion_address) == REND_SERVICE_ID_LEN_BASE32); */ + for (iter = strmap_iter_init(last_hid_serv_requests); + !strmap_iter_done(iter); ) { + const char *key; + void *val; + strmap_iter_get(iter, &key, &val); + /* XXX023 tor_assert(strlen(key) == LAST_HID_SERV_REQUEST_KEY_LEN); */ + if (tor_memeq(key + LAST_HID_SERV_REQUEST_KEY_LEN - + REND_SERVICE_ID_LEN_BASE32, + onion_address, + REND_SERVICE_ID_LEN_BASE32)) { + iter = strmap_iter_next_rmv(last_hid_serv_requests, iter); + tor_free(val); + } else { + iter = strmap_iter_next(last_hid_serv_requests, iter); + } + } +} + /** Purge the history of request times to hidden service directories, * so that future lookups of an HS descriptor will not fail because we * accessed all of the HSDir relays responsible for the descriptor @@ -476,12 +516,11 @@ rend_client_purge_last_hid_serv_requests(void) } /** Determine the responsible hidden service directories for <b>desc_id</b> - * and fetch the descriptor belonging to that ID from one of them. Only - * send a request to hidden service directories that we did not try within - * the last REND_HID_SERV_DIR_REQUERY_PERIOD seconds; on success, return 1, + * and fetch the descriptor with that ID from one of them. Only + * send a request to a hidden service directory that we have not yet tried + * during this attempt to connect to this hidden service; on success, return 1, * in the case that no hidden service directory is left to ask for the - * descriptor, return 0, and in case of a failure -1. <b>query</b> is only - * passed for pretty log statements. */ + * descriptor, return 0, and in case of a failure -1. */ static int directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query) { @@ -501,12 +540,16 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query) /* Only select those hidden service directories to which we did not send * a request recently and for which we have a router descriptor here. */ - directory_clean_last_hid_serv_requests(); /* Clean request history first. */ + + /* Clean request history first. */ + directory_clean_last_hid_serv_requests(now); SMARTLIST_FOREACH(responsible_dirs, routerstatus_t *, dir, { - if (lookup_last_hid_serv_request(dir, desc_id_base32, 0, 0) + - REND_HID_SERV_DIR_REQUERY_PERIOD >= now || - !router_get_by_digest(dir->identity_digest)) + time_t last = lookup_last_hid_serv_request( + dir, desc_id_base32, rend_query, 0, 0); + const node_t *node = node_get_by_id(dir->identity_digest); + if (last + REND_HID_SERV_DIR_REQUERY_PERIOD >= now || + !node || !node_has_descriptor(node)) SMARTLIST_DEL_CURRENT(responsible_dirs, dir); }); @@ -519,9 +562,9 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query) return 0; } - /* Remember, that we are requesting a descriptor from this hidden service + /* Remember that we are requesting a descriptor from this hidden service * directory now. */ - lookup_last_hid_serv_request(hs_dir, desc_id_base32, now, 1); + lookup_last_hid_serv_request(hs_dir, desc_id_base32, rend_query, now, 1); /* Encode descriptor cookie for logging purposes. */ if (rend_query->auth_type != REND_NO_AUTH) { @@ -859,40 +902,42 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request, void rend_client_desc_trynow(const char *query) { - edge_connection_t *conn; + entry_connection_t *conn; rend_cache_entry_t *entry; + const rend_data_t *rend_data; time_t now = time(NULL); smartlist_t *conns = get_connection_array(); - SMARTLIST_FOREACH_BEGIN(conns, connection_t *, _conn) { - if (_conn->type != CONN_TYPE_AP || - _conn->state != AP_CONN_STATE_RENDDESC_WAIT || - _conn->marked_for_close) + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, base_conn) { + if (base_conn->type != CONN_TYPE_AP || + base_conn->state != AP_CONN_STATE_RENDDESC_WAIT || + base_conn->marked_for_close) continue; - conn = TO_EDGE_CONN(_conn); - if (!conn->rend_data) + conn = TO_ENTRY_CONN(base_conn); + rend_data = ENTRY_TO_EDGE_CONN(conn)->rend_data; + if (!rend_data) continue; - if (rend_cmp_service_ids(query, conn->rend_data->onion_address)) + if (rend_cmp_service_ids(query, rend_data->onion_address)) continue; - assert_connection_ok(TO_CONN(conn), now); - if (rend_cache_lookup_entry(conn->rend_data->onion_address, -1, + assert_connection_ok(base_conn, now); + if (rend_cache_lookup_entry(rend_data->onion_address, -1, &entry) == 1 && rend_client_any_intro_points_usable(entry)) { /* either this fetch worked, or it failed but there was a * valid entry from before which we should reuse */ log_info(LD_REND,"Rend desc is usable. Launching circuits."); - conn->_base.state = AP_CONN_STATE_CIRCUIT_WAIT; + base_conn->state = AP_CONN_STATE_CIRCUIT_WAIT; /* restart their timeout values, so they get a fair shake at * connecting to the hidden service. */ - conn->_base.timestamp_created = now; - conn->_base.timestamp_lastread = now; - conn->_base.timestamp_lastwritten = now; + base_conn->timestamp_created = now; + base_conn->timestamp_lastread = now; + base_conn->timestamp_lastwritten = now; if (connection_ap_handshake_attach_circuit(conn) < 0) { /* it will never work */ log_warn(LD_REND,"Rendezvous attempt failed. Closing."); - if (!conn->_base.marked_for_close) + if (!base_conn->marked_for_close) connection_mark_unattached_ap(conn, END_STREAM_REASON_CANT_ATTACH); } } else { /* 404, or fetch didn't get that far */ @@ -902,7 +947,7 @@ rend_client_desc_trynow(const char *query) connection_mark_unattached_ap(conn, END_STREAM_REASON_RESOLVEFAILED); rend_client_note_connection_attempt_ended(query); } - } SMARTLIST_FOREACH_END(_conn); + } SMARTLIST_FOREACH_END(base_conn); } /** Clear temporary state used only during an attempt to connect to @@ -925,6 +970,9 @@ rend_client_note_connection_attempt_ended(const char *onion_address) rend_intro_point_t *, ip, ip->timed_out = 0; ); } + + /* Remove the HS's entries in last_hid_serv_requests. */ + purge_hid_serv_from_last_hid_serv_requests(onion_address); } /** Return a newly allocated extend_info_t* for a randomly chosen introduction @@ -966,8 +1014,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; @@ -1000,21 +1047,33 @@ 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; + extend_info_t *new_extend_info; 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); + new_extend_info = extend_info_from_node(node); + if (!new_extend_info) { + log_info(LD_REND, "We don't have a descriptor for the intro-point relay " + "'%s'; trying another.", + extend_info_describe(intro->extend_info)); + smartlist_del(usable_nodes, i); + goto again; + } else { + extend_info_free(intro->extend_info); + intro->extend_info = new_extend_info; + } + tor_assert(intro->extend_info != NULL); } /* Check if we should refuse to talk to this router. */ - if (options->ExcludeNodes && strict && + if (strict && routerset_contains_extendinfo(options->ExcludeNodes, intro->extend_info)) { n_excluded++; @@ -1031,8 +1090,13 @@ rend_client_get_random_intro_impl(const rend_cache_entry_t *entry, int rend_client_any_intro_points_usable(const rend_cache_entry_t *entry) { - return rend_client_get_random_intro_impl( - entry, get_options()->StrictNodes, 0) != NULL; + extend_info_t *extend_info = + rend_client_get_random_intro_impl(entry, get_options()->StrictNodes, 0); + + int rv = (extend_info != NULL); + + extend_info_free(extend_info); + return rv; } /** Client-side authorizations for hidden services; map of onion address to @@ -1080,7 +1144,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 d87cb1fe3b..89da47789a 100644 --- a/src/or/rendclient.h +++ b/src/or/rendclient.h @@ -46,7 +46,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 2ca001d984..d09e6566c2 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -819,14 +819,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; @@ -854,10 +853,10 @@ rend_cache_purge(void) /** Remove all old v2 descriptors and those for which this hidden service * directory is not responsible for any more. */ void -rend_cache_clean_v2_descs_as_dir(void) +rend_cache_clean_v2_descs_as_dir(time_t now) { digestmap_iter_t *iter; - time_t cutoff = time(NULL) - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW; + time_t cutoff = now - REND_CACHE_MAX_AGE - REND_CACHE_MAX_SKEW; for (iter = digestmap_iter_init(rend_cache_v2_dir); !digestmap_iter_done(iter); ) { const char *key; diff --git a/src/or/rendcommon.h b/src/or/rendcommon.h index c51039f1f2..0d64466dbe 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 2c54f3059d..0ded538bef 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" @@ -188,14 +189,17 @@ rend_add_service(rend_service_t *service) if (service->auth_type != REND_NO_AUTH && smartlist_len(service->clients) == 0) { - log_warn(LD_CONFIG, "Hidden service with client authorization but no " - "clients; ignoring."); + log_warn(LD_CONFIG, "Hidden service (%s) with client authorization but no " + "clients; ignoring.", + escaped(service->directory)); rend_service_free(service); return; } if (!smartlist_len(service->ports)) { - log_warn(LD_CONFIG, "Hidden service with no ports configured; ignoring."); + log_warn(LD_CONFIG, "Hidden service (%s) with no ports configured; " + "ignoring.", + escaped(service->directory)); rend_service_free(service); } else { int dupe = 0; @@ -274,7 +278,7 @@ parse_port_config(const char *string) } else { addrport = smartlist_get(sl,1); if (strchr(addrport, ':') || strchr(addrport, '.')) { - if (tor_addr_port_parse(addrport, &addr, &p)<0) { + if (tor_addr_port_lookup(addrport, &addr, &p)<0) { log_warn(LD_CONFIG,"Unparseable address in hidden service port " "configuration."); goto err; @@ -308,7 +312,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; @@ -946,8 +950,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, @@ -1101,7 +1106,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; @@ -1128,8 +1133,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? */ @@ -1137,7 +1142,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) { @@ -1147,7 +1152,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, } /* Check if we'd refuse to talk to this router */ - if (options->ExcludeNodes && options->StrictNodes && + if (options->StrictNodes && routerset_contains_extendinfo(options->ExcludeNodes, extend_info)) { log_warn(LD_REND, "Client asked to rendezvous at a relay that we " "exclude, and StrictNodes is set. Refusing service."); @@ -1435,6 +1440,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); @@ -1454,7 +1460,7 @@ rend_service_intro_has_opened(origin_circuit_t *circuit) * redefine this one as a general circuit or close it, depending. */ if (count_established_intro_points(serviceid) > (int)service->n_intro_points_wanted) { /* XXX023 remove cast */ - 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, @@ -1468,7 +1474,20 @@ rend_service_intro_has_opened(origin_circuit_t *circuit) log_info(LD_CIRC|LD_REND, "We have just finished an introduction " "circuit, but we already have enough. Redefining purpose to " "general; leaving as internal."); + TO_CIRCUIT(circuit)->purpose = CIRCUIT_PURPOSE_C_GENERAL; + + { + rend_data_t *rend_data = circuit->rend_data; + circuit->rend_data = NULL; + rend_data_free(rend_data); + } + { + crypto_pk_env_t *intro_key = circuit->intro_key; + circuit->intro_key = NULL; + crypto_free_pk_env(intro_key); + } + circuit_has_opened(circuit); return; } @@ -1578,6 +1597,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); @@ -1735,12 +1755,14 @@ directory_post_to_hs_dir(rend_service_descriptor_t *renddesc, for (j = 0; j < smartlist_len(responsible_dirs); j++) { char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1]; char *hs_dir_ip; + const node_t *node; hs_dir = smartlist_get(responsible_dirs, j); if (smartlist_digest_isin(renddesc->successful_uploads, hs_dir->identity_digest)) /* Don't upload descriptor if we succeeded in doing so last time. */ continue; - if (!router_get_by_digest(hs_dir->identity_digest)) { + node = node_get_by_id(hs_dir->identity_digest); + if (!node || !node_has_descriptor(node)) { log_info(LD_REND, "Not sending publish request for v2 descriptor to " "hidden service directory %s; we don't have its " "router descriptor. Queuing for later upload.", @@ -1963,21 +1985,21 @@ 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 intro_point_set_changed, prev_intro_nodes; unsigned int n_intro_points_unexpired; unsigned int n_intro_points_to_open; - 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); @@ -2024,8 +2046,8 @@ rend_services_introduce(void) continue; } - router = router_get_by_digest(intro->extend_info->identity_digest); - if (!router || !intro_circ) { + node = node_get_by_id(intro->extend_info->identity_digest); + if (!node || !intro_circ) { int removing_this_intro_point_changes_the_intro_point_set = 1; log_info(LD_REND, "Giving up on %s as intro point for %s" " (circuit disappeared).", @@ -2071,8 +2093,8 @@ rend_services_introduce(void) if (intro != NULL && intro->time_expiring == -1) ++n_intro_points_unexpired; - if (router) - smartlist_add(intro_routers, router); + if (node) + smartlist_add(intro_nodes, (void*)node); } SMARTLIST_FOREACH_END(intro); if (!intro_point_set_changed && @@ -2113,12 +2135,12 @@ rend_services_introduce(void) for (j = (int)n_intro_points_unexpired; j < (int)n_intro_points_to_open; ++j) { /* XXXX remove casts */ - 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; " "wanted %u.", @@ -2127,9 +2149,9 @@ rend_services_introduce(void) break; } intro_point_set_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)); intro->time_published = -1; @@ -2137,7 +2159,7 @@ rend_services_introduce(void) intro->time_expiring = -1; smartlist_add(service->intro_nodes, intro); log_info(LD_REND, "Picked router %s as an intro point for %s.", - safe_str_client(router_describe(router)), + safe_str_client(node_describe(node)), safe_str_client(service->service_id)); } @@ -2156,7 +2178,7 @@ rend_services_introduce(void) } } } - smartlist_free(intro_routers); + smartlist_free(intro_nodes); } /** Regenerate and upload rendezvous service descriptors for all diff --git a/src/or/rendservice.h b/src/or/rendservice.h index 70389afe9a..8a2994c4c0 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 1dd3d94fd0..6bbb93b821 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" @@ -643,7 +644,7 @@ rep_hist_dump_stats(time_t now, int severity) size_t len; int ret; unsigned long upt, downt; - routerinfo_t *r; + const node_t *node; rep_history_clean(now - get_options()->RephistTrackTime); @@ -657,8 +658,8 @@ rep_hist_dump_stats(time_t now, int severity) digestmap_iter_get(orhist_it, &digest1, &or_history_p); or_history = (or_history_t*) or_history_p; - if ((r = router_get_by_digest(digest1))) - name1 = r->nickname; + if ((node = node_get_by_id(digest1)) && node_get_nickname(node)) + name1 = node_get_nickname(node); else name1 = "(unknown)"; base16_encode(hexdigest1, sizeof(hexdigest1), digest1, DIGEST_LEN); @@ -688,8 +689,8 @@ rep_hist_dump_stats(time_t now, int severity) lhist_it = digestmap_iter_next(or_history->link_history_map, lhist_it)) { digestmap_iter_get(lhist_it, &digest2, &link_history_p); - if ((r = router_get_by_digest(digest2))) - name2 = r->nickname; + if ((node = node_get_by_id(digest2)) && node_get_nickname(node)) + name2 = node_get_nickname(node); else name2 = "(unknown)"; @@ -823,7 +824,7 @@ rep_hist_record_mtbf_data(time_t now, int missing_means_down) base16_encode(dbuf, sizeof(dbuf), digest, DIGEST_LEN); if (missing_means_down && hist->start_of_run && - !router_get_by_digest(digest)) { + !router_get_by_id_digest(digest)) { /* We think this relay is running, but it's not listed in our * routerlist. Somehow it fell out without telling us it went * down. Complain and also correct it. */ @@ -938,28 +939,32 @@ rep_hist_get_router_stability_doc(time_t now) } DIGESTMAP_FOREACH(history_map, id, or_history_t *, hist) { - routerinfo_t *ri; + const node_t *node; char dbuf[BASE64_DIGEST_LEN+1]; char header_buf[512]; char *info; digest_to_base64(dbuf, id); - ri = router_get_by_digest(id); - if (ri) { - char *ip = tor_dup_ip(ri->addr); + node = node_get_by_id(id); + if (node) { + char ip[INET_NTOA_BUF_LEN+1]; char tbuf[ISO_TIME_LEN+1]; - format_iso_time(tbuf, ri->cache_info.published_on); + time_t published = node_get_published_on(node); + node_get_address_string(node,ip,sizeof(ip)); + if (published > 0) + format_iso_time(tbuf, published); + else + strlcpy(tbuf, "???", sizeof(tbuf)); tor_snprintf(header_buf, sizeof(header_buf), "router %s %s %s\n" "published %s\n" "relevant-flags %s%s%s\n" "declared-uptime %ld\n", - dbuf, ri->nickname, ip, + dbuf, node_get_nickname(node), ip, tbuf, - ri->is_running ? "Running " : "", - ri->is_valid ? "Valid " : "", - ri->is_hibernating ? "Hibernating " : "", - ri->uptime); - tor_free(ip); + node->is_running ? "Running " : "", + node->is_valid ? "Valid " : "", + node->ri && node->ri->is_hibernating ? "Hibernating " : "", + node_get_declared_uptime(node)); } else { tor_snprintf(header_buf, sizeof(header_buf), "router %s {no descriptor}\n", dbuf); @@ -1474,7 +1479,7 @@ rep_hist_fill_bandwidth_history(char *buf, size_t len, const bw_array_t *b) { char *cp = buf; int i, n; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); uint64_t cutoff; if (b->num_maxes_set <= b->next_max_idx) { @@ -1770,10 +1775,13 @@ rep_hist_load_state(or_state_t *state, char **err) /*********************************************************************/ +typedef struct predicted_port_t { + uint16_t port; + time_t time; +} predicted_port_t; + /** A list of port numbers that have been used recently. */ static smartlist_t *predicted_ports_list=NULL; -/** The corresponding most recently used time for each port. */ -static smartlist_t *predicted_ports_times=NULL; /** We just got an application request for a connection with * port <b>port</b>. Remember it for the future, so we can keep @@ -1782,14 +1790,11 @@ static smartlist_t *predicted_ports_times=NULL; static void add_predicted_port(time_t now, uint16_t port) { - /* XXXX we could just use uintptr_t here, I think. -NM */ - uint16_t *tmp_port = tor_malloc(sizeof(uint16_t)); - time_t *tmp_time = tor_malloc(sizeof(time_t)); - *tmp_port = port; - *tmp_time = now; - rephist_total_alloc += sizeof(uint16_t) + sizeof(time_t); - smartlist_add(predicted_ports_list, tmp_port); - smartlist_add(predicted_ports_times, tmp_time); + predicted_port_t *pp = tor_malloc(sizeof(predicted_port_t)); + pp->port = port; + pp->time = now; + rephist_total_alloc += sizeof(*pp); + smartlist_add(predicted_ports_list, pp); } /** Initialize whatever memory and structs are needed for predicting @@ -1800,7 +1805,6 @@ static void predicted_ports_init(void) { predicted_ports_list = smartlist_create(); - predicted_ports_times = smartlist_create(); add_predicted_port(time(NULL), 80); /* add one to kickstart us */ } @@ -1810,12 +1814,11 @@ predicted_ports_init(void) static void predicted_ports_free(void) { - rephist_total_alloc -= smartlist_len(predicted_ports_list)*sizeof(uint16_t); - SMARTLIST_FOREACH(predicted_ports_list, char *, cp, tor_free(cp)); + rephist_total_alloc -= + smartlist_len(predicted_ports_list)*sizeof(predicted_port_t); + SMARTLIST_FOREACH(predicted_ports_list, predicted_port_t *, + pp, tor_free(pp)); smartlist_free(predicted_ports_list); - rephist_total_alloc -= smartlist_len(predicted_ports_times)*sizeof(time_t); - SMARTLIST_FOREACH(predicted_ports_times, char *, cp, tor_free(cp)); - smartlist_free(predicted_ports_times); } /** Remember that <b>port</b> has been asked for as of time <b>now</b>. @@ -1825,24 +1828,17 @@ predicted_ports_free(void) void rep_hist_note_used_port(time_t now, uint16_t port) { - int i; - uint16_t *tmp_port; - time_t *tmp_time; - tor_assert(predicted_ports_list); - tor_assert(predicted_ports_times); if (!port) /* record nothing */ return; - for (i = 0; i < smartlist_len(predicted_ports_list); ++i) { - tmp_port = smartlist_get(predicted_ports_list, i); - tmp_time = smartlist_get(predicted_ports_times, i); - if (*tmp_port == port) { - *tmp_time = now; + SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) { + if (pp->port == port) { + pp->time = now; return; } - } + } SMARTLIST_FOREACH_END(pp); /* it's not there yet; we need to add it */ add_predicted_port(now, port); } @@ -1851,36 +1847,28 @@ rep_hist_note_used_port(time_t now, uint16_t port) * we'll want to make connections to the same port in the future. */ #define PREDICTED_CIRCS_RELEVANCE_TIME (60*60) -/** Return a pointer to the list of port numbers that +/** Return a newly allocated pointer to a list of uint16_t * for ports that * are likely to be asked for in the near future. - * - * The caller promises not to mess with it. */ smartlist_t * rep_hist_get_predicted_ports(time_t now) { - int i; - uint16_t *tmp_port; - time_t *tmp_time; - + smartlist_t *out = smartlist_create(); tor_assert(predicted_ports_list); - tor_assert(predicted_ports_times); /* clean out obsolete entries */ - for (i = 0; i < smartlist_len(predicted_ports_list); ++i) { - tmp_time = smartlist_get(predicted_ports_times, i); - if (*tmp_time + PREDICTED_CIRCS_RELEVANCE_TIME < now) { - tmp_port = smartlist_get(predicted_ports_list, i); - log_debug(LD_CIRC, "Expiring predicted port %d", *tmp_port); - smartlist_del(predicted_ports_list, i); - smartlist_del(predicted_ports_times, i); - rephist_total_alloc -= sizeof(uint16_t)+sizeof(time_t); - tor_free(tmp_port); - tor_free(tmp_time); - i--; + SMARTLIST_FOREACH_BEGIN(predicted_ports_list, predicted_port_t *, pp) { + if (pp->time + PREDICTED_CIRCS_RELEVANCE_TIME < now) { + log_debug(LD_CIRC, "Expiring predicted port %d", pp->port); + + rephist_total_alloc -= sizeof(predicted_port_t); + tor_free(pp); + SMARTLIST_DEL_CURRENT(predicted_ports_list, pp); + } else { + smartlist_add(out, tor_memdup(&pp->port, sizeof(uint16_t))); } - } - return predicted_ports_list; + } SMARTLIST_FOREACH_END(pp); + return out; } /** The user asked us to do a resolve. Rather than keeping track of @@ -2116,7 +2104,9 @@ rep_hist_exit_stats_term(void) tor_free(exit_streams); } -/** Helper for qsort: compare two ints. */ +/** Helper for qsort: compare two ints. Does not handle overflow properly, + * but works fine for sorting an array of port numbers, which is what we use + * it for. */ static int _compare_int(const void *x, const void *y) { @@ -2124,7 +2114,8 @@ _compare_int(const void *x, const void *y) } /** Return a newly allocated string containing the exit port statistics - * until <b>now</b>, or NULL if we're not collecting exit stats. */ + * until <b>now</b>, or NULL if we're not collecting exit stats. Caller + * must ensure start_of_exit_stats_interval is in the past. */ char * rep_hist_format_exit_stats(time_t now) { @@ -2143,6 +2134,8 @@ rep_hist_format_exit_stats(time_t now) if (!start_of_exit_stats_interval) return NULL; /* Not initialized. */ + tor_assert(now >= start_of_exit_stats_interval); + /* Go through all ports to find the n ports that saw most written and * read bytes. * @@ -2374,41 +2367,60 @@ typedef struct circ_buffer_stats_t { /** List of circ_buffer_stats_t. */ static smartlist_t *circuits_for_buffer_stats = NULL; +/** Remember cell statistics <b>mean_num_cells_in_queue</b>, + * <b>mean_time_cells_in_queue</b>, and <b>processed_cells</b> of a + * circuit. */ +void +rep_hist_add_buffer_stats(double mean_num_cells_in_queue, + double mean_time_cells_in_queue, uint32_t processed_cells) +{ + circ_buffer_stats_t *stat; + if (!start_of_buffer_stats_interval) + return; /* Not initialized. */ + stat = tor_malloc_zero(sizeof(circ_buffer_stats_t)); + stat->mean_num_cells_in_queue = mean_num_cells_in_queue; + stat->mean_time_cells_in_queue = mean_time_cells_in_queue; + stat->processed_cells = processed_cells; + if (!circuits_for_buffer_stats) + circuits_for_buffer_stats = smartlist_create(); + smartlist_add(circuits_for_buffer_stats, stat); +} + /** Remember cell statistics for circuit <b>circ</b> at time * <b>end_of_interval</b> and reset cell counters in case the circuit * remains open in the next measurement interval. */ void rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval) { - circ_buffer_stats_t *stat; time_t start_of_interval; int interval_length; or_circuit_t *orcirc; + double mean_num_cells_in_queue, mean_time_cells_in_queue; + uint32_t processed_cells; if (CIRCUIT_IS_ORIGIN(circ)) return; orcirc = TO_OR_CIRCUIT(circ); if (!orcirc->processed_cells) return; - if (!circuits_for_buffer_stats) - circuits_for_buffer_stats = smartlist_create(); - start_of_interval = circ->timestamp_created.tv_sec > - start_of_buffer_stats_interval ? + start_of_interval = (circ->timestamp_created.tv_sec > + start_of_buffer_stats_interval) ? circ->timestamp_created.tv_sec : start_of_buffer_stats_interval; interval_length = (int) (end_of_interval - start_of_interval); if (interval_length <= 0) return; - stat = tor_malloc_zero(sizeof(circ_buffer_stats_t)); - stat->processed_cells = orcirc->processed_cells; + processed_cells = orcirc->processed_cells; /* 1000.0 for s -> ms; 2.0 because of app-ward and exit-ward queues */ - stat->mean_num_cells_in_queue = (double) orcirc->total_cell_waiting_time / + mean_num_cells_in_queue = (double) orcirc->total_cell_waiting_time / (double) interval_length / 1000.0 / 2.0; - stat->mean_time_cells_in_queue = + mean_time_cells_in_queue = (double) orcirc->total_cell_waiting_time / (double) orcirc->processed_cells; - smartlist_add(circuits_for_buffer_stats, stat); orcirc->total_cell_waiting_time = 0; orcirc->processed_cells = 0; + rep_hist_add_buffer_stats(mean_num_cells_in_queue, + mean_time_cells_in_queue, + processed_cells); } /** Sorting helper: return -1, 1, or 0 based on comparison of two @@ -2430,136 +2442,536 @@ _buffer_stats_compare_entries(const void **_a, const void **_b) void rep_hist_buffer_stats_term(void) { - start_of_buffer_stats_interval = 0; + rep_hist_reset_buffer_stats(0); +} + +/** Clear history of circuit statistics and set the measurement interval + * start to <b>now</b>. */ +void +rep_hist_reset_buffer_stats(time_t now) +{ if (!circuits_for_buffer_stats) circuits_for_buffer_stats = smartlist_create(); SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *, stat, tor_free(stat)); smartlist_clear(circuits_for_buffer_stats); + start_of_buffer_stats_interval = now; } -/** Write buffer statistics to $DATADIR/stats/buffer-stats and return when - * we would next want to write exit stats. */ -time_t -rep_hist_buffer_stats_write(time_t now) +/** Return a newly allocated string containing the buffer statistics until + * <b>now</b>, or NULL if we're not collecting buffer stats. Caller must + * ensure start_of_buffer_stats_interval is in the past. */ +char * +rep_hist_format_buffer_stats(time_t now) { - char *statsdir = NULL, *filename = NULL; - char written[ISO_TIME_LEN+1]; - open_file_t *open_file = NULL; - FILE *out; #define SHARES 10 int processed_cells[SHARES], circs_in_share[SHARES], number_of_circuits, i; double queued_cells[SHARES], time_in_queue[SHARES]; - smartlist_t *str_build = NULL; - char *str = NULL, *buf = NULL; - circuit_t *circ; + char *buf = NULL; + smartlist_t *processed_cells_strings, *queued_cells_strings, + *time_in_queue_strings; + char *processed_cells_string, *queued_cells_string, + *time_in_queue_string; + char t[ISO_TIME_LEN+1]; + char *result; if (!start_of_buffer_stats_interval) - return 0; /* Not initialized. */ - if (start_of_buffer_stats_interval + WRITE_STATS_INTERVAL > now) - goto done; /* Not ready to write */ + return NULL; /* Not initialized. */ - str_build = smartlist_create(); + tor_assert(now >= start_of_buffer_stats_interval); - /* add current circuits to stats */ - for (circ = _circuit_get_global_list(); circ; circ = circ->next) - rep_hist_buffer_stats_add_circ(circ, now); - /* calculate deciles */ + /* Calculate deciles if we saw at least one circuit. */ memset(processed_cells, 0, SHARES * sizeof(int)); memset(circs_in_share, 0, SHARES * sizeof(int)); memset(queued_cells, 0, SHARES * sizeof(double)); memset(time_in_queue, 0, SHARES * sizeof(double)); if (!circuits_for_buffer_stats) circuits_for_buffer_stats = smartlist_create(); - smartlist_sort(circuits_for_buffer_stats, - _buffer_stats_compare_entries); number_of_circuits = smartlist_len(circuits_for_buffer_stats); - if (number_of_circuits < 1) { - log_info(LD_HIST, "Attempt to write cell statistics to disk failed. " - "We haven't seen a single circuit to report about."); - goto done; + if (number_of_circuits > 0) { + smartlist_sort(circuits_for_buffer_stats, + _buffer_stats_compare_entries); + i = 0; + SMARTLIST_FOREACH_BEGIN(circuits_for_buffer_stats, + circ_buffer_stats_t *, stat) + { + int share = i++ * SHARES / number_of_circuits; + processed_cells[share] += stat->processed_cells; + queued_cells[share] += stat->mean_num_cells_in_queue; + time_in_queue[share] += stat->mean_time_cells_in_queue; + circs_in_share[share]++; + } + SMARTLIST_FOREACH_END(stat); } - i = 0; - SMARTLIST_FOREACH_BEGIN(circuits_for_buffer_stats, - circ_buffer_stats_t *, stat) - { - int share = i++ * SHARES / number_of_circuits; - processed_cells[share] += stat->processed_cells; - queued_cells[share] += stat->mean_num_cells_in_queue; - time_in_queue[share] += stat->mean_time_cells_in_queue; - circs_in_share[share]++; - } - SMARTLIST_FOREACH_END(stat); - /* clear buffer stats history */ - SMARTLIST_FOREACH(circuits_for_buffer_stats, circ_buffer_stats_t *, - stat, tor_free(stat)); - smartlist_clear(circuits_for_buffer_stats); - /* write to file */ - statsdir = get_datadir_fname("stats"); - if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) - goto done; - filename = get_datadir_fname2("stats", "buffer-stats"); - out = start_writing_to_stdio_file(filename, OPEN_FLAGS_APPEND | O_TEXT, - 0600, &open_file); - if (!out) - goto done; - format_iso_time(written, now); - if (fprintf(out, "cell-stats-end %s (%d s)\n", written, - (unsigned) (now - start_of_buffer_stats_interval)) < 0) - goto done; + + /* Write deciles to strings. */ + processed_cells_strings = smartlist_create(); + queued_cells_strings = smartlist_create(); + time_in_queue_strings = smartlist_create(); for (i = 0; i < SHARES; i++) { tor_asprintf(&buf,"%d", !circs_in_share[i] ? 0 : processed_cells[i] / circs_in_share[i]); - smartlist_add(str_build, buf); + smartlist_add(processed_cells_strings, buf); } - str = smartlist_join_strings(str_build, ",", 0, NULL); - if (fprintf(out, "cell-processed-cells %s\n", str) < 0) - goto done; - tor_free(str); - SMARTLIST_FOREACH(str_build, char *, c, tor_free(c)); - smartlist_clear(str_build); for (i = 0; i < SHARES; i++) { tor_asprintf(&buf, "%.2f", circs_in_share[i] == 0 ? 0.0 : queued_cells[i] / (double) circs_in_share[i]); - smartlist_add(str_build, buf); + smartlist_add(queued_cells_strings, buf); } - str = smartlist_join_strings(str_build, ",", 0, NULL); - if (fprintf(out, "cell-queued-cells %s\n", str) < 0) - goto done; - tor_free(str); - SMARTLIST_FOREACH(str_build, char *, c, tor_free(c)); - smartlist_clear(str_build); for (i = 0; i < SHARES; i++) { tor_asprintf(&buf, "%.0f", circs_in_share[i] == 0 ? 0.0 : time_in_queue[i] / (double) circs_in_share[i]); - smartlist_add(str_build, buf); + smartlist_add(time_in_queue_strings, buf); } - str = smartlist_join_strings(str_build, ",", 0, NULL); - if (fprintf(out, "cell-time-in-queue %s\n", str) < 0) - goto done; - tor_free(str); - SMARTLIST_FOREACH(str_build, char *, c, tor_free(c)); - smartlist_free(str_build); - str_build = NULL; - if (fprintf(out, "cell-circuits-per-decile %d\n", - (number_of_circuits + SHARES - 1) / SHARES) < 0) + + /* Join all observations in single strings. */ + processed_cells_string = smartlist_join_strings(processed_cells_strings, + ",", 0, NULL); + queued_cells_string = smartlist_join_strings(queued_cells_strings, + ",", 0, NULL); + time_in_queue_string = smartlist_join_strings(time_in_queue_strings, + ",", 0, NULL); + SMARTLIST_FOREACH(processed_cells_strings, char *, cp, tor_free(cp)); + SMARTLIST_FOREACH(queued_cells_strings, char *, cp, tor_free(cp)); + SMARTLIST_FOREACH(time_in_queue_strings, char *, cp, tor_free(cp)); + smartlist_free(processed_cells_strings); + smartlist_free(queued_cells_strings); + smartlist_free(time_in_queue_strings); + + /* Put everything together. */ + format_iso_time(t, now); + tor_asprintf(&result, "cell-stats-end %s (%d s)\n" + "cell-processed-cells %s\n" + "cell-queued-cells %s\n" + "cell-time-in-queue %s\n" + "cell-circuits-per-decile %d\n", + t, (unsigned) (now - start_of_buffer_stats_interval), + processed_cells_string, + queued_cells_string, + time_in_queue_string, + (number_of_circuits + SHARES - 1) / SHARES); + tor_free(processed_cells_string); + tor_free(queued_cells_string); + tor_free(time_in_queue_string); + return result; +#undef SHARES +} + +/** If 24 hours have passed since the beginning of the current buffer + * stats period, write buffer stats to $DATADIR/stats/buffer-stats + * (possibly overwriting an existing file) and reset counters. Return + * when we would next want to write buffer stats or 0 if we never want to + * write. */ +time_t +rep_hist_buffer_stats_write(time_t now) +{ + circuit_t *circ; + char *statsdir = NULL, *filename = NULL, *str = NULL; + + if (!start_of_buffer_stats_interval) + return 0; /* Not initialized. */ + if (start_of_buffer_stats_interval + WRITE_STATS_INTERVAL > now) + goto done; /* Not ready to write */ + + /* Add open circuits to the history. */ + for (circ = _circuit_get_global_list(); circ; circ = circ->next) { + rep_hist_buffer_stats_add_circ(circ, now); + } + + /* Generate history string. */ + str = rep_hist_format_buffer_stats(now); + + /* Reset both buffer history and counters of open circuits. */ + rep_hist_reset_buffer_stats(now); + + /* Try to write to disk. */ + statsdir = get_datadir_fname("stats"); + if (check_private_dir(statsdir, CPD_CREATE, get_options()->User) < 0) { + log_warn(LD_HIST, "Unable to create stats/ directory!"); goto done; - finish_writing_to_file(open_file); - open_file = NULL; - start_of_buffer_stats_interval = now; + } + filename = get_datadir_fname2("stats", "buffer-stats"); + if (write_str_to_file(filename, str, 0) < 0) + log_warn(LD_HIST, "Unable to write buffer stats to disk!"); + done: - if (open_file) - abort_writing_to_file(open_file); + tor_free(str); tor_free(filename); tor_free(statsdir); - if (str_build) { - SMARTLIST_FOREACH(str_build, char *, c, tor_free(c)); - smartlist_free(str_build); + return start_of_buffer_stats_interval + WRITE_STATS_INTERVAL; +} + +/*** Descriptor serving statistics ***/ + +/** Digestmap to track which descriptors were downloaded this stats + * collection interval. It maps descriptor digest to pointers to 1, + * effectively turning this into a list. */ +static digestmap_t *served_descs = NULL; + +/** Number of how many descriptors were downloaded in total during this + * interval. */ +static unsigned long total_descriptor_downloads; + +/** Start time of served descs stats or 0 if we're not collecting those. */ +static time_t start_of_served_descs_stats_interval; + +/** Initialize descriptor stats. */ +void +rep_hist_desc_stats_init(time_t now) +{ + if (served_descs) { + log_warn(LD_BUG, "Called rep_hist_desc_stats_init() when desc stats were " + "already initialized. This is probably harmless."); + return; // Already initialized } + served_descs = digestmap_new(); + total_descriptor_downloads = 0; + start_of_served_descs_stats_interval = now; +} + +/** Reset served descs stats to empty, starting a new interval <b>now</b>. */ +static void +rep_hist_reset_desc_stats(time_t now) +{ + rep_hist_desc_stats_term(); + rep_hist_desc_stats_init(now); +} + +/** Stop collecting served descs stats, so that rep_hist_desc_stats_init() is + * safe to be called again. */ +void +rep_hist_desc_stats_term(void) +{ + digestmap_free(served_descs, NULL); + served_descs = NULL; + start_of_served_descs_stats_interval = 0; + total_descriptor_downloads = 0; +} + +/** Helper for rep_hist_desc_stats_write(). Return a newly allocated string + * containing the served desc statistics until now, or NULL if we're not + * collecting served desc stats. Caller must ensure that now is not before + * start_of_served_descs_stats_interval. */ +static char * +rep_hist_format_desc_stats(time_t now) +{ + char t[ISO_TIME_LEN+1]; + char *result; + + digestmap_iter_t *iter; + const char *key; + void *val; + unsigned size; + int *vals; + int n = 0; + + if (!start_of_served_descs_stats_interval) + return NULL; + + size = digestmap_size(served_descs); + vals = tor_malloc(size * sizeof(int)); + + for (iter = digestmap_iter_init(served_descs); !digestmap_iter_done(iter); + iter = digestmap_iter_next(served_descs, iter) ) { + uintptr_t count; + digestmap_iter_get(iter, &key, &val); + count = (uintptr_t)val; + vals[n++] = (int)count; + (void)key; + } + + format_iso_time(t, now); + + tor_asprintf(&result, + "served-descs-stats-end %s (%d s) total=%lu unique=%u " + "max=%d q3=%d md=%d q1=%d min=%d\n", + t, + (unsigned) (now - start_of_served_descs_stats_interval), + total_descriptor_downloads, + size, + find_nth_int(vals, size, size-1), + find_nth_int(vals, size, (3*size-1)/4), + find_nth_int(vals, size, (size-1)/2), + find_nth_int(vals, size, (size-1)/4), + find_nth_int(vals, size, 0)); + + tor_free(vals); + return result; +} + +/** If WRITE_STATS_INTERVAL seconds have passed since the beginning of + * the current served desc stats interval, write the stats to + * $DATADIR/stats/served-desc-stats (possibly appending to an existing file) + * and reset the state for the next interval. Return when we would next want + * to write served desc stats or 0 if we won't want to write. */ +time_t +rep_hist_desc_stats_write(time_t now) +{ + char *statsdir = NULL, *filename = NULL, *str = NULL; + + if (!start_of_served_descs_stats_interval) + return 0; /* We're not collecting stats. */ + if (start_of_served_descs_stats_interval + WRITE_STATS_INTERVAL > now) + return start_of_served_descs_stats_interval + WRITE_STATS_INTERVAL; + + str = rep_hist_format_desc_stats(now); + + 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", "served-desc-stats"); + if (append_bytes_to_file(filename, str, strlen(str), 0) < 0) + log_warn(LD_HIST, "Unable to write served descs statistics to disk!"); + + rep_hist_reset_desc_stats(now); + + done: + tor_free(statsdir); + tor_free(filename); tor_free(str); -#undef SHARES - return start_of_buffer_stats_interval + WRITE_STATS_INTERVAL; + return start_of_served_descs_stats_interval + WRITE_STATS_INTERVAL; +} + +void +rep_hist_note_desc_served(const char * desc) +{ + void *val; + uintptr_t count; + if (!served_descs) + return; // We're not collecting stats + val = digestmap_get(served_descs, desc); + count = (uintptr_t)val; + if (count != INT_MAX) + ++count; + digestmap_set(served_descs, desc, (void*)count); + total_descriptor_downloads++; +} + +/*** 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. Caller must + * ensure start_of_conn_stats_interval is in the past. */ +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. */ + + tor_assert(now >= start_of_conn_stats_interval); + + 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 @@ -2576,11 +2988,15 @@ 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)); smartlist_free(circuits_for_buffer_stats); circuits_for_buffer_stats = NULL; } + rep_hist_desc_stats_term(); + total_descriptor_downloads = 0; } diff --git a/src/or/rephist.h b/src/or/rephist.h index b06a39ed59..0a3e46ae1a 100644 --- a/src/or/rephist.h +++ b/src/or/rephist.h @@ -77,6 +77,23 @@ void rep_hist_buffer_stats_add_circ(circuit_t *circ, time_t end_of_interval); time_t rep_hist_buffer_stats_write(time_t now); void rep_hist_buffer_stats_term(void); +void rep_hist_add_buffer_stats(double mean_num_cells_in_queue, + double mean_time_cells_in_queue, uint32_t processed_cells); +char *rep_hist_format_buffer_stats(time_t now); +void rep_hist_reset_buffer_stats(time_t now); + +void rep_hist_desc_stats_init(time_t now); +void rep_hist_note_desc_served(const char * desc); +void rep_hist_desc_stats_term(void); +time_t rep_hist_desc_stats_write(time_t now); + +void rep_hist_conn_stats_init(time_t now); +void rep_hist_note_or_conn_bytes(uint64_t conn_id, size_t num_read, + size_t num_written, time_t when); +void rep_hist_reset_conn_stats(time_t now); +char *rep_hist_format_conn_stats(time_t now); +time_t rep_hist_conn_stats_write(time_t now); +void rep_hist_conn_stats_term(void); #endif diff --git a/src/or/router.c b/src/or/router.c index 365e888af9..8fe45dd6f8 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -7,6 +7,7 @@ #define ROUTER_PRIVATE #include "or.h" +#include "circuitbuild.h" #include "circuitlist.h" #include "circuituse.h" #include "config.h" @@ -19,6 +20,7 @@ #include "hibernate.h" #include "main.h" #include "networkstatus.h" +#include "nodelist.h" #include "policies.h" #include "relay.h" #include "rephist.h" @@ -82,6 +84,11 @@ static authority_cert_t *legacy_key_certificate = NULL; static void set_onion_key(crypto_pk_env_t *k) { + if (onionkey && !crypto_pk_cmp_keys(onionkey, k)) { + /* k is already our onion key; free it and return */ + crypto_free_pk_env(k); + return; + } tor_mutex_acquire(key_lock); crypto_free_pk_env(onionkey); onionkey = k; @@ -149,8 +156,8 @@ assert_identity_keys_ok(void) } else { /* assert that we have set the client and server keys to be unequal */ if (server_identitykey) - tor_assert(0!=crypto_pk_cmp_keys(client_identitykey, - server_identitykey)); + tor_assert(0!=crypto_pk_cmp_keys(client_identitykey, + server_identitykey)); } } @@ -477,6 +484,16 @@ v3_authority_check_key_expiry(void) last_warned = now; } +int +router_initialize_tls_context(void) +{ + return tor_tls_context_init(public_server_mode(get_options()), + get_tlsclient_identity_key(), + server_mode(get_options()) ? + get_server_identity_key() : NULL, + MAX_SSL_KEY_LIFETIME_ADVERTISED); +} + /** Initialize all OR private keys, and the TLS context, as necessary. * On OPs, this only initializes the tls context. Return 0 on success, * or -1 if Tor should die. @@ -493,8 +510,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; @@ -523,10 +540,7 @@ init_keys(void) } set_client_identity_key(prkey); /* Create a TLS context. */ - if (tor_tls_context_init(0, - get_tlsclient_identity_key(), - NULL, - MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { + if (router_initialize_tls_context() < 0) { log_err(LD_GENERAL,"Error creating TLS context for Tor client."); return -1; } @@ -619,13 +633,11 @@ init_keys(void) tor_free(keydir); /* 3. Initialize link key and TLS context. */ - if (tor_tls_context_init(public_server_mode(options), - get_tlsclient_identity_key(), - get_server_identity_key(), - MAX_SSL_KEY_LIFETIME_ADVERTISED) < 0) { + if (router_initialize_tls_context() < 0) { log_err(LD_GENERAL,"Error initializing TLS context"); return -1; } + /* 4. Build our router descriptor. */ /* Must be called after keys are initialized. */ mydesc = router_get_my_descriptor(); @@ -695,11 +707,12 @@ init_keys(void) } /* 6b. [authdirserver only] add own key to approved directories. */ crypto_pk_get_digest(get_server_identity_key(), digest); - type = ((options->V1AuthoritativeDir ? V1_AUTHORITY : NO_AUTHORITY) | - (options->V2AuthoritativeDir ? V2_AUTHORITY : NO_AUTHORITY) | - (options->V3AuthoritativeDir ? V3_AUTHORITY : NO_AUTHORITY) | - (options->BridgeAuthoritativeDir ? BRIDGE_AUTHORITY : NO_AUTHORITY) | - (options->HSAuthoritativeDir ? HIDSERV_AUTHORITY : NO_AUTHORITY)); + type = ((options->V1AuthoritativeDir ? V1_DIRINFO : NO_DIRINFO) | + (options->V2AuthoritativeDir ? V2_DIRINFO : NO_DIRINFO) | + (options->V3AuthoritativeDir ? + (V3_DIRINFO|MICRODESC_DIRINFO|EXTRAINFO_DIRINFO) : NO_DIRINFO) | + (options->BridgeAuthoritativeDir ? BRIDGE_DIRINFO : NO_DIRINFO) | + (options->HSAuthoritativeDir ? HIDSERV_DIRINFO : NO_DIRINFO)); ds = router_get_trusteddirserver_by_digest(digest); if (!ds) { @@ -721,7 +734,7 @@ init_keys(void) type, ds->type); ds->type = type; } - if (v3_digest_set && (ds->type & V3_AUTHORITY) && + if (v3_digest_set && (ds->type & V3_DIRINFO) && tor_memneq(v3_digest, ds->v3_identity_digest, DIGEST_LEN)) { log_warn(LD_DIR, "V3 identity key does not match identity declared in " "DirServer line. Adjusting."); @@ -760,7 +773,7 @@ router_reset_reachability(void) int check_whether_orport_reachable(void) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); return options->AssumeReachable || can_reach_or_port; } @@ -769,10 +782,10 @@ 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() || + net_is_disabled() || can_reach_dir_port; } @@ -784,7 +797,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; @@ -798,7 +811,7 @@ decide_to_advertise_dirport(or_options_t *options, uint16_t dir_port) return 0; if (authdir_mode(options)) /* always publish */ return dir_port; - if (we_are_hibernating()) + if (net_is_disabled()) return 0; if (!check_whether_dirport_reachable()) return 0; @@ -849,14 +862,14 @@ decide_to_advertise_dirport(or_options_t *options, uint16_t dir_port) void consider_testing_reachability(int test_or, int test_dir) { - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); int orport_reachable = check_whether_orport_reachable(); tor_addr_t addr; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); if (!me) return; - if (routerset_contains_router(options->ExcludeNodes, me) && + if (routerset_contains_router(options->ExcludeNodes, me, -1) && options->StrictNodes) { /* If we've excluded ourself, and StrictNodes is set, we can't test * ourself. */ @@ -876,11 +889,14 @@ consider_testing_reachability(int test_or, int test_dir) } if (test_or && (!orport_reachable || !circuit_enough_testing_circs())) { + extend_info_t *ei; log_info(LD_CIRC, "Testing %s of my ORPort: %s:%d.", !orport_reachable ? "reachability" : "bandwidth", me->address, me->or_port); - circuit_launch_by_router(CIRCUIT_PURPOSE_TESTING, me, - CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL); + ei = extend_info_from_router(me); + circuit_launch_by_extend_info(CIRCUIT_PURPOSE_TESTING, ei, + CIRCLAUNCH_NEED_CAPACITY|CIRCLAUNCH_IS_INTERNAL); + extend_info_free(ei); } tor_addr_from_ipv4h(&addr, me->addr); @@ -903,11 +919,11 @@ consider_testing_reachability(int test_or, int test_dir) void router_orport_found_reachable(void) { - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); if (!can_reach_or_port && me) { log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from " "the outside. Excellent.%s", - get_options()->_PublishServerDescriptor != NO_AUTHORITY ? + get_options()->_PublishServerDescriptor != NO_DIRINFO ? " Publishing server descriptor." : ""); can_reach_or_port = 1; mark_my_descriptor_dirty("ORPort found reachable"); @@ -921,7 +937,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."); @@ -963,11 +979,19 @@ router_perform_bandwidth_test(int num_circs, time_t now) } } +/** Return true iff our network is in some sense disabled: either we're + * hibernating, entering hibernation, or */ +int +net_is_disabled(void) +{ + return get_options()->DisableNetwork || we_are_hibernating(); +} + /** Return true iff we believe ourselves to be an authoritative * directory server. */ int -authdir_mode(or_options_t *options) +authdir_mode(const or_options_t *options) { return options->AuthoritativeDir != 0; } @@ -975,7 +999,7 @@ authdir_mode(or_options_t *options) * directory server. */ int -authdir_mode_v1(or_options_t *options) +authdir_mode_v1(const or_options_t *options) { return authdir_mode(options) && options->V1AuthoritativeDir != 0; } @@ -983,7 +1007,7 @@ authdir_mode_v1(or_options_t *options) * directory server. */ int -authdir_mode_v2(or_options_t *options) +authdir_mode_v2(const or_options_t *options) { return authdir_mode(options) && options->V2AuthoritativeDir != 0; } @@ -991,13 +1015,13 @@ authdir_mode_v2(or_options_t *options) * directory server. */ int -authdir_mode_v3(or_options_t *options) +authdir_mode_v3(const or_options_t *options) { return authdir_mode(options) && options->V3AuthoritativeDir != 0; } /** Return true iff we are a v1, v2, or v3 directory authority. */ int -authdir_mode_any_main(or_options_t *options) +authdir_mode_any_main(const or_options_t *options) { return options->V1AuthoritativeDir || options->V2AuthoritativeDir || @@ -1006,16 +1030,16 @@ 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); } /** Return true iff we are an authoritative directory server that is * authoritative about receiving and serving descriptors of type - * <b>purpose</b> its dirport. Use -1 for "any purpose". */ + * <b>purpose</b> on its dirport. Use -1 for "any purpose". */ int -authdir_mode_handles_descs(or_options_t *options, int purpose) +authdir_mode_handles_descs(const or_options_t *options, int purpose) { if (purpose < 0) return authdir_mode_any_nonhidserv(options); @@ -1030,7 +1054,7 @@ authdir_mode_handles_descs(or_options_t *options, int purpose) * publishes its own network statuses. */ int -authdir_mode_publishes_statuses(or_options_t *options) +authdir_mode_publishes_statuses(const or_options_t *options) { if (authdir_mode_bridge(options)) return 0; @@ -1040,7 +1064,7 @@ authdir_mode_publishes_statuses(or_options_t *options) * tests reachability of the descriptors it learns about. */ int -authdir_mode_tests_reachability(or_options_t *options) +authdir_mode_tests_reachability(const or_options_t *options) { return authdir_mode_handles_descs(options, -1); } @@ -1048,7 +1072,7 @@ authdir_mode_tests_reachability(or_options_t *options) * directory server. */ int -authdir_mode_bridge(or_options_t *options) +authdir_mode_bridge(const or_options_t *options) { return authdir_mode(options) && options->BridgeAuthoritativeDir != 0; } @@ -1056,7 +1080,7 @@ authdir_mode_bridge(or_options_t *options) /** Return true iff we are trying to be a server. */ int -server_mode(or_options_t *options) +server_mode(const or_options_t *options) { if (options->ClientOnly) return 0; return (options->ORPort != 0 || options->ORListenAddress); @@ -1065,7 +1089,7 @@ server_mode(or_options_t *options) /** Return true iff we are trying to be a non-bridge server. */ int -public_server_mode(or_options_t *options) +public_server_mode(const or_options_t *options) { if (!server_mode(options)) return 0; return (!options->BridgeRelay); @@ -1075,10 +1099,10 @@ public_server_mode(or_options_t *options) * in the consensus mean that we don't want to allow exits from circuits * we got from addresses not known to be servers. */ int -should_refuse_unknown_exits(or_options_t *options) +should_refuse_unknown_exits(const or_options_t *options) { - if (options->RefuseUnknownExits_ != -1) { - return options->RefuseUnknownExits_; + if (options->RefuseUnknownExits != -1) { + return options->RefuseUnknownExits; } else { return networkstatus_get_param(NULL, "refuseunknownexits", 1, 0, 1); } @@ -1105,14 +1129,12 @@ set_server_advertised(int s) server_is_advertised = s; } -/** Return true iff we are trying to be a socks proxy. */ +/** Return true iff we are trying to proxy client connections. */ int -proxy_mode(or_options_t *options) +proxy_mode(const or_options_t *options) { - return (options->SocksPort != 0 || - options->TransPort != 0 || - options->NATDPort != 0 || - options->DNSPort != 0); + (void)options; + return smartlist_len(get_configured_client_ports()) > 0; } /** Decide if we're a publishable server. We are a publishable server if: @@ -1128,11 +1150,11 @@ proxy_mode(or_options_t *options) static int decide_if_publishable_server(void) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); if (options->ClientOnly) return 0; - if (options->_PublishServerDescriptor == NO_AUTHORITY) + if (options->_PublishServerDescriptor == NO_DIRINFO) return 0; if (!server_mode(options)) return 0; @@ -1173,7 +1195,7 @@ consider_publishable_server(int force) * the one configured in the ORPort option, or the one we actually bound to * if ORPort is "auto". */ uint16_t -router_get_advertised_or_port(or_options_t *options) +router_get_advertised_or_port(const or_options_t *options) { if (options->ORPort == CFG_AUTO_PORT) { connection_t *c = connection_get_by_type(CONN_TYPE_OR_LISTENER); @@ -1190,7 +1212,7 @@ router_get_advertised_or_port(or_options_t *options) * the one configured in the DirPort option, * or the one we actually bound to if DirPort is "auto". */ uint16_t -router_get_advertised_dir_port(or_options_t *options, uint16_t dirport) +router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport) { if (!options->DirPort) return dirport; @@ -1211,9 +1233,14 @@ router_get_advertised_dir_port(or_options_t *options, uint16_t dirport) static routerinfo_t *desc_routerinfo = NULL; /** My extrainfo */ static extrainfo_t *desc_extrainfo = NULL; +/** Why did we most recently decide to regenerate our descriptor? Used to + * tell the authorities why we're sending it to them. */ +static const char *desc_gen_reason = NULL; /** Since when has our descriptor been "clean"? 0 if we need to regenerate it * now. */ static time_t desc_clean_since = 0; +/** Why did we mark the descriptor dirty? */ +static const char *desc_dirty_reason = NULL; /** Boolean: do we need to regenerate the above? */ static int desc_needs_upload = 0; @@ -1224,11 +1251,11 @@ static int desc_needs_upload = 0; void router_upload_dir_desc_to_dirservers(int force) { - routerinfo_t *ri; + const routerinfo_t *ri; extrainfo_t *ei; char *msg; size_t desc_len, extra_len = 0, total_len; - authority_type_t auth = get_options()->_PublishServerDescriptor; + dirinfo_type_t auth = get_options()->_PublishServerDescriptor; ri = router_get_my_routerinfo(); if (!ri) { @@ -1236,7 +1263,7 @@ router_upload_dir_desc_to_dirservers(int force) return; } ei = router_get_my_extrainfo(); - if (auth == NO_AUTHORITY) + if (auth == NO_DIRINFO) return; if (!force && !desc_needs_upload) return; @@ -1257,7 +1284,7 @@ router_upload_dir_desc_to_dirservers(int force) msg[desc_len+extra_len] = 0; directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_DIR, - (auth & BRIDGE_AUTHORITY) ? + (auth & BRIDGE_DIRINFO) ? ROUTER_PURPOSE_BRIDGE : ROUTER_PURPOSE_GENERAL, auth, msg, desc_len, extra_len); @@ -1322,7 +1349,7 @@ router_extrainfo_digest_is_me(const char *digest) /** A wrapper around router_digest_is_me(). */ int -router_is_me(routerinfo_t *router) +router_is_me(const routerinfo_t *router) { return router_digest_is_me(router->cache_info.identity_digest); } @@ -1341,7 +1368,7 @@ router_fingerprint_is_me(const char *fp) /** Return a routerinfo for this OR, rebuilding a fresh one if * necessary. Return NULL on error, or if called on an OP. */ -routerinfo_t * +const routerinfo_t * router_get_my_routerinfo(void) { if (!server_mode(get_options())) @@ -1380,6 +1407,14 @@ router_get_my_extrainfo(void) return desc_extrainfo; } +/** Return a human-readable string describing what triggered us to generate + * our current descriptor, or NULL if we don't know. */ +const char * +router_get_descriptor_gen_reason(void) +{ + return desc_gen_reason; +} + /** A list of nicknames that we've warned about including in our family * declaration verbatim rather than as digests. */ static smartlist_t *warned_nonexistent_family = NULL; @@ -1391,10 +1426,8 @@ static int router_guess_address_from_dir_headers(uint32_t *guess); * dirserver headers. Place the answer in *<b>addr</b> and return * 0 on success, else return -1 if we have no guess. */ int -router_pick_published_address(or_options_t *options, uint32_t *addr) +router_pick_published_address(const or_options_t *options, uint32_t *addr) { - char buf[INET_NTOA_BUF_LEN]; - struct in_addr a; if (resolve_my_address(LOG_INFO, options, addr, NULL) < 0) { log_info(LD_CONFIG, "Could not determine our address locally. " "Checking if directory headers provide any hints."); @@ -1404,9 +1437,7 @@ router_pick_published_address(or_options_t *options, uint32_t *addr) return -1; } } - a.s_addr = htonl(*addr); - tor_inet_ntoa(&a, buf, sizeof(buf)); - log_info(LD_CONFIG,"Success: chose address '%s'.", buf); + log_info(LD_CONFIG,"Success: chose address '%s'.", fmt_addr32(*addr)); return 0; } @@ -1422,7 +1453,7 @@ router_rebuild_descriptor(int force) uint32_t addr; char platform[256]; int hibernating = we_are_hibernating(); - or_options_t *options = get_options(); + const or_options_t *options = get_options(); if (desc_clean_since && !force) return 0; @@ -1476,13 +1507,12 @@ router_rebuild_descriptor(int force) ri->policy_is_reject_star = policy_is_reject_star(ri->exit_policy); - if (desc_routerinfo) { /* inherit values */ - ri->is_valid = desc_routerinfo->is_valid; - ri->is_running = desc_routerinfo->is_running; - ri->is_named = desc_routerinfo->is_named; - } +#if 0 + /* XXXX NM NM I belive this is safe to remove */ if (authdir_mode(options)) ri->is_valid = ri->is_named = 1; /* believe in yourself */ +#endif + if (options->MyFamily) { smartlist_t *family; if (!warned_nonexistent_family) @@ -1491,13 +1521,12 @@ router_rebuild_descriptor(int force) ri->declared_family = smartlist_create(); smartlist_split_string(family, options->MyFamily, ",", SPLIT_SKIP_SPACE|SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); - SMARTLIST_FOREACH(family, char *, name, - { - routerinfo_t *member; + SMARTLIST_FOREACH_BEGIN(family, char *, name) { + const node_t *member; if (!strcasecmp(name, options->Nickname)) - member = ri; + goto skip; /* Don't list ourself, that's redundant */ else - member = router_get_by_nickname(name, 1); + member = node_get_by_nickname(name, 1); if (!member) { int is_legal = is_legal_nickname_or_hexdigest(name); if (!smartlist_string_isin(warned_nonexistent_family, name) && @@ -1517,19 +1546,21 @@ router_rebuild_descriptor(int force) smartlist_add(ri->declared_family, name); name = NULL; } - } else if (router_is_me(member)) { + } else if (router_digest_is_me(member->identity)) { /* Don't list ourself in our own family; that's redundant */ + /* XXX shouldn't be possible */ } else { char *fp = tor_malloc(HEX_DIGEST_LEN+2); fp[0] = '$'; base16_encode(fp+1,HEX_DIGEST_LEN+1, - member->cache_info.identity_digest, DIGEST_LEN); + member->identity, DIGEST_LEN); smartlist_add(ri->declared_family, fp); if (smartlist_string_isin(warned_nonexistent_family, name)) smartlist_string_remove(warned_nonexistent_family, name); } + skip: tor_free(name); - }); + } SMARTLIST_FOREACH_END(name); /* remove duplicates from the list */ smartlist_sort_strings(ri->declared_family); @@ -1590,8 +1621,6 @@ router_rebuild_descriptor(int force) strlen(ri->cache_info.signed_descriptor_body), ri->cache_info.signed_descriptor_digest); - routerinfo_set_country(ri); - if (ei) { tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei, NULL, NULL)); } @@ -1603,16 +1632,56 @@ router_rebuild_descriptor(int force) desc_clean_since = time(NULL); desc_needs_upload = 1; + desc_gen_reason = desc_dirty_reason; + desc_dirty_reason = NULL; control_event_my_descriptor_changed(); return 0; } -/** Mark descriptor out of date if it's older than <b>when</b> */ +/** If our router descriptor ever goes this long without being regenerated + * because something changed, we force an immediate regenerate-and-upload. */ +#define FORCE_REGENERATE_DESCRIPTOR_INTERVAL (18*60*60) + +/** If our router descriptor seems to be missing or unacceptable according + * to the authorities, regenerate and reupload it _this_ often. */ +#define FAST_RETRY_DESCRIPTOR_INTERVAL (90*60) + +/** Mark descriptor out of date if it's been "too long" since we last tried + * to upload one. */ void -mark_my_descriptor_dirty_if_older_than(time_t when) +mark_my_descriptor_dirty_if_too_old(time_t now) { - if (desc_clean_since < when) + networkstatus_t *ns; + const routerstatus_t *rs; + const char *retry_fast_reason = NULL; /* Set if we should retry frequently */ + const time_t slow_cutoff = now - FORCE_REGENERATE_DESCRIPTOR_INTERVAL; + const time_t fast_cutoff = now - FAST_RETRY_DESCRIPTOR_INTERVAL; + + /* If it's already dirty, don't mark it. */ + if (! desc_clean_since) + return; + + /* If it's older than FORCE_REGENERATE_DESCRIPTOR_INTERVAL, it's always + * time to rebuild it. */ + if (desc_clean_since < slow_cutoff) { mark_my_descriptor_dirty("time for new descriptor"); + return; + } + /* Now we see whether we want to be retrying frequently or no. The + * rule here is that we'll retry frequently if we aren't listed in the + * live consensus we have, or if the publication time of the + * descriptor listed for us in the consensus is very old. */ + ns = networkstatus_get_live_consensus(now); + if (ns) { + rs = networkstatus_vote_find_entry(ns, server_identitykey_digest); + if (rs == NULL) + retry_fast_reason = "not listed in consensus"; + else if (rs->published_on < slow_cutoff) + retry_fast_reason = "version listed in consensus is quite old"; + } + + if (retry_fast_reason && desc_clean_since < fast_cutoff) + mark_my_descriptor_dirty(retry_fast_reason); } /** Call when the current descriptor is out of date. */ @@ -1621,6 +1690,8 @@ mark_my_descriptor_dirty(const char *reason) { desc_clean_since = 0; log_info(LD_OR, "Decided to publish new relay descriptor: %s", reason); + if (!desc_dirty_reason) + desc_dirty_reason = reason; } /** How frequently will we republish our descriptor because of large (factor @@ -1686,7 +1757,7 @@ void check_descriptor_ipaddress_changed(time_t now) { uint32_t prev, cur; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); (void) now; if (!desc_routerinfo) @@ -1718,7 +1789,7 @@ router_new_address_suggestion(const char *suggestion, { uint32_t addr, cur = 0; struct in_addr in; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); /* first, learn what the IP address actually is */ if (!tor_inet_aton(suggestion, &in)) { @@ -1817,7 +1888,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, int result=0; addr_policy_t *tmpe; char *family_line; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); /* Make sure the identity key matches the one in the routerinfo. */ if (crypto_pk_cmp_keys(ident_key, router->identity_pkey)) { @@ -2059,7 +2130,7 @@ int extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, crypto_pk_env_t *ident_key) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); char identity[HEX_DIGEST_LEN+1]; char published[ISO_TIME_LEN+1]; char digest[DIGEST_LEN]; @@ -2083,6 +2154,12 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, tor_free(bandwidth_usage); smartlist_add(chunks, pre); + if (geoip_is_loaded()) { + char *chunk=NULL; + tor_asprintf(&chunk, "geoip-db-digest %s\n", geoip_db_digest()); + smartlist_add(chunks, chunk); + } + if (options->ExtraInfoStatistics && write_stats_to_extrainfo) { log_info(LD_GENERAL, "Adding stats to extra-info descriptor."); if (options->DirReqStatistics && @@ -2105,6 +2182,11 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, "exit-stats-end", now, &contents) > 0) { smartlist_add(chunks, contents); } + if (options->ConnDirectionStatistics && + load_stats_file("stats"PATH_SEPARATOR"conn-stats", + "conn-bi-direct", now, &contents) > 0) { + smartlist_add(chunks, contents); + } } if (should_record_bridge_info(options) && write_stats_to_extrainfo) { @@ -2291,13 +2373,45 @@ router_get_description(char *buf, const routerinfo_t *ri) return "<null>"; return format_node_description(buf, ri->cache_info.identity_digest, - ri->is_named, + router_is_named(ri), ri->nickname, NULL, ri->addr); } /** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to + * hold a human-readable description of <b>node</b>. + * + * Return a pointer to the front of <b>buf</b>. + */ +const char * +node_get_description(char *buf, const node_t *node) +{ + const char *nickname = NULL; + uint32_t addr32h = 0; + int is_named = 0; + + if (!node) + return "<null>"; + + if (node->rs) { + nickname = node->rs->nickname; + is_named = node->rs->is_named; + addr32h = node->rs->addr; + } else if (node->ri) { + nickname = node->ri->nickname; + addr32h = node->ri->addr; + } + + return format_node_description(buf, + node->identity, + is_named, + nickname, + NULL, + addr32h); +} + +/** Use <b>buf</b> (which must be at least NODE_DESC_BUF_LEN bytes long) to * hold a human-readable description of <b>rs</b>. * * Return a pointer to the front of <b>buf</b>. @@ -2345,6 +2459,18 @@ router_describe(const routerinfo_t *ri) return router_get_description(buf, ri); } +/** Return a human-readable description of the node_t <b>node</b>. + * + * This function is not thread-safe. Each call to this function invalidates + * previous values returned by this function. + */ +const char * +node_describe(const node_t *node) +{ + static char buf[NODE_DESC_BUF_LEN]; + return node_get_description(buf, node); +} + /** Return a human-readable description of the routerstatus_t <b>rs</b>. * * This function is not thread-safe. Each call to this function invalidates @@ -2379,10 +2505,15 @@ extend_info_describe(const extend_info_t *ei) void router_get_verbose_nickname(char *buf, const routerinfo_t *router) { + const char *good_digest = networkstatus_get_router_digest_by_nickname( + router->nickname); + int is_named = good_digest && tor_memeq(good_digest, + router->cache_info.identity_digest, + DIGEST_LEN); buf[0] = '$'; base16_encode(buf+1, HEX_DIGEST_LEN+1, router->cache_info.identity_digest, DIGEST_LEN); - buf[1+HEX_DIGEST_LEN] = router->is_named ? '=' : '~'; + buf[1+HEX_DIGEST_LEN] = is_named ? '=' : '~'; strlcpy(buf+1+HEX_DIGEST_LEN+1, router->nickname, MAX_NICKNAME_LEN+1); } diff --git a/src/or/router.h b/src/or/router.h index 3733099f93..6a9851cdbd 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -30,6 +30,7 @@ crypto_pk_env_t *init_key_from_file(const char *fname, int generate, int severity); void v3_authority_check_key_expiry(void); +int router_initialize_tls_context(void); int init_keys(void); int check_whether_orport_reachable(void); @@ -39,30 +40,32 @@ 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); - -uint16_t router_get_advertised_or_port(or_options_t *options); -uint16_t router_get_advertised_dir_port(or_options_t *options, +int net_is_disabled(void); + +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(const or_options_t *options); +uint16_t router_get_advertised_dir_port(const or_options_t *options, uint16_t dirport); -int server_mode(or_options_t *options); -int public_server_mode(or_options_t *options); +int server_mode(const or_options_t *options); +int public_server_mode(const or_options_t *options); int advertised_server_mode(void); -int proxy_mode(or_options_t *options); +int proxy_mode(const or_options_t *options); void consider_publishable_server(int force); -int should_refuse_unknown_exits(or_options_t *options); +int should_refuse_unknown_exits(const or_options_t *options); void router_upload_dir_desc_to_dirservers(int force); -void mark_my_descriptor_dirty_if_older_than(time_t when); +void mark_my_descriptor_dirty_if_too_old(time_t now); void mark_my_descriptor_dirty(const char *reason); void check_descriptor_bandwidth_changed(time_t now); void check_descriptor_ipaddress_changed(time_t now); @@ -70,14 +73,15 @@ void router_new_address_suggestion(const char *suggestion, const dir_connection_t *d_conn); int router_compare_to_my_exit_policy(edge_connection_t *conn); int router_my_exit_policy_is_reject_star(void); -routerinfo_t *router_get_my_routerinfo(void); +const routerinfo_t *router_get_my_routerinfo(void); extrainfo_t *router_get_my_extrainfo(void); const char *router_get_my_descriptor(void); +const char *router_get_descriptor_gen_reason(void); int router_digest_is_me(const char *digest); int router_extrainfo_digest_is_me(const char *digest); -int router_is_me(routerinfo_t *router); +int router_is_me(const routerinfo_t *router); int router_fingerprint_is_me(const char *fp); -int router_pick_published_address(or_options_t *options, uint32_t *addr); +int router_pick_published_address(const or_options_t *options, uint32_t *addr); int router_rebuild_descriptor(int force); int router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router, crypto_pk_env_t *ident_key); @@ -102,9 +106,11 @@ const char *format_node_description(char *buf, const tor_addr_t *addr, uint32_t addr32h); const char *router_get_description(char *buf, const routerinfo_t *ri); +const char *node_get_description(char *buf, const node_t *node); const char *routerstatus_get_description(char *buf, const routerstatus_t *rs); const char *extend_info_get_description(char *buf, const extend_info_t *ei); const char *router_describe(const routerinfo_t *ri); +const char *node_describe(const node_t *node); const char *routerstatus_describe(const routerstatus_t *ri); const char *extend_info_describe(const extend_info_t *ei); diff --git a/src/or/routerlist.c b/src/or/routerlist.c index f8df089a8f..689df99c57 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -22,7 +22,9 @@ #include "geoip.h" #include "hibernate.h" #include "main.h" +#include "microdesc.h" #include "networkstatus.h" +#include "nodelist.h" #include "policies.h" #include "reasons.h" #include "rendcommon.h" @@ -37,22 +39,25 @@ /****************************************************************************/ /* static function prototypes */ -static routerstatus_t *router_pick_directory_server_impl( - authority_type_t auth, int flags); -static routerstatus_t *router_pick_trusteddirserver_impl( - authority_type_t auth, int flags, int *n_busy_out); +static const routerstatus_t *router_pick_directory_server_impl( + dirinfo_type_t auth, int flags); +static const routerstatus_t *router_pick_trusteddirserver_impl( + dirinfo_type_t auth, int flags, int *n_busy_out); static void mark_all_trusteddirservers_up(void); -static int router_nickname_matches(routerinfo_t *router, const char *nickname); +static int router_nickname_matches(const routerinfo_t *router, + const char *nickname); +static int node_nickname_matches(const node_t *router, + const char *nickname); static void trusted_dir_server_free(trusted_dir_server_t *ds); -static void launch_router_descriptor_downloads(smartlist_t *downloadable, - routerstatus_t *source, - time_t now); static int signed_desc_digest_is_recognized(signed_descriptor_t *desc); static void update_router_have_minimum_dir_info(void); -static const char *signed_descriptor_get_body_impl(signed_descriptor_t *desc, - int with_annotations); +static const char *signed_descriptor_get_body_impl( + const signed_descriptor_t *desc, + int with_annotations); static void list_pending_downloads(digestmap_t *result, int purpose, const char *prefix); +static void launch_dummy_descriptor_download_as_needed(time_t now, + const or_options_t *options); DECLARE_TYPED_DIGESTMAP_FNS(sdmap_, digest_sd_map_t, signed_descriptor_t) DECLARE_TYPED_DIGESTMAP_FNS(rimap_, digest_ri_map_t, routerinfo_t) @@ -94,7 +99,7 @@ static smartlist_t *warned_nicknames = NULL; /** The last time we tried to download any routerdesc, or 0 for "never". We * use this to rate-limit download attempts when the number of routerdescs to * download is low. */ -static time_t last_routerdesc_download_attempted = 0; +static time_t last_descriptor_download_attempted = 0; /** When we last computed the weights to use for bandwidths on directory * requests, what were the total weighted bandwidth, and our share of that @@ -106,7 +111,7 @@ static uint64_t sl_last_total_weighted_bw = 0, /** Return the number of directory authorities whose type matches some bit set * in <b>type</b> */ int -get_n_authorities(authority_type_t type) +get_n_authorities(dirinfo_type_t type) { int n = 0; if (!trusted_dir_servers) @@ -117,7 +122,7 @@ get_n_authorities(authority_type_t type) return n; } -#define get_n_v2_authorities() get_n_authorities(V2_AUTHORITY) +#define get_n_v2_authorities() get_n_authorities(V2_DIRINFO) /** Helper: Return the cert_list_t for an authority whose authority ID is * <b>id_digest</b>, allocating a new list if necessary. */ @@ -312,6 +317,7 @@ trusted_dirs_remove_old_certs(void) time_t now = time(NULL); #define DEAD_CERT_LIFETIME (2*24*60*60) #define OLD_CERT_LIFETIME (7*24*60*60) +#define CERT_EXPIRY_SKEW (60*60) if (!trusted_dir_certs) return; @@ -514,7 +520,7 @@ authority_certs_fetch_missing(networkstatus_t *status, time_t now) } SMARTLIST_FOREACH_BEGIN(trusted_dir_servers, trusted_dir_server_t *, ds) { int found = 0; - if (!(ds->type & V3_AUTHORITY)) + if (!(ds->type & V3_DIRINFO)) continue; if (smartlist_digest_isin(missing_digests, ds->v3_identity_digest)) continue; @@ -600,7 +606,7 @@ router_should_rebuild_store(desc_store_t *store) /** Return the desc_store_t in <b>rl</b> that should be used to store * <b>sd</b>. */ static INLINE desc_store_t * -desc_get_store(routerlist_t *rl, signed_descriptor_t *sd) +desc_get_store(routerlist_t *rl, const signed_descriptor_t *sd) { if (sd->is_extrainfo) return &rl->extrainfo_store; @@ -926,10 +932,10 @@ router_get_trusted_dir_servers(void) * Don't pick an authority if any non-authority is viable; try to avoid using * servers that have returned 503 recently. */ -routerstatus_t * -router_pick_directory_server(authority_type_t type, int flags) +const routerstatus_t * +router_pick_directory_server(dirinfo_type_t type, int flags) { - routerstatus_t *choice; + const routerstatus_t *choice; if (get_options()->PreferTunneledDirConns) flags |= _PDS_PREFER_TUNNELED_DIR_CONNS; @@ -958,8 +964,8 @@ int router_get_my_share_of_directory_requests(double *v2_share_out, double *v3_share_out) { - routerinfo_t *me = router_get_my_routerinfo(); - routerstatus_t *rs; + const routerinfo_t *me = router_get_my_routerinfo(); + const routerstatus_t *rs; const int pds_flags = PDS_ALLOW_SELF|PDS_IGNORE_FASCISTFIREWALL; *v2_share_out = *v3_share_out = 0.0; if (!me) @@ -972,7 +978,7 @@ router_get_my_share_of_directory_requests(double *v2_share_out, /* XXXX This is a bit of a kludge */ if (rs->is_v2_dir) { sl_last_total_weighted_bw = 0; - router_pick_directory_server(V2_AUTHORITY, pds_flags); + router_pick_directory_server(V2_DIRINFO, pds_flags); if (sl_last_total_weighted_bw != 0) { *v2_share_out = U64_TO_DBL(sl_last_weighted_bw_of_me) / U64_TO_DBL(sl_last_total_weighted_bw); @@ -981,7 +987,7 @@ router_get_my_share_of_directory_requests(double *v2_share_out, if (rs->version_supports_v3_dir) { sl_last_total_weighted_bw = 0; - router_pick_directory_server(V3_AUTHORITY, pds_flags); + router_pick_directory_server(V3_DIRINFO, pds_flags); if (sl_last_total_weighted_bw != 0) { *v3_share_out = U64_TO_DBL(sl_last_weighted_bw_of_me) / U64_TO_DBL(sl_last_total_weighted_bw); @@ -1022,7 +1028,7 @@ trusteddirserver_get_by_v3_auth_digest(const char *digest) SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds, { if (tor_memeq(ds->v3_identity_digest, digest, DIGEST_LEN) && - (ds->type & V3_AUTHORITY)) + (ds->type & V3_DIRINFO)) return ds; }); @@ -1032,10 +1038,10 @@ trusteddirserver_get_by_v3_auth_digest(const char *digest) /** Try to find a running trusted dirserver. Flags are as for * router_pick_directory_server. */ -routerstatus_t * -router_pick_trusteddirserver(authority_type_t type, int flags) +const routerstatus_t * +router_pick_trusteddirserver(dirinfo_type_t type, int flags) { - routerstatus_t *choice; + const routerstatus_t *choice; int busy = 0; if (get_options()->PreferTunneledDirConns) flags |= _PDS_PREFER_TUNNELED_DIR_CONNS; @@ -1047,7 +1053,8 @@ router_pick_trusteddirserver(authority_type_t type, int flags) /* If the reason that we got no server is that servers are "busy", * we must be excluding good servers because we already have serverdesc * fetches with them. Do not mark down servers up because of this. */ - tor_assert((flags & PDS_NO_EXISTING_SERVERDESC_FETCH)); + tor_assert((flags & (PDS_NO_EXISTING_SERVERDESC_FETCH| + PDS_NO_EXISTING_MICRODESC_FETCH))); return NULL; } @@ -1067,11 +1074,11 @@ router_pick_trusteddirserver(authority_type_t type, int flags) * If the _PDS_PREFER_TUNNELED_DIR_CONNS flag is set, prefer directory servers * that we can use with BEGINDIR. */ -static routerstatus_t * -router_pick_directory_server_impl(authority_type_t type, int flags) +static const routerstatus_t * +router_pick_directory_server_impl(dirinfo_type_t type, int flags) { - or_options_t *options = get_options(); - routerstatus_t *result; + const or_options_t *options = get_options(); + const node_t *result; smartlist_t *direct, *tunnel; smartlist_t *trusted_direct, *trusted_tunnel; smartlist_t *overloaded_direct, *overloaded_tunnel; @@ -1095,54 +1102,64 @@ router_pick_directory_server_impl(authority_type_t type, int flags) overloaded_tunnel = smartlist_create(); /* Find all the running dirservers we know about. */ - SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *, - status) { + SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) { int is_trusted; - int is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now; + int is_overloaded; tor_addr_t addr; - if (!status->is_running || !status->dir_port || !status->is_valid) + const routerstatus_t *status = node->rs; + const country_t country = node->country; + if (!status) continue; - if (status->is_bad_directory) + + if (!node->is_running || !status->dir_port || !node->is_valid) + continue; + if (node->is_bad_directory) continue; - if (requireother && router_digest_is_me(status->identity_digest)) + if (requireother && router_digest_is_me(node->identity)) continue; - if (type & V3_AUTHORITY) { + if (type & V3_DIRINFO) { if (!(status->version_supports_v3_dir || - router_digest_is_trusted_dir_type(status->identity_digest, - V3_AUTHORITY))) + router_digest_is_trusted_dir_type(node->identity, + V3_DIRINFO))) continue; } - is_trusted = router_digest_is_trusted_dir(status->identity_digest); - if ((type & V2_AUTHORITY) && !(status->is_v2_dir || is_trusted)) + is_trusted = router_digest_is_trusted_dir(node->identity); + if ((type & V2_DIRINFO) && !(node->rs->is_v2_dir || is_trusted)) + continue; + if ((type & EXTRAINFO_DIRINFO) && + !router_supports_extrainfo(node->identity, 0)) continue; - if ((type & EXTRAINFO_CACHE) && - !router_supports_extrainfo(status->identity_digest, 0)) + if ((type & MICRODESC_DIRINFO) && !is_trusted && + !node->rs->version_supports_microdesc_cache) continue; - if (try_excluding && options->ExcludeNodes && - routerset_contains_routerstatus(options->ExcludeNodes, status)) { + if (try_excluding && + routerset_contains_routerstatus(options->ExcludeNodes, status, + country)) { ++n_excluded; continue; } /* XXXX IP6 proposal 118 */ - tor_addr_from_ipv4h(&addr, status->addr); + tor_addr_from_ipv4h(&addr, node->rs->addr); + + is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now; if (prefer_tunnel && status->version_supports_begindir && (!fascistfirewall || fascist_firewall_allows_address_or(&addr, status->or_port))) smartlist_add(is_trusted ? trusted_tunnel : - is_overloaded ? overloaded_tunnel : tunnel, status); + is_overloaded ? overloaded_tunnel : tunnel, (void*)node); else if (!fascistfirewall || fascist_firewall_allows_address_dir(&addr, status->dir_port)) smartlist_add(is_trusted ? trusted_direct : - is_overloaded ? overloaded_direct : direct, status); - } SMARTLIST_FOREACH_END(status); + is_overloaded ? overloaded_direct : direct, (void*)node); + } SMARTLIST_FOREACH_END(node); if (smartlist_len(tunnel)) { - result = routerstatus_sl_choose_by_bandwidth(tunnel, WEIGHT_FOR_DIR); + result = node_sl_choose_by_bandwidth(tunnel, WEIGHT_FOR_DIR); } else if (smartlist_len(overloaded_tunnel)) { - result = routerstatus_sl_choose_by_bandwidth(overloaded_tunnel, + result = node_sl_choose_by_bandwidth(overloaded_tunnel, WEIGHT_FOR_DIR); } else if (smartlist_len(trusted_tunnel)) { /* FFFF We don't distinguish between trusteds and overloaded trusteds @@ -1151,10 +1168,10 @@ router_pick_directory_server_impl(authority_type_t type, int flags) * is a feature, but it could easily be a bug. -RD */ result = smartlist_choose(trusted_tunnel); } else if (smartlist_len(direct)) { - result = routerstatus_sl_choose_by_bandwidth(direct, WEIGHT_FOR_DIR); + result = node_sl_choose_by_bandwidth(direct, WEIGHT_FOR_DIR); } else if (smartlist_len(overloaded_direct)) { - result = routerstatus_sl_choose_by_bandwidth(overloaded_direct, - WEIGHT_FOR_DIR); + result = node_sl_choose_by_bandwidth(overloaded_direct, + WEIGHT_FOR_DIR); } else { result = smartlist_choose(trusted_direct); } @@ -1173,26 +1190,27 @@ router_pick_directory_server_impl(authority_type_t type, int flags) goto retry_without_exclude; } - return result; + return result ? result->rs : NULL; } /** Choose randomly from among the trusted dirservers that are up. Flags * are as for router_pick_directory_server_impl(). */ -static routerstatus_t * -router_pick_trusteddirserver_impl(authority_type_t type, int flags, +static const routerstatus_t * +router_pick_trusteddirserver_impl(dirinfo_type_t type, int flags, int *n_busy_out) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); smartlist_t *direct, *tunnel; smartlist_t *overloaded_direct, *overloaded_tunnel; - routerinfo_t *me = router_get_my_routerinfo(); - routerstatus_t *result; + const routerinfo_t *me = router_get_my_routerinfo(); + const routerstatus_t *result; time_t now = time(NULL); const int requireother = ! (flags & PDS_ALLOW_SELF); const int fascistfirewall = ! (flags & PDS_IGNORE_FASCISTFIREWALL); const int prefer_tunnel = (flags & _PDS_PREFER_TUNNELED_DIR_CONNS); const int no_serverdesc_fetching =(flags & PDS_NO_EXISTING_SERVERDESC_FETCH); + const int no_microdesc_fetching =(flags & PDS_NO_EXISTING_MICRODESC_FETCH); int n_busy = 0; int try_excluding = 1, n_excluded = 0; @@ -1214,14 +1232,14 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags, if (!d->is_running) continue; if ((type & d->type) == 0) continue; - if ((type & EXTRAINFO_CACHE) && + if ((type & EXTRAINFO_DIRINFO) && !router_supports_extrainfo(d->digest, 1)) continue; if (requireother && me && router_digest_is_me(d->digest)) continue; - if (try_excluding && options->ExcludeNodes && + if (try_excluding && routerset_contains_routerstatus(options->ExcludeNodes, - &d->fake_status)) { + &d->fake_status, -1)) { ++n_excluded; continue; } @@ -1240,6 +1258,13 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags, continue; } } + if (no_microdesc_fetching) { + if (connection_get_by_type_addr_port_purpose( + CONN_TYPE_DIR, &addr, d->dir_port, DIR_PURPOSE_FETCH_MICRODESC)) { + ++n_busy; + continue; + } + } if (prefer_tunnel && d->or_port && @@ -1287,22 +1312,18 @@ router_pick_trusteddirserver_impl(authority_type_t type, int flags, static void mark_all_trusteddirservers_up(void) { - if (routerlist) { - SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router, - if (router_digest_is_trusted_dir(router->cache_info.identity_digest) && - router->dir_port > 0) { - router->is_running = 1; - }); - } + SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node, { + if (router_digest_is_trusted_dir(node->identity)) + node->is_running = 1; + }); if (trusted_dir_servers) { SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, dir, { routerstatus_t *rs; dir->is_running = 1; download_status_reset(&dir->v2_ns_dl_status); - rs = router_get_consensus_status_by_id(dir->digest); - if (rs && !rs->is_running) { - rs->is_running = 1; + rs = router_get_mutable_consensus_status_by_id(dir->digest); + if (rs) { rs->last_dir_503_at = 0; control_event_networkstatus_changed_single(rs); } @@ -1326,148 +1347,160 @@ router_reset_status_download_failures(void) mark_all_trusteddirservers_up(); } -/** Return true iff router1 and router2 have the same /16 network. */ +/** Return true iff router1 and router2 have similar enough network addresses + * that we should treat them as being in the same family */ static INLINE int -routers_in_same_network_family(routerinfo_t *r1, routerinfo_t *r2) +addrs_in_same_network_family(const tor_addr_t *a1, + const tor_addr_t *a2) { - return (r1->addr & 0xffff0000) == (r2->addr & 0xffff0000); + /* XXXX MOVE ? */ + return 0 == tor_addr_compare_masked(a1, a2, 16, CMP_SEMANTIC); } -/** Look through the routerlist and identify routers that - * advertise the same /16 network address as <b>router</b>. - * Add each of them to <b>sl</b>. +/** + * Add all the family of <b>node</b>, including <b>node</b> itself, to + * the smartlist <b>sl</b>. + * + * This is used to make sure we don't pick siblings in a single path, or + * pick more than one relay from a family for our entry guard list. + * Note that a node may be added to <b>sl</b> more than once if it is + * part of <b>node</b>'s family for more than one reason. */ -static void -routerlist_add_network_family(smartlist_t *sl, routerinfo_t *router) +void +nodelist_add_node_and_family(smartlist_t *sl, const node_t *node) { - SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, r, + /* XXXX MOVE */ + const smartlist_t *all_nodes = nodelist_get_list(); + const smartlist_t *declared_family; + const or_options_t *options = get_options(); + + tor_assert(node); + + declared_family = node_get_declared_family(node); + + /* Let's make sure that we have the node itself, if it's a real node. */ { - if (router != r && routers_in_same_network_family(router, r)) - smartlist_add(sl, r); - }); -} + const node_t *real_node = node_get_by_id(node->identity); + if (real_node) + smartlist_add(sl, (node_t*)real_node); + } -/** Add all the family of <b>router</b> to the smartlist <b>sl</b>. - * This is used to make sure we don't pick siblings in a single path, - * or pick more than one relay from a family for our entry guard list. - */ -void -routerlist_add_family(smartlist_t *sl, routerinfo_t *router) -{ - routerinfo_t *r; - config_line_t *cl; - or_options_t *options = get_options(); + /* First, add any nodes with similar network addresses. */ + if (options->EnforceDistinctSubnets) { + tor_addr_t node_addr; + node_get_addr(node, &node_addr); - /* First, add any routers with similar network addresses. */ - if (options->EnforceDistinctSubnets) - routerlist_add_network_family(sl, router); + SMARTLIST_FOREACH_BEGIN(all_nodes, const node_t *, node2) { + tor_addr_t a; + node_get_addr(node2, &a); + if (addrs_in_same_network_family(&a, &node_addr)) + smartlist_add(sl, (void*)node2); + } SMARTLIST_FOREACH_END(node2); + } - if (router->declared_family) { - /* Add every r such that router declares familyness with r, and r + /* Now, add all nodes in the declared_family of this node, if they + * also declare this node to be in their family. */ + if (declared_family) { + /* Add every r such that router declares familyness with node, and node * declares familyhood with router. */ - SMARTLIST_FOREACH(router->declared_family, const char *, n, - { - if (!(r = router_get_by_nickname(n, 0))) - continue; - if (!r->declared_family) - continue; - SMARTLIST_FOREACH(r->declared_family, const char *, n2, - { - if (router_nickname_matches(router, n2)) - smartlist_add(sl, r); - }); - }); + SMARTLIST_FOREACH_BEGIN(declared_family, const char *, name) { + const node_t *node2; + const smartlist_t *family2; + if (!(node2 = node_get_by_nickname(name, 0))) + continue; + if (!(family2 = node_get_declared_family(node2))) + continue; + SMARTLIST_FOREACH_BEGIN(family2, const char *, name2) { + if (node_nickname_matches(node, name2)) { + smartlist_add(sl, (void*)node2); + break; + } + } SMARTLIST_FOREACH_END(name2); + } SMARTLIST_FOREACH_END(name); } /* If the user declared any families locally, honor those too. */ - for (cl = options->NodeFamilies; cl; cl = cl->next) { - if (router_nickname_is_in_list(router, cl->value)) { - add_nickname_list_to_smartlist(sl, cl->value, 0); - } + if (options->NodeFamilySets) { + SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, { + if (routerset_contains_node(rs, node)) { + routerset_get_all_nodes(sl, rs, NULL, 0); + } + }); } } -/** Return true iff r is named by some nickname in <b>lst</b>. */ +/** Given a <b>router</b>, add every node_t in its family (including the + * node itself</b>) to <b>sl</b>. + * + * Note the type mismatch: This function takes a routerinfo, but adds nodes + * to the smartlist! + */ +static void +routerlist_add_node_and_family(smartlist_t *sl, const routerinfo_t *router) +{ + /* XXXX MOVE ? */ + node_t fake_node; + const node_t *node = node_get_by_id(router->cache_info.identity_digest);; + if (node == NULL) { + memset(&fake_node, 0, sizeof(fake_node)); + fake_node.ri = (routerinfo_t *)router; + memcpy(fake_node.identity, router->cache_info.identity_digest, DIGEST_LEN); + node = &fake_node; + } + nodelist_add_node_and_family(sl, node); +} + +/** Return true iff <b>node</b> is named by some nickname in <b>lst</b>. */ static INLINE int -router_in_nickname_smartlist(smartlist_t *lst, routerinfo_t *r) +node_in_nickname_smartlist(const smartlist_t *lst, const node_t *node) { + /* XXXX MOVE */ if (!lst) return 0; - SMARTLIST_FOREACH(lst, const char *, name, - if (router_nickname_matches(r, name)) - return 1;); + SMARTLIST_FOREACH(lst, const char *, name, { + if (node_nickname_matches(node, name)) + return 1; + }); return 0; } /** Return true iff r1 and r2 are in the same family, but not the same * router. */ int -routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2) +nodes_in_same_family(const node_t *node1, const node_t *node2) { - or_options_t *options = get_options(); - config_line_t *cl; - - if (options->EnforceDistinctSubnets && routers_in_same_network_family(r1,r2)) - return 1; + /* XXXX MOVE */ + const or_options_t *options = get_options(); - if (router_in_nickname_smartlist(r1->declared_family, r2) && - router_in_nickname_smartlist(r2->declared_family, r1)) - return 1; - - for (cl = options->NodeFamilies; cl; cl = cl->next) { - if (router_nickname_is_in_list(r1, cl->value) && - router_nickname_is_in_list(r2, cl->value)) + /* Are they in the same family because of their addresses? */ + if (options->EnforceDistinctSubnets) { + tor_addr_t a1, a2; + node_get_addr(node1, &a1); + node_get_addr(node2, &a2); + if (addrs_in_same_network_family(&a1, &a2)) return 1; } - return 0; -} - -/** Given a (possibly NULL) comma-and-whitespace separated list of nicknames, - * see which nicknames in <b>list</b> name routers in our routerlist, and add - * the routerinfos for those routers to <b>sl</b>. If <b>must_be_running</b>, - * only include routers that we think are running. - * Warn if any non-Named routers are specified by nickname. - */ -void -add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, - int must_be_running) -{ - routerinfo_t *router; - smartlist_t *nickname_list; - int have_dir_info = router_have_minimum_dir_info(); - if (!list) - return; /* nothing to do */ - tor_assert(sl); - - nickname_list = smartlist_create(); - if (!warned_nicknames) - warned_nicknames = smartlist_create(); + /* Are they in the same family because the agree they are? */ + { + const smartlist_t *f1, *f2; + f1 = node_get_declared_family(node1); + f2 = node_get_declared_family(node2); + if (f1 && f2 && + node_in_nickname_smartlist(f1, node2) && + node_in_nickname_smartlist(f2, node1)) + return 1; + } - smartlist_split_string(nickname_list, list, ",", - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + /* Are they in the same option because the user says they are? */ + if (options->NodeFamilySets) { + SMARTLIST_FOREACH(options->NodeFamilySets, const routerset_t *, rs, { + if (routerset_contains_node(rs, node1) && + routerset_contains_node(rs, node2)) + return 1; + }); + } - SMARTLIST_FOREACH(nickname_list, const char *, nick, { - int warned; - if (!is_legal_nickname_or_hexdigest(nick)) { - log_warn(LD_CONFIG, "Nickname '%s' is misformed; skipping", nick); - continue; - } - router = router_get_by_nickname(nick, 1); - warned = smartlist_string_isin(warned_nicknames, nick); - if (router) { - if (!must_be_running || router->is_running) { - smartlist_add(sl,router); - } - } else if (!router_get_consensus_status_by_nickname(nick,1)) { - if (!warned) { - log_fn(have_dir_info ? LOG_WARN : LOG_INFO, LD_CONFIG, - "Nickname list includes '%s' which isn't a known router.",nick); - smartlist_add(warned_nicknames, tor_strdup(nick)); - } - } - }); - SMARTLIST_FOREACH(nickname_list, char *, nick, tor_free(nick)); - smartlist_free(nickname_list); + return 0; } /** Return 1 iff any member of the (possibly NULL) comma-separated list @@ -1475,7 +1508,7 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, * return 0. */ int -router_nickname_is_in_list(routerinfo_t *router, const char *list) +router_nickname_is_in_list(const routerinfo_t *router, const char *list) { smartlist_t *nickname_list; int v = 0; @@ -1494,34 +1527,32 @@ router_nickname_is_in_list(routerinfo_t *router, const char *list) return v; } -/** Add every suitable router from our routerlist to <b>sl</b>, so that +/** Add every suitable node from our nodelist to <b>sl</b>, so that * we can pick a node for a circuit. */ static void -router_add_running_routers_to_smartlist(smartlist_t *sl, int allow_invalid, - int need_uptime, int need_capacity, - int need_guard) -{ - if (!routerlist) - return; +router_add_running_nodes_to_smartlist(smartlist_t *sl, int allow_invalid, + int need_uptime, int need_capacity, + int need_guard, int need_desc) +{ /* XXXX MOVE */ + SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) { + if (!node->is_running || + (!node->is_valid && !allow_invalid)) + continue; + if (need_desc && !(node->ri || (node->rs && node->md))) + continue; + if (node->ri && node->ri->purpose != ROUTER_PURPOSE_GENERAL) + continue; + if (node_is_unreliable(node, need_uptime, need_capacity, need_guard)) + continue; - SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router, - { - if (router->is_running && - router->purpose == ROUTER_PURPOSE_GENERAL && - (router->is_valid || allow_invalid) && - !router_is_unreliable(router, need_uptime, - need_capacity, need_guard)) { - /* If it's running, and it's suitable according to the - * other flags we had in mind */ - smartlist_add(sl, router); - } - }); + smartlist_add(sl, (void *)node); + } SMARTLIST_FOREACH_END(node); } /** Look through the routerlist until we find a router that has my key. Return it. */ -routerinfo_t * +const routerinfo_t * routerlist_find_my_routerinfo(void) { if (!routerlist) @@ -1541,13 +1572,13 @@ routerlist_find_my_routerinfo(void) * Don't exit enclave to excluded relays -- it wouldn't actually * hurt anything, but this way there are fewer confused users. */ -routerinfo_t * +const node_t * router_find_exact_exit_enclave(const char *address, uint16_t port) -{ +{/*XXXX MOVE*/ uint32_t addr; struct in_addr in; tor_addr_t a; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); if (!tor_inet_aton(address, &in)) return NULL; /* it's not an IP already */ @@ -1555,14 +1586,13 @@ router_find_exact_exit_enclave(const char *address, uint16_t port) tor_addr_from_ipv4h(&a, addr); - SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router, - { - if (router->addr == addr && - router->is_running && - compare_tor_addr_to_addr_policy(&a, port, router->exit_policy) == + SMARTLIST_FOREACH(nodelist_get_list(), const node_t *, node, { + if (node_get_addr_ipv4h(node) == addr && + node->is_running && + compare_tor_addr_to_node_policy(&a, port, node) == ADDR_POLICY_ACCEPTED && - !routerset_contains_router(options->_ExcludeExitNodesUnion, router)) - return router; + !routerset_contains_node(options->_ExcludeExitNodesUnion, node)) + return node; }); return NULL; } @@ -1574,14 +1604,14 @@ router_find_exact_exit_enclave(const char *address, uint16_t port) * If <b>need_guard</b>, we require that the router is a possible entry guard. */ int -router_is_unreliable(routerinfo_t *router, int need_uptime, - int need_capacity, int need_guard) +node_is_unreliable(const node_t *node, int need_uptime, + int need_capacity, int need_guard) { - if (need_uptime && !router->is_stable) + if (need_uptime && !node->is_stable) return 1; - if (need_capacity && !router->is_fast) + if (need_capacity && !node->is_fast) return 1; - if (need_guard && !router->is_possible_guard) + if (need_guard && !node->is_possible_guard) return 1; return 0; } @@ -1589,7 +1619,7 @@ router_is_unreliable(routerinfo_t *router, int need_uptime, /** Return the smaller of the router's configured BandwidthRate * and its advertised capacity. */ uint32_t -router_get_advertised_bandwidth(routerinfo_t *router) +router_get_advertised_bandwidth(const routerinfo_t *router) { if (router->bandwidthcapacity < router->bandwidthrate) return router->bandwidthcapacity; @@ -1603,7 +1633,7 @@ router_get_advertised_bandwidth(routerinfo_t *router) /** Return the smaller of the router's configured BandwidthRate * and its advertised capacity, capped by max-believe-bw. */ uint32_t -router_get_advertised_bandwidth_capped(routerinfo_t *router) +router_get_advertised_bandwidth_capped(const routerinfo_t *router) { uint32_t result = router->bandwidthcapacity; if (result > router->bandwidthrate) @@ -1645,13 +1675,10 @@ kb_to_bytes(uint32_t bw) } /** Helper function: - * choose a random element of smartlist <b>sl</b>, weighted by + * choose a random element of smartlist <b>sl</b> of nodes, weighted by * the advertised bandwidth of each element using the consensus * bandwidth weights. * - * If <b>statuses</b> is zero, then <b>sl</b> is a list of - * routerinfo_t's. Otherwise it's a list of routerstatus_t's. - * * If <b>rule</b>==WEIGHT_FOR_EXIT. we're picking an exit node: consider all * nodes' bandwidth equally regardless of their Exit status, since there may * be some in the list because they exit to obscure ports. If @@ -1661,10 +1688,9 @@ kb_to_bytes(uint32_t bw) * guard node: consider all guard's bandwidth equally. Otherwise, weight * guards proportionally less. */ -static void * -smartlist_choose_by_bandwidth_weights(smartlist_t *sl, - bandwidth_weight_rule_t rule, - int statuses) +static const node_t * +smartlist_choose_node_by_bandwidth_weights(smartlist_t *sl, + bandwidth_weight_rule_t rule) { int64_t weight_scale; int64_t rand_bw; @@ -1758,15 +1784,14 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl, bandwidths = tor_malloc_zero(sizeof(double)*smartlist_len(sl)); // Cycle through smartlist and total the bandwidth. - for (i = 0; i < (unsigned)smartlist_len(sl); ++i) { + SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) { int is_exit = 0, is_guard = 0, is_dir = 0, this_bw = 0, is_me = 0; double weight = 1; - if (statuses) { - routerstatus_t *status = smartlist_get(sl, i); - is_exit = status->is_exit && !status->is_bad_exit; - is_guard = status->is_possible_guard; - is_dir = (status->dir_port != 0); - if (!status->has_bandwidth) { + is_exit = node->is_exit && ! node->is_bad_exit; + is_guard = node->is_possible_guard; + is_dir = node_is_dir(node); + if (node->rs) { + if (!node->rs->has_bandwidth) { tor_free(bandwidths); /* This should never happen, unless all the authorites downgrade * to 0.2.0 or rogue routerstatuses get inserted into our consensus. */ @@ -1775,26 +1800,17 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl, "old router selection algorithm."); return NULL; } - this_bw = kb_to_bytes(status->bandwidth); - if (router_digest_is_me(status->identity_digest)) - is_me = 1; + this_bw = kb_to_bytes(node->rs->bandwidth); + } else if (node->ri) { + /* bridge or other descriptor not in our consensus */ + this_bw = bridge_get_advertised_bandwidth_bounded(node->ri); + have_unknown = 1; } else { - routerstatus_t *rs; - routerinfo_t *router = smartlist_get(sl, i); - rs = router_get_consensus_status_by_id( - router->cache_info.identity_digest); - is_exit = router->is_exit && !router->is_bad_exit; - is_guard = router->is_possible_guard; - is_dir = (router->dir_port != 0); - if (rs && rs->has_bandwidth) { - this_bw = kb_to_bytes(rs->bandwidth); - } else { /* bridge or other descriptor not in our consensus */ - this_bw = bridge_get_advertised_bandwidth_bounded(router); - have_unknown = 1; - } - if (router_digest_is_me(router->cache_info.identity_digest)) - is_me = 1; + /* We can't use this one. */ + continue; } + is_me = router_digest_is_me(node->identity); + if (is_guard && is_exit) { weight = (is_dir ? Wdb*Wd : Wd); } else if (is_guard) { @@ -1805,11 +1821,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 +1873,9 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl, } /** Helper function: - * choose a random element of smartlist <b>sl</b>, weighted by + * choose a random node_t element of smartlist <b>sl</b>, weighted by * the advertised bandwidth of each element. * - * If <b>statuses</b> is zero, then <b>sl</b> is a list of - * routerinfo_t's. Otherwise it's a list of routerstatus_t's. - * * If <b>rule</b>==WEIGHT_FOR_EXIT. we're picking an exit node: consider all * nodes' bandwidth equally regardless of their Exit status, since there may * be some in the list because they exit to obscure ports. If @@ -1872,13 +1885,11 @@ smartlist_choose_by_bandwidth_weights(smartlist_t *sl, * guard node: consider all guard's bandwidth equally. Otherwise, weight * guards proportionally less. */ -static void * -smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule, - int statuses) +static const node_t * +smartlist_choose_node_by_bandwidth(smartlist_t *sl, + bandwidth_weight_rule_t rule) { - unsigned int i; - routerinfo_t *router; - routerstatus_t *status=NULL; + unsigned i; int32_t *bandwidths; int is_exit; int is_guard; @@ -1919,49 +1930,34 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule, guard_bits = bitarray_init_zero(smartlist_len(sl)); /* Iterate over all the routerinfo_t or routerstatus_t, and */ - for (i = 0; i < (unsigned)smartlist_len(sl); ++i) { + SMARTLIST_FOREACH_BEGIN(sl, const node_t *, node) { /* first, learn what bandwidth we think i has */ int is_known = 1; int32_t flags = 0; uint32_t this_bw = 0; - if (statuses) { - status = smartlist_get(sl, i); - if (router_digest_is_me(status->identity_digest)) - me_idx = i; - router = router_get_by_digest(status->identity_digest); - is_exit = status->is_exit; - is_guard = status->is_possible_guard; - if (status->has_bandwidth) { - this_bw = kb_to_bytes(status->bandwidth); + i = node_sl_idx; + + if (router_digest_is_me(node->identity)) + me_idx = node_sl_idx; + + is_exit = node->is_exit; + is_guard = node->is_possible_guard; + if (node->rs) { + if (node->rs->has_bandwidth) { + this_bw = kb_to_bytes(node->rs->bandwidth); } else { /* guess */ /* XXX023 once consensuses always list bandwidths, we can take * this guessing business out. -RD */ is_known = 0; - flags = status->is_fast ? 1 : 0; + flags = node->rs->is_fast ? 1 : 0; flags |= is_exit ? 2 : 0; flags |= is_guard ? 4 : 0; } - } else { - routerstatus_t *rs; - router = smartlist_get(sl, i); - rs = router_get_consensus_status_by_id( - router->cache_info.identity_digest); - if (router_digest_is_me(router->cache_info.identity_digest)) - me_idx = i; - is_exit = router->is_exit; - is_guard = router->is_possible_guard; - if (rs && rs->has_bandwidth) { - this_bw = kb_to_bytes(rs->bandwidth); - } else if (rs) { /* guess; don't trust the descriptor */ - /* XXX023 once consensuses always list bandwidths, we can take - * this guessing business out. -RD */ - is_known = 0; - flags = router->is_fast ? 1 : 0; - flags |= is_exit ? 2 : 0; - flags |= is_guard ? 4 : 0; - } else /* bridge or other descriptor not in our consensus */ - this_bw = bridge_get_advertised_bandwidth_bounded(router); + } else if (node->ri) { + /* Must be a bridge if we're willing to use it */ + this_bw = bridge_get_advertised_bandwidth_bounded(node->ri); } + if (is_exit) bitarray_set(exit_bits, i); if (is_guard) @@ -1981,9 +1977,9 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule, total_nonexit_bw += this_bw; } else { ++n_unknown; - bandwidths[i] = -flags; + bandwidths[node_sl_idx] = -flags; } - } + } SMARTLIST_FOREACH_END(node); /* Now, fill in the unknown values. */ if (n_unknown) { @@ -2125,40 +2121,23 @@ smartlist_choose_by_bandwidth(smartlist_t *sl, bandwidth_weight_rule_t rule, return smartlist_get(sl, i); } -/** Choose a random element of router list <b>sl</b>, weighted by - * the advertised bandwidth of each router. - */ -routerinfo_t * -routerlist_sl_choose_by_bandwidth(smartlist_t *sl, - bandwidth_weight_rule_t rule) -{ - routerinfo_t *ret; - if ((ret = smartlist_choose_by_bandwidth_weights(sl, rule, 0))) { - return ret; - } else { - return smartlist_choose_by_bandwidth(sl, rule, 0); - } -} - /** Choose a random element of status list <b>sl</b>, weighted by - * the advertised bandwidth of each status. - */ -routerstatus_t * -routerstatus_sl_choose_by_bandwidth(smartlist_t *sl, - bandwidth_weight_rule_t rule) -{ - /* We are choosing neither exit nor guard here. Weight accordingly. */ - routerstatus_t *ret; - if ((ret = smartlist_choose_by_bandwidth_weights(sl, rule, 1))) { + * the advertised bandwidth of each node */ +const node_t * +node_sl_choose_by_bandwidth(smartlist_t *sl, + bandwidth_weight_rule_t rule) +{ /*XXXX MOVE */ + const node_t *ret; + if ((ret = smartlist_choose_node_by_bandwidth_weights(sl, rule))) { return ret; } else { - return smartlist_choose_by_bandwidth(sl, rule, 1); + return smartlist_choose_node_by_bandwidth(sl, rule); } } -/** Return a random running router from the routerlist. Never - * pick a node whose routerinfo is in - * <b>excludedsmartlist</b>, or whose routerinfo matches <b>excludedset</b>, +/** Return a random running node from the nodelist. Never + * pick a node that is in + * <b>excludedsmartlist</b>, or which matches <b>excludedset</b>, * even if they are the only nodes available. * If <b>CRN_NEED_UPTIME</b> is set in flags and any router has more than * a minimum uptime, return one of those. @@ -2170,21 +2149,26 @@ routerstatus_sl_choose_by_bandwidth(smartlist_t *sl, * If <b>CRN_WEIGHT_AS_EXIT</b> is set in flags, we weight bandwidths as if * picking an exit node, otherwise we weight bandwidths for picking a relay * node (that is, possibly discounting exit nodes). + * If <b>CRN_NEED_DESC</b> is set in flags, we only consider nodes that + * have a routerinfo or microdescriptor -- that is, enough info to be + * used to build a circuit. */ -routerinfo_t * +const node_t * router_choose_random_node(smartlist_t *excludedsmartlist, routerset_t *excludedset, router_crn_flags_t flags) -{ +{ /* XXXX MOVE */ const int need_uptime = (flags & CRN_NEED_UPTIME) != 0; const int need_capacity = (flags & CRN_NEED_CAPACITY) != 0; const int need_guard = (flags & CRN_NEED_GUARD) != 0; const int allow_invalid = (flags & CRN_ALLOW_INVALID) != 0; const int weight_for_exit = (flags & CRN_WEIGHT_AS_EXIT) != 0; + const int need_desc = (flags & CRN_NEED_DESC) != 0; smartlist_t *sl=smartlist_create(), - *excludednodes=smartlist_create(); - routerinfo_t *choice = NULL, *r; + *excludednodes=smartlist_create(); + const node_t *choice = NULL; + const routerinfo_t *r; bandwidth_weight_rule_t rule; tor_assert(!(weight_for_exit && need_guard)); @@ -2194,29 +2178,26 @@ router_choose_random_node(smartlist_t *excludedsmartlist, /* Exclude relays that allow single hop exit circuits, if the user * wants to (such relays might be risky) */ if (get_options()->ExcludeSingleHopRelays) { - routerlist_t *rl = router_get_routerlist(); - SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r, - if (r->allow_single_hop_exits) { - smartlist_add(excludednodes, r); + SMARTLIST_FOREACH(nodelist_get_list(), node_t *, node, + if (node_allows_single_hop_exits(node)) { + smartlist_add(excludednodes, node); }); } - if ((r = routerlist_find_my_routerinfo())) { - smartlist_add(excludednodes, r); - routerlist_add_family(excludednodes, r); - } + if ((r = routerlist_find_my_routerinfo())) + routerlist_add_node_and_family(excludednodes, r); - router_add_running_routers_to_smartlist(sl, allow_invalid, - need_uptime, need_capacity, - need_guard); + router_add_running_nodes_to_smartlist(sl, allow_invalid, + need_uptime, need_capacity, + need_guard, need_desc); smartlist_subtract(sl,excludednodes); if (excludedsmartlist) smartlist_subtract(sl,excludedsmartlist); if (excludedset) - routerset_subtract_routers(sl,excludedset); + routerset_subtract_nodes(sl,excludedset); // Always weight by bandwidth - choice = routerlist_sl_choose_by_bandwidth(sl, rule); + choice = node_sl_choose_by_bandwidth(sl, rule); smartlist_free(sl); if (!choice && (need_uptime || need_capacity || need_guard)) { @@ -2239,35 +2220,90 @@ router_choose_random_node(smartlist_t *excludedsmartlist, return choice; } -/** Helper: Return true iff the <b>identity_digest</b> and <b>nickname</b> - * combination of a router, encoded in hexadecimal, matches <b>hexdigest</b> - * (which is optionally prefixed with a single dollar sign). Return false if - * <b>hexdigest</b> is malformed, or it doesn't match. */ -static INLINE int -hex_digest_matches(const char *hexdigest, const char *identity_digest, - const char *nickname, int is_named) +/** Helper: given an extended nickname in <b>hexdigest</b> try to decode it. + * Return 0 on success, -1 on failure. Store the result into the + * DIGEST_LEN-byte buffer at <b>digest_out</b>, the single character at + * <b>nickname_qualifier_char_out</b>, and the MAXNICKNAME_LEN+1-byte buffer + * at <b>nickname_out</b>. + * + * The recognized format is: + * HexName = Dollar? HexDigest NamePart? + * Dollar = '?' + * HexDigest = HexChar*20 + * HexChar = 'a'..'f' | 'A'..'F' | '0'..'9' + * NamePart = QualChar Name + * QualChar = '=' | '~' + * Name = NameChar*(1..MAX_NICKNAME_LEN) + * NameChar = Any ASCII alphanumeric character + */ +int +hex_digest_nickname_decode(const char *hexdigest, + char *digest_out, + char *nickname_qualifier_char_out, + char *nickname_out) { - char digest[DIGEST_LEN]; size_t len; + tor_assert(hexdigest); if (hexdigest[0] == '$') ++hexdigest; len = strlen(hexdigest); - if (len < HEX_DIGEST_LEN) + if (len < HEX_DIGEST_LEN) { + return -1; + } else if (len > HEX_DIGEST_LEN && (hexdigest[HEX_DIGEST_LEN] == '=' || + hexdigest[HEX_DIGEST_LEN] == '~') && + len <= HEX_DIGEST_LEN+1+MAX_NICKNAME_LEN) { + *nickname_qualifier_char_out = hexdigest[HEX_DIGEST_LEN]; + strlcpy(nickname_out, hexdigest+HEX_DIGEST_LEN+1 , MAX_NICKNAME_LEN+1); + } else if (len == HEX_DIGEST_LEN) { + ; + } else { + return -1; + } + + if (base16_decode(digest_out, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0) + return -1; + return 0; +} + +/** Helper: Return true iff the <b>identity_digest</b> and <b>nickname</b> + * combination of a router, encoded in hexadecimal, matches <b>hexdigest</b> + * (which is optionally prefixed with a single dollar sign). Return false if + * <b>hexdigest</b> is malformed, or it doesn't match. */ +static int +hex_digest_nickname_matches(const char *hexdigest, const char *identity_digest, + const char *nickname, int is_named) +{ + char digest[DIGEST_LEN]; + char nn_char='\0'; + char nn_buf[MAX_NICKNAME_LEN+1]; + + if (hex_digest_nickname_decode(hexdigest, digest, &nn_char, nn_buf) == -1) return 0; - else if (len > HEX_DIGEST_LEN && - (hexdigest[HEX_DIGEST_LEN] == '=' || - hexdigest[HEX_DIGEST_LEN] == '~')) { - if (strcasecmp(hexdigest+HEX_DIGEST_LEN+1, nickname)) + + if (nn_char == '=' || nn_char == '~') { + if (!nickname) + return 0; + if (strcasecmp(nn_buf, nickname)) return 0; - if (hexdigest[HEX_DIGEST_LEN] == '=' && !is_named) + if (nn_char == '=' && !is_named) return 0; } - if (base16_decode(digest, DIGEST_LEN, hexdigest, HEX_DIGEST_LEN)<0) - return 0; - return (tor_memeq(digest, identity_digest, DIGEST_LEN)); + return tor_memeq(digest, identity_digest, DIGEST_LEN); +} + +/* Return true iff <b>router</b> is listed as named in the current + * consensus. */ +int +router_is_named(const routerinfo_t *router) +{ + const char *digest = + networkstatus_get_router_digest_by_nickname(router->nickname); + + return (digest && + tor_memeq(digest, router->cache_info.identity_digest, DIGEST_LEN)); } /** Return true iff the digest of <b>router</b>'s identity key, @@ -2275,10 +2311,12 @@ hex_digest_matches(const char *hexdigest, const char *identity_digest, * optionally prefixed with a single dollar sign). Return false if * <b>hexdigest</b> is malformed, or it doesn't match. */ static INLINE int -router_hex_digest_matches(routerinfo_t *router, const char *hexdigest) +router_hex_digest_matches(const routerinfo_t *router, const char *hexdigest) { - return hex_digest_matches(hexdigest, router->cache_info.identity_digest, - router->nickname, router->is_named); + return hex_digest_nickname_matches(hexdigest, + router->cache_info.identity_digest, + router->nickname, + router_is_named(router)); } /** Return true if <b>router</b>'s nickname matches <b>nickname</b> @@ -2286,20 +2324,43 @@ router_hex_digest_matches(routerinfo_t *router, const char *hexdigest) * matches a hexadecimal value stored in <b>nickname</b>. Return * false otherwise. */ static int -router_nickname_matches(routerinfo_t *router, const char *nickname) +router_nickname_matches(const routerinfo_t *router, const char *nickname) { if (nickname[0]!='$' && !strcasecmp(router->nickname, nickname)) return 1; return router_hex_digest_matches(router, nickname); } +/** Return true if <b>node</b>'s nickname matches <b>nickname</b> + * (case-insensitive), or if <b>node's</b> identity key digest + * matches a hexadecimal value stored in <b>nickname</b>. Return + * false otherwise. */ +static int +node_nickname_matches(const node_t *node, const char *nickname) +{ + const char *n = node_get_nickname(node); + if (n && nickname[0]!='$' && !strcasecmp(n, nickname)) + return 1; + return hex_digest_nickname_matches(nickname, + node->identity, + n, + node_is_named(node)); +} + /** Return the router in our routerlist whose (case-insensitive) * nickname or (case-sensitive) hexadecimal key digest is * <b>nickname</b>. Return NULL if no such router is known. */ -routerinfo_t * +const routerinfo_t * router_get_by_nickname(const char *nickname, int warn_if_unnamed) { +#if 1 + const node_t *node = node_get_by_nickname(nickname, warn_if_unnamed); + if (node) + return node->ri; + else + return NULL; +#else int maybedigest; char digest[DIGEST_LEN]; routerinfo_t *best_match=NULL; @@ -2345,15 +2406,14 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed) if (warn_if_unnamed && n_matches > 1) { smartlist_t *fps = smartlist_create(); int any_unwarned = 0; - SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router, - { + SMARTLIST_FOREACH_BEGIN(routerlist->routers, routerinfo_t *, router) { routerstatus_t *rs; char *desc; size_t dlen; char fp[HEX_DIGEST_LEN+1]; if (strcasecmp(router->nickname, nickname)) continue; - rs = router_get_consensus_status_by_id( + rs = router_get_mutable_consensus_status_by_id( router->cache_info.identity_digest); if (rs && !rs->name_lookup_warned) { rs->name_lookup_warned = 1; @@ -2366,7 +2426,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed) tor_snprintf(desc, dlen, "\"$%s\" for the one at %s:%d", fp, router->address, router->or_port); smartlist_add(fps, desc); - }); + } SMARTLIST_FOREACH_END(router); if (any_unwarned) { char *alternatives = smartlist_join_strings(fps, "; ",0,NULL); log_warn(LD_CONFIG, @@ -2379,7 +2439,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed) SMARTLIST_FOREACH(fps, char *, cp, tor_free(cp)); smartlist_free(fps); } else if (warn_if_unnamed) { - routerstatus_t *rs = router_get_consensus_status_by_id( + routerstatus_t *rs = router_get_mutable_consensus_status_by_id( best_match->cache_info.identity_digest); if (rs && !rs->name_lookup_warned) { char fp[HEX_DIGEST_LEN+1]; @@ -2395,27 +2455,15 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed) } return best_match; } - return NULL; -} - -/** Try to find a routerinfo for <b>digest</b>. If we don't have one, - * return 1. If we do, ask tor_version_as_new_as() for the answer. - */ -int -router_digest_version_as_new_as(const char *digest, const char *cutoff) -{ - routerinfo_t *router = router_get_by_digest(digest); - if (!router) - return 1; - return tor_version_as_new_as(router->platform, cutoff); +#endif } /** Return true iff <b>digest</b> is the digest of the identity key of a * trusted directory matching at least one bit of <b>type</b>. If <b>type</b> * is zero, any authority is okay. */ int -router_digest_is_trusted_dir_type(const char *digest, authority_type_t type) +router_digest_is_trusted_dir_type(const char *digest, dirinfo_type_t type) { if (!trusted_dir_servers) return 0; @@ -2459,44 +2507,20 @@ hexdigest_to_digest(const char *hexdigest, char *digest) /** Return the router in our routerlist whose hexadecimal key digest * is <b>hexdigest</b>. Return NULL if no such router is known. */ -routerinfo_t * +const routerinfo_t * router_get_by_hexdigest(const char *hexdigest) { - char digest[DIGEST_LEN]; - size_t len; - routerinfo_t *ri; - - tor_assert(hexdigest); - if (!routerlist) - return NULL; - if (hexdigest[0]=='$') - ++hexdigest; - len = strlen(hexdigest); - if (hexdigest_to_digest(hexdigest, digest) < 0) + if (is_legal_nickname(hexdigest)) return NULL; - ri = router_get_by_digest(digest); - - if (ri && len > HEX_DIGEST_LEN) { - if (hexdigest[HEX_DIGEST_LEN] == '=') { - if (strcasecmp(ri->nickname, hexdigest+HEX_DIGEST_LEN+1) || - !ri->is_named) - return NULL; - } else if (hexdigest[HEX_DIGEST_LEN] == '~') { - if (strcasecmp(ri->nickname, hexdigest+HEX_DIGEST_LEN+1)) - return NULL; - } else { - return NULL; - } - } - - return ri; + /* It's not a legal nickname, so it must be a hexdigest or nothing. */ + return router_get_by_nickname(hexdigest, 1); } -/** Return the router in our routerlist whose 20-byte key digest - * is <b>digest</b>. Return NULL if no such router is known. */ +/** As router_get_by_id_digest,but return a pointer that you're allowed to + * modify */ routerinfo_t * -router_get_by_digest(const char *digest) +router_get_mutable_by_digest(const char *digest) { tor_assert(digest); @@ -2507,6 +2531,14 @@ router_get_by_digest(const char *digest) return rimap_get(routerlist->identity_map, digest); } +/** Return the router in our routerlist whose 20-byte key digest + * is <b>digest</b>. Return NULL if no such router is known. */ +const routerinfo_t * +router_get_by_id_digest(const char *digest) +{ + return router_get_mutable_by_digest(digest); +} + /** Return the router in our routerlist whose 20-byte descriptor * is <b>digest</b>. Return NULL if no such router is known. */ signed_descriptor_t * @@ -2557,7 +2589,7 @@ extrainfo_get_by_descriptor_digest(const char *digest) * The caller must not free the string returned. */ static const char * -signed_descriptor_get_body_impl(signed_descriptor_t *desc, +signed_descriptor_get_body_impl(const signed_descriptor_t *desc, int with_annotations) { const char *r = NULL; @@ -2606,7 +2638,7 @@ signed_descriptor_get_body_impl(signed_descriptor_t *desc, * The caller must not free the string returned. */ const char * -signed_descriptor_get_body(signed_descriptor_t *desc) +signed_descriptor_get_body(const signed_descriptor_t *desc) { return signed_descriptor_get_body_impl(desc, 0); } @@ -2614,7 +2646,7 @@ signed_descriptor_get_body(signed_descriptor_t *desc) /** As signed_descriptor_get_body(), but points to the beginning of the * annotations section rather than the beginning of the descriptor. */ const char * -signed_descriptor_get_annotations(signed_descriptor_t *desc) +signed_descriptor_get_annotations(const signed_descriptor_t *desc) { return signed_descriptor_get_body_impl(desc, 1); } @@ -2667,7 +2699,6 @@ routerinfo_free(routerinfo_t *router) } addr_policy_list_free(router->exit_policy); - /* XXXX Remove if this turns out to affect performance. */ memset(router, 77, sizeof(routerinfo_t)); tor_free(router); @@ -2682,7 +2713,6 @@ extrainfo_free(extrainfo_t *extrainfo) tor_free(extrainfo->cache_info.signed_descriptor_body); tor_free(extrainfo->pending_sig); - /* XXXX remove this if it turns out to slow us down. */ memset(extrainfo, 88, sizeof(extrainfo_t)); /* debug bad memory usage */ tor_free(extrainfo); } @@ -2696,7 +2726,6 @@ signed_descriptor_free(signed_descriptor_t *sd) tor_free(sd->signed_descriptor_body); - /* XXXX remove this once more bugs go away. */ memset(sd, 99, sizeof(signed_descriptor_t)); /* Debug bad mem usage */ tor_free(sd); } @@ -2802,8 +2831,7 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri) routerinfo_t *ri_old; signed_descriptor_t *sd_old; { - /* XXXX Remove if this slows us down. */ - routerinfo_t *ri_generated = router_get_my_routerinfo(); + const routerinfo_t *ri_generated = router_get_my_routerinfo(); tor_assert(ri_generated != ri); } tor_assert(ri->cache_info.routerlist_index == -1); @@ -2825,6 +2853,7 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri) &ri->cache_info); smartlist_add(rl->routers, ri); ri->cache_info.routerlist_index = smartlist_len(rl->routers) - 1; + nodelist_add_routerinfo(ri); router_dir_info_changed(); #ifdef DEBUG_ROUTERLIST routerlist_assert_ok(rl); @@ -2845,7 +2874,6 @@ extrainfo_insert(routerlist_t *rl, extrainfo_t *ei) extrainfo_t *ei_tmp; { - /* XXXX remove this code if it slows us down. */ extrainfo_t *ei_generated = router_get_my_extrainfo(); tor_assert(ei_generated != ei); } @@ -2891,8 +2919,7 @@ static void routerlist_insert_old(routerlist_t *rl, routerinfo_t *ri) { { - /* XXXX remove this code if it slows us down. */ - routerinfo_t *ri_generated = router_get_my_routerinfo(); + const routerinfo_t *ri_generated = router_get_my_routerinfo(); tor_assert(ri_generated != ri); } tor_assert(ri->cache_info.routerlist_index == -1); @@ -2932,6 +2959,8 @@ routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int make_old, time_t now) tor_assert(0 <= idx && idx < smartlist_len(rl->routers)); tor_assert(smartlist_get(rl->routers, idx) == ri); + nodelist_remove_routerinfo(ri); + /* make sure the rephist module knows that it's not running */ rep_hist_note_router_unreachable(ri->cache_info.identity_digest, now); @@ -3043,8 +3072,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, routerinfo_t *ri_tmp; extrainfo_t *ei_tmp; { - /* XXXX Remove this if it turns out to slow us down. */ - routerinfo_t *ri_generated = router_get_my_routerinfo(); + const routerinfo_t *ri_generated = router_get_my_routerinfo(); tor_assert(ri_generated != ri_new); } tor_assert(ri_old != ri_new); @@ -3054,6 +3082,9 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old, tor_assert(0 <= idx && idx < smartlist_len(rl->routers)); tor_assert(smartlist_get(rl->routers, idx) == ri_old); + nodelist_remove_routerinfo(ri_old); + nodelist_add_routerinfo(ri_new); + router_dir_info_changed(); if (idx >= 0) { smartlist_set(rl->routers, idx, ri_new); @@ -3200,28 +3231,25 @@ routerlist_reset_warnings(void) void router_set_status(const char *digest, int up) { - routerinfo_t *router; - routerstatus_t *status; + node_t *node; tor_assert(digest); SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d, if (tor_memeq(d->digest, digest, DIGEST_LEN)) d->is_running = up); - router = router_get_by_digest(digest); - if (router) { + node = node_get_mutable_by_id(digest); + if (node) { +#if 0 log_debug(LD_DIR,"Marking router %s as %s.", - router_describe(router), up ? "up" : "down"); - if (!up && router_is_me(router) && !we_are_hibernating()) + node_describe(node), up ? "up" : "down"); +#endif + if (!up && node_is_me(node) && !net_is_disabled()) log_warn(LD_NET, "We just marked ourself as down. Are your external " "addresses reachable?"); - router->is_running = up; - } - status = router_get_consensus_status_by_id(digest); - if (status && status->is_running != up) { - status->is_running = up; - control_event_networkstatus_changed_single(status); + node->is_running = up; } + router_dir_info_changed(); } @@ -3250,11 +3278,12 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, int from_cache, int from_fetch) { const char *id_digest; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); int authdir = authdir_mode_handles_descs(options, router->purpose); int authdir_believes_valid = 0; routerinfo_t *old_router; - networkstatus_t *consensus = networkstatus_get_latest_consensus(); + networkstatus_t *consensus = + networkstatus_get_latest_consensus_by_flavor(FLAV_NS); const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list(); int in_consensus = 0; @@ -3265,7 +3294,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, id_digest = router->cache_info.identity_digest; - old_router = router_get_by_digest(id_digest); + old_router = router_get_mutable_by_digest(id_digest); /* Make sure that we haven't already got this exact descriptor. */ if (sdmap_get(routerlist->desc_digest_map, @@ -3297,12 +3326,12 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, if (authdir) { if (authdir_wants_to_reject_router(router, msg, - !from_cache && !from_fetch)) { + !from_cache && !from_fetch, + &authdir_believes_valid)) { tor_assert(*msg); routerinfo_free(router); return ROUTER_AUTHDIR_REJECTS; } - authdir_believes_valid = router->is_valid; } else if (from_fetch) { /* Only check the descriptor digest against the network statuses when * we are receiving in response to a fetch. */ @@ -3329,14 +3358,15 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns, { routerstatus_t *rs = - networkstatus_v2_find_entry(ns, id_digest); + networkstatus_v2_find_mutable_entry(ns, id_digest); if (rs && tor_memeq(rs->descriptor_digest, router->cache_info.signed_descriptor_digest, DIGEST_LEN)) rs->need_to_mirror = 0; }); if (consensus) { - routerstatus_t *rs = networkstatus_vote_find_entry(consensus, id_digest); + routerstatus_t *rs = networkstatus_vote_find_mutable_entry( + consensus, id_digest); if (rs && tor_memeq(rs->descriptor_digest, router->cache_info.signed_descriptor_digest, DIGEST_LEN)) { @@ -3950,7 +3980,7 @@ router_load_extrainfo_from_string(const char *s, const char *eos, static int signed_desc_digest_is_recognized(signed_descriptor_t *desc) { - routerstatus_t *rs; + const routerstatus_t *rs; networkstatus_t *consensus = networkstatus_get_latest_consensus(); int caches = directory_caches_dir_info(get_options()); const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list(); @@ -3974,6 +4004,18 @@ 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) +{ + if (get_options()->DisableNetwork) + return; + 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,35 +4023,37 @@ routerlist_retry_directory_downloads(time_t now) { router_reset_status_download_failures(); router_reset_descriptor_download_failures(); + if (get_options()->DisableNetwork) + return; update_networkstatus_downloads(now); - update_router_descriptor_downloads(now); + update_all_descriptor_downloads(now); } -/** Return 1 if all running sufficiently-stable routers will reject +/** Return 1 if all running sufficiently-stable routers we can use will reject * addr:port, return 0 if any might accept it. */ int -router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port, - int need_uptime) -{ +router_exit_policy_all_nodes_reject(const tor_addr_t *addr, uint16_t port, + int need_uptime) +{ /* XXXX MOVE */ addr_policy_result_t r; - if (!routerlist) return 1; - SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router, - { - if (router->is_running && - !router_is_unreliable(router, need_uptime, 0, 0)) { - r = compare_addr_to_addr_policy(addr, port, router->exit_policy); + SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), const node_t *, node) { + if (node->is_running && + !node_is_unreliable(node, need_uptime, 0, 0)) { + + r = compare_tor_addr_to_node_policy(addr, port, node); + if (r != ADDR_POLICY_REJECTED && r != ADDR_POLICY_PROBABLY_REJECTED) return 0; /* this one could be ok. good enough. */ } - }); + } SMARTLIST_FOREACH_END(node); return 1; /* all will reject. */ } /** Return true iff <b>router</b> does not permit exit streams. */ int -router_exit_policy_rejects_all(routerinfo_t *router) +router_exit_policy_rejects_all(const routerinfo_t *router) { return router->policy_is_reject_star; } @@ -4022,7 +4066,7 @@ trusted_dir_server_t * add_trusted_dir_server(const char *nickname, const char *address, uint16_t dir_port, uint16_t or_port, const char *digest, const char *v3_auth_digest, - authority_type_t type) + dirinfo_type_t type) { trusted_dir_server_t *ent; uint32_t a; @@ -4057,7 +4101,7 @@ add_trusted_dir_server(const char *nickname, const char *address, ent->is_running = 1; ent->type = type; memcpy(ent->digest, digest, DIGEST_LEN); - if (v3_auth_digest && (type & V3_AUTHORITY)) + if (v3_auth_digest && (type & V3_DIRINFO)) memcpy(ent->v3_identity_digest, v3_auth_digest, DIGEST_LEN); dlen = 64 + strlen(hostname) + (nickname?strlen(nickname):0); @@ -4136,7 +4180,7 @@ int any_trusted_dir_is_v1_authority(void) { if (trusted_dir_servers) - return get_n_authorities(V1_AUTHORITY) > 0; + return get_n_authorities(V1_DIRINFO) > 0; return 0; } @@ -4144,7 +4188,9 @@ any_trusted_dir_is_v1_authority(void) /** For every current directory connection whose purpose is <b>purpose</b>, * and where the resource being downloaded begins with <b>prefix</b>, split * rest of the resource into base16 fingerprints, decode them, and set the - * corresponding elements of <b>result</b> to a nonzero value. */ + * corresponding elements of <b>result</b> to a nonzero value. + * DOCDOC purpose==microdesc + */ static void list_pending_downloads(digestmap_t *result, int purpose, const char *prefix) @@ -4152,20 +4198,23 @@ list_pending_downloads(digestmap_t *result, const size_t p_len = strlen(prefix); smartlist_t *tmp = smartlist_create(); smartlist_t *conns = get_connection_array(); + int flags = DSR_HEX; + if (purpose == DIR_PURPOSE_FETCH_MICRODESC) + flags = DSR_DIGEST256|DSR_BASE64; tor_assert(result); - SMARTLIST_FOREACH(conns, connection_t *, conn, - { + SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) { if (conn->type == CONN_TYPE_DIR && conn->purpose == purpose && !conn->marked_for_close) { const char *resource = TO_DIR_CONN(conn)->requested_resource; if (!strcmpstart(resource, prefix)) dir_split_resource_into_fingerprints(resource + p_len, - tmp, NULL, DSR_HEX); + tmp, NULL, flags); } - }); + } SMARTLIST_FOREACH_END(conn); + SMARTLIST_FOREACH(tmp, char *, d, { digestmap_set(result, d, (void*)1); @@ -4185,13 +4234,21 @@ list_pending_descriptor_downloads(digestmap_t *result, int extrainfo) list_pending_downloads(result, purpose, "d/"); } -/** Launch downloads for all the descriptors whose digests are listed - * as digests[i] for lo <= i < hi. (Lo and hi may be out of range.) - * If <b>source</b> is given, download from <b>source</b>; otherwise, - * download from an appropriate random directory server. +/** DOCDOC */ +/*XXXX NM should use digest256, if one comes into being. */ +void +list_pending_microdesc_downloads(digestmap_t *result) +{ + list_pending_downloads(result, DIR_PURPOSE_FETCH_MICRODESC, "d/"); +} + +/** Launch downloads for all the descriptors whose digests or digests256 + * are listed as digests[i] for lo <= i < hi. (Lo and hi may be out of + * range.) If <b>source</b> is given, download from <b>source</b>; + * otherwise, download from an appropriate random directory server. */ static void -initiate_descriptor_downloads(routerstatus_t *source, +initiate_descriptor_downloads(const routerstatus_t *source, int purpose, smartlist_t *digests, int lo, int hi, int pds_flags) @@ -4199,6 +4256,20 @@ initiate_descriptor_downloads(routerstatus_t *source, int i, n = hi-lo; char *resource, *cp; size_t r_len; + + int digest_len = DIGEST_LEN, enc_digest_len = HEX_DIGEST_LEN; + char sep = '+'; + int b64_256 = 0; + + if (purpose == DIR_PURPOSE_FETCH_MICRODESC) { + /* Microdescriptors are downloaded by "-"-separated base64-encoded + * 256-bit digests. */ + digest_len = DIGEST256_LEN; + enc_digest_len = BASE64_DIGEST256_LEN; + sep = '-'; + b64_256 = 1; + } + if (n <= 0) return; if (lo < 0) @@ -4206,15 +4277,19 @@ initiate_descriptor_downloads(routerstatus_t *source, if (hi > smartlist_len(digests)) hi = smartlist_len(digests); - r_len = 8 + (HEX_DIGEST_LEN+1)*n; + r_len = 8 + (enc_digest_len+1)*n; cp = resource = tor_malloc(r_len); memcpy(cp, "d/", 2); cp += 2; for (i = lo; i < hi; ++i) { - base16_encode(cp, r_len-(cp-resource), - smartlist_get(digests,i), DIGEST_LEN); - cp += HEX_DIGEST_LEN; - *cp++ = '+'; + if (b64_256) { + digest256_to_base64(cp, smartlist_get(digests, i)); + } else { + base16_encode(cp, r_len-(cp-resource), + smartlist_get(digests,i), digest_len); + } + cp += enc_digest_len; + *cp++ = sep; } memcpy(cp-1, ".z", 3); @@ -4235,9 +4310,10 @@ initiate_descriptor_downloads(routerstatus_t *source, * running, or otherwise not a descriptor that we would make any * use of even if we had it. Else return 1. */ static INLINE int -client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options) +client_would_use_router(const routerstatus_t *rs, time_t now, + const or_options_t *options) { - if (!rs->is_running && !options->FetchUselessDescriptors) { + if (!rs->is_flagged_running && !options->FetchUselessDescriptors) { /* If we had this router descriptor, we wouldn't even bother using it. * But, if we want to have a complete list, fetch it anyway. */ return 0; @@ -4261,6 +4337,7 @@ client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options) * So use 96 because it's a nice number. */ #define MAX_DL_PER_REQUEST 96 +#define MAX_MICRODESC_DL_PER_REQUEST 92 /** Don't split our requests so finely that we are requesting fewer than * this number per server. */ #define MIN_DL_PER_REQUEST 4 @@ -4275,35 +4352,49 @@ client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options) * them until they have more, or until this amount of time has passed. */ #define MAX_CLIENT_INTERVAL_WITHOUT_REQUEST (10*60) -/** Given a list of router descriptor digests in <b>downloadable</b>, decide - * whether to delay fetching until we have more. If we don't want to delay, - * launch one or more requests to the appropriate directory authorities. */ -static void -launch_router_descriptor_downloads(smartlist_t *downloadable, - routerstatus_t *source, time_t now) +/** Given a <b>purpose</b> (FETCH_MICRODESC or FETCH_SERVERDESC) and a list of + * router descriptor digests or microdescriptor digest256s in + * <b>downloadable</b>, decide whether to delay fetching until we have more. + * If we don't want to delay, launch one or more requests to the appropriate + * directory authorities. + */ +void +launch_descriptor_downloads(int purpose, + smartlist_t *downloadable, + const routerstatus_t *source, time_t now) { int should_delay = 0, n_downloadable; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); + const char *descname; + + tor_assert(purpose == DIR_PURPOSE_FETCH_SERVERDESC || + purpose == DIR_PURPOSE_FETCH_MICRODESC); + + descname = (purpose == DIR_PURPOSE_FETCH_SERVERDESC) ? + "routerdesc" : "microdesc"; n_downloadable = smartlist_len(downloadable); if (!directory_fetches_dir_info_early(options)) { if (n_downloadable >= MAX_DL_TO_DELAY) { log_debug(LD_DIR, - "There are enough downloadable routerdescs to launch requests."); + "There are enough downloadable %ss to launch requests.", + descname); should_delay = 0; } else { - should_delay = (last_routerdesc_download_attempted + + should_delay = (last_descriptor_download_attempted + MAX_CLIENT_INTERVAL_WITHOUT_REQUEST) > now; if (!should_delay && n_downloadable) { - if (last_routerdesc_download_attempted) { + if (last_descriptor_download_attempted) { log_info(LD_DIR, - "There are not many downloadable routerdescs, but we've " + "There are not many downloadable %ss, but we've " "been waiting long enough (%d seconds). Downloading.", - (int)(now-last_routerdesc_download_attempted)); + descname, + (int)(now-last_descriptor_download_attempted)); } else { log_info(LD_DIR, - "There are not many downloadable routerdescs, but we haven't " - "tried downloading descriptors recently. Downloading."); + "There are not many downloadable %ss, but we haven't " + "tried downloading descriptors recently. Downloading.", + descname); } } } @@ -4330,12 +4421,19 @@ launch_router_descriptor_downloads(smartlist_t *downloadable, * update_router_descriptor_downloads() later on, once the connections * have succeeded or failed. */ - pds_flags |= PDS_NO_EXISTING_SERVERDESC_FETCH; + pds_flags |= (purpose == DIR_PURPOSE_FETCH_MICRODESC) ? + PDS_NO_EXISTING_MICRODESC_FETCH : + PDS_NO_EXISTING_SERVERDESC_FETCH; } n_per_request = CEIL_DIV(n_downloadable, MIN_REQUESTS); - if (n_per_request > MAX_DL_PER_REQUEST) - n_per_request = MAX_DL_PER_REQUEST; + if (purpose == DIR_PURPOSE_FETCH_MICRODESC) { + if (n_per_request > MAX_MICRODESC_DL_PER_REQUEST) + n_per_request = MAX_MICRODESC_DL_PER_REQUEST; + } else { + if (n_per_request > MAX_DL_PER_REQUEST) + n_per_request = MAX_DL_PER_REQUEST; + } if (n_per_request < MIN_DL_PER_REQUEST) n_per_request = MIN_DL_PER_REQUEST; @@ -4350,11 +4448,11 @@ launch_router_descriptor_downloads(smartlist_t *downloadable, req_plural, n_downloadable, rtr_plural, n_per_request); smartlist_sort_digests(downloadable); for (i=0; i < n_downloadable; i += n_per_request) { - initiate_descriptor_downloads(source, DIR_PURPOSE_FETCH_SERVERDESC, + initiate_descriptor_downloads(source, purpose, downloadable, i, i+n_per_request, pds_flags); } - last_routerdesc_download_attempted = now; + last_descriptor_download_attempted = now; } } @@ -4370,7 +4468,7 @@ update_router_descriptor_cache_downloads_v2(time_t now) digestmap_t *map; /* Which descs are in progress, or assigned? */ int i, j, n; int n_download; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list(); if (! directory_fetches_dir_info_early(options)) { @@ -4512,7 +4610,7 @@ void update_consensus_router_descriptor_downloads(time_t now, int is_vote, networkstatus_t *consensus) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); digestmap_t *map = NULL; smartlist_t *no_longer_old = smartlist_create(); smartlist_t *downloadable = smartlist_create(); @@ -4540,15 +4638,14 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote, map = digestmap_new(); list_pending_descriptor_downloads(map, 0); - SMARTLIST_FOREACH(consensus->routerstatus_list, void *, rsp, - { + SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, void *, rsp) { routerstatus_t *rs = is_vote ? &(((vote_routerstatus_t *)rsp)->status) : rsp; signed_descriptor_t *sd; if ((sd = router_get_by_descriptor_digest(rs->descriptor_digest))) { - routerinfo_t *ri; + const routerinfo_t *ri; ++n_have; - if (!(ri = router_get_by_digest(rs->identity_digest)) || + if (!(ri = router_get_by_id_digest(rs->identity_digest)) || tor_memneq(ri->cache_info.signed_descriptor_digest, sd->signed_descriptor_digest, DIGEST_LEN)) { /* We have a descriptor with this digest, but either there is no @@ -4581,7 +4678,8 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote, if (is_vote && source) { char time_bufnew[ISO_TIME_LEN+1]; char time_bufold[ISO_TIME_LEN+1]; - routerinfo_t *oldrouter = router_get_by_digest(rs->identity_digest); + const routerinfo_t *oldrouter; + oldrouter = router_get_by_id_digest(rs->identity_digest); format_iso_time(time_bufnew, rs->published_on); if (oldrouter) format_iso_time(time_bufold, oldrouter->cache_info.published_on); @@ -4592,7 +4690,7 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote, source->nickname, oldrouter ? "known" : "unknown"); } smartlist_add(downloadable, rs->descriptor_digest); - }); + } SMARTLIST_FOREACH_END(rsp); if (!authdir_mode_handles_descs(options, ROUTER_PURPOSE_GENERAL) && smartlist_len(no_longer_old)) { @@ -4624,7 +4722,8 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote, smartlist_len(downloadable), n_delayed, n_have, n_in_oldrouters, n_would_reject, n_wouldnt_use, n_inprogress); - launch_router_descriptor_downloads(downloadable, source, now); + launch_descriptor_downloads(DIR_PURPOSE_FETCH_SERVERDESC, + downloadable, source, now); digestmap_free(map, NULL); done: @@ -4638,27 +4737,20 @@ update_consensus_router_descriptor_downloads(time_t now, int is_vote, * do this only when we aren't seeing incoming data. see bug 652. */ #define DUMMY_DOWNLOAD_INTERVAL (20*60) -/** Launch downloads for router status as needed. */ -void -update_router_descriptor_downloads(time_t now) +/** As needed, launch a dummy router descriptor fetch to see if our + * address has changed. */ +static void +launch_dummy_descriptor_download_as_needed(time_t now, + const or_options_t *options) { - or_options_t *options = get_options(); static time_t last_dummy_download = 0; - if (should_delay_dir_fetches(options)) - return; - if (directory_fetches_dir_info_early(options)) { - update_router_descriptor_cache_downloads_v2(now); - } - update_consensus_router_descriptor_downloads(now, 0, - networkstatus_get_reasonably_live_consensus(now)); - /* XXXX023 we could be smarter here; see notes on bug 652. */ /* If we're a server that doesn't have a configured address, we rely on * directory fetches to learn when our address changes. So if we haven't * tried to get any routerdescs in a long time, try a dummy fetch now. */ if (!options->Address && server_mode(options) && - last_routerdesc_download_attempted + DUMMY_DOWNLOAD_INTERVAL < now && + last_descriptor_download_attempted + DUMMY_DOWNLOAD_INTERVAL < now && last_dummy_download + DUMMY_DOWNLOAD_INTERVAL < now) { last_dummy_download = now; directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC, @@ -4667,11 +4759,28 @@ update_router_descriptor_downloads(time_t now) } } +/** Launch downloads for router status as needed. */ +void +update_router_descriptor_downloads(time_t now) +{ + const or_options_t *options = get_options(); + if (should_delay_dir_fetches(options)) + return; + if (!we_fetch_router_descriptors(options)) + return; + if (directory_fetches_dir_info_early(options)) { + update_router_descriptor_cache_downloads_v2(now); + } + + update_consensus_router_descriptor_downloads(now, 0, + networkstatus_get_reasonably_live_consensus(now, FLAV_NS)); +} + /** Launch extrainfo downloads as needed. */ void update_extrainfo_downloads(time_t now) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); routerlist_t *rl; smartlist_t *wanted; digestmap_t *pending; @@ -4699,7 +4808,7 @@ update_extrainfo_downloads(time_t now) sd = &((routerinfo_t*)smartlist_get(lst, i))->cache_info; if (sd->is_extrainfo) continue; /* This should never happen. */ - if (old_routers && !router_get_by_digest(sd->identity_digest)) + if (old_routers && !router_get_by_id_digest(sd->identity_digest)) continue; /* Couldn't check the signature if we got it. */ if (sd->extrainfo_is_bogus) continue; @@ -4793,23 +4902,31 @@ get_dir_info_status_string(void) static void count_usable_descriptors(int *num_present, int *num_usable, const networkstatus_t *consensus, - or_options_t *options, time_t now, + const or_options_t *options, time_t now, routerset_t *in_set) { + const int md = (consensus->flavor == FLAV_MICRODESC); *num_present = 0, *num_usable=0; - SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs, - { - if (in_set && ! routerset_contains_routerstatus(in_set, rs)) + SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *, rs) + { + if (in_set && ! routerset_contains_routerstatus(in_set, rs, -1)) continue; if (client_would_use_router(rs, now, options)) { + const char * const digest = rs->descriptor_digest; + int present; ++*num_usable; /* the consensus says we want it. */ - if (router_get_by_descriptor_digest(rs->descriptor_digest)) { + if (md) + present = NULL != microdesc_cache_lookup_by_digest256(NULL, digest); + else + present = NULL != router_get_by_descriptor_digest(digest); + if (present) { /* we have the descriptor listed in the consensus. */ ++*num_present; } } - }); + } + SMARTLIST_FOREACH_END(rs); log_debug(LD_DIR, "%d usable, %d present.", *num_usable, *num_present); } @@ -4823,7 +4940,7 @@ count_loading_descriptors_progress(void) int num_present = 0, num_usable=0; time_t now = time(NULL); const networkstatus_t *consensus = - networkstatus_get_reasonably_live_consensus(now); + networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor()); double fraction; if (!consensus) @@ -4851,16 +4968,17 @@ update_router_have_minimum_dir_info(void) int num_present = 0, num_usable=0; time_t now = time(NULL); int res; - or_options_t *options = get_options(); + const or_options_t *options = get_options(); const networkstatus_t *consensus = - networkstatus_get_reasonably_live_consensus(now); + networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor()); + int using_md; if (!consensus) { if (!networkstatus_get_latest_consensus()) - strlcpy(dir_info_status, "We have no network-status consensus.", + strlcpy(dir_info_status, "We have no usable consensus.", sizeof(dir_info_status)); else - strlcpy(dir_info_status, "We have no recent network-status consensus.", + strlcpy(dir_info_status, "We have no recent usable consensus.", sizeof(dir_info_status)); res = 0; goto done; @@ -4874,19 +4992,22 @@ update_router_have_minimum_dir_info(void) goto done; } + using_md = consensus->flavor == FLAV_MICRODESC; + count_usable_descriptors(&num_present, &num_usable, consensus, options, now, NULL); if (num_present < num_usable/4) { tor_snprintf(dir_info_status, sizeof(dir_info_status), - "We have only %d/%d usable descriptors.", num_present, num_usable); + "We have only %d/%d usable %sdescriptors.", + num_present, num_usable, using_md ? "micro" : ""); res = 0; control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0); goto done; } else if (num_present < 2) { tor_snprintf(dir_info_status, sizeof(dir_info_status), - "Only %d descriptor%s here and believed reachable!", - num_present, num_present ? "" : "s"); + "Only %d %sdescriptor%s here and believed reachable!", + num_present, using_md ? "micro" : "", num_present ? "" : "s"); res = 0; goto done; } @@ -4898,8 +5019,8 @@ update_router_have_minimum_dir_info(void) if (!num_usable || !num_present) { tor_snprintf(dir_info_status, sizeof(dir_info_status), - "We have only %d/%d usable entry node descriptors.", - num_present, num_usable); + "We have only %d/%d usable entry node %sdescriptors.", + num_present, num_usable, using_md?"micro":""); res = 0; goto done; } @@ -4939,7 +5060,7 @@ void router_reset_descriptor_download_failures(void) { networkstatus_reset_download_failures(); - last_routerdesc_download_attempted = 0; + last_descriptor_download_attempted = 0; if (!routerlist) return; SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri, @@ -4963,7 +5084,7 @@ router_reset_descriptor_download_failures(void) * would not cause a recent (post 0.1.1.6) dirserver to republish. */ int -router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2) +router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2) { time_t r1pub, r2pub; long time_difference; @@ -4971,7 +5092,7 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2) /* r1 should be the one that was published first. */ if (r1->cache_info.published_on > r2->cache_info.published_on) { - routerinfo_t *ri_tmp = r2; + const routerinfo_t *ri_tmp = r2; r2 = r1; r1 = ri_tmp; } @@ -4990,7 +5111,6 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2) (r1->contact_info && r2->contact_info && strcasecmp(r1->contact_info, r2->contact_info)) || r1->is_hibernating != r2->is_hibernating || - r1->has_old_dnsworkers != r2->has_old_dnsworkers || cmp_addr_policies(r1->exit_policy, r2->exit_policy)) return 0; if ((r1->declared_family == NULL) != (r2->declared_family == NULL)) @@ -5045,7 +5165,8 @@ router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2) * incompatibility (if any). **/ int -routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei, +routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri, + extrainfo_t *ei, signed_descriptor_t *sd, const char **msg) { @@ -5053,7 +5174,7 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei, tor_assert(ri); tor_assert(ei); if (!sd) - sd = &ri->cache_info; + sd = (signed_descriptor_t*)&ri->cache_info; if (ei->bad_sig) { if (msg) *msg = "Extrainfo signature was bad, or signed with wrong key."; @@ -5118,7 +5239,7 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei, /** Assert that the internal representation of <b>rl</b> is * self-consistent. */ void -routerlist_assert_ok(routerlist_t *rl) +routerlist_assert_ok(const routerlist_t *rl) { routerinfo_t *r2; signed_descriptor_t *sd2; @@ -5208,7 +5329,7 @@ routerlist_assert_ok(routerlist_t *rl) * If <b>router</b> is NULL, it just frees its internal memory and returns. */ const char * -esc_router_info(routerinfo_t *router) +esc_router_info(const routerinfo_t *router) { static char *info=NULL; char *esc_contact, *esc_platform; @@ -5310,38 +5431,6 @@ routerset_get_countryname(const char *c) return country; } -#if 0 -/** Add the GeoIP database's integer index (+1) of a valid two-character - * country code to the routerset's <b>countries</b> bitarray. Return the - * integer index if the country code is valid, -1 otherwise.*/ -static int -routerset_add_country(const char *c) -{ - char country[3]; - country_t cc; - - /* XXXX: Country codes must be of the form \{[a-z\?]{2}\} but this accepts - \{[.]{2}\}. Do we need to be strict? -RH */ - /* Nope; if the country code is bad, we'll get 0 when we look it up. */ - - if (!geoip_is_loaded()) { - log(LOG_WARN, LD_CONFIG, "GeoIP database not loaded: Cannot add country" - "entry %s, ignoring.", c); - return -1; - } - - memcpy(country, c+1, 2); - country[2] = '\0'; - tor_strlower(country); - - if ((cc=geoip_get_country(country))==-1) { - log(LOG_WARN, LD_CONFIG, "Country code '%s' is not valid, ignoring.", - country); - } - return cc; -} -#endif - /** Update the routerset's <b>countries</b> bitarray_t. Called whenever * the GeoIP database is reloaded. */ @@ -5430,7 +5519,7 @@ routerset_parse(routerset_t *target, const char *s, const char *description) void refresh_all_country_info(void) { - or_options_t *options = get_options(); + const or_options_t *options = get_options(); if (options->EntryNodes) routerset_refresh_countries(options->EntryNodes); @@ -5443,7 +5532,7 @@ refresh_all_country_info(void) if (options->_ExcludeExitNodesUnion) routerset_refresh_countries(options->_ExcludeExitNodesUnion); - routerlist_refresh_countries(); + nodelist_refresh_countries(); } /** Add all members of the set <b>source</b> to <b>target</b>. */ @@ -5493,11 +5582,11 @@ routerset_is_empty(const routerset_t *set) static int routerset_contains(const routerset_t *set, const tor_addr_t *addr, uint16_t orport, - const char *nickname, const char *id_digest, int is_named, + const char *nickname, const char *id_digest, country_t country) { - if (!set || !set->list) return 0; - (void) is_named; /* not supported */ + if (!set || !set->list) + return 0; if (nickname && strmap_get_lc(set->names, nickname)) return 4; if (id_digest && digestmap_get(set->digests, id_digest)) @@ -5525,13 +5614,14 @@ routerset_contains_extendinfo(const routerset_t *set, const extend_info_t *ei) ei->port, ei->nickname, ei->identity_digest, - -1, /*is_named*/ -1 /*country*/); } -/** Return true iff <b>ri</b> is in <b>set</b>. */ +/** Return true iff <b>ri</b> is in <b>set</b>. If country is <b>-1</b>, we + * look up the country. */ int -routerset_contains_router(const routerset_t *set, routerinfo_t *ri) +routerset_contains_router(const routerset_t *set, const routerinfo_t *ri, + country_t country) { tor_addr_t addr; tor_addr_from_ipv4h(&addr, ri->addr); @@ -5540,13 +5630,15 @@ routerset_contains_router(const routerset_t *set, routerinfo_t *ri) ri->or_port, ri->nickname, ri->cache_info.identity_digest, - ri->is_named, - ri->country); + country); } -/** Return true iff <b>rs</b> is in <b>set</b>. */ +/** Return true iff <b>rs</b> is in <b>set</b>. If country is <b>-1</b>, we + * look up the country. */ int -routerset_contains_routerstatus(const routerset_t *set, routerstatus_t *rs) +routerset_contains_routerstatus(const routerset_t *set, + const routerstatus_t *rs, + country_t country) { tor_addr_t addr; tor_addr_from_ipv4h(&addr, rs->addr); @@ -5555,50 +5647,59 @@ routerset_contains_routerstatus(const routerset_t *set, routerstatus_t *rs) rs->or_port, rs->nickname, rs->identity_digest, - rs->is_named, - -1); + country); +} + +/** Return true iff <b>node</b> is in <b>set</b>. */ +int +routerset_contains_node(const routerset_t *set, const node_t *node) +{ + if (node->rs) + return routerset_contains_routerstatus(set, node->rs, node->country); + else if (node->ri) + return routerset_contains_router(set, node->ri, node->country); + else + return 0; } -/** Add every known routerinfo_t that is a member of <b>routerset</b> to +/** Add every known node_t that is a member of <b>routerset</b> to * <b>out</b>, but never add any that are part of <b>excludeset</b>. * If <b>running_only</b>, only add the running ones. */ void -routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset, - const routerset_t *excludeset, int running_only) -{ +routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset, + const routerset_t *excludeset, int running_only) +{ /* XXXX MOVE */ tor_assert(out); if (!routerset || !routerset->list) return; - if (!warned_nicknames) - warned_nicknames = smartlist_create(); - if (routerset_is_list(routerset)) { + if (routerset_is_list(routerset)) { /* No routers are specified by type; all are given by name or digest. * we can do a lookup in O(len(routerset)). */ SMARTLIST_FOREACH(routerset->list, const char *, name, { - routerinfo_t *router = router_get_by_nickname(name, 1); - if (router) { - if (!running_only || router->is_running) - if (!routerset_contains_router(excludeset, router)) - smartlist_add(out, router); + const node_t *node = node_get_by_nickname(name, 1); + if (node) { + if (!running_only || node->is_running) + if (!routerset_contains_node(excludeset, node)) + smartlist_add(out, (void*)node); } }); } else { /* We need to iterate over the routerlist to get all the ones of the * right kind. */ - routerlist_t *rl = router_get_routerlist(); - SMARTLIST_FOREACH(rl->routers, routerinfo_t *, router, { - if (running_only && !router->is_running) + smartlist_t *nodes = nodelist_get_list(); + SMARTLIST_FOREACH(nodes, const node_t *, node, { + if (running_only && !node->is_running) continue; - if (routerset_contains_router(routerset, router) && - !routerset_contains_router(excludeset, router)) - smartlist_add(out, router); + if (routerset_contains_node(routerset, node) && + !routerset_contains_node(excludeset, node)) + smartlist_add(out, (void*)node); }); } } #if 0 -/** Add to <b>target</b> every routerinfo_t from <b>source</b> except: +/** Add to <b>target</b> every node_t from <b>source</b> except: * * 1) Don't add it if <b>include</b> is non-empty and the relay isn't in * <b>include</b>; and @@ -5607,40 +5708,40 @@ routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset, * 3) If <b>running_only</b>, don't add non-running routers. */ void -routersets_get_disjunction(smartlist_t *target, +routersets_get_node_disjunction(smartlist_t *target, const smartlist_t *source, const routerset_t *include, const routerset_t *exclude, int running_only) { - SMARTLIST_FOREACH(source, routerinfo_t *, router, { + SMARTLIST_FOREACH(source, const node_t *, node, { int include_result; - if (running_only && !router->is_running) + if (running_only && !node->is_running) continue; if (!routerset_is_empty(include)) - include_result = routerset_contains_router(include, router); + include_result = routerset_contains_node(include, node); else include_result = 1; if (include_result) { - int exclude_result = routerset_contains_router(exclude, router); + int exclude_result = routerset_contains_node(exclude, node); if (include_result >= exclude_result) - smartlist_add(target, router); + smartlist_add(target, (void*)node); } }); } #endif -/** Remove every routerinfo_t from <b>lst</b> that is in <b>routerset</b>. */ +/** Remove every node_t from <b>lst</b> that is in <b>routerset</b>. */ void -routerset_subtract_routers(smartlist_t *lst, const routerset_t *routerset) -{ +routerset_subtract_nodes(smartlist_t *lst, const routerset_t *routerset) +{ /*XXXX MOVE ? */ tor_assert(lst); if (!routerset) return; - SMARTLIST_FOREACH(lst, routerinfo_t *, r, { - if (routerset_contains_router(routerset, r)) { + SMARTLIST_FOREACH(lst, const node_t *, node, { + if (routerset_contains_node(routerset, node)) { //log_debug(LD_DIR, "Subtracting %s",r->nickname); - SMARTLIST_DEL_CURRENT(lst, r); + SMARTLIST_DEL_CURRENT(lst, node); } }); } @@ -5706,18 +5807,23 @@ routerset_free(routerset_t *routerset) /** Refresh the country code of <b>ri</b>. This function MUST be called on * each router when the GeoIP database is reloaded, and on all new routers. */ void -routerinfo_set_country(routerinfo_t *ri) +node_set_country(node_t *node) { - ri->country = geoip_get_country_by_ip(ri->addr); + if (node->rs) + node->country = geoip_get_country_by_ip(node->rs->addr); + else if (node->ri) + node->country = geoip_get_country_by_ip(node->ri->addr); + else + node->country = -1; } /** Set the country code of all routers in the routerlist. */ void -routerlist_refresh_countries(void) +nodelist_refresh_countries(void) /* MOVE */ { - routerlist_t *rl = router_get_routerlist(); - SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, - routerinfo_set_country(ri)); + smartlist_t *nodes = nodelist_get_list(); + SMARTLIST_FOREACH(nodes, node_t *, node, + node_set_country(node)); } /** Determine the routers that are responsible for <b>id</b> (binary) and @@ -5760,7 +5866,7 @@ hid_serv_get_responsible_directories(smartlist_t *responsible_dirs, int hid_serv_acting_as_directory(void) { - routerinfo_t *me = router_get_my_routerinfo(); + const routerinfo_t *me = router_get_my_routerinfo(); if (!me) return 0; if (!get_options()->HidServDirectoryV2) { @@ -5776,7 +5882,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 fec18705b3..cae8814333 100644 --- a/src/or/routerlist.h +++ b/src/or/routerlist.h @@ -11,7 +11,7 @@ #ifndef _TOR_ROUTERLIST_H #define _TOR_ROUTERLIST_H -int get_n_authorities(authority_type_t type); +int get_n_authorities(dirinfo_type_t type); int trusted_dirs_reload_certs(void); int trusted_dirs_load_certs_from_string(const char *contents, int from_store, int flush); @@ -27,53 +27,50 @@ int router_reload_router_list(void); int authority_cert_dl_looks_uncertain(const char *id_digest); smartlist_t *router_get_trusted_dir_servers(void); -routerstatus_t *router_pick_directory_server(authority_type_t type, int flags); +const routerstatus_t *router_pick_directory_server(dirinfo_type_t type, + int flags); trusted_dir_server_t *router_get_trusteddirserver_by_digest(const char *d); trusted_dir_server_t *trusteddirserver_get_by_v3_auth_digest(const char *d); -routerstatus_t *router_pick_trusteddirserver(authority_type_t type, int flags); +const routerstatus_t *router_pick_trusteddirserver(dirinfo_type_t type, + int flags); int router_get_my_share_of_directory_requests(double *v2_share_out, double *v3_share_out); void router_reset_status_download_failures(void); -void routerlist_add_family(smartlist_t *sl, routerinfo_t *router); -int routers_in_same_family(routerinfo_t *r1, routerinfo_t *r2); int routers_have_same_or_addr(const routerinfo_t *r1, const routerinfo_t *r2); -void add_nickname_list_to_smartlist(smartlist_t *sl, const char *list, - int must_be_running); -int router_nickname_is_in_list(routerinfo_t *router, const char *list); -routerinfo_t *routerlist_find_my_routerinfo(void); -routerinfo_t *router_find_exact_exit_enclave(const char *address, +int router_nickname_is_in_list(const routerinfo_t *router, const char *list); +const routerinfo_t *routerlist_find_my_routerinfo(void); +const node_t *router_find_exact_exit_enclave(const char *address, uint16_t port); -int router_is_unreliable(routerinfo_t *router, int need_uptime, +int node_is_unreliable(const node_t *router, int need_uptime, int need_capacity, int need_guard); -uint32_t router_get_advertised_bandwidth(routerinfo_t *router); -uint32_t router_get_advertised_bandwidth_capped(routerinfo_t *router); +uint32_t router_get_advertised_bandwidth(const routerinfo_t *router); +uint32_t router_get_advertised_bandwidth_capped(const routerinfo_t *router); -routerinfo_t *routerlist_sl_choose_by_bandwidth(smartlist_t *sl, - bandwidth_weight_rule_t rule); -routerstatus_t *routerstatus_sl_choose_by_bandwidth(smartlist_t *sl, - bandwidth_weight_rule_t rule); +const node_t *node_sl_choose_by_bandwidth(smartlist_t *sl, + bandwidth_weight_rule_t rule); -routerinfo_t *router_choose_random_node(smartlist_t *excludedsmartlist, +const node_t *router_choose_random_node(smartlist_t *excludedsmartlist, struct routerset_t *excludedset, router_crn_flags_t flags); -routerinfo_t *router_get_by_nickname(const char *nickname, +const routerinfo_t *router_get_by_nickname(const char *nickname, int warn_if_unnamed); -int router_digest_version_as_new_as(const char *digest, const char *cutoff); +int router_is_named(const routerinfo_t *router); int router_digest_is_trusted_dir_type(const char *digest, - authority_type_t type); + dirinfo_type_t type); #define router_digest_is_trusted_dir(d) \ - router_digest_is_trusted_dir_type((d), NO_AUTHORITY) + router_digest_is_trusted_dir_type((d), NO_DIRINFO) int router_addr_is_trusted_dir(uint32_t addr); int hexdigest_to_digest(const char *hexdigest, char *digest); -routerinfo_t *router_get_by_hexdigest(const char *hexdigest); -routerinfo_t *router_get_by_digest(const char *digest); +const routerinfo_t *router_get_by_hexdigest(const char *hexdigest); +const routerinfo_t *router_get_by_id_digest(const char *digest); +routerinfo_t *router_get_mutable_by_digest(const char *digest); signed_descriptor_t *router_get_by_descriptor_digest(const char *digest); signed_descriptor_t *router_get_by_extrainfo_digest(const char *digest); signed_descriptor_t *extrainfo_get_by_descriptor_digest(const char *digest); -const char *signed_descriptor_get_body(signed_descriptor_t *desc); -const char *signed_descriptor_get_annotations(signed_descriptor_t *desc); +const char *signed_descriptor_get_body(const signed_descriptor_t *desc); +const char *signed_descriptor_get_annotations(const signed_descriptor_t *desc); routerlist_t *router_get_routerlist(void); void routerinfo_free(routerinfo_t *router); void extrainfo_free(extrainfo_t *extrainfo); @@ -132,63 +129,71 @@ void router_load_extrainfo_from_string(const char *s, const char *eos, int descriptor_digests); void routerlist_retry_directory_downloads(time_t now); -int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port, - int need_uptime); -int router_exit_policy_rejects_all(routerinfo_t *router); +int router_exit_policy_all_nodes_reject(const tor_addr_t *addr, uint16_t port, + int need_uptime); + +int router_exit_policy_rejects_all(const routerinfo_t *router); trusted_dir_server_t *add_trusted_dir_server(const char *nickname, const char *address, uint16_t dir_port, uint16_t or_port, const char *digest, const char *v3_auth_digest, - authority_type_t type); + dirinfo_type_t type); void authority_cert_free(authority_cert_t *cert); void clear_trusted_dir_servers(void); int any_trusted_dir_is_v1_authority(void); void update_consensus_router_descriptor_downloads(time_t now, int is_vote, networkstatus_t *consensus); void update_router_descriptor_downloads(time_t now); +void update_all_descriptor_downloads(time_t now); void update_extrainfo_downloads(time_t now); int router_have_minimum_dir_info(void); void router_dir_info_changed(void); const char *get_dir_info_status_string(void); int count_loading_descriptors_progress(void); void router_reset_descriptor_download_failures(void); -int router_differences_are_cosmetic(routerinfo_t *r1, routerinfo_t *r2); -int routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei, +int router_differences_are_cosmetic(const routerinfo_t *r1, + const routerinfo_t *r2); +int routerinfo_incompatible_with_extrainfo(const routerinfo_t *ri, + extrainfo_t *ei, signed_descriptor_t *sd, const char **msg); -void routerlist_assert_ok(routerlist_t *rl); -const char *esc_router_info(routerinfo_t *router); +void routerlist_assert_ok(const routerlist_t *rl); +const char *esc_router_info(const routerinfo_t *router); void routers_sort_by_identity(smartlist_t *routers); routerset_t *routerset_new(void); +void routerset_refresh_countries(routerset_t *rs); int routerset_parse(routerset_t *target, const char *s, const char *description); void routerset_union(routerset_t *target, const routerset_t *source); int routerset_is_list(const routerset_t *set); int routerset_needs_geoip(const routerset_t *set); int routerset_is_empty(const routerset_t *set); -int routerset_contains_router(const routerset_t *set, routerinfo_t *ri); +int routerset_contains_router(const routerset_t *set, const routerinfo_t *ri, + country_t country); int routerset_contains_routerstatus(const routerset_t *set, - routerstatus_t *rs); + const routerstatus_t *rs, + country_t country); int routerset_contains_extendinfo(const routerset_t *set, const extend_info_t *ei); -void routerset_get_all_routers(smartlist_t *out, const routerset_t *routerset, - const routerset_t *excludeset, - int running_only); + +int routerset_contains_node(const routerset_t *set, const node_t *node); +void routerset_get_all_nodes(smartlist_t *out, const routerset_t *routerset, + const routerset_t *excludeset, + int running_only); #if 0 -void routersets_get_disjunction(smartlist_t *target, const smartlist_t *source, +void routersets_get_node_disjunction(smartlist_t *target, + const smartlist_t *source, const routerset_t *include, const routerset_t *exclude, int running_only); #endif -void routerset_subtract_routers(smartlist_t *out, +void routerset_subtract_nodes(smartlist_t *out, const routerset_t *routerset); + char *routerset_to_string(const routerset_t *routerset); -void routerset_refresh_countries(routerset_t *target); int routerset_equal(const routerset_t *old, const routerset_t *new); void routerset_free(routerset_t *routerset); -void routerinfo_set_country(routerinfo_t *ri); -void routerlist_refresh_countries(void); void refresh_all_country_info(void); int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs, @@ -196,5 +201,16 @@ int hid_serv_get_responsible_directories(smartlist_t *responsible_dirs, int hid_serv_acting_as_directory(void); int hid_serv_responsible_for_desc_id(const char *id); +void list_pending_microdesc_downloads(digestmap_t *result); +void launch_descriptor_downloads(int purpose, + smartlist_t *downloadable, + const routerstatus_t *source, + time_t now); + +int hex_digest_nickname_decode(const char *hexdigest, + char *digest_out, + char *nickname_qualifier_out, + char *nickname_out); + #endif diff --git a/src/or/routerparse.c b/src/or/routerparse.c index aed4fd131e..4ea7b964cf 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 ), @@ -572,7 +570,6 @@ static int check_signature_token(const char *digest, int flags, const char *doctype); static crypto_pk_env_t *find_dir_signing_key(const char *str, const char *eos); -static int tor_version_same_series(tor_version_t *a, tor_version_t *b); #undef DEBUG_AREA_ALLOC @@ -1358,7 +1355,6 @@ router_parse_entry_from_string(const char *s, const char *end, tor_assert(tok->n_args >= 5); router = tor_malloc_zero(sizeof(routerinfo_t)); - router->country = -1; router->cache_info.routerlist_index = -1; router->cache_info.annotations_len = s-start_of_annotations + prepend_len; router->cache_info.signed_descriptor_len = end-s; @@ -1504,13 +1500,6 @@ router_parse_entry_from_string(const char *s, const char *end, router->contact_info = tor_strdup(tok->args[0]); } - if ((tok = find_opt_by_keyword(tokens, K_EVENTDNS))) { - router->has_old_dnsworkers = tok->n_args && !strcmp(tok->args[0], "0"); - } else if (router->platform) { - if (! tor_version_as_new_as(router->platform, "0.1.2.2-alpha")) - router->has_old_dnsworkers = 1; - } - if (find_opt_by_keyword(tokens, K_REJECT6) || find_opt_by_keyword(tokens, K_ACCEPT6)) { log_warn(LD_DIR, "Rejecting router with reject6/accept6 line: they crash " @@ -1575,8 +1564,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; @@ -1824,9 +1811,9 @@ authority_cert_parse_from_string(const char *s, const char **end_of_string) struct in_addr in; char *address = NULL; tor_assert(tok->n_args); - /* XXX023 use tor_addr_port_parse() below instead. -RD */ - if (parse_addr_port(LOG_WARN, tok->args[0], &address, NULL, - &cert->dir_port)<0 || + /* XXX023 use some tor_addr parse function below instead. -RD */ + if (tor_addr_port_split(LOG_WARN, tok->args[0], &address, + &cert->dir_port) < 0 || tor_inet_aton(address, &in) == 0) { log_warn(LD_DIR, "Couldn't parse dir-address in certificate"); tor_free(address); @@ -1976,6 +1963,7 @@ routerstatus_parse_entry_from_string(memarea_t *area, if (!consensus_method) flav = FLAV_NS; + tor_assert(flav == FLAV_NS || flav == FLAV_MICRODESC); eos = find_start_of_next_routerstatus(*s); @@ -1988,15 +1976,16 @@ routerstatus_parse_entry_from_string(memarea_t *area, goto err; } tok = find_by_keyword(tokens, K_R); - tor_assert(tok->n_args >= 7); + tor_assert(tok->n_args >= 7); /* guaranteed by GE(7) in K_R setup */ if (flav == FLAV_NS) { if (tok->n_args < 8) { log_warn(LD_DIR, "Too few arguments to r"); goto err; } - } else { - offset = -1; + } else if (flav == FLAV_MICRODESC) { + offset = -1; /* There is no identity digest */ } + if (vote_rs) { rs = &vote_rs->status; } else { @@ -2070,7 +2059,7 @@ routerstatus_parse_entry_from_string(memarea_t *area, else if (!strcmp(tok->args[i], "Fast")) rs->is_fast = 1; else if (!strcmp(tok->args[i], "Running")) - rs->is_running = 1; + rs->is_flagged_running = 1; else if (!strcmp(tok->args[i], "Named")) rs->is_named = 1; else if (!strcmp(tok->args[i], "Valid")) @@ -2101,6 +2090,8 @@ routerstatus_parse_entry_from_string(memarea_t *area, rs->version_supports_begindir = 1; rs->version_supports_extrainfo_upload = 1; rs->version_supports_conditional_consensus = 1; + rs->version_supports_microdesc_cache = 1; + rs->version_supports_optimistic_data = 1; } else { rs->version_supports_begindir = tor_version_as_new_as(tok->args[0], "0.2.0.1-alpha"); @@ -2110,6 +2101,16 @@ routerstatus_parse_entry_from_string(memarea_t *area, tor_version_as_new_as(tok->args[0], "0.2.0.8-alpha"); rs->version_supports_conditional_consensus = tor_version_as_new_as(tok->args[0], "0.2.1.1-alpha"); + /* XXXX023 NM microdescs: 0.2.3.1-alpha isn't widely used yet, but + * not all 0.2.3.0-alpha "versions" actually support microdesc cacheing + * right. There's a compromise here. Since this is 5 May, let's + * err on the side of having some possible caches to use. Once more + * caches are running 0.2.3.1-alpha, we can bump this version number. + */ + rs->version_supports_microdesc_cache = + tor_version_as_new_as(tok->args[0], "0.2.3.0-alpha"); + rs->version_supports_optimistic_data = + tor_version_as_new_as(tok->args[0], "0.2.3.1-alpha"); } if (vote_rs) { vote_rs->version = tor_strdup(tok->args[0]); @@ -2172,6 +2173,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)) @@ -3503,10 +3514,10 @@ networkstatus_parse_detached_signatures(const char *s, const char *eos) siglist = detached_get_signatures(sigs, flavor); is_duplicate = 0; - SMARTLIST_FOREACH(siglist, document_signature_t *, s, { - if (s->alg == alg && - tor_memeq(id_digest, s->identity_digest, DIGEST_LEN) && - tor_memeq(sk_digest, s->signing_key_digest, DIGEST_LEN)) { + SMARTLIST_FOREACH(siglist, document_signature_t *, dsig, { + if (dsig->alg == alg && + tor_memeq(id_digest, dsig->identity_digest, DIGEST_LEN) && + tor_memeq(sk_digest, dsig->signing_key_digest, DIGEST_LEN)) { is_duplicate = 1; } }); @@ -4359,7 +4370,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); @@ -4556,7 +4567,7 @@ tor_version_compare(tor_version_t *a, tor_version_t *b) /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series. */ -static int +int tor_version_same_series(tor_version_t *a, tor_version_t *b) { tor_assert(a); @@ -4875,6 +4886,11 @@ rend_decrypt_introduction_points(char **ipos_decrypted, crypto_cipher_env_t *cipher; char *dec; int declen; + if (ipos_encrypted_size < CIPHER_IV_LEN + 2) { + log_warn(LD_REND, "Size of encrypted introduction points is too " + "small."); + return -1; + } dec = tor_malloc_zero(ipos_encrypted_size - CIPHER_IV_LEN - 1); cipher = crypto_create_init_cipher(descriptor_cookie, 0); declen = crypto_cipher_decrypt_with_iv(cipher, dec, @@ -4970,7 +4986,7 @@ rend_parse_introduction_points(rend_service_descriptor_t *parsed, info->identity_digest, DIGEST_LEN); /* Parse IP address. */ tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS); - if (tor_addr_from_str(&info->addr, tok->args[0])<0) { + if (tor_addr_parse(&info->addr, tok->args[0])<0) { log_warn(LD_REND, "Could not parse introduction point address."); rend_intro_point_free(intro); goto err; diff --git a/src/or/routerparse.h b/src/or/routerparse.h index 8b8cde25f6..527de5dc8b 100644 --- a/src/or/routerparse.h +++ b/src/or/routerparse.h @@ -47,6 +47,7 @@ version_status_t tor_version_is_obsolete(const char *myversion, int tor_version_parse(const char *s, tor_version_t *out); int tor_version_as_new_as(const char *platform, const char *cutoff); int tor_version_compare(tor_version_t *a, tor_version_t *b); +int tor_version_same_series(tor_version_t *a, tor_version_t *b); void sort_version_list(smartlist_t *lst, int remove_duplicates); void assert_addr_policy_ok(smartlist_t *t); void dump_distinct_digest_count(int severity); diff --git a/src/or/status.c b/src/or/status.c new file mode 100644 index 0000000000..3e4cb779a3 --- /dev/null +++ b/src/or/status.c @@ -0,0 +1,115 @@ +/* Copyright (c) 2010-2011, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file status.c + * \brief Keep status information and log the heartbeat messages. + **/ + +#include "or.h" +#include "config.h" +#include "status.h" +#include "nodelist.h" +#include "router.h" +#include "circuitlist.h" +#include "main.h" + +/** Return the total number of circuits. */ +static int +count_circuits(void) +{ + circuit_t *circ; + int nr=0; + + for (circ = _circuit_get_global_list(); circ; circ = circ->next) + nr++; + + return nr; +} + +/** Take seconds <b>secs</b> and return a newly allocated human-readable + * uptime string */ +static char * +secs_to_uptime(long secs) +{ + long int days = secs / 86400; + int hours = (int)((secs - (days * 86400)) / 3600); + int minutes = (int)((secs - (days * 86400) - (hours * 3600)) / 60); + char *uptime_string = NULL; + + switch (days) { + case 0: + tor_asprintf(&uptime_string, "%d:%02d hours", hours, minutes); + break; + case 1: + tor_asprintf(&uptime_string, "%ld day %d:%02d hours", + days, hours, minutes); + break; + default: + tor_asprintf(&uptime_string, "%ld days %d:%02d hours", + days, hours, minutes); + break; + } + + return uptime_string; +} + +/** Take <b>bytes</b> and returns a newly allocated human-readable usage + * string. */ +static char * +bytes_to_usage(uint64_t bytes) +{ + char *bw_string = NULL; + + if (bytes < (1<<20)) { /* Less than a megabyte. */ + tor_asprintf(&bw_string, U64_FORMAT" kB", U64_PRINTF_ARG(bytes>>10)); + } else if (bytes < (1<<30)) { /* Megabytes. Let's add some precision. */ + double bw = U64_TO_DBL(bytes); + tor_asprintf(&bw_string, "%.2f MB", bw/(1<<20)); + } else { /* Gigabytes. */ + double bw = U64_TO_DBL(bytes); + tor_asprintf(&bw_string, "%.2f GB", bw/(1<<30)); + } + + return bw_string; +} + +/** Log a "heartbeat" message describing Tor's status and history so that the + * user can know that there is indeed a running Tor. Return 0 on success and + * -1 on failure. */ +int +log_heartbeat(time_t now) +{ + char *bw_sent = NULL; + char *bw_rcvd = NULL; + char *uptime = NULL; + const routerinfo_t *me; + + const or_options_t *options = get_options(); + (void)now; + + if (public_server_mode(options)) { + /* Let's check if we are in the current cached consensus. */ + if (!(me = router_get_my_routerinfo())) + return -1; /* Something stinks, we won't even attempt this. */ + else + if (!node_get_by_id(me->cache_info.identity_digest)) + log_fn(LOG_NOTICE, LD_HEARTBEAT, "Heartbeat: It seems like we are not " + "in the cached consensus."); + } + + uptime = secs_to_uptime(get_uptime()); + bw_rcvd = bytes_to_usage(get_bytes_read()); + bw_sent = bytes_to_usage(get_bytes_written()); + + log_fn(LOG_NOTICE, LD_HEARTBEAT, "Heartbeat: Tor's uptime is %s, with %d " + "circuits open. I've sent %s and received %s.", + uptime, count_circuits(),bw_sent,bw_rcvd); + + tor_free(uptime); + tor_free(bw_sent); + tor_free(bw_rcvd); + + return 0; +} + diff --git a/src/or/status.h b/src/or/status.h new file mode 100644 index 0000000000..ac726a1d2d --- /dev/null +++ b/src/or/status.h @@ -0,0 +1,10 @@ +/* Copyright (c) 2010, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#ifndef _TOR_STATUS_H +#define _TOR_STATUS_H + +int log_heartbeat(time_t now); + +#endif + diff --git a/src/or/transports.c b/src/or/transports.c new file mode 100644 index 0000000000..10155c4475 --- /dev/null +++ b/src/or/transports.c @@ -0,0 +1,1248 @@ +/* Copyright (c) 2011, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file transports.c + * \brief Pluggable Transports related code. + **/ + +#define PT_PRIVATE +#include "or.h" +#include "config.h" +#include "circuitbuild.h" +#include "transports.h" +#include "util.h" + +#ifdef MS_WINDOWS +static void set_managed_proxy_environment(LPVOID *envp, + const managed_proxy_t *mp); +#else +static int set_managed_proxy_environment(char ***envp, + const managed_proxy_t *mp); +#endif + +static INLINE int proxy_configuration_finished(const managed_proxy_t *mp); + +static void managed_proxy_destroy(managed_proxy_t *mp, + int also_terminate_process); + +static void handle_finished_proxy(managed_proxy_t *mp); +static void configure_proxy(managed_proxy_t *mp); + +static void parse_method_error(const char *line, int is_server_method); +#define parse_server_method_error(l) parse_method_error(l, 1) +#define parse_client_method_error(l) parse_method_error(l, 0) + +static INLINE void free_execve_args(char **arg); + +/** Managed proxy protocol strings */ +#define PROTO_ENV_ERROR "ENV-ERROR" +#define PROTO_NEG_SUCCESS "VERSION" +#define PROTO_NEG_FAIL "VERSION-ERROR no-version" +#define PROTO_CMETHOD "CMETHOD" +#define PROTO_SMETHOD "SMETHOD" +#define PROTO_CMETHOD_ERROR "CMETHOD-ERROR" +#define PROTO_SMETHOD_ERROR "SMETHOD-ERROR" +#define PROTO_CMETHODS_DONE "CMETHODS DONE" +#define PROTO_SMETHODS_DONE "SMETHODS DONE" + +/* The smallest valid managed proxy protocol line that can + appear. It's the size of "VERSION 1" */ +#define SMALLEST_MANAGED_LINE_SIZE 9 + +/** Number of environment variables for managed proxy clients/servers. */ +#define ENVIRON_SIZE_CLIENT 5 +#define ENVIRON_SIZE_SERVER 8 + +/** The first and only supported - at the moment - configuration + protocol version. */ +#define PROTO_VERSION_ONE 1 + +/** List of unconfigured managed proxies. */ +static smartlist_t *managed_proxy_list = NULL; +/** Number of still unconfigured proxies. */ +static int unconfigured_proxies_n = 0; + +/** "The main idea is:" + + Each managed proxy is represented by a 'managed_proxy_t'. + Each managed proxy can support multiple transports. + Each managed proxy gets configured through a multistep process. + + 'managed_proxy_list' contains all the managed proxies this tor + instance is supporting. + In the 'managed_proxy_list' there are 'unconfigured_proxies_n' + managed proxies that are still unconfigured. + + In every run_scheduled_event() tick, we attempt to launch and then + configure the unconfiged managed proxies, using the configuration + protocol defined in the 180_pluggable_transport.txt proposal. A + managed proxy might need several ticks to get fully configured. + + When a managed proxy is fully configured, we register all its + transports to the circuitbuild.c subsystem. At that point the + transports are owned by the circuitbuild.c subsystem. + + When a managed proxy fails to follow the 180 configuration + protocol, it gets marked as broken and gets destroyed. + + "In a little more technical detail:" + + While we are serially parsing torrc, we store all the transports + that a proxy should spawn in its 'transports_to_launch' element. + + When we finish reading the torrc, we spawn the managed proxy and + expect {S,C}METHOD lines from its output. We add transports + described by METHOD lines to its 'transports' element, as + 'transport_t' structs. + + When the managed proxy stops spitting METHOD lines (signified by a + '{S,C}METHODS DONE' message) we register all the transports + collected to the circuitbuild.c subsystem. At this point, the + 'transport_t's can be transformed into dangling pointers at any + point by the circuitbuild.c subsystem, and so we replace all + 'transport_t's with strings describing the transport names. We + can still go from a transport name to a 'transport_t' using the + fact that transport names uniquely identify 'transport_t's. + + "In even more technical detail I shall describe what happens when + the SIGHUP bell tolls:" + + We immediately destroy all unconfigured proxies (We shouldn't have + unconfigured proxies in the first place, except when SIGHUP rings + immediately after tor is launched.). + + We mark all managed proxies and transports to signify that they + must be removed if they don't contribute by the new torrc + (marked_for_removal). + We also mark all managed proxies to signify that they might need + to be restarted so that they end up supporting all the transports + the new torrc wants them to support (got_hup). + We also clear their 'transports_to_launch' list so that we can put + there the transports we need to launch according to the new torrc. + + We then start parsing torrc again. + + Everytime we encounter a transport line using a known pre-SIGHUP + managed proxy, we cleanse that proxy from the removal mark. + + We also mark it as unconfigured so that on the next scheduled + events tick, we investigate whether we need to restart the proxy + so that it also spawns the new transports. + If the post-SIGHUP 'transports_to_launch' list is identical to the + pre-SIGHUP one, it means that no changes were introduced to this + proxy during the SIGHUP and no restart has to take place. + + During the post-SIGHUP torrc parsing, we unmark all transports + spawned by managed proxies that we find in our torrc. + We do that so that if we don't need to restart a managed proxy, we + can continue using its old transports normally. + If we end up restarting the proxy, we destroy and unregister all + old transports from the circuitbuild.c subsystem. +*/ + +/** Return true if there are still unconfigured managed proxies. */ +int +pt_proxies_configuration_pending(void) +{ + return !! unconfigured_proxies_n; +} + +/** Return true if <b>mp</b> has the same argv as <b>proxy_argv</b> */ +static int +managed_proxy_has_argv(const managed_proxy_t *mp, char **proxy_argv) +{ + char **tmp1=proxy_argv; + char **tmp2=mp->argv; + + tor_assert(tmp1); + tor_assert(tmp2); + + while (*tmp1 && *tmp2) { + if (strcmp(*tmp1++, *tmp2++)) + return 0; + } + + if (!*tmp1 && !*tmp2) + return 1; + + return 0; +} + +/** Return a managed proxy with the same argv as <b>proxy_argv</b>. + * If no such managed proxy exists, return NULL. */ +static managed_proxy_t * +get_managed_proxy_by_argv_and_type(char **proxy_argv, int is_server) +{ + if (!managed_proxy_list) + return NULL; + + SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) { + if (managed_proxy_has_argv(mp, proxy_argv) && + mp->is_server == is_server) + return mp; + } SMARTLIST_FOREACH_END(mp); + + return NULL; +} + +/** Add <b>transport</b> to managed proxy <b>mp</b>. */ +static void +add_transport_to_proxy(const char *transport, managed_proxy_t *mp) +{ + tor_assert(mp->transports_to_launch); + if (!smartlist_string_isin(mp->transports_to_launch, transport)) + smartlist_add(mp->transports_to_launch, tor_strdup(transport)); +} + +/** Called when a SIGHUP occurs. Returns true if managed proxy + * <b>mp</b> needs to be restarted after the SIGHUP, based on the new + * torrc. */ +static int +proxy_needs_restart(const managed_proxy_t *mp) +{ + /* mp->transport_to_launch is populated with the names of the + transports that must be launched *after* the SIGHUP. + mp->transports is populated with the names of the transports that + were launched *before* the SIGHUP. + + If the two lists contain the same strings, we don't need to + restart the proxy, since it already does what we want. */ + + tor_assert(smartlist_len(mp->transports_to_launch) > 0); + tor_assert(mp->conf_state == PT_PROTO_COMPLETED); + + if (smartlist_len(mp->transports_to_launch) != smartlist_len(mp->transports)) + goto needs_restart; + + SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t_t_l) { + if (!smartlist_string_isin(mp->transports, t_t_l)) + goto needs_restart; + + } SMARTLIST_FOREACH_END(t_t_l); + + return 0; + + needs_restart: + return 1; +} + +/** Managed proxy <b>mp</b> must be restarted. Do all the necessary + * preparations and then flag its state so that it will be relaunched + * in the next tick. */ +static void +proxy_prepare_for_restart(managed_proxy_t *mp) +{ + transport_t *t_tmp = NULL; + + tor_assert(mp->conf_state == PT_PROTO_COMPLETED); + + /* destroy the process handle and terminate the process. */ + tor_process_handle_destroy(mp->process_handle, 1); + mp->process_handle = NULL; + + /* destroy all its old transports. we no longer use them. */ + SMARTLIST_FOREACH_BEGIN(mp->transports, const char *, t_name) { + t_tmp = transport_get_by_name(t_name); + if (t_tmp) + t_tmp->marked_for_removal = 1; + } SMARTLIST_FOREACH_END(t_name); + sweep_transport_list(); + + /* free the transport names in mp->transports */ + SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name)); + smartlist_clear(mp->transports); + + /* flag it as an infant proxy so that it gets launched on next tick */ + mp->conf_state = PT_PROTO_INFANT; +} + +/** Launch managed proxy <b>mp</b>. */ +static int +launch_managed_proxy(managed_proxy_t *mp) +{ + int retval; + +#ifdef MS_WINDOWS + + LPVOID envp=NULL; + + set_managed_proxy_environment(&envp, mp); + tor_assert(envp); + + /* Passing NULL as lpApplicationName makes Windows search for the .exe */ + retval = tor_spawn_background(NULL, (const char **)mp->argv, envp, + &mp->process_handle); + + tor_free(envp); + +#else + + char **envp=NULL; + + /* prepare the environment variables for the managed proxy */ + if (set_managed_proxy_environment(&envp, mp) < 0) { + log_warn(LD_GENERAL, "Could not setup the environment of " + "the managed proxy at '%s'.", mp->argv[0]); + free_execve_args(envp); + return -1; + } + + retval = tor_spawn_background(mp->argv[0], (const char **)mp->argv, + (const char **)envp, &mp->process_handle); + + /* free the memory allocated by set_managed_proxy_environment(). */ + free_execve_args(envp); + +#endif + + if (retval == PROCESS_STATUS_ERROR) { + log_warn(LD_GENERAL, "Managed proxy at '%s' failed at launch.", + mp->argv[0]); + return -1; + } + + log_info(LD_CONFIG, "Managed proxy at '%s' has spawned with PID '%d'.", + mp->argv[0], tor_process_get_pid(mp->process_handle)); + + mp->conf_state = PT_PROTO_LAUNCHED; + + return 0; +} + +/** Check if any of the managed proxies we are currently trying to + * configure have anything new to say. This is called from + * run_scheduled_events(). */ +void +pt_configure_remaining_proxies(void) +{ + log_debug(LD_CONFIG, "Configuring remaining managed proxies (%d)!", + unconfigured_proxies_n); + SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) { + tor_assert(mp->conf_state != PT_PROTO_BROKEN || + mp->conf_state != PT_PROTO_FAILED_LAUNCH); + + if (mp->got_hup) { + mp->got_hup = 0; + + /* This proxy is marked by a SIGHUP. Check whether we need to + restart it. */ + if (proxy_needs_restart(mp)) { + log_info(LD_GENERAL, "Preparing managed proxy for restart."); + proxy_prepare_for_restart(mp); + continue; + } else { /* it doesn't need to be restarted. */ + log_info(LD_GENERAL, "Nothing changed for managed proxy after HUP: " + "not restarting."); + unconfigured_proxies_n--; + tor_assert(unconfigured_proxies_n >= 0); + } + + continue; + } + + /* If the proxy is not fully configured, try to configure it + futher. */ + if (!proxy_configuration_finished(mp)) + configure_proxy(mp); + + } SMARTLIST_FOREACH_END(mp); +} + +#ifdef MS_WINDOWS + +/** Attempt to continue configuring managed proxy <b>mp</b>. */ +static void +configure_proxy(managed_proxy_t *mp) +{ + int pos; + char stdout_buf[200]; + smartlist_t *lines = NULL; + + /* if we haven't launched the proxy yet, do it now */ + if (mp->conf_state == PT_PROTO_INFANT) { + if (launch_managed_proxy(mp) < 0) { /* launch fail */ + mp->conf_state = PT_PROTO_FAILED_LAUNCH; + handle_finished_proxy(mp); + } + return; + } + + tor_assert(mp->conf_state != PT_PROTO_INFANT); + tor_assert(mp->process_handle); + + pos = tor_read_all_handle(tor_process_get_stdout_pipe(mp->process_handle), + stdout_buf, sizeof(stdout_buf) - 1, NULL); + if (pos < 0) { + log_notice(LD_GENERAL, "Failed to read data from managed proxy"); + mp->conf_state = PT_PROTO_BROKEN; + goto done; + } + + if (pos == 0) /* proxy has nothing interesting to say. */ + return; + + /* End with a null even if there isn't a \r\n at the end */ + /* TODO: What if this is a partial line? */ + stdout_buf[pos] = '\0'; + + /* Split up the buffer */ + lines = smartlist_create(); + tor_split_lines(lines, stdout_buf, pos); + + /* Handle lines. */ + SMARTLIST_FOREACH_BEGIN(lines, const char *, line) { + handle_proxy_line(line, mp); + if (proxy_configuration_finished(mp)) + goto done; + } SMARTLIST_FOREACH_END(line); + + done: + /* if the proxy finished configuring, exit the loop. */ + if (proxy_configuration_finished(mp)) + handle_finished_proxy(mp); + + if (lines) + smartlist_free(lines); +} + +#else /* MS_WINDOWS */ + +/** Attempt to continue configuring managed proxy <b>mp</b>. */ +static void +configure_proxy(managed_proxy_t *mp) +{ + enum stream_status r; + char stdout_buf[200]; + + /* if we haven't launched the proxy yet, do it now */ + if (mp->conf_state == PT_PROTO_INFANT) { + if (launch_managed_proxy(mp) < 0) { /* launch fail */ + mp->conf_state = PT_PROTO_FAILED_LAUNCH; + handle_finished_proxy(mp); + } + return; + } + + tor_assert(mp->conf_state != PT_PROTO_INFANT); + tor_assert(mp->process_handle); + + while (1) { + r = get_string_from_pipe(tor_process_get_stdout_pipe(mp->process_handle), + stdout_buf, sizeof(stdout_buf) - 1); + + if (r == IO_STREAM_OKAY) { /* got a line; handle it! */ + handle_proxy_line((const char *)stdout_buf, mp); + } else if (r == IO_STREAM_EAGAIN) { /* check back later */ + return; + } else if (r == IO_STREAM_CLOSED || r == IO_STREAM_TERM) { /* snap! */ + log_notice(LD_GENERAL, "Managed proxy stream closed. " + "Most probably application stopped running"); + mp->conf_state = PT_PROTO_BROKEN; + } else { /* unknown stream status */ + log_notice(LD_GENERAL, "Unknown stream status while configuring proxy."); + } + + /* if the proxy finished configuring, exit the loop. */ + if (proxy_configuration_finished(mp)) { + handle_finished_proxy(mp); + return; + } + } +} + +#endif /* MS_WINDOWS */ + +/** Register server managed proxy <b>mp</b> transports to state */ +static void +register_server_proxy(managed_proxy_t *mp) +{ + /* After we register this proxy's transports, we switch its + mp->transports to a list containing strings of its transport + names. (See transports.h) */ + smartlist_t *sm_tmp = smartlist_create(); + + tor_assert(mp->conf_state != PT_PROTO_COMPLETED); + SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) { + save_transport_to_state(t->name, &t->addr, t->port); + /* LOG_WARN so that the bridge operator can easily find the + transport's port in the log file and send it to the users. */ + log_warn(LD_GENERAL, "Registered server transport '%s' at '%s:%d'", + t->name, fmt_addr(&t->addr), (int)t->port); + smartlist_add(sm_tmp, tor_strdup(t->name)); + } SMARTLIST_FOREACH_END(t); + + /* Since server proxies don't register their transports in the + circuitbuild.c subsystem, it's our duty to free them when we + switch mp->transports to strings. */ + SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t)); + smartlist_free(mp->transports); + + mp->transports = sm_tmp; +} + +/** Register all the transports supported by client managed proxy + * <b>mp</b> to the bridge subsystem. */ +static void +register_client_proxy(managed_proxy_t *mp) +{ + int r; + /* After we register this proxy's transports, we switch its + mp->transports to a list containing strings of its transport + names. (See transports.h) */ + smartlist_t *sm_tmp = smartlist_create(); + + tor_assert(mp->conf_state != PT_PROTO_COMPLETED); + SMARTLIST_FOREACH_BEGIN(mp->transports, transport_t *, t) { + r = transport_add(t); + switch (r) { + case -1: + log_notice(LD_GENERAL, "Could not add transport %s. Skipping.", t->name); + transport_free(t); + break; + case 0: + log_info(LD_GENERAL, "Succesfully registered transport %s", t->name); + smartlist_add(sm_tmp, tor_strdup(t->name)); + break; + case 1: + log_info(LD_GENERAL, "Succesfully registered transport %s", t->name); + smartlist_add(sm_tmp, tor_strdup(t->name)); + transport_free(t); + break; + } + } SMARTLIST_FOREACH_END(t); + + smartlist_free(mp->transports); + mp->transports = sm_tmp; +} + +/** Register the transports of managed proxy <b>mp</b>. */ +static INLINE void +register_proxy(managed_proxy_t *mp) +{ + if (mp->is_server) + register_server_proxy(mp); + else + register_client_proxy(mp); +} + +/** Free memory allocated by managed proxy <b>mp</b>. */ +static void +managed_proxy_destroy(managed_proxy_t *mp, + int also_terminate_process) +{ + if (mp->conf_state != PT_PROTO_COMPLETED) + SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t)); + else + SMARTLIST_FOREACH(mp->transports, char *, t_name, tor_free(t_name)); + + /* free the transports smartlist */ + smartlist_free(mp->transports); + + /* free the transports_to_launch smartlist */ + SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t)); + smartlist_free(mp->transports_to_launch); + + /* remove it from the list of managed proxies */ + smartlist_remove(managed_proxy_list, mp); + + /* free the argv */ + free_execve_args(mp->argv); + + tor_process_handle_destroy(mp->process_handle, also_terminate_process); + mp->process_handle = NULL; + + tor_free(mp); +} + +/** Handle a configured or broken managed proxy <b>mp</b>. */ +static void +handle_finished_proxy(managed_proxy_t *mp) +{ + switch (mp->conf_state) { + case PT_PROTO_BROKEN: /* if broken: */ + managed_proxy_destroy(mp, 1); /* annihilate it. */ + break; + case PT_PROTO_FAILED_LAUNCH: /* if it failed before launching: */ + managed_proxy_destroy(mp, 0); /* destroy it but don't terminate */ + break; + case PT_PROTO_CONFIGURED: /* if configured correctly: */ + register_proxy(mp); /* register its transports */ + mp->conf_state = PT_PROTO_COMPLETED; /* and mark it as completed. */ + break; + case PT_PROTO_INFANT: + case PT_PROTO_LAUNCHED: + case PT_PROTO_ACCEPTING_METHODS: + case PT_PROTO_COMPLETED: + default: + log_warn(LD_CONFIG, "Unexpected managed proxy state in " + "handle_finished_proxy()."); + tor_assert(0); + } + + unconfigured_proxies_n--; + tor_assert(unconfigured_proxies_n >= 0); +} + +/** Return true if the configuration of the managed proxy <b>mp</b> is + finished. */ +static INLINE int +proxy_configuration_finished(const managed_proxy_t *mp) +{ + return (mp->conf_state == PT_PROTO_CONFIGURED || + mp->conf_state == PT_PROTO_BROKEN || + mp->conf_state == PT_PROTO_FAILED_LAUNCH); +} + +/** This function is called when a proxy sends an {S,C}METHODS DONE message. */ +static void +handle_methods_done(const managed_proxy_t *mp) +{ + tor_assert(mp->transports); + + if (smartlist_len(mp->transports) == 0) + log_notice(LD_GENERAL, "Proxy was spawned successfully, " + "but it didn't laucn any pluggable transport listeners!"); + + log_info(LD_CONFIG, "%s managed proxy configuration completed!", + mp->is_server ? "Server" : "Client"); +} + +/** Handle a configuration protocol <b>line</b> received from a + * managed proxy <b>mp</b>. */ +void +handle_proxy_line(const char *line, managed_proxy_t *mp) +{ + log_debug(LD_GENERAL, "Got a line from managed proxy: %s", line); + + if (strlen(line) < SMALLEST_MANAGED_LINE_SIZE) { + log_warn(LD_GENERAL, "Managed proxy configuration line is too small. " + "Discarding"); + goto err; + } + + if (!strcmpstart(line, PROTO_ENV_ERROR)) { + if (mp->conf_state != PT_PROTO_LAUNCHED) + goto err; + + parse_env_error(line); + goto err; + } else if (!strcmpstart(line, PROTO_NEG_FAIL)) { + if (mp->conf_state != PT_PROTO_LAUNCHED) + goto err; + + log_warn(LD_CONFIG, "Managed proxy could not pick a " + "configuration protocol version."); + goto err; + } else if (!strcmpstart(line, PROTO_NEG_SUCCESS)) { + if (mp->conf_state != PT_PROTO_LAUNCHED) + goto err; + + if (parse_version(line,mp) < 0) + goto err; + + tor_assert(mp->conf_protocol != 0); + mp->conf_state = PT_PROTO_ACCEPTING_METHODS; + return; + } else if (!strcmpstart(line, PROTO_CMETHODS_DONE)) { + if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS) + goto err; + + handle_methods_done(mp); + + mp->conf_state = PT_PROTO_CONFIGURED; + return; + } else if (!strcmpstart(line, PROTO_SMETHODS_DONE)) { + if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS) + goto err; + + handle_methods_done(mp); + + mp->conf_state = PT_PROTO_CONFIGURED; + return; + } else if (!strcmpstart(line, PROTO_CMETHOD_ERROR)) { + if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS) + goto err; + + parse_client_method_error(line); + goto err; + } else if (!strcmpstart(line, PROTO_SMETHOD_ERROR)) { + if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS) + goto err; + + parse_server_method_error(line); + goto err; + } else if (!strcmpstart(line, PROTO_CMETHOD)) { + if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS) + goto err; + + if (parse_cmethod_line(line, mp) < 0) + goto err; + + return; + } else if (!strcmpstart(line, PROTO_SMETHOD)) { + if (mp->conf_state != PT_PROTO_ACCEPTING_METHODS) + goto err; + + if (parse_smethod_line(line, mp) < 0) + goto err; + + return; + } else if (!strcmpstart(line, SPAWN_ERROR_MESSAGE)) { + log_warn(LD_GENERAL, "Could not launch managed proxy executable!"); + mp->conf_state = PT_PROTO_FAILED_LAUNCH; + return; + } + + log_warn(LD_CONFIG, "Unknown line received by managed proxy. (%s)", line); + + err: + mp->conf_state = PT_PROTO_BROKEN; + log_warn(LD_CONFIG, "Managed proxy at '%s' failed the configuration protocol" + " and will be destroyed.", mp->argv ? mp->argv[0] : ""); +} + +/** Parses an ENV-ERROR <b>line</b> and warns the user accordingly. */ +void +parse_env_error(const char *line) +{ + /* (Length of the protocol string) plus (a space) and (the first char of + the error message) */ + if (strlen(line) < (strlen(PROTO_ENV_ERROR) + 2)) + log_notice(LD_CONFIG, "Managed proxy sent us an %s without an error " + "message.", PROTO_ENV_ERROR); + + log_warn(LD_CONFIG, "Managed proxy couldn't understand the " + "pluggable transport environment variables. (%s)", + line+strlen(PROTO_ENV_ERROR)+1); +} + +/** Handles a VERSION <b>line</b>. Updates the configuration protocol + * version in <b>mp</b>. */ +int +parse_version(const char *line, managed_proxy_t *mp) +{ + if (strlen(line) < (strlen(PROTO_NEG_SUCCESS) + 2)) { + log_warn(LD_CONFIG, "Managed proxy sent us malformed %s line.", + PROTO_NEG_SUCCESS); + return -1; + } + + if (strcmp("1", line+strlen(PROTO_NEG_SUCCESS)+1)) { /* hardcoded temp */ + log_warn(LD_CONFIG, "Managed proxy tried to negotiate on version '%s'. " + "We only support version '1'", line+strlen(PROTO_NEG_SUCCESS)+1); + return -1; + } + + mp->conf_protocol = PROTO_VERSION_ONE; /* temp. till more versions appear */ + return 0; +} + +/** Parses {C,S}METHOD-ERROR <b>line</b> and warns the user + * accordingly. If <b>is_server</b> it is an SMETHOD-ERROR, + * otherwise it is a CMETHOD-ERROR. */ +static void +parse_method_error(const char *line, int is_server) +{ + const char* error = is_server ? + PROTO_SMETHOD_ERROR : PROTO_CMETHOD_ERROR; + + /* (Length of the protocol string) plus (a space) and (the first char of + the error message) */ + if (strlen(line) < (strlen(error) + 2)) + log_warn(LD_CONFIG, "Managed proxy sent us an %s without an error " + "message.", error); + + log_warn(LD_CONFIG, "%s managed proxy encountered a method error. (%s)", + is_server ? "Server" : "Client", + line+strlen(error)+1); +} + +/** Parses an SMETHOD <b>line</b> and if well-formed it registers the + * new transport in <b>mp</b>. */ +int +parse_smethod_line(const char *line, managed_proxy_t *mp) +{ + int r; + smartlist_t *items = NULL; + + char *method_name=NULL; + + char *addrport=NULL; + tor_addr_t addr; + uint16_t port = 0; + + transport_t *transport=NULL; + + items = smartlist_create(); + smartlist_split_string(items, line, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + if (smartlist_len(items) < 3) { + log_warn(LD_CONFIG, "Server managed proxy sent us a SMETHOD line " + "with too few arguments."); + goto err; + } + + tor_assert(!strcmp(smartlist_get(items,0),PROTO_SMETHOD)); + + method_name = smartlist_get(items,1); + if (!string_is_C_identifier(method_name)) { + log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).", + method_name); + goto err; + } + + addrport = smartlist_get(items, 2); + if (tor_addr_port_lookup(addrport, &addr, &port)<0) { + log_warn(LD_CONFIG, "Error parsing transport " + "address '%s'", addrport); + goto err; + } + + if (!port) { + log_warn(LD_CONFIG, + "Transport address '%s' has no port.", addrport); + goto err; + } + + transport = transport_create(&addr, port, method_name, PROXY_NONE); + if (!transport) + goto err; + + smartlist_add(mp->transports, transport); + + /* For now, notify the user so that he knows where the server + transport is listening. */ + log_info(LD_CONFIG, "Server transport %s at %s:%d.", + method_name, fmt_addr(&addr), (int)port); + + r=0; + goto done; + + err: + r = -1; + + done: + SMARTLIST_FOREACH(items, char*, s, tor_free(s)); + smartlist_free(items); + return r; +} + +/** Parses a CMETHOD <b>line</b>, and if well-formed it registers + * the new transport in <b>mp</b>. */ +int +parse_cmethod_line(const char *line, managed_proxy_t *mp) +{ + int r; + smartlist_t *items = NULL; + + char *method_name=NULL; + + char *socks_ver_str=NULL; + int socks_ver=PROXY_NONE; + + char *addrport=NULL; + tor_addr_t addr; + uint16_t port = 0; + + transport_t *transport=NULL; + + items = smartlist_create(); + smartlist_split_string(items, line, NULL, + SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1); + if (smartlist_len(items) < 4) { + log_warn(LD_CONFIG, "Client managed proxy sent us a CMETHOD line " + "with too few arguments."); + goto err; + } + + tor_assert(!strcmp(smartlist_get(items,0),PROTO_CMETHOD)); + + method_name = smartlist_get(items,1); + if (!string_is_C_identifier(method_name)) { + log_warn(LD_CONFIG, "Transport name is not a C identifier (%s).", + method_name); + goto err; + } + + socks_ver_str = smartlist_get(items,2); + + if (!strcmp(socks_ver_str,"socks4")) { + socks_ver = PROXY_SOCKS4; + } else if (!strcmp(socks_ver_str,"socks5")) { + socks_ver = PROXY_SOCKS5; + } else { + log_warn(LD_CONFIG, "Client managed proxy sent us a proxy protocol " + "we don't recognize. (%s)", socks_ver_str); + goto err; + } + + addrport = smartlist_get(items, 3); + if (tor_addr_port_lookup(addrport, &addr, &port)<0) { + log_warn(LD_CONFIG, "Error parsing transport " + "address '%s'", addrport); + goto err; + } + + if (!port) { + log_warn(LD_CONFIG, + "Transport address '%s' has no port.", addrport); + goto err; + } + + transport = transport_create(&addr, port, method_name, socks_ver); + if (!transport) + goto err; + + smartlist_add(mp->transports, transport); + + log_info(LD_CONFIG, "Transport %s at %s:%d with SOCKS %d. " + "Attached to managed proxy.", + method_name, fmt_addr(&addr), (int)port, socks_ver); + + r=0; + goto done; + + err: + r = -1; + + done: + SMARTLIST_FOREACH(items, char*, s, tor_free(s)); + smartlist_free(items); + return r; +} + +/** Return a string containing the address:port that <b>transport</b> + * should use. It's the responsibility of the caller to free() the + * received string. */ +static char * +get_bindaddr_for_proxy(const managed_proxy_t *mp) +{ + char *bindaddr = NULL; + smartlist_t *string_tmp = smartlist_create(); + + tor_assert(mp->is_server); + + SMARTLIST_FOREACH_BEGIN(mp->transports_to_launch, char *, t) { + tor_asprintf(&bindaddr, "%s-%s", t, get_bindaddr_for_transport(t)); + smartlist_add(string_tmp, bindaddr); + } SMARTLIST_FOREACH_END(t); + + bindaddr = smartlist_join_strings(string_tmp, ",", 0, NULL); + + SMARTLIST_FOREACH(string_tmp, char *, t, tor_free(t)); + smartlist_free(string_tmp); + + return bindaddr; +} + +#ifdef MS_WINDOWS + +/** Prepare the environment <b>envp</b> of managed proxy <b>mp</b>. + * <b>envp</b> is allocated on the heap and should be freed by the + * caller after its use. */ +static void +set_managed_proxy_environment(LPVOID *envp, const managed_proxy_t *mp) +{ + const or_options_t *options = get_options(); + extern char **environ; + + LPVOID tmp=NULL; + + char *state_tmp=NULL; + char *state_env=NULL; + char *transports_to_launch=NULL; + char *transports_env=NULL; + char *bindaddr_tmp=NULL; + char *bindaddr_env=NULL; + char *orport_env=NULL; + + char version_env[31]; /* XXX temp */ + char extended_env[43]; /* XXX temp */ + + int env_size = 0; + + /* A smartlist carrying all the env. variables that the managed + proxy should inherit. */ + smartlist_t *envs = smartlist_create(); + + /* Copy the whole environment of the Tor process. + It should also copy PATH and HOME of the Tor process.*/ + char **environ_tmp = environ; + while (*environ_tmp) + smartlist_add(envs, *environ_tmp++); + + /* Create the TOR_PT_* environment variables. */ + state_tmp = get_datadir_fname("pt_state/"); /* XXX temp */ + tor_asprintf(&state_env, "TOR_PT_STATE_LOCATION=%s", state_tmp); + + strcpy(version_env, "TOR_PT_MANAGED_TRANSPORT_VER=1"); + + transports_to_launch = + smartlist_join_strings(mp->transports_to_launch, ",", 0, NULL); + + tor_asprintf(&transports_env, + mp->is_server ? + "TOR_PT_SERVER_TRANSPORTS=%s" : "TOR_PT_CLIENT_TRANSPORTS=%s", + transports_to_launch); + + smartlist_add(envs, state_env); + smartlist_add(envs, version_env); + smartlist_add(envs, transports_env); + + if (mp->is_server) { + tor_asprintf(&orport_env, "TOR_PT_ORPORT=127.0.0.1:%d", options->ORPort); + + bindaddr_tmp = get_bindaddr_for_proxy(mp); + tor_asprintf(&bindaddr_env, "TOR_PT_SERVER_BINDADDR=%s", bindaddr_tmp); + + strcpy(extended_env, "TOR_PT_EXTENDED_SERVER_PORT=127.0.0.1:4200"); + + smartlist_add(envs, orport_env); + smartlist_add(envs, extended_env); + smartlist_add(envs, bindaddr_env); + } + + /* It seems like some versions of Windows need a sorted lpEnvironment + block. */ + smartlist_sort_strings(envs); + + /* An environment block consists of a null-terminated block of + null-terminated strings: */ + + /* Calculate the block's size. */ + SMARTLIST_FOREACH(envs, const char *, s, + env_size += strlen(s) + 1); + env_size += 1; /* space for last NUL */ + + *envp = tor_malloc(env_size); + tmp = *envp; + + /* Create the block. */ + SMARTLIST_FOREACH_BEGIN(envs, const char *, s) { + memcpy(tmp, s, strlen(s)); /* copy the env. variable string */ + tmp += strlen(s); + memset(tmp, '\0', 1); /* append NUL at the end of the string */ + tmp += 1; + } SMARTLIST_FOREACH_END(s); + memset(tmp, '\0', 1); /* last NUL */ + + /* Finally, free the whole mess. */ + tor_free(state_tmp); + tor_free(state_env); + tor_free(transports_to_launch); + tor_free(transports_env); + tor_free(bindaddr_tmp); + tor_free(bindaddr_env); + tor_free(orport_env); + + smartlist_free(envs); +} + +#else /* MS_WINDOWS */ + +/** Prepare the environment <b>envp</b> of managed proxy <b>mp</b>. + * <b>envp</b> is allocated on the heap and should be freed by the + * caller after its use. */ +static int +set_managed_proxy_environment(char ***envp, const managed_proxy_t *mp) +{ + const or_options_t *options = get_options(); + char **tmp=NULL; + char *state_loc=NULL; + char *transports_to_launch=NULL; + char *bindaddr=NULL; + char *home_env=NULL; + char *path_env=NULL; + + int r = -1; + int n_envs = mp->is_server ? ENVIRON_SIZE_SERVER : ENVIRON_SIZE_CLIENT; + + /* allocate enough space for our env. vars and a NULL pointer */ + *envp = tor_malloc(sizeof(char*)*(n_envs+1)); + tmp = *envp; + + state_loc = get_datadir_fname("pt_state/"); /* XXX temp */ + transports_to_launch = + smartlist_join_strings(mp->transports_to_launch, ",", 0, NULL); + + home_env = getenv("HOME"); + path_env = getenv("PATH"); + if (!home_env || !path_env) + goto done; + + tor_asprintf(tmp++, "HOME=%s", home_env); + tor_asprintf(tmp++, "PATH=%s", path_env); + tor_asprintf(tmp++, "TOR_PT_STATE_LOCATION=%s", state_loc); + tor_asprintf(tmp++, "TOR_PT_MANAGED_TRANSPORT_VER=1"); /* temp */ + if (mp->is_server) { + bindaddr = get_bindaddr_for_proxy(mp); + + /* XXX temp */ + tor_asprintf(tmp++, "TOR_PT_ORPORT=127.0.0.1:%d", options->ORPort); + tor_asprintf(tmp++, "TOR_PT_SERVER_BINDADDR=%s", bindaddr); + tor_asprintf(tmp++, "TOR_PT_SERVER_TRANSPORTS=%s", transports_to_launch); + /* XXX temp*/ + tor_asprintf(tmp++, "TOR_PT_EXTENDED_SERVER_PORT=127.0.0.1:4200"); + } else { + tor_asprintf(tmp++, "TOR_PT_CLIENT_TRANSPORTS=%s", transports_to_launch); + } + *tmp = NULL; + + r = 0; + + done: + tor_free(state_loc); + tor_free(transports_to_launch); + tor_free(bindaddr); + + return r; +} + +#endif /* MS_WINDOWS */ + +/** Create and return a new managed proxy for <b>transport</b> using + * <b>proxy_argv</b>. If <b>is_server</b> is true, it's a server + * managed proxy. */ +static managed_proxy_t * +managed_proxy_create(const smartlist_t *transport_list, + char **proxy_argv, int is_server) +{ + managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t)); + mp->conf_state = PT_PROTO_INFANT; + mp->is_server = is_server; + mp->argv = proxy_argv; + mp->transports = smartlist_create(); + + mp->transports_to_launch = smartlist_create(); + SMARTLIST_FOREACH(transport_list, const char *, transport, + add_transport_to_proxy(transport, mp)); + + /* register the managed proxy */ + if (!managed_proxy_list) + managed_proxy_list = smartlist_create(); + smartlist_add(managed_proxy_list, mp); + unconfigured_proxies_n++; + + return mp; +} + +/** Register <b>transport</b> using proxy with <b>proxy_argv</b> to + * the managed proxy subsystem. + * If <b>is_server</b> is true, then the proxy is a server proxy. */ +void +pt_kickstart_proxy(const smartlist_t *transport_list, + char **proxy_argv, int is_server) +{ + managed_proxy_t *mp=NULL; + transport_t *old_transport = NULL; + + mp = get_managed_proxy_by_argv_and_type(proxy_argv, is_server); + + if (!mp) { /* we haven't seen this proxy before */ + managed_proxy_create(transport_list, proxy_argv, is_server); + + } else { /* known proxy. add its transport to its transport list */ + if (mp->got_hup) { + /* If the managed proxy we found is marked by a SIGHUP, it means + that it's not useless and should be kept. If it's marked for + removal, unmark it and increase the unconfigured proxies so + that we try to restart it if we need to. Afterwards, check if + a transport_t for 'transport' used to exist before the SIGHUP + and make sure it doesn't get deleted because we might reuse + it. */ + if (mp->marked_for_removal) { + mp->marked_for_removal = 0; + unconfigured_proxies_n++; + } + + SMARTLIST_FOREACH_BEGIN(transport_list, const char *, transport) { + old_transport = transport_get_by_name(transport); + if (old_transport) + old_transport->marked_for_removal = 0; + } SMARTLIST_FOREACH_END(transport); + } + + SMARTLIST_FOREACH(transport_list, const char *, transport, + add_transport_to_proxy(transport, mp)); + free_execve_args(proxy_argv); + } +} + +/** Frees the array of pointers in <b>arg</b> used as arguments to + execve(2). */ +static INLINE void +free_execve_args(char **arg) +{ + char **tmp = arg; + while (*tmp) /* use the fact that the last element of the array is a + NULL pointer to know when to stop freeing */ + _tor_free(*tmp++); + + tor_free(arg); +} + +/** Tor will read its config. + * Prepare the managed proxy list so that proxies not used in the new + * config will shutdown, and proxies that need to spawn different + * transports will do so. */ +void +pt_prepare_proxy_list_for_config_read(void) +{ + if (!managed_proxy_list) + return; + + SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) { + /* Destroy unconfigured proxies. */ + if (mp->conf_state != PT_PROTO_COMPLETED) { + managed_proxy_destroy(mp, 1); + unconfigured_proxies_n--; + continue; + } + + tor_assert(mp->conf_state == PT_PROTO_COMPLETED); + + mp->marked_for_removal = 1; + mp->got_hup = 1; + SMARTLIST_FOREACH(mp->transports_to_launch, char *, t, tor_free(t)); + smartlist_clear(mp->transports_to_launch); + } SMARTLIST_FOREACH_END(mp); + + tor_assert(unconfigured_proxies_n == 0); +} + +/** The tor config was read. + * Destroy all managed proxies that were marked by a previous call to + * prepare_proxy_list_for_config_read() and are not used by the new + * config. */ +void +sweep_proxy_list(void) +{ + if (!managed_proxy_list) + return; + + SMARTLIST_FOREACH_BEGIN(managed_proxy_list, managed_proxy_t *, mp) { + if (mp->marked_for_removal) { + SMARTLIST_DEL_CURRENT(managed_proxy_list, mp); + managed_proxy_destroy(mp, 1); + } + } SMARTLIST_FOREACH_END(mp); +} + +/** Release all storage held by the pluggable transports subsystem. */ +void +pt_free_all(void) +{ + if (managed_proxy_list) { + /* If the proxy is in PT_PROTO_COMPLETED, it has registered its + transports and it's the duty of the circuitbuild.c subsystem to + free them. Otherwise, it hasn't registered its transports yet + and we should free them here. */ + SMARTLIST_FOREACH(managed_proxy_list, managed_proxy_t *, mp, + managed_proxy_destroy(mp, 1)); + + smartlist_free(managed_proxy_list); + managed_proxy_list=NULL; + } +} + diff --git a/src/or/transports.h b/src/or/transports.h new file mode 100644 index 0000000000..314af2b3a0 --- /dev/null +++ b/src/or/transports.h @@ -0,0 +1,106 @@ +/* Copyright (c) 2003-2004, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2011, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file transports.h + * \brief Headers for transports.c + **/ + +#ifndef TOR_TRANSPORTS_H +#define TOR_TRANSPORTS_H + +void pt_kickstart_proxy(const smartlist_t *transport_list, char **proxy_argv, + int is_server); + +#define pt_kickstart_client_proxy(tl, pa) \ + pt_kickstart_proxy(tl, pa, 0) +#define pt_kickstart_server_proxy(tl, pa) \ + pt_kickstart_proxy(tl, pa, 1) + +void pt_configure_remaining_proxies(void); + +int pt_proxies_configuration_pending(void); + +void pt_free_all(void); + +void pt_prepare_proxy_list_for_config_read(void); +void sweep_proxy_list(void); + +#ifdef PT_PRIVATE +/** State of the managed proxy configuration protocol. */ +enum pt_proto_state { + PT_PROTO_INFANT, /* was just born */ + PT_PROTO_LAUNCHED, /* was just launched */ + PT_PROTO_ACCEPTING_METHODS, /* accepting methods */ + PT_PROTO_CONFIGURED, /* configured successfully */ + PT_PROTO_COMPLETED, /* configure and registered its transports */ + PT_PROTO_BROKEN, /* broke during the protocol */ + PT_PROTO_FAILED_LAUNCH /* failed while launching */ +}; + +/** Structure containing information of a managed proxy. */ +typedef struct { + enum pt_proto_state conf_state; /* the current configuration state */ + char **argv; /* the cli arguments of this proxy */ + int conf_protocol; /* the configuration protocol version used */ + + int is_server; /* is it a server proxy? */ + + /* A pointer to the process handle of this managed proxy. */ + process_handle_t *process_handle; + + int pid; /* The Process ID this managed proxy is using. */ + + /** Boolean: We are re-parsing our config, and we are going to + * remove this managed proxy if we don't find it any transport + * plugins that use it. */ + unsigned int marked_for_removal : 1; + + /** Boolean: We got a SIGHUP while this proxy was running. We use + * this flag to signify that this proxy might need to be restarted + * so that it can listen for other transports according to the new + * torrc. */ + unsigned int got_hup : 1; + + /* transports to-be-launched by this proxy */ + smartlist_t *transports_to_launch; + + /* The 'transports' list contains all the transports this proxy has + launched. + + Before a managed_proxy_t reaches the PT_PROTO_COMPLETED phase, + this smartlist contains a 'transport_t' for every transport it + has launched. + + When the managed_proxy_t reaches the PT_PROTO_COMPLETED phase, it + registers all its transports to the circuitbuild.c subsystem. At + that point the 'transport_t's are owned by the circuitbuild.c + subsystem. + + To avoid carrying dangling 'transport_t's in this smartlist, + right before the managed_proxy_t reaches the PT_PROTO_COMPLETED + phase we replace all 'transport_t's with strings of their + transport names. + + So, tl;dr: + When (conf_state != PT_PROTO_COMPLETED) this list carries + (transport_t *). + When (conf_state == PT_PROTO_COMPLETED) this list carries + (char *). + */ + smartlist_t *transports; +} managed_proxy_t; + +int parse_cmethod_line(const char *line, managed_proxy_t *mp); +int parse_smethod_line(const char *line, managed_proxy_t *mp); + +int parse_version(const char *line, managed_proxy_t *mp); +void parse_env_error(const char *line); +void handle_proxy_line(const char *line, managed_proxy_t *mp); + +#endif + +#endif + diff --git a/src/test/Makefile.am b/src/test/Makefile.am index 904719d94b..ffe1f942e7 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 bench AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ -DLOCALSTATEDIR="\"$(localstatedir)\"" \ @@ -12,19 +12,37 @@ AM_CPPFLAGS = -DSHARE_DATADIR="\"$(datadir)\"" \ # matters a lot there, and is quite hard to debug if you forget to do it. test_SOURCES = \ - test_data.c \ test.c \ test_addr.c \ + test_containers.c \ test_crypto.c \ + test_data.c \ test_dir.c \ - test_containers.c \ + test_microdesc.c \ + test_pt.c \ test_util.c \ tinytest.c +bench_SOURCES = \ + bench.c + test_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ @TOR_LDFLAGS_libevent@ test_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \ ../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@ + +bench_LDFLAGS = @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ \ + @TOR_LDFLAGS_libevent@ +bench_LDADD = ../or/libtor.a ../common/libor.a ../common/libor-crypto.a \ + ../common/libor-event.a \ + @TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ \ + @TOR_LIB_WS32@ @TOR_LIB_GDI@ + +noinst_HEADERS = \ + tinytest.h \ + tinytest_macros.h \ + test.h + -noinst_HEADERS = tinytest.h tinytest_macros.h test.h diff --git a/src/test/bench.c b/src/test/bench.c new file mode 100644 index 0000000000..ff2794e7c7 --- /dev/null +++ b/src/test/bench.c @@ -0,0 +1,327 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2011, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/* Ordinarily defined in tor_main.c; this bit is just here to provide one + * since we're not linking to tor_main.c */ +const char tor_git_revision[] = ""; + +/** + * \file bench.c + * \brief Benchmarks for lower level Tor modules. + **/ + +#include "orconfig.h" + +#define RELAY_PRIVATE + +#include "or.h" +#include "relay.h" + +#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID) +static uint64_t nanostart; +static inline uint64_t +timespec_to_nsec(const struct timespec *ts) +{ + return ((uint64_t)ts->tv_sec)*1000000000 + ts->tv_nsec; +} + +static void +reset_perftime(void) +{ + struct timespec ts; + int r; + r = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); + tor_assert(r == 0); + nanostart = timespec_to_nsec(&ts); +} + +static uint64_t +perftime(void) +{ + struct timespec ts; + int r; + r = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); + tor_assert(r == 0); + return timespec_to_nsec(&ts) - nanostart; +} + +#else +static struct timeval tv_start = { 0, 0 }; +static void +reset_perftime(void) +{ + tor_gettimeofday(&tv_start); +} +static uint64_t +perftime(void) +{ + struct timeval now, out; + tor_gettimeofday(&now); + timersub(&now, &tv_start, &out); + return ((uint64_t)out.tv_sec)*1000000000 + out.tv_usec*1000; +} +#endif + +#define NANOCOUNT(start,end,iters) \ + ( ((double)((end)-(start))) / (iters) ) + +/** Run AES performance benchmarks. */ +static void +bench_aes(void) +{ + int len, i; + char *b1, *b2; + crypto_cipher_env_t *c; + uint64_t start, end; + const int bytes_per_iter = (1<<24); + reset_perftime(); + c = crypto_new_cipher_env(); + crypto_cipher_generate_key(c); + crypto_cipher_encrypt_init_cipher(c); + for (len = 1; len <= 8192; len *= 2) { + int iters = bytes_per_iter / len; + b1 = tor_malloc_zero(len); + b2 = tor_malloc_zero(len); + start = perftime(); + for (i = 0; i < iters; ++i) { + crypto_cipher_encrypt(c, b1, b2, len); + } + end = perftime(); + tor_free(b1); + tor_free(b2); + printf("%d bytes: %.2f nsec per byte\n", len, + NANOCOUNT(start, end, iters*len)); + } + crypto_free_cipher_env(c); +} + +static void +bench_cell_aes(void) +{ + uint64_t start, end; + const int len = 509; + const int iters = (1<<16); + const int max_misalign = 15; + char *b = tor_malloc(len+max_misalign); + crypto_cipher_env_t *c; + int i, misalign; + + c = crypto_new_cipher_env(); + crypto_cipher_generate_key(c); + crypto_cipher_encrypt_init_cipher(c); + + reset_perftime(); + for (misalign = 0; misalign <= max_misalign; ++misalign) { + start = perftime(); + for (i = 0; i < iters; ++i) { + crypto_cipher_crypt_inplace(c, b+misalign, len); + } + end = perftime(); + printf("%d bytes, misaligned by %d: %.2f nsec per byte\n", len, misalign, + NANOCOUNT(start, end, iters*len)); + } + + crypto_free_cipher_env(c); + tor_free(b); +} + +/** Run digestmap_t performance benchmarks. */ +static void +bench_dmap(void) +{ + smartlist_t *sl = smartlist_create(); + smartlist_t *sl2 = smartlist_create(); + uint64_t start, end, pt2, pt3, pt4; + int iters = 8192; + const int elts = 4000; + const int fpostests = 100000; + char d[20]; + int i,n=0, fp = 0; + digestmap_t *dm = digestmap_new(); + digestset_t *ds = digestset_new(elts); + + for (i = 0; i < elts; ++i) { + crypto_rand(d, 20); + smartlist_add(sl, tor_memdup(d, 20)); + } + for (i = 0; i < elts; ++i) { + crypto_rand(d, 20); + smartlist_add(sl2, tor_memdup(d, 20)); + } + printf("nbits=%d\n", ds->mask+1); + + reset_perftime(); + + start = perftime(); + for (i = 0; i < iters; ++i) { + SMARTLIST_FOREACH(sl, const char *, cp, digestmap_set(dm, cp, (void*)1)); + } + pt2 = perftime(); + printf("digestmap_set: %.2f ns per element\n", + NANOCOUNT(start, pt2, iters*elts)); + + for (i = 0; i < iters; ++i) { + SMARTLIST_FOREACH(sl, const char *, cp, digestmap_get(dm, cp)); + SMARTLIST_FOREACH(sl2, const char *, cp, digestmap_get(dm, cp)); + } + pt3 = perftime(); + printf("digestmap_get: %.2f ns per element\n", + NANOCOUNT(pt2, pt3, iters*elts*2)); + + for (i = 0; i < iters; ++i) { + SMARTLIST_FOREACH(sl, const char *, cp, digestset_add(ds, cp)); + } + pt4 = perftime(); + printf("digestset_add: %.2f ns per element\n", + NANOCOUNT(pt3, pt4, iters*elts)); + + for (i = 0; i < iters; ++i) { + SMARTLIST_FOREACH(sl, const char *, cp, n += digestset_isin(ds, cp)); + SMARTLIST_FOREACH(sl2, const char *, cp, n += digestset_isin(ds, cp)); + } + end = perftime(); + printf("digestset_isin: %.2f ns per element.\n", + NANOCOUNT(pt4, end, iters*elts*2)); + /* We need to use this, or else the whole loop gets optimized out. */ + printf("Hits == %d\n", n); + + for (i = 0; i < fpostests; ++i) { + crypto_rand(d, 20); + if (digestset_isin(ds, d)) ++fp; + } + printf("False positive rate on digestset: %.2f%%\n", + (fp/(double)fpostests)*100); + + digestmap_free(dm, NULL); + digestset_free(ds); + SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); + SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp)); + smartlist_free(sl); + smartlist_free(sl2); +} + +static void +bench_cell_ops(void) +{ + const int iters = 1<<16; + int i; + + /* benchmarks for cell ops at relay. */ + or_circuit_t *or_circ = tor_malloc_zero(sizeof(or_circuit_t)); + cell_t *cell = tor_malloc(sizeof(cell_t)); + int outbound; + uint64_t start, end; + + crypto_rand((char*)cell->payload, sizeof(cell->payload)); + + /* Mock-up or_circuit_t */ + or_circ->_base.magic = OR_CIRCUIT_MAGIC; + or_circ->_base.purpose = CIRCUIT_PURPOSE_OR; + + /* Initialize crypto */ + or_circ->p_crypto = crypto_new_cipher_env(); + crypto_cipher_generate_key(or_circ->p_crypto); + crypto_cipher_encrypt_init_cipher(or_circ->p_crypto); + or_circ->n_crypto = crypto_new_cipher_env(); + crypto_cipher_generate_key(or_circ->n_crypto); + crypto_cipher_encrypt_init_cipher(or_circ->n_crypto); + or_circ->p_digest = crypto_new_digest_env(); + or_circ->n_digest = crypto_new_digest_env(); + + reset_perftime(); + + for (outbound = 0; outbound <= 1; ++outbound) { + cell_direction_t d = outbound ? CELL_DIRECTION_OUT : CELL_DIRECTION_IN; + start = perftime(); + for (i = 0; i < iters; ++i) { + char recognized = 0; + crypt_path_t *layer_hint = NULL; + relay_crypt(TO_CIRCUIT(or_circ), cell, d, &layer_hint, &recognized); + } + end = perftime(); + printf("%sbound cells: %.2f ns per cell. (%.2f ns per byte of payload)\n", + outbound?"Out":" In", + NANOCOUNT(start,end,iters), + NANOCOUNT(start,end,iters*CELL_PAYLOAD_SIZE)); + } + + crypto_free_digest_env(or_circ->p_digest); + crypto_free_digest_env(or_circ->n_digest); + crypto_free_cipher_env(or_circ->p_crypto); + crypto_free_cipher_env(or_circ->n_crypto); + tor_free(or_circ); + tor_free(cell); +} + +typedef void (*bench_fn)(void); + +typedef struct benchmark_t { + const char *name; + bench_fn fn; + int enabled; +} benchmark_t; + +#define ENT(s) { #s , bench_##s, 0 } + +static struct benchmark_t benchmarks[] = { + ENT(dmap), + ENT(aes), + ENT(cell_aes), + ENT(cell_ops), + {NULL,NULL,0} +}; + +static benchmark_t * +find_benchmark(const char *name) +{ + benchmark_t *b; + for (b = benchmarks; b->name; ++b) { + if (!strcmp(name, b->name)) { + return b; + } + } + return NULL; +} + +/** Main entry point for benchmark code: parse the command line, and run + * some benchmarks. */ +int +main(int argc, const char **argv) +{ + int i; + int list=0, n_enabled=0; + benchmark_t *b; + + tor_threads_init(); + + for (i = 1; i < argc; ++i) { + if (!strcmp(argv[i], "--list")) { + list = 1; + } else { + benchmark_t *b = find_benchmark(argv[i]); + ++n_enabled; + if (b) { + b->enabled = 1; + } else { + printf("No such benchmark as %s\n", argv[i]); + } + } + } + + reset_perftime(); + + crypto_seed_rng(1); + + for (b = benchmarks; b->name; ++b) { + if (b->enabled || n_enabled == 0) { + printf("===== %s =====\n", b->name); + if (!list) + b->fn(); + } + } + + return 0; +} + diff --git a/src/test/test-child.c b/src/test/test-child.c new file mode 100644 index 0000000000..1b9c5e3d57 --- /dev/null +++ b/src/test/test-child.c @@ -0,0 +1,40 @@ +#include <stdio.h> +#include "orconfig.h" +#ifdef MS_WINDOWS +#define WINDOWS_LEAN_AND_MEAN +#include <windows.h> +#else +#include <unistd.h> +#endif + +/** Trivial test program which prints out its command line arguments so we can + * check if tor_spawn_background() works */ +int +main(int argc, char **argv) +{ + int i; + + fprintf(stdout, "OUT\n"); + fprintf(stderr, "ERR\n"); + for (i = 1; i < argc; i++) + fprintf(stdout, "%s\n", argv[i]); + fprintf(stdout, "SLEEPING\n"); + /* We need to flush stdout so that test_util_spawn_background_partial_read() + succeed. Otherwise ReadFile() will get the entire output in one */ + // XXX: Can we make stdio flush on newline? + fflush(stdout); +#ifdef MS_WINDOWS + Sleep(1000); +#else + sleep(1); +#endif + fprintf(stdout, "DONE\n"); +#ifdef MS_WINDOWS + Sleep(1000); +#else + sleep(1); +#endif + + return 0; +} + diff --git a/src/test/test.c b/src/test/test.c index b5b744eba7..092b2c3780 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -119,30 +119,46 @@ get_fname(const char *name) return buf; } -/** Remove all files stored under the temporary directory, and the directory - * itself. Called by atexit(). */ +/* Remove a directory and all of its subdirectories */ static void -remove_directory(void) +rm_rf(const char *dir) { + struct stat st; smartlist_t *elements; - if (getpid() != temp_dir_setup_in_pid) { - /* Only clean out the tempdir when the main process is exiting. */ - return; - } - elements = tor_listdir(temp_dir); + + elements = tor_listdir(dir); if (elements) { SMARTLIST_FOREACH(elements, const char *, cp, { - size_t len = strlen(cp)+strlen(temp_dir)+16; - char *tmp = tor_malloc(len); - tor_snprintf(tmp, len, "%s"PATH_SEPARATOR"%s", temp_dir, cp); - unlink(tmp); + char *tmp = NULL; + tor_asprintf(&tmp, "%s"PATH_SEPARATOR"%s", dir, cp); + if (0 == stat(tmp,&st) && (st.st_mode & S_IFDIR)) { + rm_rf(tmp); + } else { + if (unlink(tmp)) { + fprintf(stderr, "Error removing %s: %s\n", tmp, strerror(errno)); + } + } tor_free(tmp); }); SMARTLIST_FOREACH(elements, char *, cp, tor_free(cp)); smartlist_free(elements); } - rmdir(temp_dir); + if (rmdir(dir)) + fprintf(stderr, "Error removing directory %s: %s\n", dir, strerror(errno)); +} + +/** Remove all files stored under the temporary directory, and the directory + * itself. Called by atexit(). */ +static void +remove_directory(void) +{ + if (getpid() != temp_dir_setup_in_pid) { + /* Only clean out the tempdir when the main process is exiting. */ + return; + } + + rm_rf(temp_dir); } /** Define this if unit tests spend too much time generating public keys*/ @@ -187,6 +203,437 @@ free_pregenerated_keys(void) } } +typedef struct socks_test_data_t { + socks_request_t *req; + buf_t *buf; +} socks_test_data_t; + +static void * +socks_test_setup(const struct testcase_t *testcase) +{ + socks_test_data_t *data = tor_malloc(sizeof(socks_test_data_t)); + (void)testcase; + data->buf = buf_new_with_capacity(256); + data->req = socks_request_new(); + config_register_addressmaps(get_options()); + return data; +} +static int +socks_test_cleanup(const struct testcase_t *testcase, void *ptr) +{ + socks_test_data_t *data = ptr; + (void)testcase; + buf_free(data->buf); + socks_request_free(data->req); + tor_free(data); + return 1; +} + +const struct testcase_setup_t socks_setup = { + socks_test_setup, socks_test_cleanup +}; + +#define SOCKS_TEST_INIT() \ + socks_test_data_t *testdata = ptr; \ + buf_t *buf = testdata->buf; \ + socks_request_t *socks = testdata->req; +#define ADD_DATA(buf, s) \ + write_to_buf(s, sizeof(s)-1, buf) + +static void +socks_request_clear(socks_request_t *socks) +{ + tor_free(socks->username); + tor_free(socks->password); + memset(socks, 0, sizeof(socks_request_t)); +} + +/** Perform unsupported SOCKS 4 commands */ +static void +test_socks_4_unsupported_commands(void *ptr) +{ + SOCKS_TEST_INIT(); + + /* SOCKS 4 Send BIND [02] to IP address 2.2.2.2:4369 */ + ADD_DATA(buf, "\x04\x02\x11\x11\x02\x02\x02\x02\x00"); + test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks) == -1); + test_eq(4, socks->socks_version); + test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */ + + done: + ; +} + +/** Perform supported SOCKS 4 commands */ +static void +test_socks_4_supported_commands(void *ptr) +{ + SOCKS_TEST_INIT(); + + test_eq(0, buf_datalen(buf)); + + /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4370 */ + ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x03\x00"); + test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks) == 1); + test_eq(4, socks->socks_version); + test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */ + test_eq(SOCKS_COMMAND_CONNECT, socks->command); + test_streq("2.2.2.3", socks->address); + test_eq(4370, socks->port); + test_assert(socks->got_auth == 0); + test_assert(! socks->username); + + test_eq(0, buf_datalen(buf)); + socks_request_clear(socks); + + /* SOCKS 4 Send CONNECT [01] to IP address 2.2.2.2:4369 with userid*/ + ADD_DATA(buf, "\x04\x01\x11\x12\x02\x02\x02\x04me\x00"); + test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks) == 1); + test_eq(4, socks->socks_version); + test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */ + test_eq(SOCKS_COMMAND_CONNECT, socks->command); + test_streq("2.2.2.4", socks->address); + test_eq(4370, socks->port); + test_assert(socks->got_auth == 1); + test_assert(socks->username); + test_eq(2, socks->usernamelen); + test_memeq("me", socks->username, 2); + + test_eq(0, buf_datalen(buf)); + socks_request_clear(socks); + + /* SOCKS 4a Send RESOLVE [F0] request for torproject.org */ + ADD_DATA(buf, "\x04\xF0\x01\x01\x00\x00\x00\x02me\x00torproject.org\x00"); + test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks) == 1); + test_eq(4, socks->socks_version); + test_eq(0, socks->replylen); /* XXX: shouldn't tor reply? */ + test_streq("torproject.org", socks->address); + + test_eq(0, buf_datalen(buf)); + + done: + ; +} + +/** Perform unsupported SOCKS 5 commands */ +static void +test_socks_5_unsupported_commands(void *ptr) +{ + SOCKS_TEST_INIT(); + + /* SOCKS 5 Send unsupported BIND [02] command */ + ADD_DATA(buf, "\x05\x02\x00\x01"); + + test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), 0); + test_eq(0, buf_datalen(buf)); + test_eq(5, socks->socks_version); + test_eq(2, socks->replylen); + test_eq(5, socks->reply[0]); + test_eq(0, socks->reply[1]); + ADD_DATA(buf, "\x05\x02\x00\x01\x02\x02\x02\x01\x01\x01"); + test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), -1); + /* XXX: shouldn't tor reply 'command not supported' [07]? */ + + buf_clear(buf); + socks_request_clear(socks); + + /* SOCKS 5 Send unsupported UDP_ASSOCIATE [03] command */ + ADD_DATA(buf, "\x05\x03\x00\x01\x02"); + test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), 0); + test_eq(5, socks->socks_version); + test_eq(2, socks->replylen); + test_eq(5, socks->reply[0]); + test_eq(0, socks->reply[1]); + ADD_DATA(buf, "\x05\x03\x00\x01\x02\x02\x02\x01\x01\x01"); + test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), -1); + /* XXX: shouldn't tor reply 'command not supported' [07]? */ + + done: + ; +} + +/** Perform supported SOCKS 5 commands */ +static void +test_socks_5_supported_commands(void *ptr) +{ + SOCKS_TEST_INIT(); + + /* SOCKS 5 Send CONNECT [01] to IP address 2.2.2.2:4369 */ + ADD_DATA(buf, "\x05\x01\x00"); + test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), 0); + test_eq(5, socks->socks_version); + test_eq(2, socks->replylen); + test_eq(5, socks->reply[0]); + test_eq(0, socks->reply[1]); + + ADD_DATA(buf, "\x05\x01\x00\x01\x02\x02\x02\x02\x11\x11"); + test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), 1); + test_streq("2.2.2.2", socks->address); + test_eq(4369, socks->port); + + test_eq(0, buf_datalen(buf)); + socks_request_clear(socks); + + /* SOCKS 5 Send CONNECT [01] to FQDN torproject.org:4369 */ + ADD_DATA(buf, "\x05\x01\x00"); + ADD_DATA(buf, "\x05\x01\x00\x03\x0Etorproject.org\x11\x11"); + test_eq(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks), 1); + + test_eq(5, socks->socks_version); + test_eq(2, socks->replylen); + test_eq(5, socks->reply[0]); + test_eq(0, socks->reply[1]); + test_streq("torproject.org", socks->address); + test_eq(4369, socks->port); + + test_eq(0, buf_datalen(buf)); + socks_request_clear(socks); + + /* SOCKS 5 Send RESOLVE [F0] request for torproject.org:4369 */ + ADD_DATA(buf, "\x05\x01\x00"); + ADD_DATA(buf, "\x05\xF0\x00\x03\x0Etorproject.org\x01\x02"); + test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks) == 1); + test_eq(5, socks->socks_version); + test_eq(2, socks->replylen); + test_eq(5, socks->reply[0]); + test_eq(0, socks->reply[1]); + test_streq("torproject.org", socks->address); + + test_eq(0, buf_datalen(buf)); + socks_request_clear(socks); + + /* SOCKS 5 Send RESOLVE_PTR [F1] for IP address 2.2.2.5 */ + ADD_DATA(buf, "\x05\x01\x00"); + ADD_DATA(buf, "\x05\xF1\x00\x01\x02\x02\x02\x05\x01\x03"); + test_assert(fetch_from_buf_socks(buf, socks, get_options()->TestSocks, + get_options()->SafeSocks) == 1); + test_eq(5, socks->socks_version); + test_eq(2, socks->replylen); + test_eq(5, socks->reply[0]); + test_eq(0, socks->reply[1]); + test_streq("2.2.2.5", socks->address); + + test_eq(0, buf_datalen(buf)); + + done: + ; +} + +/** Perform SOCKS 5 authentication */ +static void +test_socks_5_no_authenticate(void *ptr) +{ + SOCKS_TEST_INIT(); + + /*SOCKS 5 No Authentication */ + ADD_DATA(buf,"\x05\x01\x00"); + test_assert(!fetch_from_buf_socks(buf, socks, + get_options()->TestSocks, + get_options()->SafeSocks)); + test_eq(2, socks->replylen); + test_eq(5, socks->reply[0]); + test_eq(SOCKS_NO_AUTH, socks->reply[1]); + + test_eq(0, buf_datalen(buf)); + + /*SOCKS 5 Send username/password anyway - pretend to be broken */ + ADD_DATA(buf,"\x01\x02\x01\x01\x02\x01\x01"); + test_assert(!fetch_from_buf_socks(buf, socks, + get_options()->TestSocks, + get_options()->SafeSocks)); + test_eq(5, socks->socks_version); + test_eq(2, socks->replylen); + test_eq(5, socks->reply[0]); + test_eq(0, socks->reply[1]); + + test_eq(2, socks->usernamelen); + test_eq(2, socks->passwordlen); + + test_memeq("\x01\x01", socks->username, 2); + test_memeq("\x01\x01", socks->password, 2); + + done: + ; +} + +/** Perform SOCKS 5 authentication */ +static void +test_socks_5_authenticate(void *ptr) +{ + SOCKS_TEST_INIT(); + + /* SOCKS 5 Negotiate username/password authentication */ + ADD_DATA(buf, "\x05\x01\x02"); + + test_assert(!fetch_from_buf_socks(buf, socks, + get_options()->TestSocks, + get_options()->SafeSocks)); + test_eq(2, socks->replylen); + test_eq(5, socks->reply[0]); + test_eq(SOCKS_USER_PASS, socks->reply[1]); + test_eq(5, socks->socks_version); + + test_eq(0, buf_datalen(buf)); + + /* SOCKS 5 Send username/password */ + ADD_DATA(buf, "\x01\x02me\x08mypasswd"); + test_assert(!fetch_from_buf_socks(buf, socks, + get_options()->TestSocks, + get_options()->SafeSocks)); + test_eq(5, socks->socks_version); + test_eq(2, socks->replylen); + test_eq(5, socks->reply[0]); + test_eq(0, socks->reply[1]); + + test_eq(2, socks->usernamelen); + test_eq(8, socks->passwordlen); + + test_memeq("me", socks->username, 2); + test_memeq("mypasswd", socks->password, 8); + + done: + ; +} + +/** Perform SOCKS 5 authentication and send data all in one go */ +static void +test_socks_5_authenticate_with_data(void *ptr) +{ + SOCKS_TEST_INIT(); + + /* SOCKS 5 Negotiate username/password authentication */ + ADD_DATA(buf, "\x05\x01\x02"); + + test_assert(!fetch_from_buf_socks(buf, socks, + get_options()->TestSocks, + get_options()->SafeSocks)); + test_eq(2, socks->replylen); + test_eq(5, socks->reply[0]); + test_eq(SOCKS_USER_PASS, socks->reply[1]); + test_eq(5, socks->socks_version); + + test_eq(0, buf_datalen(buf)); + + /* SOCKS 5 Send username/password */ + /* SOCKS 5 Send CONNECT [01] to IP address 2.2.2.2:4369 */ + ADD_DATA(buf, "\x01\x02me\x03you\x05\x01\x00\x01\x02\x02\x02\x02\x11\x11"); + test_assert(fetch_from_buf_socks(buf, socks, + get_options()->TestSocks, + get_options()->SafeSocks) == 1); + test_eq(5, socks->socks_version); + test_eq(2, socks->replylen); + test_eq(5, socks->reply[0]); + test_eq(0, socks->reply[1]); + + test_streq("2.2.2.2", socks->address); + test_eq(4369, socks->port); + + test_eq(2, socks->usernamelen); + test_eq(3, socks->passwordlen); + test_memeq("me", socks->username, 2); + test_memeq("you", socks->password, 3); + + done: + ; +} + +/** Perform SOCKS 5 authentication before method negotiated */ +static void +test_socks_5_auth_before_negotiation(void *ptr) +{ + SOCKS_TEST_INIT(); + + /* SOCKS 5 Send username/password */ + ADD_DATA(buf, "\x01\x02me\x02me"); + test_assert(fetch_from_buf_socks(buf, socks, + get_options()->TestSocks, + get_options()->SafeSocks) == -1); + test_eq(0, socks->socks_version); + test_eq(0, socks->replylen); + test_eq(0, socks->reply[0]); + test_eq(0, socks->reply[1]); + + done: + ; +} + +static void +test_buffer_copy(void *arg) +{ + generic_buffer_t *buf=NULL, *buf2=NULL; + const char *s; + size_t len; + char b[256]; + int i; + (void)arg; + + buf = generic_buffer_new(); + tt_assert(buf); + + /* Copy an empty buffer. */ + tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf)); + tt_assert(buf2); + tt_int_op(0, ==, generic_buffer_len(buf2)); + + /* Now try with a short buffer. */ + s = "And now comes an act of enormous enormance!"; + len = strlen(s); + generic_buffer_add(buf, s, len); + tt_int_op(len, ==, generic_buffer_len(buf)); + /* Add junk to buf2 so we can test replacing.*/ + generic_buffer_add(buf2, "BLARG", 5); + tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf)); + tt_int_op(len, ==, generic_buffer_len(buf2)); + generic_buffer_get(buf2, b, len); + test_mem_op(b, ==, s, len); + /* Now free buf2 and retry so we can test allocating */ + generic_buffer_free(buf2); + buf2 = NULL; + tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf)); + tt_int_op(len, ==, generic_buffer_len(buf2)); + generic_buffer_get(buf2, b, len); + test_mem_op(b, ==, s, len); + /* Clear buf for next test */ + generic_buffer_get(buf, b, len); + tt_int_op(generic_buffer_len(buf),==,0); + + /* Okay, now let's try a bigger buffer. */ + s = "Quis autem vel eum iure reprehenderit qui in ea voluptate velit " + "esse quam nihil molestiae consequatur, vel illum qui dolorem eum " + "fugiat quo voluptas nulla pariatur?"; + len = strlen(s); + for (i = 0; i < 256; ++i) { + b[0]=i; + generic_buffer_add(buf, b, 1); + generic_buffer_add(buf, s, len); + } + tt_int_op(0, ==, generic_buffer_set_to_copy(&buf2, buf)); + tt_int_op(generic_buffer_len(buf2), ==, generic_buffer_len(buf)); + for (i = 0; i < 256; ++i) { + generic_buffer_get(buf2, b, len+1); + tt_int_op((unsigned char)b[0],==,i); + test_mem_op(b+1, ==, s, len); + } + + done: + if (buf) + generic_buffer_free(buf); + if (buf2) + generic_buffer_free(buf2); +} + /** Run unit tests for buffers.c */ static void test_buffers(void) @@ -566,6 +1013,7 @@ test_policy_summary_helper(const char *policy_str, smartlist_t *policy = smartlist_create(); char *summary = NULL; int r; + short_policy_t *short_policy = NULL; line.key = (char*)"foo"; line.value = (char *)policy_str; @@ -578,10 +1026,14 @@ test_policy_summary_helper(const char *policy_str, test_assert(summary != NULL); test_streq(summary, expected_summary); + short_policy = parse_short_policy(summary); + tt_assert(short_policy); + done: tor_free(summary); if (policy) addr_policy_list_free(policy); + short_policy_free(short_policy); } /** Run unit tests for generating summary lines of exit policies */ @@ -611,12 +1063,15 @@ test_policies(void) smartlist_add(policy, p); + tor_addr_from_ipv4h(&tar, 0x01020304u); test_assert(ADDR_POLICY_ACCEPTED == - compare_addr_to_addr_policy(0x01020304u, 2, policy)); + compare_tor_addr_to_addr_policy(&tar, 2, policy)); + tor_addr_make_unspec(&tar); test_assert(ADDR_POLICY_PROBABLY_ACCEPTED == - compare_addr_to_addr_policy(0, 2, policy)); + compare_tor_addr_to_addr_policy(&tar, 2, policy)); + tor_addr_from_ipv4h(&tar, 0xc0a80102); test_assert(ADDR_POLICY_REJECTED == - compare_addr_to_addr_policy(0xc0a80102, 2, policy)); + compare_tor_addr_to_addr_policy(&tar, 2, policy)); test_assert(0 == policies_parse_exit_policy(NULL, &policy2, 1, NULL, 1)); test_assert(policy2); @@ -810,102 +1265,6 @@ test_policies(void) } } -/** Run AES performance benchmarks. */ -static void -bench_aes(void) -{ - int len, i; - char *b1, *b2; - crypto_cipher_env_t *c; - struct timeval start, end; - const int iters = 100000; - uint64_t nsec; - c = crypto_new_cipher_env(); - crypto_cipher_generate_key(c); - crypto_cipher_encrypt_init_cipher(c); - for (len = 1; len <= 8192; len *= 2) { - b1 = tor_malloc_zero(len); - b2 = tor_malloc_zero(len); - tor_gettimeofday(&start); - for (i = 0; i < iters; ++i) { - crypto_cipher_encrypt(c, b1, b2, len); - } - tor_gettimeofday(&end); - tor_free(b1); - tor_free(b2); - nsec = (uint64_t) tv_udiff(&start,&end); - nsec *= 1000; - nsec /= (iters*len); - printf("%d bytes: "U64_FORMAT" nsec per byte\n", len, - U64_PRINTF_ARG(nsec)); - } - crypto_free_cipher_env(c); -} - -/** Run digestmap_t performance benchmarks. */ -static void -bench_dmap(void) -{ - smartlist_t *sl = smartlist_create(); - smartlist_t *sl2 = smartlist_create(); - struct timeval start, end, pt2, pt3, pt4; - const int iters = 10000; - const int elts = 4000; - const int fpostests = 1000000; - char d[20]; - int i,n=0, fp = 0; - digestmap_t *dm = digestmap_new(); - digestset_t *ds = digestset_new(elts); - - for (i = 0; i < elts; ++i) { - crypto_rand(d, 20); - smartlist_add(sl, tor_memdup(d, 20)); - } - for (i = 0; i < elts; ++i) { - crypto_rand(d, 20); - smartlist_add(sl2, tor_memdup(d, 20)); - } - printf("nbits=%d\n", ds->mask+1); - - tor_gettimeofday(&start); - for (i = 0; i < iters; ++i) { - SMARTLIST_FOREACH(sl, const char *, cp, digestmap_set(dm, cp, (void*)1)); - } - tor_gettimeofday(&pt2); - for (i = 0; i < iters; ++i) { - SMARTLIST_FOREACH(sl, const char *, cp, digestmap_get(dm, cp)); - SMARTLIST_FOREACH(sl2, const char *, cp, digestmap_get(dm, cp)); - } - tor_gettimeofday(&pt3); - for (i = 0; i < iters; ++i) { - SMARTLIST_FOREACH(sl, const char *, cp, digestset_add(ds, cp)); - } - tor_gettimeofday(&pt4); - for (i = 0; i < iters; ++i) { - SMARTLIST_FOREACH(sl, const char *, cp, n += digestset_isin(ds, cp)); - SMARTLIST_FOREACH(sl2, const char *, cp, n += digestset_isin(ds, cp)); - } - tor_gettimeofday(&end); - - for (i = 0; i < fpostests; ++i) { - crypto_rand(d, 20); - if (digestset_isin(ds, d)) ++fp; - } - - printf("%ld\n",(unsigned long)tv_udiff(&start, &pt2)); - printf("%ld\n",(unsigned long)tv_udiff(&pt2, &pt3)); - printf("%ld\n",(unsigned long)tv_udiff(&pt3, &pt4)); - printf("%ld\n",(unsigned long)tv_udiff(&pt4, &end)); - printf("-- %d\n", n); - printf("++ %f\n", fp/(double)fpostests); - digestmap_free(dm, NULL); - digestset_free(ds); - SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); - SMARTLIST_FOREACH(sl2, char *, cp, tor_free(cp)); - smartlist_free(sl); - smartlist_free(sl2); -} - /** Test encoding and parsing of rendezvous service descriptors. */ static void test_rend_fns(void) @@ -1026,8 +1385,73 @@ static void test_geoip(void) { int i, j; - time_t now = time(NULL); + time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */ char *s = NULL; + const char *bridge_stats_1 = + "bridge-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "bridge-ips zz=24,xy=8\n", + *dirreq_stats_1 = + "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "dirreq-v3-ips ab=8\n" + "dirreq-v2-ips \n" + "dirreq-v3-reqs ab=8\n" + "dirreq-v2-reqs \n" + "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0," + "not-modified=0,busy=0\n" + "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0," + "busy=0\n" + "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" + "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n" + "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n" + "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n", + *dirreq_stats_2 = + "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "dirreq-v3-ips \n" + "dirreq-v2-ips \n" + "dirreq-v3-reqs \n" + "dirreq-v2-reqs \n" + "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0," + "not-modified=0,busy=0\n" + "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0," + "busy=0\n" + "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" + "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n" + "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n" + "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n", + *dirreq_stats_3 = + "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "dirreq-v3-ips \n" + "dirreq-v2-ips \n" + "dirreq-v3-reqs \n" + "dirreq-v2-reqs \n" + "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0," + "not-modified=0,busy=0\n" + "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0," + "busy=0\n" + "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" + "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n" + "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n" + "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n", + *dirreq_stats_4 = + "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "dirreq-v3-ips \n" + "dirreq-v2-ips \n" + "dirreq-v3-reqs \n" + "dirreq-v2-reqs \n" + "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0," + "not-modified=0,busy=0\n" + "dirreq-v2-resp ok=0,unavailable=0,not-found=0,not-modified=0," + "busy=0\n" + "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n" + "dirreq-v2-direct-dl complete=0,timeout=0,running=0\n" + "dirreq-v3-tunneled-dl complete=0,timeout=0,running=4\n" + "dirreq-v2-tunneled-dl complete=0,timeout=0,running=0\n", + *entry_stats_1 = + "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "entry-ips ab=8\n", + *entry_stats_2 = + "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "entry-ips \n"; /* Populate the DB a bit. Add these in order, since we can't do the final * 'sort' step. These aren't very good IP addresses, but they're perfectly @@ -1053,8 +1477,8 @@ test_geoip(void) test_streq("??", NAMEFOR(2000)); #undef NAMEFOR - get_options()->BridgeRelay = 1; - get_options()->BridgeRecordUsageByCountry = 1; + get_options_mutable()->BridgeRelay = 1; + get_options_mutable()->BridgeRecordUsageByCountry = 1; /* Put 9 observations in AB... */ for (i=32; i < 40; ++i) geoip_note_client_seen(GEOIP_CLIENT_CONNECT, i, now-7200); @@ -1077,6 +1501,114 @@ test_geoip(void) test_assert(s); test_streq("zz=24,xy=8", s); + /* Start testing bridge statistics by making sure that we don't output + * bridge stats without initializing them. */ + s = geoip_format_bridge_stats(now + 86400); + test_assert(!s); + + /* Initialize stats and generate the bridge-stats history string out of + * the connecting clients added above. */ + geoip_bridge_stats_init(now); + s = geoip_format_bridge_stats(now + 86400); + test_streq(bridge_stats_1, s); + tor_free(s); + + /* Stop collecting bridge stats and make sure we don't write a history + * string anymore. */ + geoip_bridge_stats_term(); + s = geoip_format_bridge_stats(now + 86400); + test_assert(!s); + + /* Stop being a bridge and start being a directory mirror that gathers + * directory request statistics. */ + geoip_bridge_stats_term(); + get_options_mutable()->BridgeRelay = 0; + get_options_mutable()->BridgeRecordUsageByCountry = 0; + get_options_mutable()->DirReqStatistics = 1; + + /* Start testing dirreq statistics by making sure that we don't collect + * dirreq stats without initializing them. */ + geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, 100, now); + s = geoip_format_dirreq_stats(now + 86400); + test_assert(!s); + + /* Initialize stats, note one connecting client, and generate the + * dirreq-stats history string. */ + geoip_dirreq_stats_init(now); + geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, 100, now); + s = geoip_format_dirreq_stats(now + 86400); + test_streq(dirreq_stats_1, s); + tor_free(s); + + /* Stop collecting stats, add another connecting client, and ensure we + * don't generate a history string. */ + geoip_dirreq_stats_term(); + geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, 101, now); + s = geoip_format_dirreq_stats(now + 86400); + test_assert(!s); + + /* Re-start stats, add a connecting client, reset stats, and make sure + * that we get an all empty history string. */ + geoip_dirreq_stats_init(now); + geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, 100, now); + geoip_reset_dirreq_stats(now); + s = geoip_format_dirreq_stats(now + 86400); + test_streq(dirreq_stats_2, s); + tor_free(s); + + /* Note a successful network status response and make sure that it + * appears in the history string. */ + geoip_note_ns_response(GEOIP_CLIENT_NETWORKSTATUS, GEOIP_SUCCESS); + s = geoip_format_dirreq_stats(now + 86400); + test_streq(dirreq_stats_3, s); + tor_free(s); + + /* Start a tunneled directory request. */ + geoip_start_dirreq((uint64_t) 1, 1024, GEOIP_CLIENT_NETWORKSTATUS, + DIRREQ_TUNNELED); + s = geoip_format_dirreq_stats(now + 86400); + test_streq(dirreq_stats_4, s); + + /* Stop collecting directory request statistics and start gathering + * entry stats. */ + geoip_dirreq_stats_term(); + get_options_mutable()->DirReqStatistics = 0; + get_options_mutable()->EntryStatistics = 1; + + /* Start testing entry statistics by making sure that we don't collect + * anything without initializing entry stats. */ + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 100, now); + s = geoip_format_entry_stats(now + 86400); + test_assert(!s); + + /* Initialize stats, note one connecting client, and generate the + * entry-stats history string. */ + geoip_entry_stats_init(now); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 100, now); + s = geoip_format_entry_stats(now + 86400); + test_streq(entry_stats_1, s); + tor_free(s); + + /* Stop collecting stats, add another connecting client, and ensure we + * don't generate a history string. */ + geoip_entry_stats_term(); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 101, now); + s = geoip_format_entry_stats(now + 86400); + test_assert(!s); + + /* Re-start stats, add a connecting client, reset stats, and make sure + * that we get an all empty history string. */ + geoip_entry_stats_init(now); + geoip_note_client_seen(GEOIP_CLIENT_CONNECT, 100, now); + geoip_reset_entry_stats(now); + s = geoip_format_entry_stats(now + 86400); + test_streq(entry_stats_2, s); + tor_free(s); + + /* Stop collecting entry statistics. */ + geoip_entry_stats_term(); + get_options_mutable()->EntryStatistics = 0; + done: tor_free(s); } @@ -1089,7 +1621,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 +1667,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 +1677,96 @@ test_stats(void) "exit-kibibytes-written other=0\n" "exit-kibibytes-read other=0\n" "exit-streams-opened other=0\n", s); + tor_free(s); + + /* Continue with testing connection statistics; we shouldn't collect + * conn stats without initializing them. */ + rep_hist_note_or_conn_bytes(1, 20, 400, now); + s = rep_hist_format_conn_stats(now + 86400); + test_assert(!s); + + /* Initialize stats, note bytes, and generate history string. */ + rep_hist_conn_stats_init(now); + rep_hist_note_or_conn_bytes(1, 30000, 400000, now); + rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5); + rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10); + rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); + s = rep_hist_format_conn_stats(now + 86400); + test_streq("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,1,0\n", s); + tor_free(s); + + /* Stop collecting stats, add some bytes, and ensure we don't generate + * a history string. */ + rep_hist_conn_stats_term(); + rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); + s = rep_hist_format_conn_stats(now + 86400); + test_assert(!s); + + /* Re-start stats, add some bytes, reset stats, and see what history we + * get when observing no bytes at all. */ + rep_hist_conn_stats_init(now); + rep_hist_note_or_conn_bytes(1, 30000, 400000, now); + rep_hist_note_or_conn_bytes(1, 30000, 400000, now + 5); + rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 10); + rep_hist_note_or_conn_bytes(2, 400000, 30000, now + 15); + rep_hist_reset_conn_stats(now); + s = rep_hist_format_conn_stats(now + 86400); + test_streq("conn-bi-direct 2010-08-12 13:27:30 (86400 s) 0,0,0,0\n", s); + tor_free(s); + + /* Continue with testing buffer statistics; we shouldn't collect buffer + * stats without initializing them. */ + rep_hist_add_buffer_stats(2.0, 2.0, 20); + s = rep_hist_format_buffer_stats(now + 86400); + test_assert(!s); + + /* Initialize stats, add statistics for a single circuit, and generate + * the history string. */ + rep_hist_buffer_stats_init(now); + rep_hist_add_buffer_stats(2.0, 2.0, 20); + s = rep_hist_format_buffer_stats(now + 86400); + test_streq("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "cell-processed-cells 20,0,0,0,0,0,0,0,0,0\n" + "cell-queued-cells 2.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00," + "0.00,0.00\n" + "cell-time-in-queue 2,0,0,0,0,0,0,0,0,0\n" + "cell-circuits-per-decile 1\n", s); + tor_free(s); + + /* Add nineteen more circuit statistics to the one that's already in the + * history to see that the math works correctly. */ + for (i = 21; i < 30; i++) + rep_hist_add_buffer_stats(2.0, 2.0, i); + for (i = 20; i < 30; i++) + rep_hist_add_buffer_stats(3.5, 3.5, i); + s = rep_hist_format_buffer_stats(now + 86400); + test_streq("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "cell-processed-cells 29,28,27,26,25,24,23,22,21,20\n" + "cell-queued-cells 2.75,2.75,2.75,2.75,2.75,2.75,2.75,2.75," + "2.75,2.75\n" + "cell-time-in-queue 3,3,3,3,3,3,3,3,3,3\n" + "cell-circuits-per-decile 2\n", s); + tor_free(s); + + /* Stop collecting stats, add statistics for one circuit, and ensure we + * don't generate a history string. */ + rep_hist_buffer_stats_term(); + rep_hist_add_buffer_stats(2.0, 2.0, 20); + s = rep_hist_format_buffer_stats(now + 86400); + test_assert(!s); + + /* Re-start stats, add statistics for one circuit, reset stats, and make + * sure that the history has all zeros. */ + rep_hist_buffer_stats_init(now); + rep_hist_add_buffer_stats(2.0, 2.0, 20); + rep_hist_reset_buffer_stats(now); + s = rep_hist_format_buffer_stats(now + 86400); + test_streq("cell-stats-end 2010-08-12 13:27:30 (86400 s)\n" + "cell-processed-cells 0,0,0,0,0,0,0,0,0,0\n" + "cell-queued-cells 0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00," + "0.00,0.00\n" + "cell-time-in-queue 0,0,0,0,0,0,0,0,0,0\n" + "cell-circuits-per-decile 0\n", s); done: tor_free(s); @@ -1180,12 +1803,13 @@ const struct testcase_setup_t legacy_setup = { { #group "_" #name, legacy_test_helper, 0, &legacy_setup, \ test_ ## group ## _ ## name } #define DISABLED(name) \ - { #name, legacy_test_helper, TT_SKIP, &legacy_setup, name } + { #name, legacy_test_helper, TT_SKIP, &legacy_setup, test_ ## name } #define FORK(name) \ { #name, legacy_test_helper, TT_FORK, &legacy_setup, test_ ## name } static struct testcase_t test_array[] = { ENT(buffers), + { "buffer_copy", test_buffer_copy, 0, NULL, NULL }, ENT(onion_handshake), ENT(circuit_timeout), ENT(policies), @@ -1193,8 +1817,23 @@ static struct testcase_t test_array[] = { ENT(geoip), FORK(stats), - DISABLED(bench_aes), - DISABLED(bench_dmap), + END_OF_TESTCASES +}; + +#define SOCKSENT(name) \ + { #name, test_socks_##name, TT_FORK, &socks_setup, NULL } + +static struct testcase_t socks_tests[] = { + SOCKSENT(4_unsupported_commands), + SOCKSENT(4_supported_commands), + + SOCKSENT(5_unsupported_commands), + SOCKSENT(5_supported_commands), + SOCKSENT(5_no_authenticate), + SOCKSENT(5_auth_before_negotiation), + SOCKSENT(5_authenticate), + SOCKSENT(5_authenticate_with_data), + END_OF_TESTCASES }; @@ -1203,14 +1842,19 @@ extern struct testcase_t crypto_tests[]; extern struct testcase_t container_tests[]; extern struct testcase_t util_tests[]; extern struct testcase_t dir_tests[]; +extern struct testcase_t microdesc_tests[]; +extern struct testcase_t pt_tests[]; static struct testgroup_t testgroups[] = { { "", test_array }, + { "socks/", socks_tests }, { "addr/", addr_tests }, { "crypto/", crypto_tests }, { "container/", container_tests }, { "util/", util_tests }, { "dir/", dir_tests }, + { "dir/md/", microdesc_tests }, + { "pt/", pt_tests }, END_OF_GROUPS }; @@ -1259,7 +1903,11 @@ 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; + } + crypto_set_tls_dh_prime(NULL); rep_hist_init(); network_init(); setup_directory(); diff --git a/src/test/test.h b/src/test/test.h index f7ae46ce6d..a053a7ac43 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 1dab0e0112..9d8e1fe8c5 100644 --- a/src/test/test_addr.c +++ b/src/test/test_addr.c @@ -14,30 +14,30 @@ test_addr_basic(void) uint16_t u16; char *cp; - /* Test parse_addr_port */ + /* Test addr_port_lookup */ cp = NULL; u32 = 3; u16 = 3; - test_assert(!parse_addr_port(LOG_WARN, "1.2.3.4", &cp, &u32, &u16)); + test_assert(!addr_port_lookup(LOG_WARN, "1.2.3.4", &cp, &u32, &u16)); test_streq(cp, "1.2.3.4"); test_eq(u32, 0x01020304u); test_eq(u16, 0); tor_free(cp); - test_assert(!parse_addr_port(LOG_WARN, "4.3.2.1:99", &cp, &u32, &u16)); + test_assert(!addr_port_lookup(LOG_WARN, "4.3.2.1:99", &cp, &u32, &u16)); test_streq(cp, "4.3.2.1"); test_eq(u32, 0x04030201u); test_eq(u16, 99); tor_free(cp); - test_assert(!parse_addr_port(LOG_WARN, "nonexistent.address:4040", + test_assert(!addr_port_lookup(LOG_WARN, "nonexistent.address:4040", &cp, NULL, &u16)); test_streq(cp, "nonexistent.address"); test_eq(u16, 4040); tor_free(cp); - test_assert(!parse_addr_port(LOG_WARN, "localhost:9999", &cp, &u32, &u16)); + test_assert(!addr_port_lookup(LOG_WARN, "localhost:9999", &cp, &u32, &u16)); test_streq(cp, "localhost"); test_eq(u32, 0x7f000001u); test_eq(u16, 9999); tor_free(cp); u32 = 3; - test_assert(!parse_addr_port(LOG_WARN, "localhost", NULL, &u32, &u16)); + test_assert(!addr_port_lookup(LOG_WARN, "localhost", NULL, &u32, &u16)); test_eq(cp, NULL); test_eq(u32, 0x7f000001u); test_eq(u16, 0); @@ -53,9 +53,17 @@ test_addr_basic(void) char tmpbuf[TOR_ADDR_BUF_LEN]; const char *ip = "176.192.208.224"; struct in_addr in; - tor_inet_pton(AF_INET, ip, &in); - tor_inet_ntop(AF_INET, &in, tmpbuf, sizeof(tmpbuf)); + + /* good round trip */ + test_eq(tor_inet_pton(AF_INET, ip, &in), 1); + test_eq_ptr(tor_inet_ntop(AF_INET, &in, tmpbuf, sizeof(tmpbuf)), &tmpbuf); test_streq(tmpbuf, ip); + + /* just enough buffer length */ + test_streq(tor_inet_ntop(AF_INET, &in, tmpbuf, strlen(ip) + 1), ip); + + /* too short buffer */ + test_eq_ptr(tor_inet_ntop(AF_INET, &in, tmpbuf, strlen(ip)), NULL); } done: @@ -74,7 +82,9 @@ test_addr_basic(void) cp += 2; \ if (i != 15) *cp++ = ':'; \ } \ - }, { tor_free(_print); } \ + }, \ + { tor_free(_print); }, \ + TT_EXIT_TEST_FUNCTION \ ); \ STMT_END @@ -165,6 +175,7 @@ static void test_addr_ip6_helpers(void) { char buf[TOR_ADDR_BUF_LEN], bug[TOR_ADDR_BUF_LEN]; + char rbuf[REVERSE_LOOKUP_NAME_BUF_LEN]; struct in6_addr a1, a2; tor_addr_t t1, t2; int r, i; @@ -175,8 +186,30 @@ test_addr_ip6_helpers(void) struct sockaddr_in *sin; struct sockaddr_in6 *sin6; - // struct in_addr b1, b2; /* Test tor_inet_ntop and tor_inet_pton: IPv6 */ + { + const char *ip = "2001::1234"; + const char *ip_ffff = "::ffff:192.168.1.2"; + + /* good round trip */ + test_eq(tor_inet_pton(AF_INET6, ip, &a1), 1); + test_eq_ptr(tor_inet_ntop(AF_INET6, &a1, buf, sizeof(buf)), &buf); + test_streq(buf, ip); + + /* good round trip - ::ffff:0:0 style */ + test_eq(tor_inet_pton(AF_INET6, ip_ffff, &a2), 1); + test_eq_ptr(tor_inet_ntop(AF_INET6, &a2, buf, sizeof(buf)), &buf); + test_streq(buf, ip_ffff); + + /* just long enough buffer (remember \0) */ + test_streq(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)+1), ip); + test_streq(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)+1), + ip_ffff); + + /* too short buffer (remember \0) */ + test_eq_ptr(tor_inet_ntop(AF_INET6, &a1, buf, strlen(ip)), NULL); + test_eq_ptr(tor_inet_ntop(AF_INET6, &a2, buf, strlen(ip_ffff)), NULL); + } /* ==== Converting to and from sockaddr_t. */ sin = (struct sockaddr_in *)&sa_storage; @@ -268,12 +301,23 @@ test_addr_ip6_helpers(void) test_ntop6_reduces("1000:0001:0000:0007:0000:0000:0000:0000", "1000:1:0:7::"); + /* Bad af param */ + test_eq(tor_inet_pton(AF_UNSPEC, 0, 0), -1); + /* === Test pton: invalid in6. */ test_pton6_bad("foobar."); + test_pton6_bad("-1::"); + test_pton6_bad("00001::"); + test_pton6_bad("10000::"); + test_pton6_bad("::10000"); test_pton6_bad("55555::"); test_pton6_bad("9:-60::"); + test_pton6_bad("9:+60::"); + test_pton6_bad("9|60::"); + test_pton6_bad("0x60::"); + test_pton6_bad("::0x60"); + test_pton6_bad("9:0x60::"); test_pton6_bad("1:2:33333:4:0002:3::"); - //test_pton6_bad("1:2:3333:4:00002:3::");// BAD, but glibc doesn't say so. test_pton6_bad("1:2:3333:4:fish:3::"); test_pton6_bad("1:2:3:4:5:6:7:8:9"); test_pton6_bad("1:2:3:4:5:6:7"); @@ -281,8 +325,14 @@ test_addr_ip6_helpers(void) test_pton6_bad("1:2:3:4:5:6:1.2.3"); test_pton6_bad("::1.2.3"); test_pton6_bad("::1.2.3.4.5"); + test_pton6_bad("::ffff:0xff.0.0.0"); + test_pton6_bad("::ffff:ff.0.0.0"); + test_pton6_bad("::ffff:256.0.0.0"); + test_pton6_bad("::ffff:-1.0.0.0"); test_pton6_bad("99"); test_pton6_bad(""); + test_pton6_bad("."); + test_pton6_bad(":"); test_pton6_bad("1::2::3:4"); test_pton6_bad("a:::b:c"); test_pton6_bad(":::a:b:c"); @@ -291,6 +341,9 @@ test_addr_ip6_helpers(void) /* test internal checking */ test_external_ip("fbff:ffff::2:7", 0); test_internal_ip("fc01::2:7", 0); + test_internal_ip("fc01::02:7", 0); + test_internal_ip("fc01::002:7", 0); + test_internal_ip("fc01::0002:7", 0); test_internal_ip("fdff:ffff::f:f", 0); test_external_ip("fe00::3:f", 0); @@ -361,33 +414,67 @@ test_addr_ip6_helpers(void) test_addr_compare_masked("0::2:2:1", <, "0::8000:2:1", 81); test_addr_compare_masked("0::2:2:1", ==, "0::8000:2:1", 80); - /* Test decorated addr_to_string. */ - test_eq(AF_INET6, tor_addr_from_str(&t1, "[123:45:6789::5005:11]")); + /* Test undecorated tor_addr_to_str */ + test_eq(AF_INET6, tor_addr_parse(&t1, "[123:45:6789::5005:11]")); + p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0); + test_streq(p1, "123:45:6789::5005:11"); + test_eq(AF_INET, tor_addr_parse(&t1, "18.0.0.1")); + p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 0); + test_streq(p1, "18.0.0.1"); + + /* Test decorated tor_addr_to_str */ + test_eq(AF_INET6, tor_addr_parse(&t1, "[123:45:6789::5005:11]")); p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1); test_streq(p1, "[123:45:6789::5005:11]"); - test_eq(AF_INET, tor_addr_from_str(&t1, "18.0.0.1")); + test_eq(AF_INET, tor_addr_parse(&t1, "18.0.0.1")); p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1); test_streq(p1, "18.0.0.1"); - /* Test tor_addr_parse_reverse_lookup_name */ - i = tor_addr_parse_reverse_lookup_name(&t1, "Foobar.baz", AF_UNSPEC, 0); + /* Test buffer bounds checking of tor_addr_to_str */ + test_eq(AF_INET6, tor_addr_parse(&t1, "::")); /* 2 + \0 */ + test_eq_ptr(tor_addr_to_str(buf, &t1, 2, 0), NULL); /* too short buf */ + test_streq(tor_addr_to_str(buf, &t1, 3, 0), "::"); + test_eq_ptr(tor_addr_to_str(buf, &t1, 4, 1), NULL); /* too short buf */ + test_streq(tor_addr_to_str(buf, &t1, 5, 1), "[::]"); + + test_eq(AF_INET6, tor_addr_parse(&t1, "2000::1337")); /* 10 + \0 */ + test_eq_ptr(tor_addr_to_str(buf, &t1, 10, 0), NULL); /* too short buf */ + test_streq(tor_addr_to_str(buf, &t1, 11, 0), "2000::1337"); + test_eq_ptr(tor_addr_to_str(buf, &t1, 12, 1), NULL); /* too short buf */ + test_streq(tor_addr_to_str(buf, &t1, 13, 1), "[2000::1337]"); + + test_eq(AF_INET, tor_addr_parse(&t1, "1.2.3.4")); /* 7 + \0 */ + test_eq_ptr(tor_addr_to_str(buf, &t1, 7, 0), NULL); /* too short buf */ + test_streq(tor_addr_to_str(buf, &t1, 8, 0), "1.2.3.4"); + + test_eq(AF_INET, tor_addr_parse(&t1, "255.255.255.255")); /* 15 + \0 */ + test_eq_ptr(tor_addr_to_str(buf, &t1, 15, 0), NULL); /* too short buf */ + test_streq(tor_addr_to_str(buf, &t1, 16, 0), "255.255.255.255"); + test_eq_ptr(tor_addr_to_str(buf, &t1, 15, 1), NULL); /* too short buf */ + test_streq(tor_addr_to_str(buf, &t1, 16, 1), "255.255.255.255"); + + t1.family = AF_UNSPEC; + test_eq_ptr(tor_addr_to_str(buf, &t1, sizeof(buf), 0), NULL); + + /* Test tor_addr_parse_PTR_name */ + i = tor_addr_parse_PTR_name(&t1, "Foobar.baz", AF_UNSPEC, 0); test_eq(0, i); - i = tor_addr_parse_reverse_lookup_name(&t1, "Foobar.baz", AF_UNSPEC, 1); + i = tor_addr_parse_PTR_name(&t1, "Foobar.baz", AF_UNSPEC, 1); test_eq(0, i); - i = tor_addr_parse_reverse_lookup_name(&t1, "1.0.168.192.in-addr.arpa", + i = tor_addr_parse_PTR_name(&t1, "1.0.168.192.in-addr.arpa", AF_UNSPEC, 1); test_eq(1, i); test_eq(tor_addr_family(&t1), AF_INET); p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1); test_streq(p1, "192.168.0.1"); - i = tor_addr_parse_reverse_lookup_name(&t1, "192.168.0.99", AF_UNSPEC, 0); + i = tor_addr_parse_PTR_name(&t1, "192.168.0.99", AF_UNSPEC, 0); test_eq(0, i); - i = tor_addr_parse_reverse_lookup_name(&t1, "192.168.0.99", AF_UNSPEC, 1); + i = tor_addr_parse_PTR_name(&t1, "192.168.0.99", AF_UNSPEC, 1); test_eq(1, i); p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1); test_streq(p1, "192.168.0.99"); memset(&t1, 0, sizeof(t1)); - i = tor_addr_parse_reverse_lookup_name(&t1, + i = tor_addr_parse_PTR_name(&t1, "0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f." "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9." "ip6.ARPA", @@ -396,43 +483,91 @@ test_addr_ip6_helpers(void) p1 = tor_addr_to_str(buf, &t1, sizeof(buf), 1); test_streq(p1, "[9dee:effe:ebe1:beef:fedc:ba98:7654:3210]"); /* Failing cases. */ - i = tor_addr_parse_reverse_lookup_name(&t1, + i = tor_addr_parse_PTR_name(&t1, "6.7.8.9.a.b.c.d.e.f." "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9." "ip6.ARPA", AF_UNSPEC, 0); test_eq(i, -1); - i = tor_addr_parse_reverse_lookup_name(&t1, + i = tor_addr_parse_PTR_name(&t1, "6.7.8.9.a.b.c.d.e.f.a.b.c.d.e.f.0." "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9." "ip6.ARPA", AF_UNSPEC, 0); test_eq(i, -1); - i = tor_addr_parse_reverse_lookup_name(&t1, + i = tor_addr_parse_PTR_name(&t1, "6.7.8.9.a.b.c.d.e.f.X.0.0.0.0.9." "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9." "ip6.ARPA", AF_UNSPEC, 0); test_eq(i, -1); - i = tor_addr_parse_reverse_lookup_name(&t1, "32.1.1.in-addr.arpa", + i = tor_addr_parse_PTR_name(&t1, "32.1.1.in-addr.arpa", AF_UNSPEC, 0); test_eq(i, -1); - i = tor_addr_parse_reverse_lookup_name(&t1, ".in-addr.arpa", + i = tor_addr_parse_PTR_name(&t1, ".in-addr.arpa", AF_UNSPEC, 0); test_eq(i, -1); - i = tor_addr_parse_reverse_lookup_name(&t1, "1.2.3.4.5.in-addr.arpa", + i = tor_addr_parse_PTR_name(&t1, "1.2.3.4.5.in-addr.arpa", AF_UNSPEC, 0); test_eq(i, -1); - i = tor_addr_parse_reverse_lookup_name(&t1, "1.2.3.4.5.in-addr.arpa", + i = tor_addr_parse_PTR_name(&t1, "1.2.3.4.5.in-addr.arpa", AF_INET6, 0); test_eq(i, -1); - i = tor_addr_parse_reverse_lookup_name(&t1, + i = tor_addr_parse_PTR_name(&t1, "6.7.8.9.a.b.c.d.e.f.a.b.c.d.e.0." "f.e.e.b.1.e.b.e.e.f.f.e.e.e.d.9." "ip6.ARPA", AF_INET, 0); test_eq(i, -1); + /* === Test tor_addr_to_PTR_name */ + + /* Stage IPv4 addr */ + memset(&sa_storage, 0, sizeof(sa_storage)); + sin = (struct sockaddr_in *)&sa_storage; + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = htonl(0x7f010203); /* 127.1.2.3 */ + tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin, NULL); + + /* Check IPv4 PTR - too short buffer */ + test_eq(tor_addr_to_PTR_name(rbuf, 1, &t1), -1); + test_eq(tor_addr_to_PTR_name(rbuf, + strlen("3.2.1.127.in-addr.arpa") - 1, + &t1), -1); + + /* Check IPv4 PTR - valid addr */ + test_eq(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1), + strlen("3.2.1.127.in-addr.arpa")); + test_streq(rbuf, "3.2.1.127.in-addr.arpa"); + + /* Invalid addr family */ + t1.family = AF_UNSPEC; + test_eq(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1), -1); + + /* Stage IPv6 addr */ + memset(&sa_storage, 0, sizeof(sa_storage)); + sin6 = (struct sockaddr_in6 *)&sa_storage; + sin6->sin6_family = AF_INET6; + sin6->sin6_addr.s6_addr[0] = 0x80; /* 8000::abcd */ + sin6->sin6_addr.s6_addr[14] = 0xab; + sin6->sin6_addr.s6_addr[15] = 0xcd; + + tor_addr_from_sockaddr(&t1, (struct sockaddr *)sin6, NULL); + + { + const char* addr_PTR = "d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0." + "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.ip6.arpa"; + + /* Check IPv6 PTR - too short buffer */ + test_eq(tor_addr_to_PTR_name(rbuf, 0, &t1), -1); + test_eq(tor_addr_to_PTR_name(rbuf, strlen(addr_PTR) - 1, &t1), -1); + + /* Check IPv6 PTR - valid addr */ + test_eq(tor_addr_to_PTR_name(rbuf, sizeof(rbuf), &t1), + strlen(addr_PTR)); + test_streq(rbuf, addr_PTR); + } + /* test tor_addr_parse_mask_ports */ test_addr_mask_ports_parse("[::f]/17:47-95", AF_INET6, 0, 0, 0, 0x0000000f, 17, 47, 95); diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 121af279c7..cad8c2f556 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -7,6 +7,7 @@ #define CRYPTO_PRIVATE #include "or.h" #include "test.h" +#include "aes.h" /** Run unit tests for Diffie-Hellman functionality. */ static void @@ -95,13 +96,16 @@ test_crypto_rng(void) /** Run unit tests for our AES functionality */ static void -test_crypto_aes(void) +test_crypto_aes(void *arg) { char *data1 = NULL, *data2 = NULL, *data3 = NULL; crypto_cipher_env_t *env1 = NULL, *env2 = NULL; int i, j; char *mem_op_hex_tmp=NULL; + int use_evp = !strcmp(arg,"evp"); + evaluate_evp_for_aes(use_evp); + data1 = tor_malloc(1024); data2 = tor_malloc(1024); data3 = tor_malloc(1024); @@ -231,7 +235,7 @@ test_crypto_sha(void) { crypto_digest_env_t *d1 = NULL, *d2 = NULL; int i; - char key[80]; + char key[160]; char digest[32]; char data[50]; char d_out1[DIGEST_LEN], d_out2[DIGEST256_LEN]; @@ -276,6 +280,75 @@ test_crypto_sha(void) test_streq(hex_str(digest, 20), "AA4AE5E15272D00E95705637CE8A3B55ED402112"); + /* Test HMAC-SHA256 with test cases from wikipedia and RFC 4231 */ + + /* Case empty (wikipedia) */ + crypto_hmac_sha256(digest, "", 0, "", 0); + test_streq(hex_str(digest, 32), + "B613679A0814D9EC772F95D778C35FC5FF1697C493715653C6C712144292C5AD"); + + /* Case quick-brown (wikipedia) */ + crypto_hmac_sha256(digest, "key", 3, + "The quick brown fox jumps over the lazy dog", 43); + test_streq(hex_str(digest, 32), + "F7BC83F430538424B13298E6AA6FB143EF4D59A14946175997479DBC2D1A3CD8"); + + /* "Test Case 1" from RFC 4231 */ + memset(key, 0x0b, 20); + crypto_hmac_sha256(digest, key, 20, "Hi There", 8); + test_memeq_hex(digest, + "b0344c61d8db38535ca8afceaf0bf12b" + "881dc200c9833da726e9376c2e32cff7"); + + /* "Test Case 2" from RFC 4231 */ + memset(key, 0x0b, 20); + crypto_hmac_sha256(digest, "Jefe", 4, "what do ya want for nothing?", 28); + test_memeq_hex(digest, + "5bdcc146bf60754e6a042426089575c7" + "5a003f089d2739839dec58b964ec3843"); + + /* "Test case 3" from RFC 4231 */ + memset(key, 0xaa, 20); + memset(data, 0xdd, 50); + crypto_hmac_sha256(digest, key, 20, data, 50); + test_memeq_hex(digest, + "773ea91e36800e46854db8ebd09181a7" + "2959098b3ef8c122d9635514ced565fe"); + + /* "Test case 4" from RFC 4231 */ + base16_decode(key, 25, + "0102030405060708090a0b0c0d0e0f10111213141516171819", 50); + memset(data, 0xcd, 50); + crypto_hmac_sha256(digest, key, 25, data, 50); + test_memeq_hex(digest, + "82558a389a443c0ea4cc819899f2083a" + "85f0faa3e578f8077a2e3ff46729665b"); + + /* "Test case 5" from RFC 4231 */ + memset(key, 0x0c, 20); + crypto_hmac_sha256(digest, key, 20, "Test With Truncation", 20); + test_memeq_hex(digest, + "a3b6167473100ee06e0c796c2955552b"); + + /* "Test case 6" from RFC 4231 */ + memset(key, 0xaa, 131); + crypto_hmac_sha256(digest, key, 131, + "Test Using Larger Than Block-Size Key - Hash Key First", + 54); + test_memeq_hex(digest, + "60e431591ee0b67f0d8a26aacbf5b77f" + "8e0bc6213728c5140546040f0ee37f54"); + + /* "Test case 7" from RFC 4231 */ + memset(key, 0xaa, 131); + crypto_hmac_sha256(digest, key, 131, + "This is a test using a larger than block-size key and a " + "larger than block-size data. The key needs to be hashed " + "before being used by the HMAC algorithm.", 152); + test_memeq_hex(digest, + "9b09ffa71b942fcb27635fbcd5b0e944" + "bfdc63644f0713938a7f51535c3a35e2"); + /* Incremental digest code. */ d1 = crypto_new_digest_env(); test_assert(d1); @@ -601,7 +674,7 @@ test_crypto_s2k(void) /** Test AES-CTR encryption and decryption with IV. */ static void -test_crypto_aes_iv(void) +test_crypto_aes_iv(void *arg) { crypto_cipher_env_t *cipher; char *plain, *encrypted1, *encrypted2, *decrypted1, *decrypted2; @@ -609,6 +682,9 @@ test_crypto_aes_iv(void) char key1[16], key2[16]; ssize_t encrypted_size, decrypted_size; + int use_evp = !strcmp(arg,"evp"); + evaluate_evp_for_aes(use_evp); + plain = tor_malloc(4095); encrypted1 = tor_malloc(4095 + 1 + 16); encrypted2 = tor_malloc(4095 + 1 + 16); @@ -630,7 +706,7 @@ test_crypto_aes_iv(void) crypto_free_cipher_env(cipher); cipher = NULL; test_eq(encrypted_size, 16 + 4095); - tor_assert(encrypted_size > 0); /* This is obviously true, since 4111 is + tt_assert(encrypted_size > 0); /* This is obviously true, since 4111 is * greater than 0, but its truth is not * obvious to all analysis tools. */ cipher = crypto_create_init_cipher(key1, 0); @@ -639,7 +715,7 @@ test_crypto_aes_iv(void) crypto_free_cipher_env(cipher); cipher = NULL; test_eq(decrypted_size, 4095); - tor_assert(decrypted_size > 0); + tt_assert(decrypted_size > 0); test_memeq(plain, decrypted1, 4095); /* Encrypt a second time (with a new random initialization vector). */ cipher = crypto_create_init_cipher(key1, 1); @@ -648,14 +724,14 @@ test_crypto_aes_iv(void) crypto_free_cipher_env(cipher); cipher = NULL; test_eq(encrypted_size, 16 + 4095); - tor_assert(encrypted_size > 0); + tt_assert(encrypted_size > 0); cipher = crypto_create_init_cipher(key1, 0); decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted2, 4095, encrypted2, encrypted_size); crypto_free_cipher_env(cipher); cipher = NULL; test_eq(decrypted_size, 4095); - tor_assert(decrypted_size > 0); + tt_assert(decrypted_size > 0); test_memeq(plain, decrypted2, 4095); test_memneq(encrypted1, encrypted2, encrypted_size); /* Decrypt with the wrong key. */ @@ -680,14 +756,14 @@ test_crypto_aes_iv(void) crypto_free_cipher_env(cipher); cipher = NULL; test_eq(encrypted_size, 16 + 1); - tor_assert(encrypted_size > 0); + tt_assert(encrypted_size > 0); cipher = crypto_create_init_cipher(key1, 0); decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 1, encrypted1, encrypted_size); crypto_free_cipher_env(cipher); cipher = NULL; test_eq(decrypted_size, 1); - tor_assert(decrypted_size > 0); + tt_assert(decrypted_size > 0); test_memeq(plain_1, decrypted1, 1); /* Special length case: 15. */ cipher = crypto_create_init_cipher(key1, 1); @@ -696,14 +772,14 @@ test_crypto_aes_iv(void) crypto_free_cipher_env(cipher); cipher = NULL; test_eq(encrypted_size, 16 + 15); - tor_assert(encrypted_size > 0); + tt_assert(encrypted_size > 0); cipher = crypto_create_init_cipher(key1, 0); decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 15, encrypted1, encrypted_size); crypto_free_cipher_env(cipher); cipher = NULL; test_eq(decrypted_size, 15); - tor_assert(decrypted_size > 0); + tt_assert(decrypted_size > 0); test_memeq(plain_15, decrypted1, 15); /* Special length case: 16. */ cipher = crypto_create_init_cipher(key1, 1); @@ -712,14 +788,14 @@ test_crypto_aes_iv(void) crypto_free_cipher_env(cipher); cipher = NULL; test_eq(encrypted_size, 16 + 16); - tor_assert(encrypted_size > 0); + tt_assert(encrypted_size > 0); cipher = crypto_create_init_cipher(key1, 0); decrypted_size = crypto_cipher_decrypt_with_iv(cipher, decrypted1, 16, encrypted1, encrypted_size); crypto_free_cipher_env(cipher); cipher = NULL; test_eq(decrypted_size, 16); - tor_assert(decrypted_size > 0); + tt_assert(decrypted_size > 0); test_memeq(plain_16, decrypted1, 16); /* Special length case: 17. */ cipher = crypto_create_init_cipher(key1, 1); @@ -728,12 +804,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: @@ -782,18 +858,36 @@ test_crypto_base32_decode(void) ; } +static void * +pass_data_setup_fn(const struct testcase_t *testcase) +{ + return testcase->setup_data; +} +static int +pass_data_cleanup_fn(const struct testcase_t *testcase, void *ptr) +{ + (void)ptr; + (void)testcase; + return 1; +} +static const struct testcase_setup_t pass_data = { + pass_data_setup_fn, pass_data_cleanup_fn +}; + #define CRYPTO_LEGACY(name) \ { #name, legacy_test_helper, 0, &legacy_setup, test_crypto_ ## name } struct testcase_t crypto_tests[] = { CRYPTO_LEGACY(formats), CRYPTO_LEGACY(rng), - CRYPTO_LEGACY(aes), + { "aes_AES", test_crypto_aes, TT_FORK, &pass_data, (void*)"aes" }, + { "aes_EVP", test_crypto_aes, TT_FORK, &pass_data, (void*)"evp" }, CRYPTO_LEGACY(sha), CRYPTO_LEGACY(pk), CRYPTO_LEGACY(dh), CRYPTO_LEGACY(s2k), - CRYPTO_LEGACY(aes_iv), + { "aes_iv_AES", test_crypto_aes_iv, TT_FORK, &pass_data, (void*)"aes" }, + { "aes_iv_EVP", test_crypto_aes_iv, TT_FORK, &pass_data, (void*)"evp" }, CRYPTO_LEGACY(base32_decode), END_OF_TESTCASES }; diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 8fd94289a9..5b7ce5cabe 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -7,10 +7,12 @@ #define DIRSERV_PRIVATE #define DIRVOTE_PRIVATE #define ROUTER_PRIVATE +#define HIBERNATE_PRIVATE #include "or.h" #include "directory.h" #include "dirserv.h" #include "dirvote.h" +#include "hibernate.h" #include "networkstatus.h" #include "router.h" #include "routerlist.h" @@ -85,6 +87,8 @@ test_dir_formats(void) test_assert(pk1 && pk2 && pk3); + hibernate_set_state_for_testing_(HIBERNATE_STATE_LIVE); + get_platform_str(platform, sizeof(platform)); r1 = tor_malloc_zero(sizeof(routerinfo_t)); r1->address = tor_strdup("18.244.0.1"); @@ -298,7 +302,7 @@ test_dir_versions(void) #define tt_versionstatus_op(vs1, op, vs2) \ tt_assert_test_type(vs1,vs2,#vs1" "#op" "#vs2,version_status_t, \ - (_val1 op _val2),"%d") + (_val1 op _val2),"%d",TT_EXIT_TEST_FUNCTION) #define test_v_i_o(val, ver, lst) \ tt_versionstatus_op(val, ==, tor_version_is_obsolete(ver, lst)) @@ -616,13 +620,81 @@ test_dir_param_voting(void) test_eq(0, networkstatus_get_param(&vote4, "foobar", 0, -100, 8)); smartlist_add(votes, &vote1); + + /* Do the first tests without adding all the other votes, for + * networks without many dirauths. */ + + res = dirvote_compute_params(votes, 11, 6); + test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-99"); + tor_free(res); + + res = dirvote_compute_params(votes, 12, 2); + test_streq(res, ""); + tor_free(res); + + res = dirvote_compute_params(votes, 12, 1); + test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-99"); + tor_free(res); + smartlist_add(votes, &vote2); + + res = dirvote_compute_params(votes, 11, 2); + test_streq(res, "ab=27 abcd=20 cw=5 x-yz=-99"); + tor_free(res); + + res = dirvote_compute_params(votes, 12, 2); + test_streq(res, "ab=27 cw=5 x-yz=-99"); + tor_free(res); + + res = dirvote_compute_params(votes, 12, 3); + test_streq(res, "ab=27 cw=5 x-yz=-99"); + tor_free(res); + + res = dirvote_compute_params(votes, 12, 6); + test_streq(res, ""); + tor_free(res); + smartlist_add(votes, &vote3); + + res = dirvote_compute_params(votes, 11, 3); + test_streq(res, "ab=27 abcd=20 c=60 cw=50 x-yz=-9 zzzzz=101"); + tor_free(res); + + res = dirvote_compute_params(votes, 12, 3); + test_streq(res, "ab=27 abcd=20 cw=50 x-yz=-9"); + tor_free(res); + + res = dirvote_compute_params(votes, 12, 5); + test_streq(res, "cw=50 x-yz=-9"); + tor_free(res); + + res = dirvote_compute_params(votes, 12, 9); + test_streq(res, "cw=50 x-yz=-9"); + tor_free(res); + smartlist_add(votes, &vote4); - res = dirvote_compute_params(votes); - test_streq(res, - "ab=90 abcd=20 c=1 cw=50 x-yz=-9 zzzzz=101"); + res = dirvote_compute_params(votes, 11, 4); + test_streq(res, "ab=90 abcd=20 c=1 cw=50 x-yz=-9 zzzzz=101"); + tor_free(res); + + res = dirvote_compute_params(votes, 12, 4); + test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9"); + tor_free(res); + + res = dirvote_compute_params(votes, 12, 5); + test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9"); + tor_free(res); + + /* Test that the special-cased "at least three dirauths voted for + * this param" logic works as expected. */ + res = dirvote_compute_params(votes, 12, 6); + test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9"); + tor_free(res); + + res = dirvote_compute_params(votes, 12, 10); + test_streq(res, "ab=90 abcd=20 cw=50 x-yz=-9"); + tor_free(res); done: tor_free(res); @@ -803,7 +875,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 +890,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 +907,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); @@ -1044,7 +1117,7 @@ test_dir_v3_networkstatus(void) "Running:Stable:V2Dir:Valid"); tor_free(cp); cp = smartlist_join_strings(con->net_params, ":", 0, NULL); - test_streq(cp, "bar=2000000000:circuitwindow=80:foo=660"); + test_streq(cp, "circuitwindow=80:foo=660"); tor_free(cp); test_eq(4, smartlist_len(con->voters)); /*3 voters, 1 legacy key.*/ @@ -1075,7 +1148,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 +1171,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 +1241,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); @@ -1301,7 +1375,7 @@ test_dir_v3_networkstatus(void) } #define DIR_LEGACY(name) \ - { #name, legacy_test_helper, 0, &legacy_setup, test_dir_ ## name } + { #name, legacy_test_helper, TT_FORK, &legacy_setup, test_dir_ ## name } #define DIR(name) \ { #name, test_dir_##name, 0, NULL, NULL } diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c new file mode 100644 index 0000000000..b807265c84 --- /dev/null +++ b/src/test/test_microdesc.c @@ -0,0 +1,233 @@ +/* Copyright (c) 2010-2011, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#include "or.h" + +#include "config.h" +#include "microdesc.h" + +#include "test.h" + +#ifdef MS_WINDOWS +/* For mkdir() */ +#include <direct.h> +#else +#include <dirent.h> +#endif + +static const char test_md1[] = + "onion-key\n" + "-----BEGIN RSA PUBLIC KEY-----\n" + "MIGJAoGBAMjlHH/daN43cSVRaHBwgUfnszzAhg98EvivJ9Qxfv51mvQUxPjQ07es\n" + "gV/3n8fyh3Kqr/ehi9jxkdgSRfSnmF7giaHL1SLZ29kA7KtST+pBvmTpDtHa3ykX\n" + "Xorc7hJvIyTZoc1HU+5XSynj3gsBE5IGK1ZRzrNS688LnuZMVp1tAgMBAAE=\n" + "-----END RSA PUBLIC KEY-----\n"; + +static const char test_md2[] = + "onion-key\n" + "-----BEGIN RSA PUBLIC KEY-----\n" + "MIGJAoGBAMIixIowh2DyPmDNMDwBX2DHcYcqdcH1zdIQJZkyV6c6rQHnvbcaDoSg\n" + "jgFSLJKpnGmh71FVRqep+yVB0zI1JY43kuEnXry2HbZCD9UDo3d3n7t015X5S7ON\n" + "bSSYtQGPwOr6Epf96IF6DoQxy4iDnPUAlejuhAG51s1y6/rZQ3zxAgMBAAE=\n" + "-----END RSA PUBLIC KEY-----\n"; + +static const char test_md3[] = + "@last-listed 2009-06-22\n" + "onion-key\n" + "-----BEGIN RSA PUBLIC KEY-----\n" + "MIGJAoGBAMH3340d4ENNGrqx7UxT+lB7x6DNUKOdPEOn4teceE11xlMyZ9TPv41c\n" + "qj2fRZzfxlc88G/tmiaHshmdtEpklZ740OFqaaJVj4LjPMKFNE+J7Xc1142BE9Ci\n" + "KgsbjGYe2RY261aADRWLetJ8T9QDMm+JngL4288hc8pq1uB/3TAbAgMBAAE=\n" + "-----END RSA PUBLIC KEY-----\n" + "p accept 1-700,800-1000\n" + "family nodeX nodeY nodeZ\n"; + +static void +test_md_cache(void *data) +{ + or_options_t *options = NULL; + microdesc_cache_t *mc = NULL ; + smartlist_t *added = NULL, *wanted = NULL; + microdesc_t *md1, *md2, *md3; + char d1[DIGEST256_LEN], d2[DIGEST256_LEN], d3[DIGEST256_LEN]; + const char *test_md3_noannotation = strchr(test_md3, '\n')+1; + time_t time1, time2, time3; + char *fn = NULL, *s = NULL; + (void)data; + + options = get_options_mutable(); + tt_assert(options); + + time1 = time(NULL); + time2 = time(NULL) - 2*24*60*60; + time3 = time(NULL) - 15*24*60*60; + + /* Possibly, turn this into a test setup/cleanup pair */ + tor_free(options->DataDirectory); + options->DataDirectory = tor_strdup(get_fname("md_datadir_test")); +#ifdef MS_WINDOWS + tt_int_op(0, ==, mkdir(options->DataDirectory)); +#else + tt_int_op(0, ==, mkdir(options->DataDirectory, 0700)); +#endif + + tt_assert(!strcmpstart(test_md3_noannotation, "onion-key")); + + crypto_digest256(d1, test_md1, strlen(test_md1), DIGEST_SHA256); + crypto_digest256(d2, test_md2, strlen(test_md1), DIGEST_SHA256); + crypto_digest256(d3, test_md3_noannotation, strlen(test_md3_noannotation), + DIGEST_SHA256); + + mc = get_microdesc_cache(); + + added = microdescs_add_to_cache(mc, test_md1, NULL, SAVED_NOWHERE, 0, + time1, NULL); + tt_int_op(1, ==, smartlist_len(added)); + md1 = smartlist_get(added, 0); + smartlist_free(added); + added = NULL; + + wanted = smartlist_create(); + added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0, + time2, wanted); + /* Should fail, since we didn't list test_md2's digest in wanted */ + tt_int_op(0, ==, smartlist_len(added)); + smartlist_free(added); + added = NULL; + + smartlist_add(wanted, tor_memdup(d2, DIGEST256_LEN)); + smartlist_add(wanted, tor_memdup(d3, DIGEST256_LEN)); + added = microdescs_add_to_cache(mc, test_md2, NULL, SAVED_NOWHERE, 0, + time2, wanted); + /* Now it can work. md2 should have been added */ + tt_int_op(1, ==, smartlist_len(added)); + md2 = smartlist_get(added, 0); + /* And it should have gotten removed from 'wanted' */ + tt_int_op(smartlist_len(wanted), ==, 1); + test_mem_op(smartlist_get(wanted, 0), ==, d3, DIGEST256_LEN); + smartlist_free(added); + added = NULL; + + added = microdescs_add_to_cache(mc, test_md3, NULL, + SAVED_NOWHERE, 0, -1, NULL); + /* Must fail, since SAVED_NOWHERE precludes annotations */ + tt_int_op(0, ==, smartlist_len(added)); + smartlist_free(added); + added = NULL; + + added = microdescs_add_to_cache(mc, test_md3_noannotation, NULL, + SAVED_NOWHERE, 0, time3, NULL); + /* Now it can work */ + tt_int_op(1, ==, smartlist_len(added)); + md3 = smartlist_get(added, 0); + smartlist_free(added); + added = NULL; + + /* Okay. We added 1...3. Let's poke them to see how they look, and make + * sure they're really in the journal. */ + tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1)); + tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2)); + tt_ptr_op(md3, ==, microdesc_cache_lookup_by_digest256(mc, d3)); + + tt_int_op(md1->last_listed, ==, time1); + tt_int_op(md2->last_listed, ==, time2); + tt_int_op(md3->last_listed, ==, time3); + + tt_int_op(md1->saved_location, ==, SAVED_IN_JOURNAL); + tt_int_op(md2->saved_location, ==, SAVED_IN_JOURNAL); + tt_int_op(md3->saved_location, ==, SAVED_IN_JOURNAL); + + tt_int_op(md1->bodylen, ==, strlen(test_md1)); + tt_int_op(md2->bodylen, ==, strlen(test_md2)); + tt_int_op(md3->bodylen, ==, strlen(test_md3_noannotation)); + test_mem_op(md1->body, ==, test_md1, strlen(test_md1)); + test_mem_op(md2->body, ==, test_md2, strlen(test_md2)); + test_mem_op(md3->body, ==, test_md3_noannotation, + strlen(test_md3_noannotation)); + + tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs.new", + options->DataDirectory); + s = read_file_to_str(fn, RFTS_BIN, NULL); + tt_assert(s); + test_mem_op(md1->body, ==, s + md1->off, md1->bodylen); + test_mem_op(md2->body, ==, s + md2->off, md2->bodylen); + test_mem_op(md3->body, ==, s + md3->off, md3->bodylen); + + tt_ptr_op(md1->family, ==, NULL); + tt_ptr_op(md3->family, !=, NULL); + tt_int_op(smartlist_len(md3->family), ==, 3); + tt_str_op(smartlist_get(md3->family, 0), ==, "nodeX"); + + /* Now rebuild the cache! */ + tt_int_op(microdesc_cache_rebuild(mc, 1), ==, 0); + + tt_int_op(md1->saved_location, ==, SAVED_IN_CACHE); + tt_int_op(md2->saved_location, ==, SAVED_IN_CACHE); + tt_int_op(md3->saved_location, ==, SAVED_IN_CACHE); + + /* The journal should be empty now */ + tor_free(s); + s = read_file_to_str(fn, RFTS_BIN, NULL); + tt_str_op(s, ==, ""); + tor_free(s); + tor_free(fn); + + /* read the cache. */ + tor_asprintf(&fn, "%s"PATH_SEPARATOR"cached-microdescs", + options->DataDirectory); + s = read_file_to_str(fn, RFTS_BIN, NULL); + test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1)); + test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2)); + test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation)); + + /* Okay, now we are going to forget about the cache entirely, and reload it + * from the disk. */ + microdesc_free_all(); + mc = get_microdesc_cache(); + md1 = microdesc_cache_lookup_by_digest256(mc, d1); + md2 = microdesc_cache_lookup_by_digest256(mc, d2); + md3 = microdesc_cache_lookup_by_digest256(mc, d3); + test_assert(md1); + test_assert(md2); + test_assert(md3); + test_mem_op(md1->body, ==, s + md1->off, strlen(test_md1)); + test_mem_op(md2->body, ==, s + md2->off, strlen(test_md2)); + test_mem_op(md3->body, ==, s + md3->off, strlen(test_md3_noannotation)); + + tt_int_op(md1->last_listed, ==, time1); + tt_int_op(md2->last_listed, ==, time2); + tt_int_op(md3->last_listed, ==, time3); + + /* Okay, now we are going to clear out everything older than a week old. + * In practice, that means md3 */ + microdesc_cache_clean(mc, time(NULL)-7*24*60*60, 1/*force*/); + tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1)); + tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2)); + tt_ptr_op(NULL, ==, microdesc_cache_lookup_by_digest256(mc, d3)); + md3 = NULL; /* it's history now! */ + + /* rebuild again, make sure it stays gone. */ + microdesc_cache_rebuild(mc, 1); + tt_ptr_op(md1, ==, microdesc_cache_lookup_by_digest256(mc, d1)); + tt_ptr_op(md2, ==, microdesc_cache_lookup_by_digest256(mc, d2)); + tt_ptr_op(NULL, ==, microdesc_cache_lookup_by_digest256(mc, d3)); + + done: + if (options) + tor_free(options->DataDirectory); + microdesc_free_all(); + + smartlist_free(added); + if (wanted) + SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp)); + smartlist_free(wanted); + tor_free(s); + tor_free(fn); +} + +struct testcase_t microdesc_tests[] = { + { "cache", test_md_cache, TT_FORK, NULL, NULL }, + END_OF_TESTCASES +}; + diff --git a/src/test/test_pt.c b/src/test/test_pt.c new file mode 100644 index 0000000000..45f441106e --- /dev/null +++ b/src/test/test_pt.c @@ -0,0 +1,147 @@ +/* Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2011, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" +#define PT_PRIVATE +#include "or.h" +#include "transports.h" +#include "circuitbuild.h" +#include "test.h" + +static void +reset_mp(managed_proxy_t *mp) +{ + mp->conf_state = PT_PROTO_LAUNCHED; + SMARTLIST_FOREACH(mp->transports, transport_t *, t, transport_free(t)); + smartlist_clear(mp->transports); +} + +static void +test_pt_parsing(void) +{ + char line[200]; + + managed_proxy_t *mp = tor_malloc(sizeof(managed_proxy_t)); + mp->conf_state = PT_PROTO_INFANT; + mp->transports = smartlist_create(); + + /* incomplete cmethod */ + strcpy(line,"CMETHOD trebuchet"); + test_assert(parse_cmethod_line(line, mp) < 0); + + reset_mp(mp); + + /* wrong proxy type */ + strcpy(line,"CMETHOD trebuchet dog 127.0.0.1:1999"); + test_assert(parse_cmethod_line(line, mp) < 0); + + reset_mp(mp); + + /* wrong addrport */ + strcpy(line,"CMETHOD trebuchet socks4 abcd"); + test_assert(parse_cmethod_line(line, mp) < 0); + + reset_mp(mp); + + /* correct line */ + strcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999"); + test_assert(parse_cmethod_line(line, mp) == 0); + test_assert(smartlist_len(mp->transports)); + + reset_mp(mp); + + /* incomplete smethod */ + strcpy(line,"SMETHOD trebuchet"); + test_assert(parse_smethod_line(line, mp) < 0); + + reset_mp(mp); + + /* wrong addr type */ + strcpy(line,"SMETHOD trebuchet abcd"); + test_assert(parse_smethod_line(line, mp) < 0); + + reset_mp(mp); + + /* cowwect */ + strcpy(line,"SMETHOD trebuchy 127.0.0.1:1999"); + test_assert(parse_smethod_line(line, mp) == 0); + + reset_mp(mp); + + /* unsupported version */ + strcpy(line,"VERSION 666"); + test_assert(parse_version(line, mp) < 0); + + /* incomplete VERSION */ + strcpy(line,"VERSION "); + test_assert(parse_version(line, mp) < 0); + + /* correct VERSION */ + strcpy(line,"VERSION 1"); + test_assert(parse_version(line, mp) == 0); + + done: + tor_free(mp); +} + +static void +test_pt_protocol(void) +{ + char line[200]; + + managed_proxy_t *mp = tor_malloc_zero(sizeof(managed_proxy_t)); + mp->conf_state = PT_PROTO_LAUNCHED; + mp->transports = smartlist_create(); + + /* various wrong protocol runs: */ + + strcpy(line, "TEST TEST"); + handle_proxy_line(line, mp); + test_assert(mp->conf_state == PT_PROTO_BROKEN); + + reset_mp(mp); + + strcpy(line,"VERSION 1"); + handle_proxy_line(line, mp); + test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS); + + strcpy(line,"VERSION 1"); + handle_proxy_line(line, mp); + test_assert(mp->conf_state == PT_PROTO_BROKEN); + + reset_mp(mp); + + strcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999"); + handle_proxy_line(line, mp); + test_assert(mp->conf_state == PT_PROTO_BROKEN); + + reset_mp(mp); + + /* correct protocol run: */ + strcpy(line,"VERSION 1"); + handle_proxy_line(line, mp); + test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS); + + strcpy(line,"CMETHOD trebuchet socks5 127.0.0.1:1999"); + handle_proxy_line(line, mp); + test_assert(mp->conf_state == PT_PROTO_ACCEPTING_METHODS); + + strcpy(line,"CMETHODS DONE"); + handle_proxy_line(line, mp); + test_assert(mp->conf_state == PT_PROTO_CONFIGURED); + + done: + tor_free(mp); +} + +#define PT_LEGACY(name) \ + { #name, legacy_test_helper, 0, &legacy_setup, test_pt_ ## name } + +struct testcase_t pt_tests[] = { + PT_LEGACY(parsing), + PT_LEGACY(protocol), + END_OF_TESTCASES +}; + diff --git a/src/test/test_util.c b/src/test/test_util.c index 23cd059cf7..93f11cd208 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" @@ -362,20 +363,10 @@ test_util_strmisc(void) test_assert(!tor_strisprint(cp)); tor_free(cp); - /* Test eat_whitespace. */ - { - const char *s = " \n a"; - test_eq_ptr(eat_whitespace(s), s+4); - s = "abcd"; - test_eq_ptr(eat_whitespace(s), s); - s = "#xyz\nab"; - test_eq_ptr(eat_whitespace(s), s+5); - } - /* 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"; @@ -408,6 +399,20 @@ test_util_strmisc(void) SMARTLIST_FOREACH(sl, char *, cp, tor_free(cp)); smartlist_free(sl); } + + /* Test hex_str */ + { + char binary_data[64]; + size_t i; + for (i = 0; i < sizeof(binary_data); ++i) + binary_data[i] = i; + test_streq(hex_str(binary_data, 0), ""); + test_streq(hex_str(binary_data, 1), "00"); + test_streq(hex_str(binary_data, 17), "000102030405060708090A0B0C0D0E0F10"); + test_streq(hex_str(binary_data, 32), + "000102030405060708090A0B0C0D0E0F" + "101112131415161718191A1B1C1D1E1F"); + } done: ; } @@ -639,26 +644,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 +680,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 +837,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 +1256,446 @@ test_util_load_win_lib(void *ptr) #endif static void +clear_hex_errno(char *hex_errno) +{ + memset(hex_errno, '\0', HEX_ERRNO_SIZE + 1); +} + +static void +test_util_exit_status(void *ptr) +{ + /* Leave an extra byte for a \0 so we can do string comparison */ + char hex_errno[HEX_ERRNO_SIZE + 1]; + + (void)ptr; + + clear_hex_errno(hex_errno); + format_helper_exit_status(0, 0, hex_errno); + tt_str_op(hex_errno, ==, " 0/0\n"); + + clear_hex_errno(hex_errno); + format_helper_exit_status(0, 0x7FFFFFFF, hex_errno); + tt_str_op(hex_errno, ==, " 0/7FFFFFFF\n"); + + clear_hex_errno(hex_errno); + format_helper_exit_status(0xFF, -0x80000000, hex_errno); + tt_str_op(hex_errno, ==, "FF/-80000000\n"); + + clear_hex_errno(hex_errno); + format_helper_exit_status(0x7F, 0, hex_errno); + tt_str_op(hex_errno, ==, " 7F/0\n"); + + clear_hex_errno(hex_errno); + format_helper_exit_status(0x08, -0x242, hex_errno); + tt_str_op(hex_errno, ==, " 8/-242\n"); + + done: + ; +} + +#ifndef MS_WINDOWS +/** Check that fgets waits until a full line, and not return a partial line, on + * a EAGAIN with a non-blocking pipe */ +static void +test_util_fgets_eagain(void *ptr) +{ + int test_pipe[2] = {-1, -1}; + int retval; + ssize_t retlen; + char *retptr; + FILE *test_stream = NULL; + char buf[10]; + + (void)ptr; + + /* Set up a pipe to test on */ + retval = pipe(test_pipe); + tt_int_op(retval, >=, 0); + + /* Set up the read-end to be non-blocking */ + retval = fcntl(test_pipe[0], F_SETFL, O_NONBLOCK); + tt_int_op(retval, >=, 0); + + /* Open it as a stdio stream */ + test_stream = fdopen(test_pipe[0], "r"); + tt_ptr_op(test_stream, !=, NULL); + + /* Send in a partial line */ + retlen = write(test_pipe[1], "A", 1); + tt_int_op(retlen, ==, 1); + retptr = fgets(buf, sizeof(buf), test_stream); + tt_want(retptr == NULL); + tt_int_op(errno, ==, EAGAIN); + + /* Send in the rest */ + retlen = write(test_pipe[1], "B\n", 2); + tt_int_op(retlen, ==, 2); + retptr = fgets(buf, sizeof(buf), test_stream); + tt_ptr_op(retptr, ==, buf); + tt_str_op(buf, ==, "AB\n"); + + /* Send in a full line */ + retlen = write(test_pipe[1], "CD\n", 3); + tt_int_op(retlen, ==, 3); + retptr = fgets(buf, sizeof(buf), test_stream); + tt_ptr_op(retptr, ==, buf); + tt_str_op(buf, ==, "CD\n"); + + /* Send in a partial line */ + retlen = write(test_pipe[1], "E", 1); + tt_int_op(retlen, ==, 1); + retptr = fgets(buf, sizeof(buf), test_stream); + tt_ptr_op(retptr, ==, NULL); + tt_int_op(errno, ==, EAGAIN); + + /* Send in the rest */ + retlen = write(test_pipe[1], "F\n", 2); + tt_int_op(retlen, ==, 2); + retptr = fgets(buf, sizeof(buf), test_stream); + tt_ptr_op(retptr, ==, buf); + tt_str_op(buf, ==, "EF\n"); + + /* Send in a full line and close */ + retlen = write(test_pipe[1], "GH", 2); + tt_int_op(retlen, ==, 2); + retval = close(test_pipe[1]); + test_pipe[1] = -1; + tt_int_op(retval, ==, 0); + retptr = fgets(buf, sizeof(buf), test_stream); + tt_ptr_op(retptr, ==, buf); + tt_str_op(buf, ==, "GH"); + + /* Check for EOF */ + retptr = fgets(buf, sizeof(buf), test_stream); + tt_ptr_op(retptr, ==, NULL); + tt_int_op(feof(test_stream), >, 0); + + done: + if (test_stream != NULL) + fclose(test_stream); + if (test_pipe[0] != -1) + close(test_pipe[0]); + if (test_pipe[1] != -1) + close(test_pipe[1]); +} +#endif + +/** Helper function for testing tor_spawn_background */ +static void +run_util_spawn_background(const char *argv[], const char *expected_out, + const char *expected_err, int expected_exit, + int expected_status) +{ + int retval, exit_code; + ssize_t pos; + process_handle_t *process_handle=NULL; + char stdout_buf[100], stderr_buf[100]; + int status; + + /* Start the program */ +#ifdef MS_WINDOWS + status = tor_spawn_background(NULL, argv, NULL, &process_handle); +#else + status = tor_spawn_background(argv[0], argv, NULL, &process_handle); +#endif + + tt_int_op(status, ==, expected_status); + if (status == PROCESS_STATUS_ERROR) + return; + + tt_assert(process_handle != NULL); + tt_int_op(process_handle->status, ==, expected_status); + + tt_int_op(process_handle->stdout_pipe, >, 0); + tt_int_op(process_handle->stderr_pipe, >, 0); + + /* Check stdout */ + pos = tor_read_all_from_process_stdout(process_handle, stdout_buf, + sizeof(stdout_buf) - 1); + tt_assert(pos >= 0); + stdout_buf[pos] = '\0'; + tt_str_op(stdout_buf, ==, expected_out); + tt_int_op(pos, ==, strlen(expected_out)); + + /* Check it terminated correctly */ + retval = tor_get_exit_code(process_handle, 1, &exit_code); + tt_int_op(retval, ==, PROCESS_EXIT_EXITED); + tt_int_op(exit_code, ==, expected_exit); + // TODO: Make test-child exit with something other than 0 + + /* Check stderr */ + pos = tor_read_all_from_process_stderr(process_handle, stderr_buf, + sizeof(stderr_buf) - 1); + tt_assert(pos >= 0); + stderr_buf[pos] = '\0'; + tt_str_op(stderr_buf, ==, expected_err); + tt_int_op(pos, ==, strlen(expected_err)); + + done: + if (process_handle) + tor_process_handle_destroy(process_handle, 1); +} + +/** Check that we can launch a process and read the output */ +static void +test_util_spawn_background_ok(void *ptr) +{ +#ifdef MS_WINDOWS + const char *argv[] = {"test-child.exe", "--test", NULL}; + const char *expected_out = "OUT\r\n--test\r\nSLEEPING\r\nDONE\r\n"; + const char *expected_err = "ERR\r\n"; +#else + const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL}; + const char *expected_out = "OUT\n--test\nSLEEPING\nDONE\n"; + const char *expected_err = "ERR\n"; +#endif + + (void)ptr; + + run_util_spawn_background(argv, expected_out, expected_err, 0, + PROCESS_STATUS_RUNNING); +} + +/** Check that failing to find the executable works as expected */ +static void +test_util_spawn_background_fail(void *ptr) +{ +#ifdef MS_WINDOWS + const char *argv[] = {BUILDDIR "/src/test/no-such-file", "--test", NULL}; + const char *expected_out = "ERR: Failed to spawn background process " + "- code 9/2\n"; + const char *expected_err = ""; + const int expected_status = PROCESS_STATUS_ERROR; +#else + const char *argv[] = {BUILDDIR "/src/test/no-such-file", "--test", NULL}; + const char *expected_out = "ERR: Failed to spawn background process " + "- code 9/2\n"; + const char *expected_err = ""; + /* TODO: Once we can signal failure to exec, set this to be + * PROCESS_STATUS_ERROR */ + const int expected_status = PROCESS_STATUS_RUNNING; +#endif + + (void)ptr; + + run_util_spawn_background(argv, expected_out, expected_err, 255, + expected_status); +} + +/** Test that reading from a handle returns a partial read rather than + * blocking */ +static void +test_util_spawn_background_partial_read(void *ptr) +{ + const int expected_exit = 0; + const int expected_status = PROCESS_STATUS_RUNNING; + + int retval, exit_code; + ssize_t pos = -1; + process_handle_t *process_handle=NULL; + int status; + char stdout_buf[100], stderr_buf[100]; +#ifdef MS_WINDOWS + const char *argv[] = {"test-child.exe", "--test", NULL}; + const char *expected_out[] = { "OUT\r\n--test\r\nSLEEPING\r\n", + "DONE\r\n", + NULL }; + const char *expected_err = "ERR\r\n"; +#else + const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL}; + const char *expected_out[] = { "OUT\n--test\nSLEEPING\n", + "DONE\n", + NULL }; + const char *expected_err = "ERR\n"; + int eof = 0; +#endif + int expected_out_ctr; + (void)ptr; + + /* Start the program */ +#ifdef MS_WINDOWS + status = tor_spawn_background(NULL, argv, NULL, &process_handle); +#else + status = tor_spawn_background(argv[0], argv, NULL, &process_handle); +#endif + tt_int_op(status, ==, expected_status); + tt_assert(process_handle); + tt_int_op(process_handle->status, ==, expected_status); + + /* Check stdout */ + for (expected_out_ctr = 0; expected_out[expected_out_ctr] != NULL;) { +#ifdef MS_WINDOWS + pos = tor_read_all_handle(process_handle->stdout_pipe, stdout_buf, + sizeof(stdout_buf) - 1, NULL); +#else + /* Check that we didn't read the end of file last time */ + tt_assert(!eof); + pos = tor_read_all_handle(process_handle->stdout_handle, stdout_buf, + sizeof(stdout_buf) - 1, NULL, &eof); +#endif + log_info(LD_GENERAL, "tor_read_all_handle() returned %d", (int)pos); + + /* We would have blocked, keep on trying */ + if (0 == pos) + continue; + + tt_int_op(pos, >, 0); + stdout_buf[pos] = '\0'; + tt_str_op(stdout_buf, ==, expected_out[expected_out_ctr]); + tt_int_op(pos, ==, strlen(expected_out[expected_out_ctr])); + expected_out_ctr++; + } + + /* The process should have exited without writing more */ +#ifdef MS_WINDOWS + pos = tor_read_all_handle(process_handle->stdout_pipe, stdout_buf, + sizeof(stdout_buf) - 1, + process_handle); + tt_int_op(pos, ==, 0); +#else + if (!eof) { + /* We should have got all the data, but maybe not the EOF flag */ + pos = tor_read_all_handle(process_handle->stdout_handle, stdout_buf, + sizeof(stdout_buf) - 1, + process_handle, &eof); + tt_int_op(pos, ==, 0); + tt_assert(eof); + } + /* Otherwise, we got the EOF on the last read */ +#endif + + /* Check it terminated correctly */ + retval = tor_get_exit_code(process_handle, 1, &exit_code); + tt_int_op(retval, ==, PROCESS_EXIT_EXITED); + tt_int_op(exit_code, ==, expected_exit); + + // TODO: Make test-child exit with something other than 0 + + /* Check stderr */ + pos = tor_read_all_from_process_stderr(process_handle, stderr_buf, + sizeof(stderr_buf) - 1); + tt_assert(pos >= 0); + stderr_buf[pos] = '\0'; + tt_str_op(stderr_buf, ==, expected_err); + tt_int_op(pos, ==, strlen(expected_err)); + + done: + tor_process_handle_destroy(process_handle, 1); +} + +/** + * Test that we can properly format q Windows command line + */ +static void +test_util_join_win_cmdline(void *ptr) +{ + /* Based on some test cases from "Parsing C++ Command-Line Arguments" in + * MSDN but we don't exercise all quoting rules because tor_join_win_cmdline + * will try to only generate simple cases for the child process to parse; + * i.e. we never embed quoted strings in arguments. */ + + const char *argvs[][4] = { + {"a", "bb", "CCC", NULL}, // Normal + {NULL, NULL, NULL, NULL}, // Empty argument list + {"", NULL, NULL, NULL}, // Empty argument + {"\"a", "b\"b", "CCC\"", NULL}, // Quotes + {"a\tbc", "dd dd", "E", NULL}, // Whitespace + {"a\\\\\\b", "de fg", "H", NULL}, // Backslashes + {"a\\\"b", "\\c", "D\\", NULL}, // Backslashes before quote + {"a\\\\b c", "d", "E", NULL}, // Backslashes not before quote + { NULL } // Terminator + }; + + const char *cmdlines[] = { + "a bb CCC", + "", + "\"\"", + "\\\"a b\\\"b CCC\\\"", + "\"a\tbc\" \"dd dd\" E", + "a\\\\\\b \"de fg\" H", + "a\\\\\\\"b \\c D\\", + "\"a\\\\b c\" d E", + NULL // Terminator + }; + + int i; + char *joined_argv; + + (void)ptr; + + for (i=0; cmdlines[i]!=NULL; i++) { + log_info(LD_GENERAL, "Joining argvs[%d], expecting <%s>", i, cmdlines[i]); + joined_argv = tor_join_win_cmdline(argvs[i]); + tt_str_op(joined_argv, ==, cmdlines[i]); + tor_free(joined_argv); + } + + done: + ; +} + +#define MAX_SPLIT_LINE_COUNT 3 +struct split_lines_test_t { + const char *orig_line; // Line to be split (may contain \0's) + int orig_length; // Length of orig_line + const char *split_line[MAX_SPLIT_LINE_COUNT]; // Split lines +}; + +/** + * Test that we properly split a buffer into lines + */ +static void +test_util_split_lines(void *ptr) +{ + /* Test cases. orig_line of last test case must be NULL. + * The last element of split_line[i] must be NULL. */ + struct split_lines_test_t tests[] = { + {"", 0, {NULL}}, + {"foo", 3, {"foo", NULL}}, + {"\n\rfoo\n\rbar\r\n", 12, {"foo", "bar", NULL}}, + {"fo o\r\nb\tar", 10, {"fo o", "b.ar", NULL}}, + {"\x0f""f\0o\0\n\x01""b\0r\0\r", 12, {".f.o.", ".b.r.", NULL}}, + {NULL, 0, { NULL }} + }; + + int i, j; + char *orig_line; + smartlist_t *sl; + + (void)ptr; + + for (i=0; tests[i].orig_line; i++) { + sl = smartlist_create(); + /* Allocate space for string and trailing NULL */ + orig_line = tor_memdup(tests[i].orig_line, tests[i].orig_length + 1); + tor_split_lines(sl, orig_line, tests[i].orig_length); + + j = 0; + log_info(LD_GENERAL, "Splitting test %d of length %d", + i, tests[i].orig_length); + SMARTLIST_FOREACH(sl, const char *, line, + { + /* Check we have not got too many lines */ + tt_int_op(j, <, MAX_SPLIT_LINE_COUNT); + /* Check that there actually should be a line here */ + tt_assert(tests[i].split_line[j] != NULL); + log_info(LD_GENERAL, "Line %d of test %d, should be <%s>", + j, i, tests[i].split_line[j]); + /* Check that the line is as expected */ + tt_str_op(tests[i].split_line[j], ==, line); + j++; + }); + /* Check that we didn't miss some lines */ + tt_assert(tests[i].split_line[j] == NULL); + tor_free(orig_line); + smartlist_free(sl); + } + + done: + ; +} + +static void test_util_di_ops(void) { #define LT -1 @@ -1291,6 +1748,92 @@ test_util_di_ops(void) ; } +/** + * Test counting high bits + */ +static void +test_util_n_bits_set(void *ptr) +{ + (void)ptr; + test_eq(n_bits_set_u8(0), 0); + test_eq(n_bits_set_u8(1), 1); + test_eq(n_bits_set_u8(129), 2); + test_eq(n_bits_set_u8(255), 8); + done: + ; +} + +/** + * Test LHS whitespace (and comment) eater + */ +static void +test_util_eat_whitespace(void *ptr) +{ + const char ws[] = { ' ', '\t', '\r' }; /* Except NL */ + char str[80]; + size_t i; + + (void)ptr; + + /* Try one leading ws */ + strcpy(str, "fuubaar"); + for (i = 0; i < sizeof(ws); ++i) { + str[0] = ws[i]; + test_streq(eat_whitespace(str), str + 1); + test_streq(eat_whitespace_eos(str, str + strlen(str)), str + 1); + test_streq(eat_whitespace_eos_no_nl(str, str + strlen(str)), str + 1); + test_streq(eat_whitespace_no_nl(str), str + 1); + } + str[0] = '\n'; + test_streq(eat_whitespace(str), str + 1); + test_streq(eat_whitespace_eos(str, str + strlen(str)), str + 1); + + /* Empty string */ + strcpy(str, ""); + test_eq_ptr(eat_whitespace(str), str); + test_eq_ptr(eat_whitespace_eos(str, str), str); + test_eq_ptr(eat_whitespace_eos_no_nl(str, str), str); + test_eq_ptr(eat_whitespace_no_nl(str), str); + + /* Only ws */ + strcpy(str, " \t\r\n"); + test_eq_ptr(eat_whitespace(str), str + strlen(str)); + test_eq_ptr(eat_whitespace_eos(str, str + strlen(str)), str + strlen(str)); + + strcpy(str, " \t\r "); + test_eq_ptr(eat_whitespace_no_nl(str), str + strlen(str)); + test_eq_ptr(eat_whitespace_eos_no_nl(str, str + strlen(str)), + str + strlen(str)); + + /* Multiple ws */ + strcpy(str, "fuubaar"); + for (i = 0; i < sizeof(ws); ++i) + str[i] = ws[i]; + test_streq(eat_whitespace(str), str + sizeof(ws)); + test_streq(eat_whitespace_eos(str, str + strlen(str)), str + sizeof(ws)); + test_streq(eat_whitespace_no_nl(str), str + sizeof(ws)); + test_streq(eat_whitespace_eos_no_nl(str, str + strlen(str)), + str + sizeof(ws)); + + /* Eat comment */ + strcpy(str, "# Comment \n No Comment"); + test_streq(eat_whitespace(str), "No Comment"); + test_streq(eat_whitespace_eos(str, str + strlen(str)), "No Comment"); + + /* Eat comment & ws mix */ + strcpy(str, " # \t Comment \n\t\nNo Comment"); + test_streq(eat_whitespace(str), "No Comment"); + test_streq(eat_whitespace_eos(str, str + strlen(str)), "No Comment"); + + /* Eat entire comment */ + strcpy(str, "#Comment"); + test_eq_ptr(eat_whitespace(str), str + strlen(str)); + test_eq_ptr(eat_whitespace_eos(str, str + strlen(str)), str + strlen(str)); + + done: + ; +} + #define UTIL_LEGACY(name) \ { #name, legacy_test_helper, 0, &legacy_setup, test_util_ ## name } @@ -1319,6 +1862,17 @@ struct testcase_t util_tests[] = { #ifdef MS_WINDOWS UTIL_TEST(load_win_lib, 0), #endif + UTIL_TEST(exit_status, 0), +#ifndef MS_WINDOWS + UTIL_TEST(fgets_eagain, TT_SKIP), +#endif + UTIL_TEST(spawn_background_ok, 0), + UTIL_TEST(spawn_background_fail, 0), + UTIL_TEST(spawn_background_partial_read, 0), + UTIL_TEST(join_win_cmdline, 0), + UTIL_TEST(split_lines, 0), + UTIL_TEST(n_bits_set, 0), + UTIL_TEST(eat_whitespace, 0), END_OF_TESTCASES }; diff --git a/src/test/tinytest.c b/src/test/tinytest.c index 11ffc2fe56..8caa4f5453 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 4d2f588435..98cb773d1a 100644 --- a/src/test/tinytest_demo.c +++ b/src/test/tinytest_demo.c @@ -1,4 +1,4 @@ -/* tinytest_demo.c -- Copyright 2009 Nick Mathewson +/* tinytest_demo.c -- Copyright 2009-2010 Nick Mathewson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -53,7 +53,7 @@ test_strcmp(void *data) } /* Pretty often, calling tt_abort_msg to indicate failure is more - heavy-weight than you want. Instead, just say: */ + heavy-weight than you want. Instead, just say: */ tt_assert(strcmp("testcase", "testcase") == 0); /* Occasionally, you don't want to stop the current testcase just @@ -91,7 +91,7 @@ test_strcmp(void *data) /* First you declare a type to hold the environment info, and functions to set it up and tear it down. */ struct data_buffer { - /* We're just going to have couple of character buffer. Using + /* We're just going to have couple of character buffer. Using setup/teardown functions is probably overkill for this case. You could also do file descriptors, complicated handles, temporary @@ -164,7 +164,7 @@ test_memcpy(void *ptr) /* ============================================================ */ -/* Now we need to make sure that our tests get invoked. First, you take +/* Now we need to make sure that our tests get invoked. First, you take a bunch of related tests and put them into an array of struct testcase_t. */ @@ -189,15 +189,15 @@ struct testgroup_t groups[] = { /* Every group has a 'prefix', and an array of tests. That's it. */ { "demo/", demo_tests }, - END_OF_GROUPS + END_OF_GROUPS }; int main(int c, const char **v) { - /* Finally, just call tinytest_main(). It lets you specify verbose - or quiet output with --verbose and --quiet. You can list + /* Finally, just call tinytest_main(). It lets you specify verbose + or quiet output with --verbose and --quiet. You can list specific tests: tinytest-demo demo/memcpy diff --git a/src/test/tinytest_macros.h b/src/test/tinytest_macros.h index a7fa64a824..032393ccf7 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 1bb5076849..a9a619757a 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 0000000000..8f64ad2ba3 --- /dev/null +++ b/src/tools/tor-fw-helper/Makefile.am @@ -0,0 +1,38 @@ +if USE_FW_HELPER +bin_PROGRAMS = tor-fw-helper +else +bin_PROGRAMS = +endif + +tor_fw_helper_SOURCES = \ + tor-fw-helper.c \ + tor-fw-helper-natpmp.c \ + tor-fw-helper-upnp.c +noinst_HEADERS = \ + tor-fw-helper.h \ + tor-fw-helper-natpmp.h \ + tor-fw-helper-upnp.h + +if NAT_PMP +nat_pmp_ldflags = @TOR_LDFLAGS_libnatpmp@ +nat_pmp_ldadd = -lnatpmp +nat_pmp_cppflags = @TOR_CPPFLAGS_libnatpmp@ +else +nat_pmp_ldflags = +nat_pmp_ldadd = +nat_pmp_cppflags = +endif + +if MINIUPNPC +miniupnpc_ldflags = @TOR_LDFLAGS_libminiupnpc@ +miniupnpc_ldadd = -lminiupnpc -lm @TOR_LIB_IPHLPAPI@ +miniupnpc_cppflags = @TOR_CPPFLAGS_libminiupnpc@ +else +miniupnpc_ldflags = +miniupnpc_ldadd = +miniupnpc_cppflags = +endif + +tor_fw_helper_LDFLAGS = $(nat_pmp_ldflags) $(miniupnpc_ldflags) +tor_fw_helper_LDADD = ../../common/libor.a $(nat_pmp_ldadd) $(miniupnpc_ldadd) @TOR_LIB_WS32@ +tor_fw_helper_CPPFLAGS = $(nat_pmp_cppflags) $(miniupnpc_cppflags) diff --git a/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c b/src/tools/tor-fw-helper/tor-fw-helper-natpmp.c new file mode 100644 index 0000000000..f9d5d0d586 --- /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 0000000000..0190379a23 --- /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 0000000000..c4b14a84e2 --- /dev/null +++ b/src/tools/tor-fw-helper/tor-fw-helper-upnp.c @@ -0,0 +1,189 @@ +/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch. + * Copyright (c) 2010-2011, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file tor-fw-helper-upnp.c + * \brief The implementation of our UPnP firewall helper. + **/ + +#include "orconfig.h" +#ifdef MINIUPNPC +#ifdef MS_WINDOWS +#define STATICLIB +#endif +#include <stdint.h> +#include <string.h> +#include <stdio.h> + +#include <assert.h> + +#include "compat.h" +#include "tor-fw-helper.h" +#include "tor-fw-helper-upnp.h" + +/** UPnP timeout value. */ +#define UPNP_DISCOVER_TIMEOUT 2000 +/** Description of the port mapping in the UPnP table. */ +#define UPNP_DESC "Tor relay" + +/* XXX TODO: We should print these as a useful user string when we return the + * number to a user */ +/** Magic numbers as miniupnpc return codes. */ +#define UPNP_ERR_SUCCESS 0 +#define UPNP_ERR_NODEVICESFOUND 1 +#define UPNP_ERR_NOIGDFOUND 2 +#define UPNP_ERR_ADDPORTMAPPING 3 +#define UPNP_ERR_GETPORTMAPPING 4 +#define UPNP_ERR_DELPORTMAPPING 5 +#define UPNP_ERR_GETEXTERNALIP 6 +#define UPNP_ERR_INVAL 7 +#define UPNP_ERR_OTHER 8 +#define UPNP_SUCCESS 1 + +/** This hooks miniupnpc into our multi-backend API. */ +static tor_fw_backend_t tor_miniupnp_backend = { + "miniupnp", + sizeof(struct miniupnpc_state_t), + tor_upnp_init, + tor_upnp_cleanup, + tor_upnp_fetch_public_ip, + tor_upnp_add_tcp_mapping +}; + +/** Return the backend for miniupnp. */ +const tor_fw_backend_t * +tor_fw_get_miniupnp_backend(void) +{ + return &tor_miniupnp_backend; +} + +/** Initialize the UPnP backend and store the results in + * <b>backend_state</b>.*/ +int +tor_upnp_init(tor_fw_options_t *options, void *backend_state) +{ + /* + This leaks the user agent from the client to the router - perhaps we don't + want to do that? eg: + + User-Agent: Ubuntu/10.04, UPnP/1.0, MiniUPnPc/1.4 + + */ + miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state; + struct UPNPDev *devlist; + int r; + + memset(&(state->urls), 0, sizeof(struct UPNPUrls)); + memset(&(state->data), 0, sizeof(struct IGDdatas)); + state->init = 0; + + devlist = upnpDiscover(UPNP_DISCOVER_TIMEOUT, NULL, NULL, 0); + if (NULL == devlist) { + fprintf(stderr, "E: upnpDiscover returned: NULL\n"); + return UPNP_ERR_NODEVICESFOUND; + } + + assert(options); + r = UPNP_GetValidIGD(devlist, &(state->urls), &(state->data), + state->lanaddr, UPNP_LANADDR_SZ); + fprintf(stdout, "tor-fw-helper: UPnP GetValidIGD returned: %d (%s)\n", r, + r==UPNP_SUCCESS?"SUCCESS":"FAILED"); + + freeUPNPDevlist(devlist); + + if (r != 1 && r != 2) + return UPNP_ERR_NOIGDFOUND; + + state->init = 1; + return UPNP_ERR_SUCCESS; +} + +/** Tear down the UPnP connection stored in <b>backend_state</b>.*/ +int +tor_upnp_cleanup(tor_fw_options_t *options, void *backend_state) +{ + + miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state; + assert(options); + + if (state->init) + FreeUPNPUrls(&(state->urls)); + state->init = 0; + + return UPNP_ERR_SUCCESS; +} + +/** Fetch our likely public IP from our upstream UPnP IGD enabled NAT device. + * Use the connection context stored in <b>backend_state</b>. */ +int +tor_upnp_fetch_public_ip(tor_fw_options_t *options, void *backend_state) +{ + miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state; + int r; + char externalIPAddress[16]; + + if (!state->init) { + r = tor_upnp_init(options, state); + if (r != UPNP_ERR_SUCCESS) + return r; + } + + r = UPNP_GetExternalIPAddress(state->urls.controlURL, + state->data.first.servicetype, + externalIPAddress); + + if (r != UPNPCOMMAND_SUCCESS) + goto err; + + if (externalIPAddress[0]) { + fprintf(stdout, "tor-fw-helper: ExternalIPAddress = %s\n", + externalIPAddress); tor_upnp_cleanup(options, state); + options->public_ip_status = 1; + return UPNP_ERR_SUCCESS; + } else { + goto err; + } + + err: + tor_upnp_cleanup(options, state); + return UPNP_ERR_GETEXTERNALIP; +} + +/** Add a TCP port mapping for a single port stored in <b>tor_fw_options</b> + * and store the results in <b>backend_state</b>. */ +int +tor_upnp_add_tcp_mapping(tor_fw_options_t *options, void *backend_state) +{ + miniupnpc_state_t *state = (miniupnpc_state_t *) backend_state; + int r; + char internal_port_str[6]; + char external_port_str[6]; + + if (!state->init) { + r = tor_upnp_init(options, state); + if (r != UPNP_ERR_SUCCESS) + return r; + } + + if (options->verbose) + fprintf(stdout, "V: internal port: %d, external port: %d\n", + (int)options->internal_port, (int)options->external_port); + + tor_snprintf(internal_port_str, sizeof(internal_port_str), + "%d", (int)options->internal_port); + tor_snprintf(external_port_str, sizeof(external_port_str), + "%d", (int)options->external_port); + + r = UPNP_AddPortMapping(state->urls.controlURL, + state->data.first.servicetype, + external_port_str, internal_port_str, + state->lanaddr, UPNP_DESC, "TCP", 0); + if (r != UPNPCOMMAND_SUCCESS) + return UPNP_ERR_ADDPORTMAPPING; + + options->upnp_status = 1; + return UPNP_ERR_SUCCESS; +} +#endif + diff --git a/src/tools/tor-fw-helper/tor-fw-helper-upnp.h b/src/tools/tor-fw-helper/tor-fw-helper-upnp.h new file mode 100644 index 0000000000..021a8e0aac --- /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 0000000000..002239745a --- /dev/null +++ b/src/tools/tor-fw-helper/tor-fw-helper.c @@ -0,0 +1,396 @@ +/* Copyright (c) 2010, Jacob Appelbaum, Steven J. Murdoch. + * Copyright (c) 2010-2011, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file tor-fw-helper.c + * \brief The main wrapper around our firewall helper logic. + **/ + +/* + * tor-fw-helper is a tool for opening firewalls with NAT-PMP and UPnP; this + * tool is designed to be called by hand or by Tor by way of a exec() at a + * later date. + */ + +#include "orconfig.h" +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <getopt.h> +#include <time.h> +#include <string.h> + +#ifdef MS_WINDOWS +#include <winsock2.h> +#endif + +#include "tor-fw-helper.h" +#ifdef NAT_PMP +#include "tor-fw-helper-natpmp.h" +#endif +#ifdef MINIUPNPC +#include "tor-fw-helper-upnp.h" +#endif + +/** This is our meta storage type - it holds information about each helper + including the total number of helper backends, function pointers, and helper + state. */ +typedef struct backends_t { + /** The total number of backends */ + int n_backends; + /** The backend functions as an array */ + tor_fw_backend_t backend_ops[MAX_BACKENDS]; + /** The internal backend state */ + void *backend_state[MAX_BACKENDS]; +} backends_t; + +/** Initalize each backend helper with the user input stored in <b>options</b> + * and put the results in the <b>backends</b> struct. */ +static int +init_backends(tor_fw_options_t *options, backends_t *backends) +{ + int n_available = 0; + int i, r, n; + tor_fw_backend_t *backend_ops_list[MAX_BACKENDS]; + void *data = NULL; + /* First, build a list of the working backends. */ + n = 0; +#ifdef MINIUPNPC + backend_ops_list[n++] = (tor_fw_backend_t *) tor_fw_get_miniupnp_backend(); +#endif +#ifdef NAT_PMP + backend_ops_list[n++] = (tor_fw_backend_t *) tor_fw_get_natpmp_backend(); +#endif + n_available = n; + + /* Now, for each backend that might work, try to initialize it. + * That's how we roll, initialized. + */ + n = 0; + for (i=0; i<n_available; ++i) { + data = calloc(1, backend_ops_list[i]->state_len); + if (!data) { + perror("calloc"); + exit(1); + } + r = backend_ops_list[i]->init(options, data); + if (r == 0) { + backends->backend_ops[n] = *backend_ops_list[i]; + backends->backend_state[n] = data; + n++; + } else { + free(data); + } + } + backends->n_backends = n; + + return n; +} + +/** Return the proper commandline switches when the user needs information. */ +static void +usage(void) +{ + fprintf(stderr, "tor-fw-helper usage:\n" + " [-h|--help]\n" + " [-T|--Test]\n" + " [-v|--verbose]\n" + " [-g|--fetch-public-ip]\n" + " -i|--internal-or-port [TCP port]\n" + " [-e|--external-or-port [TCP port]]\n" + " [-d|--internal-dir-port [TCP port]\n" + " [-p|--external-dir-port [TCP port]]]\n"); +} + +/** Log commandline options to a hardcoded file <b>tor-fw-helper.log</b> in the + * current working directory. */ +static int +log_commandline_options(int argc, char **argv) +{ + int i, retval; + FILE *logfile; + time_t now; + + /* Open the log file */ + logfile = fopen("tor-fw-helper.log", "a"); + if (NULL == logfile) + return -1; + + /* Send all commandline arguments to the file */ + now = time(NULL); + retval = fprintf(logfile, "START: %s\n", ctime(&now)); + for (i = 0; i < argc; i++) { + retval = fprintf(logfile, "ARG: %d: %s\n", i, argv[i]); + if (retval < 0) + goto error; + + retval = fprintf(stdout, "ARG: %d: %s\n", i, argv[i]); + if (retval < 0) + goto error; + } + now = time(NULL); + retval = fprintf(logfile, "END: %s\n", ctime(&now)); + + /* Close and clean up */ + retval = fclose(logfile); + return retval; + + /* If there was an error during writing */ + error: + fclose(logfile); + return -1; +} + +/** Iterate over over each of the supported <b>backends</b> and attempt to + * fetch the public ip. */ +static void +tor_fw_fetch_public_ip(tor_fw_options_t *tor_fw_options, + backends_t *backends) +{ + int i; + int r = 0; + + if (tor_fw_options->verbose) + fprintf(stdout, "V: tor_fw_fetch_public_ip\n"); + + for (i=0; i<backends->n_backends; ++i) { + if (tor_fw_options->verbose) { + fprintf(stdout, "V: running backend_state now: %i\n", i); + fprintf(stdout, "V: size of backend state: %u\n", + (int)(backends->backend_ops)[i].state_len); + fprintf(stdout, "V: backend state name: %s\n", + (char *)(backends->backend_ops)[i].name); + } + r = backends->backend_ops[i].fetch_public_ip(tor_fw_options, + backends->backend_state[i]); + fprintf(stdout, "tor-fw-helper: tor_fw_fetch_public_ip backend %s " + " returned: %i\n", (char *)(backends->backend_ops)[i].name, r); + } +} + +/** Iterate over each of the supported <b>backends</b> and attempt to add a + * port forward for the OR port stored in <b>tor_fw_options</b>. */ +static void +tor_fw_add_or_port(tor_fw_options_t *tor_fw_options, + backends_t *backends) +{ + int i; + int r = 0; + + if (tor_fw_options->verbose) + fprintf(stdout, "V: tor_fw_add_or_port\n"); + + for (i=0; i<backends->n_backends; ++i) { + if (tor_fw_options->verbose) { + fprintf(stdout, "V: running backend_state now: %i\n", i); + fprintf(stdout, "V: size of backend state: %u\n", + (int)(backends->backend_ops)[i].state_len); + fprintf(stdout, "V: backend state name: %s\n", + (const char *) backends->backend_ops[i].name); + } + r = backends->backend_ops[i].add_tcp_mapping(tor_fw_options, + backends->backend_state[i]); + fprintf(stdout, "tor-fw-helper: tor_fw_add_or_port backend %s " + "returned: %i\n", (const char *) backends->backend_ops[i].name, r); + } +} + +/** Iterate over each of the supported <b>backends</b> and attempt to add a + * port forward for the Dir port stored in <b>tor_fw_options</b>. */ +static void +tor_fw_add_dir_port(tor_fw_options_t *tor_fw_options, + backends_t *backends) +{ + int i; + int r = 0; + + if (tor_fw_options->verbose) + fprintf(stdout, "V: tor_fw_add_dir_port\n"); + + for (i=0; i<backends->n_backends; ++i) { + if (tor_fw_options->verbose) { + fprintf(stdout, "V: running backend_state now: %i\n", i); + fprintf(stdout, "V: size of backend state: %u\n", + (int)(backends->backend_ops)[i].state_len); + fprintf(stdout, "V: backend state name: %s\n", + (char *)(backends->backend_ops)[i].name); + } + r = backends->backend_ops[i].add_tcp_mapping(tor_fw_options, + backends->backend_state[i]); + fprintf(stdout, "tor-fw-helper: tor_fw_add_dir_port backend %s " + "returned: %i\n", (const char *)backends->backend_ops[i].name, r); + } +} + +/** Called before we make any calls to network-related functions. + * (Some operating systems require their network libraries to be + * initialized.) (from common/compat.c) */ +static int +network_init(void) +{ +#ifdef MS_WINDOWS + /* This silly exercise is necessary before windows will allow + * gethostbyname to work. */ + WSADATA WSAData; + int r; + r = WSAStartup(0x101, &WSAData); + if (r) { + fprintf(stderr, "E: Error initializing Windows network layer " + "- code was %d", r); + return -1; + } + /* WSAData.iMaxSockets might show the max sockets we're allowed to use. + * We might use it to complain if we're trying to be a server but have + * too few sockets available. */ +#endif + return 0; +} + +int +main(int argc, char **argv) +{ + int r = 0; + int c = 0; + + tor_fw_options_t tor_fw_options; + backends_t backend_state; + + memset(&tor_fw_options, 0, sizeof(tor_fw_options)); + memset(&backend_state, 0, sizeof(backend_state)); + + while (1) { + int option_index = 0; + static struct option long_options[] = + { + {"verbose", 0, 0, 'v'}, + {"help", 0, 0, 'h'}, + {"internal-or-port", 1, 0, 'i'}, + {"external-or-port", 1, 0, 'e'}, + {"internal-dir-port", 1, 0, 'd'}, + {"external-dir-port", 1, 0, 'p'}, + {"fetch-public-ip", 0, 0, 'g'}, + {"test-commandline", 0, 0, 'T'}, + {0, 0, 0, 0} + }; + + c = getopt_long(argc, argv, "vhi:e:d:p:gT", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 'v': tor_fw_options.verbose = 1; break; + case 'h': tor_fw_options.help = 1; usage(); exit(1); break; + case 'i': sscanf(optarg, "%hu", &tor_fw_options.private_or_port); + break; + case 'e': sscanf(optarg, "%hu", &tor_fw_options.public_or_port); + break; + case 'd': sscanf(optarg, "%hu", &tor_fw_options.private_dir_port); + break; + case 'p': sscanf(optarg, "%hu", &tor_fw_options.public_dir_port); + break; + case 'g': tor_fw_options.fetch_public_ip = 1; break; + case 'T': tor_fw_options.test_commandline = 1; break; + case '?': break; + default : fprintf(stderr, "Unknown option!\n"); usage(); exit(1); + } + } + + if (tor_fw_options.verbose) { + fprintf(stderr, "V: tor-fw-helper version %s\n" + "V: We were called with the following arguments:\n" + "V: verbose = %d, help = %d, pub or port = %u, " + "priv or port = %u\n" + "V: pub dir port = %u, priv dir port = %u\n" + "V: fetch_public_ip = %u\n", + tor_fw_version, tor_fw_options.verbose, tor_fw_options.help, + tor_fw_options.private_or_port, tor_fw_options.public_or_port, + tor_fw_options.private_dir_port, tor_fw_options.public_dir_port, + tor_fw_options.fetch_public_ip); + } + + if (tor_fw_options.test_commandline) { + return log_commandline_options(argc, argv); + } + + /* At the very least, we require an ORPort; + Given a private ORPort, we can ask for a mapping that matches the port + externally. + */ + if (!tor_fw_options.private_or_port && !tor_fw_options.fetch_public_ip) { + fprintf(stderr, "E: We require an ORPort or fetch_public_ip" + " request!\n"); + usage(); + exit(1); + } else { + /* When we only have one ORPort, internal/external are + set to be the same.*/ + if (!tor_fw_options.public_or_port && tor_fw_options.private_or_port) { + if (tor_fw_options.verbose) + fprintf(stdout, "V: We're setting public_or_port = " + "private_or_port.\n"); + tor_fw_options.public_or_port = tor_fw_options.private_or_port; + } + } + if (!tor_fw_options.private_dir_port) { + if (tor_fw_options.verbose) + fprintf(stdout, "V: We have no DirPort; no hole punching for " + "DirPorts\n"); + + } else { + /* When we only have one DirPort, internal/external are + set to be the same.*/ + if (!tor_fw_options.public_dir_port && tor_fw_options.private_dir_port) { + if (tor_fw_options.verbose) + fprintf(stdout, "V: We're setting public_or_port = " + "private_or_port.\n"); + + tor_fw_options.public_dir_port = tor_fw_options.private_dir_port; + } + } + + if (tor_fw_options.verbose) { + fprintf(stdout, "V: pub or port = %u, priv or port = %u\n" + "V: pub dir port = %u, priv dir port = %u\n", + tor_fw_options.private_or_port, tor_fw_options.public_or_port, + tor_fw_options.private_dir_port, + tor_fw_options.public_dir_port); + } + + // Initialize networking + if (network_init()) + exit(1); + + // Initalize the various fw-helper backend helpers + r = init_backends(&tor_fw_options, &backend_state); + if (r) + printf("tor-fw-helper: %i NAT traversal helper(s) loaded\n", r); + + if (tor_fw_options.fetch_public_ip) { + tor_fw_fetch_public_ip(&tor_fw_options, &backend_state); + } + + if (tor_fw_options.private_or_port) { + tor_fw_options.internal_port = tor_fw_options.private_or_port; + tor_fw_options.external_port = tor_fw_options.private_or_port; + tor_fw_add_or_port(&tor_fw_options, &backend_state); + } + + if (tor_fw_options.private_dir_port) { + tor_fw_options.internal_port = tor_fw_options.private_dir_port; + tor_fw_options.external_port = tor_fw_options.private_dir_port; + tor_fw_add_dir_port(&tor_fw_options, &backend_state); + } + + r = (((tor_fw_options.nat_pmp_status | tor_fw_options.upnp_status) + |tor_fw_options.public_ip_status)); + if (r > 0) { + fprintf(stdout, "tor-fw-helper: SUCCESS\n"); + } else { + fprintf(stderr, "tor-fw-helper: FAILURE\n"); + } + + exit(r); +} + diff --git a/src/tools/tor-fw-helper/tor-fw-helper.h b/src/tools/tor-fw-helper/tor-fw-helper.h new file mode 100644 index 0000000000..39d852d212 --- /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-gencert.c b/src/tools/tor-gencert.c index 7a516b4571..57f82b1bc7 100644 --- a/src/tools/tor-gencert.c +++ b/src/tools/tor-gencert.c @@ -153,7 +153,7 @@ parse_commandline(int argc, char **argv) } months_lifetime = atoi(argv[++i]); if (months_lifetime > 24 || months_lifetime < 0) { - fprintf(stderr, "Lifetime (in months) was out of range."); + fprintf(stderr, "Lifetime (in months) was out of range.\n"); return 1; } } else if (!strcmp(argv[i], "-r") || !strcmp(argv[i], "--reuse")) { @@ -169,7 +169,7 @@ parse_commandline(int argc, char **argv) fprintf(stderr, "No argument to -a\n"); return 1; } - if (parse_addr_port(LOG_ERR, argv[++i], NULL, &addr, &port)<0) + if (addr_port_lookup(LOG_ERR, argv[++i], NULL, &addr, &port)<0) return 1; in.s_addr = htonl(addr); tor_inet_ntoa(&in, b, sizeof(b)); diff --git a/src/tools/tor-resolve.c b/src/tools/tor-resolve.c index 8c4d3f6483..f1220d9d88 100644 --- a/src/tools/tor-resolve.c +++ b/src/tools/tor-resolve.c @@ -393,7 +393,7 @@ main(int argc, char **argv) socksport = 9050; /* 9050 */ } } else if (n_args == 2) { - if (parse_addr_port(LOG_WARN, arg[1], NULL, &sockshost, &socksport)<0) { + if (addr_port_lookup(LOG_WARN, arg[1], NULL, &sockshost, &socksport)<0) { fprintf(stderr, "Couldn't parse/resolve address %s", arg[1]); return 1; } diff --git a/src/win32/orconfig.h b/src/win32/orconfig.h index b3cd1db50b..34d7c75b01 100644 --- a/src/win32/orconfig.h +++ b/src/win32/orconfig.h @@ -122,6 +122,7 @@ /* Define to 1 if you have the <sys/socket.h> header file. */ #undef HAVE_SYS_SOCKET_H + /* Define to 1 if you have the <sys/stat.h> header file. */ #define HAVE_SYS_STAT_H @@ -233,5 +234,13 @@ #define USING_TWOS_COMPLEMENT /* Version number of package */ -#define VERSION "0.2.2.19-alpha" +#define VERSION "0.2.3.8-alpha-dev" + + +#define HAVE_STRUCT_SOCKADDR_IN6 +#define HAVE_STRUCT_IN6_ADDR +#define RSHIFT_DOES_SIGN_EXTEND +#define FLEXIBLE_ARRAY_MEMBER 0 +#define HAVE_EVENT2_EVENT_H +#define SHARE_DATADIR "" |